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