Eigen  3.3.3
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           int RhsCols = MatrixType::ColsAtCompileTime>
00037 struct transform_right_product_impl;
00038 
00039 template< typename Other,
00040           int Mode,
00041           int Options,
00042           int Dim,
00043           int HDim,
00044           int OtherRows=Other::RowsAtCompileTime,
00045           int OtherCols=Other::ColsAtCompileTime>
00046 struct transform_left_product_impl;
00047 
00048 template< typename Lhs,
00049           typename Rhs,
00050           bool AnyProjective = 
00051             transform_traits<Lhs>::IsProjective ||
00052             transform_traits<Rhs>::IsProjective>
00053 struct transform_transform_product_impl;
00054 
00055 template< typename Other,
00056           int Mode,
00057           int Options,
00058           int Dim,
00059           int HDim,
00060           int OtherRows=Other::RowsAtCompileTime,
00061           int OtherCols=Other::ColsAtCompileTime>
00062 struct transform_construct_from_matrix;
00063 
00064 template<typename TransformType> struct transform_take_affine_part;
00065 
00066 template<typename _Scalar, int _Dim, int _Mode, int _Options>
00067 struct traits<Transform<_Scalar,_Dim,_Mode,_Options> >
00068 {
00069   typedef _Scalar Scalar;
00070   typedef Eigen::Index StorageIndex;
00071   typedef Dense StorageKind;
00072   enum {
00073     Dim1 = _Dim==Dynamic ? _Dim : _Dim + 1,
00074     RowsAtCompileTime = _Mode==Projective ? Dim1 : _Dim,
00075     ColsAtCompileTime = Dim1,
00076     MaxRowsAtCompileTime = RowsAtCompileTime,
00077     MaxColsAtCompileTime = ColsAtCompileTime,
00078     Flags = 0
00079   };
00080 };
00081 
00082 template<int Mode> struct transform_make_affine;
00083 
00084 } // end namespace internal
00085 
00200 template<typename _Scalar, int _Dim, int _Mode, int _Options>
00201 class Transform
00202 {
00203 public:
00204   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00205   enum {
00206     Mode = _Mode,
00207     Options = _Options,
00208     Dim = _Dim,     
00209     HDim = _Dim+1,  
00210     Rows = int(Mode)==(AffineCompact) ? Dim : HDim
00211   };
00213   typedef _Scalar Scalar;
00214   typedef Eigen::Index StorageIndex;
00215   typedef Eigen::Index Index; 
00216 
00217   typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
00219   typedef const MatrixType ConstMatrixType;
00221   typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
00223   typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart;
00225   typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart;
00227   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00228                               MatrixType&,
00229                               Block<MatrixType,Dim,HDim> >::type AffinePart;
00231   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00232                               const MatrixType&,
00233                               const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
00235   typedef Matrix<Scalar,Dim,1> VectorType;
00237   typedef Block<MatrixType,Dim,1,!(internal::traits<MatrixType>::Flags & RowMajorBit)> TranslationPart;
00239   typedef const Block<ConstMatrixType,Dim,1,!(internal::traits<MatrixType>::Flags & RowMajorBit)> ConstTranslationPart;
00241   typedef Translation<Scalar,Dim> TranslationType;
00242   
00243   // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
00244   enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
00246   typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
00247 
00248 protected:
00249 
00250   MatrixType m_matrix;
00251 
00252 public:
00253 
00256   EIGEN_DEVICE_FUNC inline Transform()
00257   {
00258     check_template_params();
00259     internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix);
00260   }
00261 
00262   EIGEN_DEVICE_FUNC inline Transform(const Transform& other)
00263   {
00264     check_template_params();
00265     m_matrix = other.m_matrix;
00266   }
00267 
00268   EIGEN_DEVICE_FUNC inline explicit Transform(const TranslationType& t)
00269   {
00270     check_template_params();
00271     *this = t;
00272   }
00273   EIGEN_DEVICE_FUNC inline explicit Transform(const UniformScaling<Scalar>& s)
00274   {
00275     check_template_params();
00276     *this = s;
00277   }
00278   template<typename Derived>
00279   EIGEN_DEVICE_FUNC inline explicit Transform(const RotationBase<Derived, Dim>& r)
00280   {
00281     check_template_params();
00282     *this = r;
00283   }
00284 
00285   EIGEN_DEVICE_FUNC inline Transform& operator=(const Transform& other)
00286   { m_matrix = other.m_matrix; return *this; }
00287 
00288   typedef internal::transform_take_affine_part<Transform> take_affine_part;
00289 
00291   template<typename OtherDerived>
00292   EIGEN_DEVICE_FUNC inline explicit Transform(const EigenBase<OtherDerived>& other)
00293   {
00294     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00295       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00296 
00297     check_template_params();
00298     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00299   }
00300 
00302   template<typename OtherDerived>
00303   EIGEN_DEVICE_FUNC inline Transform& operator=(const EigenBase<OtherDerived>& other)
00304   {
00305     EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value),
00306       YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY);
00307 
00308     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00309     return *this;
00310   }
00311   
00312   template<int OtherOptions>
00313   EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other)
00314   {
00315     check_template_params();
00316     // only the options change, we can directly copy the matrices
00317     m_matrix = other.matrix();
00318   }
00319 
00320   template<int OtherMode,int OtherOptions>
00321   EIGEN_DEVICE_FUNC inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other)
00322   {
00323     check_template_params();
00324     // prevent conversions as:
00325     // Affine | AffineCompact | Isometry = Projective
00326     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)),
00327                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00328 
00329     // prevent conversions as:
00330     // Isometry = Affine | AffineCompact
00331     EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)),
00332                         YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION)
00333 
00334     enum { ModeIsAffineCompact = Mode == int(AffineCompact),
00335            OtherModeIsAffineCompact = OtherMode == int(AffineCompact)
00336     };
00337 
00338     if(ModeIsAffineCompact == OtherModeIsAffineCompact)
00339     {
00340       // We need the block expression because the code is compiled for all
00341       // combinations of transformations and will trigger a compile time error
00342       // if one tries to assign the matrices directly
00343       m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0);
00344       makeAffine();
00345     }
00346     else if(OtherModeIsAffineCompact)
00347     {
00348       typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType;
00349       internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix());
00350     }
00351     else
00352     {
00353       // here we know that Mode == AffineCompact and OtherMode != AffineCompact.
00354       // if OtherMode were Projective, the static assert above would already have caught it.
00355       // So the only possibility is that OtherMode == Affine
00356       linear() = other.linear();
00357       translation() = other.translation();
00358     }
00359   }
00360 
00361   template<typename OtherDerived>
00362   EIGEN_DEVICE_FUNC Transform(const ReturnByValue<OtherDerived>& other)
00363   {
00364     check_template_params();
00365     other.evalTo(*this);
00366   }
00367 
00368   template<typename OtherDerived>
00369   EIGEN_DEVICE_FUNC Transform& operator=(const ReturnByValue<OtherDerived>& other)
00370   {
00371     other.evalTo(*this);
00372     return *this;
00373   }
00374 
00375   #ifdef EIGEN_QT_SUPPORT
00376   inline Transform(const QMatrix& other);
00377   inline Transform& operator=(const QMatrix& other);
00378   inline QMatrix toQMatrix(void) const;
00379   inline Transform(const QTransform& other);
00380   inline Transform& operator=(const QTransform& other);
00381   inline QTransform toQTransform(void) const;
00382   #endif
00383   
00384   EIGEN_DEVICE_FUNC Index rows() const { return int(Mode)==int(Projective) ? m_matrix.cols() : (m_matrix.cols()-1); }
00385   EIGEN_DEVICE_FUNC Index cols() const { return m_matrix.cols(); }
00386 
00389   EIGEN_DEVICE_FUNC inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); }
00392   EIGEN_DEVICE_FUNC inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); }
00393 
00395   EIGEN_DEVICE_FUNC inline const MatrixType& matrix() const { return m_matrix; }
00397   EIGEN_DEVICE_FUNC inline MatrixType& matrix() { return m_matrix; }
00398 
00400   EIGEN_DEVICE_FUNC inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); }
00402   EIGEN_DEVICE_FUNC inline LinearPart linear() { return LinearPart(m_matrix,0,0); }
00403 
00405   EIGEN_DEVICE_FUNC inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); }
00407   EIGEN_DEVICE_FUNC inline AffinePart affine() { return take_affine_part::run(m_matrix); }
00408 
00410   EIGEN_DEVICE_FUNC inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); }
00412   EIGEN_DEVICE_FUNC inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); }
00413 
00438   // note: this function is defined here because some compilers cannot find the respective declaration
00439   template<typename OtherDerived>
00440   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
00441   operator * (const EigenBase<OtherDerived> &other) const
00442   { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
00443 
00451   template<typename OtherDerived> friend
00452   EIGEN_DEVICE_FUNC inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
00453     operator * (const EigenBase<OtherDerived> &a, const Transform &b)
00454   { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
00455 
00462   template<typename DiagonalDerived>
00463   EIGEN_DEVICE_FUNC inline const TransformTimeDiagonalReturnType
00464     operator * (const DiagonalBase<DiagonalDerived> &b) const
00465   {
00466     TransformTimeDiagonalReturnType res(*this);
00467     res.linearExt() *= b;
00468     return res;
00469   }
00470 
00477   template<typename DiagonalDerived>
00478   EIGEN_DEVICE_FUNC friend inline TransformTimeDiagonalReturnType
00479     operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
00480   {
00481     TransformTimeDiagonalReturnType res;
00482     res.linear().noalias() = a*b.linear();
00483     res.translation().noalias() = a*b.translation();
00484     if (Mode!=int(AffineCompact))
00485       res.matrix().row(Dim) = b.matrix().row(Dim);
00486     return res;
00487   }
00488 
00489   template<typename OtherDerived>
00490   EIGEN_DEVICE_FUNC inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
00491 
00493   EIGEN_DEVICE_FUNC inline const Transform operator * (const Transform& other) const
00494   {
00495     return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
00496   }
00497   
00498   #if EIGEN_COMP_ICC
00499 private:
00500   // this intermediate structure permits to workaround a bug in ICC 11:
00501   //   error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0>
00502   //             (const Eigen::Transform<double, 3, 2, 0> &) const"
00503   //  (the meaning of a name may have changed since the template declaration -- the type of the template is:
00504   // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>,
00505   //     Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const")
00506   // 
00507   template<int OtherMode,int OtherOptions> struct icc_11_workaround
00508   {
00509     typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType;
00510     typedef typename ProductType::ResultType ResultType;
00511   };
00512   
00513 public:
00515   template<int OtherMode,int OtherOptions>
00516   inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType
00517     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00518   {
00519     typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType;
00520     return ProductType::run(*this,other);
00521   }
00522   #else
00523 
00524   template<int OtherMode,int OtherOptions>
00525   EIGEN_DEVICE_FUNC inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
00526     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00527   {
00528     return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
00529   }
00530   #endif
00531 
00533   EIGEN_DEVICE_FUNC void setIdentity() { m_matrix.setIdentity(); }
00534 
00539   EIGEN_DEVICE_FUNC static const Transform Identity()
00540   {
00541     return Transform(MatrixType::Identity());
00542   }
00543 
00544   template<typename OtherDerived>
00545   EIGEN_DEVICE_FUNC 
00546   inline Transform& scale(const MatrixBase<OtherDerived> &other);
00547 
00548   template<typename OtherDerived>
00549   EIGEN_DEVICE_FUNC
00550   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00551 
00552   EIGEN_DEVICE_FUNC inline Transform& scale(const Scalar& s);
00553   EIGEN_DEVICE_FUNC inline Transform& prescale(const Scalar& s);
00554 
00555   template<typename OtherDerived>
00556   EIGEN_DEVICE_FUNC
00557   inline Transform& translate(const MatrixBase<OtherDerived> &other);
00558 
00559   template<typename OtherDerived>
00560   EIGEN_DEVICE_FUNC
00561   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00562 
00563   template<typename RotationType>
00564   EIGEN_DEVICE_FUNC
00565   inline Transform& rotate(const RotationType& rotation);
00566 
00567   template<typename RotationType>
00568   EIGEN_DEVICE_FUNC
00569   inline Transform& prerotate(const RotationType& rotation);
00570 
00571   EIGEN_DEVICE_FUNC Transform& shear(const Scalar& sx, const Scalar& sy);
00572   EIGEN_DEVICE_FUNC Transform& preshear(const Scalar& sx, const Scalar& sy);
00573 
00574   EIGEN_DEVICE_FUNC inline Transform& operator=(const TranslationType& t);
00575   
00576   EIGEN_DEVICE_FUNC
00577   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00578   
00579   EIGEN_DEVICE_FUNC inline Transform operator*(const TranslationType& t) const;
00580 
00581   EIGEN_DEVICE_FUNC 
00582   inline Transform& operator=(const UniformScaling<Scalar>& t);
00583   
00584   EIGEN_DEVICE_FUNC
00585   inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
00586   
00587   EIGEN_DEVICE_FUNC
00588   inline TransformTimeDiagonalReturnType operator*(const UniformScaling<Scalar>& s) const
00589   {
00590     TransformTimeDiagonalReturnType res = *this;
00591     res.scale(s.factor());
00592     return res;
00593   }
00594 
00595   EIGEN_DEVICE_FUNC
00596   inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linearExt() *= s; return *this; }
00597 
00598   template<typename Derived>
00599   EIGEN_DEVICE_FUNC inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00600   template<typename Derived>
00601   EIGEN_DEVICE_FUNC inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00602   template<typename Derived>
00603   EIGEN_DEVICE_FUNC inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00604 
00605   EIGEN_DEVICE_FUNC const LinearMatrixType rotation() const;
00606   template<typename RotationMatrixType, typename ScalingMatrixType>
00607   EIGEN_DEVICE_FUNC
00608   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00609   template<typename ScalingMatrixType, typename RotationMatrixType>
00610   EIGEN_DEVICE_FUNC
00611   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00612 
00613   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00614   EIGEN_DEVICE_FUNC
00615   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00616     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00617 
00618   EIGEN_DEVICE_FUNC
00619   inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
00620 
00622   EIGEN_DEVICE_FUNC const Scalar* data() const { return m_matrix.data(); }
00624   EIGEN_DEVICE_FUNC Scalar* data() { return m_matrix.data(); }
00625 
00631   template<typename NewScalarType>
00632   EIGEN_DEVICE_FUNC inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
00633   { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
00634 
00636   template<typename OtherScalarType>
00637   EIGEN_DEVICE_FUNC inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
00638   {
00639     check_template_params();
00640     m_matrix = other.matrix().template cast<Scalar>();
00641   }
00642 
00647   EIGEN_DEVICE_FUNC bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
00648   { return m_matrix.isApprox(other.m_matrix, prec); }
00649 
00652   EIGEN_DEVICE_FUNC void makeAffine()
00653   {
00654     internal::transform_make_affine<int(Mode)>::run(m_matrix);
00655   }
00656 
00661   EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
00662   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00667   EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
00668   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00669 
00674   EIGEN_DEVICE_FUNC inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
00675   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00680   EIGEN_DEVICE_FUNC inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
00681   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00682 
00683 
00684   #ifdef EIGEN_TRANSFORM_PLUGIN
00685   #include EIGEN_TRANSFORM_PLUGIN
00686   #endif
00687   
00688 protected:
00689   #ifndef EIGEN_PARSED_BY_DOXYGEN
00690     EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void check_template_params()
00691     {
00692       EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
00693     }
00694   #endif
00695 
00696 };
00697 
00699 typedef Transform<float,2,Isometry> Isometry2f;
00701 typedef Transform<float,3,Isometry> Isometry3f;
00703 typedef Transform<double,2,Isometry> Isometry2d;
00705 typedef Transform<double,3,Isometry> Isometry3d;
00706 
00708 typedef Transform<float,2,Affine> Affine2f;
00710 typedef Transform<float,3,Affine> Affine3f;
00712 typedef Transform<double,2,Affine> Affine2d;
00714 typedef Transform<double,3,Affine> Affine3d;
00715 
00717 typedef Transform<float,2,AffineCompact> AffineCompact2f;
00719 typedef Transform<float,3,AffineCompact> AffineCompact3f;
00721 typedef Transform<double,2,AffineCompact> AffineCompact2d;
00723 typedef Transform<double,3,AffineCompact> AffineCompact3d;
00724 
00726 typedef Transform<float,2,Projective> Projective2f;
00728 typedef Transform<float,3,Projective> Projective3f;
00730 typedef Transform<double,2,Projective> Projective2d;
00732 typedef Transform<double,3,Projective> Projective3d;
00733 
00734 /**************************
00735 *** Optional QT support ***
00736 **************************/
00737 
00738 #ifdef EIGEN_QT_SUPPORT
00739 
00743 template<typename Scalar, int Dim, int Mode,int Options>
00744 Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
00745 {
00746   check_template_params();
00747   *this = other;
00748 }
00749 
00754 template<typename Scalar, int Dim, int Mode,int Options>
00755 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
00756 {
00757   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00758   if (Mode == int(AffineCompact))
00759     m_matrix << other.m11(), other.m21(), other.dx(),
00760                 other.m12(), other.m22(), other.dy();
00761   else
00762     m_matrix << other.m11(), other.m21(), other.dx(),
00763                 other.m12(), other.m22(), other.dy(),
00764                 0, 0, 1;
00765   return *this;
00766 }
00767 
00774 template<typename Scalar, int Dim, int Mode, int Options>
00775 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
00776 {
00777   check_template_params();
00778   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00779   return QMatrix(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 }
00783 
00788 template<typename Scalar, int Dim, int Mode,int Options>
00789 Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
00790 {
00791   check_template_params();
00792   *this = other;
00793 }
00794 
00799 template<typename Scalar, int Dim, int Mode, int Options>
00800 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
00801 {
00802   check_template_params();
00803   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00804   if (Mode == int(AffineCompact))
00805     m_matrix << other.m11(), other.m21(), other.dx(),
00806                 other.m12(), other.m22(), other.dy();
00807   else
00808     m_matrix << other.m11(), other.m21(), other.dx(),
00809                 other.m12(), other.m22(), other.dy(),
00810                 other.m13(), other.m23(), other.m33();
00811   return *this;
00812 }
00813 
00818 template<typename Scalar, int Dim, int Mode, int Options>
00819 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
00820 {
00821   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00822   if (Mode == int(AffineCompact))
00823     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00824                       m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00825                       m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00826   else
00827     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00828                       m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00829                       m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00830 }
00831 #endif
00832 
00833 /*********************
00834 *** Procedural API ***
00835 *********************/
00836 
00841 template<typename Scalar, int Dim, int Mode, int Options>
00842 template<typename OtherDerived>
00843 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00844 Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
00845 {
00846   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00847   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00848   linearExt().noalias() = (linearExt() * other.asDiagonal());
00849   return *this;
00850 }
00851 
00856 template<typename Scalar, int Dim, int Mode, int Options>
00857 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s)
00858 {
00859   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00860   linearExt() *= s;
00861   return *this;
00862 }
00863 
00868 template<typename Scalar, int Dim, int Mode, int Options>
00869 template<typename OtherDerived>
00870 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00871 Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
00872 {
00873   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00874   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00875   affine().noalias() = (other.asDiagonal() * affine());
00876   return *this;
00877 }
00878 
00883 template<typename Scalar, int Dim, int Mode, int Options>
00884 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s)
00885 {
00886   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00887   m_matrix.template topRows<Dim>() *= s;
00888   return *this;
00889 }
00890 
00895 template<typename Scalar, int Dim, int Mode, int Options>
00896 template<typename OtherDerived>
00897 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00898 Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
00899 {
00900   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00901   translationExt() += linearExt() * other;
00902   return *this;
00903 }
00904 
00909 template<typename Scalar, int Dim, int Mode, int Options>
00910 template<typename OtherDerived>
00911 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00912 Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
00913 {
00914   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00915   if(int(Mode)==int(Projective))
00916     affine() += other * m_matrix.row(Dim);
00917   else
00918     translation() += other;
00919   return *this;
00920 }
00921 
00939 template<typename Scalar, int Dim, int Mode, int Options>
00940 template<typename RotationType>
00941 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00942 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
00943 {
00944   linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
00945   return *this;
00946 }
00947 
00955 template<typename Scalar, int Dim, int Mode, int Options>
00956 template<typename RotationType>
00957 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00958 Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
00959 {
00960   m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
00961                                          * m_matrix.template block<Dim,HDim>(0,0);
00962   return *this;
00963 }
00964 
00970 template<typename Scalar, int Dim, int Mode, int Options>
00971 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00972 Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy)
00973 {
00974   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00975   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00976   VectorType tmp = linear().col(0)*sy + linear().col(1);
00977   linear() << linear().col(0) + linear().col(1)*sx, tmp;
00978   return *this;
00979 }
00980 
00986 template<typename Scalar, int Dim, int Mode, int Options>
00987 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
00988 Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy)
00989 {
00990   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00991   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00992   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00993   return *this;
00994 }
00995 
00996 /******************************************************
00997 *** Scaling, Translation and Rotation compatibility ***
00998 ******************************************************/
00999 
01000 template<typename Scalar, int Dim, int Mode, int Options>
01001 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
01002 {
01003   linear().setIdentity();
01004   translation() = t.vector();
01005   makeAffine();
01006   return *this;
01007 }
01008 
01009 template<typename Scalar, int Dim, int Mode, int Options>
01010 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
01011 {
01012   Transform res = *this;
01013   res.translate(t.vector());
01014   return res;
01015 }
01016 
01017 template<typename Scalar, int Dim, int Mode, int Options>
01018 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
01019 {
01020   m_matrix.setZero();
01021   linear().diagonal().fill(s.factor());
01022   makeAffine();
01023   return *this;
01024 }
01025 
01026 template<typename Scalar, int Dim, int Mode, int Options>
01027 template<typename Derived>
01028 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
01029 {
01030   linear() = internal::toRotationMatrix<Scalar,Dim>(r);
01031   translation().setZero();
01032   makeAffine();
01033   return *this;
01034 }
01035 
01036 template<typename Scalar, int Dim, int Mode, int Options>
01037 template<typename Derived>
01038 EIGEN_DEVICE_FUNC inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
01039 {
01040   Transform res = *this;
01041   res.rotate(r.derived());
01042   return res;
01043 }
01044 
01045 /************************
01046 *** Special functions ***
01047 ************************/
01048 
01056 template<typename Scalar, int Dim, int Mode, int Options>
01057 EIGEN_DEVICE_FUNC const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
01058 Transform<Scalar,Dim,Mode,Options>::rotation() const
01059 {
01060   LinearMatrixType result;
01061   computeRotationScaling(&result, (LinearMatrixType*)0);
01062   return result;
01063 }
01064 
01065 
01077 template<typename Scalar, int Dim, int Mode, int Options>
01078 template<typename RotationMatrixType, typename ScalingMatrixType>
01079 EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
01080 {
01081   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01082 
01083   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01084   VectorType sv(svd.singularValues());
01085   sv.coeffRef(0) *= x;
01086   if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
01087   if(rotation)
01088   {
01089     LinearMatrixType m(svd.matrixU());
01090     m.col(0) /= x;
01091     rotation->lazyAssign(m * svd.matrixV().adjoint());
01092   }
01093 }
01094 
01106 template<typename Scalar, int Dim, int Mode, int Options>
01107 template<typename ScalingMatrixType, typename RotationMatrixType>
01108 EIGEN_DEVICE_FUNC void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
01109 {
01110   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01111 
01112   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01113   VectorType sv(svd.singularValues());
01114   sv.coeffRef(0) *= x;
01115   if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
01116   if(rotation)
01117   {
01118     LinearMatrixType m(svd.matrixU());
01119     m.col(0) /= x;
01120     rotation->lazyAssign(m * svd.matrixV().adjoint());
01121   }
01122 }
01123 
01127 template<typename Scalar, int Dim, int Mode, int Options>
01128 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
01129 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>&
01130 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
01131   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
01132 {
01133   linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
01134   linear() *= scale.asDiagonal();
01135   translation() = position;
01136   makeAffine();
01137   return *this;
01138 }
01139 
01140 namespace internal {
01141 
01142 template<int Mode>
01143 struct transform_make_affine
01144 {
01145   template<typename MatrixType>
01146   EIGEN_DEVICE_FUNC static void run(MatrixType &mat)
01147   {
01148     static const int Dim = MatrixType::ColsAtCompileTime-1;
01149     mat.template block<1,Dim>(Dim,0).setZero();
01150     mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1);
01151   }
01152 };
01153 
01154 template<>
01155 struct transform_make_affine<AffineCompact>
01156 {
01157   template<typename MatrixType> EIGEN_DEVICE_FUNC static void run(MatrixType &) { }
01158 };
01159     
01160 // selector needed to avoid taking the inverse of a 3x4 matrix
01161 template<typename TransformType, int Mode=TransformType::Mode>
01162 struct projective_transform_inverse
01163 {
01164   EIGEN_DEVICE_FUNC static inline void run(const TransformType&, TransformType&)
01165   {}
01166 };
01167 
01168 template<typename TransformType>
01169 struct projective_transform_inverse<TransformType, Projective>
01170 {
01171   EIGEN_DEVICE_FUNC static inline void run(const TransformType& m, TransformType& res)
01172   {
01173     res.matrix() = m.matrix().inverse();
01174   }
01175 };
01176 
01177 } // end namespace internal
01178 
01179 
01200 template<typename Scalar, int Dim, int Mode, int Options>
01201 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>
01202 Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
01203 {
01204   Transform res;
01205   if (hint == Projective)
01206   {
01207     internal::projective_transform_inverse<Transform>::run(*this, res);
01208   }
01209   else
01210   {
01211     if (hint == Isometry)
01212     {
01213       res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
01214     }
01215     else if(hint&Affine)
01216     {
01217       res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
01218     }
01219     else
01220     {
01221       eigen_assert(false && "Invalid transform traits in Transform::Inverse");
01222     }
01223     // translation and remaining parts
01224     res.matrix().template topRightCorner<Dim,1>()
01225       = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
01226     res.makeAffine(); // we do need this, because in the beginning res is uninitialized
01227   }
01228   return res;
01229 }
01230 
01231 namespace internal {
01232 
01233 /*****************************************************
01234 *** Specializations of take affine part            ***
01235 *****************************************************/
01236 
01237 template<typename TransformType> struct transform_take_affine_part {
01238   typedef typename TransformType::MatrixType MatrixType;
01239   typedef typename TransformType::AffinePart AffinePart;
01240   typedef typename TransformType::ConstAffinePart ConstAffinePart;
01241   static inline AffinePart run(MatrixType& m)
01242   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01243   static inline ConstAffinePart run(const MatrixType& m)
01244   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01245 };
01246 
01247 template<typename Scalar, int Dim, int Options>
01248 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
01249   typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
01250   static inline MatrixType& run(MatrixType& m) { return m; }
01251   static inline const MatrixType& run(const MatrixType& m) { return m; }
01252 };
01253 
01254 /*****************************************************
01255 *** Specializations of construct from matrix       ***
01256 *****************************************************/
01257 
01258 template<typename Other, int Mode, int Options, int Dim, int HDim>
01259 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
01260 {
01261   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01262   {
01263     transform->linear() = other;
01264     transform->translation().setZero();
01265     transform->makeAffine();
01266   }
01267 };
01268 
01269 template<typename Other, int Mode, int Options, int Dim, int HDim>
01270 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
01271 {
01272   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01273   {
01274     transform->affine() = other;
01275     transform->makeAffine();
01276   }
01277 };
01278 
01279 template<typename Other, int Mode, int Options, int Dim, int HDim>
01280 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
01281 {
01282   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01283   { transform->matrix() = other; }
01284 };
01285 
01286 template<typename Other, int Options, int Dim, int HDim>
01287 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
01288 {
01289   static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
01290   { transform->matrix() = other.template block<Dim,HDim>(0,0); }
01291 };
01292 
01293 /**********************************************************
01294 ***   Specializations of operator* with rhs EigenBase   ***
01295 **********************************************************/
01296 
01297 template<int LhsMode,int RhsMode>
01298 struct transform_product_result
01299 {
01300   enum 
01301   { 
01302     Mode =
01303       (LhsMode == (int)Projective    || RhsMode == (int)Projective    ) ? Projective :
01304       (LhsMode == (int)Affine        || RhsMode == (int)Affine        ) ? Affine :
01305       (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
01306       (LhsMode == (int)Isometry      || RhsMode == (int)Isometry      ) ? Isometry : Projective
01307   };
01308 };
01309 
01310 template< typename TransformType, typename MatrixType, int RhsCols>
01311 struct transform_right_product_impl< TransformType, MatrixType, 0, RhsCols>
01312 {
01313   typedef typename MatrixType::PlainObject ResultType;
01314 
01315   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01316   {
01317     return T.matrix() * other;
01318   }
01319 };
01320 
01321 template< typename TransformType, typename MatrixType, int RhsCols>
01322 struct transform_right_product_impl< TransformType, MatrixType, 1, RhsCols>
01323 {
01324   enum { 
01325     Dim = TransformType::Dim, 
01326     HDim = TransformType::HDim,
01327     OtherRows = MatrixType::RowsAtCompileTime,
01328     OtherCols = MatrixType::ColsAtCompileTime
01329   };
01330 
01331   typedef typename MatrixType::PlainObject ResultType;
01332 
01333   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01334   {
01335     EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01336 
01337     typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs;
01338 
01339     ResultType res(other.rows(),other.cols());
01340     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
01341     res.row(OtherRows-1) = other.row(OtherRows-1);
01342     
01343     return res;
01344   }
01345 };
01346 
01347 template< typename TransformType, typename MatrixType, int RhsCols>
01348 struct transform_right_product_impl< TransformType, MatrixType, 2, RhsCols>
01349 {
01350   enum { 
01351     Dim = TransformType::Dim, 
01352     HDim = TransformType::HDim,
01353     OtherRows = MatrixType::RowsAtCompileTime,
01354     OtherCols = MatrixType::ColsAtCompileTime
01355   };
01356 
01357   typedef typename MatrixType::PlainObject ResultType;
01358 
01359   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01360   {
01361     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01362 
01363     typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs;
01364     ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols()));
01365     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other;
01366 
01367     return res;
01368   }
01369 };
01370 
01371 template< typename TransformType, typename MatrixType >
01372 struct transform_right_product_impl< TransformType, MatrixType, 2, 1> // rhs is a vector of size Dim
01373 {
01374   typedef typename TransformType::MatrixType TransformMatrix;
01375   enum {
01376     Dim = TransformType::Dim,
01377     HDim = TransformType::HDim,
01378     OtherRows = MatrixType::RowsAtCompileTime,
01379     WorkingRows = EIGEN_PLAIN_ENUM_MIN(TransformMatrix::RowsAtCompileTime,HDim)
01380   };
01381 
01382   typedef typename MatrixType::PlainObject ResultType;
01383 
01384   static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other)
01385   {
01386     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01387 
01388     Matrix<typename ResultType::Scalar, Dim+1, 1> rhs;
01389     rhs.template head<Dim>() = other; rhs[Dim] = typename ResultType::Scalar(1);
01390     Matrix<typename ResultType::Scalar, WorkingRows, 1> res(T.matrix() * rhs);
01391     return res.template head<Dim>();
01392   }
01393 };
01394 
01395 /**********************************************************
01396 ***   Specializations of operator* with lhs EigenBase   ***
01397 **********************************************************/
01398 
01399 // generic HDim x HDim matrix * T => Projective
01400 template<typename Other,int Mode, int Options, int Dim, int HDim>
01401 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
01402 {
01403   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01404   typedef typename TransformType::MatrixType MatrixType;
01405   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01406   static ResultType run(const Other& other,const TransformType& tr)
01407   { return ResultType(other * tr.matrix()); }
01408 };
01409 
01410 // generic HDim x HDim matrix * AffineCompact => Projective
01411 template<typename Other, int Options, int Dim, int HDim>
01412 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
01413 {
01414   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01415   typedef typename TransformType::MatrixType MatrixType;
01416   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01417   static ResultType run(const Other& other,const TransformType& tr)
01418   {
01419     ResultType res;
01420     res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
01421     res.matrix().col(Dim) += other.col(Dim);
01422     return res;
01423   }
01424 };
01425 
01426 // affine matrix * T
01427 template<typename Other,int Mode, int Options, int Dim, int HDim>
01428 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
01429 {
01430   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01431   typedef typename TransformType::MatrixType MatrixType;
01432   typedef TransformType ResultType;
01433   static ResultType run(const Other& other,const TransformType& tr)
01434   {
01435     ResultType res;
01436     res.affine().noalias() = other * tr.matrix();
01437     res.matrix().row(Dim) = tr.matrix().row(Dim);
01438     return res;
01439   }
01440 };
01441 
01442 // affine matrix * AffineCompact
01443 template<typename Other, int Options, int Dim, int HDim>
01444 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
01445 {
01446   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01447   typedef typename TransformType::MatrixType MatrixType;
01448   typedef TransformType ResultType;
01449   static ResultType run(const Other& other,const TransformType& tr)
01450   {
01451     ResultType res;
01452     res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
01453     res.translation() += other.col(Dim);
01454     return res;
01455   }
01456 };
01457 
01458 // linear matrix * T
01459 template<typename Other,int Mode, int Options, int Dim, int HDim>
01460 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
01461 {
01462   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01463   typedef typename TransformType::MatrixType MatrixType;
01464   typedef TransformType ResultType;
01465   static ResultType run(const Other& other, const TransformType& tr)
01466   {
01467     TransformType res;
01468     if(Mode!=int(AffineCompact))
01469       res.matrix().row(Dim) = tr.matrix().row(Dim);
01470     res.matrix().template topRows<Dim>().noalias()
01471       = other * tr.matrix().template topRows<Dim>();
01472     return res;
01473   }
01474 };
01475 
01476 /**********************************************************
01477 *** Specializations of operator* with another Transform ***
01478 **********************************************************/
01479 
01480 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01481 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
01482 {
01483   enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
01484   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01485   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01486   typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
01487   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01488   {
01489     ResultType res;
01490     res.linear() = lhs.linear() * rhs.linear();
01491     res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
01492     res.makeAffine();
01493     return res;
01494   }
01495 };
01496 
01497 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01498 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
01499 {
01500   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01501   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01502   typedef Transform<Scalar,Dim,Projective> ResultType;
01503   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01504   {
01505     return ResultType( lhs.matrix() * rhs.matrix() );
01506   }
01507 };
01508 
01509 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01510 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true >
01511 {
01512   typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs;
01513   typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs;
01514   typedef Transform<Scalar,Dim,Projective> ResultType;
01515   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01516   {
01517     ResultType res;
01518     res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix();
01519     res.matrix().row(Dim) = rhs.matrix().row(Dim);
01520     return res;
01521   }
01522 };
01523 
01524 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions>
01525 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true >
01526 {
01527   typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs;
01528   typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs;
01529   typedef Transform<Scalar,Dim,Projective> ResultType;
01530   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01531   {
01532     ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix());
01533     res.matrix().col(Dim) += lhs.matrix().col(Dim);
01534     return res;
01535   }
01536 };
01537 
01538 } // end namespace internal
01539 
01540 } // end namespace Eigen
01541 
01542 #endif // EIGEN_TRANSFORM_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends