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