PageRenderTime 33ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/utility/transformations.c

https://bitbucket.org/csantoni/progetto-tesi
C | 1803 lines | 1471 code | 175 blank | 157 comment | 220 complexity | 72e27f384e687dfb704c042f8d48cec9 MD5 | raw file
  1. /* transformations.c
  2. A Python C extension module for homogeneous transformation matrices and
  3. quaternions.
  4. Refer to the transformations.py module for documentation and tests.
  5. :Author:
  6. `Christoph Gohlke <http://www.lfd.uci.edu/~gohlke/>`_
  7. :Organization:
  8. Laboratory for Fluorescence Dynamics, University of California, Irvine
  9. :Version: 2013.04.16
  10. Install
  11. -------
  12. Use this Python distutils setup script to build the extension module::
  13. # setup.py
  14. # Usage: ``python setup.py build_ext --inplace``
  15. from distutils.core import setup, Extension
  16. import numpy
  17. setup(name='_transformations',
  18. ext_modules=[Extension('_transformations', ['transformations.c'],
  19. include_dirs=[numpy.get_include()])])
  20. License
  21. -------
  22. Copyright (c) 2007-2013, Christoph Gohlke
  23. Copyright (c) 2007-2013, The Regents of the University of California
  24. Produced at the Laboratory for Fluorescence Dynamics
  25. All rights reserved.
  26. Redistribution and use in source and binary forms, with or without
  27. modification, are permitted provided that the following conditions are met:
  28. * Redistributions of source code must retain the above copyright
  29. notice, this list of conditions and the following disclaimer.
  30. * Redistributions in binary form must reproduce the above copyright
  31. notice, this list of conditions and the following disclaimer in the
  32. documentation and/or other materials provided with the distribution.
  33. * Neither the name of the copyright holders nor the names of any
  34. contributors may be used to endorse or promote products derived
  35. from this software without specific prior written permission.
  36. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  37. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  38. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  39. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  40. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  41. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  42. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  43. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  44. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  46. POSSIBILITY OF SUCH DAMAGE.
  47. */
  48. #define _VERSION_ "2013.04.16"
  49. #define WIN32_LEAN_AND_MEAN
  50. #include "Python.h"
  51. #ifdef _WIN32
  52. #include <windows.h>
  53. #include <wincrypt.h>
  54. #endif
  55. #include "structmember.h"
  56. #include "math.h"
  57. #include "float.h"
  58. #include "string.h"
  59. #include "numpy/arrayobject.h"
  60. #define EPSILON 8.8817841970012523e-016 /* 4.0 * DBL_EPSILON */
  61. #define PIVOT_TOLERANCE 1.0e-14
  62. #define DEG2RAD 0.017453292519943295769236907684886
  63. #define TWOPI 6.283185307179586476925286766559
  64. #ifndef M_PI
  65. #define M_PI 3.1415926535897932384626433832795
  66. #endif
  67. #ifndef MAX
  68. #define MAX(a, b) (((a) > (b)) ? (a) : (b))
  69. #define MIN(a, b) (((a) < (b)) ? (a) : (b))
  70. #endif
  71. #define ISZERO(x) (((x) < EPSILON) && ((x) > -EPSILON))
  72. #define NOTZERO(x) (((x) > EPSILON) || ((x) < -EPSILON))
  73. /*****************************************************************************/
  74. /* C helper functions */
  75. /*
  76. Return random doubles in half-open interval [0.0, 1.0).
  77. Uses /dev/urandom or CryptoAPI. Not very fast but random.
  78. Assumes sizeof(double) == 2*sizeof(int).
  79. */
  80. int random_doubles(
  81. double *buffer,
  82. Py_ssize_t size)
  83. {
  84. #ifndef _WIN32
  85. int done;
  86. FILE *rfile;
  87. if (size < 1)
  88. return 0;
  89. rfile = fopen("/dev/urandom", "rb");
  90. if (rfile == NULL)
  91. return -1;
  92. done = fread(buffer, size*sizeof(double), 1, rfile);
  93. fclose(rfile);
  94. #else
  95. #pragma comment(lib,"advapi32")
  96. BOOL done;
  97. HCRYPTPROV hcryptprov;
  98. if (size < 1)
  99. return 0;
  100. if (!CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL,
  101. CRYPT_VERIFYCONTEXT) || !hcryptprov)
  102. return -1;
  103. done = CryptGenRandom(hcryptprov, (DWORD)(size*sizeof(double)),
  104. (unsigned char *)buffer);
  105. CryptReleaseContext(hcryptprov, 0);
  106. #endif
  107. if (done) {
  108. unsigned int a, b;
  109. unsigned int *p = (unsigned int *)buffer;
  110. while (size--) {
  111. a = (*p++) >> 5;
  112. b = (*p++) >> 6;
  113. *buffer++ = (a * 67108864.0 + b) / 9007199254740992.0;
  114. }
  115. return 0;
  116. }
  117. return -1;
  118. }
  119. /*
  120. Tridiagonal matrix from symmetric 4x4 matrix using Housholder reduction.
  121. The input matrix is altered.
  122. */
  123. int tridiagonalize_symmetric_44(
  124. double *matrix, /* double[16] */
  125. double *diagonal, /* double[4] */
  126. double *subdiagonal) /* double[3] */
  127. {
  128. double t, n, g, h, v0, v1, v2;
  129. double *u;
  130. double *M = matrix;
  131. u = &M[1];
  132. t = u[1]*u[1] + u[2]*u[2];
  133. n = sqrt(u[0]*u[0] + t);
  134. if (n > EPSILON) {
  135. if (u[0] < 0.0)
  136. n = -n;
  137. u[0] += n;
  138. h = (u[0]*u[0] + t) / 2.0;
  139. v0 = M[5]*u[0] + M[6]*u[1] + M[7]*u[2];
  140. v1 = M[6]*u[0] + M[10]*u[1] + M[11]*u[2];
  141. v2 = M[7]*u[0] + M[11]*u[1] + M[15]*u[2];
  142. v0 /= h;
  143. v1 /= h;
  144. v2 /= h;
  145. g = (u[0]*v0 + u[1]*v1 + u[2]*v2) / (2.0 * h);
  146. v0 -= g * u[0];
  147. v1 -= g * u[1];
  148. v2 -= g * u[2];
  149. M[5] -= 2.0*v0*u[0];
  150. M[10] -= 2.0*v1*u[1];
  151. M[15] -= 2.0*v2*u[2];
  152. M[6] -= v1*u[0] + v0*u[1];
  153. M[7] -= v2*u[0] + v0*u[2];
  154. M[11] -= v2*u[1] + v1*u[2];
  155. M[1] = -n;
  156. }
  157. u = &M[6];
  158. t = u[1]*u[1];
  159. n = sqrt(u[0]*u[0] + t);
  160. if (n > EPSILON) {
  161. if (u[0] < 0.0)
  162. n = -n;
  163. u[0] += n;
  164. h = (u[0]*u[0] + t) / 2.0;
  165. v0 = M[10]*u[0] + M[11]*u[1];
  166. v1 = M[11]*u[0] + M[15]*u[1];
  167. v0 /= h;
  168. v1 /= h;
  169. g = (u[0]*v0 + u[1]*v1) / (2.0 * h);
  170. v0 -= g * u[0];
  171. v1 -= g * u[1];
  172. M[10] -= 2.0*v0*u[0];
  173. M[15] -= 2.0*v1*u[1];
  174. M[11] -= v1*u[0] + v0*u[1];
  175. M[6] = -n;
  176. }
  177. diagonal[0] = M[0];
  178. diagonal[1] = M[5];
  179. diagonal[2] = M[10];
  180. diagonal[3] = M[15];
  181. subdiagonal[0] = M[1];
  182. subdiagonal[1] = M[6];
  183. subdiagonal[2] = M[11];
  184. return 0;
  185. }
  186. /*
  187. Return largest eigenvalue of symmetric tridiagonal matrix.
  188. Matrix Algorithms: Basic decompositions. By GW Stewart. Chapter 3.
  189. */
  190. double max_eigenvalue_of_tridiag_44(
  191. double *diagonal, /* double[4] */
  192. double *subdiagonal) /* double[3] */
  193. {
  194. int count;
  195. double lower, upper, t0, t1, d, eps, eigenv;
  196. double *a = diagonal;
  197. double *b = subdiagonal;
  198. /* upper and lower bounds using Gerschgorin's theorem */
  199. t0 = fabs(b[0]);
  200. t1 = fabs(b[1]);
  201. lower = a[0] - t0;
  202. upper = a[0] + t0;
  203. d = a[1] - t0 - t1;
  204. lower = MIN(lower, d);
  205. d = a[1] + t0 + t1;
  206. upper = MAX(upper, d);
  207. t0 = fabs(b[2]);
  208. d = a[2] - t0 - t1;
  209. lower = MIN(lower, d);
  210. d = a[2] + t0 + t1;
  211. upper = MAX(upper, d);
  212. d = a[3] - t0;
  213. lower = MIN(lower, d);
  214. d = a[3] + t0;
  215. upper = MAX(upper, d);
  216. /* precision */
  217. eps = (4.0 * (fabs(lower) + fabs(upper))) * DBL_EPSILON;
  218. /* interval bisection until width is less than tolerance */
  219. while (fabs(upper - lower) > eps) {
  220. eigenv = (upper + lower) / 2.0;
  221. if ((eigenv == upper) || (eigenv == lower))
  222. return eigenv;
  223. /* counting pivots < 0 */
  224. d = a[0] - eigenv;
  225. count = (d < 0.0) ? 1 : 0;
  226. if (fabs(d) < eps)
  227. d = eps;
  228. d = a[1] - eigenv - b[0]*b[0] / d;
  229. if (d < 0.0)
  230. count++;
  231. if (fabs(d) < eps)
  232. d = eps;
  233. d = a[2] - eigenv - b[1]*b[1] / d;
  234. if (d < 0.0)
  235. count++;
  236. if (fabs(d) < eps)
  237. d = eps;
  238. d = a[3] - eigenv - b[2]*b[2] / d;
  239. if (d < 0.0)
  240. count++;
  241. if (count < 4)
  242. lower = eigenv;
  243. else
  244. upper = eigenv;
  245. }
  246. return (upper + lower) / 2.0;
  247. }
  248. /*
  249. Eigenvector of symmetric tridiagonal 4x4 matrix using Cramer's rule.
  250. */
  251. int eigenvector_of_symmetric_44(
  252. double *matrix, /* double[16] */
  253. double *vector, /* double[4] */
  254. double *buffer) /* double[12] */
  255. {
  256. double n, eps;
  257. double *M = matrix;
  258. double *v = vector;
  259. double *t = buffer;
  260. /* eps: minimum length of eigenvector to use */
  261. eps = (M[0]*M[5]*M[10]*M[15] - M[1]*M[1]*M[11]*M[11]) * 1e-6;
  262. eps *= eps;
  263. if (eps < EPSILON)
  264. eps = EPSILON;
  265. t[0] = M[10] * M[15];
  266. t[1] = M[11] * M[11];
  267. t[2] = M[6] * M[15];
  268. t[3] = M[11] * M[7];
  269. t[4] = M[6] * M[11];
  270. t[5] = M[10] * M[7];
  271. t[6] = M[2] * M[15];
  272. t[7] = M[11] * M[3];
  273. t[8] = M[2] * M[11];
  274. t[9] = M[10] * M[3];
  275. t[10] = M[2] * M[7];
  276. t[11] = M[6] * M[3];
  277. v[0] = t[1]*M[1] + t[6]*M[6] + t[9]*M[7];
  278. v[0] -= t[0]*M[1] + t[7]*M[6] + t[8]*M[7];
  279. v[1] = t[2]*M[1] + t[7]*M[5] + t[10]*M[7];
  280. v[1] -= t[3]*M[1] + t[6]*M[5] + t[11]*M[7];
  281. v[2] = t[5]*M[1] + t[8]*M[5] + t[11]*M[6];
  282. v[2] -= t[4]*M[1] + t[9]*M[5] + t[10]*M[6];
  283. v[3] = t[0]*M[5] + t[3]*M[6] + t[4]*M[7];
  284. v[3] -= t[1]*M[5] + t[2]*M[6] + t[5]*M[7];
  285. n = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
  286. if (n < eps) {
  287. v[0] = t[0]*M[0] + t[7]*M[2] + t[8]*M[3];
  288. v[0] -= t[1]*M[0] + t[6]*M[2] + t[9]*M[3];
  289. v[1] = t[3]*M[0] + t[6]*M[1] + t[11]*M[3];
  290. v[1] -= t[2]*M[0] + t[7]*M[1] + t[10]*M[3];
  291. v[2] = t[4]*M[0] + t[9]*M[1] + t[10]*M[2];
  292. v[2] -= t[5]*M[0] + t[8]*M[1] + t[11]*M[2];
  293. v[3] = t[1]*M[1] + t[2]*M[2] + t[5]*M[3];
  294. v[3] -= t[0]*M[1] + t[3]*M[2] + t[4]*M[3];
  295. n = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
  296. }
  297. if (n < eps) {
  298. t[0] = M[2] * M[7];
  299. t[1] = M[3] * M[6];
  300. t[2] = M[1] * M[7];
  301. t[3] = M[3] * M[5];
  302. t[4] = M[1] * M[6];
  303. t[5] = M[2] * M[5];
  304. t[6] = M[0] * M[7];
  305. t[7] = M[3] * M[1];
  306. t[8] = M[0] * M[6];
  307. t[9] = M[2] * M[1];
  308. t[10] = M[0] * M[5];
  309. t[11] = M[1] * M[1];
  310. v[0] = t[1]*M[3] + t[6]*M[11] + t[9]*M[15];
  311. v[0] -= t[0]*M[3] + t[7]*M[11] + t[8]*M[15];
  312. v[1] = t[2]*M[3] + t[7]*M[7] + t[10]*M[15];
  313. v[1] -= t[3]*M[3] + t[6]*M[7] + t[11]*M[15];
  314. v[2] = t[5]*M[3] + t[8]*M[7] + t[11]*M[11];
  315. v[2] -= t[4]*M[3] + t[9]*M[7] + t[10]*M[11];
  316. v[3] = t[0]*M[7] + t[3]*M[11] + t[4]*M[15];
  317. v[3] -= t[1]*M[7] + t[2]*M[11] + t[5]*M[15];
  318. n = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
  319. }
  320. if (n < eps) {
  321. v[0] = t[8]*M[11] + t[0]*M[2] + t[7]*M[10];
  322. v[0] -= t[6]*M[10] + t[9]*M[11] + t[1]*M[2];
  323. v[1] = t[6]*M[6] + t[11]*M[11] + t[3]*M[2];
  324. v[1] -= t[10]*M[11] + t[2]*M[2] + t[7]*M[6];
  325. v[2] = t[10]*M[10] + t[4]*M[2] + t[9]*M[6];
  326. v[2] -= t[8]*M[6] + t[11]*M[10] + t[5]*M[2];
  327. v[3] = t[2]*M[10] + t[5]*M[11] + t[1]*M[6];
  328. v[3] -= t[4]*M[11] + t[0]*M[6] + t[3]*M[10];
  329. n = v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3];
  330. }
  331. if (n < eps)
  332. return -1;
  333. n = sqrt(n);
  334. v[0] /= n;
  335. v[1] /= n;
  336. v[2] /= n;
  337. v[3] /= n;
  338. return 0;
  339. }
  340. /*
  341. Matrix 2x2 inversion.
  342. */
  343. int invert_matrix22(
  344. double *matrix, /* double[4] */
  345. double *result) /* double[4] */
  346. {
  347. double det = matrix[0]*matrix[3] - matrix[1]*matrix[2];
  348. if (ISZERO(det))
  349. return -1;
  350. result[0] = matrix[3] / det;
  351. result[1] = -matrix[1] / det;
  352. result[2] = -matrix[2] / det;
  353. result[3] = matrix[0] / det;
  354. return 0;
  355. }
  356. /*
  357. Matrix 3x3 inversion.
  358. */
  359. int invert_matrix33(
  360. double *matrix, /* double[9] */
  361. double *result) /* double[9] */
  362. {
  363. int i;
  364. double det;
  365. double *M = matrix;
  366. result[0] = M[8]*M[4] - M[7]*M[5];
  367. result[1] = M[7]*M[2] - M[8]*M[1];
  368. result[2] = M[5]*M[1] - M[4]*M[2];
  369. result[3] = M[6]*M[5] - M[8]*M[3];
  370. result[4] = M[8]*M[0] - M[6]*M[2];
  371. result[5] = M[3]*M[2] - M[5]*M[0];
  372. result[6] = M[7]*M[3] - M[6]*M[4];
  373. result[7] = M[6]*M[1] - M[7]*M[0];
  374. result[8] = M[4]*M[0] - M[3]*M[1];
  375. det = M[0]*result[0] + M[3]*result[1] + M[6]*result[2];
  376. if (ISZERO(det))
  377. return -1;
  378. det = 1.0 / det;
  379. for (i = 0; i < 9; i++)
  380. result[i] *= det;
  381. return 0;
  382. }
  383. /*
  384. Matrix 4x4 inversion.
  385. */
  386. int invert_matrix44(
  387. double *matrix, /* double[16] */
  388. double *result) /* double[16] */
  389. {
  390. int i;
  391. double det;
  392. double t[12];
  393. double *M = matrix;
  394. t[0] = M[10] * M[15];
  395. t[1] = M[14] * M[11];
  396. t[2] = M[6] * M[15];
  397. t[3] = M[14] * M[7];
  398. t[4] = M[6] * M[11];
  399. t[5] = M[10] * M[7];
  400. t[6] = M[2] * M[15];
  401. t[7] = M[14] * M[3];
  402. t[8] = M[2] * M[11];
  403. t[9] = M[10] * M[3];
  404. t[10] = M[2] * M[7];
  405. t[11] = M[6] * M[3];
  406. result[0] = t[0]*M[5] + t[3]*M[9] + t[4]*M[13];
  407. result[0] -= t[1]*M[5] + t[2]*M[9] + t[5]*M[13];
  408. result[1] = t[1]*M[1] + t[6]*M[9] + t[9]*M[13];
  409. result[1] -= t[0]*M[1] + t[7]*M[9] + t[8]*M[13];
  410. result[2] = t[2]*M[1] + t[7]*M[5] + t[10]*M[13];
  411. result[2] -= t[3]*M[1] + t[6]*M[5] + t[11]*M[13];
  412. result[3] = t[5]*M[1] + t[8]*M[5] + t[11]*M[9];
  413. result[3] -= t[4]*M[1] + t[9]*M[5] + t[10]*M[9];
  414. result[4] = t[1]*M[4] + t[2]*M[8] + t[5]*M[12];
  415. result[4] -= t[0]*M[4] + t[3]*M[8] + t[4]*M[12];
  416. result[5] = t[0]*M[0] + t[7]*M[8] + t[8]*M[12];
  417. result[5] -= t[1]*M[0] + t[6]*M[8] + t[9]*M[12];
  418. result[6] = t[3]*M[0] + t[6]*M[4] + t[11]*M[12];
  419. result[6] -= t[2]*M[0] + t[7]*M[4] + t[10]*M[12];
  420. result[7] = t[4]*M[0] + t[9]*M[4] + t[10]*M[8];
  421. result[7] -= t[5]*M[0] + t[8]*M[4] + t[11]*M[8];
  422. t[0] = M[8]*M[13];
  423. t[1] = M[12]*M[9];
  424. t[2] = M[4]*M[13];
  425. t[3] = M[12]*M[5];
  426. t[4] = M[4]*M[9];
  427. t[5] = M[8]*M[5];
  428. t[6] = M[0]*M[13];
  429. t[7] = M[12]*M[1];
  430. t[8] = M[0]*M[9];
  431. t[9] = M[8]*M[1];
  432. t[10] = M[0]*M[5];
  433. t[11] = M[4]*M[1];
  434. result[8] = t[0]*M[7] + t[3]*M[11] + t[4]*M[15];
  435. result[8] -= t[1]*M[7] + t[2]*M[11] + t[5]*M[15];
  436. result[9] = t[1]*M[3] + t[6]*M[11] + t[9]*M[15];
  437. result[9] -= t[0]*M[3] + t[7]*M[11] + t[8]*M[15];
  438. result[10] = t[2]*M[3] + t[7]*M[7] + t[10]*M[15];
  439. result[10]-= t[3]*M[3] + t[6]*M[7] + t[11]*M[15];
  440. result[11] = t[5]*M[3] + t[8]*M[7] + t[11]*M[11];
  441. result[11]-= t[4]*M[3] + t[9]*M[7] + t[10]*M[11];
  442. result[12] = t[2]*M[10] + t[5]*M[14] + t[1]*M[6];
  443. result[12]-= t[4]*M[14] + t[0]*M[6] + t[3]*M[10];
  444. result[13] = t[8]*M[14] + t[0]*M[2] + t[7]*M[10];
  445. result[13]-= t[6]*M[10] + t[9]*M[14] + t[1]*M[2];
  446. result[14] = t[6]*M[6] + t[11]*M[14] + t[3]*M[2];
  447. result[14]-= t[10]*M[14] + t[2]*M[2] + t[7]*M[6];
  448. result[15] = t[10]*M[10] + t[4]*M[2] + t[9]*M[6];
  449. result[15]-= t[8]*M[6] + t[11]*M[10] + t[5]*M[2];
  450. det = M[0]*result[0] + M[4]*result[1] + M[8]*result[2] + M[12]*result[3];
  451. if (ISZERO(det))
  452. return -1;
  453. det = 1.0 / det;
  454. for (i = 0; i < 16; i++)
  455. result[i] *= det;
  456. return 0;
  457. }
  458. /*
  459. Invert square matrix using LU factorization with pivoting.
  460. The input matrix is altered.
  461. */
  462. int invert_matrix(
  463. Py_ssize_t size,
  464. double *matrix, /* [size*size] */
  465. double *result, /* [size*size] */
  466. Py_ssize_t *buffer) /* [2*size] */
  467. {
  468. Py_ssize_t *seq = buffer;
  469. Py_ssize_t *iseq = buffer + size;
  470. Py_ssize_t i, j, k, ks, ps, ksk, js, p, is;
  471. double temp, temp1;
  472. double *M = matrix;
  473. /* sequence of pivots */
  474. for (k = 0; k < size; k++)
  475. seq[k] = k;
  476. /* forward solution */
  477. for (k = 0; k < size-1; k++) {
  478. ks = k*size;
  479. ksk = ks + k;
  480. /* pivoting: find maximum coefficient in column */
  481. p = k;
  482. temp = fabs(M[ksk]);
  483. for (i = k+1; i < size; i++) {
  484. temp1 = fabs(M[i*size + k]);
  485. if (temp < temp1) {
  486. temp = temp1;
  487. p = i;
  488. }
  489. }
  490. /* permutate lines with index k and p */
  491. if (p != k) {
  492. ps = p*size;
  493. for (i = 0; i < size; i++) {
  494. temp = M[ks + i];
  495. M[ks + i] = M[ps + i];
  496. M[ps + i] = temp;
  497. }
  498. i = seq[k];
  499. seq[k] = seq[p];
  500. seq[p] = i;
  501. }
  502. /* test for singular matrix */
  503. if (fabs(M[ksk]) < PIVOT_TOLERANCE)
  504. return -1;
  505. /* elimination */
  506. temp = M[ksk];
  507. for (j = k+1; j < size; j++) {
  508. M[j*size + k] /= temp;
  509. }
  510. for (j = k+1; j < size; j++) {
  511. js = j * size;
  512. temp = M[js + k];
  513. for(i = k+1; i < size; i++) {
  514. M[js + i] -= temp * M[ks + i];
  515. }
  516. M[js + k] = temp;
  517. }
  518. }
  519. /* Backward substitution with identity matrix */
  520. memset(result, 0, size*size*sizeof(double));
  521. for (i = 0; i < size; i++) {
  522. result[i*size + seq[i]] = 1.0;
  523. iseq[seq[i]] = i;
  524. }
  525. for (i = 0; i < size; i++) {
  526. is = iseq[i];
  527. for (k = 1; k < size; k++) {
  528. ks = k*size;
  529. temp = 0.0;
  530. for (j = is; j < k; j++)
  531. temp += M[ks + j] * result[j*size + i];
  532. result[ks + i] -= temp;
  533. }
  534. for (k = size-1; k >= 0; k--) {
  535. ks = k*size;
  536. temp = result[ks + i];
  537. for (j = k+1; j < size; j++)
  538. temp -= M[ks + j] * result[j*size + i];
  539. result[ks + i] = temp / M[ks + k];
  540. }
  541. }
  542. return 0;
  543. }
  544. /*
  545. Quaternion from matrix.
  546. */
  547. int quaternion_from_matrix(
  548. double *matrix, /* double[16] */
  549. double *quaternion) /* double[4] */
  550. {
  551. double s;
  552. double *M = matrix;
  553. double *q = quaternion;
  554. if (ISZERO(M[15]))
  555. return -1;
  556. if ((M[0] + M[5] + M[10]) > 0.0) {
  557. s = 0.5 / sqrt(M[0] + M[5] + M[10] + M[15]);
  558. q[0] = 0.25 / s;
  559. q[3] = (M[4] - M[1]) * s;
  560. q[2] = (M[2] - M[8]) * s;
  561. q[1] = (M[9] - M[6]) * s;
  562. } else if ((M[0] > M[5]) && (M[0] > M[10])) {
  563. s = 0.5 / sqrt(M[0] - (M[5] + M[10]) + M[15]);
  564. q[1] = 0.25 / s;
  565. q[2] = (M[4] + M[1]) * s;
  566. q[3] = (M[2] + M[8]) * s;
  567. q[0] = (M[9] - M[6]) * s;
  568. } else if (M[5] > M[10]) {
  569. s = 0.5 / sqrt(M[5] - (M[0] + M[10]) + M[15]);
  570. q[2] = 0.25 / s;
  571. q[1] = (M[4] + M[1]) * s;
  572. q[0] = (M[2] - M[8]) * s;
  573. q[3] = (M[9] + M[6]) * s;
  574. } else {
  575. s = 0.5 / sqrt(M[10] - (M[0] + M[5]) + M[15]);
  576. q[3] = 0.25 / s;
  577. q[0] = (M[4] - M[1]) * s;
  578. q[1] = (M[2] + M[8]) * s;
  579. q[2] = (M[9] + M[6]) * s;
  580. }
  581. if (M[15] != 1.0) {
  582. s = 1.0 / sqrt(M[15]);
  583. q[0] *= s;
  584. q[1] *= s;
  585. q[2] *= s;
  586. q[3] *= s;
  587. }
  588. return 0;
  589. }
  590. /*
  591. Quaternion to rotation matrix.
  592. */
  593. int quaternion_matrix(
  594. double *quat, /* double[4] */
  595. double *matrix) /* double[16] */
  596. {
  597. double *M = matrix;
  598. double *q = quat;
  599. double n = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
  600. if (n < EPSILON) {
  601. /* return identity matrix */
  602. memset(M, 0, 16*sizeof(double));
  603. M[0] = M[5] = M[10] = M[15] = 1.0;
  604. } else {
  605. q[0] /= n;
  606. q[1] /= n;
  607. q[2] /= n;
  608. q[3] /= n;
  609. {
  610. double x2 = q[1]+q[1];
  611. double y2 = q[2]+q[2];
  612. double z2 = q[3]+q[3];
  613. {
  614. double xx2 = q[1]*x2;
  615. double yy2 = q[2]*y2;
  616. double zz2 = q[3]*z2;
  617. M[0] = 1.0 - yy2 - zz2;
  618. M[5] = 1.0 - xx2 - zz2;
  619. M[10] = 1.0 - xx2 - yy2;
  620. }{
  621. double yz2 = q[2]*z2;
  622. double wx2 = q[0]*x2;
  623. M[6] = yz2 - wx2;
  624. M[9] = yz2 + wx2;
  625. }{
  626. double xy2 = q[1]*y2;
  627. double wz2 = q[0]*z2;
  628. M[1] = xy2 - wz2;
  629. M[4] = xy2 + wz2;
  630. }{
  631. double xz2 = q[1]*z2;
  632. double wy2 = q[0]*y2;
  633. M[8] = xz2 - wy2;
  634. M[2] = xz2 + wy2;
  635. }
  636. M[3] = M[7] = M[11] = M[12] = M[13] = M[14] = 0.0;
  637. M[15] = 1.0;
  638. }
  639. }
  640. return 0;
  641. }
  642. /*
  643. Unit quaternion from unit sphere points.
  644. */
  645. int quaternion_from_sphere_points(
  646. double *point0, /* double[3] */
  647. double *point1, /* double[3] */
  648. double *quat) /* double[4] */
  649. {
  650. quat[0] = point0[0]*point1[0] + point0[1]*point1[1] + point0[2]*point1[2];
  651. quat[1] = point0[1]*point1[2] - point0[2]*point1[1];
  652. quat[2] = point0[2]*point1[0] - point0[0]*point1[2];
  653. quat[3] = point0[0]*point1[1] - point0[1]*point1[0];
  654. return 0;
  655. }
  656. /*
  657. Unit quaternion to unit sphere points.
  658. */
  659. int quaternion_to_sphere_points(
  660. double *quat, /* double[4] */
  661. double *point0, /* double[3] */
  662. double *point1) /* double[3] */
  663. {
  664. double n = sqrt(quat[0]*quat[0] + quat[1]*quat[1]);
  665. if (n < EPSILON) {
  666. point0[0] = 0.0;
  667. point0[1] = 1.0;
  668. point0[2] = 0.0;
  669. } else {
  670. point0[0] = -quat[2] / n;
  671. point0[1] = quat[1] / n;
  672. point0[2] = 0.0;
  673. }
  674. point1[0] = quat[0]*point0[0] - quat[3]*point0[1];
  675. point1[1] = quat[0]*point0[1] + quat[3]*point0[0];
  676. point1[2] = quat[1]*point0[1] - quat[2]*point0[0];
  677. if (quat[0] < 0.0) {
  678. point0[0] = -point0[0];
  679. point0[1] = -point0[1];
  680. }
  681. return 0;
  682. }
  683. /*****************************************************************************/
  684. /* Python functions */
  685. /*
  686. Numpy array converters for use with PyArg_Parse functions.
  687. */
  688. static int
  689. PyConverter_DoubleArray(
  690. PyObject *object,
  691. PyObject **address)
  692. {
  693. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  694. if (*address == NULL) return NPY_FAIL;
  695. return NPY_SUCCEED;
  696. }
  697. static int
  698. PyConverter_AnyDoubleArray(
  699. PyObject *object,
  700. PyObject **address)
  701. {
  702. PyArrayObject *obj = (PyArrayObject *)object;
  703. if (PyArray_Check(object) && obj->descr->type_num == PyArray_DOUBLE) {
  704. *address = object;
  705. Py_INCREF(object);
  706. return NPY_SUCCEED;
  707. } else {
  708. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_ALIGNED);
  709. if (*address == NULL) {
  710. PyErr_Format(PyExc_ValueError, "can not convert to array");
  711. return NPY_FAIL;
  712. }
  713. return NPY_SUCCEED;
  714. }
  715. }
  716. static int
  717. PyConverter_DoubleArrayOrNone(
  718. PyObject *object,
  719. PyObject **address)
  720. {
  721. if ((object == NULL) || (object == Py_None)) {
  722. *address = NULL;
  723. } else {
  724. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  725. if (*address == NULL) {
  726. PyErr_Format(PyExc_ValueError, "can not convert to array");
  727. return NPY_FAIL;
  728. }
  729. }
  730. return NPY_SUCCEED;
  731. }
  732. static int
  733. PyConverter_DoubleMatrix44(
  734. PyObject *object,
  735. PyObject **address)
  736. {
  737. PyArrayObject *obj;
  738. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  739. if (*address == NULL) {
  740. PyErr_Format(PyExc_ValueError, "can not convert to array");
  741. return NPY_FAIL;
  742. }
  743. obj = (PyArrayObject *) *address;
  744. if ((PyArray_NDIM(obj) != 2) || (PyArray_DIM(obj, 0) != 4)
  745. || (PyArray_DIM(obj, 1) != 4) || PyArray_ISCOMPLEX(obj)) {
  746. PyErr_Format(PyExc_ValueError, "not a 4x4 matrix");
  747. Py_DECREF(*address);
  748. *address = NULL;
  749. return NPY_FAIL;
  750. }
  751. return NPY_SUCCEED;
  752. }
  753. static int
  754. PyConverter_DoubleMatrix44Copy(
  755. PyObject *object,
  756. PyObject **address)
  757. {
  758. PyArrayObject *obj;
  759. *address = PyArray_FROM_OTF(object, NPY_DOUBLE,
  760. NPY_ENSURECOPY|NPY_IN_ARRAY);
  761. if (*address == NULL) {
  762. PyErr_Format(PyExc_ValueError, "can not convert to array");
  763. return NPY_FAIL;
  764. }
  765. obj = (PyArrayObject *) *address;
  766. if ((PyArray_NDIM(obj) != 2) || (PyArray_DIM(obj, 0) != 4)
  767. || (PyArray_DIM(obj, 1) != 4) || PyArray_ISCOMPLEX(obj)) {
  768. PyErr_Format(PyExc_ValueError, "not a 4x4 matrix");
  769. Py_DECREF(*address);
  770. *address = NULL;
  771. return NPY_FAIL;
  772. }
  773. return NPY_SUCCEED;
  774. }
  775. static int
  776. PyConverter_DoubleVector3(
  777. PyObject *object,
  778. PyObject **address)
  779. {
  780. PyArrayObject *obj;
  781. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  782. if (*address == NULL) {
  783. PyErr_Format(PyExc_ValueError, "can not convert to array");
  784. return NPY_FAIL;
  785. }
  786. obj = (PyArrayObject *) *address;
  787. if ((PyArray_NDIM(obj) != 1) || (PyArray_DIM(obj, 0) < 3)
  788. || PyArray_ISCOMPLEX(obj)) {
  789. PyErr_Format(PyExc_ValueError, "not a vector3");
  790. Py_DECREF(*address);
  791. *address = NULL;
  792. return NPY_FAIL;
  793. }
  794. return NPY_SUCCEED;
  795. }
  796. static int
  797. PyConverter_DoubleVector4(
  798. PyObject *object,
  799. PyObject **address)
  800. {
  801. PyArrayObject *obj;
  802. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  803. if (*address == NULL) {
  804. PyErr_Format(PyExc_ValueError, "can not convert to array");
  805. return NPY_FAIL;
  806. }
  807. obj = (PyArrayObject *) *address;
  808. if ((PyArray_NDIM(obj) != 1) || (PyArray_DIM(obj, 0) < 4)
  809. || PyArray_ISCOMPLEX(obj)) {
  810. PyErr_Format(PyExc_ValueError, "not a vector4");
  811. Py_DECREF(*address);
  812. *address = NULL;
  813. return NPY_FAIL;
  814. }
  815. return NPY_SUCCEED;
  816. }
  817. static int
  818. PyConverter_DoubleVector4Copy(
  819. PyObject *object,
  820. PyObject **address)
  821. {
  822. PyArrayObject *obj;
  823. *address = PyArray_FROM_OTF(object, NPY_DOUBLE,
  824. NPY_ENSURECOPY|NPY_IN_ARRAY);
  825. if (*address == NULL) {
  826. PyErr_Format(PyExc_ValueError, "can not convert to array");
  827. return NPY_FAIL;
  828. }
  829. obj = (PyArrayObject *) *address;
  830. if ((PyArray_NDIM(obj) != 1) || (PyArray_DIM(obj, 0) < 4)
  831. || PyArray_ISCOMPLEX(obj)) {
  832. PyErr_Format(PyExc_ValueError, "not a vector4");
  833. Py_DECREF(*address);
  834. *address = NULL;
  835. return NPY_FAIL;
  836. }
  837. return NPY_SUCCEED;
  838. }
  839. static int
  840. PyConverter_DoubleVector3OrNone(
  841. PyObject *object,
  842. PyObject **address)
  843. {
  844. if ((object == NULL) || (object == Py_None)) {
  845. *address = NULL;
  846. } else {
  847. PyArrayObject *obj;
  848. *address = PyArray_FROM_OTF(object, NPY_DOUBLE, NPY_IN_ARRAY);
  849. if (*address == NULL) {
  850. PyErr_Format(PyExc_ValueError, "can not convert to array");
  851. return NPY_FAIL;
  852. }
  853. obj = (PyArrayObject *) *address;
  854. if ((PyArray_NDIM(obj) != 1) || (PyArray_DIM(obj, 0) < 3)
  855. || PyArray_ISCOMPLEX(obj)) {
  856. PyErr_Format(PyExc_ValueError, "not a vector3");
  857. Py_DECREF(*address);
  858. *address = NULL;
  859. return NPY_FAIL;
  860. }
  861. }
  862. return NPY_SUCCEED;
  863. }
  864. static int
  865. PyOutputConverter_AnyDoubleArrayOrNone(
  866. PyObject *object,
  867. PyArrayObject **address)
  868. {
  869. PyArrayObject *obj = (PyArrayObject *)object;
  870. if ((object == NULL) || (object == Py_None)) {
  871. *address = NULL;
  872. return NPY_SUCCEED;
  873. }
  874. if (PyArray_Check(object) && (obj->descr->type_num == PyArray_DOUBLE)) {
  875. Py_INCREF(object);
  876. *address = (PyArrayObject *)object;
  877. return NPY_SUCCEED;
  878. } else {
  879. PyErr_Format(PyExc_TypeError, "output must be array of type double");
  880. *address = NULL;
  881. return NPY_FAIL;
  882. }
  883. }
  884. /*
  885. Return i-th element of Python sequence as long, or -1 on failure.
  886. */
  887. long PySequence_GetInteger(PyObject *obj, Py_ssize_t i)
  888. {
  889. long value;
  890. PyObject *item = PySequence_GetItem(obj, i);
  891. if (item == NULL ||
  892. #if PY_MAJOR_VERSION < 3
  893. !PyInt_Check(item)
  894. #else
  895. !PyLong_Check(item)
  896. #endif
  897. ) {
  898. PyErr_Format(PyExc_ValueError, "expected integer number");
  899. Py_XDECREF(item);
  900. return -1;
  901. }
  902. #if PY_MAJOR_VERSION < 3
  903. value = PyInt_AsLong(item);
  904. #else
  905. value = PyLong_AsLong(item);
  906. #endif
  907. Py_XDECREF(item);
  908. return value;
  909. }
  910. /*
  911. Equivalence of transformations.
  912. */
  913. char py_is_same_transform_doc[] =
  914. "Return True if two matrices perform same transformation.";
  915. static PyObject *
  916. py_is_same_transform(
  917. PyObject *obj,
  918. PyObject *args,
  919. PyObject *kwds)
  920. {
  921. int result;
  922. PyArrayObject *matrix0 = NULL;
  923. PyArrayObject *matrix1 = NULL;
  924. static char *kwlist[] = {"matrix0", "matrix1", NULL};
  925. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&", kwlist,
  926. PyConverter_DoubleMatrix44, &matrix0,
  927. PyConverter_DoubleMatrix44, &matrix1)) goto _fail;
  928. {
  929. double *M0 = (double *)PyArray_DATA(matrix0);
  930. double *M1 = (double *)PyArray_DATA(matrix1);
  931. double t0 = M0[15];
  932. double t1 = M1[15];
  933. double t;
  934. int i;
  935. if (ISZERO(t0) || ISZERO(t1)) {
  936. result = 0;
  937. } else {
  938. result = 1;
  939. for (i = 0; i < 16; i++) {
  940. t = M1[i] / t1;
  941. if (fabs(M0[i]/t0 - t) > (1e-8 + 1e-5*fabs(t))) {
  942. result = 0;
  943. break;
  944. }
  945. }
  946. }
  947. }
  948. Py_DECREF(matrix0);
  949. Py_DECREF(matrix1);
  950. if (result)
  951. Py_RETURN_TRUE;
  952. else
  953. Py_RETURN_FALSE;
  954. _fail:
  955. Py_XDECREF(matrix0);
  956. Py_XDECREF(matrix1);
  957. return NULL;
  958. }
  959. /*
  960. Identity matrix.
  961. */
  962. char py_identity_matrix_doc[] = "Return identity/unit matrix.";
  963. static PyObject *
  964. py_identity_matrix(
  965. PyObject *obj,
  966. PyObject *args)
  967. {
  968. PyArrayObject *result = NULL;
  969. PyArray_Descr *type = NULL;
  970. Py_ssize_t dims[] = {4, 4};
  971. type = PyArray_DescrFromType(NPY_DOUBLE);
  972. result = (PyArrayObject*)PyArray_Zeros(2, dims, type, 0);
  973. if (result == NULL) {
  974. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  975. goto _fail;
  976. }
  977. {
  978. double *M = (double *)PyArray_DATA(result);
  979. M[0] = M[5] = M[10] = M[15] = 1.0;
  980. }
  981. return PyArray_Return(result);
  982. _fail:
  983. Py_XDECREF(result);
  984. return NULL;
  985. }
  986. /*
  987. Translation matrix.
  988. */
  989. char py_translation_matrix_doc[] =
  990. "Return matrix to translate by direction vector.";
  991. static PyObject *
  992. py_translation_matrix(
  993. PyObject *obj,
  994. PyObject *args,
  995. PyObject *kwds)
  996. {
  997. PyArrayObject *result = NULL;
  998. PyArrayObject *direction = NULL;
  999. PyArray_Descr *type = NULL;
  1000. Py_ssize_t dims[] = {4, 4};
  1001. static char *kwlist[] = {"direction", NULL};
  1002. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", kwlist,
  1003. PyConverter_DoubleVector3, &direction)) goto _fail;
  1004. type = PyArray_DescrFromType(NPY_DOUBLE);
  1005. result = (PyArrayObject*)PyArray_Zeros(2, dims, type, 0);
  1006. if (result == NULL) {
  1007. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1008. goto _fail;
  1009. }
  1010. {
  1011. double *M = (double *)PyArray_DATA(result);
  1012. double *d = (double *)PyArray_DATA(direction);
  1013. M[0] = M[5] = M[10] = M[15] = 1.0;
  1014. M[3] = d[0];
  1015. M[7] = d[1];
  1016. M[11] = d[2];
  1017. }
  1018. Py_DECREF(direction);
  1019. return PyArray_Return(result);
  1020. _fail:
  1021. Py_XDECREF(direction);
  1022. Py_XDECREF(result);
  1023. return NULL;
  1024. }
  1025. /*
  1026. Reflection matrix.
  1027. */
  1028. char py_reflection_matrix_doc[] =
  1029. "Return matrix to mirror at plane defined by point and normal vector.";
  1030. static PyObject *
  1031. py_reflection_matrix(
  1032. PyObject *obj,
  1033. PyObject *args,
  1034. PyObject *kwds)
  1035. {
  1036. PyArrayObject *result = NULL;
  1037. PyArrayObject *point = NULL;
  1038. PyArrayObject *normal = NULL;
  1039. Py_ssize_t dims[] = {4, 4};
  1040. static char *kwlist[] = {"point", "normal", NULL};
  1041. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&", kwlist,
  1042. PyConverter_DoubleVector3, &point,
  1043. PyConverter_DoubleVector3, &normal)) goto _fail;
  1044. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1045. if (result == NULL) {
  1046. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1047. goto _fail;
  1048. }
  1049. {
  1050. double *M = (double *)PyArray_DATA(result);
  1051. double *p = (double *)PyArray_DATA(point);
  1052. double *n = (double *)PyArray_DATA(normal);
  1053. double nx = n[0];
  1054. double ny = n[1];
  1055. double nz = n[2];
  1056. double t = sqrt(nx*nx + ny*ny + nz*nz);
  1057. if (t < EPSILON) {
  1058. PyErr_Format(PyExc_ValueError, "invalid normal vector");
  1059. goto _fail;
  1060. }
  1061. nx /= t;
  1062. ny /= t;
  1063. nz /= t;
  1064. M[12] = M[13] = M[14] = 0.0;
  1065. M[15] = 1.0;
  1066. M[0] = 1.0 - 2.0 * nx *nx;
  1067. M[5] = 1.0 - 2.0 * ny *ny;
  1068. M[10] = 1.0 - 2.0 * nz *nz;
  1069. M[1] = M[4] = -2.0 * nx *ny;
  1070. M[2] = M[8] = -2.0 * nx *nz;
  1071. M[6] = M[9] = -2.0 * ny *nz;
  1072. t = 2.0 * (p[0]*nx + p[1]*ny + p[2]*nz);
  1073. M[3] = nx * t;
  1074. M[7] = ny * t;
  1075. M[11] = nz * t;
  1076. }
  1077. Py_DECREF(point);
  1078. Py_DECREF(normal);
  1079. return PyArray_Return(result);
  1080. _fail:
  1081. Py_XDECREF(point);
  1082. Py_XDECREF(normal);
  1083. Py_XDECREF(result);
  1084. return NULL;
  1085. }
  1086. /*
  1087. Rotation matrix.
  1088. */
  1089. char py_rotation_matrix_doc[] =
  1090. "Return matrix to rotate about axis defined by point and direction.";
  1091. static PyObject *
  1092. py_rotation_matrix(
  1093. PyObject *obj,
  1094. PyObject *args,
  1095. PyObject *kwds)
  1096. {
  1097. PyArrayObject *result = NULL;
  1098. PyArrayObject *point = NULL;
  1099. PyArrayObject *direction = NULL;
  1100. Py_ssize_t dims[] = {4, 4};
  1101. double angle;
  1102. static char *kwlist[] = {"angle", "direction", "point", NULL};
  1103. if (!PyArg_ParseTupleAndKeywords(args, kwds, "dO&|O&", kwlist,
  1104. &angle,
  1105. PyConverter_DoubleVector3, &direction,
  1106. PyConverter_DoubleVector3OrNone, &point)) goto _fail;
  1107. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1108. if (result == NULL) {
  1109. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1110. goto _fail;
  1111. }
  1112. {
  1113. double *M = (double *)PyArray_DATA(result);
  1114. double *d = (double *)PyArray_DATA(direction);
  1115. double dx = d[0];
  1116. double dy = d[1];
  1117. double dz = d[2];
  1118. double sa = sin(angle);
  1119. double ca = cos(angle);
  1120. double ca1 = 1 - ca;
  1121. double s, t;
  1122. t = sqrt(dx*dx + dy*dy + dz*dz);
  1123. if (t < EPSILON) {
  1124. PyErr_Format(PyExc_ValueError, "invalid direction vector");
  1125. goto _fail;
  1126. }
  1127. dx /= t;
  1128. dy /= t;
  1129. dz /= t;
  1130. M[0] = ca + dx*dx * ca1;
  1131. M[5] = ca + dy*dy * ca1;
  1132. M[10] = ca + dz*dz * ca1;
  1133. s = dz * sa;
  1134. t = dx*dy * ca1;
  1135. M[1] = t - s;
  1136. M[4] = t + s;
  1137. s = dy * sa;
  1138. t = dx*dz * ca1;
  1139. M[2] = t + s;
  1140. M[8] = t - s;
  1141. s = dx * sa;
  1142. t = dy*dz * ca1;
  1143. M[6] = t - s;
  1144. M[9] = t + s;
  1145. M[12] = M[13] = M[14] = 0.0;
  1146. M[15] = 1.0;
  1147. if (point != NULL) {
  1148. double *p = (double *)PyArray_DATA(point);
  1149. M[3] = p[0] - (M[0]*p[0] + M[1]*p[1] + M[2]*p[2]);
  1150. M[7] = p[1] - (M[4]*p[0] + M[5]*p[1] + M[6]*p[2]);
  1151. M[11] = p[2] - (M[8]*p[0] + M[9]*p[1] + M[10]*p[2]);
  1152. } else {
  1153. M[3] = M[7] = M[11] = 0.0;
  1154. }
  1155. }
  1156. Py_XDECREF(point);
  1157. Py_DECREF(direction);
  1158. return PyArray_Return(result);
  1159. _fail:
  1160. Py_XDECREF(point);
  1161. Py_XDECREF(direction);
  1162. Py_XDECREF(result);
  1163. return NULL;
  1164. }
  1165. /*
  1166. Projection matrix.
  1167. */
  1168. char py_projection_matrix_doc[] =
  1169. "Return matrix to project onto plane defined by point and normal.";
  1170. static PyObject *
  1171. py_projection_matrix(
  1172. PyObject *obj,
  1173. PyObject *args,
  1174. PyObject *kwds)
  1175. {
  1176. PyArrayObject *result = NULL;
  1177. PyArrayObject *point = NULL;
  1178. PyArrayObject *normal = NULL;
  1179. PyArrayObject *direction = NULL;
  1180. PyArrayObject *perspective = NULL;
  1181. PyObject *pseudobj = NULL;
  1182. Py_ssize_t dims[] = {4, 4};
  1183. int pseudo = 0;
  1184. static char *kwlist[] = {"point", "normal", "direction",
  1185. "perspective", "pseudo", NULL};
  1186. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|O&O&O", kwlist,
  1187. PyConverter_DoubleVector3, &point,
  1188. PyConverter_DoubleVector3, &normal,
  1189. PyConverter_DoubleVector3OrNone, &direction,
  1190. PyConverter_DoubleVector3OrNone, &perspective,
  1191. &pseudobj)) goto _fail;
  1192. if (pseudobj != NULL)
  1193. pseudo = PyObject_IsTrue(pseudobj);
  1194. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1195. if (result == NULL) {
  1196. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1197. goto _fail;
  1198. }
  1199. {
  1200. double *M = (double *)PyArray_DATA(result);
  1201. double *p = (double *)PyArray_DATA(point);
  1202. double px = p[0];
  1203. double py = p[1];
  1204. double pz = p[2];
  1205. double *n = (double *)PyArray_DATA(normal);
  1206. double nx = n[0];
  1207. double ny = n[1];
  1208. double nz = n[2];
  1209. double t = sqrt(nx*nx + ny*ny + nz*nz);
  1210. if (t < EPSILON) {
  1211. PyErr_Format(PyExc_ValueError, "invalid normal vector");
  1212. goto _fail;
  1213. }
  1214. nx /= t;
  1215. ny /= t;
  1216. nz /= t;
  1217. if (perspective) {
  1218. /* perspective projection */
  1219. double *d = (double *)PyArray_DATA(perspective);
  1220. double dx = d[0];
  1221. double dy = d[1];
  1222. double dz = d[2];
  1223. t = (dx-px)*nx + (dy-py)*ny + (dz-pz)*nz;
  1224. M[0] = t - dx*nx;
  1225. M[5] = t - dy*ny;
  1226. M[10] = t - dz*nz;
  1227. M[1] = - dx*ny;
  1228. M[2] = - dx*nz;
  1229. M[4] = - dy*nx;
  1230. M[6] = - dy*nz;
  1231. M[8] = - dz*nx;
  1232. M[9] = - dz*ny;
  1233. if (pseudo) {
  1234. /* preserve relative depth */
  1235. M[0] -= nx*nx;
  1236. M[5] -= ny*ny;
  1237. M[10] -= nz*nz;
  1238. t = nx*ny;
  1239. M[1] -= t;
  1240. M[4] -= t;
  1241. t = nx*nz;
  1242. M[2] -= t;
  1243. M[8] -= t;
  1244. t = ny*nz;
  1245. M[6] -= t;
  1246. M[9] -= t;
  1247. t = px*nx + py*ny + pz*nz;
  1248. M[3] = t * (dx+nx);
  1249. M[7] = t * (dy+ny);
  1250. M[11] = t * (dz+nz);
  1251. } else {
  1252. t = px*nx + py*ny + pz*nz;
  1253. M[3] = t * dx;
  1254. M[7] = t * dy;
  1255. M[11] = t * dz;
  1256. }
  1257. M[12] = -nx;
  1258. M[13] = -ny;
  1259. M[14] = -nz;
  1260. M[15] = dx*nx + dy*ny + dz*nz;
  1261. } else if (direction) {
  1262. /* parallel projection */
  1263. double *d = (double *)PyArray_DATA(direction);
  1264. double dx = d[0];
  1265. double dy = d[1];
  1266. double dz = d[2];
  1267. double scale = dx*nx + dy*ny + dz*nz;
  1268. if (ISZERO(scale)) {
  1269. PyErr_Format(PyExc_ValueError,
  1270. "normal and direction vectors are orthogonal");
  1271. goto _fail;
  1272. }
  1273. scale = -1.0 / scale;
  1274. M[0] = 1.0 + scale * dx*nx;
  1275. M[5] = 1.0 + scale * dy*ny;
  1276. M[10] = 1.0 + scale * dz*nz;
  1277. M[1] = scale * dx*ny;
  1278. M[2] = scale * dx*nz;
  1279. M[4] = scale * dy*nx;
  1280. M[6] = scale * dy*nz;
  1281. M[8] = scale * dz*nx;
  1282. M[9] = scale * dz*ny;
  1283. t = (px*nx + py*ny + pz*nz) * -scale;
  1284. M[3] = t * dx;
  1285. M[7] = t * dy;
  1286. M[11] = t * dz;
  1287. M[12] = M[13] = M[14] = 0.0;
  1288. M[15] = 1.0;
  1289. } else {
  1290. /* orthogonal projection */
  1291. M[0] = 1.0 - nx*nx;
  1292. M[5] = 1.0 - ny*ny;
  1293. M[10] = 1.0 - nz*nz;
  1294. M[1] = M[4] = - nx*ny;
  1295. M[2] = M[8] = - nx*nz;
  1296. M[6] = M[9] = - ny*nz;
  1297. t = px*nx + py*ny + pz*nz;
  1298. M[3] = t * nx;
  1299. M[7] = t * ny;
  1300. M[11] = t * nz;
  1301. M[12] = M[13] = M[14] = 0.0;
  1302. M[15] = 1.0;
  1303. }
  1304. }
  1305. Py_DECREF(point);
  1306. Py_DECREF(normal);
  1307. Py_XDECREF(direction);
  1308. Py_XDECREF(perspective);
  1309. return PyArray_Return(result);
  1310. _fail:
  1311. Py_XDECREF(point);
  1312. Py_XDECREF(normal);
  1313. Py_XDECREF(direction);
  1314. Py_XDECREF(perspective);
  1315. Py_XDECREF(result);
  1316. return NULL;
  1317. }
  1318. /*
  1319. Clipping matrix.
  1320. */
  1321. char py_clip_matrix_doc[] =
  1322. "Return matrix to obtain normalized device coordinates from frustum.";
  1323. static PyObject *
  1324. py_clip_matrix(
  1325. PyObject *obj,
  1326. PyObject *args,
  1327. PyObject *kwds)
  1328. {
  1329. PyArrayObject *result = NULL;
  1330. PyObject *boolobj = NULL;
  1331. Py_ssize_t dims[] = {4, 4};
  1332. double *M;
  1333. double left, right, bottom, top, hither, yon;
  1334. int perspective = 0;
  1335. static char *kwlist[] = {"left", "right", "bottom",
  1336. "top", "near", "far", "perspective", NULL};
  1337. if (!PyArg_ParseTupleAndKeywords(args, kwds, "dddddd|O", kwlist,
  1338. &left, &right, &bottom, &top, &hither, &yon, &boolobj))
  1339. goto _fail;
  1340. if (boolobj != NULL)
  1341. perspective = PyObject_IsTrue(boolobj);
  1342. if ((left >= right) || (bottom >= top) || (hither >= yon)) {
  1343. PyErr_Format(PyExc_ValueError, "invalid frustum");
  1344. goto _fail;
  1345. }
  1346. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1347. if (result == NULL) {
  1348. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1349. goto _fail;
  1350. }
  1351. M = (double *)PyArray_DATA(result);
  1352. if (perspective) {
  1353. double t = 2.0 * hither;
  1354. if (hither < EPSILON) {
  1355. PyErr_Format(PyExc_ValueError, "invalid frustum: near <= 0");
  1356. goto _fail;
  1357. }
  1358. M[1] = M[3] = M[4] = M[7] = M[8] = M[9] = M[12] = M[13] = M[15] = 0.0;
  1359. M[14] = -1.0;
  1360. M[0] = t / (left-right);
  1361. M[2] = (right+left) / (right-left);
  1362. M[5] = t / (bottom-top);
  1363. M[6] = (top+bottom) / (top-bottom);
  1364. M[10] = (yon+hither) / (hither-yon);
  1365. M[11] = t*yon / (yon-hither);
  1366. } else {
  1367. M[1] = M[2] = M[4] = M[6] = M[8] = M[9] = M[12] = M[13] = M[14] = 0.0;
  1368. M[15] = 1.0;
  1369. M[0] = 2.0 / (right-left);
  1370. M[3] = (right+left) / (left-right);
  1371. M[5] = 2.0 / (top-bottom);
  1372. M[7] = (top+bottom) / (bottom-top);
  1373. M[10] = 2.0 / (yon-hither);
  1374. M[11] = (yon+hither) / (hither-yon);
  1375. }
  1376. return PyArray_Return(result);
  1377. _fail:
  1378. Py_XDECREF(result);
  1379. return NULL;
  1380. }
  1381. /*
  1382. Scale matrix.
  1383. */
  1384. char py_scale_matrix_doc[] =
  1385. "Return matrix to scale by factor around origin in direction.";
  1386. static PyObject *
  1387. py_scale_matrix(
  1388. PyObject *obj,
  1389. PyObject *args,
  1390. PyObject *kwds)
  1391. {
  1392. PyArrayObject *result = NULL;
  1393. PyArrayObject *origin = NULL;
  1394. PyArrayObject *direction = NULL;
  1395. Py_ssize_t dims[] = {4, 4};
  1396. double factor;
  1397. static char *kwlist[] = {"factor", "origin", "direction", NULL};
  1398. if (!PyArg_ParseTupleAndKeywords(args, kwds, "d|O&O&", kwlist,
  1399. &factor,
  1400. PyConverter_DoubleVector3OrNone, &origin,
  1401. PyConverter_DoubleVector3OrNone, &direction)) goto _fail;
  1402. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1403. if (result == NULL) {
  1404. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1405. goto _fail;
  1406. }
  1407. {
  1408. double *M = (double *)PyArray_DATA(result);
  1409. if (direction == NULL) {
  1410. memset(M, 0, 16*sizeof(double));
  1411. M[0] = M[5] = M[10] = factor;
  1412. M[15] = 1.0;
  1413. if (origin != NULL) {
  1414. double *p = (double *)PyArray_DATA(origin);
  1415. factor = 1.0 - factor;
  1416. M[3] = factor * p[0];
  1417. M[7] = factor * p[1];
  1418. M[11] = factor * p[2];
  1419. }
  1420. } else {
  1421. double *d = (double *)PyArray_DATA(direction);
  1422. double dx = d[0];
  1423. double dy = d[1];
  1424. double dz = d[2];
  1425. factor = 1.0 - factor;
  1426. M[0] = 1.0 - factor * dx*dx;
  1427. M[5] = 1.0 - factor * dy*dy;
  1428. M[10] = 1.0 - factor * dz*dz;
  1429. factor *= -1.0;
  1430. M[1] = M[4] = factor * dx*dy;
  1431. M[2] = M[8] = factor * dx*dz;
  1432. M[6] = M[9] = factor * dy*dz;
  1433. M[12] = M[13] = M[14] = 0.0;
  1434. M[15] = 1.0;
  1435. if (origin != NULL) {
  1436. double *p = (double *)PyArray_DATA(origin);
  1437. factor *= - (p[0]*dx + p[1]*dy + p[2]*dz);
  1438. M[3] = factor * dx;
  1439. M[7] = factor * dy;
  1440. M[11] = factor * dz;
  1441. } else {
  1442. M[3] = M[7] = M[11] = 0.0;
  1443. }
  1444. }
  1445. }
  1446. Py_XDECREF(origin);
  1447. Py_XDECREF(direction);
  1448. return PyArray_Return(result);
  1449. _fail:
  1450. Py_XDECREF(origin);
  1451. Py_XDECREF(direction);
  1452. Py_XDECREF(result);
  1453. return NULL;
  1454. }
  1455. /*
  1456. Shearing matrix.
  1457. */
  1458. char py_shear_matrix_doc[] =
  1459. "Return matrix to shear by angle along direction vector on shear plane.";
  1460. static PyObject *
  1461. py_shear_matrix(
  1462. PyObject *obj,
  1463. PyObject *args,
  1464. PyObject *kwds)
  1465. {
  1466. PyArrayObject *result = NULL;
  1467. PyArrayObject *direction = NULL;
  1468. PyArrayObject *point = NULL;
  1469. PyArrayObject *normal = NULL;
  1470. Py_ssize_t dims[] = {4, 4};
  1471. double angle;
  1472. static char *kwlist[] = {"angle", "direction", "point", "normal", NULL};
  1473. if (!PyArg_ParseTupleAndKeywords(args, kwds, "dO&O&O&", kwlist,
  1474. &angle,
  1475. PyConverter_DoubleVector3, &direction,
  1476. PyConverter_DoubleVector3, &point,
  1477. PyConverter_DoubleVector3, &normal)) goto _fail;
  1478. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1479. if (result == NULL) {
  1480. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1481. goto _fail;
  1482. }
  1483. {
  1484. double *M = (double *)PyArray_DATA(result);
  1485. double *p = (double *)PyArray_DATA(point);
  1486. double *d = (double *)PyArray_DATA(direction);
  1487. double dx = d[0];
  1488. double dy = d[1];
  1489. double dz = d[2];
  1490. double *n = (double *)PyArray_DATA(normal);
  1491. double nx = n[0];
  1492. double ny = n[1];
  1493. double nz = n[2];
  1494. double t;
  1495. t = sqrt(dx*dx + dy*dy + dz*dz);
  1496. if (t < EPSILON) {
  1497. PyErr_Format(PyExc_ValueError, "invalid direction vector");
  1498. goto _fail;
  1499. }
  1500. dx /= t;
  1501. dy /= t;
  1502. dz /= t;
  1503. t = sqrt(nx*nx + ny*ny + nz*nz);
  1504. if (t < EPSILON) {
  1505. PyErr_Format(PyExc_ValueError, "invalid normal vector");
  1506. goto _fail;
  1507. }
  1508. nx /= t;
  1509. ny /= t;
  1510. nz /= t;
  1511. if (fabs(nx*dx + ny*dy + nz*dz) > 1e-6) {
  1512. PyErr_Format(PyExc_ValueError,
  1513. "direction and normal vectors are not orthogonal");
  1514. goto _fail;
  1515. }
  1516. angle = tan(angle);
  1517. M[0] = 1.0 + angle * dx*nx;
  1518. M[5] = 1.0 + angle * dy*ny;
  1519. M[10] = 1.0 + angle * dz*nz;
  1520. M[1] = angle * dx*ny;
  1521. M[2] = angle * dx*nz;
  1522. M[4] = angle * dy*nx;
  1523. M[6] = angle * dy*nz;
  1524. M[8] = angle * dz*nx;
  1525. M[9] = angle * dz*ny;
  1526. M[12] = M[13] = M[14] = 0.0;
  1527. M[15] = 1.0;
  1528. t = -angle * (p[0]*nx + p[1]*ny + p[2]*nz);
  1529. M[3] = t * dx;
  1530. M[7] = t * dy;
  1531. M[11] = t * dz;
  1532. }
  1533. Py_DECREF(direction);
  1534. Py_DECREF(point);
  1535. Py_DECREF(normal);
  1536. return PyArray_Return(result);
  1537. _fail:
  1538. Py_XDECREF(direction);
  1539. Py_XDECREF(point);
  1540. Py_XDECREF(normal);
  1541. Py_XDECREF(result);
  1542. return NULL;
  1543. }
  1544. /*
  1545. Superimposition matrix.
  1546. */
  1547. char py_superimposition_matrix_doc[] =
  1548. "Return matrix to transform given vector set into second vector set.";
  1549. static PyObject *
  1550. py_superimposition_matrix(
  1551. PyObject *obj,
  1552. PyObject *args,
  1553. PyObject *kwds)
  1554. {
  1555. PyThreadState *_save = NULL;
  1556. PyArrayObject *result = NULL;
  1557. PyArrayObject *v0 = NULL;
  1558. PyArrayObject *v1 = NULL;
  1559. PyObject *usesvdobj = NULL;
  1560. PyObject *scalingobj = NULL;
  1561. double *buffer = NULL;
  1562. Py_ssize_t dims[] = {4, 4};
  1563. int scaling = 0;
  1564. static char *kwlist[] = {"v0", "v1", "scale", "usesvd", NULL};
  1565. if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|OO", kwlist,
  1566. PyConverter_AnyDoubleArray, &v0,
  1567. PyConverter_AnyDoubleArray, &v1,
  1568. &scalingobj, &usesvdobj)) goto _fail;
  1569. if (scalingobj != NULL)
  1570. scaling = PyObject_IsTrue(scalingobj);
  1571. if (!PyArray_SAMESHAPE(v0, v1)) {
  1572. PyErr_Format(PyExc_ValueError, "shape of vector sets must match");
  1573. goto _fail;
  1574. }
  1575. if ((PyArray_NDIM(v0) != 2) || PyArray_DIM(v0, 0) < 3) {
  1576. PyErr_Format(PyExc_ValueError,
  1577. "vector sets are of wrong shape or type");
  1578. goto _fail;
  1579. }
  1580. result = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_DOUBLE);
  1581. if (result == NULL) {
  1582. PyErr_Format(PyExc_MemoryError, "unable to allocate matrix");
  1583. goto _fail;
  1584. }
  1585. buffer = (double *)PyMem_Malloc(42 * sizeof(double));
  1586. if (!buffer) {
  1587. PyErr_Format(PyExc_MemoryError, "unable to allocate buffer");
  1588. goto _fail;
  1589. }
  1590. {
  1591. Py_ssize_t i, j;
  1592. double v0t[3], v1t[3];
  1593. double *q = buffer;
  1594. double *N = (buffer + 4);
  1595. double *M = (double *)PyArray_DATA(result);
  1596. Py_ssize_t size = PyArray_DIM(v0, 1);
  1597. Py_ssize_t v0s0 = PyArray_STRIDE(v0, 0);
  1598. Py_ssize_t v0s1 = PyArray_STRIDE(v0, 1);
  1599. Py_ssize_t v1s0 = PyArray_STRIDE(v1, 0);
  1600. Py_ssize_t v1s1 = PyArray_STRIDE(v1, 1);
  1601. /* displacements of v0 & v1 centroids from origin */
  1602. {
  1603. double t;
  1604. if (v0s1 == sizeof(double)) {
  1605. double *p;
  1606. for (j = 0; j < 3; j++) {
  1607. t = 0.0;
  1608. p = (double*)((char *)PyArray_DATA(v0) + j*v0s0);
  1609. for (i = 0; i < size; i++) {
  1610. t += p[i];
  1611. }
  1612. v0t[j] = t / (double)size;
  1613. }
  1614. } else {
  1615. char *p;
  1616. for (j = 0; j < 3; j++) {
  1617. t = 0.0;