Transform.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
6 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
7 //
8 // Eigen is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 3 of the License, or (at your option) any later version.
12 //
13 // Alternatively, you can redistribute it and/or
14 // modify it under the terms of the GNU General Public License as
15 // published by the Free Software Foundation; either version 2 of
16 // the License, or (at your option) any later version.
17 //
18 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public
24 // License and a copy of the GNU General Public License along with
25 // Eigen. If not, see <http://www.gnu.org/licenses/>.
26 
27 #ifndef EIGEN_TRANSFORM_H
28 #define EIGEN_TRANSFORM_H
29 
30 namespace Eigen {
31 
32 namespace internal {
33 
34 template<typename Transform>
35 struct transform_traits
36 {
37  enum
38  {
39  Dim = Transform::Dim,
40  HDim = Transform::HDim,
41  Mode = Transform::Mode,
42  IsProjective = (int(Mode)==int(Projective))
43  };
44 };
45 
46 template< typename TransformType,
47  typename MatrixType,
48  int Case = transform_traits<TransformType>::IsProjective ? 0
49  : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
50  : 2>
51 struct transform_right_product_impl;
52 
53 template< typename Other,
54  int Mode,
55  int Options,
56  int Dim,
57  int HDim,
58  int OtherRows=Other::RowsAtCompileTime,
59  int OtherCols=Other::ColsAtCompileTime>
60 struct transform_left_product_impl;
61 
62 template< typename Lhs,
63  typename Rhs,
64  bool AnyProjective =
65  transform_traits<Lhs>::IsProjective ||
66  transform_traits<Rhs>::IsProjective>
67 struct transform_transform_product_impl;
68 
69 template< typename Other,
70  int Mode,
71  int Options,
72  int Dim,
73  int HDim,
74  int OtherRows=Other::RowsAtCompileTime,
75  int OtherCols=Other::ColsAtCompileTime>
76 struct transform_construct_from_matrix;
77 
78 template<typename TransformType> struct transform_take_affine_part;
79 
80 } // end namespace internal
81 
190 template<typename _Scalar, int _Dim, int _Mode, int _Options>
192 {
193 public:
195  enum {
196  Mode = _Mode,
197  Options = _Options,
198  Dim = _Dim,
199  HDim = _Dim+1,
200  Rows = int(Mode)==(AffineCompact) ? Dim : HDim
201  };
203  typedef _Scalar Scalar;
204  typedef DenseIndex Index;
208  typedef const MatrixType ConstMatrixType;
216  typedef typename internal::conditional<int(Mode)==int(AffineCompact),
217  MatrixType&,
220  typedef typename internal::conditional<int(Mode)==int(AffineCompact),
221  const MatrixType&,
231 
232  // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
233  enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
236 
237 protected:
238 
239  MatrixType m_matrix;
240 
241 public:
242 
245  inline Transform()
246  {
247  check_template_params();
248  if (int(Mode)==Affine)
249  makeAffine();
250  }
251 
252  inline Transform(const Transform& other)
253  {
254  check_template_params();
255  m_matrix = other.m_matrix;
256  }
257 
258  inline explicit Transform(const TranslationType& t)
259  {
260  check_template_params();
261  *this = t;
262  }
263  inline explicit Transform(const UniformScaling<Scalar>& s)
264  {
265  check_template_params();
266  *this = s;
267  }
268  template<typename Derived>
269  inline explicit Transform(const RotationBase<Derived, Dim>& r)
270  {
271  check_template_params();
272  *this = r;
273  }
274 
275  inline Transform& operator=(const Transform& other)
276  { m_matrix = other.m_matrix; return *this; }
277 
278  typedef internal::transform_take_affine_part<Transform> take_affine_part;
279 
281  template<typename OtherDerived>
282  inline explicit Transform(const EigenBase<OtherDerived>& other)
283  {
284  EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
285  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
286 
287  check_template_params();
288  internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
289  }
290 
292  template<typename OtherDerived>
293  inline Transform& operator=(const EigenBase<OtherDerived>& other)
294  {
295  EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
296  YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
297 
298  internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
299  return *this;
300  }
301 
302  template<int OtherOptions>
304  {
305  check_template_params();
306  // only the options change, we can directly copy the matrices
307  m_matrix = other.matrix();
308  }
309 
310  template<int OtherMode,int OtherOptions>
312  {
313  check_template_params();
314  // prevent conversions as:
315  // Affine | AffineCompact | Isometry = Projective
316  EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
317  YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
318 
319  // prevent conversions as:
320  // Isometry = Affine | AffineCompact
321  EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
322  YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
323 
324  enum { ModeIsAffineCompact = Mode == int(AffineCompact),
325  OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
326  };
327 
328  if(ModeIsAffineCompact == OtherModeIsAffineCompact)
329  {
330  // We need the block expression because the code is compiled for all
331  // combinations of transformations and will trigger a compile time error
332  // if one tries to assign the matrices directly
333  m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
334  makeAffine();
335  }
336  else if(OtherModeIsAffineCompact)
337  {
338  typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
339  internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
340  }
341  else
342  {
343  // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
344  // if OtherMode were Projective, the static assert above would already have caught it.
345  // So the only possibility is that OtherMode == Affine
346  linear() = other.linear();
347  translation() = other.translation();
348  }
349  }
350 
351  template<typename OtherDerived>
353  {
354  check_template_params();
355  other.evalTo(*this);
356  }
357 
358  template<typename OtherDerived>
359  Transform& operator=(const ReturnByValue<OtherDerived>& other)
360  {
361  other.evalTo(*this);
362  return *this;
363  }
364 
365  #ifdef EIGEN_QT_SUPPORT
366  inline Transform(const QMatrix& other);
367  inline Transform& operator=(const QMatrix& other);
368  inline QMatrix toQMatrix(void) const;
369  inline Transform(const QTransform& other);
370  inline Transform& operator=(const QTransform& other);
371  inline QTransform toQTransform(void) const;
372  #endif
373 
376  inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
379  inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
380 
382  inline const MatrixType& matrix() const { return m_matrix; }
384  inline MatrixType& matrix() { return m_matrix; }
385 
387  inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
389  inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
390 
392  inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
394  inline AffinePart affine() { return take_affine_part::run(m_matrix); }
395 
397  inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
399  inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
400 
412  // note: this function is defined here because some compilers cannot find the respective declaration
413  template<typename OtherDerived>
414  EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
416  { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
417 
425  template<typename OtherDerived> friend
426  inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
428  { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
429 
436  template<typename DiagonalDerived>
437  inline const TransformTimeDiagonalReturnType
439  {
440  TransformTimeDiagonalReturnType res(*this);
441  res.linear() *= b;
442  return res;
443  }
444 
451  template<typename DiagonalDerived>
452  friend inline TransformTimeDiagonalReturnType
454  {
455  TransformTimeDiagonalReturnType res;
456  res.linear().noalias() = a*b.linear();
457  res.translation().noalias() = a*b.translation();
458  if (Mode!=int(AffineCompact))
459  res.matrix().row(Dim) = b.matrix().row(Dim);
460  return res;
461  }
462 
463  template<typename OtherDerived>
464  inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
465 
467  inline const Transform operator * (const Transform& other) const
468  {
469  return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
470  }
471 
472  #ifdef __INTEL_COMPILER
473 private:
474  // this intermediate structure permits to workaround a bug in ICC 11:
475  // error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
476  // (const Eigen::Transform<double, 3, 2, 0> &) const"
477  // (the meaning of a name may have changed since the template declaration -- the type of the template is:
478  // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
479  // Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
480  //
481  template<int OtherMode,int OtherOptions> struct icc_11_workaround
482  {
483  typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType;
484  typedef typename ProductType::ResultType ResultType;
485  };
486 
487 public:
489  template<int OtherMode,int OtherOptions>
490  inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
491  operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
492  {
493  typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
494  return ProductType::run(*this,other);
495  }
496  #else
497 
498  template<int OtherMode,int OtherOptions>
499  inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
501  {
502  return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
503  }
504  #endif
505 
507  void setIdentity() { m_matrix.setIdentity(); }
508 
513  static const Transform Identity()
514  {
515  return Transform(MatrixType::Identity());
516  }
517 
518  template<typename OtherDerived>
519  inline Transform& scale(const MatrixBase<OtherDerived> &other);
520 
521  template<typename OtherDerived>
522  inline Transform& prescale(const MatrixBase<OtherDerived> &other);
523 
524  inline Transform& scale(Scalar s);
525  inline Transform& prescale(Scalar s);
526 
527  template<typename OtherDerived>
528  inline Transform& translate(const MatrixBase<OtherDerived> &other);
529 
530  template<typename OtherDerived>
531  inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
532 
533  template<typename RotationType>
534  inline Transform& rotate(const RotationType& rotation);
535 
536  template<typename RotationType>
537  inline Transform& prerotate(const RotationType& rotation);
538 
539  Transform& shear(Scalar sx, Scalar sy);
540  Transform& preshear(Scalar sx, Scalar sy);
541 
542  inline Transform& operator=(const TranslationType& t);
543  inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
544  inline Transform operator*(const TranslationType& t) const;
545 
546  inline Transform& operator=(const UniformScaling<Scalar>& t);
547  inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
548  inline Transform operator*(const UniformScaling<Scalar>& s) const;
549 
550  inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
551 
552  template<typename Derived>
553  inline Transform& operator=(const RotationBase<Derived,Dim>& r);
554  template<typename Derived>
555  inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
556  template<typename Derived>
557  inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
558 
559  const LinearMatrixType rotation() const;
560  template<typename RotationMatrixType, typename ScalingMatrixType>
561  void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
562  template<typename ScalingMatrixType, typename RotationMatrixType>
563  void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
564 
565  template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
566  Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
567  const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
568 
570 
572  const Scalar* data() const { return m_matrix.data(); }
574  Scalar* data() { return m_matrix.data(); }
575 
581  template<typename NewScalarType>
582  inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
583  { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
584 
586  template<typename OtherScalarType>
588  {
589  check_template_params();
590  m_matrix = other.matrix().template cast<Scalar>();
591  }
592 
598  { return m_matrix.isApprox(other.m_matrix, prec); }
599 
602  void makeAffine()
603  {
604  if(int(Mode)!=int(AffineCompact))
605  {
606  matrix().template block<1,Dim>(Dim,0).setZero();
607  matrix().coeffRef(Dim,Dim) = 1;
608  }
609  }
610 
616  { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
622  { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
623 
629  { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
635  { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
636 
637 
638  #ifdef EIGEN_TRANSFORM_PLUGIN
639  #include EIGEN_TRANSFORM_PLUGIN
640  #endif
641 
642 protected:
643  #ifndef EIGEN_PARSED_BY_DOXYGEN
644  static EIGEN_STRONG_INLINE void check_template_params()
645  {
646  EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
647  }
648  #endif
649 
650 };
651 
660 
669 
678 
687 
688 /**************************
689 *** Optional QT support ***
690 **************************/
691 
692 #ifdef EIGEN_QT_SUPPORT
693 
697 template<typename Scalar, int Dim, int Mode,int Options>
699 {
700  check_template_params();
701  *this = other;
702 }
703 
708 template<typename Scalar, int Dim, int Mode,int Options>
710 {
711  EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
712  m_matrix << other.m11(), other.m21(), other.dx(),
713  other.m12(), other.m22(), other.dy(),
714  0, 0, 1;
715  return *this;
716 }
717 
724 template<typename Scalar, int Dim, int Mode, int Options>
726 {
727  check_template_params();
728  EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
729  return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
730  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
731  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
732 }
733 
738 template<typename Scalar, int Dim, int Mode,int Options>
740 {
741  check_template_params();
742  *this = other;
743 }
744 
749 template<typename Scalar, int Dim, int Mode, int Options>
751 {
752  check_template_params();
753  EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
754  if (Mode == int(AffineCompact))
755  m_matrix << other.m11(), other.m21(), other.dx(),
756  other.m12(), other.m22(), other.dy();
757  else
758  m_matrix << other.m11(), other.m21(), other.dx(),
759  other.m12(), other.m22(), other.dy(),
760  other.m13(), other.m23(), other.m33();
761  return *this;
762 }
763 
768 template<typename Scalar, int Dim, int Mode, int Options>
770 {
771  EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
772  if (Mode == int(AffineCompact))
773  return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
774  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
775  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
776  else
777  return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
778  m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
779  m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
780 }
781 #endif
782 
783 /*********************
784 *** Procedural API ***
785 *********************/
786 
791 template<typename Scalar, int Dim, int Mode, int Options>
792 template<typename OtherDerived>
795 {
796  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
797  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
798  linearExt().noalias() = (linearExt() * other.asDiagonal());
799  return *this;
800 }
801 
806 template<typename Scalar, int Dim, int Mode, int Options>
808 {
809  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
810  linearExt() *= s;
811  return *this;
812 }
813 
818 template<typename Scalar, int Dim, int Mode, int Options>
819 template<typename OtherDerived>
822 {
823  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
824  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
825  m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
826  return *this;
827 }
828 
833 template<typename Scalar, int Dim, int Mode, int Options>
835 {
836  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
837  m_matrix.template topRows<Dim>() *= s;
838  return *this;
839 }
840 
845 template<typename Scalar, int Dim, int Mode, int Options>
846 template<typename OtherDerived>
849 {
850  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
851  translationExt() += linearExt() * other;
852  return *this;
853 }
854 
859 template<typename Scalar, int Dim, int Mode, int Options>
860 template<typename OtherDerived>
863 {
864  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
865  if(int(Mode)==int(Projective))
866  affine() += other * m_matrix.row(Dim);
867  else
868  translation() += other;
869  return *this;
870 }
871 
889 template<typename Scalar, int Dim, int Mode, int Options>
890 template<typename RotationType>
892 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
893 {
894  linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
895  return *this;
896 }
897 
905 template<typename Scalar, int Dim, int Mode, int Options>
906 template<typename RotationType>
909 {
910  m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
911  * m_matrix.template block<Dim,HDim>(0,0);
912  return *this;
913 }
914 
920 template<typename Scalar, int Dim, int Mode, int Options>
923 {
924  EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
925  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
926  VectorType tmp = linear().col(0)*sy + linear().col(1);
927  linear() << linear().col(0) + linear().col(1)*sx, tmp;
928  return *this;
929 }
930 
936 template<typename Scalar, int Dim, int Mode, int Options>
939 {
940  EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
941  EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
942  m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
943  return *this;
944 }
945 
946 /******************************************************
947 *** Scaling, Translation and Rotation compatibility ***
948 ******************************************************/
949 
950 template<typename Scalar, int Dim, int Mode, int Options>
952 {
953  linear().setIdentity();
954  translation() = t.vector();
955  makeAffine();
956  return *this;
957 }
958 
959 template<typename Scalar, int Dim, int Mode, int Options>
961 {
962  Transform res = *this;
963  res.translate(t.vector());
964  return res;
965 }
966 
967 template<typename Scalar, int Dim, int Mode, int Options>
969 {
970  m_matrix.setZero();
971  linear().diagonal().fill(s.factor());
972  makeAffine();
973  return *this;
974 }
975 
976 template<typename Scalar, int Dim, int Mode, int Options>
978 {
979  Transform res = *this;
980  res.scale(s.factor());
981  return res;
982 }
983 
984 template<typename Scalar, int Dim, int Mode, int Options>
985 template<typename Derived>
987 {
988  linear() = internal::toRotationMatrix<Scalar,Dim>(r);
989  translation().setZero();
990  makeAffine();
991  return *this;
992 }
993 
994 template<typename Scalar, int Dim, int Mode, int Options>
995 template<typename Derived>
997 {
998  Transform res = *this;
999  res.rotate(r.derived());
1000  return res;
1001 }
1002 
1003 /************************
1004 *** Special functions ***
1005 ************************/
1006 
1014 template<typename Scalar, int Dim, int Mode, int Options>
1017 {
1018  LinearMatrixType result;
1019  computeRotationScaling(&result, (LinearMatrixType*)0);
1020  return result;
1021 }
1022 
1023 
1035 template<typename Scalar, int Dim, int Mode, int Options>
1036 template<typename RotationMatrixType, typename ScalingMatrixType>
1037 void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
1038 {
1040 
1041  Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
1042  VectorType sv(svd.singularValues());
1043  sv.coeffRef(0) *= x;
1044  if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
1045  if(rotation)
1046  {
1047  LinearMatrixType m(svd.matrixU());
1048  m.col(0) /= x;
1049  rotation->lazyAssign(m * svd.matrixV().adjoint());
1050  }
1051 }
1052 
1064 template<typename Scalar, int Dim, int Mode, int Options>
1065 template<typename ScalingMatrixType, typename RotationMatrixType>
1066 void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
1067 {
1069 
1070  Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
1071  VectorType sv(svd.singularValues());
1072  sv.coeffRef(0) *= x;
1073  if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
1074  if(rotation)
1075  {
1076  LinearMatrixType m(svd.matrixU());
1077  m.col(0) /= x;
1078  rotation->lazyAssign(m * svd.matrixV().adjoint());
1079  }
1080 }
1081 
1085 template<typename Scalar, int Dim, int Mode, int Options>
1086 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
1089  const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
1090 {
1091  linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
1092  linear() *= scale.asDiagonal();
1093  translation() = position;
1094  makeAffine();
1095  return *this;
1096 }
1097 
1098 namespace internal {
1099 
1100 // selector needed to avoid taking the inverse of a 3x4 matrix
1101 template<typename TransformType, int Mode=TransformType::Mode>
1102 struct projective_transform_inverse
1103 {
1104  static inline void run(const TransformType&, TransformType&)
1105  {}
1106 };
1107 
1108 template<typename TransformType>
1109 struct projective_transform_inverse<TransformType, Projective>
1110 {
1111  static inline void run(const TransformType& m, TransformType& res)
1112  {
1113  res.matrix() = m.matrix().inverse();
1114  }
1115 };
1116 
1117 } // end namespace internal
1118 
1119 
1140 template<typename Scalar, int Dim, int Mode, int Options>
1141 Transform<Scalar,Dim,Mode,Options>
1143 {
1144  Transform res;
1145  if (hint == Projective)
1146  {
1147  internal::projective_transform_inverse<Transform>::run(*this, res);
1148  }
1149  else
1150  {
1151  if (hint == Isometry)
1152  {
1153  res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
1154  }
1155  else if(hint&Affine)
1156  {
1157  res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
1158  }
1159  else
1160  {
1161  eigen_assert(false && "Invalid transform traits in Transform::Inverse");
1162  }
1163  // translation and remaining parts
1164  res.matrix().template topRightCorner<Dim,1>()
1165  = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
1166  res.makeAffine(); // we do need this, because in the beginning res is uninitialized
1167  }
1168  return res;
1169 }
1170 
1171 namespace internal {
1172 
1173 /*****************************************************
1174 *** Specializations of take affine part ***
1175 *****************************************************/
1176 
1177 template<typename TransformType> struct transform_take_affine_part {
1178  typedef typename TransformType::MatrixType MatrixType;
1179  typedef typename TransformType::AffinePart AffinePart;
1180  typedef typename TransformType::ConstAffinePart ConstAffinePart;
1181  static inline AffinePart run(MatrixType& m)
1182  { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
1183  static inline ConstAffinePart run(const MatrixType& m)
1184  { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
1185 };
1186 
1187 template<typename Scalar, int Dim, int Options>
1188 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
1189  typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
1190  static inline MatrixType& run(MatrixType& m) { return m; }
1191  static inline const MatrixType& run(const MatrixType& m) { return m; }
1192 };
1193 
1194 /*****************************************************
1195 *** Specializations of construct from matrix ***
1196 *****************************************************/
1197 
1198 template<typename Other, int Mode, int Options, int Dim, int HDim>
1199 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
1200 {
1201  static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1202  {
1203  transform->linear() = other;
1204  transform->translation().setZero();
1205  transform->makeAffine();
1206  }
1207 };
1208 
1209 template<typename Other, int Mode, int Options, int Dim, int HDim>
1210 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
1211 {
1212  static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1213  {
1214  transform->affine() = other;
1215  transform->makeAffine();
1216  }
1217 };
1218 
1219 template<typename Other, int Mode, int Options, int Dim, int HDim>
1220 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
1221 {
1222  static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
1223  { transform->matrix() = other; }
1224 };
1225 
1226 template<typename Other, int Options, int Dim, int HDim>
1227 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
1228 {
1229  static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
1230  { transform->matrix() = other.template block<Dim,HDim>(0,0); }
1231 };
1232 
1233 /**********************************************************
1234 *** Specializations of operator* with rhs EigenBase ***
1235 **********************************************************/
1236 
1237 template<int LhsMode,int RhsMode>
1238 struct transform_product_result
1239 {
1240  enum
1241  {
1242  Mode =
1243  (LhsMode == (int)Projective || RhsMode == (int)Projective ) ? Projective :
1244  (LhsMode == (int)Affine || RhsMode == (int)Affine ) ? Affine :
1245  (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
1246  (LhsMode == (int)Isometry || RhsMode == (int)Isometry ) ? Isometry : Projective
1247  };
1248 };
1249 
1250 template< typename TransformType, typename MatrixType >
1251 struct transform_right_product_impl< TransformType, MatrixType, 0 >
1252 {
1253  typedef typename MatrixType::PlainObject ResultType;
1254 
1255  static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1256  {
1257  return T.matrix() * other;
1258  }
1259 };
1260 
1261 template< typename TransformType, typename MatrixType >
1262 struct transform_right_product_impl< TransformType, MatrixType, 1 >
1263 {
1264  enum {
1265  Dim = TransformType::Dim,
1266  HDim = TransformType::HDim,
1267  OtherRows = MatrixType::RowsAtCompileTime,
1268  OtherCols = MatrixType::ColsAtCompileTime
1269  };
1270 
1271  typedef typename MatrixType::PlainObject ResultType;
1272 
1273  static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1274  {
1275  EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1276 
1277  typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
1278 
1279  ResultType res(other.rows(),other.cols());
1280  TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
1281  res.row(OtherRows-1) = other.row(OtherRows-1);
1282 
1283  return res;
1284  }
1285 };
1286 
1287 template< typename TransformType, typename MatrixType >
1288 struct transform_right_product_impl< TransformType, MatrixType, 2 >
1289 {
1290  enum {
1291  Dim = TransformType::Dim,
1292  HDim = TransformType::HDim,
1293  OtherRows = MatrixType::RowsAtCompileTime,
1294  OtherCols = MatrixType::ColsAtCompileTime
1295  };
1296 
1297  typedef typename MatrixType::PlainObject ResultType;
1298 
1299  static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
1300  {
1301  EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
1302 
1303  typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs;
1304  ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
1305  TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
1306 
1307  return res;
1308  }
1309 };
1310 
1311 /**********************************************************
1312 *** Specializations of operator* with lhs EigenBase ***
1313 **********************************************************/
1314 
1315 // generic HDim x HDim matrix * T => Projective
1316 template<typename Other,int Mode, int Options, int Dim, int HDim>
1317 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
1318 {
1319  typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
1320  typedef typename TransformType::MatrixType MatrixType;
1321  typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
1322  static ResultType run(const Other& other,const TransformType& tr)
1323  { return ResultType(other * tr.matrix()); }
1324 };
1325 
1326 // generic HDim x HDim matrix * AffineCompact => Projective
1327 template<typename Other, int Options, int Dim, int HDim>
1328 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
1329 {
1330  typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
1331  typedef typename TransformType::MatrixType MatrixType;
1332  typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
1333  static ResultType run(const Other& other,const TransformType& tr)
1334  {
1335  ResultType res;
1336  res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
1337  res.matrix().col(Dim) += other.col(Dim);
1338  return res;
1339  }
1340 };
1341 
1342 // affine matrix * T
1343 template<typename Other,int Mode, int Options, int Dim, int HDim>
1344 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
1345 {
1346  typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
1347  typedef typename TransformType::MatrixType MatrixType;
1348  typedef TransformType ResultType;
1349  static ResultType run(const Other& other,const TransformType& tr)
1350  {
1351  ResultType res;
1352  res.affine().noalias() = other * tr.matrix();
1353  res.matrix().row(Dim) = tr.matrix().row(Dim);
1354  return res;
1355  }
1356 };
1357 
1358 // affine matrix * AffineCompact
1359 template<typename Other, int Options, int Dim, int HDim>
1360 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
1361 {
1362  typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
1363  typedef typename TransformType::MatrixType MatrixType;
1364  typedef TransformType ResultType;
1365  static ResultType run(const Other& other,const TransformType& tr)
1366  {
1367  ResultType res;
1368  res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
1369  res.translation() += other.col(Dim);
1370  return res;
1371  }
1372 };
1373 
1374 // linear matrix * T
1375 template<typename Other,int Mode, int Options, int Dim, int HDim>
1376 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
1377 {
1378  typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
1379  typedef typename TransformType::MatrixType MatrixType;
1380  typedef TransformType ResultType;
1381  static ResultType run(const Other& other, const TransformType& tr)
1382  {
1383  TransformType res;
1384  if(Mode!=int(AffineCompact))
1385  res.matrix().row(Dim) = tr.matrix().row(Dim);
1386  res.matrix().template topRows<Dim>().noalias()
1387  = other * tr.matrix().template topRows<Dim>();
1388  return res;
1389  }
1390 };
1391 
1392 /**********************************************************
1393 *** Specializations of operator* with another Transform ***
1394 **********************************************************/
1395 
1396 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1397 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
1398 {
1399  enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
1400  typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
1401  typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
1402  typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
1403  static ResultType run(const Lhs& lhs, const Rhs& rhs)
1404  {
1405  ResultType res;
1406  res.linear() = lhs.linear() * rhs.linear();
1407  res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
1408  res.makeAffine();
1409  return res;
1410  }
1411 };
1412 
1413 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
1414 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
1415 {
1416  typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
1417  typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
1418  typedef Transform<Scalar,Dim,Projective> ResultType;
1419  static ResultType run(const Lhs& lhs, const Rhs& rhs)
1420  {
1421  return ResultType( lhs.matrix() * rhs.matrix() );
1422  }
1423 };
1424 
1425 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1426 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true >
1427 {
1428  typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs;
1429  typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs;
1430  typedef Transform<Scalar,Dim,Projective> ResultType;
1431  static ResultType run(const Lhs& lhs, const Rhs& rhs)
1432  {
1433  ResultType res;
1434  res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
1435  res.matrix().row(Dim) = rhs.matrix().row(Dim);
1436  return res;
1437  }
1438 };
1439 
1440 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
1441 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true >
1442 {
1443  typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs;
1444  typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs;
1445  typedef Transform<Scalar,Dim,Projective> ResultType;
1446  static ResultType run(const Lhs& lhs, const Rhs& rhs)
1447  {
1448  ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
1449  res.matrix().col(Dim) += lhs.matrix().col(Dim);
1450  return res;
1451  }
1452 };
1453 
1454 } // end namespace internal
1455 
1456 } // end namespace Eigen
1457 
1458 #endif // EIGEN_TRANSFORM_H