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