MOAB  4.9.3pre
Quaternion.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008-2010 Gael Guennebaud <[email protected]>
00005 // Copyright (C) 2009 Mathieu Gautier <[email protected]>
00006 //
00007 // This Source Code Form is subject to the terms of the Mozilla
00008 // Public License v. 2.0. If a copy of the MPL was not distributed
00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00010 
00011 #ifndef EIGEN_QUATERNION_H
00012 #define EIGEN_QUATERNION_H
00013 namespace Eigen { 
00014 
00015 
00016 /***************************************************************************
00017 * Definition of QuaternionBase<Derived>
00018 * The implementation is at the end of the file
00019 ***************************************************************************/
00020 
00021 namespace internal {
00022 template<typename Other,
00023          int OtherRows=Other::RowsAtCompileTime,
00024          int OtherCols=Other::ColsAtCompileTime>
00025 struct quaternionbase_assign_impl;
00026 }
00027 
00034 template<class Derived>
00035 class QuaternionBase : public RotationBase<Derived, 3>
00036 {
00037  public:
00038   typedef RotationBase<Derived, 3> Base;
00039 
00040   using Base::operator*;
00041   using Base::derived;
00042 
00043   typedef typename internal::traits<Derived>::Scalar Scalar;
00044   typedef typename NumTraits<Scalar>::Real RealScalar;
00045   typedef typename internal::traits<Derived>::Coefficients Coefficients;
00046   enum {
00047     Flags = Eigen::internal::traits<Derived>::Flags
00048   };
00049 
00050  // typedef typename Matrix<Scalar,4,1> Coefficients;
00052   typedef Matrix<Scalar,3,1> Vector3;
00054   typedef Matrix<Scalar,3,3> Matrix3;
00056   typedef AngleAxis<Scalar> AngleAxisType;
00057 
00058 
00059 
00061   inline Scalar x() const { return this->derived().coeffs().coeff(0); }
00063   inline Scalar y() const { return this->derived().coeffs().coeff(1); }
00065   inline Scalar z() const { return this->derived().coeffs().coeff(2); }
00067   inline Scalar w() const { return this->derived().coeffs().coeff(3); }
00068 
00070   inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
00072   inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
00074   inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
00076   inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
00077 
00079   inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
00080 
00082   inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
00083 
00085   inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
00086 
00088   inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
00089 
00090   EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
00091   template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
00092 
00093 // disabled this copy operator as it is giving very strange compilation errors when compiling
00094 // test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
00095 // useful; however notice that we already have the templated operator= above and e.g. in MatrixBase
00096 // we didn't have to add, in addition to templated operator=, such a non-templated copy operator.
00097 //  Derived& operator=(const QuaternionBase& other)
00098 //  { return operator=<Derived>(other); }
00099 
00100   Derived& operator=(const AngleAxisType& aa);
00101   template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
00102 
00106   static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
00107 
00110   inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
00111 
00115   inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
00116 
00120   inline Scalar norm() const { return coeffs().norm(); }
00121 
00124   inline void normalize() { coeffs().normalize(); }
00127   inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
00128 
00134   template<class OtherDerived> inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
00135 
00136   template<class OtherDerived> Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
00137 
00139   Matrix3 toRotationMatrix() const;
00140 
00142   template<typename Derived1, typename Derived2>
00143   Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
00144 
00145   template<class OtherDerived> EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
00146   template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
00147 
00149   Quaternion<Scalar> inverse() const;
00150 
00152   Quaternion<Scalar> conjugate() const;
00153 
00154   template<class OtherDerived> Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
00155 
00160   template<class OtherDerived>
00161   bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
00162   { return coeffs().isApprox(other.coeffs(), prec); }
00163 
00165   EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
00166 
00172   template<typename NewScalarType>
00173   inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
00174   {
00175     return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(derived());
00176   }
00177 
00178 #ifdef EIGEN_QUATERNIONBASE_PLUGIN
00179 # include EIGEN_QUATERNIONBASE_PLUGIN
00180 #endif
00181 };
00182 
00183 /***************************************************************************
00184 * Definition/implementation of Quaternion<Scalar>
00185 ***************************************************************************/
00186 
00212 namespace internal {
00213 template<typename _Scalar,int _Options>
00214 struct traits<Quaternion<_Scalar,_Options> >
00215 {
00216   typedef Quaternion<_Scalar,_Options> PlainObject;
00217   typedef _Scalar Scalar;
00218   typedef Matrix<_Scalar,4,1,_Options> Coefficients;
00219   enum{
00220     Alignment = internal::traits<Coefficients>::Alignment,
00221     Flags = LvalueBit
00222   };
00223 };
00224 }
00225 
00226 template<typename _Scalar, int _Options>
00227 class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
00228 {
00229 public:
00230   typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
00231   enum { NeedsAlignment = internal::traits<Quaternion>::Alignment>0 };
00232 
00233   typedef _Scalar Scalar;
00234 
00235   EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
00236   using Base::operator*=;
00237 
00238   typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
00239   typedef typename Base::AngleAxisType AngleAxisType;
00240 
00242   inline Quaternion() {}
00243 
00251   inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
00252 
00254   explicit inline Quaternion(const Scalar* data) : m_coeffs(data) {}
00255 
00257   template<class Derived> EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
00258 
00260   explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
00261 
00266   template<typename Derived>
00267   explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
00268 
00270   template<typename OtherScalar, int OtherOptions>
00271   explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
00272   { m_coeffs = other.coeffs().template cast<Scalar>(); }
00273 
00274   template<typename Derived1, typename Derived2>
00275   static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
00276 
00277   inline Coefficients& coeffs() { return m_coeffs;}
00278   inline const Coefficients& coeffs() const { return m_coeffs;}
00279 
00280   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(NeedsAlignment))
00281   
00282 #ifdef EIGEN_QUATERNION_PLUGIN
00283 # include EIGEN_QUATERNION_PLUGIN
00284 #endif
00285 
00286 protected:
00287   Coefficients m_coeffs;
00288   
00289 #ifndef EIGEN_PARSED_BY_DOXYGEN
00290     static EIGEN_STRONG_INLINE void _check_template_params()
00291     {
00292       EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options,
00293         INVALID_MATRIX_TEMPLATE_PARAMETERS)
00294     }
00295 #endif
00296 };
00297 
00300 typedef Quaternion<float> Quaternionf;
00303 typedef Quaternion<double> Quaterniond;
00304 
00305 /***************************************************************************
00306 * Specialization of Map<Quaternion<Scalar>>
00307 ***************************************************************************/
00308 
00309 namespace internal {
00310   template<typename _Scalar, int _Options>
00311   struct traits<Map<Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
00312   {
00313     typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
00314   };
00315 }
00316 
00317 namespace internal {
00318   template<typename _Scalar, int _Options>
00319   struct traits<Map<const Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
00320   {
00321     typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
00322     typedef traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> > TraitsBase;
00323     enum {
00324       Flags = TraitsBase::Flags & ~LvalueBit
00325     };
00326   };
00327 }
00328 
00340 template<typename _Scalar, int _Options>
00341 class Map<const Quaternion<_Scalar>, _Options >
00342   : public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
00343 {
00344   public:
00345     typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
00346 
00347     typedef _Scalar Scalar;
00348     typedef typename internal::traits<Map>::Coefficients Coefficients;
00349     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
00350     using Base::operator*=;
00351 
00358     explicit EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
00359 
00360     inline const Coefficients& coeffs() const { return m_coeffs;}
00361 
00362   protected:
00363     const Coefficients m_coeffs;
00364 };
00365 
00377 template<typename _Scalar, int _Options>
00378 class Map<Quaternion<_Scalar>, _Options >
00379   : public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
00380 {
00381   public:
00382     typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
00383 
00384     typedef _Scalar Scalar;
00385     typedef typename internal::traits<Map>::Coefficients Coefficients;
00386     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
00387     using Base::operator*=;
00388 
00395     explicit EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
00396 
00397     inline Coefficients& coeffs() { return m_coeffs; }
00398     inline const Coefficients& coeffs() const { return m_coeffs; }
00399 
00400   protected:
00401     Coefficients m_coeffs;
00402 };
00403 
00406 typedef Map<Quaternion<float>, 0>         QuaternionMapf;
00409 typedef Map<Quaternion<double>, 0>        QuaternionMapd;
00412 typedef Map<Quaternion<float>, Aligned>   QuaternionMapAlignedf;
00415 typedef Map<Quaternion<double>, Aligned>  QuaternionMapAlignedd;
00416 
00417 /***************************************************************************
00418 * Implementation of QuaternionBase methods
00419 ***************************************************************************/
00420 
00421 // Generic Quaternion * Quaternion product
00422 // This product can be specialized for a given architecture via the Arch template argument.
00423 namespace internal {
00424 template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
00425 {
00426   static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
00427     return Quaternion<Scalar>
00428     (
00429       a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
00430       a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
00431       a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
00432       a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
00433     );
00434   }
00435 };
00436 }
00437 
00439 template <class Derived>
00440 template <class OtherDerived>
00441 EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
00442 QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
00443 {
00444   EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
00445    YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00446   return internal::quat_product<Architecture::Target, Derived, OtherDerived,
00447                          typename internal::traits<Derived>::Scalar,
00448                          EIGEN_PLAIN_ENUM_MIN(internal::traits<Derived>::Alignment, internal::traits<OtherDerived>::Alignment)>::run(*this, other);
00449 }
00450 
00452 template <class Derived>
00453 template <class OtherDerived>
00454 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
00455 {
00456   derived() = derived() * other.derived();
00457   return derived();
00458 }
00459 
00467 template <class Derived>
00468 EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
00469 QuaternionBase<Derived>::_transformVector(const Vector3& v) const
00470 {
00471     // Note that this algorithm comes from the optimization by hand
00472     // of the conversion to a Matrix followed by a Matrix/Vector product.
00473     // It appears to be much faster than the common algorithm found
00474     // in the literature (30 versus 39 flops). It also requires two
00475     // Vector3 as temporaries.
00476     Vector3 uv = this->vec().cross(v);
00477     uv += uv;
00478     return v + this->w() * uv + this->vec().cross(uv);
00479 }
00480 
00481 template<class Derived>
00482 EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
00483 {
00484   coeffs() = other.coeffs();
00485   return derived();
00486 }
00487 
00488 template<class Derived>
00489 template<class OtherDerived>
00490 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
00491 {
00492   coeffs() = other.coeffs();
00493   return derived();
00494 }
00495 
00498 template<class Derived>
00499 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
00500 {
00501   using std::cos;
00502   using std::sin;
00503   Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
00504   this->w() = cos(ha);
00505   this->vec() = sin(ha) * aa.axis();
00506   return derived();
00507 }
00508 
00515 template<class Derived>
00516 template<class MatrixDerived>
00517 inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
00518 {
00519   EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
00520    YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00521   internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
00522   return derived();
00523 }
00524 
00528 template<class Derived>
00529 inline typename QuaternionBase<Derived>::Matrix3
00530 QuaternionBase<Derived>::toRotationMatrix(void) const
00531 {
00532   // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
00533   // if not inlined then the cost of the return by value is huge ~ +35%,
00534   // however, not inlining this function is an order of magnitude slower, so
00535   // it has to be inlined, and so the return by value is not an issue
00536   Matrix3 res;
00537 
00538   const Scalar tx  = Scalar(2)*this->x();
00539   const Scalar ty  = Scalar(2)*this->y();
00540   const Scalar tz  = Scalar(2)*this->z();
00541   const Scalar twx = tx*this->w();
00542   const Scalar twy = ty*this->w();
00543   const Scalar twz = tz*this->w();
00544   const Scalar txx = tx*this->x();
00545   const Scalar txy = ty*this->x();
00546   const Scalar txz = tz*this->x();
00547   const Scalar tyy = ty*this->y();
00548   const Scalar tyz = tz*this->y();
00549   const Scalar tzz = tz*this->z();
00550 
00551   res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
00552   res.coeffRef(0,1) = txy-twz;
00553   res.coeffRef(0,2) = txz+twy;
00554   res.coeffRef(1,0) = txy+twz;
00555   res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
00556   res.coeffRef(1,2) = tyz-twx;
00557   res.coeffRef(2,0) = txz-twy;
00558   res.coeffRef(2,1) = tyz+twx;
00559   res.coeffRef(2,2) = Scalar(1)-(txx+tyy);
00560 
00561   return res;
00562 }
00563 
00574 template<class Derived>
00575 template<typename Derived1, typename Derived2>
00576 inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
00577 {
00578   using std::sqrt;
00579   Vector3 v0 = a.normalized();
00580   Vector3 v1 = b.normalized();
00581   Scalar c = v1.dot(v0);
00582 
00583   // if dot == -1, vectors are nearly opposites
00584   // => accurately compute the rotation axis by computing the
00585   //    intersection of the two planes. This is done by solving:
00586   //       x^T v0 = 0
00587   //       x^T v1 = 0
00588   //    under the constraint:
00589   //       ||x|| = 1
00590   //    which yields a singular value problem
00591   if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
00592   {
00593     c = numext::maxi(c,Scalar(-1));
00594     Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
00595     JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
00596     Vector3 axis = svd.matrixV().col(2);
00597 
00598     Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
00599     this->w() = sqrt(w2);
00600     this->vec() = axis * sqrt(Scalar(1) - w2);
00601     return derived();
00602   }
00603   Vector3 axis = v0.cross(v1);
00604   Scalar s = sqrt((Scalar(1)+c)*Scalar(2));
00605   Scalar invs = Scalar(1)/s;
00606   this->vec() = axis * invs;
00607   this->w() = s * Scalar(0.5);
00608 
00609   return derived();
00610 }
00611 
00612 
00623 template<typename Scalar, int Options>
00624 template<typename Derived1, typename Derived2>
00625 Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
00626 {
00627     Quaternion quat;
00628     quat.setFromTwoVectors(a, b);
00629     return quat;
00630 }
00631 
00632 
00639 template <class Derived>
00640 inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
00641 {
00642   // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite()  ??
00643   Scalar n2 = this->squaredNorm();
00644   if (n2 > Scalar(0))
00645     return Quaternion<Scalar>(conjugate().coeffs() / n2);
00646   else
00647   {
00648     // return an invalid result to flag the error
00649     return Quaternion<Scalar>(Coefficients::Zero());
00650   }
00651 }
00652 
00653 // Generic conjugate of a Quaternion
00654 namespace internal {
00655 template<int Arch, class Derived, typename Scalar, int _Options> struct quat_conj
00656 {
00657   static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived>& q){
00658     return Quaternion<Scalar>(q.w(),-q.x(),-q.y(),-q.z());
00659   }
00660 };
00661 }
00662                          
00669 template <class Derived>
00670 inline Quaternion<typename internal::traits<Derived>::Scalar>
00671 QuaternionBase<Derived>::conjugate() const
00672 {
00673   return internal::quat_conj<Architecture::Target, Derived,
00674                          typename internal::traits<Derived>::Scalar,
00675                          internal::traits<Derived>::Alignment>::run(*this);
00676                          
00677 }
00678 
00682 template <class Derived>
00683 template <class OtherDerived>
00684 inline typename internal::traits<Derived>::Scalar
00685 QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
00686 {
00687   using std::atan2;
00688   using std::abs;
00689   Quaternion<Scalar> d = (*this) * other.conjugate();
00690   return Scalar(2) * atan2( d.vec().norm(), abs(d.w()) );
00691 }
00692 
00693  
00694     
00701 template <class Derived>
00702 template <class OtherDerived>
00703 Quaternion<typename internal::traits<Derived>::Scalar>
00704 QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
00705 {
00706   using std::acos;
00707   using std::sin;
00708   using std::abs;
00709   static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
00710   Scalar d = this->dot(other);
00711   Scalar absD = abs(d);
00712 
00713   Scalar scale0;
00714   Scalar scale1;
00715 
00716   if(absD>=one)
00717   {
00718     scale0 = Scalar(1) - t;
00719     scale1 = t;
00720   }
00721   else
00722   {
00723     // theta is the angle between the 2 quaternions
00724     Scalar theta = acos(absD);
00725     Scalar sinTheta = sin(theta);
00726 
00727     scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
00728     scale1 = sin( ( t * theta) ) / sinTheta;
00729   }
00730   if(d<Scalar(0)) scale1 = -scale1;
00731 
00732   return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
00733 }
00734 
00735 namespace internal {
00736 
00737 // set from a rotation matrix
00738 template<typename Other>
00739 struct quaternionbase_assign_impl<Other,3,3>
00740 {
00741   typedef typename Other::Scalar Scalar;
00742   template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& a_mat)
00743   {
00744     const typename internal::nested_eval<Other,2>::type mat(a_mat);
00745     using std::sqrt;
00746     // This algorithm comes from  "Quaternion Calculus and Fast Animation",
00747     // Ken Shoemake, 1987 SIGGRAPH course notes
00748     Scalar t = mat.trace();
00749     if (t > Scalar(0))
00750     {
00751       t = sqrt(t + Scalar(1.0));
00752       q.w() = Scalar(0.5)*t;
00753       t = Scalar(0.5)/t;
00754       q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
00755       q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
00756       q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
00757     }
00758     else
00759     {
00760       Index i = 0;
00761       if (mat.coeff(1,1) > mat.coeff(0,0))
00762         i = 1;
00763       if (mat.coeff(2,2) > mat.coeff(i,i))
00764         i = 2;
00765       Index j = (i+1)%3;
00766       Index k = (j+1)%3;
00767 
00768       t = sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
00769       q.coeffs().coeffRef(i) = Scalar(0.5) * t;
00770       t = Scalar(0.5)/t;
00771       q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
00772       q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
00773       q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
00774     }
00775   }
00776 };
00777 
00778 // set from a vector of coefficients assumed to be a quaternion
00779 template<typename Other>
00780 struct quaternionbase_assign_impl<Other,4,1>
00781 {
00782   typedef typename Other::Scalar Scalar;
00783   template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& vec)
00784   {
00785     q.coeffs() = vec;
00786   }
00787 };
00788 
00789 } // end namespace internal
00790 
00791 } // end namespace Eigen
00792 
00793 #endif // EIGEN_QUATERNION_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines