00001
00002 #ifndef IG_STAT_QUATERN_H
00003 #define IG_STAT_QUATERN_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
00044 CWTSQuaternion(const CWTSVector<4, T> &vec): CWTSVector<4, T>(vec) {}
00045 CWTSQuaternion(const CWTSQuaternion &qtn): CWTSVector<4, T>(qtn) {}
00046
00047
00048 CWTSQuaternion(const CWTSSpaceVector<T> &, const T & = CWTSZero<T>());
00049
00050 CWTSQuaternion(const T &, const T &, const T &, const T &);
00051
00052 CWTSQuaternion(const T &);
00053
00054
00055
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
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
00078 void storeProduct(const CWTSQuaternion &, const CWTSQuaternion &);
00079
00080 void storeConjugate(const CWTSQuaternion &);
00081
00082 void makeConjugate();
00083
00084
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
00124
00125
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
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
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
00277 template <class T>
00278 void
00279 CWTSQuaternion<T>::storeConjugate(const CWTSQuaternion<T> &qtn)
00280 {
00281
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
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
00307 template <class T>
00308 inline T
00309 re(const CWTSQuaternion<T> &qtn)
00310 {
00311 return qtn[3];
00312 }
00313
00314
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
00323 template <class T>
00324 CWTSQuaternion<T>
00325 conj(const CWTSQuaternion<T> &qtn)
00326 {
00327
00328 CWTSQuaternion<T> qtnResult(qtn);
00329 qtnResult.makeConjugate();
00330 return qtnResult;
00331 }
00332
00333
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
00350
00351 template <class T>
00352 inline CWTSQuaternion<T>
00353 sgn(const CWTSQuaternion<T> &qtn)
00354 {
00355 return qtn.unit();
00356 }
00357
00358
00359
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
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
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
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