MOAB
4.9.3pre
|
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