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