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