Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Transform.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> 00006 // Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com> 00007 // 00008 // This Source Code Form is subject to the terms of the Mozilla 00009 // Public License v. 2.0. If a copy of the MPL was not distributed 00010 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00011 00012 #ifndef EIGEN_TRANSFORM_H 00013 #define EIGEN_TRANSFORM_H 00014 00015 namespace Eigen { 00016 00017 namespace internal { 00018 00019 template<typename Transform> 00020 struct transform_traits 00021 { 00022 enum 00023 { 00024 Dim = Transform::Dim, 00025 HDim = Transform::HDim, 00026 Mode = Transform::Mode, 00027 IsProjective = (int(Mode)==int(Projective)) 00028 }; 00029 }; 00030 00031 template< typename TransformType, 00032 typename MatrixType, 00033 int Case = transform_traits<TransformType>::IsProjective ? 0 00034 : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1 00035 : 2> 00036 struct transform_right_product_impl; 00037 00038 template< typename Other, 00039 int Mode, 00040 int Options, 00041 int Dim, 00042 int HDim, 00043 int OtherRows=Other::RowsAtCompileTime, 00044 int OtherCols=Other::ColsAtCompileTime> 00045 struct transform_left_product_impl; 00046 00047 template< typename Lhs, 00048 typename Rhs, 00049 bool AnyProjective = 00050 transform_traits<Lhs>::IsProjective || 00051 transform_traits<Rhs>::IsProjective> 00052 struct transform_transform_product_impl; 00053 00054 template< typename Other, 00055 int Mode, 00056 int Options, 00057 int Dim, 00058 int HDim, 00059 int OtherRows=Other::RowsAtCompileTime, 00060 int OtherCols=Other::ColsAtCompileTime> 00061 struct transform_construct_from_matrix; 00062 00063 template<typename TransformType> struct transform_take_affine_part; 00064 00065 template<int Mode> struct transform_make_affine; 00066 00067 } // end namespace internal 00068 00069 /** \geometry_module \ingroup Geometry_Module 00070 * 00071 * \class Transform 00072 * 00073 * \brief Represents an homogeneous transformation in a N dimensional space 00074 * 00075 * \tparam _Scalar the scalar type, i.e., the type of the coefficients 00076 * \tparam _Dim the dimension of the space 00077 * \tparam _Mode the type of the transformation. Can be: 00078 * - #Affine: the transformation is stored as a (Dim+1)^2 matrix, 00079 * where the last row is assumed to be [0 ... 0 1]. 00080 * - #AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix. 00081 * - #Projective: the transformation is stored as a (Dim+1)^2 matrix 00082 * without any assumption. 00083 * \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor. 00084 * These Options are passed directly to the underlying matrix type. 00085 * 00086 * The homography is internally represented and stored by a matrix which 00087 * is available through the matrix() method. To understand the behavior of 00088 * this class you have to think a Transform object as its internal 00089 * matrix representation. The chosen convention is right multiply: 00090 * 00091 * \code v' = T * v \endcode 00092 * 00093 * Therefore, an affine transformation matrix M is shaped like this: 00094 * 00095 * \f$ \left( \begin{array}{cc} 00096 * linear & translation\\ 00097 * 0 ... 0 & 1 00098 * \end{array} \right) \f$ 00099 * 00100 * Note that for a projective transformation the last row can be anything, 00101 * and then the interpretation of different parts might be sightly different. 00102 * 00103 * However, unlike a plain matrix, the Transform class provides many features 00104 * simplifying both its assembly and usage. In particular, it can be composed 00105 * with any other transformations (Transform,Translation,RotationBase,DiagonalMatrix) 00106 * and can be directly used to transform implicit homogeneous vectors. All these 00107 * operations are handled via the operator*. For the composition of transformations, 00108 * its principle consists to first convert the right/left hand sides of the product 00109 * to a compatible (Dim+1)^2 matrix and then perform a pure matrix product. 00110 * Of course, internally, operator* tries to perform the minimal number of operations 00111 * according to the nature of each terms. Likewise, when applying the transform 00112 * to points, the latters are automatically promoted to homogeneous vectors 00113 * before doing the matrix product. The conventions to homogeneous representations 00114 * are performed as follow: 00115 * 00116 * \b Translation t (Dim)x(1): 00117 * \f$ \left( \begin{array}{cc} 00118 * I & t \\ 00119 * 0\,...\,0 & 1 00120 * \end{array} \right) \f$ 00121 * 00122 * \b Rotation R (Dim)x(Dim): 00123 * \f$ \left( \begin{array}{cc} 00124 * R & 0\\ 00125 * 0\,...\,0 & 1 00126 * \end{array} \right) \f$ 00127 *<!-- 00128 * \b Linear \b Matrix L (Dim)x(Dim): 00129 * \f$ \left( \begin{array}{cc} 00130 * L & 0\\ 00131 * 0\,...\,0 & 1 00132 * \end{array} \right) \f$ 00133 * 00134 * \b Affine \b Matrix A (Dim)x(Dim+1): 00135 * \f$ \left( \begin{array}{c} 00136 * A\\ 00137 * 0\,...\,0\,1 00138 * \end{array} \right) \f$ 00139 *--> 00140 * \b Scaling \b DiagonalMatrix S (Dim)x(Dim): 00141 * \f$ \left( \begin{array}{cc} 00142 * S & 0\\ 00143 * 0\,...\,0 & 1 00144 * \end{array} \right) \f$ 00145 * 00146 * \b Column \b point v (Dim)x(1): 00147 * \f$ \left( \begin{array}{c} 00148 * v\\ 00149 * 1 00150 * \end{array} \right) \f$ 00151 * 00152 * \b Set \b of \b column \b points V1...Vn (Dim)x(n): 00153 * \f$ \left( \begin{array}{ccc} 00154 * v_1 & ... & v_n\\ 00155 * 1 & ... & 1 00156 * \end{array} \right) \f$ 00157 * 00158 * The concatenation of a Transform object with any kind of other transformation 00159 * always returns a Transform object. 00160 * 00161 * A little exception to the "as pure matrix product" rule is the case of the 00162 * transformation of non homogeneous vectors by an affine transformation. In 00163 * that case the last matrix row can be ignored, and the product returns non 00164 * homogeneous vectors. 00165 * 00166 * Since, for instance, a Dim x Dim matrix is interpreted as a linear transformation, 00167 * it is not possible to directly transform Dim vectors stored in a Dim x Dim matrix. 00168 * The solution is either to use a Dim x Dynamic matrix or explicitly request a 00169 * vector transformation by making the vector homogeneous: 00170 * \code 00171 * m' = T * m.colwise().homogeneous(); 00172 * \endcode 00173 * Note that there is zero overhead. 00174 * 00175 * Conversion methods from/to Qt's QMatrix and QTransform are available if the 00176 * preprocessor token EIGEN_QT_SUPPORT is defined. 00177 * 00178 * This class can be extended with the help of the plugin mechanism described on the page 00179 * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_TRANSFORM_PLUGIN. 00180 * 00181 * \sa class Matrix, class Quaternion 00182 */ 00183 template<typename _Scalar, int _Dim, int _Mode, int _Options> 00184 class Transform 00185 { 00186 public: 00187 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)) 00188 enum { 00189 Mode = _Mode, 00190 Options = _Options, 00191 Dim = _Dim, ///< space dimension in which the transformation holds 00192 HDim = _Dim+1, ///< size of a respective homogeneous vector 00193 Rows = int(Mode)==(AffineCompact) ? Dim : HDim 00194 }; 00195 /** the scalar type of the coefficients */ 00196 typedef _Scalar Scalar; 00197 typedef DenseIndex Index; 00198 /** type of the matrix used to represent the transformation */ 00199 typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType; 00200 /** constified MatrixType */ 00201 typedef const MatrixType ConstMatrixType; 00202 /** type of the matrix used to represent the linear part of the transformation */ 00203 typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType; 00204 /** type of read/write reference to the linear part of the transformation */ 00205 typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart; 00206 /** type of read reference to the linear part of the transformation */ 00207 typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart; 00208 /** type of read/write reference to the affine part of the transformation */ 00209 typedef typename internal::conditional<int(Mode)==int(AffineCompact), 00210 MatrixType&, 00211 Block<MatrixType,Dim,HDim> >::type AffinePart; 00212 /** type of read reference to the affine part of the transformation */ 00213 typedef typename internal::conditional<int(Mode)==int(AffineCompact), 00214 const MatrixType&, 00215 const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart; 00216 /** type of a vector */ 00217 typedef Matrix<Scalar,Dim,1> VectorType; 00218 /** type of a read/write reference to the translation part of the rotation */ 00219 typedef Block<MatrixType,Dim,1,int(Mode)==(AffineCompact)> TranslationPart; 00220 /** type of a read reference to the translation part of the rotation */ 00221 typedef const Block<ConstMatrixType,Dim,1,int(Mode)==(AffineCompact)> ConstTranslationPart; 00222 /** corresponding translation type */ 00223 typedef Translation<Scalar,Dim> TranslationType; 00224 00225 // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0 00226 enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) }; 00227 /** The return type of the product between a diagonal matrix and a transform */ 00228 typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType; 00229 00230 protected: 00231 00232 MatrixType m_matrix; 00233 00234 public: 00235 00236 /** Default constructor without initialization of the meaningful coefficients. 00237 * If Mode==Affine, then the last row is set to [0 ... 0 1] */ 00238 inline Transform () 00239 { 00240 check_template_params(); 00241 internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix); 00242 } 00243 00244 inline Transform (const Transform & other) 00245 { 00246 check_template_params(); 00247 m_matrix = other.m_matrix; 00248 } 00249 00250 inline explicit Transform(const TranslationType& t) 00251 { 00252 check_template_params(); 00253 *this = t; 00254 } 00255 inline explicit Transform(const UniformScaling<Scalar>& s) 00256 { 00257 check_template_params(); 00258 *this = s; 00259 } 00260 template<typename Derived> 00261 inline explicit Transform(const RotationBase<Derived, Dim>& r) 00262 { 00263 check_template_params(); 00264 *this = r; 00265 } 00266 00267 inline Transform& operator=(const Transform& other) 00268 { m_matrix = other.m_matrix; return *this; } 00269 00270 typedef internal::transform_take_affine_part<Transform> take_affine_part; 00271 00272 /** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */ 00273 template<typename OtherDerived> 00274 inline explicit Transform (const EigenBase<OtherDerived>& other) 00275 { 00276 EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value), 00277 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); 00278 00279 check_template_params(); 00280 internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived ()); 00281 } 00282 00283 /** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */ 00284 template<typename OtherDerived> 00285 inline Transform & operator=(const EigenBase<OtherDerived>& other) 00286 { 00287 EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value), 00288 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); 00289 00290 internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived ()); 00291 return *this; 00292 } 00293 00294 template<int OtherOptions> 00295 inline Transform (const Transform<Scalar,Dim,Mode,OtherOptions> & other) 00296 { 00297 check_template_params(); 00298 // only the options change, we can directly copy the matrices 00299 m_matrix = other.matrix (); 00300 } 00301 00302 template<int OtherMode,int OtherOptions> 00303 inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) 00304 { 00305 check_template_params(); 00306 // prevent conversions as: 00307 // Affine | AffineCompact | Isometry = Projective 00308 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)), 00309 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION) 00310 00311 // prevent conversions as: 00312 // Isometry = Affine | AffineCompact 00313 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)), 00314 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION) 00315 00316 enum { ModeIsAffineCompact = Mode == int(AffineCompact), 00317 OtherModeIsAffineCompact = OtherMode == int(AffineCompact) 00318 }; 00319 00320 if(ModeIsAffineCompact == OtherModeIsAffineCompact) 00321 { 00322 // We need the block expression because the code is compiled for all 00323 // combinations of transformations and will trigger a compile time error 00324 // if one tries to assign the matrices directly 00325 m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0); 00326 makeAffine(); 00327 } 00328 else if(OtherModeIsAffineCompact) 00329 { 00330 typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType; 00331 internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix()); 00332 } 00333 else 00334 { 00335 // here we know that Mode == AffineCompact and OtherMode != AffineCompact. 00336 // if OtherMode were Projective, the static assert above would already have caught it. 00337 // So the only possibility is that OtherMode == Affine 00338 linear() = other.linear(); 00339 translation() = other.translation(); 00340 } 00341 } 00342 00343 template<typename OtherDerived> 00344 Transform(const ReturnByValue<OtherDerived>& other) 00345 { 00346 check_template_params(); 00347 other.evalTo(*this); 00348 } 00349 00350 template<typename OtherDerived> 00351 Transform& operator=(const ReturnByValue<OtherDerived>& other) 00352 { 00353 other.evalTo(*this); 00354 return *this; 00355 } 00356 00357 #ifdef EIGEN_QT_SUPPORT 00358 inline Transform(const QMatrix& other); 00359 inline Transform& operator=(const QMatrix& other); 00360 inline QMatrix toQMatrix(void) const; 00361 inline Transform(const QTransform& other); 00362 inline Transform& operator=(const QTransform& other); 00363 inline QTransform toQTransform(void) const; 00364 #endif 00365 00366 /** shortcut for m_matrix(row,col); 00367 * \sa MatrixBase::operator(Index,Index) const */ 00368 inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); } 00369 /** shortcut for m_matrix(row,col); 00370 * \sa MatrixBase::operator(Index,Index) */ 00371 inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); } 00372 00373 /** \returns a read-only expression of the transformation matrix */ 00374 inline const MatrixType& matrix () const { return m_matrix; } 00375 /** \returns a writable expression of the transformation matrix */ 00376 inline MatrixType& matrix () { return m_matrix; } 00377 00378 /** \returns a read-only expression of the linear part of the transformation */ 00379 inline ConstLinearPart linear () const { return ConstLinearPart(m_matrix,0,0); } 00380 /** \returns a writable expression of the linear part of the transformation */ 00381 inline LinearPart linear () { return LinearPart(m_matrix,0,0); } 00382 00383 /** \returns a read-only expression of the Dim x HDim affine part of the transformation */ 00384 inline ConstAffinePart affine () const { return take_affine_part::run(m_matrix); } 00385 /** \returns a writable expression of the Dim x HDim affine part of the transformation */ 00386 inline AffinePart affine () { return take_affine_part::run(m_matrix); } 00387 00388 /** \returns a read-only expression of the translation vector of the transformation */ 00389 inline ConstTranslationPart translation () const { return ConstTranslationPart(m_matrix,0,Dim); } 00390 /** \returns a writable expression of the translation vector of the transformation */ 00391 inline TranslationPart translation () { return TranslationPart(m_matrix,0,Dim); } 00392 00393 /** \returns an expression of the product between the transform \c *this and a matrix expression \a other. 00394 * 00395 * The right-hand-side \a other can be either: 00396 * \li an homogeneous vector of size Dim+1, 00397 * \li a set of homogeneous vectors of size Dim+1 x N, 00398 * \li a transformation matrix of size Dim+1 x Dim+1. 00399 * 00400 * Moreover, if \c *this represents an affine transformation (i.e., Mode!=Projective), then \a other can also be: 00401 * \li a point of size Dim (computes: \code this->linear() * other + this->translation()\endcode), 00402 * \li a set of N points as a Dim x N matrix (computes: \code (this->linear() * other).colwise() + this->translation()\endcode), 00403 * 00404 * In all cases, the return type is a matrix or vector of same sizes as the right-hand-side \a other. 00405 * 00406 * If you want to interpret \a other as a linear or affine transformation, then first convert it to a Transform<> type, 00407 * or do your own cooking. 00408 * 00409 * Finally, if you want to apply Affine transformations to vectors, then explicitly apply the linear part only: 00410 * \code 00411 * Affine3f A; 00412 * Vector3f v1, v2; 00413 * v2 = A.linear() * v1; 00414 * \endcode 00415 * 00416 */ 00417 // note: this function is defined here because some compilers cannot find the respective declaration 00418 template<typename OtherDerived> 00419 EIGEN_STRONG_INLINE const typename OtherDerived::PlainObject 00420 operator * (const EigenBase<OtherDerived> &other) const 00421 { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived ()); } 00422 00423 /** \returns the product expression of a transformation matrix \a a times a transform \a b 00424 * 00425 * The left hand side \a other can be either: 00426 * \li a linear transformation matrix of size Dim x Dim, 00427 * \li an affine transformation matrix of size Dim x Dim+1, 00428 * \li a general transformation matrix of size Dim+1 x Dim+1. 00429 */ 00430 template<typename OtherDerived> friend 00431 inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType 00432 operator * (const EigenBase<OtherDerived> &a, const Transform &b) 00433 { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived (),b); } 00434 00435 /** \returns The product expression of a transform \a a times a diagonal matrix \a b 00436 * 00437 * The rhs diagonal matrix is interpreted as an affine scaling transformation. The 00438 * product results in a Transform of the same type (mode) as the lhs only if the lhs 00439 * mode is no isometry. In that case, the returned transform is an affinity. 00440 */ 00441 template<typename DiagonalDerived> 00442 inline const TransformTimeDiagonalReturnType 00443 operator * (const DiagonalBase<DiagonalDerived> &b) const 00444 { 00445 TransformTimeDiagonalReturnType res(*this); 00446 res.linear () *= b; 00447 return res; 00448 } 00449 00450 /** \returns The product expression of a diagonal matrix \a a times a transform \a b 00451 * 00452 * The lhs diagonal matrix is interpreted as an affine scaling transformation. The 00453 * product results in a Transform of the same type (mode) as the lhs only if the lhs 00454 * mode is no isometry. In that case, the returned transform is an affinity. 00455 */ 00456 template<typename DiagonalDerived> 00457 friend inline TransformTimeDiagonalReturnType 00458 operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b) 00459 { 00460 TransformTimeDiagonalReturnType res; 00461 res.linear ().noalias() = a*b.linear (); 00462 res.translation ().noalias() = a*b.translation (); 00463 if (Mode!=int(AffineCompact)) 00464 res.matrix ().row(Dim) = b.matrix ().row(Dim); 00465 return res; 00466 } 00467 00468 template<typename OtherDerived> 00469 inline Transform & operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; } 00470 00471 /** Concatenates two transformations */ 00472 inline const Transform operator * (const Transform & other) const 00473 { 00474 return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other); 00475 } 00476 00477 #ifdef __INTEL_COMPILER 00478 private: 00479 // this intermediate structure permits to workaround a bug in ICC 11: 00480 // error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0> 00481 // (const Eigen::Transform<double, 3, 2, 0> &) const" 00482 // (the meaning of a name may have changed since the template declaration -- the type of the template is: 00483 // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>, 00484 // Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const") 00485 // 00486 template<int OtherMode,int OtherOptions> struct icc_11_workaround 00487 { 00488 typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType; 00489 typedef typename ProductType::ResultType ResultType; 00490 }; 00491 00492 public: 00493 /** Concatenates two different transformations */ 00494 template<int OtherMode,int OtherOptions> 00495 inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType 00496 operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions> & other) const 00497 { 00498 typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType; 00499 return ProductType::run(*this,other); 00500 } 00501 #else 00502 /** Concatenates two different transformations */ 00503 template<int OtherMode,int OtherOptions> 00504 inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType 00505 operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions> & other) const 00506 { 00507 return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other); 00508 } 00509 #endif 00510 00511 /** \sa MatrixBase::setIdentity() */ 00512 void setIdentity () { m_matrix.setIdentity(); } 00513 00514 /** 00515 * \brief Returns an identity transformation. 00516 * \todo In the future this function should be returning a Transform expression. 00517 */ 00518 static const Transform Identity() 00519 { 00520 return Transform (MatrixType::Identity()); 00521 } 00522 00523 template<typename OtherDerived> 00524 inline Transform & scale(const MatrixBase<OtherDerived> &other); 00525 00526 template<typename OtherDerived> 00527 inline Transform & prescale(const MatrixBase<OtherDerived> &other); 00528 00529 inline Transform & scale(const Scalar& s); 00530 inline Transform & prescale(const Scalar& s); 00531 00532 template<typename OtherDerived> 00533 inline Transform & translate(const MatrixBase<OtherDerived> &other); 00534 00535 template<typename OtherDerived> 00536 inline Transform & pretranslate(const MatrixBase<OtherDerived> &other); 00537 00538 template<typename RotationType> 00539 inline Transform & rotate(const RotationType& rotation); 00540 00541 template<typename RotationType> 00542 inline Transform & prerotate(const RotationType& rotation); 00543 00544 Transform & shear(const Scalar& sx, const Scalar& sy); 00545 Transform & preshear(const Scalar& sx, const Scalar& sy); 00546 00547 inline Transform & operator=(const TranslationType& t); 00548 inline Transform & operator*=(const TranslationType& t) { return translate(t.vector()); } 00549 inline Transform operator* (const TranslationType& t) const; 00550 00551 inline Transform& operator=(const UniformScaling<Scalar>& t); 00552 inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); } 00553 inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode))> operator* (const UniformScaling<Scalar>& s) const 00554 { 00555 Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode)),Options> res = *this; 00556 res.scale(s.factor()); 00557 return res; 00558 } 00559 00560 inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; } 00561 00562 template<typename Derived> 00563 inline Transform& operator=(const RotationBase<Derived,Dim>& r); 00564 template<typename Derived> 00565 inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); } 00566 template<typename Derived> 00567 inline Transform operator* (const RotationBase<Derived,Dim>& r) const; 00568 00569 const LinearMatrixType rotation() const; 00570 template<typename RotationMatrixType, typename ScalingMatrixType> 00571 void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const; 00572 template<typename ScalingMatrixType, typename RotationMatrixType> 00573 void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const; 00574 00575 template<typename PositionDerived, typename OrientationType, typename ScaleDerived> 00576 Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position, 00577 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale); 00578 00579 inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const; 00580 00581 /** \returns a const pointer to the column major internal matrix */ 00582 const Scalar* data () const { return m_matrix.data (); } 00583 /** \returns a non-const pointer to the column major internal matrix */ 00584 Scalar* data () { return m_matrix.data (); } 00585 00586 /** \returns \c *this with scalar type casted to \a NewScalarType 00587 * 00588 * Note that if \a NewScalarType is equal to the current scalar type of \c *this 00589 * then this function smartly returns a const reference to \c *this. 00590 */ 00591 template<typename NewScalarType> 00592 inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const 00593 { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); } 00594 00595 /** Copy constructor with scalar type conversion */ 00596 template<typename OtherScalarType> 00597 inline explicit Transform (const Transform<OtherScalarType,Dim,Mode,Options> & other) 00598 { 00599 check_template_params(); 00600 m_matrix = other.matrix ().template cast<Scalar>(); 00601 } 00602 00603 /** \returns \c true if \c *this is approximately equal to \a other, within the precision 00604 * determined by \a prec. 00605 * 00606 * \sa MatrixBase::isApprox() */ 00607 bool isApprox(const Transform & other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const 00608 { return m_matrix.isApprox(other.m_matrix, prec); } 00609 00610 /** Sets the last row to [0 ... 0 1] 00611 */ 00612 void makeAffine() 00613 { 00614 internal::transform_make_affine<int(Mode)>::run(m_matrix); 00615 } 00616 00617 /** \internal 00618 * \returns the Dim x Dim linear part if the transformation is affine, 00619 * and the HDim x Dim part for projective transformations. 00620 */ 00621 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() 00622 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); } 00623 /** \internal 00624 * \returns the Dim x Dim linear part if the transformation is affine, 00625 * and the HDim x Dim part for projective transformations. 00626 */ 00627 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const 00628 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); } 00629 00630 /** \internal 00631 * \returns the translation part if the transformation is affine, 00632 * and the last column for projective transformations. 00633 */ 00634 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() 00635 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); } 00636 /** \internal 00637 * \returns the translation part if the transformation is affine, 00638 * and the last column for projective transformations. 00639 */ 00640 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const 00641 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); } 00642 00643 00644 #ifdef EIGEN_TRANSFORM_PLUGIN 00645 #include EIGEN_TRANSFORM_PLUGIN 00646 #endif 00647 00648 protected: 00649 #ifndef EIGEN_PARSED_BY_DOXYGEN 00650 static EIGEN_STRONG_INLINE void check_template_params() 00651 { 00652 EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS) 00653 } 00654 #endif 00655 00656 }; 00657 00658 /** \ingroup Geometry_Module */ 00659 typedef Transform<float,2,Isometry> Isometry2f; 00660 /** \ingroup Geometry_Module */ 00661 typedef Transform<float,3,Isometry> Isometry3f; 00662 /** \ingroup Geometry_Module */ 00663 typedef Transform<double,2,Isometry> Isometry2d; 00664 /** \ingroup Geometry_Module */ 00665 typedef Transform<double,3,Isometry> Isometry3d; 00666 00667 /** \ingroup Geometry_Module */ 00668 typedef Transform<float,2,Affine> Affine2f; 00669 /** \ingroup Geometry_Module */ 00670 typedef Transform<float,3,Affine> Affine3f; 00671 /** \ingroup Geometry_Module */ 00672 typedef Transform<double,2,Affine> Affine2d; 00673 /** \ingroup Geometry_Module */ 00674 typedef Transform<double,3,Affine> Affine3d; 00675 00676 /** \ingroup Geometry_Module */ 00677 typedef Transform<float,2,AffineCompact> AffineCompact2f; 00678 /** \ingroup Geometry_Module */ 00679 typedef Transform<float,3,AffineCompact> AffineCompact3f; 00680 /** \ingroup Geometry_Module */ 00681 typedef Transform<double,2,AffineCompact> AffineCompact2d; 00682 /** \ingroup Geometry_Module */ 00683 typedef Transform<double,3,AffineCompact> AffineCompact3d; 00684 00685 /** \ingroup Geometry_Module */ 00686 typedef Transform<float,2,Projective> Projective2f; 00687 /** \ingroup Geometry_Module */ 00688 typedef Transform<float,3,Projective> Projective3f; 00689 /** \ingroup Geometry_Module */ 00690 typedef Transform<double,2,Projective> Projective2d; 00691 /** \ingroup Geometry_Module */ 00692 typedef Transform<double,3,Projective> Projective3d; 00693 00694 /************************** 00695 *** Optional QT support *** 00696 **************************/ 00697 00698 #ifdef EIGEN_QT_SUPPORT 00699 /** Initializes \c *this from a QMatrix assuming the dimension is 2. 00700 * 00701 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00702 */ 00703 template<typename Scalar, int Dim, int Mode,int Options> 00704 Transform<Scalar,Dim,Mode,Options>::Transform (const QMatrix& other) 00705 { 00706 check_template_params(); 00707 *this = other; 00708 } 00709 00710 /** Set \c *this from a QMatrix assuming the dimension is 2. 00711 * 00712 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00713 */ 00714 template<typename Scalar, int Dim, int Mode,int Options> 00715 Transform<Scalar,Dim,Mode,Options> & Transform<Scalar,Dim,Mode,Options>::operator= (const QMatrix& other) 00716 { 00717 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00718 m_matrix << other.m11(), other.m21(), other.dx(), 00719 other.m12(), other.m22(), other.dy(), 00720 0, 0, 1; 00721 return *this; 00722 } 00723 00724 /** \returns a QMatrix from \c *this assuming the dimension is 2. 00725 * 00726 * \warning this conversion might loss data if \c *this is not affine 00727 * 00728 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00729 */ 00730 template<typename Scalar, int Dim, int Mode, int Options> 00731 QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix (void) const 00732 { 00733 check_template_params(); 00734 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00735 return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0), 00736 m_matrix.coeff(0,1), m_matrix.coeff(1,1), 00737 m_matrix.coeff(0,2), m_matrix.coeff(1,2)); 00738 } 00739 00740 /** Initializes \c *this from a QTransform assuming the dimension is 2. 00741 * 00742 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00743 */ 00744 template<typename Scalar, int Dim, int Mode,int Options> 00745 Transform<Scalar,Dim,Mode,Options>::Transform (const QTransform& other) 00746 { 00747 check_template_params(); 00748 *this = other; 00749 } 00750 00751 /** Set \c *this from a QTransform assuming the dimension is 2. 00752 * 00753 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00754 */ 00755 template<typename Scalar, int Dim, int Mode, int Options> 00756 Transform<Scalar,Dim,Mode,Options> & Transform<Scalar,Dim,Mode,Options>::operator= (const QTransform& other) 00757 { 00758 check_template_params(); 00759 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00760 if (Mode == int(AffineCompact)) 00761 m_matrix << other.m11(), other.m21(), other.dx(), 00762 other.m12(), other.m22(), other.dy(); 00763 else 00764 m_matrix << other.m11(), other.m21(), other.dx(), 00765 other.m12(), other.m22(), other.dy(), 00766 other.m13(), other.m23(), other.m33(); 00767 return *this; 00768 } 00769 00770 /** \returns a QTransform from \c *this assuming the dimension is 2. 00771 * 00772 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 00773 */ 00774 template<typename Scalar, int Dim, int Mode, int Options> 00775 QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform (void) const 00776 { 00777 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00778 if (Mode == int(AffineCompact)) 00779 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), 00780 m_matrix.coeff(0,1), m_matrix.coeff(1,1), 00781 m_matrix.coeff(0,2), m_matrix.coeff(1,2)); 00782 else 00783 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0), 00784 m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1), 00785 m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2)); 00786 } 00787 #endif 00788 00789 /********************* 00790 *** Procedural API *** 00791 *********************/ 00792 00793 /** Applies on the right the non uniform scale transformation represented 00794 * by the vector \a other to \c *this and returns a reference to \c *this. 00795 * \sa prescale() 00796 */ 00797 template<typename Scalar, int Dim, int Mode, int Options> 00798 template<typename OtherDerived> 00799 Transform<Scalar,Dim,Mode,Options> & 00800 Transform<Scalar,Dim,Mode,Options>::scale (const MatrixBase<OtherDerived> &other) 00801 { 00802 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 00803 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00804 linearExt().noalias() = (linearExt() * other.asDiagonal ()); 00805 return *this; 00806 } 00807 00808 /** Applies on the right a uniform scale of a factor \a c to \c *this 00809 * and returns a reference to \c *this. 00810 * \sa prescale(Scalar) 00811 */ 00812 template<typename Scalar, int Dim, int Mode, int Options> 00813 inline Transform<Scalar,Dim,Mode,Options> & Transform<Scalar,Dim,Mode,Options>::scale (const Scalar& s) 00814 { 00815 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00816 linearExt() *= s; 00817 return *this; 00818 } 00819 00820 /** Applies on the left the non uniform scale transformation represented 00821 * by the vector \a other to \c *this and returns a reference to \c *this. 00822 * \sa scale() 00823 */ 00824 template<typename Scalar, int Dim, int Mode, int Options> 00825 template<typename OtherDerived> 00826 Transform<Scalar,Dim,Mode,Options> & 00827 Transform<Scalar,Dim,Mode,Options>::prescale (const MatrixBase<OtherDerived> &other) 00828 { 00829 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 00830 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00831 m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal () * m_matrix.template block<Dim,HDim>(0,0)); 00832 return *this; 00833 } 00834 00835 /** Applies on the left a uniform scale of a factor \a c to \c *this 00836 * and returns a reference to \c *this. 00837 * \sa scale(Scalar) 00838 */ 00839 template<typename Scalar, int Dim, int Mode, int Options> 00840 inline Transform<Scalar,Dim,Mode,Options> & Transform<Scalar,Dim,Mode,Options>::prescale (const Scalar& s) 00841 { 00842 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00843 m_matrix.template topRows<Dim>() *= s; 00844 return *this; 00845 } 00846 00847 /** Applies on the right the translation matrix represented by the vector \a other 00848 * to \c *this and returns a reference to \c *this. 00849 * \sa pretranslate() 00850 */ 00851 template<typename Scalar, int Dim, int Mode, int Options> 00852 template<typename OtherDerived> 00853 Transform<Scalar,Dim,Mode,Options> & 00854 Transform<Scalar,Dim,Mode,Options>::translate (const MatrixBase<OtherDerived> &other) 00855 { 00856 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 00857 translationExt() += linearExt() * other; 00858 return *this; 00859 } 00860 00861 /** Applies on the left the translation matrix represented by the vector \a other 00862 * to \c *this and returns a reference to \c *this. 00863 * \sa translate() 00864 */ 00865 template<typename Scalar, int Dim, int Mode, int Options> 00866 template<typename OtherDerived> 00867 Transform<Scalar,Dim,Mode,Options> & 00868 Transform<Scalar,Dim,Mode,Options>::pretranslate (const MatrixBase<OtherDerived> &other) 00869 { 00870 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 00871 if(int(Mode)==int(Projective)) 00872 affine() += other * m_matrix.row(Dim); 00873 else 00874 translation() += other; 00875 return *this; 00876 } 00877 00878 /** Applies on the right the rotation represented by the rotation \a rotation 00879 * to \c *this and returns a reference to \c *this. 00880 * 00881 * The template parameter \a RotationType is the type of the rotation which 00882 * must be known by internal::toRotationMatrix<>. 00883 * 00884 * Natively supported types includes: 00885 * - any scalar (2D), 00886 * - a Dim x Dim matrix expression, 00887 * - a Quaternion (3D), 00888 * - a AngleAxis (3D) 00889 * 00890 * This mechanism is easily extendable to support user types such as Euler angles, 00891 * or a pair of Quaternion for 4D rotations. 00892 * 00893 * \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType) 00894 */ 00895 template<typename Scalar, int Dim, int Mode, int Options> 00896 template<typename RotationType> 00897 Transform<Scalar,Dim,Mode,Options> & 00898 Transform<Scalar,Dim,Mode,Options>::rotate (const RotationType& rotation) 00899 { 00900 linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation); 00901 return *this; 00902 } 00903 00904 /** Applies on the left the rotation represented by the rotation \a rotation 00905 * to \c *this and returns a reference to \c *this. 00906 * 00907 * See rotate() for further details. 00908 * 00909 * \sa rotate() 00910 */ 00911 template<typename Scalar, int Dim, int Mode, int Options> 00912 template<typename RotationType> 00913 Transform<Scalar,Dim,Mode,Options> & 00914 Transform<Scalar,Dim,Mode,Options>::prerotate (const RotationType& rotation) 00915 { 00916 m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation) 00917 * m_matrix.template block<Dim,HDim>(0,0); 00918 return *this; 00919 } 00920 00921 /** Applies on the right the shear transformation represented 00922 * by the vector \a other to \c *this and returns a reference to \c *this. 00923 * \warning 2D only. 00924 * \sa preshear() 00925 */ 00926 template<typename Scalar, int Dim, int Mode, int Options> 00927 Transform<Scalar,Dim,Mode,Options> & 00928 Transform<Scalar,Dim,Mode,Options>::shear (const Scalar& sx, const Scalar& sy) 00929 { 00930 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00931 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00932 VectorType tmp = linear().col(0)*sy + linear().col(1); 00933 linear() << linear().col(0) + linear().col(1)*sx, tmp; 00934 return *this; 00935 } 00936 00937 /** Applies on the left the shear transformation represented 00938 * by the vector \a other to \c *this and returns a reference to \c *this. 00939 * \warning 2D only. 00940 * \sa shear() 00941 */ 00942 template<typename Scalar, int Dim, int Mode, int Options> 00943 Transform<Scalar,Dim,Mode,Options> & 00944 Transform<Scalar,Dim,Mode,Options>::preshear (const Scalar& sx, const Scalar& sy) 00945 { 00946 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 00947 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 00948 m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0); 00949 return *this; 00950 } 00951 00952 /****************************************************** 00953 *** Scaling, Translation and Rotation compatibility *** 00954 ******************************************************/ 00955 00956 template<typename Scalar, int Dim, int Mode, int Options> 00957 inline Transform<Scalar,Dim,Mode,Options> & Transform<Scalar,Dim,Mode,Options>::operator= (const TranslationType& t) 00958 { 00959 linear().setIdentity (); 00960 translation() = t.vector(); 00961 makeAffine(); 00962 return *this; 00963 } 00964 00965 template<typename Scalar, int Dim, int Mode, int Options> 00966 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator* (const TranslationType& t) const 00967 { 00968 Transform res = *this; 00969 res.translate(t.vector()); 00970 return res; 00971 } 00972 00973 template<typename Scalar, int Dim, int Mode, int Options> 00974 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s) 00975 { 00976 m_matrix.setZero(); 00977 linear().diagonal().fill(s.factor()); 00978 makeAffine(); 00979 return *this; 00980 } 00981 00982 template<typename Scalar, int Dim, int Mode, int Options> 00983 template<typename Derived> 00984 inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r) 00985 { 00986 linear() = internal::toRotationMatrix<Scalar,Dim>(r); 00987 translation().setZero(); 00988 makeAffine(); 00989 return *this; 00990 } 00991 00992 template<typename Scalar, int Dim, int Mode, int Options> 00993 template<typename Derived> 00994 inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator* (const RotationBase<Derived,Dim>& r) const 00995 { 00996 Transform res = *this; 00997 res.rotate(r.derived()); 00998 return res; 00999 } 01000 01001 /************************ 01002 *** Special functions *** 01003 ************************/ 01004 01005 /** \returns the rotation part of the transformation 01006 * 01007 * 01008 * \svd_module 01009 * 01010 * \sa computeRotationScaling(), computeScalingRotation(), class SVD 01011 */ 01012 template<typename Scalar, int Dim, int Mode, int Options> 01013 const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType 01014 Transform<Scalar,Dim,Mode,Options>::rotation () const 01015 { 01016 LinearMatrixType result; 01017 computeRotationScaling(&result, (LinearMatrixType*)0); 01018 return result; 01019 } 01020 01021 01022 /** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being 01023 * not necessarily positive. 01024 * 01025 * If either pointer is zero, the corresponding computation is skipped. 01026 * 01027 * 01028 * 01029 * \svd_module 01030 * 01031 * \sa computeScalingRotation(), rotation(), class SVD 01032 */ 01033 template<typename Scalar, int Dim, int Mode, int Options> 01034 template<typename RotationMatrixType, typename ScalingMatrixType> 01035 void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling (RotationMatrixType *rotation, ScalingMatrixType *scaling) const 01036 { 01037 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV); 01038 01039 Scalar x = (svd.matrixU () * svd.matrixV ().adjoint()).determinant(); // so x has absolute value 1 01040 VectorType sv(svd.singularValues ()); 01041 sv.coeffRef(0) *= x; 01042 if(scaling) scaling->lazyAssign(svd.matrixV () * sv.asDiagonal() * svd.matrixV ().adjoint()); 01043 if(rotation) 01044 { 01045 LinearMatrixType m(svd.matrixU ()); 01046 m.col(0) /= x; 01047 rotation->lazyAssign(m * svd.matrixV ().adjoint()); 01048 } 01049 } 01050 01051 /** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being 01052 * not necessarily positive. 01053 * 01054 * If either pointer is zero, the corresponding computation is skipped. 01055 * 01056 * 01057 * 01058 * \svd_module 01059 * 01060 * \sa computeRotationScaling(), rotation(), class SVD 01061 */ 01062 template<typename Scalar, int Dim, int Mode, int Options> 01063 template<typename ScalingMatrixType, typename RotationMatrixType> 01064 void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation (ScalingMatrixType *scaling, RotationMatrixType *rotation) const 01065 { 01066 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV); 01067 01068 Scalar x = (svd.matrixU () * svd.matrixV ().adjoint()).determinant(); // so x has absolute value 1 01069 VectorType sv(svd.singularValues ()); 01070 sv.coeffRef(0) *= x; 01071 if(scaling) scaling->lazyAssign(svd.matrixU () * sv.asDiagonal() * svd.matrixU ().adjoint()); 01072 if(rotation) 01073 { 01074 LinearMatrixType m(svd.matrixU ()); 01075 m.col(0) /= x; 01076 rotation->lazyAssign(m * svd.matrixV ().adjoint()); 01077 } 01078 } 01079 01080 /** Convenient method to set \c *this from a position, orientation and scale 01081 * of a 3D object. 01082 */ 01083 template<typename Scalar, int Dim, int Mode, int Options> 01084 template<typename PositionDerived, typename OrientationType, typename ScaleDerived> 01085 Transform<Scalar,Dim,Mode,Options> & 01086 Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale (const MatrixBase<PositionDerived> &position, 01087 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale) 01088 { 01089 linear() = internal::toRotationMatrix<Scalar,Dim>(orientation); 01090 linear() *= scale.asDiagonal (); 01091 translation() = position; 01092 makeAffine(); 01093 return *this; 01094 } 01095 01096 namespace internal { 01097 01098 template<int Mode> 01099 struct transform_make_affine 01100 { 01101 template<typename MatrixType> 01102 static void run(MatrixType &mat) 01103 { 01104 static const int Dim = MatrixType::ColsAtCompileTime-1; 01105 mat.template block<1,Dim>(Dim,0).setZero(); 01106 mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1); 01107 } 01108 }; 01109 01110 template<> 01111 struct transform_make_affine<AffineCompact> 01112 { 01113 template<typename MatrixType> static void run(MatrixType &) { } 01114 }; 01115 01116 // selector needed to avoid taking the inverse of a 3x4 matrix 01117 template<typename TransformType, int Mode=TransformType::Mode> 01118 struct projective_transform_inverse 01119 { 01120 static inline void run(const TransformType&, TransformType&) 01121 {} 01122 }; 01123 01124 template<typename TransformType> 01125 struct projective_transform_inverse<TransformType, Projective> 01126 { 01127 static inline void run(const TransformType& m, TransformType& res) 01128 { 01129 res.matrix() = m.matrix().inverse(); 01130 } 01131 }; 01132 01133 } // end namespace internal 01134 01135 01136 /** 01137 * 01138 * \returns the inverse transformation according to some given knowledge 01139 * on \c *this. 01140 * 01141 * \param hint allows to optimize the inversion process when the transformation 01142 * is known to be not a general transformation (optional). The possible values are: 01143 * - #Projective if the transformation is not necessarily affine, i.e., if the 01144 * last row is not guaranteed to be [0 ... 0 1] 01145 * - #Affine if the last row can be assumed to be [0 ... 0 1] 01146 * - #Isometry if the transformation is only a concatenations of translations 01147 * and rotations. 01148 * The default is the template class parameter \c Mode. 01149 * 01150 * \warning unless \a traits is always set to NoShear or NoScaling, this function 01151 * requires the generic inverse method of MatrixBase defined in the LU module. If 01152 * you forget to include this module, then you will get hard to debug linking errors. 01153 * 01154 * \sa MatrixBase::inverse() 01155 */ 01156 template<typename Scalar, int Dim, int Mode, int Options> 01157 Transform<Scalar,Dim,Mode,Options> 01158 Transform<Scalar,Dim,Mode,Options>::inverse (TransformTraits hint) const 01159 { 01160 Transform res; 01161 if (hint == Projective) 01162 { 01163 internal::projective_transform_inverse<Transform>::run(*this, res); 01164 } 01165 else 01166 { 01167 if (hint == Isometry) 01168 { 01169 res.matrix ().template topLeftCorner<Dim,Dim>() = linear().transpose(); 01170 } 01171 else if(hint&Affine) 01172 { 01173 res.matrix ().template topLeftCorner<Dim,Dim>() = linear().inverse(); 01174 } 01175 else 01176 { 01177 eigen_assert(false && "Invalid transform traits in Transform::Inverse"); 01178 } 01179 // translation and remaining parts 01180 res.matrix ().template topRightCorner<Dim,1>() 01181 = - res.matrix ().template topLeftCorner<Dim,Dim>() * translation(); 01182 res.makeAffine(); // we do need this, because in the beginning res is uninitialized 01183 } 01184 return res; 01185 } 01186 01187 namespace internal { 01188 01189 /***************************************************** 01190 *** Specializations of take affine part *** 01191 *****************************************************/ 01192 01193 template<typename TransformType> struct transform_take_affine_part { 01194 typedef typename TransformType::MatrixType MatrixType; 01195 typedef typename TransformType::AffinePart AffinePart; 01196 typedef typename TransformType::ConstAffinePart ConstAffinePart; 01197 static inline AffinePart run(MatrixType& m) 01198 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); } 01199 static inline ConstAffinePart run(const MatrixType& m) 01200 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); } 01201 }; 01202 01203 template<typename Scalar, int Dim, int Options> 01204 struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > { 01205 typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType; 01206 static inline MatrixType& run(MatrixType& m) { return m; } 01207 static inline const MatrixType& run(const MatrixType& m) { return m; } 01208 }; 01209 01210 /***************************************************** 01211 *** Specializations of construct from matrix *** 01212 *****************************************************/ 01213 01214 template<typename Other, int Mode, int Options, int Dim, int HDim> 01215 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim> 01216 { 01217 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 01218 { 01219 transform->linear() = other; 01220 transform->translation().setZero(); 01221 transform->makeAffine(); 01222 } 01223 }; 01224 01225 template<typename Other, int Mode, int Options, int Dim, int HDim> 01226 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim> 01227 { 01228 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 01229 { 01230 transform->affine() = other; 01231 transform->makeAffine(); 01232 } 01233 }; 01234 01235 template<typename Other, int Mode, int Options, int Dim, int HDim> 01236 struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim> 01237 { 01238 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 01239 { transform->matrix() = other; } 01240 }; 01241 01242 template<typename Other, int Options, int Dim, int HDim> 01243 struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim> 01244 { 01245 static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other) 01246 { transform->matrix() = other.template block<Dim,HDim>(0,0); } 01247 }; 01248 01249 /********************************************************** 01250 *** Specializations of operator* with rhs EigenBase *** 01251 **********************************************************/ 01252 01253 template<int LhsMode,int RhsMode> 01254 struct transform_product_result 01255 { 01256 enum 01257 { 01258 Mode = 01259 (LhsMode == (int)Projective || RhsMode == (int)Projective ) ? Projective : 01260 (LhsMode == (int)Affine || RhsMode == (int)Affine ) ? Affine : 01261 (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact : 01262 (LhsMode == (int)Isometry || RhsMode == (int)Isometry ) ? Isometry : Projective 01263 }; 01264 }; 01265 01266 template< typename TransformType, typename MatrixType > 01267 struct transform_right_product_impl< TransformType, MatrixType, 0 > 01268 { 01269 typedef typename MatrixType::PlainObject ResultType; 01270 01271 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 01272 { 01273 return T.matrix() * other; 01274 } 01275 }; 01276 01277 template< typename TransformType, typename MatrixType > 01278 struct transform_right_product_impl< TransformType, MatrixType, 1 > 01279 { 01280 enum { 01281 Dim = TransformType::Dim, 01282 HDim = TransformType::HDim, 01283 OtherRows = MatrixType::RowsAtCompileTime, 01284 OtherCols = MatrixType::ColsAtCompileTime 01285 }; 01286 01287 typedef typename MatrixType::PlainObject ResultType; 01288 01289 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 01290 { 01291 EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); 01292 01293 typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs; 01294 01295 ResultType res(other.rows(),other.cols()); 01296 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other; 01297 res.row(OtherRows-1) = other.row(OtherRows-1); 01298 01299 return res; 01300 } 01301 }; 01302 01303 template< typename TransformType, typename MatrixType > 01304 struct transform_right_product_impl< TransformType, MatrixType, 2 > 01305 { 01306 enum { 01307 Dim = TransformType::Dim, 01308 HDim = TransformType::HDim, 01309 OtherRows = MatrixType::RowsAtCompileTime, 01310 OtherCols = MatrixType::ColsAtCompileTime 01311 }; 01312 01313 typedef typename MatrixType::PlainObject ResultType; 01314 01315 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 01316 { 01317 EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); 01318 01319 typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs; 01320 ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols())); 01321 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other; 01322 01323 return res; 01324 } 01325 }; 01326 01327 /********************************************************** 01328 *** Specializations of operator* with lhs EigenBase *** 01329 **********************************************************/ 01330 01331 // generic HDim x HDim matrix * T => Projective 01332 template<typename Other,int Mode, int Options, int Dim, int HDim> 01333 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim> 01334 { 01335 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 01336 typedef typename TransformType::MatrixType MatrixType; 01337 typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType; 01338 static ResultType run(const Other& other,const TransformType& tr) 01339 { return ResultType(other * tr.matrix()); } 01340 }; 01341 01342 // generic HDim x HDim matrix * AffineCompact => Projective 01343 template<typename Other, int Options, int Dim, int HDim> 01344 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim> 01345 { 01346 typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType; 01347 typedef typename TransformType::MatrixType MatrixType; 01348 typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType; 01349 static ResultType run(const Other& other,const TransformType& tr) 01350 { 01351 ResultType res; 01352 res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix(); 01353 res.matrix().col(Dim) += other.col(Dim); 01354 return res; 01355 } 01356 }; 01357 01358 // affine matrix * T 01359 template<typename Other,int Mode, int Options, int Dim, int HDim> 01360 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim> 01361 { 01362 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 01363 typedef typename TransformType::MatrixType MatrixType; 01364 typedef TransformType ResultType; 01365 static ResultType run(const Other& other,const TransformType& tr) 01366 { 01367 ResultType res; 01368 res.affine().noalias() = other * tr.matrix(); 01369 res.matrix().row(Dim) = tr.matrix().row(Dim); 01370 return res; 01371 } 01372 }; 01373 01374 // affine matrix * AffineCompact 01375 template<typename Other, int Options, int Dim, int HDim> 01376 struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim> 01377 { 01378 typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType; 01379 typedef typename TransformType::MatrixType MatrixType; 01380 typedef TransformType ResultType; 01381 static ResultType run(const Other& other,const TransformType& tr) 01382 { 01383 ResultType res; 01384 res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix(); 01385 res.translation() += other.col(Dim); 01386 return res; 01387 } 01388 }; 01389 01390 // linear matrix * T 01391 template<typename Other,int Mode, int Options, int Dim, int HDim> 01392 struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim> 01393 { 01394 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 01395 typedef typename TransformType::MatrixType MatrixType; 01396 typedef TransformType ResultType; 01397 static ResultType run(const Other& other, const TransformType& tr) 01398 { 01399 TransformType res; 01400 if(Mode!=int(AffineCompact)) 01401 res.matrix().row(Dim) = tr.matrix().row(Dim); 01402 res.matrix().template topRows<Dim>().noalias() 01403 = other * tr.matrix().template topRows<Dim>(); 01404 return res; 01405 } 01406 }; 01407 01408 /********************************************************** 01409 *** Specializations of operator* with another Transform *** 01410 **********************************************************/ 01411 01412 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 01413 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false > 01414 { 01415 enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode }; 01416 typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs; 01417 typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs; 01418 typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType; 01419 static ResultType run(const Lhs& lhs, const Rhs& rhs) 01420 { 01421 ResultType res; 01422 res.linear() = lhs.linear() * rhs.linear(); 01423 res.translation() = lhs.linear() * rhs.translation() + lhs.translation(); 01424 res.makeAffine(); 01425 return res; 01426 } 01427 }; 01428 01429 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 01430 struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true > 01431 { 01432 typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs; 01433 typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs; 01434 typedef Transform<Scalar,Dim,Projective> ResultType; 01435 static ResultType run(const Lhs& lhs, const Rhs& rhs) 01436 { 01437 return ResultType( lhs.matrix() * rhs.matrix() ); 01438 } 01439 }; 01440 01441 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 01442 struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true > 01443 { 01444 typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs; 01445 typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs; 01446 typedef Transform<Scalar,Dim,Projective> ResultType; 01447 static ResultType run(const Lhs& lhs, const Rhs& rhs) 01448 { 01449 ResultType res; 01450 res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix(); 01451 res.matrix().row(Dim) = rhs.matrix().row(Dim); 01452 return res; 01453 } 01454 }; 01455 01456 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 01457 struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true > 01458 { 01459 typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs; 01460 typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs; 01461 typedef Transform<Scalar,Dim,Projective> ResultType; 01462 static ResultType run(const Lhs& lhs, const Rhs& rhs) 01463 { 01464 ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix()); 01465 res.matrix().col(Dim) += lhs.matrix().col(Dim); 01466 return res; 01467 } 01468 }; 01469 01470 } // end namespace internal 01471 01472 } // end namespace Eigen 01473 01474 #endif // EIGEN_TRANSFORM_H
Generated on Thu Nov 17 2022 22:01:30 by
1.7.2