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 15 namespace Eigen { 16 17 namespace internal { 18 19 template<typename Transform> 20 struct 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 31 template< 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> 37 struct transform_right_product_impl; 38 39 template< typename Other, 40 int Mode, 41 int Options, 42 int Dim, 43 int HDim, 44 int OtherRows=Other::RowsAtCompileTime, 45 int OtherCols=Other::ColsAtCompileTime> 46 struct transform_left_product_impl; 47 48 template< typename Lhs, 49 typename Rhs, 50 bool AnyProjective = 51 transform_traits<Lhs>::IsProjective || 52 transform_traits<Rhs>::IsProjective> 53 struct transform_transform_product_impl; 54 55 template< typename Other, 56 int Mode, 57 int Options, 58 int Dim, 59 int HDim, 60 int OtherRows=Other::RowsAtCompileTime, 61 int OtherCols=Other::ColsAtCompileTime> 62 struct transform_construct_from_matrix; 63 64 template<typename TransformType> struct transform_take_affine_part; 65 66 template<typename _Scalar, int _Dim, int _Mode, int _Options> 67 struct 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 82 template<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 */ 200 template<typename _Scalar, int _Dim, int _Mode, int _Options> 201 class Transform 202 { 203 public: 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 248 protected: 249 250 MatrixType m_matrix; 251 252 public: 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 499 private: 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 513 public: 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 688 protected: 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 */ 699 typedef Transform<float,2,Isometry> Isometry2f; 700 /** \ingroup Geometry_Module */ 701 typedef Transform<float,3,Isometry> Isometry3f; 702 /** \ingroup Geometry_Module */ 703 typedef Transform<double,2,Isometry> Isometry2d; 704 /** \ingroup Geometry_Module */ 705 typedef Transform<double,3,Isometry> Isometry3d; 706 707 /** \ingroup Geometry_Module */ 708 typedef Transform<float,2,Affine> Affine2f; 709 /** \ingroup Geometry_Module */ 710 typedef Transform<float,3,Affine> Affine3f; 711 /** \ingroup Geometry_Module */ 712 typedef Transform<double,2,Affine> Affine2d; 713 /** \ingroup Geometry_Module */ 714 typedef Transform<double,3,Affine> Affine3d; 715 716 /** \ingroup Geometry_Module */ 717 typedef Transform<float,2,AffineCompact> AffineCompact2f; 718 /** \ingroup Geometry_Module */ 719 typedef Transform<float,3,AffineCompact> AffineCompact3f; 720 /** \ingroup Geometry_Module */ 721 typedef Transform<double,2,AffineCompact> AffineCompact2d; 722 /** \ingroup Geometry_Module */ 723 typedef Transform<double,3,AffineCompact> AffineCompact3d; 724 725 /** \ingroup Geometry_Module */ 726 typedef Transform<float,2,Projective> Projective2f; 727 /** \ingroup Geometry_Module */ 728 typedef Transform<float,3,Projective> Projective3f; 729 /** \ingroup Geometry_Module */ 730 typedef Transform<double,2,Projective> Projective2d; 731 /** \ingroup Geometry_Module */ 732 typedef 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 */ 743 template<typename Scalar, int Dim, int Mode,int Options> 744 Transform<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 */ 754 template<typename Scalar, int Dim, int Mode,int Options> 755 Transform<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 */ 774 template<typename Scalar, int Dim, int Mode, int Options> 775 QMatrix 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 */ 788 template<typename Scalar, int Dim, int Mode,int Options> 789 Transform<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 */ 799 template<typename Scalar, int Dim, int Mode, int Options> 800 Transform<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 */ 818 template<typename Scalar, int Dim, int Mode, int Options> 819 QTransform 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 */ 841 template<typename Scalar, int Dim, int Mode, int Options> 842 template<typename OtherDerived> 843 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 844 Transform<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 */ 856 template<typename Scalar, int Dim, int Mode, int Options> 857 EIGEN_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 */ 868 template<typename Scalar, int Dim, int Mode, int Options> 869 template<typename OtherDerived> 870 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 871 Transform<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 */ 883 template<typename Scalar, int Dim, int Mode, int Options> 884 EIGEN_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 */ 895 template<typename Scalar, int Dim, int Mode, int Options> 896 template<typename OtherDerived> 897 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 898 Transform<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 */ 909 template<typename Scalar, int Dim, int Mode, int Options> 910 template<typename OtherDerived> 911 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 912 Transform<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 */ 939 template<typename Scalar, int Dim, int Mode, int Options> 940 template<typename RotationType> 941 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 942 Transform<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 */ 955 template<typename Scalar, int Dim, int Mode, int Options> 956 template<typename RotationType> 957 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 958 Transform<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 */ 970 template<typename Scalar, int Dim, int Mode, int Options> 971 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 972 Transform<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 */ 986 template<typename Scalar, int Dim, int Mode, int Options> 987 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 988 Transform<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 1000 template<typename Scalar, int Dim, int Mode, int Options> 1001 EIGEN_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 1009 template<typename Scalar, int Dim, int Mode, int Options> 1010 EIGEN_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 1017 template<typename Scalar, int Dim, int Mode, int Options> 1018 EIGEN_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 1026 template<typename Scalar, int Dim, int Mode, int Options> 1027 template<typename Derived> 1028 EIGEN_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 1036 template<typename Scalar, int Dim, int Mode, int Options> 1037 template<typename Derived> 1038 EIGEN_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 */ 1056 template<typename Scalar, int Dim, int Mode, int Options> 1057 EIGEN_DEVICE_FUNC const typename Transform<Scalar,Dim,Mode,Options>::LinearMatrixType 1058 Transform<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 */ 1077 template<typename Scalar, int Dim, int Mode, int Options> 1078 template<typename RotationMatrixType, typename ScalingMatrixType> 1079 EIGEN_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 */ 1106 template<typename Scalar, int Dim, int Mode, int Options> 1107 template<typename ScalingMatrixType, typename RotationMatrixType> 1108 EIGEN_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 */ 1127 template<typename Scalar, int Dim, int Mode, int Options> 1128 template<typename PositionDerived, typename OrientationType, typename ScaleDerived> 1129 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options>& 1130 Transform<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 1140 namespace internal { 1141 1142 template<int Mode> 1143 struct 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 1154 template<> 1155 struct 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 1161 template<typename TransformType, int Mode=TransformType::Mode> 1162 struct projective_transform_inverse 1163 { 1164 EIGEN_DEVICE_FUNC static inline void run(const TransformType&, TransformType&) 1165 {} 1166 }; 1167 1168 template<typename TransformType> 1169 struct 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 */ 1200 template<typename Scalar, int Dim, int Mode, int Options> 1201 EIGEN_DEVICE_FUNC Transform<Scalar,Dim,Mode,Options> 1202 Transform<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 1231 namespace internal { 1232 1233 /***************************************************** 1234 *** Specializations of take affine part *** 1235 *****************************************************/ 1236 1237 template<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 1247 template<typename Scalar, int Dim, int Options> 1248 struct 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 1258 template<typename Other, int Mode, int Options, int Dim, int HDim> 1259 struct 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 1269 template<typename Other, int Mode, int Options, int Dim, int HDim> 1270 struct 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 1279 template<typename Other, int Mode, int Options, int Dim, int HDim> 1280 struct 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 1286 template<typename Other, int Options, int Dim, int HDim> 1287 struct 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 1297 template<int LhsMode,int RhsMode> 1298 struct 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 1310 template< typename TransformType, typename MatrixType, int RhsCols> 1311 struct 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 1321 template< typename TransformType, typename MatrixType, int RhsCols> 1322 struct 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 1347 template< typename TransformType, typename MatrixType, int RhsCols> 1348 struct 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 1371 template< typename TransformType, typename MatrixType > 1372 struct 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 1400 template<typename Other,int Mode, int Options, int Dim, int HDim> 1401 struct 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 1411 template<typename Other, int Options, int Dim, int HDim> 1412 struct 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 1427 template<typename Other,int Mode, int Options, int Dim, int HDim> 1428 struct 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 1443 template<typename Other, int Options, int Dim, int HDim> 1444 struct 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 1459 template<typename Other,int Mode, int Options, int Dim, int HDim> 1460 struct 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 1480 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 1481 struct 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 1497 template<typename Scalar, int Dim, int LhsMode, int LhsOptions, int RhsMode, int RhsOptions> 1498 struct 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 1509 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 1510 struct 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 1524 template<typename Scalar, int Dim, int LhsOptions, int RhsOptions> 1525 struct 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