00001 #ifndef OPENTISSUE_CORE_MATH_MATH_QUATERNION_H
00002 #define OPENTISSUE_CORE_MATH_MATH_QUATERNION_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_vector3.h>
00013 #include <OpenTissue/core/math/math_matrix3x3.h>
00014 #include <OpenTissue/core/math/math_value_traits.h>
00015 #include <OpenTissue/core/math/math_is_number.h>
00016
00017 #include <cmath>
00018 #include <iosfwd>
00019
00020
00021 namespace OpenTissue
00022 {
00023
00024 namespace math
00025 {
00026
00027 template<
00028 typename value_type_
00029
00030 >
00031 class Quaternion
00032 {
00033 protected:
00034
00035 typedef typename OpenTissue::math::ValueTraits<value_type_> value_traits_ ;
00036
00037 public:
00038
00039 typedef value_traits_ value_traits;
00040 typedef value_type_ value_type;
00041 typedef Vector3<value_type> vector3_type;
00042 typedef Matrix3x3<value_type> matrix3x3_type;
00043 typedef size_t index_type;
00044
00045 protected:
00046
00047 value_type m_s;
00048 vector3_type m_v;
00049
00050 public:
00051
00052 value_type & s() { return m_s; }
00053 value_type const & s() const { return m_s; }
00054
00055 vector3_type & v() { return m_v; }
00056 vector3_type const & v() const { return m_v; }
00057
00058 public:
00059
00060 Quaternion()
00061 : m_s(value_traits::one())
00062 , m_v(value_traits::zero(),value_traits::zero(),value_traits::zero())
00063 {}
00064
00065 ~Quaternion(){}
00066
00067 Quaternion(Quaternion const & q) { *this = q; }
00068
00069 explicit Quaternion(matrix3x3_type const & M){ *this = M; }
00070
00071 explicit Quaternion(value_type const & s_val, value_type const & x, value_type const & y, value_type const & z)
00072 : m_s(s_val)
00073 , m_v(x,y,z)
00074 { }
00075
00076 explicit Quaternion(value_type const & s_val, vector3_type const & v_val)
00077 : m_s(s_val)
00078 , m_v(v_val)
00079 { }
00080
00081 Quaternion & operator=(Quaternion const & cpy)
00082 {
00083 m_s = cpy.m_s;
00084 m_v = cpy.m_v;
00085 return *this;
00086 }
00087
00096 Quaternion & operator=(matrix3x3_type const & M)
00097 {
00098 using std::sqrt;
00099
00100 value_type const & M00 = M(0,0);
00101 value_type const & M01 = M(0,1);
00102 value_type const & M02 = M(0,2);
00103 value_type const & M10 = M(1,0);
00104 value_type const & M11 = M(1,1);
00105 value_type const & M12 = M(1,2);
00106 value_type const & M20 = M(2,0);
00107 value_type const & M21 = M(2,1);
00108 value_type const & M22 = M(2,2);
00109
00110 value_type tr = M00 + M11 + M22;
00111 value_type r;
00112
00113 value_type const half = value_traits::one()/value_traits::two();
00114
00115 if(tr>=value_traits::zero())
00116 {
00117 r = sqrt(tr + value_traits::one());
00118 m_s = half*r;
00119 r = half/r;
00120 m_v[0] = (M21 - M12) * r;
00121 m_v[1] = (M02 - M20) * r;
00122 m_v[2] = (M10 - M01) * r;
00123 }
00124 else
00125 {
00126 int i = 0;
00127 if(M11>M00)
00128 i = 1;
00129 if(M22>M(i,i))
00130 i = 2;
00131 switch(i)
00132 {
00133 case 0:
00134 r = sqrt((M00 - (M11+M22)) + value_traits::one());
00135 m_v[0] = half*r;
00136 r = half/r;
00137 m_v[1] = (M01 + M10) * r;
00138 m_v[2] = (M20 + M02) * r;
00139 m_s = (M21 - M12) * r;
00140 break;
00141 case 1:
00142 r = sqrt((M11 - (M22+M00)) + value_traits::one());
00143 m_v[1] = half*r;
00144 r = half/r;
00145 m_v[2] = (M12 + M21)*r;
00146 m_v[0] = (M01 + M10)*r;
00147 m_s = (M02 - M20)*r;
00148 break;
00149 case 2:
00150 r = sqrt((M22 - (M00+M11)) + value_traits::one());
00151 m_v[2] = half*r;
00152 r = half/r;
00153 m_v[0] = (M20 + M02) * r;
00154 m_v[1] = (M12 + M21) * r;
00155 m_s = (M10 - M01) * r;
00156 break;
00157 };
00158 }
00159 return *this;
00160 }
00161
00162 public:
00163
00164
00165 bool operator==(Quaternion const & cmp) const { return m_s==cmp.m_s && m_v==cmp.m_v; }
00166 bool operator!=(Quaternion const & cmp) const { return !(*this==cmp); }
00167
00168 public:
00169
00170 Quaternion & operator+= (Quaternion const & q )
00171 {
00172 m_s += q.m_s;
00173 m_v += q.m_v;
00174 return *this;
00175 }
00176
00177 Quaternion & operator-= (Quaternion const & q )
00178 {
00179 m_s -= q.m_s;
00180 m_v -= q.m_v;
00181 return *this;
00182 }
00183
00184 Quaternion operator+ ( Quaternion const &q ) const { return Quaternion(m_s + q.m_s, m_v + q.m_v); }
00185 Quaternion operator- ( Quaternion const &q ) const { return Quaternion(m_s - q.m_s, m_v - q.m_v); }
00186
00187 Quaternion & operator*=(value_type const &s_val )
00188 {
00189 m_s *= s_val;
00190 m_v *= s_val;
00191 return *this;
00192 }
00193
00194 Quaternion & operator/=( value_type const &s_val )
00195 {
00196 assert(s_val || !"quaterion::operator/=(): division by zero");
00197 m_s /= s_val;
00198 m_v /= s_val;
00199 return *this;
00200 }
00201
00202 Quaternion operator-() const { return Quaternion(-m_s,-m_v); }
00203
00204 value_type operator*(Quaternion const &q) const { return m_s*q.m_s + m_v*q.m_v; }
00205
00213 Quaternion operator%(Quaternion const & b)
00214 {
00215 return Quaternion( m_s*b.s() - dot(m_v , b.v()), cross(m_v , b.v()) + b.v()*m_s + m_v*b.s() );
00216 }
00217
00223 Quaternion operator%(vector3_type const & v_val)
00224 {
00225 return Quaternion( - dot( m_v() , v_val) , cross(m_v , v_val) + v_val*m_s );
00226 }
00227
00228 public:
00229
00230 void random(value_type const & min_value, value_type const & max_value)
00231 {
00232 Random<value_type> value(min_value,max_value);
00233 m_v(0) = value();
00234 m_v(1) = value();
00235 m_v(2) = value();
00236 m_s = value();
00237 }
00238
00239 void random() { random(value_traits::zero(),value_traits::one()); }
00240
00248 void Ru(value_type const & rad,vector3_type const & axe)
00249 {
00250 using std::cos;
00251 using std::sin;
00252
00253 value_type teta = rad/value_traits::two();
00254
00255 value_type cteta = boost::numeric_cast<value_type>( cos(teta) );
00256 value_type steta = boost::numeric_cast<value_type>( sin(teta) );
00257 m_s = cteta;
00258
00259 m_v = unit(axe) * steta;
00260 }
00261
00266 void identity()
00267 {
00268 m_s = value_traits::one();
00269 m_v.clear();
00270 }
00271
00277 void Rx(value_type const & rad)
00278 {
00279 using std::cos;
00280 using std::sin;
00281
00282 value_type teta = rad/value_traits::two();
00283 value_type cteta = boost::numeric_cast<value_type>( cos(teta) );
00284 value_type steta = boost::numeric_cast<value_type>( sin(teta) );
00285
00286 m_s = cteta;
00287 m_v(0) = steta;
00288 m_v(1) = value_traits::zero();
00289 m_v(2) = value_traits::zero();
00290 }
00291
00297 void Ry(value_type const & rad)
00298 {
00299 using std::cos;
00300 using std::sin;
00301
00302 value_type teta = rad/value_traits::two();
00303 value_type cteta = boost::numeric_cast<value_type>( cos(teta) );
00304 value_type steta = boost::numeric_cast<value_type>( sin(teta) );
00305
00306 m_s = cteta;
00307 m_v(0) = value_traits::zero();
00308 m_v(1) = steta;
00309 m_v(2) = value_traits::zero();
00310 }
00311
00317 void Rz(value_type const & rad)
00318 {
00319 using std::cos;
00320 using std::sin;
00321
00322 value_type teta = rad/value_traits::two();
00323 value_type cteta = boost::numeric_cast<value_type>( cos(teta) );
00324 value_type steta = boost::numeric_cast<value_type>( sin(teta) );
00325
00326 m_s = cteta;
00327 m_v(0) = value_traits::zero();
00328 m_v(1) = value_traits::zero();
00329 m_v(2) = steta;
00330 }
00331
00337 vector3_type rotate(vector3_type const & r) const { return ((*this) % r % conj(*this)).v(); }
00338
00339 public:
00340
00355 bool is_equal(Quaternion const & q,value_type const & threshold) const
00356 {
00357 using std::fabs;
00358
00359 assert( threshold>=value_traits::zero() || !"is_equal(): threshold must be non-negative");
00360
00361 return fabs(m_s-q.m_s)<threshold && m_v.is_equal(q.v(),threshold);
00362 }
00363
00364 };
00365
00366
00367 template<typename T>
00368 inline Vector3<T> rotate(Quaternion<T> const & q, Vector3<T> const & r)
00369 {
00370 return prod( prod(q , r) , conj(q)).v();
00371 }
00372
00373 template<typename T>
00374 inline Quaternion<T> prod(Quaternion<T> const & a, Quaternion<T> const & b)
00375 {
00376 return Quaternion<T>( a.s()*b.s() - dot(a.v() , b.v()), cross(a.v() , b.v()) + b.v()*a.s() + a.v()*b.s() );
00377 }
00378
00379 template<typename T>
00380 inline Quaternion<T> prod(Quaternion<T> const & a, Vector3<T> const & b)
00381 {
00382 return Quaternion<T>( - dot(a.v() , b), cross(a.v() , b) + b*a.s() );
00383 }
00384
00385 template<typename T>
00386 inline Quaternion<T> prod(Vector3<T> const & a, Quaternion<T> const & b)
00387 {
00388 return Quaternion<T>( - dot(a , b.v()), cross(a , b.v()) + a*b.s() );
00389 }
00390
00391 template<typename T>
00392 inline Quaternion<T> operator%(Quaternion<T> const & a, Quaternion<T> const & b) { return prod(a,b); }
00393 template<typename T>
00394 inline Quaternion<T> operator%(Quaternion<T> const & a, Vector3<T> const & b) { return prod(a,b); }
00395 template<typename T>
00396 inline Quaternion<T> operator%(Vector3<T> const & a, Quaternion<T> const & b) { return prod(a,b); }
00397 template <typename T, typename T2>
00398 inline Quaternion<T> operator*( const Quaternion<T> &q, const T2 &s_val ) { return Quaternion<T>( q.s()*s_val, q.v()*s_val); }
00399 template <typename T2, typename T>
00400 inline Quaternion<T> operator*( const T2 &s_val, const Quaternion<T> &q ) { return Quaternion<T>( q.s()*s_val, q.v()*s_val); }
00401 template <typename T, typename T2>
00402 inline Quaternion<T> operator/( const Quaternion<T> &q, const T2 &s_val ) { return Quaternion<T>( q.s()/s_val, q.v()/s_val); }
00403 template <typename T2, typename T>
00404 inline Quaternion<T> operator/( const T2 &s_val, const Quaternion<T> &q ) { return Quaternion<T>( q.s()/s_val, q.v()/s_val); }
00405
00406 template<typename T>
00407 inline T const length(Quaternion<T> const & q)
00408 {
00409 using std::sqrt;
00410 return sqrt( q*q );
00411 }
00412
00413 template<typename T>
00414 inline Quaternion<T> unit(Quaternion<T> const & q)
00415 {
00416 typedef typename Quaternion<T>::value_traits value_traits;
00417
00418 using std::sqrt;
00419 using std::fabs;
00420
00421 T l = length(q);
00422
00423 if(fabs(l) > value_traits::zero())
00424 return Quaternion<T> (q.s()/l,q.v()/l);
00425 return Quaternion<T> (value_traits::zero(),value_traits::zero(),value_traits::zero(),value_traits::zero());
00426 }
00427
00428 template<typename T>
00429 inline Quaternion<T> normalize(Quaternion<T> const & q) { return unit(q); }
00430
00439 template<typename T>
00440 inline Quaternion<T> log(Quaternion<T> const & q)
00441 {
00442 typedef typename Quaternion<T>::value_traits value_traits;
00443
00444 using std::acos;
00445 using std::sin;
00446
00447 if(q.s()==value_traits::one() && is_zero(q.v()))
00448 return Quaternion<T>(value_traits::zero(),value_traits::zero(),value_traits::zero(),value_traits::zero());
00449
00450 T teta = boost::numeric_cast<T>( acos(q.s()) );
00451 T st = boost::numeric_cast<T>( sin(teta) );
00452 return Quaternion<T>( value_traits::zero(), q.v()*(teta/st) );
00453 }
00454
00462 template<typename T>
00463 inline Quaternion<T> hat(Quaternion<T> const & q)
00464 {
00465 return Quaternion<T>( q.v()(2), - q.v()(1) , q.v()(0), -q.s());
00466 }
00467
00476 template<typename T>
00477 inline Quaternion<T> exp(Quaternion<T> const & q)
00478 {
00479 using std::sqrt;
00480 using std::cos;
00481 using std::sin;
00482
00483
00484
00485 T teta = boost::numeric_cast<T>( sqrt(q.v() *q.v()) );
00486 T ct = boost::numeric_cast<T>( cos(teta) );
00487 T st = boost::numeric_cast<T>( sin(teta) );
00488
00489 return Quaternion<T>(ct,q.v()*st);
00490 }
00491
00506 template<typename T>
00507
00508 inline Quaternion<T> qlerp(Quaternion<T> const & A,Quaternion<T> const & B,T const & w)
00509 {
00510 typedef typename Quaternion<T>::value_traits value_traits;
00511
00512 assert(w>=value_traits::zero() || !"qlerp(): w must not be less than 0");
00513 assert(w<=value_traits::one() || !"qlerp(): w must not be larger than 1");
00514 T mw = value_traits::one() - w;
00515 return ((mw * A) + (w * B));
00516 }
00517
00527 template<typename T>
00528 inline Quaternion<T> slerp(Quaternion<T> const & A,Quaternion<T> const & B,T const & w)
00529 {
00530 typedef typename Quaternion<T>::value_traits value_traits;
00531
00532 using std::acos;
00533 using std::sin;
00534
00535 assert(w>=value_traits::zero() || !"slerp(): w must not be less than 0");
00536 assert(w<=value_traits::one() || !"slerp(): w must not be larger than 1");
00537
00538 T q_tiny = boost::numeric_cast<T>( 10e-7 );
00539
00540 T norm = A*B;
00541
00542 bool flip = false;
00543 if( norm < value_traits::zero() )
00544 {
00545 norm = -norm;
00546 flip = true;
00547 }
00548 T weight = w;
00549 T inv_weight;
00550 if(value_traits::one() - norm < q_tiny)
00551 {
00552 inv_weight = value_traits::one() - weight;
00553 }
00554 else
00555 {
00556 T theta = boost::numeric_cast<T>( acos(norm) );
00557 T s_val = boost::numeric_cast<T>( value_traits::one() / sin(theta) );
00558 inv_weight = boost::numeric_cast<T>( sin((value_traits::one() - weight) * theta) * s_val );
00559 weight = boost::numeric_cast<T>( sin(weight * theta) * s_val );
00560 }
00561 if(flip)
00562 {
00563 weight = -weight;
00564 }
00565 return ( inv_weight * A + weight * B);
00566 }
00567
00583 template<typename T>
00584 inline Quaternion<T> squad(
00585 Quaternion<T> const & q0
00586 , Quaternion<T> const & q1
00587 , Quaternion<T> const & q2
00588 , Quaternion<T> const & q3
00589 , T const & u
00590 )
00591 {
00592 typedef typename Quaternion<T>::value_traits value_traits;
00593
00594 assert(u>=value_traits::zero() || !"squad(): u must not be less than 0");
00595 assert(u<=value_traits::one() || !"squad(): u must not be larger than 1");
00596
00597 T u2 = value_traits::two() *u*(value_traits::one() -u);
00598 return slerp( slerp(q0,q3,u), slerp(q1,q2,u), u2);
00599 }
00600
00604 template<typename T>
00605 inline Quaternion<T> conj(Quaternion<T> const & q)
00606 {
00607 return Quaternion<T>(q.s(),-q.v());
00608 }
00609
00619 template<typename T>
00620 inline void get_axis_angle(Quaternion<T> const & Q,Vector3<T> & axis, T & theta)
00621 {
00622 using std::atan2;
00623
00624 typedef typename Quaternion<T>::value_traits value_traits;
00625 typedef Vector3<T> V;
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 T const ct2 = Q.s();
00716 T const st2 = length( Q.v() );
00717
00718 theta = value_traits::two()* atan2(st2,ct2);
00719
00720 assert( st2 >= value_traits::zero() || !"get_axis_angle(): |sin(theta/2)| must be non-negative");
00721 assert( theta >= value_traits::zero() || !"get_axis_angle(): theta must be non-negative");
00722 assert( is_number(theta) || !"get_axis_angle(): NaN encountered");
00723
00724 axis = st2 > value_traits::zero() ? Q.v() / st2 : V(value_traits::zero(), value_traits::zero(), value_traits::zero());
00725 }
00726
00759 template<typename T>
00760 inline T get_angle(Quaternion<T> const & Q_rel,Vector3<T> const & axis)
00761 {
00762 typedef typename Quaternion<T>::value_traits value_traits;
00763
00764 using std::atan2;
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 T ct2 = Q_rel.s();
00799 T st2 = length( Q_rel.v() );
00800 T theta = value_traits::zero();
00801
00802
00803 if( Q_rel.v() * axis >= value_traits::zero())
00804 {
00805
00806
00807 theta = value_traits::two()* atan2(st2,ct2);
00808 }
00809 else
00810 {
00811
00812
00813 theta = value_traits::two() * atan2(st2,-ct2);
00814 }
00815
00816
00817 if (theta > value_traits::pi())
00818 theta -= value_traits::two()*value_traits::pi();
00819
00820
00821 theta = -theta;
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 return theta;
00846 }
00847
00848 template<typename T>
00849 inline std::ostream & operator<< (std::ostream & o,Quaternion<T> const & q)
00850 {
00851 o << "[" << q.s() << "," << q.v()(0) << "," << q.v()(1) << "," << q.v()(2) << "]";
00852 return o;
00853 }
00854
00855 template<typename T>
00856 inline std::istream & operator>>(std::istream & i,Quaternion<T> & q)
00857 {
00858 char dummy;
00859 i >> dummy;
00860 i >> q.s();
00861 i >> dummy;
00862 i >> q.v()(0);
00863 i >> dummy;
00864 i >> q.v()(1);
00865 i >> dummy;
00866 i >> q.v()(2);
00867 i >> dummy;
00868 return i;
00869 }
00870
00871 }
00872
00873 }
00874
00875
00876 #endif