LinearR4.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. *
  3. * Mathematics Subpackage (VrMath)
  4. *
  5. *
  6. * Author: Samuel R. Buss, [email protected].
  7. * Web page: http://math.ucsd.edu/~sbuss/MathCG
  8. *
  9. *
  10. This software is provided 'as-is', without any express or implied warranty.
  11. In no event will the authors be held liable for any damages arising from the use of this software.
  12. Permission is granted to anyone to use this software for any purpose,
  13. including commercial applications, and to alter it and redistribute it freely,
  14. subject to the following restrictions:
  15. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
  16. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  17. 3. This notice may not be removed or altered from any source distribution.
  18. *
  19. *
  20. */
  21. #include "LinearR4.h"
  22. #include <assert.h>
  23. const VectorR4 VectorR4::Zero(0.0, 0.0, 0.0, 0.0);
  24. const VectorR4 VectorR4::UnitX( 1.0, 0.0, 0.0, 0.0);
  25. const VectorR4 VectorR4::UnitY( 0.0, 1.0, 0.0, 0.0);
  26. const VectorR4 VectorR4::UnitZ( 0.0, 0.0, 1.0, 0.0);
  27. const VectorR4 VectorR4::UnitW( 0.0, 0.0, 0.0, 1.0);
  28. const VectorR4 VectorR4::NegUnitX(-1.0, 0.0, 0.0, 0.0);
  29. const VectorR4 VectorR4::NegUnitY( 0.0,-1.0, 0.0, 0.0);
  30. const VectorR4 VectorR4::NegUnitZ( 0.0, 0.0,-1.0, 0.0);
  31. const VectorR4 VectorR4::NegUnitW( 0.0, 0.0, 0.0,-1.0);
  32. const Matrix4x4 Matrix4x4::Identity(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
  33. 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0);
  34. // ******************************************************
  35. // * VectorR4 class - math library functions *
  36. // * * * * * * * * * * * * * * * * * * * * * * * * * * **
  37. double VectorR4::MaxAbs() const
  38. {
  39. register double m;
  40. m = (x>0.0) ? x : -x;
  41. if ( y>m ) m=y;
  42. else if ( -y >m ) m = -y;
  43. if ( z>m ) m=z;
  44. else if ( -z>m ) m = -z;
  45. if ( w>m ) m=w;
  46. else if ( -w>m ) m = -w;
  47. return m;
  48. }
  49. // ******************************************************
  50. // * Matrix4x4 class - math library functions *
  51. // * * * * * * * * * * * * * * * * * * * * * * * * * * **
  52. void Matrix4x4::operator*= (const Matrix4x4& B) // Matrix product
  53. {
  54. double t1, t2, t3; // temporary values
  55. t1 = m11*B.m11 + m12*B.m21 + m13*B.m31 + m14*B.m41;
  56. t2 = m11*B.m12 + m12*B.m22 + m13*B.m32 + m14*B.m42;
  57. t3 = m11*B.m13 + m12*B.m23 + m13*B.m33 + m14*B.m43;
  58. m14 = m11*B.m14 + m12*B.m24 + m13*B.m34 + m14*B.m44;
  59. m11 = t1;
  60. m12 = t2;
  61. m13 = t3;
  62. t1 = m21*B.m11 + m22*B.m21 + m23*B.m31 + m24*B.m41;
  63. t2 = m21*B.m12 + m22*B.m22 + m23*B.m32 + m24*B.m42;
  64. t3 = m21*B.m13 + m22*B.m23 + m23*B.m33 + m24*B.m43;
  65. m24 = m21*B.m14 + m22*B.m24 + m23*B.m34 + m24*B.m44;
  66. m21 = t1;
  67. m22 = t2;
  68. m23 = t3;
  69. t1 = m31*B.m11 + m32*B.m21 + m33*B.m31 + m34*B.m41;
  70. t2 = m31*B.m12 + m32*B.m22 + m33*B.m32 + m34*B.m42;
  71. t3 = m31*B.m13 + m32*B.m23 + m33*B.m33 + m34*B.m43;
  72. m34 = m31*B.m14 + m32*B.m24 + m33*B.m34 + m34*B.m44;
  73. m31 = t1;
  74. m32 = t2;
  75. m33 = t3;
  76. t1 = m41*B.m11 + m42*B.m21 + m43*B.m31 + m44*B.m41;
  77. t2 = m41*B.m12 + m42*B.m22 + m43*B.m32 + m44*B.m42;
  78. t3 = m41*B.m13 + m42*B.m23 + m43*B.m33 + m44*B.m43;
  79. m44 = m41*B.m14 + m42*B.m24 + m43*B.m34 + m44*B.m44;
  80. m41 = t1;
  81. m42 = t2;
  82. m43 = t3;
  83. }
  84. inline void ReNormalizeHelper ( double &a, double &b, double &c, double &d )
  85. {
  86. register double scaleF = a*a+b*b+c*c+d*d; // Inner product of Vector-R4
  87. scaleF = 1.0-0.5*(scaleF-1.0);
  88. a *= scaleF;
  89. b *= scaleF;
  90. c *= scaleF;
  91. d *= scaleF;
  92. }
  93. Matrix4x4& Matrix4x4::ReNormalize() {
  94. ReNormalizeHelper( m11, m21, m31, m41 ); // Renormalize first column
  95. ReNormalizeHelper( m12, m22, m32, m42 ); // Renormalize second column
  96. ReNormalizeHelper( m13, m23, m33, m43 ); // Renormalize third column
  97. ReNormalizeHelper( m14, m24, m34, m44 ); // Renormalize fourth column
  98. double alpha = 0.5*(m11*m12 + m21*m22 + m31*m32 + m41*m42); //1st and 2nd cols
  99. double beta = 0.5*(m11*m13 + m21*m23 + m31*m33 + m41*m43); //1st and 3rd cols
  100. double gamma = 0.5*(m11*m14 + m21*m24 + m31*m34 + m41*m44); //1st and 4nd cols
  101. double delta = 0.5*(m12*m13 + m22*m23 + m32*m33 + m42*m43); //2nd and 3rd cols
  102. double eps = 0.5*(m12*m14 + m22*m24 + m32*m34 + m42*m44); //2nd and 4nd cols
  103. double phi = 0.5*(m13*m14 + m23*m24 + m33*m34 + m43*m44); //3rd and 4nd cols
  104. double temp1, temp2, temp3;
  105. temp1 = m11 - alpha*m12 - beta*m13 - gamma*m14;
  106. temp2 = m12 - alpha*m11 - delta*m13 - eps*m14;
  107. temp3 = m13 - beta*m11 - delta*m12 - phi*m14;
  108. m14 -= (gamma*m11 + eps*m12 + phi*m13);
  109. m11 = temp1;
  110. m12 = temp2;
  111. m13 = temp3;
  112. temp1 = m21 - alpha*m22 - beta*m23 - gamma*m24;
  113. temp2 = m22 - alpha*m21 - delta*m23 - eps*m24;
  114. temp3 = m23 - beta*m21 - delta*m22 - phi*m24;
  115. m24 -= (gamma*m21 + eps*m22 + phi*m23);
  116. m21 = temp1;
  117. m22 = temp2;
  118. m23 = temp3;
  119. temp1 = m31 - alpha*m32 - beta*m33 - gamma*m34;
  120. temp2 = m32 - alpha*m31 - delta*m33 - eps*m34;
  121. temp3 = m33 - beta*m31 - delta*m32 - phi*m34;
  122. m34 -= (gamma*m31 + eps*m32 + phi*m33);
  123. m31 = temp1;
  124. m32 = temp2;
  125. m33 = temp3;
  126. temp1 = m41 - alpha*m42 - beta*m43 - gamma*m44;
  127. temp2 = m42 - alpha*m41 - delta*m43 - eps*m44;
  128. temp3 = m43 - beta*m41 - delta*m42 - phi*m44;
  129. m44 -= (gamma*m41 + eps*m42 + phi*m43);
  130. m41 = temp1;
  131. m42 = temp2;
  132. m43 = temp3;
  133. return *this;
  134. }
  135. // ******************************************************
  136. // * LinearMapR4 class - math library functions *
  137. // * * * * * * * * * * * * * * * * * * * * * * * * * * **
  138. double LinearMapR4::Determinant () const // Returns the determinant
  139. {
  140. double Tbt34C12 = m31*m42-m32*m41; // 2x2 subdeterminants
  141. double Tbt34C13 = m31*m43-m33*m41;
  142. double Tbt34C14 = m31*m44-m34*m41;
  143. double Tbt34C23 = m32*m43-m33*m42;
  144. double Tbt34C24 = m32*m44-m34*m42;
  145. double Tbt34C34 = m33*m44-m34*m43;
  146. double sd11 = m22*Tbt34C34 - m23*Tbt34C24 + m24*Tbt34C23; // 3x3 subdeterminants
  147. double sd12 = m21*Tbt34C34 - m23*Tbt34C14 + m24*Tbt34C13;
  148. double sd13 = m21*Tbt34C24 - m22*Tbt34C14 + m24*Tbt34C12;
  149. double sd14 = m21*Tbt34C23 - m22*Tbt34C13 + m23*Tbt34C12;
  150. return ( m11*sd11 - m12*sd12 + m13*sd13 - m14*sd14 );
  151. }
  152. LinearMapR4 LinearMapR4::Inverse() const // Returns inverse
  153. {
  154. double Tbt34C12 = m31*m42-m32*m41; // 2x2 subdeterminants
  155. double Tbt34C13 = m31*m43-m33*m41;
  156. double Tbt34C14 = m31*m44-m34*m41;
  157. double Tbt34C23 = m32*m43-m33*m42;
  158. double Tbt34C24 = m32*m44-m34*m42;
  159. double Tbt34C34 = m33*m44-m34*m43;
  160. double Tbt24C12 = m21*m42-m22*m41; // 2x2 subdeterminants
  161. double Tbt24C13 = m21*m43-m23*m41;
  162. double Tbt24C14 = m21*m44-m24*m41;
  163. double Tbt24C23 = m22*m43-m23*m42;
  164. double Tbt24C24 = m22*m44-m24*m42;
  165. double Tbt24C34 = m23*m44-m24*m43;
  166. double Tbt23C12 = m21*m32-m22*m31; // 2x2 subdeterminants
  167. double Tbt23C13 = m21*m33-m23*m31;
  168. double Tbt23C14 = m21*m34-m24*m31;
  169. double Tbt23C23 = m22*m33-m23*m32;
  170. double Tbt23C24 = m22*m34-m24*m32;
  171. double Tbt23C34 = m23*m34-m24*m33;
  172. double sd11 = m22*Tbt34C34 - m23*Tbt34C24 + m24*Tbt34C23; // 3x3 subdeterminants
  173. double sd12 = m21*Tbt34C34 - m23*Tbt34C14 + m24*Tbt34C13;
  174. double sd13 = m21*Tbt34C24 - m22*Tbt34C14 + m24*Tbt34C12;
  175. double sd14 = m21*Tbt34C23 - m22*Tbt34C13 + m23*Tbt34C12;
  176. double sd21 = m12*Tbt34C34 - m13*Tbt34C24 + m14*Tbt34C23; // 3x3 subdeterminants
  177. double sd22 = m11*Tbt34C34 - m13*Tbt34C14 + m14*Tbt34C13;
  178. double sd23 = m11*Tbt34C24 - m12*Tbt34C14 + m14*Tbt34C12;
  179. double sd24 = m11*Tbt34C23 - m12*Tbt34C13 + m13*Tbt34C12;
  180. double sd31 = m12*Tbt24C34 - m13*Tbt24C24 + m14*Tbt24C23; // 3x3 subdeterminants
  181. double sd32 = m11*Tbt24C34 - m13*Tbt24C14 + m14*Tbt24C13;
  182. double sd33 = m11*Tbt24C24 - m12*Tbt24C14 + m14*Tbt24C12;
  183. double sd34 = m11*Tbt24C23 - m12*Tbt24C13 + m13*Tbt24C12;
  184. double sd41 = m12*Tbt23C34 - m13*Tbt23C24 + m14*Tbt23C23; // 3x3 subdeterminants
  185. double sd42 = m11*Tbt23C34 - m13*Tbt23C14 + m14*Tbt23C13;
  186. double sd43 = m11*Tbt23C24 - m12*Tbt23C14 + m14*Tbt23C12;
  187. double sd44 = m11*Tbt23C23 - m12*Tbt23C13 + m13*Tbt23C12;
  188. register double detInv = 1.0/(m11*sd11 - m12*sd12 + m13*sd13 - m14*sd14);
  189. return( LinearMapR4( sd11*detInv, -sd12*detInv, sd13*detInv, -sd14*detInv,
  190. -sd21*detInv, sd22*detInv, -sd23*detInv, sd24*detInv,
  191. sd31*detInv, -sd32*detInv, sd33*detInv, -sd34*detInv,
  192. -sd41*detInv, sd42*detInv, -sd43*detInv, sd44*detInv ) );
  193. }
  194. LinearMapR4& LinearMapR4::Invert() // Converts into inverse.
  195. {
  196. double Tbt34C12 = m31*m42-m32*m41; // 2x2 subdeterminants
  197. double Tbt34C13 = m31*m43-m33*m41;
  198. double Tbt34C14 = m31*m44-m34*m41;
  199. double Tbt34C23 = m32*m43-m33*m42;
  200. double Tbt34C24 = m32*m44-m34*m42;
  201. double Tbt34C34 = m33*m44-m34*m43;
  202. double Tbt24C12 = m21*m42-m22*m41; // 2x2 subdeterminants
  203. double Tbt24C13 = m21*m43-m23*m41;
  204. double Tbt24C14 = m21*m44-m24*m41;
  205. double Tbt24C23 = m22*m43-m23*m42;
  206. double Tbt24C24 = m22*m44-m24*m42;
  207. double Tbt24C34 = m23*m44-m24*m43;
  208. double Tbt23C12 = m21*m32-m22*m31; // 2x2 subdeterminants
  209. double Tbt23C13 = m21*m33-m23*m31;
  210. double Tbt23C14 = m21*m34-m24*m31;
  211. double Tbt23C23 = m22*m33-m23*m32;
  212. double Tbt23C24 = m22*m34-m24*m32;
  213. double Tbt23C34 = m23*m34-m24*m33;
  214. double sd11 = m22*Tbt34C34 - m23*Tbt34C24 + m24*Tbt34C23; // 3x3 subdeterminants
  215. double sd12 = m21*Tbt34C34 - m23*Tbt34C14 + m24*Tbt34C13;
  216. double sd13 = m21*Tbt34C24 - m22*Tbt34C14 + m24*Tbt34C12;
  217. double sd14 = m21*Tbt34C23 - m22*Tbt34C13 + m23*Tbt34C12;
  218. double sd21 = m12*Tbt34C34 - m13*Tbt34C24 + m14*Tbt34C23; // 3x3 subdeterminants
  219. double sd22 = m11*Tbt34C34 - m13*Tbt34C14 + m14*Tbt34C13;
  220. double sd23 = m11*Tbt34C24 - m12*Tbt34C14 + m14*Tbt34C12;
  221. double sd24 = m11*Tbt34C23 - m12*Tbt34C13 + m13*Tbt34C12;
  222. double sd31 = m12*Tbt24C34 - m13*Tbt24C24 + m14*Tbt24C23; // 3x3 subdeterminants
  223. double sd32 = m11*Tbt24C34 - m13*Tbt24C14 + m14*Tbt24C13;
  224. double sd33 = m11*Tbt24C24 - m12*Tbt24C14 + m14*Tbt24C12;
  225. double sd34 = m11*Tbt24C23 - m12*Tbt24C13 + m13*Tbt24C12;
  226. double sd41 = m12*Tbt23C34 - m13*Tbt23C24 + m14*Tbt23C23; // 3x3 subdeterminants
  227. double sd42 = m11*Tbt23C34 - m13*Tbt23C14 + m14*Tbt23C13;
  228. double sd43 = m11*Tbt23C24 - m12*Tbt23C14 + m14*Tbt23C12;
  229. double sd44 = m11*Tbt23C23 - m12*Tbt23C13 + m13*Tbt23C12;
  230. register double detInv = 1.0/(m11*sd11 - m12*sd12 + m13*sd13 - m14*sd14);
  231. m11 = sd11*detInv;
  232. m12 = -sd21*detInv;
  233. m13 = sd31*detInv;
  234. m14 = -sd41*detInv;
  235. m21 = -sd12*detInv;
  236. m22 = sd22*detInv;
  237. m23 = -sd32*detInv;
  238. m24 = sd42*detInv;
  239. m31 = sd13*detInv;
  240. m32 = -sd23*detInv;
  241. m33 = sd33*detInv;
  242. m34 = -sd43*detInv;
  243. m41 = -sd14*detInv;
  244. m42 = sd24*detInv;
  245. m43 = -sd34*detInv;
  246. m44 = sd44*detInv;
  247. return ( *this );
  248. }
  249. VectorR4 LinearMapR4::Solve(const VectorR4& u) const // Returns solution
  250. {
  251. // Just uses Inverse() for now.
  252. return ( Inverse()*u );
  253. }
  254. // ******************************************************
  255. // * RotationMapR4 class - math library functions *
  256. // * * * * * * * * * * * * * * * * * * * * * * * * * * **
  257. // ***************************************************************
  258. // * 4-space vector and matrix utilities *
  259. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  260. // Returns u * v^T
  261. LinearMapR4 TimesTranspose( const VectorR4& u, const VectorR4& v)
  262. {
  263. LinearMapR4 result;
  264. TimesTranspose( u, v, result );
  265. return result;
  266. }
  267. // The following routines are use to obtain
  268. // a righthanded orthonormal basis to complement vectors u,v,w.
  269. // The vectors u,v,w must be unit and orthonormal.
  270. // The value is returned in "rotmat" with the first column(s) of
  271. // rotmat equal to u,v,w as appropriate.
  272. void GetOrtho( const VectorR4& u, RotationMapR4& rotmat )
  273. {
  274. rotmat.SetColumn1(u);
  275. GetOrtho( 1, rotmat );
  276. }
  277. void GetOrtho( const VectorR4& u, const VectorR4& v, RotationMapR4& rotmat )
  278. {
  279. rotmat.SetColumn1(u);
  280. rotmat.SetColumn2(v);
  281. GetOrtho( 2, rotmat );
  282. }
  283. void GetOrtho( const VectorR4& u, const VectorR4& v, const VectorR4& s,
  284. RotationMapR4& rotmat )
  285. {
  286. rotmat.SetColumn1(u);
  287. rotmat.SetColumn2(v);
  288. rotmat.SetColumn3(s);
  289. GetOrtho( 3, rotmat );
  290. }
  291. // This final version of GetOrtho is mainly for internal use.
  292. // It uses a Gram-Schmidt procedure to extend a partial orthonormal
  293. // basis to a complete orthonormal basis.
  294. // j = number of columns of rotmat that have already been set.
  295. void GetOrtho( int j, RotationMapR4& rotmat)
  296. {
  297. if ( j==0 ) {
  298. rotmat.SetIdentity();
  299. return;
  300. }
  301. if ( j==1 ) {
  302. rotmat.SetColumn2( -rotmat.m21, rotmat.m11, -rotmat.m41, rotmat.m31 );
  303. j = 2;
  304. }
  305. assert ( rotmat.Column1().Norm()<1.0001 && 0.9999<rotmat.Column1().Norm()
  306. && rotmat.Column1().Norm()<1.0001 && 0.9999<rotmat.Column1().Norm()
  307. && (rotmat.Column1()^rotmat.Column2()) < 0.001
  308. && (rotmat.Column1()^rotmat.Column2()) > -0.001 );
  309. // 2x2 subdeterminants in first 2 columns
  310. double d12 = rotmat.m11*rotmat.m22-rotmat.m12*rotmat.m21;
  311. double d13 = rotmat.m11*rotmat.m32-rotmat.m12*rotmat.m31;
  312. double d14 = rotmat.m11*rotmat.m42-rotmat.m12*rotmat.m41;
  313. double d23 = rotmat.m21*rotmat.m32-rotmat.m22*rotmat.m31;
  314. double d24 = rotmat.m21*rotmat.m42-rotmat.m22*rotmat.m41;
  315. double d34 = rotmat.m31*rotmat.m42-rotmat.m32*rotmat.m41;
  316. VectorR4 vec3;
  317. if ( j==2 ) {
  318. if ( d12>0.4 || d12<-0.4 || d13>0.4 || d13<-0.4
  319. || d23>0.4 || d23<-0.4 ) {
  320. vec3.Set( d23, -d13, d12, 0.0);
  321. }
  322. else if ( d24>0.4 || d24<-0.4 || d14>0.4 || d14<-0.4 ) {
  323. vec3.Set( d24, -d14, 0.0, d12 );
  324. }
  325. else {
  326. vec3.Set( d34, 0.0, -d14, d13 );
  327. }
  328. vec3.Normalize();
  329. rotmat.SetColumn3(vec3);
  330. }
  331. // Do the final column
  332. rotmat.SetColumn4 (
  333. -rotmat.m23*d34 + rotmat.m33*d24 - rotmat.m43*d23,
  334. rotmat.m13*d34 - rotmat.m33*d14 + rotmat.m43*d13,
  335. -rotmat.m13*d24 + rotmat.m23*d14 - rotmat.m43*d12,
  336. rotmat.m13*d23 - rotmat.m23*d13 + rotmat.m33*d12 );
  337. assert ( 0.99 < (((LinearMapR4)rotmat)).Determinant()
  338. && (((LinearMapR4)rotmat)).Determinant() < 1.01 );
  339. }
  340. // *********************************************************************
  341. // Rotation routines *
  342. // *********************************************************************
  343. // Rotate unit vector x in the direction of "dir": length of dir is rotation angle.
  344. // x must be a unit vector. dir must be perpindicular to x.
  345. VectorR4& VectorR4::RotateUnitInDirection ( const VectorR4& dir)
  346. {
  347. assert ( this->Norm()<1.0001 && this->Norm()>0.9999 &&
  348. (dir^(*this))<0.0001 && (dir^(*this))>-0.0001 );
  349. double theta = dir.NormSq();
  350. if ( theta==0.0 ) {
  351. return *this;
  352. }
  353. else {
  354. theta = sqrt(theta);
  355. double costheta = cos(theta);
  356. double sintheta = sin(theta);
  357. VectorR4 dirUnit = dir/theta;
  358. *this = costheta*(*this) + sintheta*dirUnit;
  359. // this->NormalizeFast();
  360. return ( *this );
  361. }
  362. }
  363. // RotateToMap returns a RotationMapR4 that rotates fromVec to toVec,
  364. // leaving the orthogonal subspace fixed.
  365. // fromVec and toVec should be unit vectors
  366. RotationMapR4 RotateToMap( const VectorR4& fromVec, const VectorR4& toVec)
  367. {
  368. LinearMapR4 result;
  369. result.SetIdentity();
  370. LinearMapR4 temp;
  371. VectorR4 vPerp = ProjectPerpUnitDiff( toVec, fromVec );
  372. double sintheta = vPerp.Norm(); // theta = angle between toVec and fromVec
  373. VectorR4 vProj = toVec-vPerp;
  374. double costheta = vProj^fromVec;
  375. if ( sintheta == 0.0 ) {
  376. // The vectors either coincide (return identity) or directly oppose
  377. if ( costheta < 0.0 ) {
  378. result = -result; // Vectors directly oppose: return -identity.
  379. }
  380. }
  381. else {
  382. vPerp /= sintheta; // Normalize
  383. VectorProjectMap ( fromVec, temp ); // project in fromVec direction
  384. temp *= (costheta-1.0);
  385. result += temp;
  386. VectorProjectMap ( vPerp, temp ); // Project in vPerp direction
  387. temp *= (costheta-1.0);
  388. result += temp;
  389. TimesTranspose ( vPerp, fromVec, temp ); // temp = (vPerp)*(fromVec^T)
  390. temp *= sintheta;
  391. result += temp;
  392. temp.MakeTranspose();
  393. result -= temp; // (-sintheta)*(fromVec)*(vPerp^T)
  394. }
  395. RotationMapR4 rotationResult;
  396. rotationResult.Set(result); // Make explicitly a RotationMapR4
  397. return rotationResult;
  398. }
  399. // ***************************************************************
  400. // Stream Output Routines *
  401. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  402. ostream& operator<< ( ostream& os, const VectorR4& u )
  403. {
  404. return (os << "<" << u.x << "," << u.y << "," << u.z << "," << u.w << ">");
  405. }