00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef EIGEN_QUATERNION_H
00027 #define EIGEN_QUATERNION_H
00028
00029
00030
00031
00032
00033
00034 namespace internal {
00035 template<typename Other,
00036 int OtherRows=Other::RowsAtCompileTime,
00037 int OtherCols=Other::ColsAtCompileTime>
00038 struct quaternionbase_assign_impl;
00039 }
00040
00041 template<class Derived>
00042 class QuaternionBase : public RotationBase<Derived, 3>
00043 {
00044 typedef RotationBase<Derived, 3> Base;
00045 public:
00046 using Base::operator*;
00047 using Base::derived;
00048
00049 typedef typename internal::traits<Derived>::Scalar Scalar;
00050 typedef typename NumTraits<Scalar>::Real RealScalar;
00051 typedef typename internal::traits<Derived>::Coefficients Coefficients;
00052
00053
00055 typedef Matrix<Scalar,3,1> Vector3;
00057 typedef Matrix<Scalar,3,3> Matrix3;
00059 typedef AngleAxis<Scalar> AngleAxisType;
00060
00061
00062
00064 inline Scalar x() const { return this->derived().coeffs().coeff(0); }
00066 inline Scalar y() const { return this->derived().coeffs().coeff(1); }
00068 inline Scalar z() const { return this->derived().coeffs().coeff(2); }
00070 inline Scalar w() const { return this->derived().coeffs().coeff(3); }
00071
00073 inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
00075 inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
00077 inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
00079 inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
00080
00082 inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
00083
00085 inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
00086
00088 inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
00089
00091 inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
00092
00093 EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
00094 template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
00095
00096
00097
00098
00099
00100
00101
00102
00103 Derived& operator=(const AngleAxisType& aa);
00104 template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
00105
00109 inline static Quaternion<Scalar> Identity() { return Quaternion<Scalar>(1, 0, 0, 0); }
00110
00113 inline QuaternionBase& setIdentity() { coeffs() << 0, 0, 0, 1; return *this; }
00114
00118 inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
00119
00123 inline Scalar norm() const { return coeffs().norm(); }
00124
00127 inline void normalize() { coeffs().normalize(); }
00130 inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
00131
00137 template<class OtherDerived> inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
00138
00139 template<class OtherDerived> Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
00140
00142 Matrix3 toRotationMatrix() const;
00143
00145 template<typename Derived1, typename Derived2>
00146 Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
00147
00148 template<class OtherDerived> EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
00149 template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
00150
00152 Quaternion<Scalar> inverse() const;
00153
00155 Quaternion<Scalar> conjugate() const;
00156
00161 template<class OtherDerived> Quaternion<Scalar> slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const;
00162
00167 template<class OtherDerived>
00168 bool isApprox(const QuaternionBase<OtherDerived>& other, RealScalar prec = NumTraits<Scalar>::dummy_precision()) const
00169 { return coeffs().isApprox(other.coeffs(), prec); }
00170
00172 EIGEN_STRONG_INLINE Vector3 _transformVector(Vector3 v) const;
00173
00179 template<typename NewScalarType>
00180 inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
00181 {
00182 return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(
00183 coeffs().template cast<NewScalarType>());
00184 }
00185
00186 #ifdef EIGEN_QUATERNIONBASE_PLUGIN
00187 # include EIGEN_QUATERNIONBASE_PLUGIN
00188 #endif
00189 };
00190
00191
00192
00193
00194
00217 namespace internal {
00218 template<typename _Scalar,int _Options>
00219 struct traits<Quaternion<_Scalar,_Options> >
00220 {
00221 typedef Quaternion<_Scalar,_Options> PlainObject;
00222 typedef _Scalar Scalar;
00223 typedef Matrix<_Scalar,4,1,_Options> Coefficients;
00224 enum{
00225 PacketAccess = _Options & DontAlign ? Unaligned : Aligned
00226 };
00227 };
00228 }
00229
00230 template<typename _Scalar, int _Options>
00231 class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >{
00232 typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
00233 public:
00234 typedef _Scalar Scalar;
00235
00236 EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Quaternion)
00237 using Base::operator*=;
00238
00239 typedef typename internal::traits<Quaternion<Scalar,_Options> >::Coefficients Coefficients;
00240 typedef typename Base::AngleAxisType AngleAxisType;
00241
00243 inline Quaternion() {}
00244
00252 inline Quaternion(Scalar w, Scalar x, Scalar y, Scalar z) : m_coeffs(x, y, z, w){}
00253
00255 inline Quaternion(const Scalar* data) : m_coeffs(data) {}
00256
00258 template<class Derived> EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
00259
00261 explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
00262
00267 template<typename Derived>
00268 explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
00269
00270 inline Coefficients& coeffs() { return m_coeffs;}
00271 inline const Coefficients& coeffs() const { return m_coeffs;}
00272
00273 protected:
00274 Coefficients m_coeffs;
00275
00276 #ifndef EIGEN_PARSED_BY_DOXYGEN
00277 EIGEN_STRONG_INLINE static void _check_template_params()
00278 {
00279 EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options,
00280 INVALID_MATRIX_TEMPLATE_PARAMETERS)
00281 }
00282 #endif
00283 };
00284
00287 typedef Quaternion<float> Quaternionf;
00290 typedef Quaternion<double> Quaterniond;
00291
00292
00293
00294
00295
00296 namespace internal {
00297 template<typename _Scalar, int _PacketAccess>
00298 struct traits<Map<Quaternion<_Scalar>, _PacketAccess> >:
00299 traits<Quaternion<_Scalar> >
00300 {
00301 typedef _Scalar Scalar;
00302 typedef Map<Matrix<_Scalar,4,1>, _PacketAccess> Coefficients;
00303 enum {
00304 PacketAccess = _PacketAccess
00305 };
00306 };
00307 }
00308
00319 template<typename _Scalar, int PacketAccess>
00320 class Map<const Quaternion<_Scalar>, PacketAccess >
00321 : public QuaternionBase<Map<const Quaternion<_Scalar>, PacketAccess> >
00322 {
00323 typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
00324
00325 public:
00326 typedef _Scalar Scalar;
00327 typedef typename internal::traits<Map>::Coefficients Coefficients;
00328 EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
00329 using Base::operator*=;
00330
00337 EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
00338
00339 inline const Coefficients& coeffs() const { return m_coeffs;}
00340
00341 protected:
00342 const Coefficients m_coeffs;
00343 };
00344
00355 template<typename _Scalar, int PacketAccess>
00356 class Map<Quaternion<_Scalar>, PacketAccess >
00357 : public QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> >
00358 {
00359 typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
00360
00361 public:
00362 typedef _Scalar Scalar;
00363 typedef typename internal::traits<Map>::Coefficients Coefficients;
00364 EIGEN_INHERIT_ASSIGNMENT_EQUAL_OPERATOR(Map)
00365 using Base::operator*=;
00366
00373 EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
00374
00375 inline Coefficients& coeffs() { return m_coeffs; }
00376 inline const Coefficients& coeffs() const { return m_coeffs; }
00377
00378 protected:
00379 Coefficients m_coeffs;
00380 };
00381
00384 typedef Map<Quaternion<float>, 0> QuaternionMapf;
00387 typedef Map<Quaternion<double>, 0> QuaternionMapd;
00390 typedef Map<Quaternion<float>, Aligned> QuaternionMapAlignedf;
00393 typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
00394
00395
00396
00397
00398
00399
00400
00401 namespace internal {
00402 template<int Arch, class Derived1, class Derived2, typename Scalar, int PacketAccess> struct quat_product
00403 {
00404 EIGEN_STRONG_INLINE static Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
00405 return Quaternion<Scalar>
00406 (
00407 a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
00408 a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
00409 a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
00410 a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
00411 );
00412 }
00413 };
00414 }
00415
00417 template <class Derived>
00418 template <class OtherDerived>
00419 EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
00420 QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
00421 {
00422 EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
00423 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00424 return internal::quat_product<Architecture::Target, Derived, OtherDerived,
00425 typename internal::traits<Derived>::Scalar,
00426 internal::traits<Derived>::PacketAccess && internal::traits<OtherDerived>::PacketAccess>::run(*this, other);
00427 }
00428
00430 template <class Derived>
00431 template <class OtherDerived>
00432 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
00433 {
00434 derived() = derived() * other.derived();
00435 return derived();
00436 }
00437
00445 template <class Derived>
00446 EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
00447 QuaternionBase<Derived>::_transformVector(Vector3 v) const
00448 {
00449
00450
00451
00452
00453
00454 Vector3 uv = this->vec().cross(v);
00455 uv += uv;
00456 return v + this->w() * uv + this->vec().cross(uv);
00457 }
00458
00459 template<class Derived>
00460 EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
00461 {
00462 coeffs() = other.coeffs();
00463 return derived();
00464 }
00465
00466 template<class Derived>
00467 template<class OtherDerived>
00468 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
00469 {
00470 coeffs() = other.coeffs();
00471 return derived();
00472 }
00473
00476 template<class Derived>
00477 EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
00478 {
00479 Scalar ha = Scalar(0.5)*aa.angle();
00480 this->w() = internal::cos(ha);
00481 this->vec() = internal::sin(ha) * aa.axis();
00482 return derived();
00483 }
00484
00491 template<class Derived>
00492 template<class MatrixDerived>
00493 inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
00494 {
00495 EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
00496 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
00497 internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
00498 return derived();
00499 }
00500
00504 template<class Derived>
00505 inline typename QuaternionBase<Derived>::Matrix3
00506 QuaternionBase<Derived>::toRotationMatrix(void) const
00507 {
00508
00509
00510
00511
00512 Matrix3 res;
00513
00514 const Scalar tx = 2*this->x();
00515 const Scalar ty = 2*this->y();
00516 const Scalar tz = 2*this->z();
00517 const Scalar twx = tx*this->w();
00518 const Scalar twy = ty*this->w();
00519 const Scalar twz = tz*this->w();
00520 const Scalar txx = tx*this->x();
00521 const Scalar txy = ty*this->x();
00522 const Scalar txz = tz*this->x();
00523 const Scalar tyy = ty*this->y();
00524 const Scalar tyz = tz*this->y();
00525 const Scalar tzz = tz*this->z();
00526
00527 res.coeffRef(0,0) = 1-(tyy+tzz);
00528 res.coeffRef(0,1) = txy-twz;
00529 res.coeffRef(0,2) = txz+twy;
00530 res.coeffRef(1,0) = txy+twz;
00531 res.coeffRef(1,1) = 1-(txx+tzz);
00532 res.coeffRef(1,2) = tyz-twx;
00533 res.coeffRef(2,0) = txz-twy;
00534 res.coeffRef(2,1) = tyz+twx;
00535 res.coeffRef(2,2) = 1-(txx+tyy);
00536
00537 return res;
00538 }
00539
00550 template<class Derived>
00551 template<typename Derived1, typename Derived2>
00552 inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
00553 {
00554 Vector3 v0 = a.normalized();
00555 Vector3 v1 = b.normalized();
00556 Scalar c = v1.dot(v0);
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
00567 {
00568 c = std::max<Scalar>(c,-1);
00569 Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
00570 JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
00571 Vector3 axis = svd.matrixV().col(2);
00572
00573 Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
00574 this->w() = internal::sqrt(w2);
00575 this->vec() = axis * internal::sqrt(Scalar(1) - w2);
00576 return derived();
00577 }
00578 Vector3 axis = v0.cross(v1);
00579 Scalar s = internal::sqrt((Scalar(1)+c)*Scalar(2));
00580 Scalar invs = Scalar(1)/s;
00581 this->vec() = axis * invs;
00582 this->w() = s * Scalar(0.5);
00583
00584 return derived();
00585 }
00586
00593 template <class Derived>
00594 inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
00595 {
00596
00597 Scalar n2 = this->squaredNorm();
00598 if (n2 > 0)
00599 return Quaternion<Scalar>(conjugate().coeffs() / n2);
00600 else
00601 {
00602
00603 return Quaternion<Scalar>(Coefficients::Zero());
00604 }
00605 }
00606
00613 template <class Derived>
00614 inline Quaternion<typename internal::traits<Derived>::Scalar>
00615 QuaternionBase<Derived>::conjugate() const
00616 {
00617 return Quaternion<Scalar>(this->w(),-this->x(),-this->y(),-this->z());
00618 }
00619
00623 template <class Derived>
00624 template <class OtherDerived>
00625 inline typename internal::traits<Derived>::Scalar
00626 QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
00627 {
00628 double d = internal::abs(this->dot(other));
00629 if (d>=1.0)
00630 return Scalar(0);
00631 return static_cast<Scalar>(2 * std::acos(d));
00632 }
00633
00637 template <class Derived>
00638 template <class OtherDerived>
00639 Quaternion<typename internal::traits<Derived>::Scalar>
00640 QuaternionBase<Derived>::slerp(Scalar t, const QuaternionBase<OtherDerived>& other) const
00641 {
00642 static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
00643 Scalar d = this->dot(other);
00644 Scalar absD = internal::abs(d);
00645
00646 Scalar scale0;
00647 Scalar scale1;
00648
00649 if (absD>=one)
00650 {
00651 scale0 = Scalar(1) - t;
00652 scale1 = t;
00653 }
00654 else
00655 {
00656
00657 Scalar theta = std::acos(absD);
00658 Scalar sinTheta = internal::sin(theta);
00659
00660 scale0 = internal::sin( ( Scalar(1) - t ) * theta) / sinTheta;
00661 scale1 = internal::sin( ( t * theta) ) / sinTheta;
00662 if (d<0)
00663 scale1 = -scale1;
00664 }
00665
00666 return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
00667 }
00668
00669 namespace internal {
00670
00671
00672 template<typename Other>
00673 struct quaternionbase_assign_impl<Other,3,3>
00674 {
00675 typedef typename Other::Scalar Scalar;
00676 typedef DenseIndex Index;
00677 template<class Derived> inline static void run(QuaternionBase<Derived>& q, const Other& mat)
00678 {
00679
00680
00681 Scalar t = mat.trace();
00682 if (t > Scalar(0))
00683 {
00684 t = sqrt(t + Scalar(1.0));
00685 q.w() = Scalar(0.5)*t;
00686 t = Scalar(0.5)/t;
00687 q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
00688 q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
00689 q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
00690 }
00691 else
00692 {
00693 DenseIndex i = 0;
00694 if (mat.coeff(1,1) > mat.coeff(0,0))
00695 i = 1;
00696 if (mat.coeff(2,2) > mat.coeff(i,i))
00697 i = 2;
00698 DenseIndex j = (i+1)%3;
00699 DenseIndex k = (j+1)%3;
00700
00701 t = sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
00702 q.coeffs().coeffRef(i) = Scalar(0.5) * t;
00703 t = Scalar(0.5)/t;
00704 q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
00705 q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
00706 q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
00707 }
00708 }
00709 };
00710
00711
00712 template<typename Other>
00713 struct quaternionbase_assign_impl<Other,4,1>
00714 {
00715 typedef typename Other::Scalar Scalar;
00716 template<class Derived> inline static void run(QuaternionBase<Derived>& q, const Other& vec)
00717 {
00718 q.coeffs() = vec;
00719 }
00720 };
00721
00722 }
00723
00724 #endif // EIGEN_QUATERNION_H