Transform.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
00007 //
00008 // This Source Code Form is subject to the terms of the Mozilla
00009 // Public License v. 2.0. If a copy of the MPL was not distributed
00010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00011 
00012 #ifndef EIGEN_TRANSFORM_H
00013 #define EIGEN_TRANSFORM_H
00014 
00015 namespace Eigen { 
00016 
00017 namespace internal {
00018 
00019 template<typename Transform>
00020 struct transform_traits
00021 {
00022   enum
00023   {
00024     Dim = Transform::Dim,
00025     HDim = Transform::HDim,
00026     Mode = Transform::Mode,
00027     IsProjective = (int(Mode)==int(Projective))
00028   };
00029 };
00030 
00031 template< typename TransformType,
00032           typename MatrixType,
00033           int Case = transform_traits<TransformType>::IsProjective ? 0
00034                    : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
00035                    : 2>
00036 struct transform_right_product_impl;
00037 
00038 template< typename Other,
00039           int Mode,
00040           int Options,
00041           int Dim,
00042           int HDim,
00043           int OtherRows=Other::RowsAtCompileTime,
00044           int OtherCols=Other::ColsAtCompileTime>
00045 struct transform_left_product_impl;
00046 
00047 template< typename Lhs,
00048           typename Rhs,
00049           bool AnyProjective = 
00050             transform_traits<Lhs>::IsProjective ||
00051             transform_traits<Rhs>::IsProjective>
00052 struct transform_transform_product_impl;
00053 
00054 template< typename Other,
00055           int Mode,
00056           int Options,
00057           int Dim,
00058           int HDim,
00059           int OtherRows=Other::RowsAtCompileTime,
00060           int OtherCols=Other::ColsAtCompileTime>
00061 struct transform_construct_from_matrix;
00062 
00063 template<typename TransformType> struct transform_take_affine_part;
00064 
00065 template<int Mode> struct transform_make_affine;
00066 
00067 } // end namespace internal
00068 
00177 template<typename _Scalar, int _Dim, int _Mode, int _Options>
00178 class Transform
00179 {
00180 public:
00181   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00182   enum {
00183     Mode = _Mode,
00184     Options = _Options,
00185     Dim = _Dim,     
00186     HDim = _Dim+1,  
00187     Rows = int(Mode)==(AffineCompact) ? Dim : HDim
00188   };
00190   typedef _Scalar Scalar;
00191   typedef DenseIndex Index;
00193   typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
00195   typedef const MatrixType ConstMatrixType;
00197   typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
00199   typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
00201   typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
00203   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00204                               MatrixType&,
00205                               Block<MatrixType,Dim,HDim> >::type AffinePart;
00207   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00208                               const MatrixType&,
00209                               const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
00211   typedef Matrix<Scalar,Dim,1> VectorType;
00213   typedef Block<MatrixType,Dim,1,int(Mode)==(AffineCompact)> TranslationPart;
00215   typedef const Block<ConstMatrixType,Dim,1,int(Mode)==(AffineCompact)> ConstTranslationPart;
00217   typedef Translation<Scalar,Dim> TranslationType;
00218   
00219   // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
00220   enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
00222   typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
00223 
00224 protected:
00225 
00226   MatrixType m_matrix;
00227 
00228 public:
00229 
00232   inline Transform()
00233   {
00234     check_template_params();
00235     internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
00236   }
00237 
00238   inline Transform(const Transform& other)
00239   {
00240     check_template_params();
00241     m_matrix = other.m_matrix;
00242   }
00243 
00244   inline explicit Transform(const TranslationType& t)
00245   {
00246     check_template_params();
00247     *this = t;
00248   }
00249   inline explicit Transform(const UniformScaling<Scalar>& s)
00250   {
00251     check_template_params();
00252     *this = s;
00253   }
00254   template<typename Derived>
00255   inline explicit Transform(const RotationBase<Derived, Dim>& r)
00256   {
00257     check_template_params();
00258     *this = r;
00259   }
00260 
00261   inline Transform& operator=(const Transform& other)
00262   { m_matrix = other.m_matrix; return *this; }
00263 
00264   typedef internal::transform_take_affine_part<Transform> take_affine_part;
00265 
00267   template<typename OtherDerived>
00268   inline explicit Transform(const EigenBase<OtherDerived>& other)
00269   {
00270     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00271       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00272 
00273     check_template_params();
00274     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00275   }
00276 
00278   template<typename OtherDerived>
00279   inline Transform& operator=(const EigenBase<OtherDerived>& other)
00280   {
00281     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00282       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00283 
00284     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00285     return *this;
00286   }
00287   
00288   template<int OtherOptions>
00289   inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
00290   {
00291     check_template_params();
00292     // only the options change, we can directly copy the matrices
00293     m_matrix = other.matrix();
00294   }
00295 
00296   template<int OtherMode,int OtherOptions>
00297   inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
00298   {
00299     check_template_params();
00300     // prevent conversions as:
00301     // Affine | AffineCompact | Isometry = Projective
00302     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
00303                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00304 
00305     // prevent conversions as:
00306     // Isometry = Affine | AffineCompact
00307     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
00308                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00309 
00310     enum { ModeIsAffineCompact = Mode == int(AffineCompact),
00311            OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
00312     };
00313 
00314     if(ModeIsAffineCompact == OtherModeIsAffineCompact)
00315     {
00316       // We need the block expression because the code is compiled for all
00317       // combinations of transformations and will trigger a compile time error
00318       // if one tries to assign the matrices directly
00319       m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
00320       makeAffine();
00321     }
00322     else if(OtherModeIsAffineCompact)
00323     {
00324       typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
00325       internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
00326     }
00327     else
00328     {
00329       // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
00330       // if OtherMode were Projective, the static assert above would already have caught it.
00331       // So the only possibility is that OtherMode == Affine
00332       linear() = other.linear();
00333       translation() = other.translation();
00334     }
00335   }
00336 
00337   template<typename OtherDerived>
00338   Transform(const ReturnByValue<OtherDerived>& other)
00339   {
00340     check_template_params();
00341     other.evalTo(*this);
00342   }
00343 
00344   template<typename OtherDerived>
00345   Transform& operator=(const ReturnByValue<OtherDerived>& other)
00346   {
00347     other.evalTo(*this);
00348     return *this;
00349   }
00350 
00351   #ifdef EIGEN_QT_SUPPORT
00352   inline Transform(const QMatrix& other);
00353   inline Transform& operator=(const QMatrix& other);
00354   inline QMatrix toQMatrix(void) const;
00355   inline Transform(const QTransform& other);
00356   inline Transform& operator=(const QTransform& other);
00357   inline QTransform toQTransform(void) const;
00358   #endif
00359 
00362   inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
00365   inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
00366 
00368   inline const MatrixType& matrix() const { return m_matrix; }
00370   inline MatrixType& matrix() { return m_matrix; }
00371 
00373   inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
00375   inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
00376 
00378   inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
00380   inline AffinePart affine() { return take_affine_part::run(m_matrix); }
00381 
00383   inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
00385   inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
00386 
00398   // note: this function is defined here because some compilers cannot find the respective declaration
00399   template<typename OtherDerived>
00400   EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
00401   operator * (const EigenBase<OtherDerived> &other) const
00402   { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
00403 
00411   template<typename OtherDerived> friend
00412   inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
00413     operator * (const EigenBase<OtherDerived> &a, const Transform &b)
00414   { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
00415 
00422   template<typename DiagonalDerived>
00423   inline const TransformTimeDiagonalReturnType
00424     operator * (const DiagonalBase<DiagonalDerived> &b) const
00425   {
00426     TransformTimeDiagonalReturnType res(*this);
00427     res.linear() *= b;
00428     return res;
00429   }
00430 
00437   template<typename DiagonalDerived>
00438   friend inline TransformTimeDiagonalReturnType
00439     operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
00440   {
00441     TransformTimeDiagonalReturnType res;
00442     res.linear().noalias() = a*b.linear();
00443     res.translation().noalias() = a*b.translation();
00444     if (Mode!=int(AffineCompact))
00445       res.matrix().row(Dim) = b.matrix().row(Dim);
00446     return res;
00447   }
00448 
00449   template<typename OtherDerived>
00450   inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
00451 
00453   inline const Transform operator * (const Transform& other) const
00454   {
00455     return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
00456   }
00457   
00458   #ifdef __INTEL_COMPILER
00459 private:
00460   // this intermediate structure permits to workaround a bug in ICC 11:
00461   //   error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
00462   //             (const Eigen::Transform<double, 3, 2, 0> &) const"
00463   //  (the meaning of a name may have changed since the template declaration -- the type of the template is:
00464   // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
00465   //     Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
00466   // 
00467   template<int OtherMode,int OtherOptions> struct icc_11_workaround
00468   {
00469     typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType;
00470     typedef typename ProductType::ResultType ResultType;
00471   };
00472   
00473 public:
00475   template<int OtherMode,int OtherOptions>
00476   inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
00477     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00478   {
00479     typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
00480     return ProductType::run(*this,other);
00481   }
00482   #else
00483 
00484   template<int OtherMode,int OtherOptions>
00485   inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
00486     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00487   {
00488     return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
00489   }
00490   #endif
00491 
00493   void setIdentity() { m_matrix.setIdentity(); }
00494 
00499   static const Transform Identity()
00500   {
00501     return Transform(MatrixType::Identity());
00502   }
00503 
00504   template<typename OtherDerived>
00505   inline Transform& scale(const MatrixBase<OtherDerived> &other);
00506 
00507   template<typename OtherDerived>
00508   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00509 
00510   inline Transform& scale(const Scalar& s);
00511   inline Transform& prescale(const Scalar& s);
00512 
00513   template<typename OtherDerived>
00514   inline Transform& translate(const MatrixBase<OtherDerived> &other);
00515 
00516   template<typename OtherDerived>
00517   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00518 
00519   template<typename RotationType>
00520   inline Transform& rotate(const RotationType& rotation);
00521 
00522   template<typename RotationType>
00523   inline Transform& prerotate(const RotationType& rotation);
00524 
00525   Transform& shear(const Scalar& sx, const Scalar& sy);
00526   Transform& preshear(const Scalar& sx, const Scalar& sy);
00527 
00528   inline Transform& operator=(const TranslationType& t);
00529   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00530   inline Transform operator*(const TranslationType& t) const;
00531 
00532   inline Transform& operator=(const UniformScaling<Scalar>& t);
00533   inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
00534   inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode))> operator*(const UniformScaling<Scalar>& s) const
00535   {
00536     Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode)),Options> res = *this;
00537     res.scale(s.factor());
00538     return res;
00539   }
00540 
00541   inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
00542 
00543   template<typename Derived>
00544   inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00545   template<typename Derived>
00546   inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00547   template<typename Derived>
00548   inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00549 
00550   const LinearMatrixType rotation() const;
00551   template<typename RotationMatrixType, typename ScalingMatrixType>
00552   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00553   template<typename ScalingMatrixType, typename RotationMatrixType>
00554   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00555 
00556   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00557   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00558     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00559 
00560   inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
00561 
00563   const Scalar* data() const { return m_matrix.data(); }
00565   Scalar* data() { return m_matrix.data(); }
00566 
00572   template<typename NewScalarType>
00573   inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
00574   { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
00575 
00577   template<typename OtherScalarType>
00578   inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
00579   {
00580     check_template_params();
00581     m_matrix = other.matrix().template cast<Scalar>();
00582   }
00583 
00588   bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
00589   { return m_matrix.isApprox(other.m_matrix, prec); }
00590 
00593   void makeAffine()
00594   {
00595     internal::transform_make_affine<int(Mode)>::run(m_matrix);
00596   }
00597 
00602   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
00603   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00608   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
00609   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00610 
00615   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
00616   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00621   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
00622   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00623 
00624 
00625   #ifdef EIGEN_TRANSFORM_PLUGIN
00626   #include EIGEN_TRANSFORM_PLUGIN
00627   #endif
00628   
00629 protected:
00630   #ifndef EIGEN_PARSED_BY_DOXYGEN
00631     static EIGEN_STRONG_INLINE void check_template_params()
00632     {
00633       EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
00634     }
00635   #endif
00636 
00637 };
00638 
00640 typedef Transform<float,2,Isometry> Isometry2f;
00642 typedef Transform<float,3,Isometry> Isometry3f;
00644 typedef Transform<double,2,Isometry> Isometry2d;
00646 typedef Transform<double,3,Isometry> Isometry3d;
00647 
00649 typedef Transform<float,2,Affine> Affine2f;
00651 typedef Transform<float,3,Affine> Affine3f;
00653 typedef Transform<double,2,Affine> Affine2d;
00655 typedef Transform<double,3,Affine> Affine3d;
00656 
00658 typedef Transform<float,2,AffineCompact> AffineCompact2f;
00660 typedef Transform<float,3,AffineCompact> AffineCompact3f;
00662 typedef Transform<double,2,AffineCompact> AffineCompact2d;
00664 typedef Transform<double,3,AffineCompact> AffineCompact3d;
00665 
00667 typedef Transform<float,2,Projective> Projective2f;
00669 typedef Transform<float,3,Projective> Projective3f;
00671 typedef Transform<double,2,Projective> Projective2d;
00673 typedef Transform<double,3,Projective> Projective3d;
00674 
00675 /**************************
00676 *** Optional QT support ***
00677 **************************/
00678 
00679 #ifdef EIGEN_QT_SUPPORT
00680 
00684 template<typename Scalar, int Dim, int Mode,int Options>
00685 Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
00686 {
00687   check_template_params();
00688   *this = other;
00689 }
00690 
00695 template<typename Scalar, int Dim, int Mode,int Options>
00696 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
00697 {
00698   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00699   m_matrix << other.m11(), other.m21(), other.dx(),
00700               other.m12(), other.m22(), other.dy(),
00701               0, 0, 1;
00702   return *this;
00703 }
00704 
00711 template<typename Scalar, int Dim, int Mode, int Options>
00712 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
00713 {
00714   check_template_params();
00715   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00716   return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00717                  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00718                  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00719 }
00720 
00725 template<typename Scalar, int Dim, int Mode,int Options>
00726 Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
00727 {
00728   check_template_params();
00729   *this = other;
00730 }
00731 
00736 template<typename Scalar, int Dim, int Mode, int Options>
00737 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
00738 {
00739   check_template_params();
00740   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00741   if (Mode == int(AffineCompact))
00742     m_matrix << other.m11(), other.m21(), other.dx(),
00743                 other.m12(), other.m22(), other.dy();
00744   else
00745     m_matrix << other.m11(), other.m21(), other.dx(),
00746                 other.m12(), other.m22(), other.dy(),
00747                 other.m13(), other.m23(), other.m33();
00748   return *this;
00749 }
00750 
00755 template<typename Scalar, int Dim, int Mode, int Options>
00756 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
00757 {
00758   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00759   if (Mode == int(AffineCompact))
00760     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00761                       m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00762                       m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00763   else
00764     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00765                       m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00766                       m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00767 }
00768 #endif
00769 
00770 /*********************
00771 *** Procedural API ***
00772 *********************/
00773 
00778 template<typename Scalar, int Dim, int Mode, int Options>
00779 template<typename OtherDerived>
00780 Transform<Scalar,Dim,Mode,Options>&
00781 Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
00782 {
00783   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00784   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00785   linearExt().noalias() = (linearExt() * other.asDiagonal());
00786   return *this;
00787 }
00788 
00793 template<typename Scalar, int Dim, int Mode, int Options>
00794 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
00795 {
00796   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00797   linearExt() *= s;
00798   return *this;
00799 }
00800 
00805 template<typename Scalar, int Dim, int Mode, int Options>
00806 template<typename OtherDerived>
00807 Transform<Scalar,Dim,Mode,Options>&
00808 Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
00809 {
00810   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00811   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00812   m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
00813   return *this;
00814 }
00815 
00820 template<typename Scalar, int Dim, int Mode, int Options>
00821 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
00822 {
00823   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00824   m_matrix.template topRows<Dim>() *= s;
00825   return *this;
00826 }
00827 
00832 template<typename Scalar, int Dim, int Mode, int Options>
00833 template<typename OtherDerived>
00834 Transform<Scalar,Dim,Mode,Options>&
00835 Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
00836 {
00837   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00838   translationExt() += linearExt() * other;
00839   return *this;
00840 }
00841 
00846 template<typename Scalar, int Dim, int Mode, int Options>
00847 template<typename OtherDerived>
00848 Transform<Scalar,Dim,Mode,Options>&
00849 Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
00850 {
00851   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00852   if(int(Mode)==int(Projective))
00853     affine() += other * m_matrix.row(Dim);
00854   else
00855     translation() += other;
00856   return *this;
00857 }
00858 
00876 template<typename Scalar, int Dim, int Mode, int Options>
00877 template<typename RotationType>
00878 Transform<Scalar,Dim,Mode,Options>&
00879 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
00880 {
00881   linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
00882   return *this;
00883 }
00884 
00892 template<typename Scalar, int Dim, int Mode, int Options>
00893 template<typename RotationType>
00894 Transform<Scalar,Dim,Mode,Options>&
00895 Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
00896 {
00897   m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
00898                                          * m_matrix.template block<Dim,HDim>(0,0);
00899   return *this;
00900 }
00901 
00907 template<typename Scalar, int Dim, int Mode, int Options>
00908 Transform<Scalar,Dim,Mode,Options>&
00909 Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
00910 {
00911   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00912   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00913   VectorType tmp = linear().col(0)*sy + linear().col(1);
00914   linear() << linear().col(0) + linear().col(1)*sx, tmp;
00915   return *this;
00916 }
00917 
00923 template<typename Scalar, int Dim, int Mode, int Options>
00924 Transform<Scalar,Dim,Mode,Options>&
00925 Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
00926 {
00927   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00928   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00929   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00930   return *this;
00931 }
00932 
00933 /******************************************************
00934 *** Scaling, Translation and Rotation compatibility ***
00935 ******************************************************/
00936 
00937 template<typename Scalar, int Dim, int Mode, int Options>
00938 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
00939 {
00940   linear().setIdentity();
00941   translation() = t.vector();
00942   makeAffine();
00943   return *this;
00944 }
00945 
00946 template<typename Scalar, int Dim, int Mode, int Options>
00947 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
00948 {
00949   Transform res = *this;
00950   res.translate(t.vector());
00951   return res;
00952 }
00953 
00954 template<typename Scalar, int Dim, int Mode, int Options>
00955 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
00956 {
00957   m_matrix.setZero();
00958   linear().diagonal().fill(s.factor());
00959   makeAffine();
00960   return *this;
00961 }
00962 
00963 template<typename Scalar, int Dim, int Mode, int Options>
00964 template<typename Derived>
00965 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
00966 {
00967   linear() = internal::toRotationMatrix<Scalar,Dim>(r);
00968   translation().setZero();
00969   makeAffine();
00970   return *this;
00971 }
00972 
00973 template<typename Scalar, int Dim, int Mode, int Options>
00974 template<typename Derived>
00975 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
00976 {
00977   Transform res = *this;
00978   res.rotate(r.derived());
00979   return res;
00980 }
00981 
00982 /************************
00983 *** Special functions ***
00984 ************************/
00985 
00993 template<typename Scalar, int Dim, int Mode, int Options>
00994 const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
00995 Transform<Scalar,Dim,Mode,Options>::rotation() const
00996 {
00997   LinearMatrixType result;
00998   computeRotationScaling(&result, (LinearMatrixType*)0);
00999   return result;
01000 }
01001 
01002 
01014 template<typename Scalar, int Dim, int Mode, int Options>
01015 template<typename RotationMatrixType, typename ScalingMatrixType>
01016 void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
01017 {
01018   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01019 
01020   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01021   VectorType sv(svd.singularValues());
01022   sv.coeffRef(0) *= x;
01023   if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
01024   if(rotation)
01025   {
01026     LinearMatrixType m(svd.matrixU());
01027     m.col(0) /= x;
01028     rotation->lazyAssign(m * svd.matrixV().adjoint());
01029   }
01030 }
01031 
01043 template<typename Scalar, int Dim, int Mode, int Options>
01044 template<typename ScalingMatrixType, typename RotationMatrixType>
01045 void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
01046 {
01047   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01048 
01049   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01050   VectorType sv(svd.singularValues());
01051   sv.coeffRef(0) *= x;
01052   if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
01053   if(rotation)
01054   {
01055     LinearMatrixType m(svd.matrixU());
01056     m.col(0) /= x;
01057     rotation->lazyAssign(m * svd.matrixV().adjoint());
01058   }
01059 }
01060 
01064 template<typename Scalar, int Dim, int Mode, int Options>
01065 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
01066 Transform<Scalar,Dim,Mode,Options>&
01067 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
01068   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
01069 {
01070   linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
01071   linear() *= scale.asDiagonal();
01072   translation() = position;
01073   makeAffine();
01074   return *this;
01075 }
01076 
01077 namespace internal {
01078 
01079 template<int Mode>
01080 struct transform_make_affine
01081 {
01082   template<typename MatrixType>
01083   static void run(MatrixType &mat)
01084   {
01085     static const int Dim = MatrixType::ColsAtCompileTime-1;
01086     mat.template block<1,Dim>(Dim,0).setZero();
01087     mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
01088   }
01089 };
01090 
01091 template<>
01092 struct transform_make_affine<AffineCompact>
01093 {
01094   template<typename MatrixType> static void run(MatrixType &) { }
01095 };
01096     
01097 // selector needed to avoid taking the inverse of a 3x4 matrix
01098 template<typename TransformType, int Mode=TransformType::Mode>
01099 struct projective_transform_inverse
01100 {
01101   static inline void run(const TransformType&, TransformType&)
01102   {}
01103 };
01104 
01105 template<typename TransformType>
01106 struct projective_transform_inverse<TransformType, Projective>
01107 {
01108   static inline void run(const TransformType& m, TransformType& res)
01109   {
01110     res.matrix() = m.matrix().inverse();
01111   }
01112 };
01113 
01114 } // end namespace internal
01115 
01116 
01137 template<typename Scalar, int Dim, int Mode, int Options>
01138 Transform<Scalar,Dim,Mode,Options>
01139 Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
01140 {
01141   Transform res;
01142   if (hint == Projective)
01143   {
01144     internal::projective_transform_inverse<Transform>::run(*this, res);
01145   }
01146   else
01147   {
01148     if (hint == Isometry)
01149     {
01150       res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
01151     }
01152     else if(hint&Affine)
01153     {
01154       res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
01155     }
01156     else
01157     {
01158       eigen_assert(false && "Invalid transform traits in Transform::Inverse");
01159     }
01160     // translation and remaining parts
01161     res.matrix().template topRightCorner<Dim,1>()
01162       = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
01163     res.makeAffine(); // we do need this, because in the beginning res is uninitialized
01164   }
01165   return res;
01166 }
01167 
01168 namespace internal {
01169 
01170 /*****************************************************
01171 *** Specializations of take affine part            ***
01172 *****************************************************/
01173 
01174 template<typename TransformType> struct transform_take_affine_part {
01175   typedef typename TransformType::MatrixType MatrixType;
01176   typedef typename TransformType::AffinePart AffinePart;
01177   typedef typename TransformType::ConstAffinePart ConstAffinePart;
01178   static inline AffinePart run(MatrixType& m)
01179   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01180   static inline ConstAffinePart run(const MatrixType& m)
01181   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01182 };
01183 
01184 template<typename Scalar, int Dim, int Options>
01185 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
01186   typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
01187   static inline MatrixType& run(MatrixType& m) { return m; }
01188   static inline const MatrixType& run(const MatrixType& m) { return m; }
01189 };
01190 
01191 /*****************************************************
01192 *** Specializations of construct from matrix       ***
01193 *****************************************************/
01194 
01195 template<typename Other, int Mode, int Options, int Dim, int HDim>
01196 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
01197 {
01198   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01199   {
01200     transform->linear() = other;
01201     transform->translation().setZero();
01202     transform->makeAffine();
01203   }
01204 };
01205 
01206 template<typename Other, int Mode, int Options, int Dim, int HDim>
01207 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
01208 {
01209   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01210   {
01211     transform->affine() = other;
01212     transform->makeAffine();
01213   }
01214 };
01215 
01216 template<typename Other, int Mode, int Options, int Dim, int HDim>
01217 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
01218 {
01219   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01220   { transform->matrix() = other; }
01221 };
01222 
01223 template<typename Other, int Options, int Dim, int HDim>
01224 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
01225 {
01226   static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
01227   { transform->matrix() = other.template block<Dim,HDim>(0,0); }
01228 };
01229 
01230 /**********************************************************
01231 ***   Specializations of operator* with rhs EigenBase   ***
01232 **********************************************************/
01233 
01234 template<int LhsMode,int RhsMode>
01235 struct transform_product_result
01236 {
01237   enum 
01238   { 
01239     Mode =
01240       (LhsMode == (int)Projective    || RhsMode == (int)Projective    ) ? Projective :
01241       (LhsMode == (int)Affine        || RhsMode == (int)Affine        ) ? Affine :
01242       (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
01243       (LhsMode == (int)Isometry      || RhsMode == (int)Isometry      ) ? Isometry : Projective
01244   };
01245 };
01246 
01247 template< typename TransformType, typename MatrixType >
01248 struct transform_right_product_impl< TransformType, MatrixType, 0 >
01249 {
01250   typedef typename MatrixType::PlainObject ResultType;
01251 
01252   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01253   {
01254     return T.matrix() * other;
01255   }
01256 };
01257 
01258 template< typename TransformType, typename MatrixType >
01259 struct transform_right_product_impl< TransformType, MatrixType, 1 >
01260 {
01261   enum { 
01262     Dim = TransformType::Dim, 
01263     HDim = TransformType::HDim,
01264     OtherRows = MatrixType::RowsAtCompileTime,
01265     OtherCols = MatrixType::ColsAtCompileTime
01266   };
01267 
01268   typedef typename MatrixType::PlainObject ResultType;
01269 
01270   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01271   {
01272     EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01273 
01274     typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
01275 
01276     ResultType res(other.rows(),other.cols());
01277     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
01278     res.row(OtherRows-1) = other.row(OtherRows-1);
01279     
01280     return res;
01281   }
01282 };
01283 
01284 template< typename TransformType, typename MatrixType >
01285 struct transform_right_product_impl< TransformType, MatrixType, 2 >
01286 {
01287   enum { 
01288     Dim = TransformType::Dim, 
01289     HDim = TransformType::HDim,
01290     OtherRows = MatrixType::RowsAtCompileTime,
01291     OtherCols = MatrixType::ColsAtCompileTime
01292   };
01293 
01294   typedef typename MatrixType::PlainObject ResultType;
01295 
01296   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01297   {
01298     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01299 
01300     typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs;
01301     ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
01302     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
01303 
01304     return res;
01305   }
01306 };
01307 
01308 /**********************************************************
01309 ***   Specializations of operator* with lhs EigenBase   ***
01310 **********************************************************/
01311 
01312 // generic HDim x HDim matrix * T => Projective
01313 template<typename Other,int Mode, int Options, int Dim, int HDim>
01314 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
01315 {
01316   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01317   typedef typename TransformType::MatrixType MatrixType;
01318   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01319   static ResultType run(const Other& other,const TransformType& tr)
01320   { return ResultType(other * tr.matrix()); }
01321 };
01322 
01323 // generic HDim x HDim matrix * AffineCompact => Projective
01324 template<typename Other, int Options, int Dim, int HDim>
01325 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
01326 {
01327   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01328   typedef typename TransformType::MatrixType MatrixType;
01329   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01330   static ResultType run(const Other& other,const TransformType& tr)
01331   {
01332     ResultType res;
01333     res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
01334     res.matrix().col(Dim) += other.col(Dim);
01335     return res;
01336   }
01337 };
01338 
01339 // affine matrix * T
01340 template<typename Other,int Mode, int Options, int Dim, int HDim>
01341 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
01342 {
01343   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01344   typedef typename TransformType::MatrixType MatrixType;
01345   typedef TransformType ResultType;
01346   static ResultType run(const Other& other,const TransformType& tr)
01347   {
01348     ResultType res;
01349     res.affine().noalias() = other * tr.matrix();
01350     res.matrix().row(Dim) = tr.matrix().row(Dim);
01351     return res;
01352   }
01353 };
01354 
01355 // affine matrix * AffineCompact
01356 template<typename Other, int Options, int Dim, int HDim>
01357 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
01358 {
01359   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01360   typedef typename TransformType::MatrixType MatrixType;
01361   typedef TransformType ResultType;
01362   static ResultType run(const Other& other,const TransformType& tr)
01363   {
01364     ResultType res;
01365     res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
01366     res.translation() += other.col(Dim);
01367     return res;
01368   }
01369 };
01370 
01371 // linear matrix * T
01372 template<typename Other,int Mode, int Options, int Dim, int HDim>
01373 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
01374 {
01375   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01376   typedef typename TransformType::MatrixType MatrixType;
01377   typedef TransformType ResultType;
01378   static ResultType run(const Other& other, const TransformType& tr)
01379   {
01380     TransformType res;
01381     if(Mode!=int(AffineCompact))
01382       res.matrix().row(Dim) = tr.matrix().row(Dim);
01383     res.matrix().template topRows<Dim>().noalias()
01384       = other * tr.matrix().template topRows<Dim>();
01385     return res;
01386   }
01387 };
01388 
01389 /**********************************************************
01390 *** Specializations of operator* with another Transform ***
01391 **********************************************************/
01392 
01393 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01394 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
01395 {
01396   enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
01397   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01398   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01399   typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
01400   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01401   {
01402     ResultType res;
01403     res.linear() = lhs.linear() * rhs.linear();
01404     res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
01405     res.makeAffine();
01406     return res;
01407   }
01408 };
01409 
01410 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01411 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
01412 {
01413   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01414   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01415   typedef Transform<Scalar,Dim,Projective> ResultType;
01416   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01417   {
01418     return ResultType( lhs.matrix() * rhs.matrix() );
01419   }
01420 };
01421 
01422 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01423 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true >
01424 {
01425   typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs;
01426   typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs;
01427   typedef Transform<Scalar,Dim,Projective> ResultType;
01428   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01429   {
01430     ResultType res;
01431     res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
01432     res.matrix().row(Dim) = rhs.matrix().row(Dim);
01433     return res;
01434   }
01435 };
01436 
01437 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01438 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true >
01439 {
01440   typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs;
01441   typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs;
01442   typedef Transform<Scalar,Dim,Projective> ResultType;
01443   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01444   {
01445     ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
01446     res.matrix().col(Dim) += lhs.matrix().col(Dim);
01447     return res;
01448   }
01449 };
01450 
01451 } // end namespace internal
01452 
01453 } // end namespace Eigen
01454 
01455 #endif // EIGEN_TRANSFORM_H


turtlebot_exploration_3d
Author(s): Bona , Shawn
autogenerated on Thu Jun 6 2019 21:00:22