cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

Quaternion.h (34367B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
      5 // Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr>
      6 //
      7 // This Source Code Form is subject to the terms of the Mozilla
      8 // Public License v. 2.0. If a copy of the MPL was not distributed
      9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     10 
     11 #ifndef EIGEN_QUATERNION_H
     12 #define EIGEN_QUATERNION_H
     13 namespace Eigen { 
     14 
     15 
     16 /***************************************************************************
     17 * Definition of QuaternionBase<Derived>
     18 * The implementation is at the end of the file
     19 ***************************************************************************/
     20 
     21 namespace internal {
     22 template<typename Other,
     23          int OtherRows=Other::RowsAtCompileTime,
     24          int OtherCols=Other::ColsAtCompileTime>
     25 struct quaternionbase_assign_impl;
     26 }
     27 
     28 /** \geometry_module \ingroup Geometry_Module
     29   * \class QuaternionBase
     30   * \brief Base class for quaternion expressions
     31   * \tparam Derived derived type (CRTP)
     32   * \sa class Quaternion
     33   */
     34 template<class Derived>
     35 class QuaternionBase : public RotationBase<Derived, 3>
     36 {
     37  public:
     38   typedef RotationBase<Derived, 3> Base;
     39 
     40   using Base::operator*;
     41   using Base::derived;
     42 
     43   typedef typename internal::traits<Derived>::Scalar Scalar;
     44   typedef typename NumTraits<Scalar>::Real RealScalar;
     45   typedef typename internal::traits<Derived>::Coefficients Coefficients;
     46   typedef typename Coefficients::CoeffReturnType CoeffReturnType;
     47   typedef typename internal::conditional<bool(internal::traits<Derived>::Flags&LvalueBit),
     48                                         Scalar&, CoeffReturnType>::type NonConstCoeffReturnType;
     49 
     50 
     51   enum {
     52     Flags = Eigen::internal::traits<Derived>::Flags
     53   };
     54 
     55  // typedef typename Matrix<Scalar,4,1> Coefficients;
     56   /** the type of a 3D vector */
     57   typedef Matrix<Scalar,3,1> Vector3;
     58   /** the equivalent rotation matrix type */
     59   typedef Matrix<Scalar,3,3> Matrix3;
     60   /** the equivalent angle-axis type */
     61   typedef AngleAxis<Scalar> AngleAxisType;
     62 
     63 
     64 
     65   /** \returns the \c x coefficient */
     66   EIGEN_DEVICE_FUNC inline CoeffReturnType x() const { return this->derived().coeffs().coeff(0); }
     67   /** \returns the \c y coefficient */
     68   EIGEN_DEVICE_FUNC inline CoeffReturnType y() const { return this->derived().coeffs().coeff(1); }
     69   /** \returns the \c z coefficient */
     70   EIGEN_DEVICE_FUNC inline CoeffReturnType z() const { return this->derived().coeffs().coeff(2); }
     71   /** \returns the \c w coefficient */
     72   EIGEN_DEVICE_FUNC inline CoeffReturnType w() const { return this->derived().coeffs().coeff(3); }
     73 
     74   /** \returns a reference to the \c x coefficient (if Derived is a non-const lvalue) */
     75   EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType x() { return this->derived().coeffs().x(); }
     76   /** \returns a reference to the \c y coefficient (if Derived is a non-const lvalue) */
     77   EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType y() { return this->derived().coeffs().y(); }
     78   /** \returns a reference to the \c z coefficient (if Derived is a non-const lvalue) */
     79   EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType z() { return this->derived().coeffs().z(); }
     80   /** \returns a reference to the \c w coefficient (if Derived is a non-const lvalue) */
     81   EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType w() { return this->derived().coeffs().w(); }
     82 
     83   /** \returns a read-only vector expression of the imaginary part (x,y,z) */
     84   EIGEN_DEVICE_FUNC inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
     85 
     86   /** \returns a vector expression of the imaginary part (x,y,z) */
     87   EIGEN_DEVICE_FUNC inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
     88 
     89   /** \returns a read-only vector expression of the coefficients (x,y,z,w) */
     90   EIGEN_DEVICE_FUNC inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
     91 
     92   /** \returns a vector expression of the coefficients (x,y,z,w) */
     93   EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
     94 
     95   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
     96   template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
     97 
     98 // disabled this copy operator as it is giving very strange compilation errors when compiling
     99 // test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
    100 // useful; however notice that we already have the templated operator= above and e.g. in MatrixBase
    101 // we didn't have to add, in addition to templated operator=, such a non-templated copy operator.
    102 //  Derived& operator=(const QuaternionBase& other)
    103 //  { return operator=<Derived>(other); }
    104 
    105   EIGEN_DEVICE_FUNC Derived& operator=(const AngleAxisType& aa);
    106   template<class OtherDerived> EIGEN_DEVICE_FUNC Derived& operator=(const MatrixBase<OtherDerived>& m);
    107 
    108   /** \returns a quaternion representing an identity rotation
    109     * \sa MatrixBase::Identity()
    110     */
    111   EIGEN_DEVICE_FUNC static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
    112 
    113   /** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
    114     */
    115   EIGEN_DEVICE_FUNC inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
    116 
    117   /** \returns the squared norm of the quaternion's coefficients
    118     * \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
    119     */
    120   EIGEN_DEVICE_FUNC inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
    121 
    122   /** \returns the norm of the quaternion's coefficients
    123     * \sa QuaternionBase::squaredNorm(), MatrixBase::norm()
    124     */
    125   EIGEN_DEVICE_FUNC inline Scalar norm() const { return coeffs().norm(); }
    126 
    127   /** Normalizes the quaternion \c *this
    128     * \sa normalized(), MatrixBase::normalize() */
    129   EIGEN_DEVICE_FUNC inline void normalize() { coeffs().normalize(); }
    130   /** \returns a normalized copy of \c *this
    131     * \sa normalize(), MatrixBase::normalized() */
    132   EIGEN_DEVICE_FUNC inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
    133 
    134     /** \returns the dot product of \c *this and \a other
    135     * Geometrically speaking, the dot product of two unit quaternions
    136     * corresponds to the cosine of half the angle between the two rotations.
    137     * \sa angularDistance()
    138     */
    139   template<class OtherDerived> EIGEN_DEVICE_FUNC inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
    140 
    141   template<class OtherDerived> EIGEN_DEVICE_FUNC Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
    142 
    143   /** \returns an equivalent 3x3 rotation matrix */
    144   EIGEN_DEVICE_FUNC inline Matrix3 toRotationMatrix() const;
    145 
    146   /** \returns the quaternion which transform \a a into \a b through a rotation */
    147   template<typename Derived1, typename Derived2>
    148   EIGEN_DEVICE_FUNC Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
    149 
    150   template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
    151   template<class OtherDerived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
    152 
    153   /** \returns the quaternion describing the inverse rotation */
    154   EIGEN_DEVICE_FUNC Quaternion<Scalar> inverse() const;
    155 
    156   /** \returns the conjugated quaternion */
    157   EIGEN_DEVICE_FUNC Quaternion<Scalar> conjugate() const;
    158 
    159   template<class OtherDerived> EIGEN_DEVICE_FUNC Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
    160 
    161   /** \returns true if each coefficients of \c *this and \a other are all exactly equal.
    162     * \warning When using floating point scalar values you probably should rather use a
    163     *          fuzzy comparison such as isApprox()
    164     * \sa isApprox(), operator!= */
    165   template<class OtherDerived>
    166   EIGEN_DEVICE_FUNC inline bool operator==(const QuaternionBase<OtherDerived>& other) const
    167   { return coeffs() == other.coeffs(); }
    168 
    169   /** \returns true if at least one pair of coefficients of \c *this and \a other are not exactly equal to each other.
    170     * \warning When using floating point scalar values you probably should rather use a
    171     *          fuzzy comparison such as isApprox()
    172     * \sa isApprox(), operator== */
    173   template<class OtherDerived>
    174   EIGEN_DEVICE_FUNC inline bool operator!=(const QuaternionBase<OtherDerived>& other) const
    175   { return coeffs() != other.coeffs(); }
    176 
    177   /** \returns \c true if \c *this is approximately equal to \a other, within the precision
    178     * determined by \a prec.
    179     *
    180     * \sa MatrixBase::isApprox() */
    181   template<class OtherDerived>
    182   EIGEN_DEVICE_FUNC bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
    183   { return coeffs().isApprox(other.coeffs(), prec); }
    184 
    185   /** return the result vector of \a v through the rotation*/
    186   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
    187 
    188   #ifdef EIGEN_PARSED_BY_DOXYGEN
    189   /** \returns \c *this with scalar type casted to \a NewScalarType
    190     *
    191     * Note that if \a NewScalarType is equal to the current scalar type of \c *this
    192     * then this function smartly returns a const reference to \c *this.
    193     */
    194   template<typename NewScalarType>
    195   EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const;
    196 
    197   #else
    198 
    199   template<typename NewScalarType>
    200   EIGEN_DEVICE_FUNC inline
    201   typename internal::enable_if<internal::is_same<Scalar,NewScalarType>::value,const Derived&>::type cast() const
    202   {
    203     return derived();
    204   }
    205 
    206   template<typename NewScalarType>
    207   EIGEN_DEVICE_FUNC inline
    208   typename internal::enable_if<!internal::is_same<Scalar,NewScalarType>::value,Quaternion<NewScalarType> >::type cast() const
    209   {
    210     return Quaternion<NewScalarType>(coeffs().template cast<NewScalarType>());
    211   }
    212   #endif
    213 
    214 #ifndef EIGEN_NO_IO
    215   friend std::ostream& operator<<(std::ostream& s, const QuaternionBase<Derived>& q) {
    216     s << q.x() << "i + " << q.y() << "j + " << q.z() << "k" << " + " << q.w();
    217     return s;
    218   }
    219 #endif
    220 
    221 #ifdef EIGEN_QUATERNIONBASE_PLUGIN
    222 # include EIGEN_QUATERNIONBASE_PLUGIN
    223 #endif
    224 protected:
    225   EIGEN_DEFAULT_COPY_CONSTRUCTOR(QuaternionBase)
    226   EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(QuaternionBase)
    227 };
    228 
    229 /***************************************************************************
    230 * Definition/implementation of Quaternion<Scalar>
    231 ***************************************************************************/
    232 
    233 /** \geometry_module \ingroup Geometry_Module
    234   *
    235   * \class Quaternion
    236   *
    237   * \brief The quaternion class used to represent 3D orientations and rotations
    238   *
    239   * \tparam _Scalar the scalar type, i.e., the type of the coefficients
    240   * \tparam _Options controls the memory alignment of the coefficients. Can be \# AutoAlign or \# DontAlign. Default is AutoAlign.
    241   *
    242   * This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
    243   * orientations and rotations of objects in three dimensions. Compared to other representations
    244   * like Euler angles or 3x3 matrices, quaternions offer the following advantages:
    245   * \li \b compact storage (4 scalars)
    246   * \li \b efficient to compose (28 flops),
    247   * \li \b stable spherical interpolation
    248   *
    249   * The following two typedefs are provided for convenience:
    250   * \li \c Quaternionf for \c float
    251   * \li \c Quaterniond for \c double
    252   *
    253   * \warning Operations interpreting the quaternion as rotation have undefined behavior if the quaternion is not normalized.
    254   *
    255   * \sa  class AngleAxis, class Transform
    256   */
    257 
    258 namespace internal {
    259 template<typename _Scalar,int _Options>
    260 struct traits<Quaternion<_Scalar,_Options> >
    261 {
    262   typedef Quaternion<_Scalar,_Options> PlainObject;
    263   typedef _Scalar Scalar;
    264   typedef Matrix<_Scalar,4,1,_Options> Coefficients;
    265   enum{
    266     Alignment = internal::traits<Coefficients>::Alignment,
    267     Flags = LvalueBit
    268   };
    269 };
    270 }
    271 
    272 template<typename _Scalar, int _Options>
    273 class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
    274 {
    275 public:
    276   typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
    277   enum { NeedsAlignment = internal::traits<Quaternion>::Alignment>0 };
    278 
    279   typedef _Scalar Scalar;
    280 
    281   EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
    282   using Base::operator*=;
    283 
    284   typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
    285   typedef typename Base::AngleAxisType AngleAxisType;
    286 
    287   /** Default constructor leaving the quaternion uninitialized. */
    288   EIGEN_DEVICE_FUNC inline Quaternion() {}
    289 
    290   /** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
    291     * its four coefficients \a w, \a x, \a y and \a z.
    292     *
    293     * \warning Note the order of the arguments: the real \a w coefficient first,
    294     * while internally the coefficients are stored in the following order:
    295     * [\c x, \c y, \c z, \c w]
    296     */
    297   EIGEN_DEVICE_FUNC inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
    298 
    299   /** Constructs and initialize a quaternion from the array data */
    300   EIGEN_DEVICE_FUNC explicit inline Quaternion(const Scalar* data) : m_coeffs(data) {}
    301 
    302   /** Copy constructor */
    303   template<class Derived> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
    304 
    305   /** Constructs and initializes a quaternion from the angle-axis \a aa */
    306   EIGEN_DEVICE_FUNC explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
    307 
    308   /** Constructs and initializes a quaternion from either:
    309     *  - a rotation matrix expression,
    310     *  - a 4D vector expression representing quaternion coefficients.
    311     */
    312   template<typename Derived>
    313   EIGEN_DEVICE_FUNC explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
    314 
    315   /** Explicit copy constructor with scalar conversion */
    316   template<typename OtherScalar, int OtherOptions>
    317   EIGEN_DEVICE_FUNC explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
    318   { m_coeffs = other.coeffs().template cast<Scalar>(); }
    319 
    320 #if EIGEN_HAS_RVALUE_REFERENCES
    321   // We define a copy constructor, which means we don't get an implicit move constructor or assignment operator.
    322   /** Default move constructor */
    323   EIGEN_DEVICE_FUNC inline Quaternion(Quaternion&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_constructible<Scalar>::value)
    324     : m_coeffs(std::move(other.coeffs()))
    325   {}
    326 
    327   /** Default move assignment operator */
    328   EIGEN_DEVICE_FUNC Quaternion& operator=(Quaternion&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value)
    329   {
    330     m_coeffs = std::move(other.coeffs());
    331     return *this;
    332   }
    333 #endif
    334 
    335   EIGEN_DEVICE_FUNC static Quaternion UnitRandom();
    336 
    337   template<typename Derived1, typename Derived2>
    338   EIGEN_DEVICE_FUNC static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
    339 
    340   EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs;}
    341   EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs;}
    342 
    343   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(NeedsAlignment))
    344   
    345 #ifdef EIGEN_QUATERNION_PLUGIN
    346 # include EIGEN_QUATERNION_PLUGIN
    347 #endif
    348 
    349 protected:
    350   Coefficients m_coeffs;
    351   
    352 #ifndef EIGEN_PARSED_BY_DOXYGEN
    353     static EIGEN_STRONG_INLINE void _check_template_params()
    354     {
    355       EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options,
    356         INVALID_MATRIX_TEMPLATE_PARAMETERS)
    357     }
    358 #endif
    359 };
    360 
    361 /** \ingroup Geometry_Module
    362   * single precision quaternion type */
    363 typedef Quaternion<float> Quaternionf;
    364 /** \ingroup Geometry_Module
    365   * double precision quaternion type */
    366 typedef Quaternion<double> Quaterniond;
    367 
    368 /***************************************************************************
    369 * Specialization of Map<Quaternion<Scalar>>
    370 ***************************************************************************/
    371 
    372 namespace internal {
    373   template<typename _Scalar, int _Options>
    374   struct traits<Map<Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
    375   {
    376     typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
    377   };
    378 }
    379 
    380 namespace internal {
    381   template<typename _Scalar, int _Options>
    382   struct traits<Map<const Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
    383   {
    384     typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
    385     typedef traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> > TraitsBase;
    386     enum {
    387       Flags = TraitsBase::Flags & ~LvalueBit
    388     };
    389   };
    390 }
    391 
    392 /** \ingroup Geometry_Module
    393   * \brief Quaternion expression mapping a constant memory buffer
    394   *
    395   * \tparam _Scalar the type of the Quaternion coefficients
    396   * \tparam _Options see class Map
    397   *
    398   * This is a specialization of class Map for Quaternion. This class allows to view
    399   * a 4 scalar memory buffer as an Eigen's Quaternion object.
    400   *
    401   * \sa class Map, class Quaternion, class QuaternionBase
    402   */
    403 template<typename _Scalar, int _Options>
    404 class Map<const Quaternion<_Scalar>, _Options >
    405   : public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
    406 {
    407   public:
    408     typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
    409 
    410     typedef _Scalar Scalar;
    411     typedef typename internal::traits<Map>::Coefficients Coefficients;
    412     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
    413     using Base::operator*=;
    414 
    415     /** Constructs a Mapped Quaternion object from the pointer \a coeffs
    416       *
    417       * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
    418       * \code *coeffs == {x, y, z, w} \endcode
    419       *
    420       * If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
    421     EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
    422 
    423     EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs;}
    424 
    425   protected:
    426     const Coefficients m_coeffs;
    427 };
    428 
    429 /** \ingroup Geometry_Module
    430   * \brief Expression of a quaternion from a memory buffer
    431   *
    432   * \tparam _Scalar the type of the Quaternion coefficients
    433   * \tparam _Options see class Map
    434   *
    435   * This is a specialization of class Map for Quaternion. This class allows to view
    436   * a 4 scalar memory buffer as an Eigen's  Quaternion object.
    437   *
    438   * \sa class Map, class Quaternion, class QuaternionBase
    439   */
    440 template<typename _Scalar, int _Options>
    441 class Map<Quaternion<_Scalar>, _Options >
    442   : public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
    443 {
    444   public:
    445     typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
    446 
    447     typedef _Scalar Scalar;
    448     typedef typename internal::traits<Map>::Coefficients Coefficients;
    449     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
    450     using Base::operator*=;
    451 
    452     /** Constructs a Mapped Quaternion object from the pointer \a coeffs
    453       *
    454       * The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
    455       * \code *coeffs == {x, y, z, w} \endcode
    456       *
    457       * If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
    458     EIGEN_DEVICE_FUNC explicit EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
    459 
    460     EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return m_coeffs; }
    461     EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return m_coeffs; }
    462 
    463   protected:
    464     Coefficients m_coeffs;
    465 };
    466 
    467 /** \ingroup Geometry_Module
    468   * Map an unaligned array of single precision scalars as a quaternion */
    469 typedef Map<Quaternion<float>, 0>         QuaternionMapf;
    470 /** \ingroup Geometry_Module
    471   * Map an unaligned array of double precision scalars as a quaternion */
    472 typedef Map<Quaternion<double>, 0>        QuaternionMapd;
    473 /** \ingroup Geometry_Module
    474   * Map a 16-byte aligned array of single precision scalars as a quaternion */
    475 typedef Map<Quaternion<float>, Aligned>   QuaternionMapAlignedf;
    476 /** \ingroup Geometry_Module
    477   * Map a 16-byte aligned array of double precision scalars as a quaternion */
    478 typedef Map<Quaternion<double>, Aligned>  QuaternionMapAlignedd;
    479 
    480 /***************************************************************************
    481 * Implementation of QuaternionBase methods
    482 ***************************************************************************/
    483 
    484 // Generic Quaternion * Quaternion product
    485 // This product can be specialized for a given architecture via the Arch template argument.
    486 namespace internal {
    487 template<int Arch, class Derived1, class Derived2, typename Scalar> struct quat_product
    488 {
    489   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
    490     return Quaternion<Scalar>
    491     (
    492       a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
    493       a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
    494       a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
    495       a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
    496     );
    497   }
    498 };
    499 }
    500 
    501 /** \returns the concatenation of two rotations as a quaternion-quaternion product */
    502 template <class Derived>
    503 template <class OtherDerived>
    504 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
    505 QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
    506 {
    507   EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
    508    YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
    509   return internal::quat_product<Architecture::Target, Derived, OtherDerived,
    510                          typename internal::traits<Derived>::Scalar>::run(*this, other);
    511 }
    512 
    513 /** \sa operator*(Quaternion) */
    514 template <class Derived>
    515 template <class OtherDerived>
    516 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
    517 {
    518   derived() = derived() * other.derived();
    519   return derived();
    520 }
    521 
    522 /** Rotation of a vector by a quaternion.
    523   * \remarks If the quaternion is used to rotate several points (>1)
    524   * then it is much more efficient to first convert it to a 3x3 Matrix.
    525   * Comparison of the operation cost for n transformations:
    526   *   - Quaternion2:    30n
    527   *   - Via a Matrix3: 24 + 15n
    528   */
    529 template <class Derived>
    530 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
    531 QuaternionBase<Derived>::_transformVector(const Vector3& v) const
    532 {
    533     // Note that this algorithm comes from the optimization by hand
    534     // of the conversion to a Matrix followed by a Matrix/Vector product.
    535     // It appears to be much faster than the common algorithm found
    536     // in the literature (30 versus 39 flops). It also requires two
    537     // Vector3 as temporaries.
    538     Vector3 uv = this->vec().cross(v);
    539     uv += uv;
    540     return v + this->w() * uv + this->vec().cross(uv);
    541 }
    542 
    543 template<class Derived>
    544 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
    545 {
    546   coeffs() = other.coeffs();
    547   return derived();
    548 }
    549 
    550 template<class Derived>
    551 template<class OtherDerived>
    552 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
    553 {
    554   coeffs() = other.coeffs();
    555   return derived();
    556 }
    557 
    558 /** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
    559   */
    560 template<class Derived>
    561 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
    562 {
    563   EIGEN_USING_STD(cos)
    564   EIGEN_USING_STD(sin)
    565   Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
    566   this->w() = cos(ha);
    567   this->vec() = sin(ha) * aa.axis();
    568   return derived();
    569 }
    570 
    571 /** Set \c *this from the expression \a xpr:
    572   *   - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion
    573   *   - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
    574   *     and \a xpr is converted to a quaternion
    575   */
    576 
    577 template<class Derived>
    578 template<class MatrixDerived>
    579 EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
    580 {
    581   EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
    582    YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
    583   internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
    584   return derived();
    585 }
    586 
    587 /** Convert the quaternion to a 3x3 rotation matrix. The quaternion is required to
    588   * be normalized, otherwise the result is undefined.
    589   */
    590 template<class Derived>
    591 EIGEN_DEVICE_FUNC inline typename QuaternionBase<Derived>::Matrix3
    592 QuaternionBase<Derived>::toRotationMatrix(void) const
    593 {
    594   // NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
    595   // if not inlined then the cost of the return by value is huge ~ +35%,
    596   // however, not inlining this function is an order of magnitude slower, so
    597   // it has to be inlined, and so the return by value is not an issue
    598   Matrix3 res;
    599 
    600   const Scalar tx  = Scalar(2)*this->x();
    601   const Scalar ty  = Scalar(2)*this->y();
    602   const Scalar tz  = Scalar(2)*this->z();
    603   const Scalar twx = tx*this->w();
    604   const Scalar twy = ty*this->w();
    605   const Scalar twz = tz*this->w();
    606   const Scalar txx = tx*this->x();
    607   const Scalar txy = ty*this->x();
    608   const Scalar txz = tz*this->x();
    609   const Scalar tyy = ty*this->y();
    610   const Scalar tyz = tz*this->y();
    611   const Scalar tzz = tz*this->z();
    612 
    613   res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
    614   res.coeffRef(0,1) = txy-twz;
    615   res.coeffRef(0,2) = txz+twy;
    616   res.coeffRef(1,0) = txy+twz;
    617   res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
    618   res.coeffRef(1,2) = tyz-twx;
    619   res.coeffRef(2,0) = txz-twy;
    620   res.coeffRef(2,1) = tyz+twx;
    621   res.coeffRef(2,2) = Scalar(1)-(txx+tyy);
    622 
    623   return res;
    624 }
    625 
    626 /** Sets \c *this to be a quaternion representing a rotation between
    627   * the two arbitrary vectors \a a and \a b. In other words, the built
    628   * rotation represent a rotation sending the line of direction \a a
    629   * to the line of direction \a b, both lines passing through the origin.
    630   *
    631   * \returns a reference to \c *this.
    632   *
    633   * Note that the two input vectors do \b not have to be normalized, and
    634   * do not need to have the same norm.
    635   */
    636 template<class Derived>
    637 template<typename Derived1, typename Derived2>
    638 EIGEN_DEVICE_FUNC inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
    639 {
    640   EIGEN_USING_STD(sqrt)
    641   Vector3 v0 = a.normalized();
    642   Vector3 v1 = b.normalized();
    643   Scalar c = v1.dot(v0);
    644 
    645   // if dot == -1, vectors are nearly opposites
    646   // => accurately compute the rotation axis by computing the
    647   //    intersection of the two planes. This is done by solving:
    648   //       x^T v0 = 0
    649   //       x^T v1 = 0
    650   //    under the constraint:
    651   //       ||x|| = 1
    652   //    which yields a singular value problem
    653   if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
    654   {
    655     c = numext::maxi(c,Scalar(-1));
    656     Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
    657     JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
    658     Vector3 axis = svd.matrixV().col(2);
    659 
    660     Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
    661     this->w() = sqrt(w2);
    662     this->vec() = axis * sqrt(Scalar(1) - w2);
    663     return derived();
    664   }
    665   Vector3 axis = v0.cross(v1);
    666   Scalar s = sqrt((Scalar(1)+c)*Scalar(2));
    667   Scalar invs = Scalar(1)/s;
    668   this->vec() = axis * invs;
    669   this->w() = s * Scalar(0.5);
    670 
    671   return derived();
    672 }
    673 
    674 /** \returns a random unit quaternion following a uniform distribution law on SO(3)
    675   *
    676   * \note The implementation is based on http://planning.cs.uiuc.edu/node198.html
    677   */
    678 template<typename Scalar, int Options>
    679 EIGEN_DEVICE_FUNC Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UnitRandom()
    680 {
    681   EIGEN_USING_STD(sqrt)
    682   EIGEN_USING_STD(sin)
    683   EIGEN_USING_STD(cos)
    684   const Scalar u1 = internal::random<Scalar>(0, 1),
    685                u2 = internal::random<Scalar>(0, 2*EIGEN_PI),
    686                u3 = internal::random<Scalar>(0, 2*EIGEN_PI);
    687   const Scalar a = sqrt(Scalar(1) - u1),
    688                b = sqrt(u1);
    689   return Quaternion (a * sin(u2), a * cos(u2), b * sin(u3), b * cos(u3));
    690 }
    691 
    692 
    693 /** Returns a quaternion representing a rotation between
    694   * the two arbitrary vectors \a a and \a b. In other words, the built
    695   * rotation represent a rotation sending the line of direction \a a
    696   * to the line of direction \a b, both lines passing through the origin.
    697   *
    698   * \returns resulting quaternion
    699   *
    700   * Note that the two input vectors do \b not have to be normalized, and
    701   * do not need to have the same norm.
    702   */
    703 template<typename Scalar, int Options>
    704 template<typename Derived1, typename Derived2>
    705 EIGEN_DEVICE_FUNC Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
    706 {
    707     Quaternion quat;
    708     quat.setFromTwoVectors(a, b);
    709     return quat;
    710 }
    711 
    712 
    713 /** \returns the multiplicative inverse of \c *this
    714   * Note that in most cases, i.e., if you simply want the opposite rotation,
    715   * and/or the quaternion is normalized, then it is enough to use the conjugate.
    716   *
    717   * \sa QuaternionBase::conjugate()
    718   */
    719 template <class Derived>
    720 EIGEN_DEVICE_FUNC inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
    721 {
    722   // FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite()  ??
    723   Scalar n2 = this->squaredNorm();
    724   if (n2 > Scalar(0))
    725     return Quaternion<Scalar>(conjugate().coeffs() / n2);
    726   else
    727   {
    728     // return an invalid result to flag the error
    729     return Quaternion<Scalar>(Coefficients::Zero());
    730   }
    731 }
    732 
    733 // Generic conjugate of a Quaternion
    734 namespace internal {
    735 template<int Arch, class Derived, typename Scalar> struct quat_conj
    736 {
    737   EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived>& q){
    738     return Quaternion<Scalar>(q.w(),-q.x(),-q.y(),-q.z());
    739   }
    740 };
    741 }
    742                          
    743 /** \returns the conjugate of the \c *this which is equal to the multiplicative inverse
    744   * if the quaternion is normalized.
    745   * The conjugate of a quaternion represents the opposite rotation.
    746   *
    747   * \sa Quaternion2::inverse()
    748   */
    749 template <class Derived>
    750 EIGEN_DEVICE_FUNC inline Quaternion<typename internal::traits<Derived>::Scalar>
    751 QuaternionBase<Derived>::conjugate() const
    752 {
    753   return internal::quat_conj<Architecture::Target, Derived,
    754                          typename internal::traits<Derived>::Scalar>::run(*this);
    755                          
    756 }
    757 
    758 /** \returns the angle (in radian) between two rotations
    759   * \sa dot()
    760   */
    761 template <class Derived>
    762 template <class OtherDerived>
    763 EIGEN_DEVICE_FUNC inline typename internal::traits<Derived>::Scalar
    764 QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
    765 {
    766   EIGEN_USING_STD(atan2)
    767   Quaternion<Scalar> d = (*this) * other.conjugate();
    768   return Scalar(2) * atan2( d.vec().norm(), numext::abs(d.w()) );
    769 }
    770 
    771  
    772     
    773 /** \returns the spherical linear interpolation between the two quaternions
    774   * \c *this and \a other at the parameter \a t in [0;1].
    775   * 
    776   * This represents an interpolation for a constant motion between \c *this and \a other,
    777   * see also http://en.wikipedia.org/wiki/Slerp.
    778   */
    779 template <class Derived>
    780 template <class OtherDerived>
    781 EIGEN_DEVICE_FUNC Quaternion<typename internal::traits<Derived>::Scalar>
    782 QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
    783 {
    784   EIGEN_USING_STD(acos)
    785   EIGEN_USING_STD(sin)
    786   const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
    787   Scalar d = this->dot(other);
    788   Scalar absD = numext::abs(d);
    789 
    790   Scalar scale0;
    791   Scalar scale1;
    792 
    793   if(absD>=one)
    794   {
    795     scale0 = Scalar(1) - t;
    796     scale1 = t;
    797   }
    798   else
    799   {
    800     // theta is the angle between the 2 quaternions
    801     Scalar theta = acos(absD);
    802     Scalar sinTheta = sin(theta);
    803 
    804     scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
    805     scale1 = sin( ( t * theta) ) / sinTheta;
    806   }
    807   if(d<Scalar(0)) scale1 = -scale1;
    808 
    809   return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
    810 }
    811 
    812 namespace internal {
    813 
    814 // set from a rotation matrix
    815 template<typename Other>
    816 struct quaternionbase_assign_impl<Other,3,3>
    817 {
    818   typedef typename Other::Scalar Scalar;
    819   template<class Derived> EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& a_mat)
    820   {
    821     const typename internal::nested_eval<Other,2>::type mat(a_mat);
    822     EIGEN_USING_STD(sqrt)
    823     // This algorithm comes from  "Quaternion Calculus and Fast Animation",
    824     // Ken Shoemake, 1987 SIGGRAPH course notes
    825     Scalar t = mat.trace();
    826     if (t > Scalar(0))
    827     {
    828       t = sqrt(t + Scalar(1.0));
    829       q.w() = Scalar(0.5)*t;
    830       t = Scalar(0.5)/t;
    831       q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
    832       q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
    833       q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
    834     }
    835     else
    836     {
    837       Index i = 0;
    838       if (mat.coeff(1,1) > mat.coeff(0,0))
    839         i = 1;
    840       if (mat.coeff(2,2) > mat.coeff(i,i))
    841         i = 2;
    842       Index j = (i+1)%3;
    843       Index k = (j+1)%3;
    844 
    845       t = sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
    846       q.coeffs().coeffRef(i) = Scalar(0.5) * t;
    847       t = Scalar(0.5)/t;
    848       q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
    849       q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
    850       q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
    851     }
    852   }
    853 };
    854 
    855 // set from a vector of coefficients assumed to be a quaternion
    856 template<typename Other>
    857 struct quaternionbase_assign_impl<Other,4,1>
    858 {
    859   typedef typename Other::Scalar Scalar;
    860   template<class Derived> EIGEN_DEVICE_FUNC static inline void run(QuaternionBase<Derived>& q, const Other& vec)
    861   {
    862     q.coeffs() = vec;
    863   }
    864 };
    865 
    866 } // end namespace internal
    867 
    868 } // end namespace Eigen
    869 
    870 #endif // EIGEN_QUATERNION_H