1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 5// Copyright (C) 2009 Benoit Jacob <jacob.benoit.1@gmail.com> 6// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com> 7// 8// This Source Code Form is subject to the terms of the Mozilla 9// Public License v. 2.0. If a copy of the MPL was not distributed 10// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 11 12#ifndef EIGEN_TRANSFORM_H 13#define EIGEN_TRANSFORM_H 14 15namespace Eigen { 16 17namespace internal { 18 19template<typename Transform> 20struct transform_traits 21{ 22 enum 23 { 24 Dim = Transform::Dim, 25 HDim = Transform::HDim, 26 Mode = Transform::Mode, 27 IsProjective = (int(Mode)==int(Projective)) 28 }; 29}; 30 31template< typename TransformType, 32 typename MatrixType, 33 int Case = transform_traits<TransformType>::IsProjective ? 0 34 : int(MatrixType::RowsAtCompileTime) == int(transform_traits<TransformType>::HDim) ? 1 35 : 2> 36struct transform_right_product_impl; 37 38template< typename Other, 39 int Mode, 40 int Options, 41 int Dim, 42 int HDim, 43 int OtherRows=Other::RowsAtCompileTime, 44 int OtherCols=Other::ColsAtCompileTime> 45struct transform_left_product_impl; 46 47template< typename Lhs, 48 typename Rhs, 49 bool AnyProjective = 50 transform_traits<Lhs>::IsProjective || 51 transform_traits<Rhs>::IsProjective> 52struct transform_transform_product_impl; 53 54template< typename Other, 55 int Mode, 56 int Options, 57 int Dim, 58 int HDim, 59 int OtherRows=Other::RowsAtCompileTime, 60 int OtherCols=Other::ColsAtCompileTime> 61struct transform_construct_from_matrix; 62 63template<typename TransformType> struct transform_take_affine_part; 64 65template<int Mode> struct transform_make_affine; 66 67} // end namespace internal 68 69/** \geometry_module \ingroup Geometry_Module 70 * 71 * \class Transform 72 * 73 * \brief Represents an homogeneous transformation in a N dimensional space 74 * 75 * \tparam _Scalar the scalar type, i.e., the type of the coefficients 76 * \tparam _Dim the dimension of the space 77 * \tparam _Mode the type of the transformation. Can be: 78 * - #Affine: the transformation is stored as a (Dim+1)^2 matrix, 79 * where the last row is assumed to be [0 ... 0 1]. 80 * - #AffineCompact: the transformation is stored as a (Dim)x(Dim+1) matrix. 81 * - #Projective: the transformation is stored as a (Dim+1)^2 matrix 82 * without any assumption. 83 * \tparam _Options has the same meaning as in class Matrix. It allows to specify DontAlign and/or RowMajor. 84 * These Options are passed directly to the underlying matrix type. 85 * 86 * The homography is internally represented and stored by a matrix which 87 * is available through the matrix() method. To understand the behavior of 88 * this class you have to think a Transform object as its internal 89 * matrix representation. The chosen convention is right multiply: 90 * 91 * \code v' = T * v \endcode 92 * 93 * Therefore, an affine transformation matrix M is shaped like this: 94 * 95 * \f$ \left( \begin{array}{cc} 96 * linear & translation\\ 97 * 0 ... 0 & 1 98 * \end{array} \right) \f$ 99 * 100 * Note that for a projective transformation the last row can be anything, 101 * and then the interpretation of different parts might be sightly different. 102 * 103 * However, unlike a plain matrix, the Transform class provides many features 104 * simplifying both its assembly and usage. In particular, it can be composed 105 * with any other transformations (Transform,Translation,RotationBase,Matrix) 106 * and can be directly used to transform implicit homogeneous vectors. All these 107 * operations are handled via the operator*. For the composition of transformations, 108 * its principle consists to first convert the right/left hand sides of the product 109 * to a compatible (Dim+1)^2 matrix and then perform a pure matrix product. 110 * Of course, internally, operator* tries to perform the minimal number of operations 111 * according to the nature of each terms. Likewise, when applying the transform 112 * to non homogeneous vectors, the latters are automatically promoted to homogeneous 113 * one before doing the matrix product. The convertions to homogeneous representations 114 * are performed as follow: 115 * 116 * \b Translation t (Dim)x(1): 117 * \f$ \left( \begin{array}{cc} 118 * I & t \\ 119 * 0\,...\,0 & 1 120 * \end{array} \right) \f$ 121 * 122 * \b Rotation R (Dim)x(Dim): 123 * \f$ \left( \begin{array}{cc} 124 * R & 0\\ 125 * 0\,...\,0 & 1 126 * \end{array} \right) \f$ 127 * 128 * \b Linear \b Matrix L (Dim)x(Dim): 129 * \f$ \left( \begin{array}{cc} 130 * L & 0\\ 131 * 0\,...\,0 & 1 132 * \end{array} \right) \f$ 133 * 134 * \b Affine \b Matrix A (Dim)x(Dim+1): 135 * \f$ \left( \begin{array}{c} 136 * A\\ 137 * 0\,...\,0\,1 138 * \end{array} \right) \f$ 139 * 140 * \b Column \b vector v (Dim)x(1): 141 * \f$ \left( \begin{array}{c} 142 * v\\ 143 * 1 144 * \end{array} \right) \f$ 145 * 146 * \b Set \b of \b column \b vectors V1...Vn (Dim)x(n): 147 * \f$ \left( \begin{array}{ccc} 148 * v_1 & ... & v_n\\ 149 * 1 & ... & 1 150 * \end{array} \right) \f$ 151 * 152 * The concatenation of a Transform object with any kind of other transformation 153 * always returns a Transform object. 154 * 155 * A little exception to the "as pure matrix product" rule is the case of the 156 * transformation of non homogeneous vectors by an affine transformation. In 157 * that case the last matrix row can be ignored, and the product returns non 158 * homogeneous vectors. 159 * 160 * Since, for instance, a Dim x Dim matrix is interpreted as a linear transformation, 161 * it is not possible to directly transform Dim vectors stored in a Dim x Dim matrix. 162 * The solution is either to use a Dim x Dynamic matrix or explicitly request a 163 * vector transformation by making the vector homogeneous: 164 * \code 165 * m' = T * m.colwise().homogeneous(); 166 * \endcode 167 * Note that there is zero overhead. 168 * 169 * Conversion methods from/to Qt's QMatrix and QTransform are available if the 170 * preprocessor token EIGEN_QT_SUPPORT is defined. 171 * 172 * This class can be extended with the help of the plugin mechanism described on the page 173 * \ref TopicCustomizingEigen by defining the preprocessor symbol \c EIGEN_TRANSFORM_PLUGIN. 174 * 175 * \sa class Matrix, class Quaternion 176 */ 177template<typename _Scalar, int _Dim, int _Mode, int _Options> 178class Transform 179{ 180public: 181 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1)) 182 enum { 183 Mode = _Mode, 184 Options = _Options, 185 Dim = _Dim, ///< space dimension in which the transformation holds 186 HDim = _Dim+1, ///< size of a respective homogeneous vector 187 Rows = int(Mode)==(AffineCompact) ? Dim : HDim 188 }; 189 /** the scalar type of the coefficients */ 190 typedef _Scalar Scalar; 191 typedef DenseIndex Index; 192 /** type of the matrix used to represent the transformation */ 193 typedef typename internal::make_proper_matrix_type<Scalar,Rows,HDim,Options>::type MatrixType; 194 /** constified MatrixType */ 195 typedef const MatrixType ConstMatrixType; 196 /** type of the matrix used to represent the linear part of the transformation */ 197 typedef Matrix<Scalar,Dim,Dim,Options> LinearMatrixType; 198 /** type of read/write reference to the linear part of the transformation */ 199 typedef Block<MatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> LinearPart; 200 /** type of read reference to the linear part of the transformation */ 201 typedef const Block<ConstMatrixType,Dim,Dim,int(Mode)==(AffineCompact) && (Options&RowMajor)==0> ConstLinearPart; 202 /** type of read/write reference to the affine part of the transformation */ 203 typedef typename internal::conditional<int(Mode)==int(AffineCompact), 204 MatrixType&, 205 Block<MatrixType,Dim,HDim> >::type AffinePart; 206 /** type of read reference to the affine part of the transformation */ 207 typedef typename internal::conditional<int(Mode)==int(AffineCompact), 208 const MatrixType&, 209 const Block<const MatrixType,Dim,HDim> >::type ConstAffinePart; 210 /** type of a vector */ 211 typedef Matrix<Scalar,Dim,1> VectorType; 212 /** type of a read/write reference to the translation part of the rotation */ 213 typedef Block<MatrixType,Dim,1,int(Mode)==(AffineCompact)> TranslationPart; 214 /** type of a read reference to the translation part of the rotation */ 215 typedef const Block<ConstMatrixType,Dim,1,int(Mode)==(AffineCompact)> ConstTranslationPart; 216 /** corresponding translation type */ 217 typedef Translation<Scalar,Dim> TranslationType; 218 219 // this intermediate enum is needed to avoid an ICE with gcc 3.4 and 4.0 220 enum { TransformTimeDiagonalMode = ((Mode==int(Isometry))?Affine:int(Mode)) }; 221 /** The return type of the product between a diagonal matrix and a transform */ 222 typedef Transform<Scalar,Dim,TransformTimeDiagonalMode> TransformTimeDiagonalReturnType; 223 224protected: 225 226 MatrixType m_matrix; 227 228public: 229 230 /** Default constructor without initialization of the meaningful coefficients. 231 * If Mode==Affine, then the last row is set to [0 ... 0 1] */ 232 inline Transform() 233 { 234 check_template_params(); 235 internal::transform_make_affine<(int(Mode)==Affine) ? Affine : AffineCompact>::run(m_matrix); 236 } 237 238 inline Transform(const Transform& other) 239 { 240 check_template_params(); 241 m_matrix = other.m_matrix; 242 } 243 244 inline explicit Transform(const TranslationType& t) 245 { 246 check_template_params(); 247 *this = t; 248 } 249 inline explicit Transform(const UniformScaling<Scalar>& s) 250 { 251 check_template_params(); 252 *this = s; 253 } 254 template<typename Derived> 255 inline explicit Transform(const RotationBase<Derived, Dim>& r) 256 { 257 check_template_params(); 258 *this = r; 259 } 260 261 inline Transform& operator=(const Transform& other) 262 { m_matrix = other.m_matrix; return *this; } 263 264 typedef internal::transform_take_affine_part<Transform> take_affine_part; 265 266 /** Constructs and initializes a transformation from a Dim^2 or a (Dim+1)^2 matrix. */ 267 template<typename OtherDerived> 268 inline explicit Transform(const EigenBase<OtherDerived>& other) 269 { 270 EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value), 271 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); 272 273 check_template_params(); 274 internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived()); 275 } 276 277 /** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */ 278 template<typename OtherDerived> 279 inline Transform& operator=(const EigenBase<OtherDerived>& other) 280 { 281 EIGEN_STATIC_ASSERT((internal::is_same<Scalar,typename OtherDerived::Scalar>::value), 282 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY); 283 284 internal::transform_construct_from_matrix<OtherDerived,Mode,Options,Dim,HDim>::run(this, other.derived()); 285 return *this; 286 } 287 288 template<int OtherOptions> 289 inline Transform(const Transform<Scalar,Dim,Mode,OtherOptions>& other) 290 { 291 check_template_params(); 292 // only the options change, we can directly copy the matrices 293 m_matrix = other.matrix(); 294 } 295 296 template<int OtherMode,int OtherOptions> 297 inline Transform(const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) 298 { 299 check_template_params(); 300 // prevent conversions as: 301 // Affine | AffineCompact | Isometry = Projective 302 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Projective), Mode==int(Projective)), 303 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION) 304 305 // prevent conversions as: 306 // Isometry = Affine | AffineCompact 307 EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(OtherMode==int(Affine)||OtherMode==int(AffineCompact), Mode!=int(Isometry)), 308 YOU_PERFORMED_AN_INVALID_TRANSFORMATION_CONVERSION) 309 310 enum { ModeIsAffineCompact = Mode == int(AffineCompact), 311 OtherModeIsAffineCompact = OtherMode == int(AffineCompact) 312 }; 313 314 if(ModeIsAffineCompact == OtherModeIsAffineCompact) 315 { 316 // We need the block expression because the code is compiled for all 317 // combinations of transformations and will trigger a compile time error 318 // if one tries to assign the matrices directly 319 m_matrix.template block<Dim,Dim+1>(0,0) = other.matrix().template block<Dim,Dim+1>(0,0); 320 makeAffine(); 321 } 322 else if(OtherModeIsAffineCompact) 323 { 324 typedef typename Transform<Scalar,Dim,OtherMode,OtherOptions>::MatrixType OtherMatrixType; 325 internal::transform_construct_from_matrix<OtherMatrixType,Mode,Options,Dim,HDim>::run(this, other.matrix()); 326 } 327 else 328 { 329 // here we know that Mode == AffineCompact and OtherMode != AffineCompact. 330 // if OtherMode were Projective, the static assert above would already have caught it. 331 // So the only possibility is that OtherMode == Affine 332 linear() = other.linear(); 333 translation() = other.translation(); 334 } 335 } 336 337 template<typename OtherDerived> 338 Transform(const ReturnByValue<OtherDerived>& other) 339 { 340 check_template_params(); 341 other.evalTo(*this); 342 } 343 344 template<typename OtherDerived> 345 Transform& operator=(const ReturnByValue<OtherDerived>& other) 346 { 347 other.evalTo(*this); 348 return *this; 349 } 350 351 #ifdef EIGEN_QT_SUPPORT 352 inline Transform(const QMatrix& other); 353 inline Transform& operator=(const QMatrix& other); 354 inline QMatrix toQMatrix(void) const; 355 inline Transform(const QTransform& other); 356 inline Transform& operator=(const QTransform& other); 357 inline QTransform toQTransform(void) const; 358 #endif 359 360 /** shortcut for m_matrix(row,col); 361 * \sa MatrixBase::operator(Index,Index) const */ 362 inline Scalar operator() (Index row, Index col) const { return m_matrix(row,col); } 363 /** shortcut for m_matrix(row,col); 364 * \sa MatrixBase::operator(Index,Index) */ 365 inline Scalar& operator() (Index row, Index col) { return m_matrix(row,col); } 366 367 /** \returns a read-only expression of the transformation matrix */ 368 inline const MatrixType& matrix() const { return m_matrix; } 369 /** \returns a writable expression of the transformation matrix */ 370 inline MatrixType& matrix() { return m_matrix; } 371 372 /** \returns a read-only expression of the linear part of the transformation */ 373 inline ConstLinearPart linear() const { return ConstLinearPart(m_matrix,0,0); } 374 /** \returns a writable expression of the linear part of the transformation */ 375 inline LinearPart linear() { return LinearPart(m_matrix,0,0); } 376 377 /** \returns a read-only expression of the Dim x HDim affine part of the transformation */ 378 inline ConstAffinePart affine() const { return take_affine_part::run(m_matrix); } 379 /** \returns a writable expression of the Dim x HDim affine part of the transformation */ 380 inline AffinePart affine() { return take_affine_part::run(m_matrix); } 381 382 /** \returns a read-only expression of the translation vector of the transformation */ 383 inline ConstTranslationPart translation() const { return ConstTranslationPart(m_matrix,0,Dim); } 384 /** \returns a writable expression of the translation vector of the transformation */ 385 inline TranslationPart translation() { return TranslationPart(m_matrix,0,Dim); } 386 387 /** \returns an expression of the product between the transform \c *this and a matrix expression \a other 388 * 389 * The right hand side \a other might be either: 390 * \li a vector of size Dim, 391 * \li an homogeneous vector of size Dim+1, 392 * \li a set of vectors of size Dim x Dynamic, 393 * \li a set of homogeneous vectors of size Dim+1 x Dynamic, 394 * \li a linear transformation matrix of size Dim x Dim, 395 * \li an affine transformation matrix of size Dim x Dim+1, 396 * \li a transformation matrix of size Dim+1 x Dim+1. 397 */ 398 // note: this function is defined here because some compilers cannot find the respective declaration 399 template<typename OtherDerived> 400 EIGEN_STRONG_INLINE const typename internal::transform_right_product_impl<Transform, OtherDerived>::ResultType 401 operator * (const EigenBase<OtherDerived> &other) const 402 { return internal::transform_right_product_impl<Transform, OtherDerived>::run(*this,other.derived()); } 403 404 /** \returns the product expression of a transformation matrix \a a times a transform \a b 405 * 406 * The left hand side \a other might be either: 407 * \li a linear transformation matrix of size Dim x Dim, 408 * \li an affine transformation matrix of size Dim x Dim+1, 409 * \li a general transformation matrix of size Dim+1 x Dim+1. 410 */ 411 template<typename OtherDerived> friend 412 inline const typename internal::transform_left_product_impl<OtherDerived,Mode,Options,_Dim,_Dim+1>::ResultType 413 operator * (const EigenBase<OtherDerived> &a, const Transform &b) 414 { return internal::transform_left_product_impl<OtherDerived,Mode,Options,Dim,HDim>::run(a.derived(),b); } 415 416 /** \returns The product expression of a transform \a a times a diagonal matrix \a b 417 * 418 * The rhs diagonal matrix is interpreted as an affine scaling transformation. The 419 * product results in a Transform of the same type (mode) as the lhs only if the lhs 420 * mode is no isometry. In that case, the returned transform is an affinity. 421 */ 422 template<typename DiagonalDerived> 423 inline const TransformTimeDiagonalReturnType 424 operator * (const DiagonalBase<DiagonalDerived> &b) const 425 { 426 TransformTimeDiagonalReturnType res(*this); 427 res.linear() *= b; 428 return res; 429 } 430 431 /** \returns The product expression of a diagonal matrix \a a times a transform \a b 432 * 433 * The lhs diagonal matrix is interpreted as an affine scaling transformation. The 434 * product results in a Transform of the same type (mode) as the lhs only if the lhs 435 * mode is no isometry. In that case, the returned transform is an affinity. 436 */ 437 template<typename DiagonalDerived> 438 friend inline TransformTimeDiagonalReturnType 439 operator * (const DiagonalBase<DiagonalDerived> &a, const Transform &b) 440 { 441 TransformTimeDiagonalReturnType res; 442 res.linear().noalias() = a*b.linear(); 443 res.translation().noalias() = a*b.translation(); 444 if (Mode!=int(AffineCompact)) 445 res.matrix().row(Dim) = b.matrix().row(Dim); 446 return res; 447 } 448 449 template<typename OtherDerived> 450 inline Transform& operator*=(const EigenBase<OtherDerived>& other) { return *this = *this * other; } 451 452 /** Concatenates two transformations */ 453 inline const Transform operator * (const Transform& other) const 454 { 455 return internal::transform_transform_product_impl<Transform,Transform>::run(*this,other); 456 } 457 458 #ifdef __INTEL_COMPILER 459private: 460 // this intermediate structure permits to workaround a bug in ICC 11: 461 // error: template instantiation resulted in unexpected function type of "Eigen::Transform<double, 3, 32, 0> 462 // (const Eigen::Transform<double, 3, 2, 0> &) const" 463 // (the meaning of a name may have changed since the template declaration -- the type of the template is: 464 // "Eigen::internal::transform_transform_product_impl<Eigen::Transform<double, 3, 32, 0>, 465 // Eigen::Transform<double, 3, Mode, Options>, <expression>>::ResultType (const Eigen::Transform<double, 3, Mode, Options> &) const") 466 // 467 template<int OtherMode,int OtherOptions> struct icc_11_workaround 468 { 469 typedef internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> > ProductType; 470 typedef typename ProductType::ResultType ResultType; 471 }; 472 473public: 474 /** Concatenates two different transformations */ 475 template<int OtherMode,int OtherOptions> 476 inline typename icc_11_workaround<OtherMode,OtherOptions>::ResultType 477 operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const 478 { 479 typedef typename icc_11_workaround<OtherMode,OtherOptions>::ProductType ProductType; 480 return ProductType::run(*this,other); 481 } 482 #else 483 /** Concatenates two different transformations */ 484 template<int OtherMode,int OtherOptions> 485 inline typename internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::ResultType 486 operator * (const Transform<Scalar,Dim,OtherMode,OtherOptions>& other) const 487 { 488 return internal::transform_transform_product_impl<Transform,Transform<Scalar,Dim,OtherMode,OtherOptions> >::run(*this,other); 489 } 490 #endif 491 492 /** \sa MatrixBase::setIdentity() */ 493 void setIdentity() { m_matrix.setIdentity(); } 494 495 /** 496 * \brief Returns an identity transformation. 497 * \todo In the future this function should be returning a Transform expression. 498 */ 499 static const Transform Identity() 500 { 501 return Transform(MatrixType::Identity()); 502 } 503 504 template<typename OtherDerived> 505 inline Transform& scale(const MatrixBase<OtherDerived> &other); 506 507 template<typename OtherDerived> 508 inline Transform& prescale(const MatrixBase<OtherDerived> &other); 509 510 inline Transform& scale(const Scalar& s); 511 inline Transform& prescale(const Scalar& s); 512 513 template<typename OtherDerived> 514 inline Transform& translate(const MatrixBase<OtherDerived> &other); 515 516 template<typename OtherDerived> 517 inline Transform& pretranslate(const MatrixBase<OtherDerived> &other); 518 519 template<typename RotationType> 520 inline Transform& rotate(const RotationType& rotation); 521 522 template<typename RotationType> 523 inline Transform& prerotate(const RotationType& rotation); 524 525 Transform& shear(const Scalar& sx, const Scalar& sy); 526 Transform& preshear(const Scalar& sx, const Scalar& sy); 527 528 inline Transform& operator=(const TranslationType& t); 529 inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); } 530 inline Transform operator*(const TranslationType& t) const; 531 532 inline Transform& operator=(const UniformScaling<Scalar>& t); 533 inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); } 534 inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode))> operator*(const UniformScaling<Scalar>& s) const 535 { 536 Transform<Scalar,Dim,(int(Mode)==int(Isometry)?int(Affine):int(Mode)),Options> res = *this; 537 res.scale(s.factor()); 538 return res; 539 } 540 541 inline Transform& operator*=(const DiagonalMatrix<Scalar,Dim>& s) { linear() *= s; return *this; } 542 543 template<typename Derived> 544 inline Transform& operator=(const RotationBase<Derived,Dim>& r); 545 template<typename Derived> 546 inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); } 547 template<typename Derived> 548 inline Transform operator*(const RotationBase<Derived,Dim>& r) const; 549 550 const LinearMatrixType rotation() const; 551 template<typename RotationMatrixType, typename ScalingMatrixType> 552 void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const; 553 template<typename ScalingMatrixType, typename RotationMatrixType> 554 void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const; 555 556 template<typename PositionDerived, typename OrientationType, typename ScaleDerived> 557 Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position, 558 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale); 559 560 inline Transform inverse(TransformTraits traits = (TransformTraits)Mode) const; 561 562 /** \returns a const pointer to the column major internal matrix */ 563 const Scalar* data() const { return m_matrix.data(); } 564 /** \returns a non-const pointer to the column major internal matrix */ 565 Scalar* data() { return m_matrix.data(); } 566 567 /** \returns \c *this with scalar type casted to \a NewScalarType 568 * 569 * Note that if \a NewScalarType is equal to the current scalar type of \c *this 570 * then this function smartly returns a const reference to \c *this. 571 */ 572 template<typename NewScalarType> 573 inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type cast() const 574 { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim,Mode,Options> >::type(*this); } 575 576 /** Copy constructor with scalar type conversion */ 577 template<typename OtherScalarType> 578 inline explicit Transform(const Transform<OtherScalarType,Dim,Mode,Options>& other) 579 { 580 check_template_params(); 581 m_matrix = other.matrix().template cast<Scalar>(); 582 } 583 584 /** \returns \c true if \c *this is approximately equal to \a other, within the precision 585 * determined by \a prec. 586 * 587 * \sa MatrixBase::isApprox() */ 588 bool isApprox(const Transform& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const 589 { return m_matrix.isApprox(other.m_matrix, prec); } 590 591 /** Sets the last row to [0 ... 0 1] 592 */ 593 void makeAffine() 594 { 595 internal::transform_make_affine<int(Mode)>::run(m_matrix); 596 } 597 598 /** \internal 599 * \returns the Dim x Dim linear part if the transformation is affine, 600 * and the HDim x Dim part for projective transformations. 601 */ 602 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() 603 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); } 604 /** \internal 605 * \returns the Dim x Dim linear part if the transformation is affine, 606 * and the HDim x Dim part for projective transformations. 607 */ 608 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,Dim> linearExt() const 609 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,Dim>(0,0); } 610 611 /** \internal 612 * \returns the translation part if the transformation is affine, 613 * and the last column for projective transformations. 614 */ 615 inline Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() 616 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); } 617 /** \internal 618 * \returns the translation part if the transformation is affine, 619 * and the last column for projective transformations. 620 */ 621 inline const Block<MatrixType,int(Mode)==int(Projective)?HDim:Dim,1> translationExt() const 622 { return m_matrix.template block<int(Mode)==int(Projective)?HDim:Dim,1>(0,Dim); } 623 624 625 #ifdef EIGEN_TRANSFORM_PLUGIN 626 #include EIGEN_TRANSFORM_PLUGIN 627 #endif 628 629protected: 630 #ifndef EIGEN_PARSED_BY_DOXYGEN 631 static EIGEN_STRONG_INLINE void check_template_params() 632 { 633 EIGEN_STATIC_ASSERT((Options & (DontAlign|RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS) 634 } 635 #endif 636 637}; 638 639/** \ingroup Geometry_Module */ 640typedef Transform<float,2,Isometry> Isometry2f; 641/** \ingroup Geometry_Module */ 642typedef Transform<float,3,Isometry> Isometry3f; 643/** \ingroup Geometry_Module */ 644typedef Transform<double,2,Isometry> Isometry2d; 645/** \ingroup Geometry_Module */ 646typedef Transform<double,3,Isometry> Isometry3d; 647 648/** \ingroup Geometry_Module */ 649typedef Transform<float,2,Affine> Affine2f; 650/** \ingroup Geometry_Module */ 651typedef Transform<float,3,Affine> Affine3f; 652/** \ingroup Geometry_Module */ 653typedef Transform<double,2,Affine> Affine2d; 654/** \ingroup Geometry_Module */ 655typedef Transform<double,3,Affine> Affine3d; 656 657/** \ingroup Geometry_Module */ 658typedef Transform<float,2,AffineCompact> AffineCompact2f; 659/** \ingroup Geometry_Module */ 660typedef Transform<float,3,AffineCompact> AffineCompact3f; 661/** \ingroup Geometry_Module */ 662typedef Transform<double,2,AffineCompact> AffineCompact2d; 663/** \ingroup Geometry_Module */ 664typedef Transform<double,3,AffineCompact> AffineCompact3d; 665 666/** \ingroup Geometry_Module */ 667typedef Transform<float,2,Projective> Projective2f; 668/** \ingroup Geometry_Module */ 669typedef Transform<float,3,Projective> Projective3f; 670/** \ingroup Geometry_Module */ 671typedef Transform<double,2,Projective> Projective2d; 672/** \ingroup Geometry_Module */ 673typedef Transform<double,3,Projective> Projective3d; 674 675/************************** 676*** Optional QT support *** 677**************************/ 678 679#ifdef EIGEN_QT_SUPPORT 680/** Initializes \c *this from a QMatrix assuming the dimension is 2. 681 * 682 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 683 */ 684template<typename Scalar, int Dim, int Mode,int Options> 685Transform<Scalar,Dim,Mode,Options>::Transform(const QMatrix& other) 686{ 687 check_template_params(); 688 *this = other; 689} 690 691/** Set \c *this from a QMatrix assuming the dimension is 2. 692 * 693 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 694 */ 695template<typename Scalar, int Dim, int Mode,int Options> 696Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QMatrix& other) 697{ 698 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 699 m_matrix << other.m11(), other.m21(), other.dx(), 700 other.m12(), other.m22(), other.dy(), 701 0, 0, 1; 702 return *this; 703} 704 705/** \returns a QMatrix from \c *this assuming the dimension is 2. 706 * 707 * \warning this conversion might loss data if \c *this is not affine 708 * 709 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 710 */ 711template<typename Scalar, int Dim, int Mode, int Options> 712QMatrix Transform<Scalar,Dim,Mode,Options>::toQMatrix(void) const 713{ 714 check_template_params(); 715 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 716 return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0), 717 m_matrix.coeff(0,1), m_matrix.coeff(1,1), 718 m_matrix.coeff(0,2), m_matrix.coeff(1,2)); 719} 720 721/** Initializes \c *this from a QTransform assuming the dimension is 2. 722 * 723 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 724 */ 725template<typename Scalar, int Dim, int Mode,int Options> 726Transform<Scalar,Dim,Mode,Options>::Transform(const QTransform& other) 727{ 728 check_template_params(); 729 *this = other; 730} 731 732/** Set \c *this from a QTransform assuming the dimension is 2. 733 * 734 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 735 */ 736template<typename Scalar, int Dim, int Mode, int Options> 737Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const QTransform& other) 738{ 739 check_template_params(); 740 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 741 if (Mode == int(AffineCompact)) 742 m_matrix << other.m11(), other.m21(), other.dx(), 743 other.m12(), other.m22(), other.dy(); 744 else 745 m_matrix << other.m11(), other.m21(), other.dx(), 746 other.m12(), other.m22(), other.dy(), 747 other.m13(), other.m23(), other.m33(); 748 return *this; 749} 750 751/** \returns a QTransform from \c *this assuming the dimension is 2. 752 * 753 * This function is available only if the token EIGEN_QT_SUPPORT is defined. 754 */ 755template<typename Scalar, int Dim, int Mode, int Options> 756QTransform Transform<Scalar,Dim,Mode,Options>::toQTransform(void) const 757{ 758 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 759 if (Mode == int(AffineCompact)) 760 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), 761 m_matrix.coeff(0,1), m_matrix.coeff(1,1), 762 m_matrix.coeff(0,2), m_matrix.coeff(1,2)); 763 else 764 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0), 765 m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1), 766 m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2)); 767} 768#endif 769 770/********************* 771*** Procedural API *** 772*********************/ 773 774/** Applies on the right the non uniform scale transformation represented 775 * by the vector \a other to \c *this and returns a reference to \c *this. 776 * \sa prescale() 777 */ 778template<typename Scalar, int Dim, int Mode, int Options> 779template<typename OtherDerived> 780Transform<Scalar,Dim,Mode,Options>& 781Transform<Scalar,Dim,Mode,Options>::scale(const MatrixBase<OtherDerived> &other) 782{ 783 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 784 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 785 linearExt().noalias() = (linearExt() * other.asDiagonal()); 786 return *this; 787} 788 789/** Applies on the right a uniform scale of a factor \a c to \c *this 790 * and returns a reference to \c *this. 791 * \sa prescale(Scalar) 792 */ 793template<typename Scalar, int Dim, int Mode, int Options> 794inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::scale(const Scalar& s) 795{ 796 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 797 linearExt() *= s; 798 return *this; 799} 800 801/** Applies on the left the non uniform scale transformation represented 802 * by the vector \a other to \c *this and returns a reference to \c *this. 803 * \sa scale() 804 */ 805template<typename Scalar, int Dim, int Mode, int Options> 806template<typename OtherDerived> 807Transform<Scalar,Dim,Mode,Options>& 808Transform<Scalar,Dim,Mode,Options>::prescale(const MatrixBase<OtherDerived> &other) 809{ 810 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 811 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 812 m_matrix.template block<Dim,HDim>(0,0).noalias() = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)); 813 return *this; 814} 815 816/** Applies on the left a uniform scale of a factor \a c to \c *this 817 * and returns a reference to \c *this. 818 * \sa scale(Scalar) 819 */ 820template<typename Scalar, int Dim, int Mode, int Options> 821inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::prescale(const Scalar& s) 822{ 823 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 824 m_matrix.template topRows<Dim>() *= s; 825 return *this; 826} 827 828/** Applies on the right the translation matrix represented by the vector \a other 829 * to \c *this and returns a reference to \c *this. 830 * \sa pretranslate() 831 */ 832template<typename Scalar, int Dim, int Mode, int Options> 833template<typename OtherDerived> 834Transform<Scalar,Dim,Mode,Options>& 835Transform<Scalar,Dim,Mode,Options>::translate(const MatrixBase<OtherDerived> &other) 836{ 837 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 838 translationExt() += linearExt() * other; 839 return *this; 840} 841 842/** Applies on the left the translation matrix represented by the vector \a other 843 * to \c *this and returns a reference to \c *this. 844 * \sa translate() 845 */ 846template<typename Scalar, int Dim, int Mode, int Options> 847template<typename OtherDerived> 848Transform<Scalar,Dim,Mode,Options>& 849Transform<Scalar,Dim,Mode,Options>::pretranslate(const MatrixBase<OtherDerived> &other) 850{ 851 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim)) 852 if(int(Mode)==int(Projective)) 853 affine() += other * m_matrix.row(Dim); 854 else 855 translation() += other; 856 return *this; 857} 858 859/** Applies on the right the rotation represented by the rotation \a rotation 860 * to \c *this and returns a reference to \c *this. 861 * 862 * The template parameter \a RotationType is the type of the rotation which 863 * must be known by internal::toRotationMatrix<>. 864 * 865 * Natively supported types includes: 866 * - any scalar (2D), 867 * - a Dim x Dim matrix expression, 868 * - a Quaternion (3D), 869 * - a AngleAxis (3D) 870 * 871 * This mechanism is easily extendable to support user types such as Euler angles, 872 * or a pair of Quaternion for 4D rotations. 873 * 874 * \sa rotate(Scalar), class Quaternion, class AngleAxis, prerotate(RotationType) 875 */ 876template<typename Scalar, int Dim, int Mode, int Options> 877template<typename RotationType> 878Transform<Scalar,Dim,Mode,Options>& 879Transform<Scalar,Dim,Mode,Options>::rotate(const RotationType& rotation) 880{ 881 linearExt() *= internal::toRotationMatrix<Scalar,Dim>(rotation); 882 return *this; 883} 884 885/** Applies on the left the rotation represented by the rotation \a rotation 886 * to \c *this and returns a reference to \c *this. 887 * 888 * See rotate() for further details. 889 * 890 * \sa rotate() 891 */ 892template<typename Scalar, int Dim, int Mode, int Options> 893template<typename RotationType> 894Transform<Scalar,Dim,Mode,Options>& 895Transform<Scalar,Dim,Mode,Options>::prerotate(const RotationType& rotation) 896{ 897 m_matrix.template block<Dim,HDim>(0,0) = internal::toRotationMatrix<Scalar,Dim>(rotation) 898 * m_matrix.template block<Dim,HDim>(0,0); 899 return *this; 900} 901 902/** Applies on the right the shear transformation represented 903 * by the vector \a other to \c *this and returns a reference to \c *this. 904 * \warning 2D only. 905 * \sa preshear() 906 */ 907template<typename Scalar, int Dim, int Mode, int Options> 908Transform<Scalar,Dim,Mode,Options>& 909Transform<Scalar,Dim,Mode,Options>::shear(const Scalar& sx, const Scalar& sy) 910{ 911 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 912 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 913 VectorType tmp = linear().col(0)*sy + linear().col(1); 914 linear() << linear().col(0) + linear().col(1)*sx, tmp; 915 return *this; 916} 917 918/** Applies on the left the shear transformation represented 919 * by the vector \a other to \c *this and returns a reference to \c *this. 920 * \warning 2D only. 921 * \sa shear() 922 */ 923template<typename Scalar, int Dim, int Mode, int Options> 924Transform<Scalar,Dim,Mode,Options>& 925Transform<Scalar,Dim,Mode,Options>::preshear(const Scalar& sx, const Scalar& sy) 926{ 927 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE) 928 EIGEN_STATIC_ASSERT(Mode!=int(Isometry), THIS_METHOD_IS_ONLY_FOR_SPECIFIC_TRANSFORMATIONS) 929 m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0); 930 return *this; 931} 932 933/****************************************************** 934*** Scaling, Translation and Rotation compatibility *** 935******************************************************/ 936 937template<typename Scalar, int Dim, int Mode, int Options> 938inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const TranslationType& t) 939{ 940 linear().setIdentity(); 941 translation() = t.vector(); 942 makeAffine(); 943 return *this; 944} 945 946template<typename Scalar, int Dim, int Mode, int Options> 947inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const TranslationType& t) const 948{ 949 Transform res = *this; 950 res.translate(t.vector()); 951 return res; 952} 953 954template<typename Scalar, int Dim, int Mode, int Options> 955inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const UniformScaling<Scalar>& s) 956{ 957 m_matrix.setZero(); 958 linear().diagonal().fill(s.factor()); 959 makeAffine(); 960 return *this; 961} 962 963template<typename Scalar, int Dim, int Mode, int Options> 964template<typename Derived> 965inline Transform<Scalar,Dim,Mode,Options>& Transform<Scalar,Dim,Mode,Options>::operator=(const RotationBase<Derived,Dim>& r) 966{ 967 linear() = internal::toRotationMatrix<Scalar,Dim>(r); 968 translation().setZero(); 969 makeAffine(); 970 return *this; 971} 972 973template<typename Scalar, int Dim, int Mode, int Options> 974template<typename Derived> 975inline Transform<Scalar,Dim,Mode,Options> Transform<Scalar,Dim,Mode,Options>::operator*(const RotationBase<Derived,Dim>& r) const 976{ 977 Transform res = *this; 978 res.rotate(r.derived()); 979 return res; 980} 981 982/************************ 983*** Special functions *** 984************************/ 985 986/** \returns the rotation part of the transformation 987 * 988 * 989 * \svd_module 990 * 991 * \sa computeRotationScaling(), computeScalingRotation(), class SVD 992 */ 993template<typename Scalar, int Dim, int Mode, int Options> 994const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType 995Transform<Scalar,Dim,Mode,Options>::rotation() const 996{ 997 LinearMatrixType result; 998 computeRotationScaling(&result, (LinearMatrixType*)0); 999 return result; 1000} 1001 1002 1003/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being 1004 * not necessarily positive. 1005 * 1006 * If either pointer is zero, the corresponding computation is skipped. 1007 * 1008 * 1009 * 1010 * \svd_module 1011 * 1012 * \sa computeScalingRotation(), rotation(), class SVD 1013 */ 1014template<typename Scalar, int Dim, int Mode, int Options> 1015template<typename RotationMatrixType, typename ScalingMatrixType> 1016void Transform<Scalar,Dim,Mode,Options>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const 1017{ 1018 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV); 1019 1020 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1 1021 VectorType sv(svd.singularValues()); 1022 sv.coeffRef(0) *= x; 1023 if(scaling) scaling->lazyAssign(svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint()); 1024 if(rotation) 1025 { 1026 LinearMatrixType m(svd.matrixU()); 1027 m.col(0) /= x; 1028 rotation->lazyAssign(m * svd.matrixV().adjoint()); 1029 } 1030} 1031 1032/** decomposes the linear part of the transformation as a product rotation x scaling, the scaling being 1033 * not necessarily positive. 1034 * 1035 * If either pointer is zero, the corresponding computation is skipped. 1036 * 1037 * 1038 * 1039 * \svd_module 1040 * 1041 * \sa computeRotationScaling(), rotation(), class SVD 1042 */ 1043template<typename Scalar, int Dim, int Mode, int Options> 1044template<typename ScalingMatrixType, typename RotationMatrixType> 1045void Transform<Scalar,Dim,Mode,Options>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const 1046{ 1047 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU | ComputeFullV); 1048 1049 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1 1050 VectorType sv(svd.singularValues()); 1051 sv.coeffRef(0) *= x; 1052 if(scaling) scaling->lazyAssign(svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint()); 1053 if(rotation) 1054 { 1055 LinearMatrixType m(svd.matrixU()); 1056 m.col(0) /= x; 1057 rotation->lazyAssign(m * svd.matrixV().adjoint()); 1058 } 1059} 1060 1061/** Convenient method to set \c *this from a position, orientation and scale 1062 * of a 3D object. 1063 */ 1064template<typename Scalar, int Dim, int Mode, int Options> 1065template<typename PositionDerived, typename OrientationType, typename ScaleDerived> 1066Transform<Scalar,Dim,Mode,Options>& 1067Transform<Scalar,Dim,Mode,Options>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position, 1068 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale) 1069{ 1070 linear() = internal::toRotationMatrix<Scalar,Dim>(orientation); 1071 linear() *= scale.asDiagonal(); 1072 translation() = position; 1073 makeAffine(); 1074 return *this; 1075} 1076 1077namespace internal { 1078 1079template<int Mode> 1080struct transform_make_affine 1081{ 1082 template<typename MatrixType> 1083 static void run(MatrixType &mat) 1084 { 1085 static const int Dim = MatrixType::ColsAtCompileTime-1; 1086 mat.template block<1,Dim>(Dim,0).setZero(); 1087 mat.coeffRef(Dim,Dim) = typename MatrixType::Scalar(1); 1088 } 1089}; 1090 1091template<> 1092struct transform_make_affine<AffineCompact> 1093{ 1094 template<typename MatrixType> static void run(MatrixType &) { } 1095}; 1096 1097// selector needed to avoid taking the inverse of a 3x4 matrix 1098template<typename TransformType, int Mode=TransformType::Mode> 1099struct projective_transform_inverse 1100{ 1101 static inline void run(const TransformType&, TransformType&) 1102 {} 1103}; 1104 1105template<typename TransformType> 1106struct projective_transform_inverse<TransformType, Projective> 1107{ 1108 static inline void run(const TransformType& m, TransformType& res) 1109 { 1110 res.matrix() = m.matrix().inverse(); 1111 } 1112}; 1113 1114} // end namespace internal 1115 1116 1117/** 1118 * 1119 * \returns the inverse transformation according to some given knowledge 1120 * on \c *this. 1121 * 1122 * \param hint allows to optimize the inversion process when the transformation 1123 * is known to be not a general transformation (optional). The possible values are: 1124 * - #Projective if the transformation is not necessarily affine, i.e., if the 1125 * last row is not guaranteed to be [0 ... 0 1] 1126 * - #Affine if the last row can be assumed to be [0 ... 0 1] 1127 * - #Isometry if the transformation is only a concatenations of translations 1128 * and rotations. 1129 * The default is the template class parameter \c Mode. 1130 * 1131 * \warning unless \a traits is always set to NoShear or NoScaling, this function 1132 * requires the generic inverse method of MatrixBase defined in the LU module. If 1133 * you forget to include this module, then you will get hard to debug linking errors. 1134 * 1135 * \sa MatrixBase::inverse() 1136 */ 1137template<typename Scalar, int Dim, int Mode, int Options> 1138Transform<Scalar,Dim,Mode,Options> 1139Transform<Scalar,Dim,Mode,Options>::inverse(TransformTraits hint) const 1140{ 1141 Transform res; 1142 if (hint == Projective) 1143 { 1144 internal::projective_transform_inverse<Transform>::run(*this, res); 1145 } 1146 else 1147 { 1148 if (hint == Isometry) 1149 { 1150 res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose(); 1151 } 1152 else if(hint&Affine) 1153 { 1154 res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse(); 1155 } 1156 else 1157 { 1158 eigen_assert(false && "Invalid transform traits in Transform::Inverse"); 1159 } 1160 // translation and remaining parts 1161 res.matrix().template topRightCorner<Dim,1>() 1162 = - res.matrix().template topLeftCorner<Dim,Dim>() * translation(); 1163 res.makeAffine(); // we do need this, because in the beginning res is uninitialized 1164 } 1165 return res; 1166} 1167 1168namespace internal { 1169 1170/***************************************************** 1171*** Specializations of take affine part *** 1172*****************************************************/ 1173 1174template<typename TransformType> struct transform_take_affine_part { 1175 typedef typename TransformType::MatrixType MatrixType; 1176 typedef typename TransformType::AffinePart AffinePart; 1177 typedef typename TransformType::ConstAffinePart ConstAffinePart; 1178 static inline AffinePart run(MatrixType& m) 1179 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); } 1180 static inline ConstAffinePart run(const MatrixType& m) 1181 { return m.template block<TransformType::Dim,TransformType::HDim>(0,0); } 1182}; 1183 1184template<typename Scalar, int Dim, int Options> 1185struct transform_take_affine_part<Transform<Scalar,Dim,AffineCompact, Options> > { 1186 typedef typename Transform<Scalar,Dim,AffineCompact,Options>::MatrixType MatrixType; 1187 static inline MatrixType& run(MatrixType& m) { return m; } 1188 static inline const MatrixType& run(const MatrixType& m) { return m; } 1189}; 1190 1191/***************************************************** 1192*** Specializations of construct from matrix *** 1193*****************************************************/ 1194 1195template<typename Other, int Mode, int Options, int Dim, int HDim> 1196struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,Dim> 1197{ 1198 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 1199 { 1200 transform->linear() = other; 1201 transform->translation().setZero(); 1202 transform->makeAffine(); 1203 } 1204}; 1205 1206template<typename Other, int Mode, int Options, int Dim, int HDim> 1207struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, Dim,HDim> 1208{ 1209 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 1210 { 1211 transform->affine() = other; 1212 transform->makeAffine(); 1213 } 1214}; 1215 1216template<typename Other, int Mode, int Options, int Dim, int HDim> 1217struct transform_construct_from_matrix<Other, Mode,Options,Dim,HDim, HDim,HDim> 1218{ 1219 static inline void run(Transform<typename Other::Scalar,Dim,Mode,Options> *transform, const Other& other) 1220 { transform->matrix() = other; } 1221}; 1222 1223template<typename Other, int Options, int Dim, int HDim> 1224struct transform_construct_from_matrix<Other, AffineCompact,Options,Dim,HDim, HDim,HDim> 1225{ 1226 static inline void run(Transform<typename Other::Scalar,Dim,AffineCompact,Options> *transform, const Other& other) 1227 { transform->matrix() = other.template block<Dim,HDim>(0,0); } 1228}; 1229 1230/********************************************************** 1231*** Specializations of operator* with rhs EigenBase *** 1232**********************************************************/ 1233 1234template<int LhsMode,int RhsMode> 1235struct transform_product_result 1236{ 1237 enum 1238 { 1239 Mode = 1240 (LhsMode == (int)Projective || RhsMode == (int)Projective ) ? Projective : 1241 (LhsMode == (int)Affine || RhsMode == (int)Affine ) ? Affine : 1242 (LhsMode == (int)AffineCompact || RhsMode == (int)AffineCompact ) ? AffineCompact : 1243 (LhsMode == (int)Isometry || RhsMode == (int)Isometry ) ? Isometry : Projective 1244 }; 1245}; 1246 1247template< typename TransformType, typename MatrixType > 1248struct transform_right_product_impl< TransformType, MatrixType, 0 > 1249{ 1250 typedef typename MatrixType::PlainObject ResultType; 1251 1252 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 1253 { 1254 return T.matrix() * other; 1255 } 1256}; 1257 1258template< typename TransformType, typename MatrixType > 1259struct transform_right_product_impl< TransformType, MatrixType, 1 > 1260{ 1261 enum { 1262 Dim = TransformType::Dim, 1263 HDim = TransformType::HDim, 1264 OtherRows = MatrixType::RowsAtCompileTime, 1265 OtherCols = MatrixType::ColsAtCompileTime 1266 }; 1267 1268 typedef typename MatrixType::PlainObject ResultType; 1269 1270 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 1271 { 1272 EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); 1273 1274 typedef Block<ResultType, Dim, OtherCols, int(MatrixType::RowsAtCompileTime)==Dim> TopLeftLhs; 1275 1276 ResultType res(other.rows(),other.cols()); 1277 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other; 1278 res.row(OtherRows-1) = other.row(OtherRows-1); 1279 1280 return res; 1281 } 1282}; 1283 1284template< typename TransformType, typename MatrixType > 1285struct transform_right_product_impl< TransformType, MatrixType, 2 > 1286{ 1287 enum { 1288 Dim = TransformType::Dim, 1289 HDim = TransformType::HDim, 1290 OtherRows = MatrixType::RowsAtCompileTime, 1291 OtherCols = MatrixType::ColsAtCompileTime 1292 }; 1293 1294 typedef typename MatrixType::PlainObject ResultType; 1295 1296 static EIGEN_STRONG_INLINE ResultType run(const TransformType& T, const MatrixType& other) 1297 { 1298 EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); 1299 1300 typedef Block<ResultType, Dim, OtherCols, true> TopLeftLhs; 1301 ResultType res(Replicate<typename TransformType::ConstTranslationPart, 1, OtherCols>(T.translation(),1,other.cols())); 1302 TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other; 1303 1304 return res; 1305 } 1306}; 1307 1308/********************************************************** 1309*** Specializations of operator* with lhs EigenBase *** 1310**********************************************************/ 1311 1312// generic HDim x HDim matrix * T => Projective 1313template<typename Other,int Mode, int Options, int Dim, int HDim> 1314struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, HDim,HDim> 1315{ 1316 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 1317 typedef typename TransformType::MatrixType MatrixType; 1318 typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType; 1319 static ResultType run(const Other& other,const TransformType& tr) 1320 { return ResultType(other * tr.matrix()); } 1321}; 1322 1323// generic HDim x HDim matrix * AffineCompact => Projective 1324template<typename Other, int Options, int Dim, int HDim> 1325struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, HDim,HDim> 1326{ 1327 typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType; 1328 typedef typename TransformType::MatrixType MatrixType; 1329 typedef Transform<typename Other::Scalar,Dim,Projective,Options> ResultType; 1330 static ResultType run(const Other& other,const TransformType& tr) 1331 { 1332 ResultType res; 1333 res.matrix().noalias() = other.template block<HDim,Dim>(0,0) * tr.matrix(); 1334 res.matrix().col(Dim) += other.col(Dim); 1335 return res; 1336 } 1337}; 1338 1339// affine matrix * T 1340template<typename Other,int Mode, int Options, int Dim, int HDim> 1341struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,HDim> 1342{ 1343 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 1344 typedef typename TransformType::MatrixType MatrixType; 1345 typedef TransformType ResultType; 1346 static ResultType run(const Other& other,const TransformType& tr) 1347 { 1348 ResultType res; 1349 res.affine().noalias() = other * tr.matrix(); 1350 res.matrix().row(Dim) = tr.matrix().row(Dim); 1351 return res; 1352 } 1353}; 1354 1355// affine matrix * AffineCompact 1356template<typename Other, int Options, int Dim, int HDim> 1357struct transform_left_product_impl<Other,AffineCompact,Options,Dim,HDim, Dim,HDim> 1358{ 1359 typedef Transform<typename Other::Scalar,Dim,AffineCompact,Options> TransformType; 1360 typedef typename TransformType::MatrixType MatrixType; 1361 typedef TransformType ResultType; 1362 static ResultType run(const Other& other,const TransformType& tr) 1363 { 1364 ResultType res; 1365 res.matrix().noalias() = other.template block<Dim,Dim>(0,0) * tr.matrix(); 1366 res.translation() += other.col(Dim); 1367 return res; 1368 } 1369}; 1370 1371// linear matrix * T 1372template<typename Other,int Mode, int Options, int Dim, int HDim> 1373struct transform_left_product_impl<Other,Mode,Options,Dim,HDim, Dim,Dim> 1374{ 1375 typedef Transform<typename Other::Scalar,Dim,Mode,Options> TransformType; 1376 typedef typename TransformType::MatrixType MatrixType; 1377 typedef TransformType ResultType; 1378 static ResultType run(const Other& other, const TransformType& tr) 1379 { 1380 TransformType res; 1381 if(Mode!=int(AffineCompact)) 1382 res.matrix().row(Dim) = tr.matrix().row(Dim); 1383 res.matrix().template topRows<Dim>().noalias() 1384 = other * tr.matrix().template topRows<Dim>(); 1385 return res; 1386 } 1387}; 1388 1389/********************************************************** 1390*** Specializations of operator* with another Transform *** 1391**********************************************************/ 1392 1393template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 1394struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,false > 1395{ 1396 enum { ResultMode = transform_product_result<LhsMode,RhsMode>::Mode }; 1397 typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs; 1398 typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs; 1399 typedef Transform<Scalar,Dim,ResultMode,LhsOptions> ResultType; 1400 static ResultType run(const Lhs& lhs, const Rhs& rhs) 1401 { 1402 ResultType res; 1403 res.linear() = lhs.linear() * rhs.linear(); 1404 res.translation() = lhs.linear() * rhs.translation() + lhs.translation(); 1405 res.makeAffine(); 1406 return res; 1407 } 1408}; 1409 1410template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 1411struct transform_transform_product_impl<Transform<Scalar,Dim,LhsMode,LhsOptions>,Transform<Scalar,Dim,RhsMode,RhsOptions>,true > 1412{ 1413 typedef Transform<Scalar,Dim,LhsMode,LhsOptions> Lhs; 1414 typedef Transform<Scalar,Dim,RhsMode,RhsOptions> Rhs; 1415 typedef Transform<Scalar,Dim,Projective> ResultType; 1416 static ResultType run(const Lhs& lhs, const Rhs& rhs) 1417 { 1418 return ResultType( lhs.matrix() * rhs.matrix() ); 1419 } 1420}; 1421 1422template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 1423struct transform_transform_product_impl<Transform<Scalar,Dim,AffineCompact,LhsOptions>,Transform<Scalar,Dim,Projective,RhsOptions>,true > 1424{ 1425 typedef Transform<Scalar,Dim,AffineCompact,LhsOptions> Lhs; 1426 typedef Transform<Scalar,Dim,Projective,RhsOptions> Rhs; 1427 typedef Transform<Scalar,Dim,Projective> ResultType; 1428 static ResultType run(const Lhs& lhs, const Rhs& rhs) 1429 { 1430 ResultType res; 1431 res.matrix().template topRows<Dim>() = lhs.matrix() * rhs.matrix(); 1432 res.matrix().row(Dim) = rhs.matrix().row(Dim); 1433 return res; 1434 } 1435}; 1436 1437template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 1438struct transform_transform_product_impl<Transform<Scalar,Dim,Projective,LhsOptions>,Transform<Scalar,Dim,AffineCompact,RhsOptions>,true > 1439{ 1440 typedef Transform<Scalar,Dim,Projective,LhsOptions> Lhs; 1441 typedef Transform<Scalar,Dim,AffineCompact,RhsOptions> Rhs; 1442 typedef Transform<Scalar,Dim,Projective> ResultType; 1443 static ResultType run(const Lhs& lhs, const Rhs& rhs) 1444 { 1445 ResultType res(lhs.matrix().template leftCols<Dim>() * rhs.matrix()); 1446 res.matrix().col(Dim) += lhs.matrix().col(Dim); 1447 return res; 1448 } 1449}; 1450 1451} // end namespace internal 1452 1453} // end namespace Eigen 1454 1455#endif // EIGEN_TRANSFORM_H 1456