World of Rigid Bodies (WoRB)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Quaternion.h
Go to the documentation of this file.
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