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
00171 MC_quaternion rot = MC_quaternion::quat_interp(quaternion_vec,weights);
00172 res.set_block(0,2,0,2,rot.matrix());
00173
00174
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
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
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 }