Quater.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #ifndef SOFA_HELPER_QUATER_H
00028 #define SOFA_HELPER_QUATER_H
00029 
00030 #include <sofa/defaulttype/Vec.h>
00031 #include <sofa/defaulttype/Mat.h>
00032 #include <math.h>
00033 #include <assert.h>
00034 #include <iostream>
00035 
00036 namespace sofa
00037 {
00038 
00039 namespace helper
00040 {
00041 
00042 template<class Real>
00043 class Quater
00044 {
00045 private:
00046         Real _q[4];
00047 
00048 public:
00049         Quater();
00050         virtual ~Quater();
00051         Quater(Real x, Real y, Real z, Real w);
00052         template<class Real2>
00053         Quater(const Real2 q[]) { for (int i=0; i<4; i++) _q[i] = (Real)q[i]; }
00054         template<class Real2>
00055         Quater(const Quater<Real2>& q) { for (int i=0; i<4; i++) _q[i] = (Real)q[i]; }
00056         Quater( const defaulttype::Vec<3,Real>& axis, Real angle );
00057         
00058         static Quater identity() {
00059             return Quater(0,0,0,1);
00060         }
00061             
00062 
00064         const Real* ptr() const
00065         {
00066             return this->_q;
00067         }
00068 
00070         Real* ptr()
00071         {
00072             return this->_q;
00073         }
00074 
00076         void normalize();
00077 
00078         void clear()
00079         {
00080                 _q[0]=0.0;
00081                 _q[1]=0.0;
00082                 _q[2]=0.0;
00083                 _q[3]=1.0;
00084         }
00085 
00086         void fromMatrix(const defaulttype::Matrix3 &m);
00087 
00088         template<class Mat33>
00089         void toMatrix(Mat33 &m) const
00090         {
00091                 m[0][0] = (typename Mat33::Real) (1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]));
00092                 m[0][1] = (typename Mat33::Real) (2.0f * (_q[0] * _q[1] - _q[2] * _q[3]));
00093                 m[0][2] = (typename Mat33::Real) (2.0f * (_q[2] * _q[0] + _q[1] * _q[3]));
00094 
00095                 m[1][0] = (typename Mat33::Real) (2.0f * (_q[0] * _q[1] + _q[2] * _q[3]));
00096                 m[1][1] = (typename Mat33::Real) (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]));
00097                 m[1][2] = (typename Mat33::Real) (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]));
00098 
00099                 m[2][0] = (typename Mat33::Real) (2.0f * (_q[2] * _q[0] - _q[1] * _q[3]));
00100                 m[2][1] = (typename Mat33::Real) (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]));
00101                 m[2][2] = (typename Mat33::Real) (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]));
00102         }
00103 
00105         template<class Vec>
00106         Vec rotate( const Vec& v ) const
00107         {
00108                 return Vec(
00109                     (typename Vec::value_type)((1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]))*v[0] + (2.0f * (_q[0] * _q[1] - _q[2] * _q[3])) * v[1] + (2.0f * (_q[2] * _q[0] + _q[1] * _q[3])) * v[2]),
00110                     (typename Vec::value_type)((2.0f * (_q[0] * _q[1] + _q[2] * _q[3]))*v[0] + (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]))*v[1] + (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]))*v[2]),
00111                     (typename Vec::value_type)((2.0f * (_q[2] * _q[0] - _q[1] * _q[3]))*v[0] + (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]))*v[1] + (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]))*v[2])
00112                        );
00113 
00114         }
00115 
00117         template<class Vec>
00118         Vec inverseRotate( const Vec& v ) const
00119         {
00120                 return Vec(
00121                     (typename Vec::value_type)((1.0f - 2.0f * (_q[1] * _q[1] + _q[2] * _q[2]))*v[0] + (2.0f * (_q[0] * _q[1] + _q[2] * _q[3])) * v[1] + (2.0f * (_q[2] * _q[0] - _q[1] * _q[3])) * v[2]),
00122                     (typename Vec::value_type)((2.0f * (_q[0] * _q[1] - _q[2] * _q[3]))*v[0] + (1.0f - 2.0f * (_q[2] * _q[2] + _q[0] * _q[0]))*v[1] + (2.0f * (_q[1] * _q[2] + _q[0] * _q[3]))*v[2]),
00123                     (typename Vec::value_type)((2.0f * (_q[2] * _q[0] + _q[1] * _q[3]))*v[0] + (2.0f * (_q[1] * _q[2] - _q[0] * _q[3]))*v[1] + (1.0f - 2.0f * (_q[1] * _q[1] + _q[0] * _q[0]))*v[2])
00124                        );
00125 
00126         }
00127 
00131         //template <class T>
00132         //friend Quater<T> operator+(Quater<T> q1, Quater<T> q2);
00133         Quater<Real> operator+(const Quater<Real> &q1) const;
00134 
00135         Quater<Real> operator*(const Quater<Real> &q1) const;
00136 
00137     Quater<Real> operator*(const Real &r) const;
00138 
00140         //template <class T>
00141         //friend Quater<T> operator*(const Quater<T>& q1, const Quater<T>& q2);
00142 
00143         Quater quatVectMult(const defaulttype::Vec<3,Real>& vect);
00144 
00145         Quater vectQuatMult(const defaulttype::Vec<3,Real>& vect);
00146 
00147         Real& operator[](int index)
00148         {
00149                 assert(index >= 0 && index < 4);
00150                 return _q[index];
00151         }
00152 
00153         const Real& operator[](int index) const
00154         {
00155                 assert(index >= 0 && index < 4);
00156                 return _q[index];
00157         }
00158 
00159         Quater inverse() const;
00160 
00161         defaulttype::Vec<3,Real> toEulerVector() const;
00162 
00163         // A useful function, builds a rotation matrix in Matrix based on
00164         // given quaternion.
00165 
00166     void buildRotationMatrix(Real m[4][4]) const;
00167     void writeOpenGlMatrix( double* m ) const; 
00168         void writeOpenGlMatrix( float* m ) const; 
00169 
00170         //void buildRotationMatrix(MATRIX4x4 m);
00171 
00172         //void buildRotationMatrix(Matrix &m);
00173 
00174         // This function computes a quaternion based on an axis (defined by
00175         // the given vector) and an angle about which to rotate.  The angle is
00176         // expressed in radians.
00177         Quater axisToQuat(defaulttype::Vec<3,Real> a, Real phi);
00178 
00180         template<class V>
00181         static Quater createFromRotationVector(const V& a)
00182         {
00183                 Real phi = (Real)sqrt(a*a);
00184                 if( phi < 1.0e-5 )
00185                         return Quater(0,0,0,1);
00186                 else {
00187                         Real nor = 1/phi;
00188                         Real s = (Real)sin(phi/2);
00189                         return Quater( a[0]*s*nor, a[1]*s*nor,a[2]*s*nor, (Real)cos(phi/2) );
00190                 }
00191         }
00192     
00194     static Quater createQuaterFromEuler( defaulttype::Vec<3,Real> v) {
00195       Real quat[4];      Real a0 = v.elems[0];
00196       Real a1 = v.elems[1];
00197       Real a2 = v.elems[2];
00198       quat[3] = cos(a0/2)*cos(a1/2)*cos(a2/2) + sin(a0/2)*sin(a1/2)*sin(a2/2);
00199       quat[0] = sin(a0/2)*cos(a1/2)*cos(a2/2) - cos(a0/2)*sin(a1/2)*sin(a2/2);
00200       quat[1] = cos(a0/2)*sin(a1/2)*cos(a2/2) + sin(a0/2)*cos(a1/2)*sin(a2/2);
00201       quat[2] = cos(a0/2)*cos(a1/2)*sin(a2/2) - sin(a0/2)*sin(a1/2)*cos(a2/2);
00202       Quater quatResult( quat[0], quat[1], quat[2], quat[3] );     
00203       return quatResult;
00204     }
00205     
00207         template<class T>
00208         static Quater createFromRotationVector(T a0, T a1, T a2 )
00209         {
00210             Real phi = (Real)sqrt((Real)(a0*a0+a1*a1+a2*a2));
00211             if( phi < 1.0e-5 )
00212                 return Quater(0,0,0,1);
00213             else {
00214                 Real nor = 1/phi;
00215                 Real s = (Real)sin(phi/2.0);
00216                 return Quater( a0*s*nor, a1*s*nor,a2*s*nor, (Real)cos(phi/2.0) );
00217             }
00218         }
00220         template<class V>
00221         static Quater set(const V& a){ return createFromRotationVector(a); }
00222 
00224         template<class T>
00225         static Quater set(T a0, T a1, T a2){ return createFromRotationVector(a0,a1,a2); }
00226 
00227 
00228         // Print the quaternion
00229 //         inline friend std::ostream& operator<<(std::ostream& out, Quater Q)
00230 //      {
00231 //          return (out << "(" << Q._q[0] << "," << Q._q[1] << "," << Q._q[2] << ","
00232 //              << Q._q[3] << ")");
00233 //      }
00234 
00235         // Print the quaternion (C style)
00236         void print();
00237 
00238         void operator+=(const Quater& q2);
00239         void operator*=(const Quater& q2);
00240         
00242         inline friend std::ostream& operator << ( std::ostream& out, const Quater& v ){
00243             out<<v._q[0]<<" "<<v._q[1]<<" "<<v._q[2]<<" "<<v._q[3];
00244             return out;
00245         }
00247         inline friend std::istream& operator >> ( std::istream& in, Quater& v ){
00248             in>>v._q[0]>>v._q[1]>>v._q[2]>>v._q[3];
00249             return in;
00250         }
00251 
00252         static unsigned int size(){return 4;};
00253 };
00254 
00255 //typedef Quater<double> Quat; ///< alias
00256 //typedef Quater<float> Quatf; ///< alias
00257 //typedef Quater<double> Quaternion; ///< alias
00258 
00259 } // namespace helper
00260 
00261 } // namespace sofa
00262 
00263 #endif
00264 

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1