Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

stat_quatern.h

Go to the documentation of this file.
00001 // -*-c++-*-
00002 #ifndef IG_STAT_QUATERN_H
00003 #define IG_STAT_QUATERN_H
00004 
00005 // $Id: stat_quatern.h,v 1.1.2.8 2005/07/02 15:41:46 hkuiper Exp $
00006 
00007 // CwMtx matrix and vector math library
00008 // Copyright (C) 1999-2001  Harry Kuiper
00009 // Copyright (C) 2000  Will DeVore (template conversion)
00010 // Copyright (C) 2000  Jiri Ecer (constructor from exponential form)
00011 
00012 // This library is free software; you can redistribute it and/or
00013 // modify it under the terms of the GNU Lesser General Public
00014 // License as published by the Free Software Foundation; either
00015 // version 2 of the License, or (at your option) any later version.
00016 
00017 // This library is distributed in the hope that it will be useful,
00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020 // Lesser General Public License for more details.
00021 
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License along with this library; if not, write to the Free Software
00024 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00025 // USA
00026 
00027 #ifndef IG_STAT_SVECTOR_H
00028 #include "stat_svector.h"
00029 #endif
00030 
00031 namespace CwMtx
00032 {
00033   using std::exp;
00034   using std::log;
00035 
00036   // prefix qtn
00037   template <class T = double>
00038   class CWTSQuaternion : public CWTSVector<4, T>
00039   {
00040   public:
00041     CWTSQuaternion(): CWTSVector<4, T>() {}
00042     CWTSQuaternion(const CWTSMatrix<4, 1, T> &mat): CWTSVector<4, T>(mat) {}
00043     // assumption: vec has four elements
00044     CWTSQuaternion(const CWTSVector<4, T> &vec): CWTSVector<4, T>(vec) {}
00045     CWTSQuaternion(const CWTSQuaternion &qtn): CWTSVector<4, T>(qtn) {}
00046     // the space vector will become the quaternion's imaginary part, T
00047     // will become its real part
00048     CWTSQuaternion(const CWTSSpaceVector<T> &, const T & = CWTSZero<T>());
00049     // creates a quaternion, index runs from left to right
00050     CWTSQuaternion(const T &, const T &, const T &, const T &);
00051     // creates a quaternion from a scalar
00052     CWTSQuaternion(const T &);
00053 
00054     // constructor from exponential form: q = r*exp(svec*angle), svec
00055     // should be a unity vector, angle is in radians
00056     CWTSQuaternion(const T &r, const CWTSSpaceVector<T> &svec, const T &angle);
00057 
00058     ~CWTSQuaternion() {}
00059 
00060     CWTSQuaternion operator +(const CWTSQuaternion &) const;
00061     CWTSQuaternion operator -(const CWTSQuaternion &) const;
00062     CWTSQuaternion operator -() const;
00063     CWTSQuaternion operator *(const T &) const;
00064     CWTSQuaternion operator *(const CWTSQuaternion &) const;
00065     CWTSQuaternion operator /(const T &value) const;
00066     CWTSQuaternion operator /(const CWTSQuaternion &) const;
00067 
00068     // not inherited
00069     CWTSQuaternion & operator =(const CWTSQuaternion &);
00070     CWTSQuaternion & operator +=(const CWTSQuaternion &);
00071     CWTSQuaternion & operator -=(const CWTSQuaternion &);
00072     CWTSQuaternion & operator *=(const T &);
00073     CWTSQuaternion & operator *=(const CWTSQuaternion &);
00074     CWTSQuaternion & operator /=(const T &);
00075     CWTSQuaternion & operator /=(const CWTSQuaternion &);
00076 
00077     // stores product of qtn*qtn in this
00078     void storeProduct(const CWTSQuaternion &, const CWTSQuaternion &);
00079     // stores conjugate of argument in this
00080     void storeConjugate(const CWTSQuaternion &);
00081     // makes this its own conjugate
00082     void makeConjugate();
00083 
00084     // returns a unit quaternion with same direction as this
00085     CWTSQuaternion unit() const { return (*this)/(this->norm()); }
00086   };
00087 
00088   template <class T>
00089   inline CWTSQuaternion<T>::CWTSQuaternion(const T &elemIm0,
00090                                            const T &elemIm1,
00091                                            const T &elemIm2,
00092                                            const T &elemReal)
00093     :
00094     CWTSVector<4, T>()
00095   {
00096     (*this)[0] = elemIm0;
00097     (*this)[1] = elemIm1;
00098     (*this)[2] = elemIm2;
00099     (*this)[3] = elemReal;
00100   }
00101 
00102   template <class T>
00103   inline CWTSQuaternion<T>::CWTSQuaternion(const T &elemReal)
00104   {
00105     (*this)[0] = CWTSZero<T>();
00106     (*this)[1] = CWTSZero<T>();
00107     (*this)[2] = CWTSZero<T>();
00108     (*this)[3] = elemReal;
00109   }
00110 
00111   template <class T>
00112   inline CWTSQuaternion<T>::CWTSQuaternion(const CWTSSpaceVector<T> &svecIm,
00113                                            const T &elemReal)
00114     :
00115     CWTSVector<4, T>()
00116   {
00117     (*this)[0] = svecIm[0];
00118     (*this)[1] = svecIm[1];
00119     (*this)[2] = svecIm[2];
00120     (*this)[3] = elemReal;
00121   }
00122 
00123   // NOTE: This only works with template arguments that can be
00124   // converted to floating point types due to the use of sin(3) and
00125   // cos(3).
00126   template <class T>
00127   CWTSQuaternion<T>::CWTSQuaternion(const T &r,
00128                                     const CWTSSpaceVector<T> &svec,
00129                                     const T &angle)
00130     :
00131     CWTSVector<4, T>()
00132   {
00133     T rsina = r*sin(angle);
00134 
00135     (*this)[0] = svec[0]*rsina;
00136     (*this)[1] = svec[1]*rsina;
00137     (*this)[2] = svec[2]*rsina;
00138     (*this)[3] = r*cos(angle);
00139   }
00140 
00141   // not inherited
00142   template <class T>
00143   inline CWTSQuaternion<T> &
00144   CWTSQuaternion<T>::operator =(const CWTSQuaternion<T> &qtn)
00145   {
00146     return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator=(qtn));
00147   }
00148 
00149   template <class T>
00150   inline CWTSQuaternion<T> &
00151   CWTSQuaternion<T>::operator +=(const CWTSQuaternion<T> &qtn)
00152   {
00153     return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator+=(qtn));
00154   }
00155 
00156   template <class T>
00157   inline CWTSQuaternion<T> &
00158   CWTSQuaternion<T>::operator -=(const CWTSQuaternion<T> &qtn)
00159   {
00160     return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator-=(qtn));
00161   }
00162 
00163   template <class T>
00164   inline CWTSQuaternion<T> &
00165   CWTSQuaternion<T>::operator *=(const T &value)
00166   {
00167     return
00168       static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator*=(value));
00169   }
00170 
00171   template <class T>
00172   inline CWTSQuaternion<T> &
00173   CWTSQuaternion<T>::operator *=(const CWTSQuaternion<T> &qtn)
00174   {
00175     return (*this) = (*this)*qtn;
00176   }
00177 
00178   template <class T>
00179   inline CWTSQuaternion<T> &
00180   CWTSQuaternion<T>::operator /=(const T &value)
00181   {
00182     return (*this) *= CWTSUnity<T>()/value;
00183   }
00184 
00185   template <class T>
00186   inline CWTSQuaternion<T> &
00187   CWTSQuaternion<T>::operator /=(const CWTSQuaternion<T> &qtn)
00188   {
00189     return (*this) = (*this)/qtn;
00190   }
00191 
00192   template <class T>
00193   CWTSQuaternion<T>
00194   CWTSQuaternion<T>::operator +(const CWTSQuaternion<T> &qtn) const
00195   {
00196     return CWTSQuaternion(*this) += qtn;
00197   }
00198 
00199   template <class T>
00200   CWTSQuaternion<T>
00201   CWTSQuaternion<T>::operator -(const CWTSQuaternion<T> &qtn) const
00202   {
00203     return CWTSQuaternion(*this) -= qtn;
00204   }
00205 
00206   template <class T>
00207   CWTSQuaternion<T>
00208   CWTSQuaternion<T>::operator -() const
00209   {
00210     return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
00211   }
00212 
00213   template <class T>
00214   CWTSQuaternion<T>
00215   CWTSQuaternion<T>::operator *(const T &value) const
00216   {
00217     return CWTSQuaternion(*this) *= value;
00218   }
00219 
00220   template <class T>
00221   inline CWTSQuaternion<T>
00222   CWTSQuaternion<T>::operator /(const T &value) const
00223   {
00224     return (*this)*(CWTSUnity<T>()/value);
00225   }
00226 
00227   template <class T>
00228   void
00229   CWTSQuaternion<T>::storeProduct(const CWTSQuaternion<T> &qtnLeft,
00230                                   const CWTSQuaternion<T> &qtnRight)
00231   {
00232     // to reduce the number of calls to the subscript operator
00233     T qtnLeft0 = qtnLeft[0];
00234     T qtnLeft1 = qtnLeft[1];
00235     T qtnLeft2 = qtnLeft[2];
00236     T qtnLeft3 = qtnLeft[3];
00237 
00238     T qtnRight0 = qtnRight[0];
00239     T qtnRight1 = qtnRight[1];
00240     T qtnRight2 = qtnRight[2];
00241     T qtnRight3 = qtnRight[3];
00242 
00243     (*this)[0] =
00244       qtnLeft0*qtnRight3 + qtnLeft1*qtnRight2
00245       - qtnLeft2*qtnRight1 + qtnLeft3*qtnRight0;
00246 
00247     (*this)[1] =
00248       -qtnLeft0*qtnRight2 + qtnLeft1*qtnRight3
00249       + qtnLeft2*qtnRight0 + qtnLeft3*qtnRight1;
00250 
00251     (*this)[2] =
00252       qtnLeft0*qtnRight1 - qtnLeft1*qtnRight0
00253       + qtnLeft2*qtnRight3 + qtnLeft3*qtnRight2;
00254 
00255     (*this)[3] =
00256       -qtnLeft0*qtnRight0 - qtnLeft1*qtnRight1
00257       - qtnLeft2*qtnRight2 + qtnLeft3*qtnRight3;
00258   }
00259 
00260   template <class T>
00261   CWTSQuaternion<T>
00262   CWTSQuaternion<T>::operator *(const CWTSQuaternion<T> &qtn) const
00263   {
00264     CWTSQuaternion qtnResult;
00265     qtnResult.storeProduct(*this, qtn);
00266     return qtnResult;
00267   }
00268 
00269   template <class T>
00270   CWTSQuaternion<T>
00271   CWTSQuaternion<T>::operator /(const CWTSQuaternion<T> &qtn) const
00272   {
00273     return (*this)*inv(qtn);
00274   }
00275 
00276   // stores conjugate of argument in this
00277   template <class T>
00278   void
00279   CWTSQuaternion<T>::storeConjugate(const CWTSQuaternion<T> &qtn)
00280   {
00281     // copy argument into this
00282     (*this) = qtn;
00283     makeConjugate();
00284   }
00285 
00286   template <class T>
00287   void
00288   CWTSQuaternion<T>::makeConjugate()
00289   {
00290     T tmp = CWTSZero<T>() - CWTSUnity<T>();
00291 
00292     (*this)[0] *= tmp;
00293     (*this)[1] *= tmp;
00294     (*this)[2] *= tmp;
00295   }
00296 
00297   // template functions designed work with the Quaternion class.
00298 
00299   template <class T>
00300   inline CWTSQuaternion<T>
00301   operator *(const T &value, const CWTSQuaternion<T> &qtn)
00302   {
00303     return qtn*value;
00304   }
00305 
00306   // return real part of a quaternion
00307   template <class T>
00308   inline T
00309   re(const CWTSQuaternion<T> &qtn)
00310   {
00311     return qtn[3];
00312   }
00313 
00314   // returns imaginary (vector) part of a quaternion
00315   template <class T>
00316   CWTSSpaceVector<T>
00317   im(const CWTSQuaternion<T> &qtn)
00318   {
00319     return CWTSSpaceVector<T>(qtn[0], qtn[1], qtn[2]);
00320   }
00321 
00322   // the conjugate
00323   template <class T>
00324   CWTSQuaternion<T>
00325   conj(const CWTSQuaternion<T> &qtn)
00326   {
00327     // copy input quaternion
00328     CWTSQuaternion<T> qtnResult(qtn);
00329     qtnResult.makeConjugate();
00330     return qtnResult;
00331   }
00332 
00333   // the inverse
00334   template <class T>
00335   CWTSQuaternion<T>
00336   inv(const CWTSQuaternion<T> &qtn)
00337   {
00338     T qtn0 = qtn[0];
00339     T qtn1 = qtn[1];
00340     T qtn2 = qtn[2];
00341     T qtn3 = qtn[3];
00342 
00343     return conj(qtn)/static_cast<const T &>(qtn0*qtn0
00344                                             + qtn1*qtn1
00345                                             + qtn2*qtn2
00346                                             + qtn3*qtn3);
00347   }
00348 
00349   // the sign of a quaternion is a unit quaternion with the same
00350   // direction
00351   template <class T>
00352   inline CWTSQuaternion<T>
00353   sgn(const CWTSQuaternion<T> &qtn)
00354   {
00355     return qtn.unit();
00356   }
00357 
00358   // the argument of a quaternion is the angle between it and the
00359   // scalar number 1 (analogous to the argument of a complex number)
00360   template <class T>
00361   inline T
00362   arg(const CWTSQuaternion<T> &qtn)
00363   {
00364     return atan2(norm(im(qtn)), re(qtn));
00365   }
00366 
00367   // quaternion exponentiation
00368   template <class T>
00369   CWTSQuaternion<T>
00370   exp(const CWTSQuaternion<T> &qtn)
00371   {
00372     CWTSSpaceVector<T> svec = im(qtn);
00373     T len = norm(svec);
00374 
00375     if (len == CWTSZero<T>())
00376       {
00377         return exp(re(qtn))*CWTSQuaternion<T>(CWTSZero<T>(),
00378                                               CWTSZero<T>(),
00379                                               CWTSZero<T>(),
00380                                               cos(len));
00381       }
00382     else
00383       {
00384         return exp(re(qtn))*CWTSQuaternion<T>(sgn(svec)*sin(len), cos(len));
00385       }
00386   }
00387 
00388   // quaternion logarithm (with base e)
00389   template <class T>
00390   CWTSQuaternion<T>
00391   log(const CWTSQuaternion<T> &qtn)
00392   {
00393     CWTSSpaceVector<T> svec = im(qtn);
00394     T len = norm(svec);
00395 
00396     if (len == CWTSZero<T>())
00397       {
00398         return CWTSQuaternion<T>(CWTSZero<T>(),
00399                                  CWTSZero<T>(),
00400                                  CWTSZero<T>(),
00401                                  log(norm(qtn)));
00402       }
00403     else
00404       {
00405         return CWTSQuaternion<T>(sgn(svec)*arg(qtn), log(norm(qtn)));
00406       }
00407   }
00408 
00409   // quaternion power! raise qtn1 to the power qtn2
00410   template <class T>
00411   inline CWTSQuaternion<T>
00412   pow(const CWTSQuaternion<T> &qtn1, const CWTSQuaternion<T> &qtn2)
00413   {
00414     return exp(qtn2*log(qtn1));
00415   }
00416 }
00417 
00418 #endif // IG_STAT_QUATERN_H

Generated on Sun Jul 3 12:18:46 2005 for Matrix and vector library by  doxygen 1.4.2