2
0

PolyMatrix4.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. Copyright (C) 2011 by Ivan Safrin
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "PolyMatrix4.h"
  20. using namespace Polycode;
  21. Matrix4::Matrix4() {
  22. identity();
  23. }
  24. Matrix4::~Matrix4() {
  25. }
  26. Matrix4::Matrix4(const Number *m) {
  27. memcpy(ml, m, sizeof(Number)*16);
  28. }
  29. Matrix4 Matrix4::Inverse() const
  30. {
  31. Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2], m03 = m[0][3];
  32. Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2], m13 = m[1][3];
  33. Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2], m23 = m[2][3];
  34. Number m30 = m[3][0], m31 = m[3][1], m32 = m[3][2], m33 = m[3][3];
  35. Number v0 = m20 * m31 - m21 * m30;
  36. Number v1 = m20 * m32 - m22 * m30;
  37. Number v2 = m20 * m33 - m23 * m30;
  38. Number v3 = m21 * m32 - m22 * m31;
  39. Number v4 = m21 * m33 - m23 * m31;
  40. Number v5 = m22 * m33 - m23 * m32;
  41. Number t00 = + (v5 * m11 - v4 * m12 + v3 * m13);
  42. Number t10 = - (v5 * m10 - v2 * m12 + v1 * m13);
  43. Number t20 = + (v4 * m10 - v2 * m11 + v0 * m13);
  44. Number t30 = - (v3 * m10 - v1 * m11 + v0 * m12);
  45. Number invDet = 1 / (t00 * m00 + t10 * m01 + t20 * m02 + t30 * m03);
  46. Number d00 = t00 * invDet;
  47. Number d10 = t10 * invDet;
  48. Number d20 = t20 * invDet;
  49. Number d30 = t30 * invDet;
  50. Number d01 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
  51. Number d11 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
  52. Number d21 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
  53. Number d31 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
  54. v0 = m10 * m31 - m11 * m30;
  55. v1 = m10 * m32 - m12 * m30;
  56. v2 = m10 * m33 - m13 * m30;
  57. v3 = m11 * m32 - m12 * m31;
  58. v4 = m11 * m33 - m13 * m31;
  59. v5 = m12 * m33 - m13 * m32;
  60. Number d02 = + (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
  61. Number d12 = - (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
  62. Number d22 = + (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
  63. Number d32 = - (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
  64. v0 = m21 * m10 - m20 * m11;
  65. v1 = m22 * m10 - m20 * m12;
  66. v2 = m23 * m10 - m20 * m13;
  67. v3 = m22 * m11 - m21 * m12;
  68. v4 = m23 * m11 - m21 * m13;
  69. v5 = m23 * m12 - m22 * m13;
  70. Number d03 = - (v5 * m01 - v4 * m02 + v3 * m03) * invDet;
  71. Number d13 = + (v5 * m00 - v2 * m02 + v1 * m03) * invDet;
  72. Number d23 = - (v4 * m00 - v2 * m01 + v0 * m03) * invDet;
  73. Number d33 = + (v3 * m00 - v1 * m01 + v0 * m02) * invDet;
  74. return Matrix4(
  75. d00, d01, d02, d03,
  76. d10, d11, d12, d13,
  77. d20, d21, d22, d23,
  78. d30, d31, d32, d33);
  79. }
  80. Matrix4 Matrix4::inverseAffine(void) const
  81. {
  82. Number m10 = m[1][0], m11 = m[1][1], m12 = m[1][2];
  83. Number m20 = m[2][0], m21 = m[2][1], m22 = m[2][2];
  84. Number t00 = m22 * m11 - m21 * m12;
  85. Number t10 = m20 * m12 - m22 * m10;
  86. Number t20 = m21 * m10 - m20 * m11;
  87. Number m00 = m[0][0], m01 = m[0][1], m02 = m[0][2];
  88. Number invDet = 1 / (m00 * t00 + m01 * t10 + m02 * t20);
  89. t00 *= invDet; t10 *= invDet; t20 *= invDet;
  90. m00 *= invDet; m01 *= invDet; m02 *= invDet;
  91. Number r00 = t00;
  92. Number r01 = m02 * m21 - m01 * m22;
  93. Number r02 = m01 * m12 - m02 * m11;
  94. Number r10 = t10;
  95. Number r11 = m00 * m22 - m02 * m20;
  96. Number r12 = m02 * m10 - m00 * m12;
  97. Number r20 = t20;
  98. Number r21 = m01 * m20 - m00 * m21;
  99. Number r22 = m00 * m11 - m01 * m10;
  100. Number m03 = m[0][3], m13 = m[1][3], m23 = m[2][3];
  101. Number r03 = - (r00 * m03 + r01 * m13 + r02 * m23);
  102. Number r13 = - (r10 * m03 + r11 * m13 + r12 * m23);
  103. Number r23 = - (r20 * m03 + r21 * m13 + r22 * m23);
  104. return Matrix4(
  105. r00, r01, r02, r03,
  106. r10, r11, r12, r13,
  107. r20, r21, r22, r23,
  108. 0, 0, 0, 1);
  109. }
  110. Number Matrix4::determinant() const {
  111. const Number *cols[4] = {m[0],m[1],m[2],m[3]};
  112. return generalDeterminant(cols, 4);
  113. }
  114. // Determinant function by Edward Popko
  115. // Source: http://paulbourke.net/miscellaneous/determinant/
  116. //==============================================================================
  117. // Recursive definition of determinate using expansion by minors.
  118. //
  119. // Notes: 1) arguments:
  120. // a (double **) pointer to a pointer of an arbitrary square matrix
  121. // n (int) dimension of the square matrix
  122. //
  123. // 2) Determinant is a recursive function, calling itself repeatedly
  124. // each time with a sub-matrix of the original till a terminal
  125. // 2X2 matrix is achieved and a simple determinat can be computed.
  126. // As the recursion works backwards, cumulative determinants are
  127. // found till untimately, the final determinate is returned to the
  128. // initial function caller.
  129. //
  130. // 3) m is a matrix (4X4 in example) and m13 is a minor of it.
  131. // A minor of m is a 3X3 in which a row and column of values
  132. // had been excluded. Another minor of the submartix is also
  133. // possible etc.
  134. // m a b c d m13 . . . .
  135. // e f g h e f . h row 1 column 3 is elminated
  136. // i j k l i j . l creating a 3 X 3 sub martix
  137. // m n o p m n . p
  138. //
  139. // 4) the following function finds the determinant of a matrix
  140. // by recursively minor-ing a row and column, each time reducing
  141. // the sub-matrix by one row/column. When a 2X2 matrix is
  142. // obtained, the determinat is a simple calculation and the
  143. // process of unstacking previous recursive calls begins.
  144. //
  145. // m n
  146. // o p determinant = m*p - n*o
  147. //
  148. // 5) this function uses dynamic memory allocation on each call to
  149. // build a m X m matrix this requires ** and * pointer variables
  150. // First memory allocation is ** and gets space for a list of other
  151. // pointers filled in by the second call to malloc.
  152. //
  153. // 6) C++ implements two dimensional arrays as an array of arrays
  154. // thus two dynamic malloc's are needed and have corresponsing
  155. // free() calles.
  156. //
  157. // 7) the final determinant value is the sum of sub determinants
  158. //
  159. //==============================================================================
  160. Number Matrix4::generalDeterminant(Number const* const*a,int n)
  161. {
  162. int i,j,j1,j2; // general loop and matrix subscripts
  163. Number det = 0; // init determinant
  164. Number **m = NULL; // pointer to pointers to implement 2d
  165. // square array
  166. if (n < 1) { } // error condition, should never get here
  167. else if (n == 1) { // should not get here
  168. det = a[0][0];
  169. }
  170. else if (n == 2) { // basic 2X2 sub-matrix determinate
  171. // definition. When n==2, this ends the
  172. det = a[0][0] * a[1][1] - a[1][0] * a[0][1];// the recursion series
  173. }
  174. // recursion continues, solve next sub-matrix
  175. else { // solve the next minor by building a
  176. // sub matrix
  177. det = 0; // initialize determinant of sub-matrix
  178. // for each column in sub-matrix
  179. for (j1 = 0; j1 < n; j1++) {
  180. // get space for the pointer list
  181. m = new Number*[n-1];
  182. for (i = 0; i < n-1; i++)
  183. m[i] = new Number[n-1];
  184. // i[0][1][2][3] first malloc
  185. // m -> + + + + space for 4 pointers
  186. // | | | | j second malloc
  187. // | | | +-> _ _ _ [0] pointers to
  188. // | | +----> _ _ _ [1] and memory for
  189. // | +-------> _ a _ [2] 4 doubles
  190. // +----------> _ _ _ [3]
  191. //
  192. // a[1][2]
  193. // build sub-matrix with minor elements excluded
  194. for (i = 1; i < n; i++) {
  195. j2 = 0; // start at first sum-matrix column position
  196. // loop to copy source matrix less one column
  197. for (j = 0; j < n; j++) {
  198. if (j == j1) continue; // don't copy the minor column element
  199. m[i-1][j2] = a[i][j]; // copy source element into new sub-matrix
  200. // i-1 because new sub-matrix is one row
  201. // (and column) smaller with excluded minors
  202. j2++; // move to next sub-matrix column position
  203. }
  204. }
  205. det += pow(-1.0,1.0 + j1 + 1.0) * a[0][j1] * generalDeterminant(m,n-1);
  206. // sum x raised to y power
  207. // recursively get determinant of next
  208. // sub-matrix which is now one
  209. // row & column smaller
  210. for (i = 0 ; i < n-1 ; i++) delete[] m[i];// free the storage allocated to
  211. // to this minor's set of pointers
  212. delete[] m; // free the storage for the original
  213. // pointer to pointer
  214. }
  215. }
  216. return(det) ;
  217. }