Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #ifndef QGLVIEWER_QUATERNION_H
00024 #define QGLVIEWER_QUATERNION_H
00025 
00026 #include "vec.h"
00027 #include <math.h>
00028 #include <iostream>
00029 
00030 namespace qglviewer {
00066         class QGLVIEWER_EXPORT Quaternion
00067         {
00068         public:
00072                 Quaternion()
00073                 { q[0]=q[1]=q[2]=0.0;  q[3]=1.0; }
00074 
00076                 Quaternion(const Vec& axis, double angle)
00077                 {
00078                         setAxisAngle(axis, angle);
00079                 }
00080 
00081                 Quaternion(const Vec& from, const Vec& to);
00082 
00088                 Quaternion(double q0, double q1, double q2, double q3)
00089                 { q[0]=q0;    q[1]=q1;    q[2]=q2;    q[3]=q3; }
00090 
00092                 Quaternion(const Quaternion& Q)
00093                 { for (int i=0; i<4; ++i) q[i] = Q.q[i]; }
00094 
00096                 Quaternion& operator=(const Quaternion& Q)
00097                 {
00098                         for (int i=0; i<4; ++i)
00099                                 q[i] = Q.q[i];
00100                         return (*this);
00101                 }
00102 
00106                 void setAxisAngle(const Vec& axis, double angle)
00107                 {
00108                         const double norm = axis.norm();
00109                         if (norm < 1E-8)
00110                         {
00111                                 
00112                                 q[0] = 0.0;      q[1] = 0.0;      q[2] = 0.0;      q[3] = 1.0;
00113                         }
00114                         else
00115                         {
00116                                 const double sin_half_angle = sin(angle / 2.0);
00117                                 q[0] = sin_half_angle*axis[0]/norm;
00118                                 q[1] = sin_half_angle*axis[1]/norm;
00119                                 q[2] = sin_half_angle*axis[2]/norm;
00120                                 q[3] = cos(angle / 2.0);
00121                         }
00122                 }
00123 
00125                 void setValue(double q0, double q1, double q2, double q3)
00126                 { q[0]=q0;    q[1]=q1;    q[2]=q2;    q[3]=q3; }
00127 
00128 #ifndef DOXYGEN
00129                 void setFromRotationMatrix(const float m[3][3]);
00130                 void setFromRotatedBase(const Vec& X, const Vec& Y, const Vec& Z);
00131 #endif
00132                 void setFromRotationMatrix(const double m[3][3]);
00133                 void setFromRotatedBasis(const Vec& X, const Vec& Y, const Vec& Z);
00135 
00136 
00139                 Vec axis() const;
00140                 double angle() const;
00141                 void getAxisAngle(Vec& axis, float& angle) const;
00142 
00144                 double operator[](int i) const { return q[i]; }
00145 
00147                 double& operator[](int i) { return q[i]; }
00149 
00150 
00164                 friend Quaternion operator*(const Quaternion& a, const Quaternion& b)
00165                 {
00166                         return Quaternion(a.q[3]*b.q[0] + b.q[3]*a.q[0] + a.q[1]*b.q[2] - a.q[2]*b.q[1],
00167                                 a.q[3]*b.q[1] + b.q[3]*a.q[1] + a.q[2]*b.q[0] - a.q[0]*b.q[2],
00168                                 a.q[3]*b.q[2] + b.q[3]*a.q[2] + a.q[0]*b.q[1] - a.q[1]*b.q[0],
00169                                 a.q[3]*b.q[3] - b.q[0]*a.q[0] - a.q[1]*b.q[1] - a.q[2]*b.q[2]);
00170                 }
00171 
00178                 Quaternion& operator*=(const Quaternion &q)
00179                 {
00180                         *this = (*this)*q;
00181                         return *this;
00182                 }
00183 
00187                 friend Vec operator*(const Quaternion& q, const Vec& v)
00188                 {
00189                         return q.rotate(v);
00190                 }
00191 
00192                 Vec rotate(const Vec& v) const;
00193                 Vec inverseRotate(const Vec& v) const;
00195 
00196 
00205                 Quaternion inverse() const { return Quaternion(-q[0], -q[1], -q[2], q[3]); }
00206 
00210                 void invert() { q[0] = -q[0]; q[1] = -q[1]; q[2] = -q[2]; }
00211 
00220                 void negate() { invert(); q[3] = -q[3]; }
00221 
00227                 double normalize()
00228                 {
00229                         const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
00230                         for (int i=0; i<4; ++i)
00231                                 q[i] /= norm;
00232                         return norm;
00233                 }
00234 
00238                 Quaternion normalized() const
00239                 {
00240                         double Q[4];
00241                         const double norm = sqrt(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
00242                         for (int i=0; i<4; ++i)
00243                                 Q[i] = q[i] / norm;
00244                         return Quaternion(Q[0], Q[1], Q[2], Q[3]);
00245                 }
00247 
00248 
00251                 const GLdouble* matrix() const;
00252                 void getMatrix(GLdouble m[4][4]) const;
00253                 void getMatrix(GLdouble m[16]) const;
00254 
00255                 void getRotationMatrix(float m[3][3]) const;
00256 
00257                 const GLdouble* inverseMatrix() const;
00258                 void getInverseMatrix(GLdouble m[4][4]) const;
00259                 void getInverseMatrix(GLdouble m[16]) const;
00260 
00261                 void getInverseRotationMatrix(float m[3][3]) const;
00263 
00264 
00267                 static Quaternion slerp(const Quaternion& a, const Quaternion& b, float t, bool allowFlip=true);
00268                 static Quaternion squad(const Quaternion& a, const Quaternion& tgA, const Quaternion& tgB, const Quaternion& b, float t);
00270                 static double dot(const Quaternion& a, const Quaternion& b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3]; }
00271 
00272                 Quaternion log();
00273                 Quaternion exp();
00274                 static Quaternion lnDif(const Quaternion& a, const Quaternion& b);
00275                 static Quaternion squadTangent(const Quaternion& before, const Quaternion& center, const Quaternion& after);
00277 
00280                 static Quaternion randomQuaternion();
00282 
00285                 explicit Quaternion(const QDomElement& element);
00286                 QDomElement domElement(const QString& name, QDomDocument& document) const;
00287                 void initFromDOMElement(const QDomElement& element);
00289 
00290 #ifdef DOXYGEN
00291 
00298                 std::ostream& operator<<(std::ostream& o, const qglviewer::Vec&);
00300 #endif
00301 
00302         private:
00304                 double q[4];
00305         };
00306 
00307 } 
00308 
00309 std::ostream& operator<<(std::ostream& o, const qglviewer::Quaternion&);
00310 
00311 #endif // QGLVIEWER_QUATERNION_H