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