Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / extern / Eigen2 / Eigen / src / Geometry / Transform.h
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra. Eigen itself is part of the KDE project.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
5 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6 //
7 // Eigen is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 3 of the License, or (at your option) any later version.
11 //
12 // Alternatively, you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License as
14 // published by the Free Software Foundation; either version 2 of
15 // the License, or (at your option) any later version.
16 //
17 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License and a copy of the GNU General Public License along with
24 // Eigen. If not, see <http://www.gnu.org/licenses/>.
25
26 #ifndef EIGEN_TRANSFORM_H
27 #define EIGEN_TRANSFORM_H
28
29 /** Represents some traits of a transformation */
30 enum TransformTraits {
31   Isometry,       ///< the transformation is a concatenation of translations and rotations
32   Affine,         ///< the transformation is affine (linear transformation + translation)
33   Projective      ///< the transformation might not be affine
34 };
35
36 // Note that we have to pass Dim and HDim because it is not allowed to use a template
37 // parameter to define a template specialization. To be more precise, in the following
38 // specializations, it is not allowed to use Dim+1 instead of HDim.
39 template< typename Other,
40           int Dim,
41           int HDim,
42           int OtherRows=Other::RowsAtCompileTime,
43           int OtherCols=Other::ColsAtCompileTime>
44 struct ei_transform_product_impl;
45
46 /** \geometry_module \ingroup Geometry_Module
47   *
48   * \class Transform
49   *
50   * \brief Represents an homogeneous transformation in a N dimensional space
51   *
52   * \param _Scalar the scalar type, i.e., the type of the coefficients
53   * \param _Dim the dimension of the space
54   *
55   * The homography is internally represented and stored as a (Dim+1)^2 matrix which
56   * is available through the matrix() method.
57   *
58   * Conversion methods from/to Qt's QMatrix and QTransform are available if the
59   * preprocessor token EIGEN_QT_SUPPORT is defined.
60   *
61   * \sa class Matrix, class Quaternion
62   */
63 template<typename _Scalar, int _Dim>
64 class Transform
65 {
66 public:
67   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
68   enum {
69     Dim = _Dim,     ///< space dimension in which the transformation holds
70     HDim = _Dim+1   ///< size of a respective homogeneous vector
71   };
72   /** the scalar type of the coefficients */
73   typedef _Scalar Scalar;
74   /** type of the matrix used to represent the transformation */
75   typedef Matrix<Scalar,HDim,HDim> MatrixType;
76   /** type of the matrix used to represent the linear part of the transformation */
77   typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
78   /** type of read/write reference to the linear part of the transformation */
79   typedef Block<MatrixType,Dim,Dim> LinearPart;
80   /** type of a vector */
81   typedef Matrix<Scalar,Dim,1> VectorType;
82   /** type of a read/write reference to the translation part of the rotation */
83   typedef Block<MatrixType,Dim,1> TranslationPart;
84   /** corresponding translation type */
85   typedef Translation<Scalar,Dim> TranslationType;
86   /** corresponding scaling transformation type */
87   typedef Scaling<Scalar,Dim> ScalingType;
88
89 protected:
90
91   MatrixType m_matrix;
92
93 public:
94
95   /** Default constructor without initialization of the coefficients. */
96   inline Transform() { }
97
98   inline Transform(const Transform& other)
99   {
100     m_matrix = other.m_matrix;
101   }
102
103   inline explicit Transform(const TranslationType& t) { *this = t; }
104   inline explicit Transform(const ScalingType& s) { *this = s; }
105   template<typename Derived>
106   inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
107
108   inline Transform& operator=(const Transform& other)
109   { m_matrix = other.m_matrix; return *this; }
110
111   template<typename OtherDerived, bool BigMatrix> // MSVC 2005 will commit suicide if BigMatrix has a default value
112   struct construct_from_matrix
113   {
114     static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
115     {
116       transform->matrix() = other;
117     }
118   };
119
120   template<typename OtherDerived> struct construct_from_matrix<OtherDerived, true>
121   {
122     static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
123     {
124       transform->linear() = other;
125       transform->translation().setZero();
126       transform->matrix()(Dim,Dim) = Scalar(1);
127       transform->matrix().template block<1,Dim>(Dim,0).setZero();
128     }
129   };
130
131   /** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */
132   template<typename OtherDerived>
133   inline explicit Transform(const MatrixBase<OtherDerived>& other)
134   {
135     construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
136   }
137
138   /** Set \c *this from a (Dim+1)^2 matrix. */
139   template<typename OtherDerived>
140   inline Transform& operator=(const MatrixBase<OtherDerived>& other)
141   { m_matrix = other; return *this; }
142
143   #ifdef EIGEN_QT_SUPPORT
144   inline Transform(const QMatrix& other);
145   inline Transform& operator=(const QMatrix& other);
146   inline QMatrix toQMatrix(void) const;
147   inline Transform(const QTransform& other);
148   inline Transform& operator=(const QTransform& other);
149   inline QTransform toQTransform(void) const;
150   #endif
151
152   /** shortcut for m_matrix(row,col);
153     * \sa MatrixBase::operaror(int,int) const */
154   inline Scalar operator() (int row, int col) const { return m_matrix(row,col); }
155   /** shortcut for m_matrix(row,col);
156     * \sa MatrixBase::operaror(int,int) */
157   inline Scalar& operator() (int row, int col) { return m_matrix(row,col); }
158
159   /** \returns a read-only expression of the transformation matrix */
160   inline const MatrixType& matrix() const { return m_matrix; }
161   /** \returns a writable expression of the transformation matrix */
162   inline MatrixType& matrix() { return m_matrix; }
163
164   /** \returns a read-only expression of the linear (linear) part of the transformation */
165   inline const LinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
166   /** \returns a writable expression of the linear (linear) part of the transformation */
167   inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
168
169   /** \returns a read-only expression of the translation vector of the transformation */
170   inline const TranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
171   /** \returns a writable expression of the translation vector of the transformation */
172   inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
173
174   /** \returns an expression of the product between the transform \c *this and a matrix expression \a other
175   *
176   * The right hand side \a other might be either:
177   * \li a vector of size Dim,
178   * \li an homogeneous vector of size Dim+1,
179   * \li a transformation matrix of size Dim+1 x Dim+1.
180   */
181   // note: this function is defined here because some compilers cannot find the respective declaration
182   template<typename OtherDerived>
183   inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
184   operator * (const MatrixBase<OtherDerived> &other) const
185   { return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
186
187   /** \returns the product expression of a transformation matrix \a a times a transform \a b
188     * The transformation matrix \a a must have a Dim+1 x Dim+1 sizes. */
189   template<typename OtherDerived>
190   friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
191   operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
192   { return a.derived() * b.matrix(); }
193
194   /** Contatenates two transformations */
195   inline const Transform
196   operator * (const Transform& other) const
197   { return Transform(m_matrix * other.matrix()); }
198
199   /** \sa MatrixBase::setIdentity() */
200   void setIdentity() { m_matrix.setIdentity(); }
201   static const typename MatrixType::IdentityReturnType Identity()
202   {
203     return MatrixType::Identity();
204   }
205
206   template<typename OtherDerived>
207   inline Transform& scale(const MatrixBase<OtherDerived> &other);
208
209   template<typename OtherDerived>
210   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
211
212   inline Transform& scale(Scalar s);
213   inline Transform& prescale(Scalar s);
214
215   template<typename OtherDerived>
216   inline Transform& translate(const MatrixBase<OtherDerived> &other);
217
218   template<typename OtherDerived>
219   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
220
221   template<typename RotationType>
222   inline Transform& rotate(const RotationType& rotation);
223
224   template<typename RotationType>
225   inline Transform& prerotate(const RotationType& rotation);
226
227   Transform& shear(Scalar sx, Scalar sy);
228   Transform& preshear(Scalar sx, Scalar sy);
229
230   inline Transform& operator=(const TranslationType& t);
231   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
232   inline Transform operator*(const TranslationType& t) const;
233
234   inline Transform& operator=(const ScalingType& t);
235   inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); }
236   inline Transform operator*(const ScalingType& s) const;
237   friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
238   {
239     Transform res = t;
240     res.matrix().row(Dim) = t.matrix().row(Dim);
241     res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
242     return res;
243   }
244
245   template<typename Derived>
246   inline Transform& operator=(const RotationBase<Derived,Dim>& r);
247   template<typename Derived>
248   inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
249   template<typename Derived>
250   inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
251
252   LinearMatrixType rotation() const;
253   template<typename RotationMatrixType, typename ScalingMatrixType>
254   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
255   template<typename ScalingMatrixType, typename RotationMatrixType>
256   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
257
258   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
259   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
260     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
261
262   inline const MatrixType inverse(TransformTraits traits = Affine) const;
263
264   /** \returns a const pointer to the column major internal matrix */
265   const Scalar* data() const { return m_matrix.data(); }
266   /** \returns a non-const pointer to the column major internal matrix */
267   Scalar* data() { return m_matrix.data(); }
268
269   /** \returns \c *this with scalar type casted to \a NewScalarType
270     *
271     * Note that if \a NewScalarType is equal to the current scalar type of \c *this
272     * then this function smartly returns a const reference to \c *this.
273     */
274   template<typename NewScalarType>
275   inline typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
276   { return typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
277
278   /** Copy constructor with scalar type conversion */
279   template<typename OtherScalarType>
280   inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
281   { m_matrix = other.matrix().template cast<Scalar>(); }
282
283   /** \returns \c true if \c *this is approximately equal to \a other, within the precision
284     * determined by \a prec.
285     *
286     * \sa MatrixBase::isApprox() */
287   bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
288   { return m_matrix.isApprox(other.m_matrix, prec); }
289
290   #ifdef EIGEN_TRANSFORM_PLUGIN
291   #include EIGEN_TRANSFORM_PLUGIN
292   #endif
293
294 protected:
295
296 };
297
298 /** \ingroup Geometry_Module */
299 typedef Transform<float,2> Transform2f;
300 /** \ingroup Geometry_Module */
301 typedef Transform<float,3> Transform3f;
302 /** \ingroup Geometry_Module */
303 typedef Transform<double,2> Transform2d;
304 /** \ingroup Geometry_Module */
305 typedef Transform<double,3> Transform3d;
306
307 /**************************
308 *** Optional QT support ***
309 **************************/
310
311 #ifdef EIGEN_QT_SUPPORT
312 /** Initialises \c *this from a QMatrix assuming the dimension is 2.
313   *
314   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
315   */
316 template<typename Scalar, int Dim>
317 Transform<Scalar,Dim>::Transform(const QMatrix& other)
318 {
319   *this = other;
320 }
321
322 /** Set \c *this from a QMatrix assuming the dimension is 2.
323   *
324   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
325   */
326 template<typename Scalar, int Dim>
327 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
328 {
329   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
330   m_matrix << other.m11(), other.m21(), other.dx(),
331               other.m12(), other.m22(), other.dy(),
332               0, 0, 1;
333    return *this;
334 }
335
336 /** \returns a QMatrix from \c *this assuming the dimension is 2.
337   *
338   * \warning this convertion might loss data if \c *this is not affine
339   *
340   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
341   */
342 template<typename Scalar, int Dim>
343 QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
344 {
345   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
346   return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
347                  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
348                  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
349 }
350
351 /** Initialises \c *this from a QTransform assuming the dimension is 2.
352   *
353   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
354   */
355 template<typename Scalar, int Dim>
356 Transform<Scalar,Dim>::Transform(const QTransform& other)
357 {
358   *this = other;
359 }
360
361 /** Set \c *this from a QTransform assuming the dimension is 2.
362   *
363   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
364   */
365 template<typename Scalar, int Dim>
366 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
367 {
368   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
369   m_matrix << other.m11(), other.m21(), other.dx(),
370               other.m12(), other.m22(), other.dy(),
371               other.m13(), other.m23(), other.m33();
372    return *this;
373 }
374
375 /** \returns a QTransform from \c *this assuming the dimension is 2.
376   *
377   * This function is available only if the token EIGEN_QT_SUPPORT is defined.
378   */
379 template<typename Scalar, int Dim>
380 QTransform Transform<Scalar,Dim>::toQTransform(void) const
381 {
382   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
383   return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
384                     m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
385                     m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
386 }
387 #endif
388
389 /*********************
390 *** Procedural API ***
391 *********************/
392
393 /** Applies on the right the non uniform scale transformation represented
394   * by the vector \a other to \c *this and returns a reference to \c *this.
395   * \sa prescale()
396   */
397 template<typename Scalar, int Dim>
398 template<typename OtherDerived>
399 Transform<Scalar,Dim>&
400 Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
401 {
402   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
403   linear() = (linear() * other.asDiagonal()).lazy();
404   return *this;
405 }
406
407 /** Applies on the right a uniform scale of a factor \a c to \c *this
408   * and returns a reference to \c *this.
409   * \sa prescale(Scalar)
410   */
411 template<typename Scalar, int Dim>
412 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::scale(Scalar s)
413 {
414   linear() *= s;
415   return *this;
416 }
417
418 /** Applies on the left the non uniform scale transformation represented
419   * by the vector \a other to \c *this and returns a reference to \c *this.
420   * \sa scale()
421   */
422 template<typename Scalar, int Dim>
423 template<typename OtherDerived>
424 Transform<Scalar,Dim>&
425 Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
426 {
427   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
428   m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
429   return *this;
430 }
431
432 /** Applies on the left a uniform scale of a factor \a c to \c *this
433   * and returns a reference to \c *this.
434   * \sa scale(Scalar)
435   */
436 template<typename Scalar, int Dim>
437 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::prescale(Scalar s)
438 {
439   m_matrix.template corner<Dim,HDim>(TopLeft) *= s;
440   return *this;
441 }
442
443 /** Applies on the right the translation matrix represented by the vector \a other
444   * to \c *this and returns a reference to \c *this.
445   * \sa pretranslate()
446   */
447 template<typename Scalar, int Dim>
448 template<typename OtherDerived>
449 Transform<Scalar,Dim>&
450 Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
451 {
452   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
453   translation() += linear() * other;
454   return *this;
455 }
456
457 /** Applies on the left the translation matrix represented by the vector \a other
458   * to \c *this and returns a reference to \c *this.
459   * \sa translate()
460   */
461 template<typename Scalar, int Dim>
462 template<typename OtherDerived>
463 Transform<Scalar,Dim>&
464 Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
465 {
466   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
467   translation() += other;
468   return *this;
469 }
470
471 /** Applies on the right the rotation represented by the rotation \a rotation
472   * to \c *this and returns a reference to \c *this.
473   *
474   * The template parameter \a RotationType is the type of the rotation which
475   * must be known by ei_toRotationMatrix<>.
476   *
477   * Natively supported types includes:
478   *   - any scalar (2D),
479   *   - a Dim x Dim matrix expression,
480   *   - a Quaternion (3D),
481   *   - a AngleAxis (3D)
482   *
483   * This mechanism is easily extendable to support user types such as Euler angles,
484   * or a pair of Quaternion for 4D rotations.
485   *
486   * \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType)
487   */
488 template<typename Scalar, int Dim>
489 template<typename RotationType>
490 Transform<Scalar,Dim>&
491 Transform<Scalar,Dim>::rotate(const RotationType& rotation)
492 {
493   linear() *= ei_toRotationMatrix<Scalar,Dim>(rotation);
494   return *this;
495 }
496
497 /** Applies on the left the rotation represented by the rotation \a rotation
498   * to \c *this and returns a reference to \c *this.
499   *
500   * See rotate() for further details.
501   *
502   * \sa rotate()
503   */
504 template<typename Scalar, int Dim>
505 template<typename RotationType>
506 Transform<Scalar,Dim>&
507 Transform<Scalar,Dim>::prerotate(const RotationType& rotation)
508 {
509   m_matrix.template block<Dim,HDim>(0,0) = ei_toRotationMatrix<Scalar,Dim>(rotation)
510                                          * m_matrix.template block<Dim,HDim>(0,0);
511   return *this;
512 }
513
514 /** Applies on the right the shear transformation represented
515   * by the vector \a other to \c *this and returns a reference to \c *this.
516   * \warning 2D only.
517   * \sa preshear()
518   */
519 template<typename Scalar, int Dim>
520 Transform<Scalar,Dim>&
521 Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
522 {
523   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
524   VectorType tmp = linear().col(0)*sy + linear().col(1);
525   linear() << linear().col(0) + linear().col(1)*sx, tmp;
526   return *this;
527 }
528
529 /** Applies on the left the shear transformation represented
530   * by the vector \a other to \c *this and returns a reference to \c *this.
531   * \warning 2D only.
532   * \sa shear()
533   */
534 template<typename Scalar, int Dim>
535 Transform<Scalar,Dim>&
536 Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
537 {
538   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
539   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
540   return *this;
541 }
542
543 /******************************************************
544 *** Scaling, Translation and Rotation compatibility ***
545 ******************************************************/
546
547 template<typename Scalar, int Dim>
548 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
549 {
550   linear().setIdentity();
551   translation() = t.vector();
552   m_matrix.template block<1,Dim>(Dim,0).setZero();
553   m_matrix(Dim,Dim) = Scalar(1);
554   return *this;
555 }
556
557 template<typename Scalar, int Dim>
558 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const
559 {
560   Transform res = *this;
561   res.translate(t.vector());
562   return res;
563 }
564
565 template<typename Scalar, int Dim>
566 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s)
567 {
568   m_matrix.setZero();
569   linear().diagonal() = s.coeffs();
570   m_matrix.coeffRef(Dim,Dim) = Scalar(1);
571   return *this;
572 }
573
574 template<typename Scalar, int Dim>
575 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const
576 {
577   Transform res = *this;
578   res.scale(s.coeffs());
579   return res;
580 }
581
582 template<typename Scalar, int Dim>
583 template<typename Derived>
584 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
585 {
586   linear() = ei_toRotationMatrix<Scalar,Dim>(r);
587   translation().setZero();
588   m_matrix.template block<1,Dim>(Dim,0).setZero();
589   m_matrix.coeffRef(Dim,Dim) = Scalar(1);
590   return *this;
591 }
592
593 template<typename Scalar, int Dim>
594 template<typename Derived>
595 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
596 {
597   Transform res = *this;
598   res.rotate(r.derived());
599   return res;
600 }
601
602 /************************
603 *** Special functions ***
604 ************************/
605
606 /** \returns the rotation part of the transformation
607   * \nonstableyet
608   *
609   * \svd_module
610   *
611   * \sa computeRotationScaling(), computeScalingRotation(), class SVD
612   */
613 template<typename Scalar, int Dim>
614 typename Transform<Scalar,Dim>::LinearMatrixType
615 Transform<Scalar,Dim>::rotation() const
616 {
617   LinearMatrixType result;
618   computeRotationScaling(&result, (LinearMatrixType*)0);
619   return result;
620 }
621
622
623 /** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
624   * not necessarily positive.
625   *
626   * If either pointer is zero, the corresponding computation is skipped.
627   *
628   * \nonstableyet
629   *
630   * \svd_module
631   *
632   * \sa computeScalingRotation(), rotation(), class SVD
633   */
634 template<typename Scalar, int Dim>
635 template<typename RotationMatrixType, typename ScalingMatrixType>
636 void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
637 {
638   linear().svd().computeRotationScaling(rotation, scaling);
639 }
640
641 /** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being
642   * not necessarily positive.
643   *
644   * If either pointer is zero, the corresponding computation is skipped.
645   *
646   * \nonstableyet
647   *
648   * \svd_module
649   *
650   * \sa computeRotationScaling(), rotation(), class SVD
651   */
652 template<typename Scalar, int Dim>
653 template<typename ScalingMatrixType, typename RotationMatrixType>
654 void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
655 {
656   linear().svd().computeScalingRotation(scaling, rotation);
657 }
658
659 /** Convenient method to set \c *this from a position, orientation and scale
660   * of a 3D object.
661   */
662 template<typename Scalar, int Dim>
663 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
664 Transform<Scalar,Dim>&
665 Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
666   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
667 {
668   linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
669   linear() *= scale.asDiagonal();
670   translation() = position;
671   m_matrix.template block<1,Dim>(Dim,0).setZero();
672   m_matrix(Dim,Dim) = Scalar(1);
673   return *this;
674 }
675
676 /** \nonstableyet
677   *
678   * \returns the inverse transformation matrix according to some given knowledge
679   * on \c *this.
680   *
681   * \param traits allows to optimize the inversion process when the transformion
682   * is known to be not a general transformation. The possible values are:
683   *  - Projective if the transformation is not necessarily affine, i.e., if the
684   *    last row is not guaranteed to be [0 ... 0 1]
685   *  - Affine is the default, the last row is assumed to be [0 ... 0 1]
686   *  - Isometry if the transformation is only a concatenations of translations
687   *    and rotations.
688   *
689   * \warning unless \a traits is always set to NoShear or NoScaling, this function
690   * requires the generic inverse method of MatrixBase defined in the LU module. If
691   * you forget to include this module, then you will get hard to debug linking errors.
692   *
693   * \sa MatrixBase::inverse()
694   */
695 template<typename Scalar, int Dim>
696 inline const typename Transform<Scalar,Dim>::MatrixType
697 Transform<Scalar,Dim>::inverse(TransformTraits traits) const
698 {
699   if (traits == Projective)
700   {
701     return m_matrix.inverse();
702   }
703   else
704   {
705     MatrixType res;
706     if (traits == Affine)
707     {
708       res.template corner<Dim,Dim>(TopLeft) = linear().inverse();
709     }
710     else if (traits == Isometry)
711     {
712       res.template corner<Dim,Dim>(TopLeft) = linear().transpose();
713     }
714     else
715     {
716       ei_assert("invalid traits value in Transform::inverse()");
717     }
718     // translation and remaining parts
719     res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation();
720     res.template corner<1,Dim>(BottomLeft).setZero();
721     res.coeffRef(Dim,Dim) = Scalar(1);
722     return res;
723   }
724 }
725
726 /*****************************************************
727 *** Specializations of operator* with a MatrixBase ***
728 *****************************************************/
729
730 template<typename Other, int Dim, int HDim>
731 struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
732 {
733   typedef Transform<typename Other::Scalar,Dim> TransformType;
734   typedef typename TransformType::MatrixType MatrixType;
735   typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
736   static ResultType run(const TransformType& tr, const Other& other)
737   { return tr.matrix() * other; }
738 };
739
740 template<typename Other, int Dim, int HDim>
741 struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
742 {
743   typedef Transform<typename Other::Scalar,Dim> TransformType;
744   typedef typename TransformType::MatrixType MatrixType;
745   typedef TransformType ResultType;
746   static ResultType run(const TransformType& tr, const Other& other)
747   {
748     TransformType res;
749     res.translation() = tr.translation();
750     res.matrix().row(Dim) = tr.matrix().row(Dim);
751     res.linear() = (tr.linear() * other).lazy();
752     return res;
753   }
754 };
755
756 template<typename Other, int Dim, int HDim>
757 struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
758 {
759   typedef Transform<typename Other::Scalar,Dim> TransformType;
760   typedef typename TransformType::MatrixType MatrixType;
761   typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
762   static ResultType run(const TransformType& tr, const Other& other)
763   { return tr.matrix() * other; }
764 };
765
766 template<typename Other, int Dim, int HDim>
767 struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
768 {
769   typedef typename Other::Scalar Scalar;
770   typedef Transform<Scalar,Dim> TransformType;
771   typedef typename TransformType::LinearPart MatrixType;
772   typedef const CwiseUnaryOp<
773       ei_scalar_multiple_op<Scalar>,
774       NestByValue<CwiseBinaryOp<
775         ei_scalar_sum_op<Scalar>,
776         NestByValue<typename ProductReturnType<NestByValue<MatrixType>,Other>::Type >,
777         NestByValue<typename TransformType::TranslationPart> > >
778       > ResultType;
779   // FIXME should we offer an optimized version when the last row is known to be 0,0...,0,1 ?
780   static ResultType run(const TransformType& tr, const Other& other)
781   { return ((tr.linear().nestByValue() * other).nestByValue() + tr.translation().nestByValue()).nestByValue()
782           * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
783 };
784
785 #endif // EIGEN_TRANSFORM_H