cart-elc

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

Transform.h (61930B)


      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
      5 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
      6 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
      7 //
      8 // This Source Code Form is subject to the terms of the Mozilla
      9 // Public License v. 2.0. If a copy of the MPL was not distributed
     10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     11 
     12 #ifndef EIGEN_TRANSFORM_H
     13 #define EIGEN_TRANSFORM_H
     14 
     15 namespace Eigen {
     16 
     17 namespace internal {
     18 
     19 template<typename Transform>
     20 struct transform_traits
     21 {
     22   enum
     23   {
     24     Dim = Transform::Dim,
     25     HDim = Transform::HDim,
     26     Mode = Transform::Mode,
     27     IsProjective = (int(Mode)==int(Projective))
     28   };
     29 };
     30 
     31 template< typename TransformType,
     32           typename MatrixType,
     33           int Case = transform_traits<TransformType>::IsProjective ? 0
     34                    : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
     35                    : 2,
     36           int RhsCols = MatrixType::ColsAtCompileTime>
     37 struct transform_right_product_impl;
     38 
     39 template< typename Other,
     40           int Mode,
     41           int Options,
     42           int Dim,
     43           int HDim,
     44           int OtherRows=Other::RowsAtCompileTime,
     45           int OtherCols=Other::ColsAtCompileTime>
     46 struct transform_left_product_impl;
     47 
     48 template< typename Lhs,
     49           typename Rhs,
     50           bool AnyProjective =
     51             transform_traits<Lhs>::IsProjective ||
     52             transform_traits<Rhs>::IsProjective>
     53 struct transform_transform_product_impl;
     54 
     55 template< typename Other,
     56           int Mode,
     57           int Options,
     58           int Dim,
     59           int HDim,
     60           int OtherRows=Other::RowsAtCompileTime,
     61           int OtherCols=Other::ColsAtCompileTime>
     62 struct transform_construct_from_matrix;
     63 
     64 template<typename TransformType> struct transform_take_affine_part;
     65 
     66 template<typename _Scalar, int _Dim, int _Mode, int _Options>
     67 struct traits<Transform<_Scalar,_Dim,_Mode,_Options> >
     68 {
     69   typedef _Scalar Scalar;
     70   typedef Eigen::Index StorageIndex;
     71   typedef Dense StorageKind;
     72   enum {
     73     Dim1 = _Dim==Dynamic ? _Dim : _Dim + 1,
     74     RowsAtCompileTime = _Mode==Projective ? Dim1 : _Dim,
     75     ColsAtCompileTime = Dim1,
     76     MaxRowsAtCompileTime = RowsAtCompileTime,
     77     MaxColsAtCompileTime = ColsAtCompileTime,
     78     Flags = 0
     79   };
     80 };
     81 
     82 template<int Mode> struct transform_make_affine;
     83 
     84 } // end namespace internal
     85 
     86 /** \geometry_module \ingroup Geometry_Module
     87   *
     88   * \class Transform
     89   *
     90   * \brief Represents an homogeneous transformation in a N dimensional space
     91   *
     92   * \tparam _Scalar the scalar type, i.e., the type of the coefficients
     93   * \tparam _Dim the dimension of the space
     94   * \tparam _Mode the type of the transformation. Can be:
     95   *              - #Affine: the transformation is stored as a (Dim+1)^2 matrix,
     96   *                         where the last row is assumed to be [0 ... 0 1].
     97   *              - #AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix.
     98   *              - #Projective: the transformation is stored as a (Dim+1)^2 matrix
     99   *                             without any assumption.
    100   *              - #Isometry: same as #Affine with the additional assumption that
    101   *                           the linear part represents a rotation. This assumption is exploited
    102   *                           to speed up some functions such as inverse() and rotation().
    103   * \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor.
    104   *                  These Options are passed directly to the underlying matrix type.
    105   *
    106   * The homography is internally represented and stored by a matrix which
    107   * is available through the matrix() method. To understand the behavior of
    108   * this class you have to think a Transform object as its internal
    109   * matrix representation. The chosen convention is right multiply:
    110   *
    111   * \code v' = T * v \endcode
    112   *
    113   * Therefore, an affine transformation matrix M is shaped like this:
    114   *
    115   * \f$ \left( \begin{array}{cc}
    116   * linear & translation\\
    117   * 0 ... 0 & 1
    118   * \end{array} \right) \f$
    119   *
    120   * Note that for a projective transformation the last row can be anything,
    121   * and then the interpretation of different parts might be slightly different.
    122   *
    123   * However, unlike a plain matrix, the Transform class provides many features
    124   * simplifying both its assembly and usage. In particular, it can be composed
    125   * with any other transformations (Transform,Translation,RotationBase,DiagonalMatrix)
    126   * and can be directly used to transform implicit homogeneous vectors. All these
    127   * operations are handled via the operator*. For the composition of transformations,
    128   * its principle consists to first convert the right/left hand sides of the product
    129   * to a compatible (Dim+1)^2 matrix and then perform a pure matrix product.
    130   * Of course, internally, operator* tries to perform the minimal number of operations
    131   * according to the nature of each terms. Likewise, when applying the transform
    132   * to points, the latters are automatically promoted to homogeneous vectors
    133   * before doing the matrix product. The conventions to homogeneous representations
    134   * are performed as follow:
    135   *
    136   * \b Translation t (Dim)x(1):
    137   * \f$ \left( \begin{array}{cc}
    138   * I & t \\
    139   * 0\,...\,0 & 1
    140   * \end{array} \right) \f$
    141   *
    142   * \b Rotation R (Dim)x(Dim):
    143   * \f$ \left( \begin{array}{cc}
    144   * R & 0\\
    145   * 0\,...\,0 & 1
    146   * \end{array} \right) \f$
    147   *<!--
    148   * \b Linear \b Matrix L (Dim)x(Dim):
    149   * \f$ \left( \begin{array}{cc}
    150   * L & 0\\
    151   * 0\,...\,0 & 1
    152   * \end{array} \right) \f$
    153   *
    154   * \b Affine \b Matrix A (Dim)x(Dim+1):
    155   * \f$ \left( \begin{array}{c}
    156   * A\\
    157   * 0\,...\,0\,1
    158   * \end{array} \right) \f$
    159   *-->
    160   * \b Scaling \b DiagonalMatrix S (Dim)x(Dim):
    161   * \f$ \left( \begin{array}{cc}
    162   * S & 0\\
    163   * 0\,...\,0 & 1
    164   * \end{array} \right) \f$
    165   *
    166   * \b Column \b point v (Dim)x(1):
    167   * \f$ \left( \begin{array}{c}
    168   * v\\
    169   * 1
    170   * \end{array} \right) \f$
    171   *
    172   * \b Set \b of \b column \b points V1...Vn (Dim)x(n):
    173   * \f$ \left( \begin{array}{ccc}
    174   * v_1 & ... & v_n\\
    175   * 1 & ... & 1
    176   * \end{array} \right) \f$
    177   *
    178   * The concatenation of a Transform object with any kind of other transformation
    179   * always returns a Transform object.
    180   *
    181   * A little exception to the "as pure matrix product" rule is the case of the
    182   * transformation of non homogeneous vectors by an affine transformation. In
    183   * that case the last matrix row can be ignored, and the product returns non
    184   * homogeneous vectors.
    185   *
    186   * Since, for instance, a Dim x Dim matrix is interpreted as a linear transformation,
    187   * it is not possible to directly transform Dim vectors stored in a Dim x Dim matrix.
    188   * The solution is either to use a Dim x Dynamic matrix or explicitly request a
    189   * vector transformation by making the vector homogeneous:
    190   * \code
    191   * m' = T * m.colwise().homogeneous();
    192   * \endcode
    193   * Note that there is zero overhead.
    194   *
    195   * Conversion methods from/to Qt's QMatrix and QTransform are available if the
    196   * preprocessor token EIGEN_QT_SUPPORT is defined.
    197   *
    198   * This class can be extended with the help of the plugin mechanism described on the page
    199   * \ref TopicCustomizing_Plugins by defining the preprocessor symbol \c EIGEN_TRANSFORM_PLUGIN.
    200   *
    201   * \sa class Matrix, class Quaternion
    202   */
    203 template<typename _Scalar, int _Dim, int _Mode, int _Options>
    204 class Transform
    205 {
    206 public:
    207   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
    208   enum {
    209     Mode = _Mode,
    210     Options = _Options,
    211     Dim = _Dim,     ///< space dimension in which the transformation holds
    212     HDim = _Dim+1,  ///< size of a respective homogeneous vector
    213     Rows = int(Mode)==(AffineCompact) ? Dim : HDim
    214   };
    215   /** the scalar type of the coefficients */
    216   typedef _Scalar Scalar;
    217   typedef Eigen::Index StorageIndex;
    218   typedef Eigen::Index Index; ///< \deprecated since Eigen 3.3
    219   /** type of the matrix used to represent the transformation */
    220   typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
    221   /** constified MatrixType */
    222   typedef const MatrixType ConstMatrixType;
    223   /** type of the matrix used to represent the linear part of the transformation */
    224   typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
    225   /** type of read/write reference to the linear part of the transformation */
    226   typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (int(Options)&RowMajor)==0> LinearPart;
    227   /** type of read reference to the linear part of the transformation */
    228   typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (int(Options)&RowMajor)==0> ConstLinearPart;
    229   /** type of read/write reference to the affine part of the transformation */
    230   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
    231                               MatrixType&,
    232                               Block<MatrixType,Dim,HDim> >::type AffinePart;
    233   /** type of read reference to the affine part of the transformation */
    234   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
    235                               const MatrixType&,
    236                               const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
    237   /** type of a vector */
    238   typedef Matrix<Scalar,Dim,1> VectorType;
    239   /** type of a read/write reference to the translation part of the rotation */
    240   typedef Block<MatrixType,Dim,1,!(internal::traits<MatrixType>::Flags & RowMajorBit)> TranslationPart;
    241   /** type of a read reference to the translation part of the rotation */
    242   typedef const Block<ConstMatrixType,Dim,1,!(internal::traits<MatrixType>::Flags & RowMajorBit)> ConstTranslationPart;
    243   /** corresponding translation type */
    244   typedef Translation<Scalar,Dim> TranslationType;
    245 
    246   // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
    247   enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
    248   /** The return type of the product between a diagonal matrix and a transform */
    249   typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
    250 
    251 protected:
    252 
    253   MatrixType m_matrix;
    254 
    255 public:
    256 
    257   /** Default constructor without initialization of the meaningful coefficients.
    258     * If Mode==Affine or Mode==Isometry, then the last row is set to [0 ... 0 1] */
    259   EIGEN_DEVICE_FUNC inline Transform()
    260   {
    261     check_template_params();
    262     internal::transform_make_affine<(int(Mode)==Affine || int(Mode)==Isometry) ? Affine : AffineCompact>::run(m_matrix);
    263   }
    264 
    265   EIGEN_DEVICE_FUNC inline explicit Transform(const TranslationType& t)
    266   {
    267     check_template_params();
    268     *this = t;
    269   }
    270   EIGEN_DEVICE_FUNC inline explicit Transform(const UniformScaling<Scalar>& s)
    271   {
    272     check_template_params();
    273     *this = s;
    274   }
    275   template<typename Derived>
    276   EIGEN_DEVICE_FUNC inline explicit Transform(const RotationBase<Derived, Dim>& r)
    277   {
    278     check_template_params();
    279     *this = r;
    280   }
    281 
    282   typedef internal::transform_take_affine_part<Transform> take_affine_part;
    283 
    284   /** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
    285   template<typename OtherDerived>
    286   EIGEN_DEVICE_FUNC inline explicit Transform(const EigenBase<OtherDerived>& other)
    287   {
    288     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
    289       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
    290 
    291     check_template_params();
    292     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
    293   }
    294 
    295   /** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */
    296   template<typename OtherDerived>
    297   EIGEN_DEVICE_FUNC inline Transform& operator=(const EigenBase<OtherDerived>& other)
    298   {
    299     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
    300       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
    301 
    302     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
    303     return *this;
    304   }
    305 
    306   template<int OtherOptions>
    307   EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
    308   {
    309     check_template_params();
    310     // only the options change, we can directly copy the matrices
    311     m_matrix = other.matrix();
    312   }
    313 
    314   template<int OtherMode,int OtherOptions>
    315   EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
    316   {
    317     check_template_params();
    318     // prevent conversions as:
    319     // Affine | AffineCompact | Isometry = Projective
    320     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
    321                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
    322 
    323     // prevent conversions as:
    324     // Isometry = Affine | AffineCompact
    325     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
    326                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
    327 
    328     enum { ModeIsAffineCompact = Mode == int(AffineCompact),
    329            OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
    330     };
    331 
    332     if(EIGEN_CONST_CONDITIONAL(ModeIsAffineCompact == OtherModeIsAffineCompact))
    333     {
    334       // We need the block expression because the code is compiled for all
    335       // combinations of transformations and will trigger a compile time error
    336       // if one tries to assign the matrices directly
    337       m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
    338       makeAffine();
    339     }
    340     else if(EIGEN_CONST_CONDITIONAL(OtherModeIsAffineCompact))
    341     {
    342       typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
    343       internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
    344     }
    345     else
    346     {
    347       // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
    348       // if OtherMode were Projective, the static assert above would already have caught it.
    349       // So the only possibility is that OtherMode == Affine
    350       linear() = other.linear();
    351       translation() = other.translation();
    352     }
    353   }
    354 
    355   template<typename OtherDerived>
    356   EIGEN_DEVICE_FUNC Transform(const ReturnByValue<OtherDerived>& other)
    357   {
    358     check_template_params();
    359     other.evalTo(*this);
    360   }
    361 
    362   template<typename OtherDerived>
    363   EIGEN_DEVICE_FUNC Transform& operator=(const ReturnByValue<OtherDerived>& other)
    364   {
    365     other.evalTo(*this);
    366     return *this;
    367   }
    368 
    369   #ifdef EIGEN_QT_SUPPORT
    370   inline Transform(const QMatrix& other);
    371   inline Transform& operator=(const QMatrix& other);
    372   inline QMatrix toQMatrix(void) const;
    373   inline Transform(const QTransform& other);
    374   inline Transform& operator=(const QTransform& other);
    375   inline QTransform toQTransform(void) const;
    376   #endif
    377 
    378   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index rows() const EIGEN_NOEXCEPT { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
    379   EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR Index cols() const EIGEN_NOEXCEPT { return m_matrix.cols(); }
    380 
    381   /** shortcut for m_matrix(row,col);
    382     * \sa MatrixBase::operator(Index,Index) const */
    383   EIGEN_DEVICE_FUNC inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
    384   /** shortcut for m_matrix(row,col);
    385     * \sa MatrixBase::operator(Index,Index) */
    386   EIGEN_DEVICE_FUNC inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
    387 
    388   /** \returns a read-only expression of the transformation matrix */
    389   EIGEN_DEVICE_FUNC inline const MatrixType& matrix() const { return m_matrix; }
    390   /** \returns a writable expression of the transformation matrix */
    391   EIGEN_DEVICE_FUNC inline MatrixType& matrix() { return m_matrix; }
    392 
    393   /** \returns a read-only expression of the linear part of the transformation */
    394   EIGEN_DEVICE_FUNC inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
    395   /** \returns a writable expression of the linear part of the transformation */
    396   EIGEN_DEVICE_FUNC inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
    397 
    398   /** \returns a read-only expression of the Dim x HDim affine part of the transformation */
    399   EIGEN_DEVICE_FUNC inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
    400   /** \returns a writable expression of the Dim x HDim affine part of the transformation */
    401   EIGEN_DEVICE_FUNC inline AffinePart affine() { return take_affine_part::run(m_matrix); }
    402 
    403   /** \returns a read-only expression of the translation vector of the transformation */
    404   EIGEN_DEVICE_FUNC inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
    405   /** \returns a writable expression of the translation vector of the transformation */
    406   EIGEN_DEVICE_FUNC inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
    407 
    408   /** \returns an expression of the product between the transform \c *this and a matrix expression \a other.
    409     *
    410     * The right-hand-side \a other can be either:
    411     * \li an homogeneous vector of size Dim+1,
    412     * \li a set of homogeneous vectors of size Dim+1 x N,
    413     * \li a transformation matrix of size Dim+1 x Dim+1.
    414     *
    415     * Moreover, if \c *this represents an affine transformation (i.e., Mode!=Projective), then \a other can also be:
    416     * \li a point of size Dim (computes: \code this->linear() * other + this->translation()\endcode),
    417     * \li a set of N points as a Dim x N matrix (computes: \code (this->linear() * other).colwise() + this->translation()\endcode),
    418     *
    419     * In all cases, the return type is a matrix or vector of same sizes as the right-hand-side \a other.
    420     *
    421     * If you want to interpret \a other as a linear or affine transformation, then first convert it to a Transform<> type,
    422     * or do your own cooking.
    423     *
    424     * Finally, if you want to apply Affine transformations to vectors, then explicitly apply the linear part only:
    425     * \code
    426     * Affine3f A;
    427     * Vector3f v1, v2;
    428     * v2 = A.linear() * v1;
    429     * \endcode
    430     *
    431     */
    432   // note: this function is defined here because some compilers cannot find the respective declaration
    433   template<typename OtherDerived>
    434   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
    435   operator * (const EigenBase<OtherDerived> &other) const
    436   { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
    437 
    438   /** \returns the product expression of a transformation matrix \a a times a transform \a b
    439     *
    440     * The left hand side \a other can be either:
    441     * \li a linear transformation matrix of size Dim x Dim,
    442     * \li an affine transformation matrix of size Dim x Dim+1,
    443     * \li a general transformation matrix of size Dim+1 x Dim+1.
    444     */
    445   template<typename OtherDerived> friend
    446   EIGEN_DEVICE_FUNC inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
    447     operator * (const EigenBase<OtherDerived> &a, const Transform &b)
    448   { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
    449 
    450   /** \returns The product expression of a transform \a a times a diagonal matrix \a b
    451     *
    452     * The rhs diagonal matrix is interpreted as an affine scaling transformation. The
    453     * product results in a Transform of the same type (mode) as the lhs only if the lhs
    454     * mode is no isometry. In that case, the returned transform is an affinity.
    455     */
    456   template<typename DiagonalDerived>
    457   EIGEN_DEVICE_FUNC inline const TransformTimeDiagonalReturnType
    458     operator * (const DiagonalBase<DiagonalDerived> &b) const
    459   {
    460     TransformTimeDiagonalReturnType res(*this);
    461     res.linearExt() *= b;
    462     return res;
    463   }
    464 
    465   /** \returns The product expression of a diagonal matrix \a a times a transform \a b
    466     *
    467     * The lhs diagonal matrix is interpreted as an affine scaling transformation. The
    468     * product results in a Transform of the same type (mode) as the lhs only if the lhs
    469     * mode is no isometry. In that case, the returned transform is an affinity.
    470     */
    471   template<typename DiagonalDerived>
    472   EIGEN_DEVICE_FUNC friend inline TransformTimeDiagonalReturnType
    473     operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
    474   {
    475     TransformTimeDiagonalReturnType res;
    476     res.linear().noalias() = a*b.linear();
    477     res.translation().noalias() = a*b.translation();
    478     if (EIGEN_CONST_CONDITIONAL(Mode!=int(AffineCompact)))
    479       res.matrix().row(Dim) = b.matrix().row(Dim);
    480     return res;
    481   }
    482 
    483   template<typename OtherDerived>
    484   EIGEN_DEVICE_FUNC inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
    485 
    486   /** Concatenates two transformations */
    487   EIGEN_DEVICE_FUNC inline const Transform operator * (const Transform& other) const
    488   {
    489     return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
    490   }
    491 
    492   #if EIGEN_COMP_ICC
    493 private:
    494   // this intermediate structure permits to workaround a bug in ICC 11:
    495   //   error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
    496   //             (const Eigen::Transform<double, 3, 2, 0> &) const"
    497   //  (the meaning of a name may have changed since the template declaration -- the type of the template is:
    498   // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
    499   //     Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
    500   //
    501   template<int OtherMode,int OtherOptions> struct icc_11_workaround
    502   {
    503     typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType;
    504     typedef typename ProductType::ResultType ResultType;
    505   };
    506 
    507 public:
    508   /** Concatenates two different transformations */
    509   template<int OtherMode,int OtherOptions>
    510   inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
    511     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
    512   {
    513     typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
    514     return ProductType::run(*this,other);
    515   }
    516   #else
    517   /** Concatenates two different transformations */
    518   template<int OtherMode,int OtherOptions>
    519   EIGEN_DEVICE_FUNC inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
    520     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
    521   {
    522     return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
    523   }
    524   #endif
    525 
    526   /** \sa MatrixBase::setIdentity() */
    527   EIGEN_DEVICE_FUNC void setIdentity() { m_matrix.setIdentity(); }
    528 
    529   /**
    530    * \brief Returns an identity transformation.
    531    * \todo In the future this function should be returning a Transform expression.
    532    */
    533   EIGEN_DEVICE_FUNC static const Transform Identity()
    534   {
    535     return Transform(MatrixType::Identity());
    536   }
    537 
    538   template<typename OtherDerived>
    539   EIGEN_DEVICE_FUNC
    540   inline Transform& scale(const MatrixBase<OtherDerived> &other);
    541 
    542   template<typename OtherDerived>
    543   EIGEN_DEVICE_FUNC
    544   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
    545 
    546   EIGEN_DEVICE_FUNC inline Transform& scale(const Scalar& s);
    547   EIGEN_DEVICE_FUNC inline Transform& prescale(const Scalar& s);
    548 
    549   template<typename OtherDerived>
    550   EIGEN_DEVICE_FUNC
    551   inline Transform& translate(const MatrixBase<OtherDerived> &other);
    552 
    553   template<typename OtherDerived>
    554   EIGEN_DEVICE_FUNC
    555   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
    556 
    557   template<typename RotationType>
    558   EIGEN_DEVICE_FUNC
    559   inline Transform& rotate(const RotationType& rotation);
    560 
    561   template<typename RotationType>
    562   EIGEN_DEVICE_FUNC
    563   inline Transform& prerotate(const RotationType& rotation);
    564 
    565   EIGEN_DEVICE_FUNC Transform& shear(const Scalar& sx, const Scalar& sy);
    566   EIGEN_DEVICE_FUNC Transform& preshear(const Scalar& sx, const Scalar& sy);
    567 
    568   EIGEN_DEVICE_FUNC inline Transform& operator=(const TranslationType& t);
    569 
    570   EIGEN_DEVICE_FUNC
    571   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
    572 
    573   EIGEN_DEVICE_FUNC inline Transform operator*(const TranslationType& t) const;
    574 
    575   EIGEN_DEVICE_FUNC
    576   inline Transform& operator=(const UniformScaling<Scalar>& t);
    577 
    578   EIGEN_DEVICE_FUNC
    579   inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
    580 
    581   EIGEN_DEVICE_FUNC
    582   inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
    583   {
    584     TransformTimeDiagonalReturnType res = *this;
    585     res.scale(s.factor());
    586     return res;
    587   }
    588 
    589   EIGEN_DEVICE_FUNC
    590   inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linearExt() *= s; return *this; }
    591 
    592   template<typename Derived>
    593   EIGEN_DEVICE_FUNC inline Transform& operator=(const RotationBase<Derived,Dim>& r);
    594   template<typename Derived>
    595   EIGEN_DEVICE_FUNC inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
    596   template<typename Derived>
    597   EIGEN_DEVICE_FUNC inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
    598 
    599   typedef typename internal::conditional<int(Mode)==Isometry,ConstLinearPart,const LinearMatrixType>::type RotationReturnType;
    600   EIGEN_DEVICE_FUNC RotationReturnType rotation() const;
    601 
    602   template<typename RotationMatrixType, typename ScalingMatrixType>
    603   EIGEN_DEVICE_FUNC
    604   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
    605   template<typename ScalingMatrixType, typename RotationMatrixType>
    606   EIGEN_DEVICE_FUNC
    607   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
    608 
    609   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
    610   EIGEN_DEVICE_FUNC
    611   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
    612     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
    613 
    614   EIGEN_DEVICE_FUNC
    615   inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
    616 
    617   /** \returns a const pointer to the column major internal matrix */
    618   EIGEN_DEVICE_FUNC const Scalar* data() const { return m_matrix.data(); }
    619   /** \returns a non-const pointer to the column major internal matrix */
    620   EIGEN_DEVICE_FUNC Scalar* data() { return m_matrix.data(); }
    621 
    622   /** \returns \c *this with scalar type casted to \a NewScalarType
    623     *
    624     * Note that if \a NewScalarType is equal to the current scalar type of \c *this
    625     * then this function smartly returns a const reference to \c *this.
    626     */
    627   template<typename NewScalarType>
    628   EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
    629   { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
    630 
    631   /** Copy constructor with scalar type conversion */
    632   template<typename OtherScalarType>
    633   EIGEN_DEVICE_FUNC inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
    634   {
    635     check_template_params();
    636     m_matrix = other.matrix().template cast<Scalar>();
    637   }
    638 
    639   /** \returns \c true if \c *this is approximately equal to \a other, within the precision
    640     * determined by \a prec.
    641     *
    642     * \sa MatrixBase::isApprox() */
    643   EIGEN_DEVICE_FUNC bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
    644   { return m_matrix.isApprox(other.m_matrix, prec); }
    645 
    646   /** Sets the last row to [0 ... 0 1]
    647     */
    648   EIGEN_DEVICE_FUNC void makeAffine()
    649   {
    650     internal::transform_make_affine<int(Mode)>::run(m_matrix);
    651   }
    652 
    653   /** \internal
    654     * \returns the Dim x Dim linear part if the transformation is affine,
    655     *          and the HDim x Dim part for projective transformations.
    656     */
    657   EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
    658   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
    659   /** \internal
    660     * \returns the Dim x Dim linear part if the transformation is affine,
    661     *          and the HDim x Dim part for projective transformations.
    662     */
    663   EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
    664   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
    665 
    666   /** \internal
    667     * \returns the translation part if the transformation is affine,
    668     *          and the last column for projective transformations.
    669     */
    670   EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
    671   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
    672   /** \internal
    673     * \returns the translation part if the transformation is affine,
    674     *          and the last column for projective transformations.
    675     */
    676   EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
    677   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
    678 
    679 
    680   #ifdef EIGEN_TRANSFORM_PLUGIN
    681   #include EIGEN_TRANSFORM_PLUGIN
    682   #endif
    683 
    684 protected:
    685   #ifndef EIGEN_PARSED_BY_DOXYGEN
    686     EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void check_template_params()
    687     {
    688       EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
    689     }
    690   #endif
    691 
    692 };
    693 
    694 /** \ingroup Geometry_Module */
    695 typedef Transform<float,2,Isometry> Isometry2f;
    696 /** \ingroup Geometry_Module */
    697 typedef Transform<float,3,Isometry> Isometry3f;
    698 /** \ingroup Geometry_Module */
    699 typedef Transform<double,2,Isometry> Isometry2d;
    700 /** \ingroup Geometry_Module */
    701 typedef Transform<double,3,Isometry> Isometry3d;
    702 
    703 /** \ingroup Geometry_Module */
    704 typedef Transform<float,2,Affine> Affine2f;
    705 /** \ingroup Geometry_Module */
    706 typedef Transform<float,3,Affine> Affine3f;
    707 /** \ingroup Geometry_Module */
    708 typedef Transform<double,2,Affine> Affine2d;
    709 /** \ingroup Geometry_Module */
    710 typedef Transform<double,3,Affine> Affine3d;
    711 
    712 /** \ingroup Geometry_Module */
    713 typedef Transform<float,2,AffineCompact> AffineCompact2f;
    714 /** \ingroup Geometry_Module */
    715 typedef Transform<float,3,AffineCompact> AffineCompact3f;
    716 /** \ingroup Geometry_Module */
    717 typedef Transform<double,2,AffineCompact> AffineCompact2d;
    718 /** \ingroup Geometry_Module */
    719 typedef Transform<double,3,AffineCompact> AffineCompact3d;
    720 
    721 /** \ingroup Geometry_Module */
    722 typedef Transform<float,2,Projective> Projective2f;
    723 /** \ingroup Geometry_Module */
    724 typedef Transform<float,3,Projective> Projective3f;
    725 /** \ingroup Geometry_Module */
    726 typedef Transform<double,2,Projective> Projective2d;
    727 /** \ingroup Geometry_Module */
    728 typedef Transform<double,3,Projective> Projective3d;
    729 
    730 /**************************
    731 *** Optional QT support ***
    732 **************************/
    733 
    734 #ifdef EIGEN_QT_SUPPORT
    735 /** Initializes \c *this from a QMatrix assuming the dimension is 2.
    736   *
    737   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    738   */
    739 template<typename Scalar, int Dim, int Mode,int Options>
    740 Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
    741 {
    742   check_template_params();
    743   *this = other;
    744 }
    745 
    746 /** Set \c *this from a QMatrix assuming the dimension is 2.
    747   *
    748   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    749   */
    750 template<typename Scalar, int Dim, int Mode,int Options>
    751 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
    752 {
    753   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    754   if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
    755     m_matrix << other.m11(), other.m21(), other.dx(),
    756                 other.m12(), other.m22(), other.dy();
    757   else
    758     m_matrix << other.m11(), other.m21(), other.dx(),
    759                 other.m12(), other.m22(), other.dy(),
    760                 0, 0, 1;
    761   return *this;
    762 }
    763 
    764 /** \returns a QMatrix from \c *this assuming the dimension is 2.
    765   *
    766   * \warning this conversion might loss data if \c *this is not affine
    767   *
    768   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    769   */
    770 template<typename Scalar, int Dim, int Mode, int Options>
    771 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
    772 {
    773   check_template_params();
    774   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    775   return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
    776                  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
    777                  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
    778 }
    779 
    780 /** Initializes \c *this from a QTransform assuming the dimension is 2.
    781   *
    782   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    783   */
    784 template<typename Scalar, int Dim, int Mode,int Options>
    785 Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
    786 {
    787   check_template_params();
    788   *this = other;
    789 }
    790 
    791 /** Set \c *this from a QTransform assuming the dimension is 2.
    792   *
    793   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    794   */
    795 template<typename Scalar, int Dim, int Mode, int Options>
    796 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
    797 {
    798   check_template_params();
    799   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    800   if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
    801     m_matrix << other.m11(), other.m21(), other.dx(),
    802                 other.m12(), other.m22(), other.dy();
    803   else
    804     m_matrix << other.m11(), other.m21(), other.dx(),
    805                 other.m12(), other.m22(), other.dy(),
    806                 other.m13(), other.m23(), other.m33();
    807   return *this;
    808 }
    809 
    810 /** \returns a QTransform from \c *this assuming the dimension is 2.
    811   *
    812   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
    813   */
    814 template<typename Scalar, int Dim, int Mode, int Options>
    815 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
    816 {
    817   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    818   if (EIGEN_CONST_CONDITIONAL(Mode == int(AffineCompact)))
    819     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
    820                       m_matrix.coeff(0,1), m_matrix.coeff(1,1),
    821                       m_matrix.coeff(0,2), m_matrix.coeff(1,2));
    822   else
    823     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
    824                       m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
    825                       m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
    826 }
    827 #endif
    828 
    829 /*********************
    830 *** Procedural API ***
    831 *********************/
    832 
    833 /** Applies on the right the non uniform scale transformation represented
    834   * by the vector \a other to \c *this and returns a reference to \c *this.
    835   * \sa prescale()
    836   */
    837 template<typename Scalar, int Dim, int Mode, int Options>
    838 template<typename OtherDerived>
    839 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    840 Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
    841 {
    842   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
    843   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    844   linearExt().noalias() = (linearExt() * other.asDiagonal());
    845   return *this;
    846 }
    847 
    848 /** Applies on the right a uniform scale of a factor \a c to \c *this
    849   * and returns a reference to \c *this.
    850   * \sa prescale(Scalar)
    851   */
    852 template<typename Scalar, int Dim, int Mode, int Options>
    853 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
    854 {
    855   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    856   linearExt() *= s;
    857   return *this;
    858 }
    859 
    860 /** Applies on the left the non uniform scale transformation represented
    861   * by the vector \a other to \c *this and returns a reference to \c *this.
    862   * \sa scale()
    863   */
    864 template<typename Scalar, int Dim, int Mode, int Options>
    865 template<typename OtherDerived>
    866 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    867 Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
    868 {
    869   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
    870   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    871   affine().noalias() = (other.asDiagonal() * affine());
    872   return *this;
    873 }
    874 
    875 /** Applies on the left a uniform scale of a factor \a c to \c *this
    876   * and returns a reference to \c *this.
    877   * \sa scale(Scalar)
    878   */
    879 template<typename Scalar, int Dim, int Mode, int Options>
    880 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
    881 {
    882   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    883   m_matrix.template topRows<Dim>() *= s;
    884   return *this;
    885 }
    886 
    887 /** Applies on the right the translation matrix represented by the vector \a other
    888   * to \c *this and returns a reference to \c *this.
    889   * \sa pretranslate()
    890   */
    891 template<typename Scalar, int Dim, int Mode, int Options>
    892 template<typename OtherDerived>
    893 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    894 Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
    895 {
    896   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
    897   translationExt() += linearExt() * other;
    898   return *this;
    899 }
    900 
    901 /** Applies on the left the translation matrix represented by the vector \a other
    902   * to \c *this and returns a reference to \c *this.
    903   * \sa translate()
    904   */
    905 template<typename Scalar, int Dim, int Mode, int Options>
    906 template<typename OtherDerived>
    907 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    908 Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
    909 {
    910   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
    911   if(EIGEN_CONST_CONDITIONAL(int(Mode)==int(Projective)))
    912     affine() += other * m_matrix.row(Dim);
    913   else
    914     translation() += other;
    915   return *this;
    916 }
    917 
    918 /** Applies on the right the rotation represented by the rotation \a rotation
    919   * to \c *this and returns a reference to \c *this.
    920   *
    921   * The template parameter \a RotationType is the type of the rotation which
    922   * must be known by internal::toRotationMatrix<>.
    923   *
    924   * Natively supported types includes:
    925   *   - any scalar (2D),
    926   *   - a Dim x Dim matrix expression,
    927   *   - a Quaternion (3D),
    928   *   - a AngleAxis (3D)
    929   *
    930   * This mechanism is easily extendable to support user types such as Euler angles,
    931   * or a pair of Quaternion for 4D rotations.
    932   *
    933   * \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType)
    934   */
    935 template<typename Scalar, int Dim, int Mode, int Options>
    936 template<typename RotationType>
    937 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    938 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
    939 {
    940   linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
    941   return *this;
    942 }
    943 
    944 /** Applies on the left the rotation represented by the rotation \a rotation
    945   * to \c *this and returns a reference to \c *this.
    946   *
    947   * See rotate() for further details.
    948   *
    949   * \sa rotate()
    950   */
    951 template<typename Scalar, int Dim, int Mode, int Options>
    952 template<typename RotationType>
    953 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    954 Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
    955 {
    956   m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
    957                                          * m_matrix.template block<Dim,HDim>(0,0);
    958   return *this;
    959 }
    960 
    961 /** Applies on the right the shear transformation represented
    962   * by the vector \a other to \c *this and returns a reference to \c *this.
    963   * \warning 2D only.
    964   * \sa preshear()
    965   */
    966 template<typename Scalar, int Dim, int Mode, int Options>
    967 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    968 Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
    969 {
    970   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    971   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    972   VectorType tmp = linear().col(0)*sy + linear().col(1);
    973   linear() << linear().col(0) + linear().col(1)*sx, tmp;
    974   return *this;
    975 }
    976 
    977 /** Applies on the left the shear transformation represented
    978   * by the vector \a other to \c *this and returns a reference to \c *this.
    979   * \warning 2D only.
    980   * \sa shear()
    981   */
    982 template<typename Scalar, int Dim, int Mode, int Options>
    983 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
    984 Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
    985 {
    986   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
    987   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
    988   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
    989   return *this;
    990 }
    991 
    992 /******************************************************
    993 *** Scaling, Translation and Rotation compatibility ***
    994 ******************************************************/
    995 
    996 template<typename Scalar, int Dim, int Mode, int Options>
    997 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
    998 {
    999   linear().setIdentity();
   1000   translation() = t.vector();
   1001   makeAffine();
   1002   return *this;
   1003 }
   1004 
   1005 template<typename Scalar, int Dim, int Mode, int Options>
   1006 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
   1007 {
   1008   Transform res = *this;
   1009   res.translate(t.vector());
   1010   return res;
   1011 }
   1012 
   1013 template<typename Scalar, int Dim, int Mode, int Options>
   1014 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
   1015 {
   1016   m_matrix.setZero();
   1017   linear().diagonal().fill(s.factor());
   1018   makeAffine();
   1019   return *this;
   1020 }
   1021 
   1022 template<typename Scalar, int Dim, int Mode, int Options>
   1023 template<typename Derived>
   1024 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
   1025 {
   1026   linear() = internal::toRotationMatrix<Scalar,Dim>(r);
   1027   translation().setZero();
   1028   makeAffine();
   1029   return *this;
   1030 }
   1031 
   1032 template<typename Scalar, int Dim, int Mode, int Options>
   1033 template<typename Derived>
   1034 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
   1035 {
   1036   Transform res = *this;
   1037   res.rotate(r.derived());
   1038   return res;
   1039 }
   1040 
   1041 /************************
   1042 *** Special functions ***
   1043 ************************/
   1044 
   1045 namespace internal {
   1046 template<int Mode> struct transform_rotation_impl {
   1047   template<typename TransformType>
   1048   EIGEN_DEVICE_FUNC static inline
   1049   const typename TransformType::LinearMatrixType run(const TransformType& t)
   1050   {
   1051     typedef typename TransformType::LinearMatrixType LinearMatrixType;
   1052     LinearMatrixType result;
   1053     t.computeRotationScaling(&result, (LinearMatrixType*)0);
   1054     return result;
   1055   }
   1056 };
   1057 template<> struct transform_rotation_impl<Isometry> {
   1058   template<typename TransformType>
   1059   EIGEN_DEVICE_FUNC static inline
   1060   typename TransformType::ConstLinearPart run(const TransformType& t)
   1061   {
   1062     return t.linear();
   1063   }
   1064 };
   1065 }
   1066 /** \returns the rotation part of the transformation
   1067   *
   1068   * If Mode==Isometry, then this method is an alias for linear(),
   1069   * otherwise it calls computeRotationScaling() to extract the rotation
   1070   * through a SVD decomposition.
   1071   *
   1072   * \svd_module
   1073   *
   1074   * \sa computeRotationScaling(), computeScalingRotation(), class SVD
   1075   */
   1076 template<typename Scalar, int Dim, int Mode, int Options>
   1077 EIGEN_DEVICE_FUNC
   1078 typename Transform<Scalar,Dim,Mode,Options>::RotationReturnType
   1079 Transform<Scalar,Dim,Mode,Options>::rotation() const
   1080 {
   1081   return internal::transform_rotation_impl<Mode>::run(*this);
   1082 }
   1083 
   1084 
   1085 /** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
   1086   * not necessarily positive.
   1087   *
   1088   * If either pointer is zero, the corresponding computation is skipped.
   1089   *
   1090   *
   1091   *
   1092   * \svd_module
   1093   *
   1094   * \sa computeScalingRotation(), rotation(), class SVD
   1095   */
   1096 template<typename Scalar, int Dim, int Mode, int Options>
   1097 template<typename RotationMatrixType, typename ScalingMatrixType>
   1098 EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
   1099 {
   1100   // Note that JacobiSVD is faster than BDCSVD for small matrices.
   1101   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
   1102 
   1103   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant() < Scalar(0) ? Scalar(-1) : Scalar(1); // so x has absolute value 1
   1104   VectorType sv(svd.singularValues());
   1105   sv.coeffRef(Dim-1) *= x;
   1106   if(scaling) *scaling = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
   1107   if(rotation)
   1108   {
   1109     LinearMatrixType m(svd.matrixU());
   1110     m.col(Dim-1) *= x;
   1111     *rotation = m * svd.matrixV().adjoint();
   1112   }
   1113 }
   1114 
   1115 /** decomposes the linear part of the transformation as a product scaling x rotation, the scaling being
   1116   * not necessarily positive.
   1117   *
   1118   * If either pointer is zero, the corresponding computation is skipped.
   1119   *
   1120   *
   1121   *
   1122   * \svd_module
   1123   *
   1124   * \sa computeRotationScaling(), rotation(), class SVD
   1125   */
   1126 template<typename Scalar, int Dim, int Mode, int Options>
   1127 template<typename ScalingMatrixType, typename RotationMatrixType>
   1128 EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
   1129 {
   1130   // Note that JacobiSVD is faster than BDCSVD for small matrices.
   1131   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
   1132 
   1133   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant() < Scalar(0) ? Scalar(-1) : Scalar(1); // so x has absolute value 1
   1134   VectorType sv(svd.singularValues());
   1135   sv.coeffRef(Dim-1) *= x;
   1136   if(scaling) *scaling = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
   1137   if(rotation)
   1138   {
   1139     LinearMatrixType m(svd.matrixU());
   1140     m.col(Dim-1) *= x;
   1141     *rotation = m * svd.matrixV().adjoint();
   1142   }
   1143 }
   1144 
   1145 /** Convenient method to set \c *this from a position, orientation and scale
   1146   * of a 3D object.
   1147   */
   1148 template<typename Scalar, int Dim, int Mode, int Options>
   1149 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
   1150 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
   1151 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
   1152   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
   1153 {
   1154   linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
   1155   linear() *= scale.asDiagonal();
   1156   translation() = position;
   1157   makeAffine();
   1158   return *this;
   1159 }
   1160 
   1161 namespace internal {
   1162 
   1163 template<int Mode>
   1164 struct transform_make_affine
   1165 {
   1166   template<typename MatrixType>
   1167   EIGEN_DEVICE_FUNC static void run(MatrixType &mat)
   1168   {
   1169     static const int Dim = MatrixType::ColsAtCompileTime-1;
   1170     mat.template block<1,Dim>(Dim,0).setZero();
   1171     mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
   1172   }
   1173 };
   1174 
   1175 template<>
   1176 struct transform_make_affine<AffineCompact>
   1177 {
   1178   template<typename MatrixType> EIGEN_DEVICE_FUNC static void run(MatrixType &) { }
   1179 };
   1180 
   1181 // selector needed to avoid taking the inverse of a 3x4 matrix
   1182 template<typename TransformType, int Mode=TransformType::Mode>
   1183 struct projective_transform_inverse
   1184 {
   1185   EIGEN_DEVICE_FUNC static inline void run(const TransformType&, TransformType&)
   1186   {}
   1187 };
   1188 
   1189 template<typename TransformType>
   1190 struct projective_transform_inverse<TransformType, Projective>
   1191 {
   1192   EIGEN_DEVICE_FUNC static inline void run(const TransformType& m, TransformType& res)
   1193   {
   1194     res.matrix() = m.matrix().inverse();
   1195   }
   1196 };
   1197 
   1198 } // end namespace internal
   1199 
   1200 
   1201 /**
   1202   *
   1203   * \returns the inverse transformation according to some given knowledge
   1204   * on \c *this.
   1205   *
   1206   * \param hint allows to optimize the inversion process when the transformation
   1207   * is known to be not a general transformation (optional). The possible values are:
   1208   *  - #Projective if the transformation is not necessarily affine, i.e., if the
   1209   *    last row is not guaranteed to be [0 ... 0 1]
   1210   *  - #Affine if the last row can be assumed to be [0 ... 0 1]
   1211   *  - #Isometry if the transformation is only a concatenations of translations
   1212   *    and rotations.
   1213   *  The default is the template class parameter \c Mode.
   1214   *
   1215   * \warning unless \a traits is always set to NoShear or NoScaling, this function
   1216   * requires the generic inverse method of MatrixBase defined in the LU module. If
   1217   * you forget to include this module, then you will get hard to debug linking errors.
   1218   *
   1219   * \sa MatrixBase::inverse()
   1220   */
   1221 template<typename Scalar, int Dim, int Mode, int Options>
   1222 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>
   1223 Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
   1224 {
   1225   Transform res;
   1226   if (hint == Projective)
   1227   {
   1228     internal::projective_transform_inverse<Transform>::run(*this, res);
   1229   }
   1230   else
   1231   {
   1232     if (hint == Isometry)
   1233     {
   1234       res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
   1235     }
   1236     else if(hint&Affine)
   1237     {
   1238       res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
   1239     }
   1240     else
   1241     {
   1242       eigen_assert(false && "Invalid transform traits in Transform::Inverse");
   1243     }
   1244     // translation and remaining parts
   1245     res.matrix().template topRightCorner<Dim,1>()
   1246       = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
   1247     res.makeAffine(); // we do need this, because in the beginning res is uninitialized
   1248   }
   1249   return res;
   1250 }
   1251 
   1252 namespace internal {
   1253 
   1254 /*****************************************************
   1255 *** Specializations of take affine part            ***
   1256 *****************************************************/
   1257 
   1258 template<typename TransformType> struct transform_take_affine_part {
   1259   typedef typename TransformType::MatrixType MatrixType;
   1260   typedef typename TransformType::AffinePart AffinePart;
   1261   typedef typename TransformType::ConstAffinePart ConstAffinePart;
   1262   static inline AffinePart run(MatrixType& m)
   1263   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
   1264   static inline ConstAffinePart run(const MatrixType& m)
   1265   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
   1266 };
   1267 
   1268 template<typename Scalar, int Dim, int Options>
   1269 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
   1270   typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
   1271   static inline MatrixType& run(MatrixType& m) { return m; }
   1272   static inline const MatrixType& run(const MatrixType& m) { return m; }
   1273 };
   1274 
   1275 /*****************************************************
   1276 *** Specializations of construct from matrix       ***
   1277 *****************************************************/
   1278 
   1279 template<typename Other, int Mode, int Options, int Dim, int HDim>
   1280 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
   1281 {
   1282   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
   1283   {
   1284     transform->linear() = other;
   1285     transform->translation().setZero();
   1286     transform->makeAffine();
   1287   }
   1288 };
   1289 
   1290 template<typename Other, int Mode, int Options, int Dim, int HDim>
   1291 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
   1292 {
   1293   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
   1294   {
   1295     transform->affine() = other;
   1296     transform->makeAffine();
   1297   }
   1298 };
   1299 
   1300 template<typename Other, int Mode, int Options, int Dim, int HDim>
   1301 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
   1302 {
   1303   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
   1304   { transform->matrix() = other; }
   1305 };
   1306 
   1307 template<typename Other, int Options, int Dim, int HDim>
   1308 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
   1309 {
   1310   static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
   1311   { transform->matrix() = other.template block<Dim,HDim>(0,0); }
   1312 };
   1313 
   1314 /**********************************************************
   1315 ***   Specializations of operator* with rhs EigenBase   ***
   1316 **********************************************************/
   1317 
   1318 template<int LhsMode,int RhsMode>
   1319 struct transform_product_result
   1320 {
   1321   enum
   1322   {
   1323     Mode =
   1324       (LhsMode == (int)Projective    || RhsMode == (int)Projective    ) ? Projective :
   1325       (LhsMode == (int)Affine        || RhsMode == (int)Affine        ) ? Affine :
   1326       (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
   1327       (LhsMode == (int)Isometry      || RhsMode == (int)Isometry      ) ? Isometry : Projective
   1328   };
   1329 };
   1330 
   1331 template< typename TransformType, typename MatrixType, int RhsCols>
   1332 struct transform_right_product_impl< TransformType, MatrixType, 0, RhsCols>
   1333 {
   1334   typedef typename MatrixType::PlainObject ResultType;
   1335 
   1336   static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
   1337   {
   1338     return T.matrix() * other;
   1339   }
   1340 };
   1341 
   1342 template< typename TransformType, typename MatrixType, int RhsCols>
   1343 struct transform_right_product_impl< TransformType, MatrixType, 1, RhsCols>
   1344 {
   1345   enum {
   1346     Dim = TransformType::Dim,
   1347     HDim = TransformType::HDim,
   1348     OtherRows = MatrixType::RowsAtCompileTime,
   1349     OtherCols = MatrixType::ColsAtCompileTime
   1350   };
   1351 
   1352   typedef typename MatrixType::PlainObject ResultType;
   1353 
   1354   static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
   1355   {
   1356     EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
   1357 
   1358     typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
   1359 
   1360     ResultType res(other.rows(),other.cols());
   1361     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
   1362     res.row(OtherRows-1) = other.row(OtherRows-1);
   1363 
   1364     return res;
   1365   }
   1366 };
   1367 
   1368 template< typename TransformType, typename MatrixType, int RhsCols>
   1369 struct transform_right_product_impl< TransformType, MatrixType, 2, RhsCols>
   1370 {
   1371   enum {
   1372     Dim = TransformType::Dim,
   1373     HDim = TransformType::HDim,
   1374     OtherRows = MatrixType::RowsAtCompileTime,
   1375     OtherCols = MatrixType::ColsAtCompileTime
   1376   };
   1377 
   1378   typedef typename MatrixType::PlainObject ResultType;
   1379 
   1380   static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
   1381   {
   1382     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
   1383 
   1384     typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs;
   1385     ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
   1386     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
   1387 
   1388     return res;
   1389   }
   1390 };
   1391 
   1392 template< typename TransformType, typename MatrixType >
   1393 struct transform_right_product_impl< TransformType, MatrixType, 2, 1> // rhs is a vector of size Dim
   1394 {
   1395   typedef typename TransformType::MatrixType TransformMatrix;
   1396   enum {
   1397     Dim = TransformType::Dim,
   1398     HDim = TransformType::HDim,
   1399     OtherRows = MatrixType::RowsAtCompileTime,
   1400     WorkingRows = EIGEN_PLAIN_ENUM_MIN(TransformMatrix::RowsAtCompileTime,HDim)
   1401   };
   1402 
   1403   typedef typename MatrixType::PlainObject ResultType;
   1404 
   1405   static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
   1406   {
   1407     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
   1408 
   1409     Matrix<typename ResultType::Scalar, Dim+1, 1> rhs;
   1410     rhs.template head<Dim>() = other; rhs[Dim] = typename ResultType::Scalar(1);
   1411     Matrix<typename ResultType::Scalar, WorkingRows, 1> res(T.matrix() * rhs);
   1412     return res.template head<Dim>();
   1413   }
   1414 };
   1415 
   1416 /**********************************************************
   1417 ***   Specializations of operator* with lhs EigenBase   ***
   1418 **********************************************************/
   1419 
   1420 // generic HDim x HDim matrix * T => Projective
   1421 template<typename Other,int Mode, int Options, int Dim, int HDim>
   1422 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
   1423 {
   1424   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
   1425   typedef typename TransformType::MatrixType MatrixType;
   1426   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
   1427   static ResultType run(const Other& other,const TransformType& tr)
   1428   { return ResultType(other * tr.matrix()); }
   1429 };
   1430 
   1431 // generic HDim x HDim matrix * AffineCompact => Projective
   1432 template<typename Other, int Options, int Dim, int HDim>
   1433 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
   1434 {
   1435   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
   1436   typedef typename TransformType::MatrixType MatrixType;
   1437   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
   1438   static ResultType run(const Other& other,const TransformType& tr)
   1439   {
   1440     ResultType res;
   1441     res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
   1442     res.matrix().col(Dim) += other.col(Dim);
   1443     return res;
   1444   }
   1445 };
   1446 
   1447 // affine matrix * T
   1448 template<typename Other,int Mode, int Options, int Dim, int HDim>
   1449 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
   1450 {
   1451   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
   1452   typedef typename TransformType::MatrixType MatrixType;
   1453   typedef TransformType ResultType;
   1454   static ResultType run(const Other& other,const TransformType& tr)
   1455   {
   1456     ResultType res;
   1457     res.affine().noalias() = other * tr.matrix();
   1458     res.matrix().row(Dim) = tr.matrix().row(Dim);
   1459     return res;
   1460   }
   1461 };
   1462 
   1463 // affine matrix * AffineCompact
   1464 template<typename Other, int Options, int Dim, int HDim>
   1465 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
   1466 {
   1467   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
   1468   typedef typename TransformType::MatrixType MatrixType;
   1469   typedef TransformType ResultType;
   1470   static ResultType run(const Other& other,const TransformType& tr)
   1471   {
   1472     ResultType res;
   1473     res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
   1474     res.translation() += other.col(Dim);
   1475     return res;
   1476   }
   1477 };
   1478 
   1479 // linear matrix * T
   1480 template<typename Other,int Mode, int Options, int Dim, int HDim>
   1481 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
   1482 {
   1483   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
   1484   typedef typename TransformType::MatrixType MatrixType;
   1485   typedef TransformType ResultType;
   1486   static ResultType run(const Other& other, const TransformType& tr)
   1487   {
   1488     TransformType res;
   1489     if(Mode!=int(AffineCompact))
   1490       res.matrix().row(Dim) = tr.matrix().row(Dim);
   1491     res.matrix().template topRows<Dim>().noalias()
   1492       = other * tr.matrix().template topRows<Dim>();
   1493     return res;
   1494   }
   1495 };
   1496 
   1497 /**********************************************************
   1498 *** Specializations of operator* with another Transform ***
   1499 **********************************************************/
   1500 
   1501 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
   1502 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
   1503 {
   1504   enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
   1505   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
   1506   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
   1507   typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
   1508   static ResultType run(const Lhs& lhs, const Rhs& rhs)
   1509   {
   1510     ResultType res;
   1511     res.linear() = lhs.linear() * rhs.linear();
   1512     res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
   1513     res.makeAffine();
   1514     return res;
   1515   }
   1516 };
   1517 
   1518 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
   1519 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
   1520 {
   1521   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
   1522   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
   1523   typedef Transform<Scalar,Dim,Projective> ResultType;
   1524   static ResultType run(const Lhs& lhs, const Rhs& rhs)
   1525   {
   1526     return ResultType( lhs.matrix() * rhs.matrix() );
   1527   }
   1528 };
   1529 
   1530 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
   1531 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true >
   1532 {
   1533   typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs;
   1534   typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs;
   1535   typedef Transform<Scalar,Dim,Projective> ResultType;
   1536   static ResultType run(const Lhs& lhs, const Rhs& rhs)
   1537   {
   1538     ResultType res;
   1539     res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
   1540     res.matrix().row(Dim) = rhs.matrix().row(Dim);
   1541     return res;
   1542   }
   1543 };
   1544 
   1545 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
   1546 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true >
   1547 {
   1548   typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs;
   1549   typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs;
   1550   typedef Transform<Scalar,Dim,Projective> ResultType;
   1551   static ResultType run(const Lhs& lhs, const Rhs& rhs)
   1552   {
   1553     ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
   1554     res.matrix().col(Dim) += lhs.matrix().col(Dim);
   1555     return res;
   1556   }
   1557 };
   1558 
   1559 } // end namespace internal
   1560 
   1561 } // end namespace Eigen
   1562 
   1563 #endif // EIGEN_TRANSFORM_H