Eigen  3.2.8
Transform.h
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 
00183 template<typename _Scalar, int _Dim, int _Mode, int _Options>
00184 class Transform
00185 {
00186 public:
00187   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00188   enum {
00189     Mode = _Mode,
00190     Options = _Options,
00191     Dim = _Dim,     
00192     HDim = _Dim+1,  
00193     Rows = int(Mode)==(AffineCompact) ? Dim : HDim
00194   };
00196   typedef _Scalar Scalar;
00197   typedef DenseIndex Index;
00199   typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
00201   typedef const MatrixType ConstMatrixType;
00203   typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
00205   typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
00207   typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
00209   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00210                               MatrixType&,
00211                               Block<MatrixType,Dim,HDim> >::type AffinePart;
00213   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00214                               const MatrixType&,
00215                               const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
00217   typedef Matrix<Scalar,Dim,1> VectorType;
00219   typedef Block<MatrixType,Dim,1,int(Mode)==(AffineCompact)> TranslationPart;
00221   typedef const Block<ConstMatrixType,Dim,1,int(Mode)==(AffineCompact)> ConstTranslationPart;
00223   typedef Translation<Scalar,Dim> TranslationType;
00224   
00225   // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
00226   enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
00228   typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
00229 
00230 protected:
00231 
00232   MatrixType m_matrix;
00233 
00234 public:
00235 
00238   inline Transform()
00239   {
00240     check_template_params();
00241     internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
00242   }
00243 
00244   inline Transform(const Transform& other)
00245   {
00246     check_template_params();
00247     m_matrix = other.m_matrix;
00248   }
00249 
00250   inline explicit Transform(const TranslationType& t)
00251   {
00252     check_template_params();
00253     *this = t;
00254   }
00255   inline explicit Transform(const UniformScaling<Scalar>& s)
00256   {
00257     check_template_params();
00258     *this = s;
00259   }
00260   template<typename Derived>
00261   inline explicit Transform(const RotationBase<Derived, Dim>& r)
00262   {
00263     check_template_params();
00264     *this = r;
00265   }
00266 
00267   inline Transform& operator=(const Transform& other)
00268   { m_matrix = other.m_matrix; return *this; }
00269 
00270   typedef internal::transform_take_affine_part<Transform> take_affine_part;
00271 
00273   template<typename OtherDerived>
00274   inline explicit Transform(const EigenBase<OtherDerived>& other)
00275   {
00276     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00277       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00278 
00279     check_template_params();
00280     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00281   }
00282 
00284   template<typename OtherDerived>
00285   inline Transform& operator=(const EigenBase<OtherDerived>& other)
00286   {
00287     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00288       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00289 
00290     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00291     return *this;
00292   }
00293   
00294   template<int OtherOptions>
00295   inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
00296   {
00297     check_template_params();
00298     // only the options change, we can directly copy the matrices
00299     m_matrix = other.matrix();
00300   }
00301 
00302   template<int OtherMode,int OtherOptions>
00303   inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
00304   {
00305     check_template_params();
00306     // prevent conversions as:
00307     // Affine | AffineCompact | Isometry = Projective
00308     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
00309                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00310 
00311     // prevent conversions as:
00312     // Isometry = Affine | AffineCompact
00313     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
00314                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00315 
00316     enum { ModeIsAffineCompact = Mode == int(AffineCompact),
00317            OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
00318     };
00319 
00320     if(ModeIsAffineCompact == OtherModeIsAffineCompact)
00321     {
00322       // We need the block expression because the code is compiled for all
00323       // combinations of transformations and will trigger a compile time error
00324       // if one tries to assign the matrices directly
00325       m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
00326       makeAffine();
00327     }
00328     else if(OtherModeIsAffineCompact)
00329     {
00330       typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
00331       internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
00332     }
00333     else
00334     {
00335       // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
00336       // if OtherMode were Projective, the static assert above would already have caught it.
00337       // So the only possibility is that OtherMode == Affine
00338       linear() = other.linear();
00339       translation() = other.translation();
00340     }
00341   }
00342 
00343   template<typename OtherDerived>
00344   Transform(const ReturnByValue<OtherDerived>& other)
00345   {
00346     check_template_params();
00347     other.evalTo(*this);
00348   }
00349 
00350   template<typename OtherDerived>
00351   Transform& operator=(const ReturnByValue<OtherDerived>& other)
00352   {
00353     other.evalTo(*this);
00354     return *this;
00355   }
00356 
00357   #ifdef EIGEN_QT_SUPPORT
00358   inline Transform(const QMatrix& other);
00359   inline Transform& operator=(const QMatrix& other);
00360   inline QMatrix toQMatrix(void) const;
00361   inline Transform(const QTransform& other);
00362   inline Transform& operator=(const QTransform& other);
00363   inline QTransform toQTransform(void) const;
00364   #endif
00365 
00368   inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
00371   inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
00372 
00374   inline const MatrixType& matrix() const { return m_matrix; }
00376   inline MatrixType& matrix() { return m_matrix; }
00377 
00379   inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
00381   inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
00382 
00384   inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
00386   inline AffinePart affine() { return take_affine_part::run(m_matrix); }
00387 
00389   inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
00391   inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
00392 
00417   // note: this function is defined here because some compilers cannot find the respective declaration
00418   template<typename OtherDerived>
00419   EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject
00420   operator * (const EigenBase<OtherDerived> &other) const
00421   { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
00422 
00430   template<typename OtherDerived> friend
00431   inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
00432     operator * (const EigenBase<OtherDerived> &a, const Transform &b)
00433   { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
00434 
00441   template<typename DiagonalDerived>
00442   inline const TransformTimeDiagonalReturnType
00443     operator * (const DiagonalBase<DiagonalDerived> &b) const
00444   {
00445     TransformTimeDiagonalReturnType res(*this);
00446     res.linear() *= b;
00447     return res;
00448   }
00449 
00456   template<typename DiagonalDerived>
00457   friend inline TransformTimeDiagonalReturnType
00458     operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
00459   {
00460     TransformTimeDiagonalReturnType res;
00461     res.linear().noalias() = a*b.linear();
00462     res.translation().noalias() = a*b.translation();
00463     if (Mode!=int(AffineCompact))
00464       res.matrix().row(Dim) = b.matrix().row(Dim);
00465     return res;
00466   }
00467 
00468   template<typename OtherDerived>
00469   inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
00470 
00472   inline const Transform operator * (const Transform& other) const
00473   {
00474     return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
00475   }
00476   
00477   #ifdef __INTEL_COMPILER
00478 private:
00479   // this intermediate structure permits to workaround a bug in ICC 11:
00480   //   error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
00481   //             (const Eigen::Transform<double, 3, 2, 0> &) const"
00482   //  (the meaning of a name may have changed since the template declaration -- the type of the template is:
00483   // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
00484   //     Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
00485   // 
00486   template<int OtherMode,int OtherOptions> struct icc_11_workaround
00487   {
00488     typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType;
00489     typedef typename ProductType::ResultType ResultType;
00490   };
00491   
00492 public:
00494   template<int OtherMode,int OtherOptions>
00495   inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
00496     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00497   {
00498     typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
00499     return ProductType::run(*this,other);
00500   }
00501   #else
00502 
00503   template<int OtherMode,int OtherOptions>
00504   inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
00505     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00506   {
00507     return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
00508   }
00509   #endif
00510 
00512   void setIdentity() { m_matrix.setIdentity(); }
00513 
00518   static const Transform Identity()
00519   {
00520     return Transform(MatrixType::Identity());
00521   }
00522 
00523   template<typename OtherDerived>
00524   inline Transform& scale(const MatrixBase<OtherDerived> &other);
00525 
00526   template<typename OtherDerived>
00527   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00528 
00529   inline Transform& scale(const Scalar& s);
00530   inline Transform& prescale(const Scalar& s);
00531 
00532   template<typename OtherDerived>
00533   inline Transform& translate(const MatrixBase<OtherDerived> &other);
00534 
00535   template<typename OtherDerived>
00536   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00537 
00538   template<typename RotationType>
00539   inline Transform& rotate(const RotationType& rotation);
00540 
00541   template<typename RotationType>
00542   inline Transform& prerotate(const RotationType& rotation);
00543 
00544   Transform& shear(const Scalar& sx, const Scalar& sy);
00545   Transform& preshear(const Scalar& sx, const Scalar& sy);
00546 
00547   inline Transform& operator=(const TranslationType& t);
00548   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00549   inline Transform operator*(const TranslationType& t) const;
00550 
00551   inline Transform& operator=(const UniformScaling<Scalar>& t);
00552   inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
00553   inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode))> operator*(const UniformScaling<Scalar>& s) const
00554   {
00555     Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode)),Options> res = *this;
00556     res.scale(s.factor());
00557     return res;
00558   }
00559 
00560   inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
00561 
00562   template<typename Derived>
00563   inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00564   template<typename Derived>
00565   inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00566   template<typename Derived>
00567   inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00568 
00569   const LinearMatrixType rotation() const;
00570   template<typename RotationMatrixType, typename ScalingMatrixType>
00571   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00572   template<typename ScalingMatrixType, typename RotationMatrixType>
00573   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00574 
00575   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00576   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00577     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00578 
00579   inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
00580 
00582   const Scalar* data() const { return m_matrix.data(); }
00584   Scalar* data() { return m_matrix.data(); }
00585 
00591   template<typename NewScalarType>
00592   inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
00593   { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
00594 
00596   template<typename OtherScalarType>
00597   inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
00598   {
00599     check_template_params();
00600     m_matrix = other.matrix().template cast<Scalar>();
00601   }
00602 
00607   bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
00608   { return m_matrix.isApprox(other.m_matrix, prec); }
00609 
00612   void makeAffine()
00613   {
00614     internal::transform_make_affine<int(Mode)>::run(m_matrix);
00615   }
00616 
00621   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
00622   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00627   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
00628   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00629 
00634   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
00635   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00640   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
00641   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00642 
00643 
00644   #ifdef EIGEN_TRANSFORM_PLUGIN
00645   #include EIGEN_TRANSFORM_PLUGIN
00646   #endif
00647   
00648 protected:
00649   #ifndef EIGEN_PARSED_BY_DOXYGEN
00650     static EIGEN_STRONG_INLINE void check_template_params()
00651     {
00652       EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
00653     }
00654   #endif
00655 
00656 };
00657 
00659 typedef Transform<float,2,Isometry> Isometry2f;
00661 typedef Transform<float,3,Isometry> Isometry3f;
00663 typedef Transform<double,2,Isometry> Isometry2d;
00665 typedef Transform<double,3,Isometry> Isometry3d;
00666 
00668 typedef Transform<float,2,Affine> Affine2f;
00670 typedef Transform<float,3,Affine> Affine3f;
00672 typedef Transform<double,2,Affine> Affine2d;
00674 typedef Transform<double,3,Affine> Affine3d;
00675 
00677 typedef Transform<float,2,AffineCompact> AffineCompact2f;
00679 typedef Transform<float,3,AffineCompact> AffineCompact3f;
00681 typedef Transform<double,2,AffineCompact> AffineCompact2d;
00683 typedef Transform<double,3,AffineCompact> AffineCompact3d;
00684 
00686 typedef Transform<float,2,Projective> Projective2f;
00688 typedef Transform<float,3,Projective> Projective3f;
00690 typedef Transform<double,2,Projective> Projective2d;
00692 typedef Transform<double,3,Projective> Projective3d;
00693 
00694 /**************************
00695 *** Optional QT support ***
00696 **************************/
00697 
00698 #ifdef EIGEN_QT_SUPPORT
00699 
00703 template<typename Scalar, int Dim, int Mode,int Options>
00704 Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
00705 {
00706   check_template_params();
00707   *this = other;
00708 }
00709 
00714 template<typename Scalar, int Dim, int Mode,int Options>
00715 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
00716 {
00717   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00718   m_matrix << other.m11(), other.m21(), other.dx(),
00719               other.m12(), other.m22(), other.dy(),
00720               0, 0, 1;
00721   return *this;
00722 }
00723 
00730 template<typename Scalar, int Dim, int Mode, int Options>
00731 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
00732 {
00733   check_template_params();
00734   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00735   return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00736                  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00737                  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00738 }
00739 
00744 template<typename Scalar, int Dim, int Mode,int Options>
00745 Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
00746 {
00747   check_template_params();
00748   *this = other;
00749 }
00750 
00755 template<typename Scalar, int Dim, int Mode, int Options>
00756 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
00757 {
00758   check_template_params();
00759   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00760   if (Mode == int(AffineCompact))
00761     m_matrix << other.m11(), other.m21(), other.dx(),
00762                 other.m12(), other.m22(), other.dy();
00763   else
00764     m_matrix << other.m11(), other.m21(), other.dx(),
00765                 other.m12(), other.m22(), other.dy(),
00766                 other.m13(), other.m23(), other.m33();
00767   return *this;
00768 }
00769 
00774 template<typename Scalar, int Dim, int Mode, int Options>
00775 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
00776 {
00777   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00778   if (Mode == int(AffineCompact))
00779     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00780                       m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00781                       m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00782   else
00783     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00784                       m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00785                       m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00786 }
00787 #endif
00788 
00789 /*********************
00790 *** Procedural API ***
00791 *********************/
00792 
00797 template<typename Scalar, int Dim, int Mode, int Options>
00798 template<typename OtherDerived>
00799 Transform<Scalar,Dim,Mode,Options>&
00800 Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
00801 {
00802   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00803   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00804   linearExt().noalias() = (linearExt() * other.asDiagonal());
00805   return *this;
00806 }
00807 
00812 template<typename Scalar, int Dim, int Mode, int Options>
00813 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
00814 {
00815   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00816   linearExt() *= s;
00817   return *this;
00818 }
00819 
00824 template<typename Scalar, int Dim, int Mode, int Options>
00825 template<typename OtherDerived>
00826 Transform<Scalar,Dim,Mode,Options>&
00827 Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
00828 {
00829   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00830   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00831   m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
00832   return *this;
00833 }
00834 
00839 template<typename Scalar, int Dim, int Mode, int Options>
00840 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
00841 {
00842   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00843   m_matrix.template topRows<Dim>() *= s;
00844   return *this;
00845 }
00846 
00851 template<typename Scalar, int Dim, int Mode, int Options>
00852 template<typename OtherDerived>
00853 Transform<Scalar,Dim,Mode,Options>&
00854 Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
00855 {
00856   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00857   translationExt() += linearExt() * other;
00858   return *this;
00859 }
00860 
00865 template<typename Scalar, int Dim, int Mode, int Options>
00866 template<typename OtherDerived>
00867 Transform<Scalar,Dim,Mode,Options>&
00868 Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
00869 {
00870   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00871   if(int(Mode)==int(Projective))
00872     affine() += other * m_matrix.row(Dim);
00873   else
00874     translation() += other;
00875   return *this;
00876 }
00877 
00895 template<typename Scalar, int Dim, int Mode, int Options>
00896 template<typename RotationType>
00897 Transform<Scalar,Dim,Mode,Options>&
00898 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
00899 {
00900   linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
00901   return *this;
00902 }
00903 
00911 template<typename Scalar, int Dim, int Mode, int Options>
00912 template<typename RotationType>
00913 Transform<Scalar,Dim,Mode,Options>&
00914 Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
00915 {
00916   m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
00917                                          * m_matrix.template block<Dim,HDim>(0,0);
00918   return *this;
00919 }
00920 
00926 template<typename Scalar, int Dim, int Mode, int Options>
00927 Transform<Scalar,Dim,Mode,Options>&
00928 Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
00929 {
00930   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00931   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00932   VectorType tmp = linear().col(0)*sy + linear().col(1);
00933   linear() << linear().col(0) + linear().col(1)*sx, tmp;
00934   return *this;
00935 }
00936 
00942 template<typename Scalar, int Dim, int Mode, int Options>
00943 Transform<Scalar,Dim,Mode,Options>&
00944 Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
00945 {
00946   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00947   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00948   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00949   return *this;
00950 }
00951 
00952 /******************************************************
00953 *** Scaling, Translation and Rotation compatibility ***
00954 ******************************************************/
00955 
00956 template<typename Scalar, int Dim, int Mode, int Options>
00957 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
00958 {
00959   linear().setIdentity();
00960   translation() = t.vector();
00961   makeAffine();
00962   return *this;
00963 }
00964 
00965 template<typename Scalar, int Dim, int Mode, int Options>
00966 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
00967 {
00968   Transform res = *this;
00969   res.translate(t.vector());
00970   return res;
00971 }
00972 
00973 template<typename Scalar, int Dim, int Mode, int Options>
00974 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
00975 {
00976   m_matrix.setZero();
00977   linear().diagonal().fill(s.factor());
00978   makeAffine();
00979   return *this;
00980 }
00981 
00982 template<typename Scalar, int Dim, int Mode, int Options>
00983 template<typename Derived>
00984 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
00985 {
00986   linear() = internal::toRotationMatrix<Scalar,Dim>(r);
00987   translation().setZero();
00988   makeAffine();
00989   return *this;
00990 }
00991 
00992 template<typename Scalar, int Dim, int Mode, int Options>
00993 template<typename Derived>
00994 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
00995 {
00996   Transform res = *this;
00997   res.rotate(r.derived());
00998   return res;
00999 }
01000 
01001 /************************
01002 *** Special functions ***
01003 ************************/
01004 
01012 template<typename Scalar, int Dim, int Mode, int Options>
01013 const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
01014 Transform<Scalar,Dim,Mode,Options>::rotation() const
01015 {
01016   LinearMatrixType result;
01017   computeRotationScaling(&result, (LinearMatrixType*)0);
01018   return result;
01019 }
01020 
01021 
01033 template<typename Scalar, int Dim, int Mode, int Options>
01034 template<typename RotationMatrixType, typename ScalingMatrixType>
01035 void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
01036 {
01037   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01038 
01039   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01040   VectorType sv(svd.singularValues());
01041   sv.coeffRef(0) *= x;
01042   if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
01043   if(rotation)
01044   {
01045     LinearMatrixType m(svd.matrixU());
01046     m.col(0) /= x;
01047     rotation->lazyAssign(m * svd.matrixV().adjoint());
01048   }
01049 }
01050 
01062 template<typename Scalar, int Dim, int Mode, int Options>
01063 template<typename ScalingMatrixType, typename RotationMatrixType>
01064 void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
01065 {
01066   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01067 
01068   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01069   VectorType sv(svd.singularValues());
01070   sv.coeffRef(0) *= x;
01071   if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
01072   if(rotation)
01073   {
01074     LinearMatrixType m(svd.matrixU());
01075     m.col(0) /= x;
01076     rotation->lazyAssign(m * svd.matrixV().adjoint());
01077   }
01078 }
01079 
01083 template<typename Scalar, int Dim, int Mode, int Options>
01084 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
01085 Transform<Scalar,Dim,Mode,Options>&
01086 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
01087   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
01088 {
01089   linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
01090   linear() *= scale.asDiagonal();
01091   translation() = position;
01092   makeAffine();
01093   return *this;
01094 }
01095 
01096 namespace internal {
01097 
01098 template<int Mode>
01099 struct transform_make_affine
01100 {
01101   template<typename MatrixType>
01102   static void run(MatrixType &mat)
01103   {
01104     static const int Dim = MatrixType::ColsAtCompileTime-1;
01105     mat.template block<1,Dim>(Dim,0).setZero();
01106     mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
01107   }
01108 };
01109 
01110 template<>
01111 struct transform_make_affine<AffineCompact>
01112 {
01113   template<typename MatrixType> static void run(MatrixType &) { }
01114 };
01115     
01116 // selector needed to avoid taking the inverse of a 3x4 matrix
01117 template<typename TransformType, int Mode=TransformType::Mode>
01118 struct projective_transform_inverse
01119 {
01120   static inline void run(const TransformType&, TransformType&)
01121   {}
01122 };
01123 
01124 template<typename TransformType>
01125 struct projective_transform_inverse<TransformType, Projective>
01126 {
01127   static inline void run(const TransformType& m, TransformType& res)
01128   {
01129     res.matrix() = m.matrix().inverse();
01130   }
01131 };
01132 
01133 } // end namespace internal
01134 
01135 
01156 template<typename Scalar, int Dim, int Mode, int Options>
01157 Transform<Scalar,Dim,Mode,Options>
01158 Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
01159 {
01160   Transform res;
01161   if (hint == Projective)
01162   {
01163     internal::projective_transform_inverse<Transform>::run(*this, res);
01164   }
01165   else
01166   {
01167     if (hint == Isometry)
01168     {
01169       res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
01170     }
01171     else if(hint&Affine)
01172     {
01173       res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
01174     }
01175     else
01176     {
01177       eigen_assert(false && "Invalid transform traits in Transform::Inverse");
01178     }
01179     // translation and remaining parts
01180     res.matrix().template topRightCorner<Dim,1>()
01181       = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
01182     res.makeAffine(); // we do need this, because in the beginning res is uninitialized
01183   }
01184   return res;
01185 }
01186 
01187 namespace internal {
01188 
01189 /*****************************************************
01190 *** Specializations of take affine part            ***
01191 *****************************************************/
01192 
01193 template<typename TransformType> struct transform_take_affine_part {
01194   typedef typename TransformType::MatrixType MatrixType;
01195   typedef typename TransformType::AffinePart AffinePart;
01196   typedef typename TransformType::ConstAffinePart ConstAffinePart;
01197   static inline AffinePart run(MatrixType& m)
01198   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01199   static inline ConstAffinePart run(const MatrixType& m)
01200   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01201 };
01202 
01203 template<typename Scalar, int Dim, int Options>
01204 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
01205   typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
01206   static inline MatrixType& run(MatrixType& m) { return m; }
01207   static inline const MatrixType& run(const MatrixType& m) { return m; }
01208 };
01209 
01210 /*****************************************************
01211 *** Specializations of construct from matrix       ***
01212 *****************************************************/
01213 
01214 template<typename Other, int Mode, int Options, int Dim, int HDim>
01215 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
01216 {
01217   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01218   {
01219     transform->linear() = other;
01220     transform->translation().setZero();
01221     transform->makeAffine();
01222   }
01223 };
01224 
01225 template<typename Other, int Mode, int Options, int Dim, int HDim>
01226 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
01227 {
01228   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01229   {
01230     transform->affine() = other;
01231     transform->makeAffine();
01232   }
01233 };
01234 
01235 template<typename Other, int Mode, int Options, int Dim, int HDim>
01236 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
01237 {
01238   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01239   { transform->matrix() = other; }
01240 };
01241 
01242 template<typename Other, int Options, int Dim, int HDim>
01243 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
01244 {
01245   static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
01246   { transform->matrix() = other.template block<Dim,HDim>(0,0); }
01247 };
01248 
01249 /**********************************************************
01250 ***   Specializations of operator* with rhs EigenBase   ***
01251 **********************************************************/
01252 
01253 template<int LhsMode,int RhsMode>
01254 struct transform_product_result
01255 {
01256   enum 
01257   { 
01258     Mode =
01259       (LhsMode == (int)Projective    || RhsMode == (int)Projective    ) ? Projective :
01260       (LhsMode == (int)Affine        || RhsMode == (int)Affine        ) ? Affine :
01261       (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
01262       (LhsMode == (int)Isometry      || RhsMode == (int)Isometry      ) ? Isometry : Projective
01263   };
01264 };
01265 
01266 template< typename TransformType, typename MatrixType >
01267 struct transform_right_product_impl< TransformType, MatrixType, 0 >
01268 {
01269   typedef typename MatrixType::PlainObject ResultType;
01270 
01271   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01272   {
01273     return T.matrix() * other;
01274   }
01275 };
01276 
01277 template< typename TransformType, typename MatrixType >
01278 struct transform_right_product_impl< TransformType, MatrixType, 1 >
01279 {
01280   enum { 
01281     Dim = TransformType::Dim, 
01282     HDim = TransformType::HDim,
01283     OtherRows = MatrixType::RowsAtCompileTime,
01284     OtherCols = MatrixType::ColsAtCompileTime
01285   };
01286 
01287   typedef typename MatrixType::PlainObject ResultType;
01288 
01289   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01290   {
01291     EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01292 
01293     typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
01294 
01295     ResultType res(other.rows(),other.cols());
01296     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
01297     res.row(OtherRows-1) = other.row(OtherRows-1);
01298     
01299     return res;
01300   }
01301 };
01302 
01303 template< typename TransformType, typename MatrixType >
01304 struct transform_right_product_impl< TransformType, MatrixType, 2 >
01305 {
01306   enum { 
01307     Dim = TransformType::Dim, 
01308     HDim = TransformType::HDim,
01309     OtherRows = MatrixType::RowsAtCompileTime,
01310     OtherCols = MatrixType::ColsAtCompileTime
01311   };
01312 
01313   typedef typename MatrixType::PlainObject ResultType;
01314 
01315   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01316   {
01317     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01318 
01319     typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs;
01320     ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
01321     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
01322 
01323     return res;
01324   }
01325 };
01326 
01327 /**********************************************************
01328 ***   Specializations of operator* with lhs EigenBase   ***
01329 **********************************************************/
01330 
01331 // generic HDim x HDim matrix * T => Projective
01332 template<typename Other,int Mode, int Options, int Dim, int HDim>
01333 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
01334 {
01335   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01336   typedef typename TransformType::MatrixType MatrixType;
01337   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01338   static ResultType run(const Other& other,const TransformType& tr)
01339   { return ResultType(other * tr.matrix()); }
01340 };
01341 
01342 // generic HDim x HDim matrix * AffineCompact => Projective
01343 template<typename Other, int Options, int Dim, int HDim>
01344 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
01345 {
01346   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01347   typedef typename TransformType::MatrixType MatrixType;
01348   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01349   static ResultType run(const Other& other,const TransformType& tr)
01350   {
01351     ResultType res;
01352     res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
01353     res.matrix().col(Dim) += other.col(Dim);
01354     return res;
01355   }
01356 };
01357 
01358 // affine matrix * T
01359 template<typename Other,int Mode, int Options, int Dim, int HDim>
01360 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
01361 {
01362   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01363   typedef typename TransformType::MatrixType MatrixType;
01364   typedef TransformType ResultType;
01365   static ResultType run(const Other& other,const TransformType& tr)
01366   {
01367     ResultType res;
01368     res.affine().noalias() = other * tr.matrix();
01369     res.matrix().row(Dim) = tr.matrix().row(Dim);
01370     return res;
01371   }
01372 };
01373 
01374 // affine matrix * AffineCompact
01375 template<typename Other, int Options, int Dim, int HDim>
01376 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
01377 {
01378   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01379   typedef typename TransformType::MatrixType MatrixType;
01380   typedef TransformType ResultType;
01381   static ResultType run(const Other& other,const TransformType& tr)
01382   {
01383     ResultType res;
01384     res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
01385     res.translation() += other.col(Dim);
01386     return res;
01387   }
01388 };
01389 
01390 // linear matrix * T
01391 template<typename Other,int Mode, int Options, int Dim, int HDim>
01392 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
01393 {
01394   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01395   typedef typename TransformType::MatrixType MatrixType;
01396   typedef TransformType ResultType;
01397   static ResultType run(const Other& other, const TransformType& tr)
01398   {
01399     TransformType res;
01400     if(Mode!=int(AffineCompact))
01401       res.matrix().row(Dim) = tr.matrix().row(Dim);
01402     res.matrix().template topRows<Dim>().noalias()
01403       = other * tr.matrix().template topRows<Dim>();
01404     return res;
01405   }
01406 };
01407 
01408 /**********************************************************
01409 *** Specializations of operator* with another Transform ***
01410 **********************************************************/
01411 
01412 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01413 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
01414 {
01415   enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
01416   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01417   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01418   typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
01419   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01420   {
01421     ResultType res;
01422     res.linear() = lhs.linear() * rhs.linear();
01423     res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
01424     res.makeAffine();
01425     return res;
01426   }
01427 };
01428 
01429 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01430 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
01431 {
01432   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01433   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01434   typedef Transform<Scalar,Dim,Projective> ResultType;
01435   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01436   {
01437     return ResultType( lhs.matrix() * rhs.matrix() );
01438   }
01439 };
01440 
01441 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01442 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true >
01443 {
01444   typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs;
01445   typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs;
01446   typedef Transform<Scalar,Dim,Projective> ResultType;
01447   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01448   {
01449     ResultType res;
01450     res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
01451     res.matrix().row(Dim) = rhs.matrix().row(Dim);
01452     return res;
01453   }
01454 };
01455 
01456 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01457 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true >
01458 {
01459   typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs;
01460   typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs;
01461   typedef Transform<Scalar,Dim,Projective> ResultType;
01462   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01463   {
01464     ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
01465     res.matrix().col(Dim) += lhs.matrix().col(Dim);
01466     return res;
01467   }
01468 };
01469 
01470 } // end namespace internal
01471 
01472 } // end namespace Eigen
01473 
01474 #endif // EIGEN_TRANSFORM_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends