|
World of Rigid Bodies (WoRB)
|
00001 #ifndef _QUATERNION_H_INCLUDED 00002 #define _QUATERNION_H_INCLUDED 00003 00004 /** 00005 * @file Quaternion.h 00006 * @brief Definitions for the Quaternion class that encapsulates Hamilton real 00007 * quaternions. 00008 * @author Mikica Kocic 00009 * @version 0.5 00010 * @date 2012-05-11 00011 * @copyright GNU Public License. 00012 */ 00013 00014 #include <cmath> // we use: sqrt (), fabs () 00015 00016 namespace WoRB 00017 { 00018 ///////////////////////////////////////////////////////////////////////////////////// 00019 /** @class Quaternion 00020 * 00021 * Encapsulates Hamilton real quaternions. 00022 * 00023 * @note The Quaternion class is implemented with inline methods only. 00024 */ 00025 class Quaternion 00026 { 00027 public: 00028 ///////////////////////////////////////////////////////////////////////////////// 00029 /** @name Quaternion components 00030 * 00031 * - *w*: holds the real (aka scalar) part of the quaternion. 00032 * - *x*, *y*, *z*: holds the pure imaginary (vector) part of the quaternion. 00033 * 00034 * See <a href="http://en.wikipedia.org/wiki/Quaternion"> 00035 * Quaternions on Wikipedia </a> 00036 */ 00037 ///////////////////////////////////////////////////////////////////////////////// 00038 /*@{*/ 00039 double w; //!< Holds the real (scalar) part of the quaternion. 00040 double x; //!< Holds _i_-component of the pure imaginary (vector) part. 00041 double y; //!< Holds _j_-component of the pure imaginary (vector) part. 00042 double z; //!< Holds _k_-component of the pure imaginary (vector) part. 00043 /*@}*/ 00044 ///////////////////////////////////////////////////////////////////////////////// 00045 /** @name Constructors and assignment operators */ 00046 ///////////////////////////////////////////////////////////////////////////////// 00047 /*@{*/ 00048 /** The default constructor; creates a zero quaternion 00049 */ 00050 Quaternion () 00051 : w(0), x(0), y(0), z(0) 00052 { 00053 } 00054 00055 /** Creates a quaternion having only the scalar (real) part. 00056 */ 00057 Quaternion( double scalar ) 00058 : w(scalar), x(0), y(0), z(0) 00059 { 00060 } 00061 00062 /** Creates a quaternion with the given components. 00063 */ 00064 Quaternion( double w, double x, double y, double z ) 00065 : w(w), x(x), y(y), z(z) 00066 { 00067 } 00068 00069 /** Sets the scalar (real) part of the quaternion also clearing the vector part. 00070 */ 00071 Quaternion& operator = ( double scalar ) 00072 { 00073 w = scalar; 00074 x = y = z = 0; 00075 return *this; 00076 } 00077 00078 /** Constructs a quaternion from axis angle representation of rotation. 00079 */ 00080 static Quaternion FromAxisAngle( double angle, 00081 double vx, double vy, double vz ) 00082 { 00083 double norm = sqrt( vx * vx + vy * vy + vz * vz ); 00084 00085 if ( norm == 0 ) { 00086 return Quaternion( 1 ); 00087 } 00088 00089 double Re = cos( angle/2 ); 00090 double Im = sin( angle/2 ) / norm; 00091 00092 return Quaternion( Re, Im * vx, Im * vy, Im * vz ); 00093 } 00094 /*@}*/ 00095 ///////////////////////////////////////////////////////////////////////////////// 00096 /** @name Indexing operators */ 00097 ///////////////////////////////////////////////////////////////////////////////// 00098 /*@{*/ 00099 double operator [] ( unsigned index ) const 00100 { 00101 if ( index <= 2 ) { 00102 return *(&x + index); 00103 } 00104 return w; 00105 } 00106 00107 double& operator [] ( unsigned index ) 00108 { 00109 if ( index <= 2 ) { 00110 return *(&x + index); 00111 } 00112 return w; 00113 } 00114 /*@}*/ 00115 ///////////////////////////////////////////////////////////////////////////////// 00116 /** @name Methods acting on quaterinion components */ 00117 ///////////////////////////////////////////////////////////////////////////////// 00118 /*@{*/ 00119 /** Normalizes the quaternion to a given length. 00120 */ 00121 Quaternion& Normalize( double length = 1.0 ) 00122 { 00123 double norm = Norm (); 00124 00125 // Handle zero length quaternion. 00126 // Note that norm == 0 if and only if w == x == y == z == 0 00127 // 00128 if ( norm == 0 ) { 00129 w = length; 00130 return *this; 00131 } 00132 00133 return *this *= length / norm; 00134 } 00135 00136 /** Limits the size of the quaternion to the given maximum. 00137 */ 00138 Quaternion& Trim( double size ) 00139 { 00140 if ( ImSquaredNorm () > size * size ) 00141 { 00142 return Normalize( size ); 00143 } 00144 00145 return *this; 00146 } 00147 00148 /** Removes the quaternion components that are bellow the limit. 00149 */ 00150 Quaternion& Zeroize( double eps = 1e-4 ) 00151 { 00152 if ( fabs( x ) < eps ) x = 0; 00153 if ( fabs( y ) < eps ) y = 0; 00154 if ( fabs( z ) < eps ) z = 0; 00155 if ( fabs( w ) < eps ) w = 0; 00156 00157 return *this; 00158 } 00159 /*@}*/ 00160 ///////////////////////////////////////////////////////////////////////////////// 00161 /** @name Unary operations */ 00162 ///////////////////////////////////////////////////////////////////////////////// 00163 /*@{*/ 00164 /** Flips signs of all the components of the quaternion. 00165 */ 00166 Quaternion operator - () const 00167 { 00168 return Quaternion( -w, -x, -y, -z ); 00169 } 00170 00171 /** Returns the conjugate of the quaternion. 00172 */ 00173 Quaternion Conjugate () const 00174 { 00175 return Quaternion( w, -x, -y, -z ); 00176 } 00177 00178 /** Gets the squared magnitude of this quaternion. 00179 */ 00180 double SquaredNorm () const 00181 { 00182 return w * w + x * x + y * y + z * z; 00183 } 00184 00185 /** Gets the squared magnitude of the scalar part of this quaternion. 00186 */ 00187 double ReSquaredNorm () const 00188 { 00189 return w * w; 00190 } 00191 00192 /** Gets the squared magnitude of the vector part of this quaternion. 00193 */ 00194 double ImSquaredNorm () const 00195 { 00196 return x * x + y * y + z * z; 00197 } 00198 00199 /** Gets the magnitude of this quaternion. 00200 */ 00201 double Norm () const 00202 { 00203 return sqrt( SquaredNorm () ); 00204 } 00205 00206 /** Gets the magnitude of the vector part of this quaternion. 00207 */ 00208 double ImNorm () const 00209 { 00210 return sqrt( ImSquaredNorm () ); 00211 } 00212 00213 /** Returns the normalized version (versor) of a quaternion. 00214 */ 00215 Quaternion Unit( double length = 1.0 ) const 00216 { 00217 return Quaternion( *this ).Normalize( length ); 00218 } 00219 /*@}*/ 00220 ///////////////////////////////////////////////////////////////////////////////// 00221 /** @name Binary operations */ 00222 ///////////////////////////////////////////////////////////////////////////////// 00223 /*@{*/ 00224 /** Returns the value of the given quaternion added to this. 00225 */ 00226 Quaternion operator + ( const Quaternion& q ) const 00227 { 00228 return Quaternion( w + q.w, x + q.x, y + q.y, z + q.z ); 00229 } 00230 00231 /** Adds the given quaternion to this. 00232 */ 00233 Quaternion& operator += ( const Quaternion& q ) 00234 { 00235 w += q.w; x += q.x; y += q.y; z += q.z; 00236 return *this; 00237 } 00238 00239 /** Returns the value of the given quaternion subtracted from this. 00240 */ 00241 Quaternion operator - (const Quaternion& q) const 00242 { 00243 return Quaternion( w - q.w, x - q.x, y - q.y, z - q.z ); 00244 } 00245 00246 /** Subtracts the given quaternion from this. 00247 */ 00248 Quaternion operator -= ( const Quaternion& q ) 00249 { 00250 w -= q.w; x -= q.x; y -= q.y; z -= q.z; 00251 return *this; 00252 } 00253 00254 /** Multiplies the quaternion by the given quaternion. 00255 */ 00256 Quaternion operator * ( const Quaternion& q ) const 00257 { 00258 return Quaternion( 00259 w * q.w - x * q.x - y * q.y - z * q.z, 00260 w * q.x + x * q.w + y * q.z - z * q.y, 00261 w * q.y + y * q.w + z * q.x - x * q.z, 00262 w * q.z + z * q.w + x * q.y - y * q.x 00263 ); 00264 } 00265 00266 /** Multiplies the quaternion by the given quaternion. 00267 */ 00268 Quaternion& operator *= ( const Quaternion& right ) 00269 { 00270 return *this = *this * right; 00271 } 00272 00273 /** Returns a copy of this quaternion scaled the given scalar value. 00274 */ 00275 Quaternion operator * ( double value ) const 00276 { 00277 return Quaternion( w * value, x * value, y * value, z * value); 00278 } 00279 00280 /** Multiplies this quaternion by the given scalar value. 00281 */ 00282 Quaternion& operator *= ( double value ) 00283 { 00284 w *= value; x *= value; y *= value; z *= value; 00285 return *this; 00286 } 00287 00288 /** Returns a component-wise product of this and another quaternion. 00289 */ 00290 Quaternion ComponentWiseProduct( const Quaternion& q ) const 00291 { 00292 return Quaternion( w * q.w, x * q.x, y * q.y, z * q.z); 00293 } 00294 00295 /** Returns a vector product of the vector parts of this and another quaternion. 00296 */ 00297 Quaternion Cross( const Quaternion& q ) const 00298 { 00299 return Quaternion( 0, 00300 y * q.z - z * q.y, 00301 z * q.x - x * q.z, 00302 x * q.y - y * q.x ); 00303 } 00304 00305 /** Returns a scalar product of the vector parts of this and another quaternion. 00306 */ 00307 double Dot( const Quaternion &q ) const 00308 { 00309 return /* w * q.w + */ x * q.x + y * q.y + z * q.z; 00310 } 00311 /*@}*/ 00312 ///////////////////////////////////////////////////////////////////////////////// 00313 /** @name Comparison operators */ 00314 ///////////////////////////////////////////////////////////////////////////////// 00315 /*@{*/ 00316 /** Checks if the two quaternions have identical components. 00317 */ 00318 bool operator == ( const Quaternion& q ) const 00319 { 00320 return w == q.w && x == q.x && y == q.y && z == q.z; 00321 } 00322 00323 /** Checks if the two vectors have non-identical components. 00324 */ 00325 bool operator != ( const Quaternion& q ) const 00326 { 00327 return !( *this == q ); 00328 } 00329 00330 /** Checks if this quaternion is component-by-component less than the other. 00331 */ 00332 bool operator < ( const Quaternion& q ) const 00333 { 00334 return w < q.w && x < q.x && y < q.y && z < q.z; 00335 } 00336 00337 /** Checks if this quaternion is component-by-component less than the other. 00338 */ 00339 bool operator > (const Quaternion& q) const 00340 { 00341 return w > q.w && x > q.x && y > q.y && z > q.z; 00342 } 00343 00344 /** Checks if this quaternion is component-by-component less than the other. 00345 */ 00346 bool operator <= ( const Quaternion& q ) const 00347 { 00348 return w <= q.w && x <= q.x && y <= q.y && z <= q.z; 00349 } 00350 00351 /** Checks if this quaternion is component-by-component less than the other. 00352 */ 00353 bool operator >= ( const Quaternion& q ) const 00354 { 00355 return w >= q.w && x >= q.x && y >= q.y && z >= q.z; 00356 } 00357 /*@}*/ 00358 ///////////////////////////////////////////////////////////////////////////////// 00359 00360 public: void Dump ( const char* name ) const; 00361 }; 00362 00363 inline static Quaternion operator + ( double scalar, const Quaternion& q ) 00364 { 00365 return Quaternion( scalar + q.w, scalar + q.x, scalar + q.y, scalar + q.z ); 00366 } 00367 00368 inline static Quaternion operator - ( double scalar, const Quaternion& q ) 00369 { 00370 return Quaternion( scalar - q.w, scalar - q.x, scalar - q.y, scalar - q.z ); 00371 } 00372 00373 inline static Quaternion operator * ( double scalar, const Quaternion& q ) 00374 { 00375 return Quaternion( scalar * q.w, scalar * q.x, scalar * q.y, scalar * q.z ); 00376 } 00377 00378 ///////////////////////////////////////////////////////////////////////////////////// 00379 /** @class SpatialVector 00380 * 00381 * Encapsulates a spatial vector. 00382 * Spatial vector is a pure imaginary quaternion (with the imaginary part only). 00383 */ 00384 class SpatialVector : public Quaternion 00385 { 00386 public: 00387 00388 /** Creates a spatial vector with the given components 00389 */ 00390 SpatialVector( double x, double y, double z ) 00391 : Quaternion( 0, x, y, z ) 00392 { 00393 } 00394 }; 00395 00396 } // namespace WoRB 00397 00398 #endif // _QUATERNION_H_INCLUDED