Spherical.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. //
  22. // Spherical Operations Classes
  23. //
  24. //
  25. // B. SphericalInterpolator
  26. //
  27. // OrientationR3
  28. //
  29. // A. Quaternion
  30. //
  31. // B. RotationMapR3 // Elsewhere
  32. //
  33. // C. EulerAnglesR3 // TO DO
  34. //
  35. //
  36. // Functions for spherical operations
  37. // A. Many routines for rotation and averaging on a sphere
  38. //
  39. #ifndef SPHERICAL_H
  40. #define SPHERICAL_H
  41. #include "LinearR3.h"
  42. #include "LinearR4.h"
  43. #include "MathMisc.h"
  44. class SphericalInterpolator; // Spherical linear interpolation of vectors
  45. class SphericalBSpInterpolator; // Spherical Bspline interpolation of vector
  46. class Quaternion; // Quaternion (x,y,z,w) values.
  47. class EulerAnglesR3; // Euler Angles
  48. // *****************************************************
  49. // SphericalInterpolator class *
  50. // - Does linear interpolation (slerp-ing) *
  51. // * * * * * * * * * * * * * * * * * * * * * * * * * * *
  52. class SphericalInterpolator {
  53. private:
  54. VectorR3 startDir, endDir; // Unit vectors (starting and ending)
  55. double startLen, endLen; // Magnitudes of the vectors
  56. double rotRate; // Angle between start and end vectors
  57. public:
  58. SphericalInterpolator( const VectorR3& u, const VectorR3& v );
  59. VectorR3 InterValue ( double frac ) const;
  60. };
  61. // ***************************************************************
  62. // * Quaternion class - prototypes *
  63. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  64. class Quaternion {
  65. public:
  66. double x, y, z, w;
  67. public:
  68. Quaternion() :x(0.0), y(0.0), z(0.0), w(1.0) {};
  69. Quaternion( double, double, double, double );
  70. inline Quaternion& Set( double xx, double yy, double zz, double ww );
  71. inline Quaternion& Set( const VectorR4& );
  72. Quaternion& Set( const EulerAnglesR3& );
  73. Quaternion& Set( const RotationMapR3& );
  74. Quaternion& SetRotate( const VectorR3& );
  75. Quaternion& SetIdentity(); // Set to the identity map
  76. Quaternion Inverse() const; // Return the Inverse
  77. Quaternion& Invert(); // Invert this quaternion
  78. double Angle(); // Angle of rotation
  79. double Norm(); // Norm of x,y,z component
  80. Quaternion& operator*=(const Quaternion&);
  81. };
  82. Quaternion operator*(const Quaternion&, const Quaternion&);
  83. inline Quaternion ToQuat( const VectorR4& v)
  84. {
  85. return Quaternion(v.x,v.y,v.z,v.w);
  86. }
  87. inline double Quaternion::Norm()
  88. {
  89. return sqrt( x*x + y*y + z*z );
  90. }
  91. inline double Quaternion::Angle ()
  92. {
  93. double halfAngle = asin(Norm());
  94. return halfAngle+halfAngle;
  95. }
  96. // ****************************************************************
  97. // Solid Geometry Routines *
  98. // ****************************************************************
  99. // Compute the angle formed by two geodesics on the unit sphere.
  100. // Three unit vectors u,v,w specify the geodesics u-v and v-w which
  101. // meet at vertex uv. The angle from v-w to v-u is returned. This
  102. // is always in the range [0, 2PI).
  103. double SphereAngle( const VectorR3& u, const VectorR3& v, const VectorR3& w );
  104. // Compute the area of a triangle on the unit sphere. Three unit vectors
  105. // specify the corners of the triangle in COUNTERCLOCKWISE order.
  106. inline double SphericalTriangleArea(
  107. const VectorR3& u, const VectorR3& v, const VectorR3& w )
  108. {
  109. double AngleA = SphereAngle( u,v,w );
  110. double AngleB = SphereAngle( v,w,u );
  111. double AngleC = SphereAngle( w,u,v );
  112. return ( AngleA+AngleB+AngleC - PI );
  113. }
  114. // ****************************************************************
  115. // Spherical Mean routines *
  116. // ****************************************************************
  117. // Weighted sum of vectors
  118. VectorR3 WeightedSum( long Num, const VectorR3 vv[], const double weights[] );
  119. VectorR4 WeightedSum( long Num, const VectorR4 vv[], const double weights[] );
  120. // Weighted average of vectors on the sphere.
  121. // Sum of weights should equal one (but no checking is done)
  122. VectorR3 ComputeMeanSphere( long Num, const VectorR3 vv[], const double weights[],
  123. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  124. VectorR3 ComputeMeanSphere( long Num, const VectorR3 vv[], const double weights[],
  125. const VectorR3& InitialVec,
  126. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  127. VectorR4 ComputeMeanSphere( long Num, const VectorR4 vv[], const double weights[],
  128. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  129. Quaternion ComputeMeanQuat( long Num, const Quaternion qq[], const double weights[],
  130. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  131. // Next functions mostly for internal use.
  132. // It takes an initial estimate InitialVec (and a flag for
  133. // indicating quaternions).
  134. VectorR4 ComputeMeanSphere( long Num, const VectorR4 vv[], const double weights[],
  135. const VectorR4& InitialVec, int QuatFlag=0,
  136. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  137. const int SPHERICAL_NOTQUAT=0;
  138. const int SPHERICAL_QUAT=1;
  139. // Slow version, mostly for testing
  140. VectorR3 ComputeMeanSphereSlow( long Num, const VectorR3 vv[], const double weights[],
  141. double tolerance = 1.0e-16, double bkuptolerance = 5.0e-16 );
  142. VectorR4 ComputeMeanSphereSlow( long Num, const VectorR4 vv[], const double weights[],
  143. double tolerance = 1.0e-16, double bkuptolerance = 5.0e-16 );
  144. VectorR3 ComputeMeanSphereOld( long Num, const VectorR3 vv[], const double weights[],
  145. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  146. VectorR4 ComputeMeanSphereOld( long Num, const VectorR4 vv[], const double weights[],
  147. const VectorR4& InitialVec, int QuatFlag,
  148. double tolerance = 1.0e-15, double bkuptolerance = 1.0e-13 );
  149. // Solves a system of spherical-mean equalities, where the system is
  150. // given as a tridiagonal matrix.
  151. void SolveTriDiagSphere ( int numPoints,
  152. const double* tridiagvalues, const VectorR3* c,
  153. VectorR3* p,
  154. double accuracy=1.0e-15, double bkupaccuracy=1.0e-13 );
  155. void SolveTriDiagSphere ( int numPoints,
  156. const double* tridiagvalues, const VectorR4* c,
  157. VectorR4* p,
  158. double accuracy=1.0e-15, double bkupaccuracy=1.0e-13 );
  159. // The "Slow" version uses a simpler but slower iteration with a linear rate of
  160. // convergence. The base version uses a Newton iteration with a quadratic
  161. // rate of convergence.
  162. void SolveTriDiagSphereSlow ( int numPoints,
  163. const double* tridiagvalues, const VectorR3* c,
  164. VectorR3* p,
  165. double accuracy=1.0e-15, double bkupaccuracy=5.0e-15 );
  166. void SolveTriDiagSphereSlow ( int numPoints,
  167. const double* tridiagvalues, const VectorR4* c,
  168. VectorR4* p,
  169. double accuracy=1.0e-15, double bkupaccuracy=5.0e-15 );
  170. // The "Unstable" version probably shouldn't be used except for very short sequences
  171. // of knots. Mostly it's used for testing purposes now.
  172. void SolveTriDiagSphereUnstable ( int numPoints,
  173. const double* tridiagvalues, const VectorR3* c,
  174. VectorR3* p,
  175. double accuracy=1.0e-15, double bkupaccuracy=1.0e-13 );
  176. void SolveTriDiagSphereHelperUnstable ( int numPoints,
  177. const double* tridiagvalues, const VectorR3 *c,
  178. const VectorR3& p0value,
  179. VectorR3 *p,
  180. double accuracy=1.0e-15, double bkupaccuracy=1.0e-13 );
  181. // ***************************************************************
  182. // * Quaternion class - inlined member functions *
  183. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  184. inline VectorR4::VectorR4 ( const Quaternion& q )
  185. : x(q.x), y(q.y), z(q.z), w(q.w)
  186. {}
  187. inline VectorR4& VectorR4::Set ( const Quaternion& q )
  188. {
  189. x = q.x; y = q.y; z = q.z; w = q.w;
  190. return *this;
  191. }
  192. inline Quaternion::Quaternion( double xx, double yy, double zz, double ww)
  193. : x(xx), y(yy), z(zz), w(ww)
  194. {}
  195. inline Quaternion& Quaternion::Set( double xx, double yy, double zz, double ww )
  196. {
  197. x = xx;
  198. y = yy;
  199. z = zz;
  200. w = ww;
  201. return *this;
  202. }
  203. inline Quaternion& Quaternion::Set( const VectorR4& u)
  204. {
  205. x = u.x;
  206. y = u.y;
  207. z = u.z;
  208. w = u.w;
  209. return *this;
  210. }
  211. inline Quaternion& Quaternion::SetIdentity()
  212. {
  213. x = y = z = 0.0;
  214. w = 1.0;
  215. return *this;
  216. }
  217. inline Quaternion operator*(const Quaternion& q1, const Quaternion& q2)
  218. {
  219. Quaternion q(q1);
  220. q *= q2;
  221. return q;
  222. }
  223. inline Quaternion& Quaternion::operator*=( const Quaternion& q )
  224. {
  225. double wnew = w*q.w - (x*q.x + y*q.y + z*q.z);
  226. double xnew = w*q.x + q.w*x + (y*q.z - z*q.y);
  227. double ynew = w*q.y + q.w*y + (z*q.x - x*q.z);
  228. z = w*q.z + q.w*z + (x*q.y - y*q.x);
  229. w = wnew;
  230. x = xnew;
  231. y = ynew;
  232. return *this;
  233. }
  234. inline Quaternion Quaternion::Inverse() const // Return the Inverse
  235. {
  236. return ( Quaternion( x, y, z, -w ) );
  237. }
  238. inline Quaternion& Quaternion::Invert() // Invert this quaternion
  239. {
  240. w = -w;
  241. return *this;
  242. }
  243. #endif // SPHERICAL_H