MC_quaternion.cpp

Go to the documentation of this file.
00001 
00002 #include <cmath>
00003 #include <MC_double_vector.hpp>
00004 #include <MC_v3d.hpp>
00005 #include <MC_v3d_vector.hpp>
00006 #include <MC_matrix.hpp>
00007 
00008 #include <MC_quaternion.hpp>
00009 
00010 namespace mesh_conv
00011 {
00012 
00013     MC_quaternion::MC_quaternion()
00014             :MC_v4d(1,0,0,0)
00015     {}
00016     MC_quaternion::MC_quaternion(const MC_v3d& axis,const double& angle)
00017             :MC_v4d(0,0,0,0)
00018     {
00019         double sin_phi=sin(angle/2.0);
00020         MC_v3d n_axis=axis.normalized();
00021         *this=MC_v4d(n_axis[0]*sin_phi,n_axis[1]*sin_phi,n_axis[2]*sin_phi,cos(angle/2.0));
00022     }
00023     MC_quaternion::MC_quaternion(const MC_v4d& v)
00024             :MC_v4d(v)
00025     {}
00026     MC_quaternion::MC_quaternion(const MC_quaternion& q)
00027             :MC_v4d(q[0],q[1],q[2],q[3])
00028     {}
00029     MC_quaternion::MC_quaternion(const double& x,const double& y,const double& z,const double& w)
00030             :MC_v4d(x,y,z,w)
00031     {}
00032 
00033     MC_matrix MC_quaternion::matrix() const
00034     {
00035         double x2 = (*this)[0]*(*this)[0];
00036         double y2 = (*this)[1]*(*this)[1];
00037         double z2 = (*this)[2]*(*this)[2];
00038         double xy = (*this)[0]*(*this)[1];
00039         double xz = (*this)[0]*(*this)[2];
00040         double yz = (*this)[1]*(*this)[2];
00041         double wx = (*this)[3]*(*this)[0];
00042         double wy = (*this)[3]*(*this)[1];
00043         double wz = (*this)[3]*(*this)[2];
00044 
00045         MC_matrix M(3,3);
00046         M(0,0) = 1-2*(y2+z2);
00047         M(1,0) =   2*(xy+wz);
00048         M(2,0) =   2*(xz-wy);
00049 
00050         M(0,1) =   2*(xy-wz);
00051         M(1,1) = 1-2*(x2+z2);
00052         M(2,1) =   2*(yz+wx);
00053 
00054         M(0,2) =   2*(xz+wy);
00055         M(1,2) =   2*(yz-wx);
00056         M(2,2) = 1-2*(x2+y2);
00057 
00058         return M;
00059     }
00060 
00061     MC_quaternion MC_quaternion::conjugated() const
00062     {
00063         MC_quaternion q2;
00064         for(int k_dim=0;k_dim<3;k_dim++)
00065             q2[k_dim]=-(*this)[k_dim];
00066         q2[3]=(*this)[3];
00067         return q2;
00068     }
00069     MC_quaternion operator*(const MC_quaternion& q0,const MC_quaternion& q1)
00070     {
00071         MC_quaternion q2;
00072         double w0=q0[3],w1=q1[3];
00073         MC_v3d v0=MC_v3d(q0[0],q0[1],q0[2]);
00074         MC_v3d v1=MC_v3d(q1[0],q1[1],q1[2]);
00075 
00076         q2[3]=w0*w1-v0.dot(v1);
00077         q2.set_v3d(w0*v1+w1*v0-v0.cross(v1));
00078 
00079         return q2;
00080     }
00081     MC_quaternion& MC_quaternion::operator*=(const MC_quaternion& q1)
00082     {
00083 
00084         double w0=(*this)[3],w1=q1[3];
00085         MC_v3d v0=MC_v3d((*this)[0],(*this)[1],(*this)[2]);
00086         MC_v3d v1=MC_v3d(q1[0],q1[1],q1[2]);
00087 
00088         (*this)[3]=w0*w1-v0.dot(v1);
00089         set_v3d(w0*v1+w1*v0-v0.cross(v1));
00090 
00091         return *this;
00092     }
00093 
00094     MC_v3d MC_quaternion::axis() const
00095     {return MC_v3d((*this)(0),(*this)(1),(*this)(2)).normalized();}
00096     double MC_quaternion::angle() const
00097     {return 2*acos((*this)[3]);}
00098     MC_quaternion MC_quaternion::slerp(const MC_quaternion& q0,const MC_quaternion& q1,const double& t)
00099     {
00100         double cos_theta = q0.dot(q1);
00101         double theta = acos(cos_theta);
00102         double sin_theta = sqrt(1-cos_theta*cos_theta);
00103 
00104         double epsilon=0.0001;
00105         if(fabs(sin_theta)<epsilon)
00106         {std::cout<<"Warning in Quaternion::SLERP, sin(theta) is zero"<<std::endl;return q0;}
00107 
00108         MC_quaternion interpolated = (sin((1-t)*theta)*q0 + sin(t*theta)*q1) / sin_theta;
00109         return interpolated;
00110     }
00111 
00112     MC_quaternion MC_quaternion::pow(const double& t) const
00113     {return MC_quaternion::exp( t * log());}
00114     MC_quaternion MC_quaternion::inverted() const
00115     {
00116         double n=norm();
00117         double epsilon=0.000001;
00118         if(n<epsilon)
00119         {std::cout<<"Error in Quaternion::invert(), norm is zero"<<std::endl;exit(-1);}
00120 
00121         MC_quaternion Q = conjugated()/(n*n);
00122         return Q;
00123     }
00124     MC_v3d MC_quaternion::log() const
00125     {
00126 
00127         double n=sqrt(1-(*this)[3]*(*this)[3]);
00128         double acos_w = acos((*this)[3]);
00129 
00130         double epsilon=0.0001;
00131         if(n<epsilon)
00132             return MC_v3d(0,0,0);
00133 
00134         return acos_w/n*MC_v3d((*this)[0],(*this)[1],(*this)[2]);
00135     }
00136     MC_quaternion MC_quaternion::exp(const MC_v3d& v)
00137     {
00138         double epsilon=0.000001;
00139         double n=v.norm();
00140         if(n<epsilon)
00141             return MC_quaternion(0,0,0,1);
00142 
00143         double a = sin(n)/n;
00144 
00145         return MC_quaternion(a*v[0],a*v[1],a*v[2],cos(n));
00146     }
00147 
00148 
00149 
00150     MC_quaternion MC_quaternion::quat_interp(const std::vector <MC_quaternion>& quaternion_vec,const MC_double_vector& weights)
00151     {
00152         if(int(quaternion_vec.size())!=weights.size())
00153         {std::cout<<"Error in MC_quaternion::quat_interp(vector<MC_quaternion>,MC_double_vector), size are not compatible ("<<quaternion_vec.size()<<","<<weights.size()<<")"<<std::endl;exit(-1);}
00154 
00155         MC_quaternion temp(0,0,0,0);
00156         int N=quaternion_vec.size();
00157         for(int k=0;k<N;k++)
00158             temp += weights[k]*quaternion_vec[k];
00159         temp /= temp.norm();
00160         return temp;
00161     }
00162 
00163     MC_matrix MC_quaternion::quat_interp(const std::vector <MC_quaternion>& quaternion_vec,const MC_double_vector& weights,const MC_v3d_vector& translation_vec)
00164     {
00165         MC_matrix res(4,4);
00166 
00167         if(weights.size()!=translation_vec.size())
00168         {std::cout<<"Error in MC_quaternion::quat_interp(vector<MC_quaternion>("<<quaternion_vec.size()<<"),MC_double_vector("<<weights.size()<<"),MC_v3d_vector("<<translation_vec.size()<<")), size are not compatible"<<std::endl;exit(-1);}
00169 
00170         //first do the rotation
00171         MC_quaternion rot = MC_quaternion::quat_interp(quaternion_vec,weights);
00172         res.set_block(0,2,0,2,rot.matrix());
00173 
00174         //then the translation by linear interpolation
00175         MC_v3d tr = MC_v3d_vector::sum(weights*translation_vec);
00176         res.set_block(0,2,3,3,tr);
00177         res(3,3)=1;
00178 
00179         return res;
00180 
00181     }
00182 
00183     MC_matrix MC_quaternion::quat_interp(const std::vector <MC_matrix>& matrix_vec,const MC_double_vector& weights)
00184     {
00185         if(static_cast<int>(matrix_vec.size()) !=weights.size())
00186         {std::cout<<"Error in MC_quaternion::quat_interp(vector<MC_matrix>,MC_double_vector), size are not compatible ("<<matrix_vec.size()<<","<<weights.size()<<")"<<std::endl;exit(-1);}
00187 
00188         int N=matrix_vec.size();
00189 
00190         // rotation
00191         std::vector <MC_quaternion> quaternion_vec(N);
00192         for(int k=0;k<N;k++)
00193             quaternion_vec[k] = MC_quaternion(matrix_vec[k]);
00194         MC_quaternion res = MC_quaternion::quat_interp(quaternion_vec,weights);
00195 
00196         // translation
00197         MC_v3d tr;
00198         for(int k=0;k<N;k++)
00199             tr += weights[k]*(matrix_vec[k].translation_part());
00200 
00201 
00202         MC_matrix interpolated_matrix(4,4);
00203         interpolated_matrix.set_block(0,2,0,2,res.matrix());
00204         interpolated_matrix.set_block(0,2,3,3,tr);
00205 
00206 
00207         return interpolated_matrix;
00208 
00209     }
00210 
00211 
00212 }

Generated on Sun Apr 18 20:24:47 2010 by  doxygen 1.6.1