00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef EIGEN_TRANSFORM_H
00027 #define EIGEN_TRANSFORM_H
00028
00030 enum TransformTraits {
00031 Isometry,
00032 Affine,
00033 Projective
00034 };
00035
00036
00037
00038
00039 template< typename Other,
00040 int Dim,
00041 int HDim,
00042 int OtherRows=Other::RowsAtCompileTime,
00043 int OtherCols=Other::ColsAtCompileTime>
00044 struct ei_transform_product_impl;
00045
00063 template<typename _Scalar, int _Dim>
00064 class Transform
00065 {
00066 public:
00067 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00068 enum {
00069 Dim = _Dim,
00070 HDim = _Dim+1
00071 };
00073 typedef _Scalar Scalar;
00075 typedef Matrix<Scalar,HDim,HDim> MatrixType;
00077 typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
00079 typedef Block<MatrixType,Dim,Dim> LinearPart;
00081 typedef Matrix<Scalar,Dim,1> VectorType;
00083 typedef Block<MatrixType,Dim,1> TranslationPart;
00085 typedef Translation<Scalar,Dim> TranslationType;
00087 typedef Scaling<Scalar,Dim> ScalingType;
00088
00089 protected:
00090
00091 MatrixType m_matrix;
00092
00093 public:
00094
00096 inline Transform() { }
00097
00098 inline Transform(const Transform& other)
00099 {
00100 m_matrix = other.m_matrix;
00101 }
00102
00103 inline explicit Transform(const TranslationType& t) { *this = t; }
00104 inline explicit Transform(const ScalingType& s) { *this = s; }
00105 template<typename Derived>
00106 inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
00107
00108 inline Transform& operator=(const Transform& other)
00109 { m_matrix = other.m_matrix; return *this; }
00110
00111 template<typename OtherDerived, bool BigMatrix>
00112 struct construct_from_matrix
00113 {
00114 static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
00115 {
00116 transform->matrix() = other;
00117 }
00118 };
00119
00120 template<typename OtherDerived> struct construct_from_matrix<OtherDerived, true>
00121 {
00122 static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
00123 {
00124 transform->linear() = other;
00125 transform->translation().setZero();
00126 transform->matrix()(Dim,Dim) = Scalar(1);
00127 transform->matrix().template block<1,Dim>(Dim,0).setZero();
00128 }
00129 };
00130
00132 template<typename OtherDerived>
00133 inline explicit Transform(const MatrixBase<OtherDerived>& other)
00134 {
00135 construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
00136 }
00137
00139 template<typename OtherDerived>
00140 inline Transform& operator=(const MatrixBase<OtherDerived>& other)
00141 { m_matrix = other; return *this; }
00142
00143 #ifdef EIGEN_QT_SUPPORT
00144 inline Transform(const QMatrix& other);
00145 inline Transform& operator=(const QMatrix& other);
00146 inline QMatrix toQMatrix(void) const;
00147 inline Transform(const QTransform& other);
00148 inline Transform& operator=(const QTransform& other);
00149 inline QTransform toQTransform(void) const;
00150 #endif
00151
00154 inline Scalar operator() (int row, int col) const { return m_matrix(row,col); }
00157 inline Scalar& operator() (int row, int col) { return m_matrix(row,col); }
00158
00160 inline const MatrixType& matrix() const { return m_matrix; }
00162 inline MatrixType& matrix() { return m_matrix; }
00163
00165 inline const LinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
00167 inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
00168
00170 inline const TranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
00172 inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
00173
00181
00182 template<typename OtherDerived>
00183 inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
00184 operator * (const MatrixBase<OtherDerived> &other) const
00185 { return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
00186
00189 template<typename OtherDerived>
00190 friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
00191 operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
00192 { return a.derived() * b.matrix(); }
00193
00195 inline const Transform
00196 operator * (const Transform& other) const
00197 { return Transform(m_matrix * other.matrix()); }
00198
00200 void setIdentity() { m_matrix.setIdentity(); }
00201 static const typename MatrixType::IdentityReturnType Identity()
00202 {
00203 return MatrixType::Identity();
00204 }
00205
00206 template<typename OtherDerived>
00207 inline Transform& scale(const MatrixBase<OtherDerived> &other);
00208
00209 template<typename OtherDerived>
00210 inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00211
00212 inline Transform& scale(Scalar s);
00213 inline Transform& prescale(Scalar s);
00214
00215 template<typename OtherDerived>
00216 inline Transform& translate(const MatrixBase<OtherDerived> &other);
00217
00218 template<typename OtherDerived>
00219 inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00220
00221 template<typename RotationType>
00222 inline Transform& rotate(const RotationType& rotation);
00223
00224 template<typename RotationType>
00225 inline Transform& prerotate(const RotationType& rotation);
00226
00227 Transform& shear(Scalar sx, Scalar sy);
00228 Transform& preshear(Scalar sx, Scalar sy);
00229
00230 inline Transform& operator=(const TranslationType& t);
00231 inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00232 inline Transform operator*(const TranslationType& t) const;
00233
00234 inline Transform& operator=(const ScalingType& t);
00235 inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); }
00236 inline Transform operator*(const ScalingType& s) const;
00237 friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
00238 {
00239 Transform res = t;
00240 res.matrix().row(Dim) = t.matrix().row(Dim);
00241 res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
00242 return res;
00243 }
00244
00245 template<typename Derived>
00246 inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00247 template<typename Derived>
00248 inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00249 template<typename Derived>
00250 inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00251
00252 LinearMatrixType rotation() const;
00253 template<typename RotationMatrixType, typename ScalingMatrixType>
00254 void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00255 template<typename ScalingMatrixType, typename RotationMatrixType>
00256 void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00257
00258 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00259 Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00260 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00261
00262 inline const MatrixType inverse(TransformTraits traits = Affine) const;
00263
00265 const Scalar* data() const { return m_matrix.data(); }
00267 Scalar* data() { return m_matrix.data(); }
00268
00274 template<typename NewScalarType>
00275 inline typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
00276 { return typename ei_cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
00277
00279 template<typename OtherScalarType>
00280 inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
00281 { m_matrix = other.matrix().template cast<Scalar>(); }
00282
00287 bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
00288 { return m_matrix.isApprox(other.m_matrix, prec); }
00289
00290 #ifdef EIGEN_TRANSFORM_PLUGIN
00291 #include EIGEN_TRANSFORM_PLUGIN
00292 #endif
00293
00294 protected:
00295
00296 };
00297
00299 typedef Transform<float,2> Transform2f;
00301 typedef Transform<float,3> Transform3f;
00303 typedef Transform<double,2> Transform2d;
00305 typedef Transform<double,3> Transform3d;
00306
00307
00308
00309
00310
00311 #ifdef EIGEN_QT_SUPPORT
00312
00316 template<typename Scalar, int Dim>
00317 Transform<Scalar,Dim>::Transform(const QMatrix& other)
00318 {
00319 *this = other;
00320 }
00321
00326 template<typename Scalar, int Dim>
00327 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
00328 {
00329 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00330 m_matrix << other.m11(), other.m21(), other.dx(),
00331 other.m12(), other.m22(), other.dy(),
00332 0, 0, 1;
00333 return *this;
00334 }
00335
00342 template<typename Scalar, int Dim>
00343 QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
00344 {
00345 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00346 return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00347 m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00348 m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00349 }
00350
00355 template<typename Scalar, int Dim>
00356 Transform<Scalar,Dim>::Transform(const QTransform& other)
00357 {
00358 *this = other;
00359 }
00360
00365 template<typename Scalar, int Dim>
00366 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
00367 {
00368 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00369 m_matrix << other.m11(), other.m21(), other.dx(),
00370 other.m12(), other.m22(), other.dy(),
00371 other.m13(), other.m23(), other.m33();
00372 return *this;
00373 }
00374
00379 template<typename Scalar, int Dim>
00380 QTransform Transform<Scalar,Dim>::toQTransform(void) const
00381 {
00382 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00383 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00384 m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00385 m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00386 }
00387 #endif
00388
00389
00390
00391
00392
00397 template<typename Scalar, int Dim>
00398 template<typename OtherDerived>
00399 Transform<Scalar,Dim>&
00400 Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
00401 {
00402 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00403 linear() = (linear() * other.asDiagonal()).lazy();
00404 return *this;
00405 }
00406
00411 template<typename Scalar, int Dim>
00412 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::scale(Scalar s)
00413 {
00414 linear() *= s;
00415 return *this;
00416 }
00417
00422 template<typename Scalar, int Dim>
00423 template<typename OtherDerived>
00424 Transform<Scalar,Dim>&
00425 Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
00426 {
00427 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00428 m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
00429 return *this;
00430 }
00431
00436 template<typename Scalar, int Dim>
00437 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::prescale(Scalar s)
00438 {
00439 m_matrix.template corner<Dim,HDim>(TopLeft) *= s;
00440 return *this;
00441 }
00442
00447 template<typename Scalar, int Dim>
00448 template<typename OtherDerived>
00449 Transform<Scalar,Dim>&
00450 Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
00451 {
00452 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00453 translation() += linear() * other;
00454 return *this;
00455 }
00456
00461 template<typename Scalar, int Dim>
00462 template<typename OtherDerived>
00463 Transform<Scalar,Dim>&
00464 Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
00465 {
00466 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00467 translation() += other;
00468 return *this;
00469 }
00470
00488 template<typename Scalar, int Dim>
00489 template<typename RotationType>
00490 Transform<Scalar,Dim>&
00491 Transform<Scalar,Dim>::rotate(const RotationType& rotation)
00492 {
00493 linear() *= ei_toRotationMatrix<Scalar,Dim>(rotation);
00494 return *this;
00495 }
00496
00504 template<typename Scalar, int Dim>
00505 template<typename RotationType>
00506 Transform<Scalar,Dim>&
00507 Transform<Scalar,Dim>::prerotate(const RotationType& rotation)
00508 {
00509 m_matrix.template block<Dim,HDim>(0,0) = ei_toRotationMatrix<Scalar,Dim>(rotation)
00510 * m_matrix.template block<Dim,HDim>(0,0);
00511 return *this;
00512 }
00513
00519 template<typename Scalar, int Dim>
00520 Transform<Scalar,Dim>&
00521 Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
00522 {
00523 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00524 VectorType tmp = linear().col(0)*sy + linear().col(1);
00525 linear() << linear().col(0) + linear().col(1)*sx, tmp;
00526 return *this;
00527 }
00528
00534 template<typename Scalar, int Dim>
00535 Transform<Scalar,Dim>&
00536 Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
00537 {
00538 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00539 m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00540 return *this;
00541 }
00542
00543
00544
00545
00546
00547 template<typename Scalar, int Dim>
00548 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
00549 {
00550 linear().setIdentity();
00551 translation() = t.vector();
00552 m_matrix.template block<1,Dim>(Dim,0).setZero();
00553 m_matrix(Dim,Dim) = Scalar(1);
00554 return *this;
00555 }
00556
00557 template<typename Scalar, int Dim>
00558 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const
00559 {
00560 Transform res = *this;
00561 res.translate(t.vector());
00562 return res;
00563 }
00564
00565 template<typename Scalar, int Dim>
00566 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s)
00567 {
00568 m_matrix.setZero();
00569 linear().diagonal() = s.coeffs();
00570 m_matrix.coeffRef(Dim,Dim) = Scalar(1);
00571 return *this;
00572 }
00573
00574 template<typename Scalar, int Dim>
00575 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const
00576 {
00577 Transform res = *this;
00578 res.scale(s.coeffs());
00579 return res;
00580 }
00581
00582 template<typename Scalar, int Dim>
00583 template<typename Derived>
00584 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
00585 {
00586 linear() = ei_toRotationMatrix<Scalar,Dim>(r);
00587 translation().setZero();
00588 m_matrix.template block<1,Dim>(Dim,0).setZero();
00589 m_matrix.coeffRef(Dim,Dim) = Scalar(1);
00590 return *this;
00591 }
00592
00593 template<typename Scalar, int Dim>
00594 template<typename Derived>
00595 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
00596 {
00597 Transform res = *this;
00598 res.rotate(r.derived());
00599 return res;
00600 }
00601
00602
00603
00604
00605
00613 template<typename Scalar, int Dim>
00614 typename Transform<Scalar,Dim>::LinearMatrixType
00615 Transform<Scalar,Dim>::rotation() const
00616 {
00617 LinearMatrixType result;
00618 computeRotationScaling(&result, (LinearMatrixType*)0);
00619 return result;
00620 }
00621
00622
00634 template<typename Scalar, int Dim>
00635 template<typename RotationMatrixType, typename ScalingMatrixType>
00636 void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
00637 {
00638 linear().svd().computeRotationScaling(rotation, scaling);
00639 }
00640
00652 template<typename Scalar, int Dim>
00653 template<typename ScalingMatrixType, typename RotationMatrixType>
00654 void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
00655 {
00656 linear().svd().computeScalingRotation(scaling, rotation);
00657 }
00658
00662 template<typename Scalar, int Dim>
00663 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00664 Transform<Scalar,Dim>&
00665 Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00666 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
00667 {
00668 linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
00669 linear() *= scale.asDiagonal();
00670 translation() = position;
00671 m_matrix.template block<1,Dim>(Dim,0).setZero();
00672 m_matrix(Dim,Dim) = Scalar(1);
00673 return *this;
00674 }
00675
00695 template<typename Scalar, int Dim>
00696 inline const typename Transform<Scalar,Dim>::MatrixType
00697 Transform<Scalar,Dim>::inverse(TransformTraits traits) const
00698 {
00699 if (traits == Projective)
00700 {
00701 return m_matrix.inverse();
00702 }
00703 else
00704 {
00705 MatrixType res;
00706 if (traits == Affine)
00707 {
00708 res.template corner<Dim,Dim>(TopLeft) = linear().inverse();
00709 }
00710 else if (traits == Isometry)
00711 {
00712 res.template corner<Dim,Dim>(TopLeft) = linear().transpose();
00713 }
00714 else
00715 {
00716 ei_assert("invalid traits value in Transform::inverse()");
00717 }
00718
00719 res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation();
00720 res.template corner<1,Dim>(BottomLeft).setZero();
00721 res.coeffRef(Dim,Dim) = Scalar(1);
00722 return res;
00723 }
00724 }
00725
00726
00727
00728
00729
00730 template<typename Other, int Dim, int HDim>
00731 struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
00732 {
00733 typedef Transform<typename Other::Scalar,Dim> TransformType;
00734 typedef typename TransformType::MatrixType MatrixType;
00735 typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
00736 static ResultType run(const TransformType& tr, const Other& other)
00737 { return tr.matrix() * other; }
00738 };
00739
00740 template<typename Other, int Dim, int HDim>
00741 struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
00742 {
00743 typedef Transform<typename Other::Scalar,Dim> TransformType;
00744 typedef typename TransformType::MatrixType MatrixType;
00745 typedef TransformType ResultType;
00746 static ResultType run(const TransformType& tr, const Other& other)
00747 {
00748 TransformType res;
00749 res.translation() = tr.translation();
00750 res.matrix().row(Dim) = tr.matrix().row(Dim);
00751 res.linear() = (tr.linear() * other).lazy();
00752 return res;
00753 }
00754 };
00755
00756 template<typename Other, int Dim, int HDim>
00757 struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
00758 {
00759 typedef Transform<typename Other::Scalar,Dim> TransformType;
00760 typedef typename TransformType::MatrixType MatrixType;
00761 typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
00762 static ResultType run(const TransformType& tr, const Other& other)
00763 { return tr.matrix() * other; }
00764 };
00765
00766 template<typename Other, int Dim, int HDim>
00767 struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
00768 {
00769 typedef typename Other::Scalar Scalar;
00770 typedef Transform<Scalar,Dim> TransformType;
00771 typedef typename TransformType::LinearPart MatrixType;
00772 typedef const CwiseUnaryOp<
00773 ei_scalar_multiple_op<Scalar>,
00774 NestByValue<CwiseBinaryOp<
00775 ei_scalar_sum_op<Scalar>,
00776 NestByValue<typename ProductReturnType<NestByValue<MatrixType>,Other>::Type >,
00777 NestByValue<typename TransformType::TranslationPart> > >
00778 > ResultType;
00779
00780 static ResultType run(const TransformType& tr, const Other& other)
00781 { return ((tr.linear().nestByValue() * other).nestByValue() + tr.translation().nestByValue()).nestByValue()
00782 * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
00783 };
00784
00785 #endif // EIGEN_TRANSFORM_H