Transform.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
00007 //
00008 // Eigen is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 3 of the License, or (at your option) any later version.
00012 //
00013 // Alternatively, you can redistribute it and/or
00014 // modify it under the terms of the GNU General Public License as
00015 // published by the Free Software Foundation; either version 2 of
00016 // the License, or (at your option) any later version.
00017 //
00018 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00019 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00020 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00021 // GNU General Public License for more details.
00022 //
00023 // You should have received a copy of the GNU Lesser General Public
00024 // License and a copy of the GNU General Public License along with
00025 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 #ifndef EIGEN_TRANSFORM_H
00028 #define EIGEN_TRANSFORM_H
00029 
00030 namespace internal {
00031 
00032 template<typename Transform>
00033 struct transform_traits
00034 {
00035   enum
00036   {
00037     Dim = Transform::Dim,
00038     HDim = Transform::HDim,
00039     Mode = Transform::Mode,
00040     IsProjective = (Mode==Projective)
00041   };
00042 };
00043 
00044 template< typename TransformType,
00045           typename MatrixType,
00046           int Case = transform_traits<TransformType>::IsProjective ? 0
00047                    : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1
00048                    : 2>
00049 struct transform_right_product_impl;
00050 
00051 template< typename Other,
00052           int Mode,
00053           int Options,
00054           int Dim,
00055           int HDim,
00056           int OtherRows=Other::RowsAtCompileTime,
00057           int OtherCols=Other::ColsAtCompileTime>
00058 struct transform_left_product_impl;
00059 
00060 template< typename Lhs,
00061           typename Rhs,
00062           bool AnyProjective = 
00063             transform_traits<Lhs>::IsProjective ||
00064             transform_traits<Lhs>::IsProjective>
00065 struct transform_transform_product_impl;
00066 
00067 template< typename Other,
00068           int Mode,
00069           int Options,
00070           int Dim,
00071           int HDim,
00072           int OtherRows=Other::RowsAtCompileTime,
00073           int OtherCols=Other::ColsAtCompileTime>
00074 struct transform_construct_from_matrix;
00075 
00076 template<typename TransformType> struct transform_take_affine_part;
00077 
00078 } // end namespace internal
00079 
00188 template<typename _Scalar, int _Dim, int _Mode, int _Options>
00189 class Transform
00190 {
00191 public:
00192   EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00193   enum {
00194     Mode = _Mode,
00195     Options = _Options,
00196     Dim = _Dim,     
00197     HDim = _Dim+1,  
00198     Rows = int(Mode)==(AffineCompact) ? Dim : HDim
00199   };
00201   typedef _Scalar Scalar;
00202   typedef DenseIndex Index;
00204   typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType;
00206   typedef const MatrixType ConstMatrixType;
00208   typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType;
00210   typedef Block<MatrixType,Dim,Dim> LinearPart;
00212   typedef const Block<ConstMatrixType,Dim,Dim> ConstLinearPart;
00214   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00215                               MatrixType&,
00216                               Block<MatrixType,Dim,HDim> >::type AffinePart;
00218   typedef typename internal::conditional<int(Mode)==int(AffineCompact),
00219                               const MatrixType&,
00220                               const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart;
00222   typedef Matrix<Scalar,Dim,1> VectorType;
00224   typedef Block<MatrixType,Dim,1> TranslationPart;
00226   typedef const Block<ConstMatrixType,Dim,1> ConstTranslationPart;
00228   typedef Translation<Scalar,Dim> TranslationType;
00229   
00230   // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0
00231   enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) };
00233   typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType;
00234 
00235 protected:
00236 
00237   MatrixType m_matrix;
00238 
00239 public:
00240 
00243   inline Transform()
00244   {
00245     check_template_params();
00246     if (int(Mode)==Affine)
00247       makeAffine();
00248   }
00249 
00250   inline Transform(const Transform& other)
00251   {
00252     check_template_params();
00253     m_matrix = other.m_matrix;
00254   }
00255 
00256   inline explicit Transform(const TranslationType& t)
00257   {
00258     check_template_params();
00259     *this = t;
00260   }
00261   inline explicit Transform(const UniformScaling<Scalar>& s)
00262   {
00263     check_template_params();
00264     *this = s;
00265   }
00266   template<typename Derived>
00267   inline explicit Transform(const RotationBase<Derived, Dim>& r)
00268   {
00269     check_template_params();
00270     *this = r;
00271   }
00272 
00273   inline Transform& operator=(const Transform& other)
00274   { m_matrix = other.m_matrix; return *this; }
00275 
00276   typedef internal::transform_take_affine_part<Transform> take_affine_part;
00277 
00279   template<typename OtherDerived>
00280   inline explicit Transform(const EigenBase<OtherDerived>& other)
00281   {
00282     check_template_params();
00283     internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived());
00284   }
00285 
00287   template<typename OtherDerived>
00288   inline Transform& operator=(const EigenBase<OtherDerived>& other)
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 m_matrix.template block<Dim,Dim>(0,0); }
00381   inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(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 m_matrix.template block<Dim,1>(0,Dim); }
00391   inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
00392 
00404   // note: this function is defined here because some compilers cannot find the respective declaration
00405   template<typename OtherDerived>
00406   EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType
00407   operator * (const EigenBase<OtherDerived> &other) const
00408   { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); }
00409 
00417   template<typename OtherDerived> friend
00418   inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType
00419     operator * (const EigenBase<OtherDerived> &a, const Transform &b)
00420   { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); }
00421 
00428   template<typename DiagonalDerived>
00429   inline const TransformTimeDiagonalReturnType
00430     operator * (const DiagonalBase<DiagonalDerived> &b) const
00431   {
00432     TransformTimeDiagonalReturnType res(*this);
00433     res.linear() *= b;
00434     return res;
00435   }
00436 
00443   template<typename DiagonalDerived>
00444   friend inline TransformTimeDiagonalReturnType
00445     operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b)
00446   {
00447     TransformTimeDiagonalReturnType res;
00448     res.linear().noalias() = a*b.linear();
00449     res.translation().noalias() = a*b.translation();
00450     if (Mode!=int(AffineCompact))
00451       res.matrix().row(Dim) = b.matrix().row(Dim);
00452     return res;
00453   }
00454 
00455   template<typename OtherDerived>
00456   inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; }
00457 
00459   inline const Transform operator * (const Transform& other) const
00460   {
00461     return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other);
00462   }
00463 
00465   template<int OtherMode,int OtherOptions>
00466   inline const typename internal::transform_transform_product_impl<
00467     Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType
00468     operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const
00469   {
00470     return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other);
00471   }
00472 
00474   void setIdentity() { m_matrix.setIdentity(); }
00475 
00480   static const Transform Identity()
00481   {
00482     return Transform(MatrixType::Identity());
00483   }
00484 
00485   template<typename OtherDerived>
00486   inline Transform& scale(const MatrixBase<OtherDerived> &other);
00487 
00488   template<typename OtherDerived>
00489   inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00490 
00491   inline Transform& scale(Scalar s);
00492   inline Transform& prescale(Scalar s);
00493 
00494   template<typename OtherDerived>
00495   inline Transform& translate(const MatrixBase<OtherDerived> &other);
00496 
00497   template<typename OtherDerived>
00498   inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00499 
00500   template<typename RotationType>
00501   inline Transform& rotate(const RotationType& rotation);
00502 
00503   template<typename RotationType>
00504   inline Transform& prerotate(const RotationType& rotation);
00505 
00506   Transform& shear(Scalar sx, Scalar sy);
00507   Transform& preshear(Scalar sx, Scalar sy);
00508 
00509   inline Transform& operator=(const TranslationType& t);
00510   inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00511   inline Transform operator*(const TranslationType& t) const;
00512 
00513   inline Transform& operator=(const UniformScaling<Scalar>& t);
00514   inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
00515   inline Transform operator*(const UniformScaling<Scalar>& s) const;
00516 
00517   inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; }
00518 
00519   template<typename Derived>
00520   inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00521   template<typename Derived>
00522   inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00523   template<typename Derived>
00524   inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00525 
00526   const LinearMatrixType rotation() const;
00527   template<typename RotationMatrixType, typename ScalingMatrixType>
00528   void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00529   template<typename ScalingMatrixType, typename RotationMatrixType>
00530   void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00531 
00532   template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00533   Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00534     const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00535 
00536   inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const;
00537 
00539   const Scalar* data() const { return m_matrix.data(); }
00541   Scalar* data() { return m_matrix.data(); }
00542 
00548   template<typename NewScalarType>
00549   inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const
00550   { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); }
00551 
00553   template<typename OtherScalarType>
00554   inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other)
00555   {
00556     check_template_params();
00557     m_matrix = other.matrix().template cast<Scalar>();
00558   }
00559 
00564   bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = NumTraits<Scalar>::dummy_precision()) const
00565   { return m_matrix.isApprox(other.m_matrix, prec); }
00566 
00569   void makeAffine()
00570   {
00571     if(int(Mode)!=int(AffineCompact))
00572     {
00573       matrix().template block<1,Dim>(Dim,0).setZero();
00574       matrix().coeffRef(Dim,Dim) = 1;
00575     }
00576   }
00577 
00582   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt()
00583   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00588   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const
00589   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); }
00590 
00595   inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt()
00596   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00601   inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const
00602   { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); }
00603 
00604 
00605   #ifdef EIGEN_TRANSFORM_PLUGIN
00606   #include EIGEN_TRANSFORM_PLUGIN
00607   #endif
00608   
00609 protected:
00610   #ifndef EIGEN_PARSED_BY_DOXYGEN
00611     EIGEN_STRONG_INLINE static void check_template_params()
00612     {
00613       EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
00614     }
00615   #endif
00616 
00617 };
00618 
00620 typedef Transform<float,2,Isometry> Isometry2f;
00622 typedef Transform<float,3,Isometry> Isometry3f;
00624 typedef Transform<double,2,Isometry> Isometry2d;
00626 typedef Transform<double,3,Isometry> Isometry3d;
00627 
00629 typedef Transform<float,2,Affine> Affine2f;
00631 typedef Transform<float,3,Affine> Affine3f;
00633 typedef Transform<double,2,Affine> Affine2d;
00635 typedef Transform<double,3,Affine> Affine3d;
00636 
00638 typedef Transform<float,2,AffineCompact> AffineCompact2f;
00640 typedef Transform<float,3,AffineCompact> AffineCompact3f;
00642 typedef Transform<double,2,AffineCompact> AffineCompact2d;
00644 typedef Transform<double,3,AffineCompact> AffineCompact3d;
00645 
00647 typedef Transform<float,2,Projective> Projective2f;
00649 typedef Transform<float,3,Projective> Projective3f;
00651 typedef Transform<double,2,Projective> Projective2d;
00653 typedef Transform<double,3,Projective> Projective3d;
00654 
00655 /**************************
00656 *** Optional QT support ***
00657 **************************/
00658 
00659 #ifdef EIGEN_QT_SUPPORT
00660 
00664 template<typename Scalar, int Dim, int Mode,int Options>
00665 Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other)
00666 {
00667   check_template_params();
00668   *this = other;
00669 }
00670 
00675 template<typename Scalar, int Dim, int Mode,int Options>
00676 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other)
00677 {
00678   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00679   m_matrix << other.m11(), other.m21(), other.dx(),
00680               other.m12(), other.m22(), other.dy(),
00681               0, 0, 1;
00682   return *this;
00683 }
00684 
00691 template<typename Scalar, int Dim, int Mode, int Options>
00692 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const
00693 {
00694   check_template_params();
00695   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00696   return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00697                  m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00698                  m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00699 }
00700 
00705 template<typename Scalar, int Dim, int Mode,int Options>
00706 Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other)
00707 {
00708   check_template_params();
00709   *this = other;
00710 }
00711 
00716 template<typename Scalar, int Dim, int Mode, int Options>
00717 Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other)
00718 {
00719   check_template_params();
00720   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00721   if (Mode == int(AffineCompact))
00722     m_matrix << other.m11(), other.m21(), other.dx(),
00723                 other.m12(), other.m22(), other.dy();
00724   else
00725     m_matrix << other.m11(), other.m21(), other.dx(),
00726                 other.m12(), other.m22(), other.dy(),
00727                 other.m13(), other.m23(), other.m33();
00728   return *this;
00729 }
00730 
00735 template<typename Scalar, int Dim, int Mode, int Options>
00736 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const
00737 {
00738   EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00739   if (Mode == int(AffineCompact))
00740     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00741                       m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00742                       m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00743   else
00744     return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00745                       m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00746                       m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00747 }
00748 #endif
00749 
00750 /*********************
00751 *** Procedural API ***
00752 *********************/
00753 
00758 template<typename Scalar, int Dim, int Mode, int Options>
00759 template<typename OtherDerived>
00760 Transform<Scalar,Dim,Mode,Options>&
00761 Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other)
00762 {
00763   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00764   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00765   linearExt().noalias() = (linearExt() * other.asDiagonal());
00766   return *this;
00767 }
00768 
00773 template<typename Scalar, int Dim, int Mode, int Options>
00774 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(Scalar s)
00775 {
00776   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00777   linearExt() *= s;
00778   return *this;
00779 }
00780 
00785 template<typename Scalar, int Dim, int Mode, int Options>
00786 template<typename OtherDerived>
00787 Transform<Scalar,Dim,Mode,Options>&
00788 Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other)
00789 {
00790   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00791   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00792   m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0));
00793   return *this;
00794 }
00795 
00800 template<typename Scalar, int Dim, int Mode, int Options>
00801 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(Scalar s)
00802 {
00803   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00804   m_matrix.template topRows<Dim>() *= s;
00805   return *this;
00806 }
00807 
00812 template<typename Scalar, int Dim, int Mode, int Options>
00813 template<typename OtherDerived>
00814 Transform<Scalar,Dim,Mode,Options>&
00815 Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other)
00816 {
00817   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00818   translationExt() += linearExt() * other;
00819   return *this;
00820 }
00821 
00826 template<typename Scalar, int Dim, int Mode, int Options>
00827 template<typename OtherDerived>
00828 Transform<Scalar,Dim,Mode,Options>&
00829 Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other)
00830 {
00831   EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00832   if(int(Mode)==int(Projective))
00833     affine() += other * m_matrix.row(Dim);
00834   else
00835     translation() += other;
00836   return *this;
00837 }
00838 
00856 template<typename Scalar, int Dim, int Mode, int Options>
00857 template<typename RotationType>
00858 Transform<Scalar,Dim,Mode,Options>&
00859 Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation)
00860 {
00861   linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation);
00862   return *this;
00863 }
00864 
00872 template<typename Scalar, int Dim, int Mode, int Options>
00873 template<typename RotationType>
00874 Transform<Scalar,Dim,Mode,Options>&
00875 Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation)
00876 {
00877   m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation)
00878                                          * m_matrix.template block<Dim,HDim>(0,0);
00879   return *this;
00880 }
00881 
00887 template<typename Scalar, int Dim, int Mode, int Options>
00888 Transform<Scalar,Dim,Mode,Options>&
00889 Transform<Scalar,Dim,Mode,Options>::shear(Scalar sx, Scalar sy)
00890 {
00891   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00892   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00893   VectorType tmp = linear().col(0)*sy + linear().col(1);
00894   linear() << linear().col(0) + linear().col(1)*sx, tmp;
00895   return *this;
00896 }
00897 
00903 template<typename Scalar, int Dim, int Mode, int Options>
00904 Transform<Scalar,Dim,Mode,Options>&
00905 Transform<Scalar,Dim,Mode,Options>::preshear(Scalar sx, Scalar sy)
00906 {
00907   EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00908   EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS)
00909   m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00910   return *this;
00911 }
00912 
00913 /******************************************************
00914 *** Scaling, Translation and Rotation compatibility ***
00915 ******************************************************/
00916 
00917 template<typename Scalar, int Dim, int Mode, int Options>
00918 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t)
00919 {
00920   linear().setIdentity();
00921   translation() = t.vector();
00922   makeAffine();
00923   return *this;
00924 }
00925 
00926 template<typename Scalar, int Dim, int Mode, int Options>
00927 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const
00928 {
00929   Transform res = *this;
00930   res.translate(t.vector());
00931   return res;
00932 }
00933 
00934 template<typename Scalar, int Dim, int Mode, int Options>
00935 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s)
00936 {
00937   m_matrix.setZero();
00938   linear().diagonal().fill(s.factor());
00939   makeAffine();
00940   return *this;
00941 }
00942 
00943 template<typename Scalar, int Dim, int Mode, int Options>
00944 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const UniformScaling<Scalar>& s) const
00945 {
00946   Transform res = *this;
00947   res.scale(s.factor());
00948   return res;
00949 }
00950 
00951 template<typename Scalar, int Dim, int Mode, int Options>
00952 template<typename Derived>
00953 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r)
00954 {
00955   linear() = internal::toRotationMatrix<Scalar,Dim>(r);
00956   translation().setZero();
00957   makeAffine();
00958   return *this;
00959 }
00960 
00961 template<typename Scalar, int Dim, int Mode, int Options>
00962 template<typename Derived>
00963 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const
00964 {
00965   Transform res = *this;
00966   res.rotate(r.derived());
00967   return res;
00968 }
00969 
00970 /************************
00971 *** Special functions ***
00972 ************************/
00973 
00981 template<typename Scalar, int Dim, int Mode, int Options>
00982 const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType
00983 Transform<Scalar,Dim,Mode,Options>::rotation() const
00984 {
00985   LinearMatrixType result;
00986   computeRotationScaling(&result, (LinearMatrixType*)0);
00987   return result;
00988 }
00989 
00990 
01002 template<typename Scalar, int Dim, int Mode, int Options>
01003 template<typename RotationMatrixType, typename ScalingMatrixType>
01004 void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
01005 {
01006   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01007 
01008   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01009   VectorType sv(svd.singularValues());
01010   sv.coeffRef(0) *= x;
01011   if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint());
01012   if(rotation)
01013   {
01014     LinearMatrixType m(svd.matrixU());
01015     m.col(0) /= x;
01016     rotation->lazyAssign(m * svd.matrixV().adjoint());
01017   }
01018 }
01019 
01031 template<typename Scalar, int Dim, int Mode, int Options>
01032 template<typename ScalingMatrixType, typename RotationMatrixType>
01033 void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
01034 {
01035   JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV);
01036 
01037   Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
01038   VectorType sv(svd.singularValues());
01039   sv.coeffRef(0) *= x;
01040   if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint());
01041   if(rotation)
01042   {
01043     LinearMatrixType m(svd.matrixU());
01044     m.col(0) /= x;
01045     rotation->lazyAssign(m * svd.matrixV().adjoint());
01046   }
01047 }
01048 
01052 template<typename Scalar, int Dim, int Mode, int Options>
01053 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
01054 Transform<Scalar,Dim,Mode,Options>&
01055 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
01056   const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
01057 {
01058   linear() = internal::toRotationMatrix<Scalar,Dim>(orientation);
01059   linear() *= scale.asDiagonal();
01060   translation() = position;
01061   makeAffine();
01062   return *this;
01063 }
01064 
01065 namespace internal {
01066 
01067 // selector needed to avoid taking the inverse of a 3x4 matrix
01068 template<typename TransformType, int Mode=TransformType::Mode>
01069 struct projective_transform_inverse
01070 {
01071   static inline void run(const TransformType&, TransformType&)
01072   {}
01073 };
01074 
01075 template<typename TransformType>
01076 struct projective_transform_inverse<TransformType, Projective>
01077 {
01078   static inline void run(const TransformType& m, TransformType& res)
01079   {
01080     res.matrix() = m.matrix().inverse();
01081   }
01082 };
01083 
01084 } // end namespace internal
01085 
01086 
01107 template<typename Scalar, int Dim, int Mode, int Options>
01108 Transform<Scalar,Dim,Mode,Options>
01109 Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const
01110 {
01111   Transform res;
01112   if (hint == Projective)
01113   {
01114     internal::projective_transform_inverse<Transform>::run(*this, res);
01115   }
01116   else
01117   {
01118     if (hint == Isometry)
01119     {
01120       res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose();
01121     }
01122     else if(hint&Affine)
01123     {
01124       res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse();
01125     }
01126     else
01127     {
01128       eigen_assert(false && "Invalid transform traits in Transform::Inverse");
01129     }
01130     // translation and remaining parts
01131     res.matrix().template topRightCorner<Dim,1>()
01132       = - res.matrix().template topLeftCorner<Dim,Dim>() * translation();
01133     res.makeAffine(); // we do need this, because in the beginning res is uninitialized
01134   }
01135   return res;
01136 }
01137 
01138 namespace internal {
01139 
01140 /*****************************************************
01141 *** Specializations of take affine part            ***
01142 *****************************************************/
01143 
01144 template<typename TransformType> struct transform_take_affine_part {
01145   typedef typename TransformType::MatrixType MatrixType;
01146   typedef typename TransformType::AffinePart AffinePart;
01147   typedef typename TransformType::ConstAffinePart ConstAffinePart;
01148   static inline AffinePart run(MatrixType& m)
01149   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01150   static inline ConstAffinePart run(const MatrixType& m)
01151   { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); }
01152 };
01153 
01154 template<typename Scalar, int Dim, int Options>
01155 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > {
01156   typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType;
01157   static inline MatrixType& run(MatrixType& m) { return m; }
01158   static inline const MatrixType& run(const MatrixType& m) { return m; }
01159 };
01160 
01161 /*****************************************************
01162 *** Specializations of construct from matrix       ***
01163 *****************************************************/
01164 
01165 template<typename Other, int Mode, int Options, int Dim, int HDim>
01166 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim>
01167 {
01168   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01169   {
01170     transform->linear() = other;
01171     transform->translation().setZero();
01172     transform->makeAffine();
01173   }
01174 };
01175 
01176 template<typename Other, int Mode, int Options, int Dim, int HDim>
01177 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim>
01178 {
01179   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01180   {
01181     transform->affine() = other;
01182     transform->makeAffine();
01183   }
01184 };
01185 
01186 template<typename Other, int Mode, int Options, int Dim, int HDim>
01187 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim>
01188 {
01189   static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other)
01190   { transform->matrix() = other; }
01191 };
01192 
01193 template<typename Other, int Options, int Dim, int HDim>
01194 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim>
01195 {
01196   static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other)
01197   { transform->matrix() = other.template block<Dim,HDim>(0,0); }
01198 };
01199 
01200 /**********************************************************
01201 ***   Specializations of operator* with rhs EigenBase   ***
01202 **********************************************************/
01203 
01204 template<int LhsMode,int RhsMode>
01205 struct transform_product_result
01206 {
01207   enum 
01208   { 
01209     Mode =
01210       (LhsMode == (int)Projective    || RhsMode == (int)Projective    ) ? Projective :
01211       (LhsMode == (int)Affine        || RhsMode == (int)Affine        ) ? Affine :
01212       (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact :
01213       (LhsMode == (int)Isometry      || RhsMode == (int)Isometry      ) ? Isometry : Projective
01214   };
01215 };
01216 
01217 template< typename TransformType, typename MatrixType >
01218 struct transform_right_product_impl< TransformType, MatrixType, 0 >
01219 {
01220   typedef typename MatrixType::PlainObject ResultType;
01221 
01222   EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
01223   {
01224     return T.matrix() * other;
01225   }
01226 };
01227 
01228 template< typename TransformType, typename MatrixType >
01229 struct transform_right_product_impl< TransformType, MatrixType, 1 >
01230 {
01231   enum { 
01232     Dim = TransformType::Dim, 
01233     HDim = TransformType::HDim,
01234     OtherRows = MatrixType::RowsAtCompileTime,
01235     OtherCols = MatrixType::ColsAtCompileTime
01236   };
01237 
01238   typedef typename MatrixType::PlainObject ResultType;
01239 
01240   EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
01241   {
01242     EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01243 
01244     typedef Block<ResultType, Dim, OtherCols> TopLeftLhs;
01245 
01246     ResultType res(other.rows(),other.cols());
01247     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other;
01248     res.row(OtherRows-1) = other.row(OtherRows-1);
01249     
01250     return res;
01251   }
01252 };
01253 
01254 template< typename TransformType, typename MatrixType >
01255 struct transform_right_product_impl< TransformType, MatrixType, 2 >
01256 {
01257   enum { 
01258     Dim = TransformType::Dim, 
01259     HDim = TransformType::HDim,
01260     OtherRows = MatrixType::RowsAtCompileTime,
01261     OtherCols = MatrixType::ColsAtCompileTime
01262   };
01263 
01264   typedef typename MatrixType::PlainObject ResultType;
01265 
01266   EIGEN_STRONG_INLINE static ResultType run(const TransformType& T, const MatrixType& other)
01267   {
01268     EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES);
01269 
01270     typedef Block<ResultType, Dim, OtherCols> TopLeftLhs;
01271 
01272     ResultType res(other.rows(),other.cols());
01273     TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.linear() * other;
01274     TopLeftLhs(res, 0, 0, Dim, other.cols()).colwise() += T.translation();
01275 
01276     return res;
01277   }
01278 };
01279 
01280 /**********************************************************
01281 ***   Specializations of operator* with lhs EigenBase   ***
01282 **********************************************************/
01283 
01284 // generic HDim x HDim matrix * T => Projective
01285 template<typename Other,int Mode, int Options, int Dim, int HDim>
01286 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim>
01287 {
01288   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01289   typedef typename TransformType::MatrixType MatrixType;
01290   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01291   static ResultType run(const Other& other,const TransformType& tr)
01292   { return ResultType(other * tr.matrix()); }
01293 };
01294 
01295 // generic HDim x HDim matrix * AffineCompact => Projective
01296 template<typename Other, int Options, int Dim, int HDim>
01297 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim>
01298 {
01299   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01300   typedef typename TransformType::MatrixType MatrixType;
01301   typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType;
01302   static ResultType run(const Other& other,const TransformType& tr)
01303   {
01304     ResultType res;
01305     res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix();
01306     res.matrix().col(Dim) += other.col(Dim);
01307     return res;
01308   }
01309 };
01310 
01311 // affine matrix * T
01312 template<typename Other,int Mode, int Options, int Dim, int HDim>
01313 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim>
01314 {
01315   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01316   typedef typename TransformType::MatrixType MatrixType;
01317   typedef TransformType ResultType;
01318   static ResultType run(const Other& other,const TransformType& tr)
01319   {
01320     ResultType res;
01321     res.affine().noalias() = other * tr.matrix();
01322     res.matrix().row(Dim) = tr.matrix().row(Dim);
01323     return res;
01324   }
01325 };
01326 
01327 // affine matrix * AffineCompact
01328 template<typename Other, int Options, int Dim, int HDim>
01329 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim>
01330 {
01331   typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType;
01332   typedef typename TransformType::MatrixType MatrixType;
01333   typedef TransformType ResultType;
01334   static ResultType run(const Other& other,const TransformType& tr)
01335   {
01336     ResultType res;
01337     res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix();
01338     res.translation() += other.col(Dim);
01339     return res;
01340   }
01341 };
01342 
01343 // linear matrix * T
01344 template<typename Other,int Mode, int Options, int Dim, int HDim>
01345 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim>
01346 {
01347   typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType;
01348   typedef typename TransformType::MatrixType MatrixType;
01349   typedef TransformType ResultType;
01350   static ResultType run(const Other& other, const TransformType& tr)
01351   {
01352     TransformType res;
01353     if(Mode!=int(AffineCompact))
01354       res.matrix().row(Dim) = tr.matrix().row(Dim);
01355     res.matrix().template topRows<Dim>().noalias()
01356       = other * tr.matrix().template topRows<Dim>();
01357     return res;
01358   }
01359 };
01360 
01361 /**********************************************************
01362 *** Specializations of operator* with another Transform ***
01363 **********************************************************/
01364 
01365 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01366 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false >
01367 {
01368   enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode };
01369   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01370   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01371   typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType;
01372   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01373   {
01374     ResultType res;
01375     res.linear() = lhs.linear() * rhs.linear();
01376     res.translation() = lhs.linear() * rhs.translation() + lhs.translation();
01377     res.makeAffine();
01378     return res;
01379   }
01380 };
01381 
01382 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions>
01383 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true >
01384 {
01385   typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs;
01386   typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs;
01387   typedef Transform<Scalar,Dim,Projective> ResultType;
01388   static ResultType run(const Lhs& lhs, const Rhs& rhs)
01389   {
01390     return ResultType( lhs.matrix() * rhs.matrix() );
01391   }
01392 };
01393 
01394 } // end namespace internal
01395 
01396 #endif // EIGEN_TRANSFORM_H


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:33:11