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
00027
00028
00029
00030
00031
00032 template< typename Other,
00033 int Dim,
00034 int HDim,
00035 int OtherRows=Other::RowsAtCompileTime,
00036 int OtherCols=Other::ColsAtCompileTime>
00037 struct ei_transform_product_impl;
00038
00056 template<typename _Scalar, int _Dim>
00057 class Transform
00058 {
00059 public:
00060 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim==Dynamic ? Dynamic : (_Dim+1)*(_Dim+1))
00061 enum {
00062 Dim = _Dim,
00063 HDim = _Dim+1
00064 };
00066 typedef _Scalar Scalar;
00068 typedef Matrix<Scalar,HDim,HDim> MatrixType;
00070 typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
00072 typedef Block<MatrixType,Dim,Dim> LinearPart;
00074 typedef const Block<const MatrixType,Dim,Dim> ConstLinearPart;
00076 typedef Matrix<Scalar,Dim,1> VectorType;
00078 typedef Block<MatrixType,Dim,1> TranslationPart;
00080 typedef const Block<const MatrixType,Dim,1> ConstTranslationPart;
00082 typedef Translation<Scalar,Dim> TranslationType;
00084 typedef Scaling<Scalar,Dim> ScalingType;
00085
00086 protected:
00087
00088 MatrixType m_matrix;
00089
00090 public:
00091
00093 inline Transform() { }
00094
00095 inline Transform(const Transform& other)
00096 {
00097 m_matrix = other.m_matrix;
00098 }
00099
00100 inline explicit Transform(const TranslationType& t) { *this = t; }
00101 inline explicit Transform(const ScalingType& s) { *this = s; }
00102 template<typename Derived>
00103 inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
00104
00105 inline Transform& operator=(const Transform& other)
00106 { m_matrix = other.m_matrix; return *this; }
00107
00108 template<typename OtherDerived, bool BigMatrix>
00109 struct construct_from_matrix
00110 {
00111 static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
00112 {
00113 transform->matrix() = other;
00114 }
00115 };
00116
00117 template<typename OtherDerived> struct construct_from_matrix<OtherDerived, true>
00118 {
00119 static inline void run(Transform *transform, const MatrixBase<OtherDerived>& other)
00120 {
00121 transform->linear() = other;
00122 transform->translation().setZero();
00123 transform->matrix()(Dim,Dim) = Scalar(1);
00124 transform->matrix().template block<1,Dim>(Dim,0).setZero();
00125 }
00126 };
00127
00129 template<typename OtherDerived>
00130 inline explicit Transform(const MatrixBase<OtherDerived>& other)
00131 {
00132 construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
00133 }
00134
00136 template<typename OtherDerived>
00137 inline Transform& operator=(const MatrixBase<OtherDerived>& other)
00138 { m_matrix = other; return *this; }
00139
00140 #ifdef EIGEN_QT_SUPPORT
00141 inline Transform(const QMatrix& other);
00142 inline Transform& operator=(const QMatrix& other);
00143 inline QMatrix toQMatrix(void) const;
00144 inline Transform(const QTransform& other);
00145 inline Transform& operator=(const QTransform& other);
00146 inline QTransform toQTransform(void) const;
00147 #endif
00148
00151 inline Scalar operator() (int row, int col) const { return m_matrix(row,col); }
00154 inline Scalar& operator() (int row, int col) { return m_matrix(row,col); }
00155
00157 inline const MatrixType& matrix() const { return m_matrix; }
00159 inline MatrixType& matrix() { return m_matrix; }
00160
00162 inline ConstLinearPart linear() const { return m_matrix.template block<Dim,Dim>(0,0); }
00164 inline LinearPart linear() { return m_matrix.template block<Dim,Dim>(0,0); }
00165
00167 inline ConstTranslationPart translation() const { return m_matrix.template block<Dim,1>(0,Dim); }
00169 inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
00170
00178
00179 template<typename OtherDerived>
00180 inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
00181 operator * (const MatrixBase<OtherDerived> &other) const
00182 { return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
00183
00186 template<typename OtherDerived>
00187 friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type
00188 operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
00189 { return a.derived() * b.matrix(); }
00190
00192 inline const Transform
00193 operator * (const Transform& other) const
00194 { return Transform(m_matrix * other.matrix()); }
00195
00197 void setIdentity() { m_matrix.setIdentity(); }
00198 static const typename MatrixType::IdentityReturnType Identity()
00199 {
00200 return MatrixType::Identity();
00201 }
00202
00203 template<typename OtherDerived>
00204 inline Transform& scale(const MatrixBase<OtherDerived> &other);
00205
00206 template<typename OtherDerived>
00207 inline Transform& prescale(const MatrixBase<OtherDerived> &other);
00208
00209 inline Transform& scale(Scalar s);
00210 inline Transform& prescale(Scalar s);
00211
00212 template<typename OtherDerived>
00213 inline Transform& translate(const MatrixBase<OtherDerived> &other);
00214
00215 template<typename OtherDerived>
00216 inline Transform& pretranslate(const MatrixBase<OtherDerived> &other);
00217
00218 template<typename RotationType>
00219 inline Transform& rotate(const RotationType& rotation);
00220
00221 template<typename RotationType>
00222 inline Transform& prerotate(const RotationType& rotation);
00223
00224 Transform& shear(Scalar sx, Scalar sy);
00225 Transform& preshear(Scalar sx, Scalar sy);
00226
00227 inline Transform& operator=(const TranslationType& t);
00228 inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
00229 inline Transform operator*(const TranslationType& t) const;
00230
00231 inline Transform& operator=(const ScalingType& t);
00232 inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); }
00233 inline Transform operator*(const ScalingType& s) const;
00234 friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
00235 {
00236 Transform res = t;
00237 res.matrix().row(Dim) = t.matrix().row(Dim);
00238 res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
00239 return res;
00240 }
00241
00242 template<typename Derived>
00243 inline Transform& operator=(const RotationBase<Derived,Dim>& r);
00244 template<typename Derived>
00245 inline Transform& operator*=(const RotationBase<Derived,Dim>& r) { return rotate(r.toRotationMatrix()); }
00246 template<typename Derived>
00247 inline Transform operator*(const RotationBase<Derived,Dim>& r) const;
00248
00249 LinearMatrixType rotation() const;
00250 template<typename RotationMatrixType, typename ScalingMatrixType>
00251 void computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const;
00252 template<typename ScalingMatrixType, typename RotationMatrixType>
00253 void computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const;
00254
00255 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00256 Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00257 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale);
00258
00259 inline const MatrixType inverse(TransformTraits traits = Affine) const;
00260
00262 const Scalar* data() const { return m_matrix.data(); }
00264 Scalar* data() { return m_matrix.data(); }
00265
00271 template<typename NewScalarType>
00272 inline typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type cast() const
00273 { return typename internal::cast_return_type<Transform,Transform<NewScalarType,Dim> >::type(*this); }
00274
00276 template<typename OtherScalarType>
00277 inline explicit Transform(const Transform<OtherScalarType,Dim>& other)
00278 { m_matrix = other.matrix().template cast<Scalar>(); }
00279
00284 bool isApprox(const Transform& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
00285 { return m_matrix.isApprox(other.m_matrix, prec); }
00286
00287 #ifdef EIGEN_TRANSFORM_PLUGIN
00288 #include EIGEN_TRANSFORM_PLUGIN
00289 #endif
00290
00291 protected:
00292
00293 };
00294
00296 typedef Transform<float,2> Transform2f;
00298 typedef Transform<float,3> Transform3f;
00300 typedef Transform<double,2> Transform2d;
00302 typedef Transform<double,3> Transform3d;
00303
00304
00305
00306
00307
00308 #ifdef EIGEN_QT_SUPPORT
00309
00313 template<typename Scalar, int Dim>
00314 Transform<Scalar,Dim>::Transform(const QMatrix& other)
00315 {
00316 *this = other;
00317 }
00318
00323 template<typename Scalar, int Dim>
00324 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QMatrix& other)
00325 {
00326 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00327 m_matrix << other.m11(), other.m21(), other.dx(),
00328 other.m12(), other.m22(), other.dy(),
00329 0, 0, 1;
00330 return *this;
00331 }
00332
00339 template<typename Scalar, int Dim>
00340 QMatrix Transform<Scalar,Dim>::toQMatrix(void) const
00341 {
00342 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00343 return QMatrix(m_matrix.coeff(0,0), m_matrix.coeff(1,0),
00344 m_matrix.coeff(0,1), m_matrix.coeff(1,1),
00345 m_matrix.coeff(0,2), m_matrix.coeff(1,2));
00346 }
00347
00352 template<typename Scalar, int Dim>
00353 Transform<Scalar,Dim>::Transform(const QTransform& other)
00354 {
00355 *this = other;
00356 }
00357
00362 template<typename Scalar, int Dim>
00363 Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const QTransform& other)
00364 {
00365 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00366 m_matrix << other.m11(), other.m21(), other.dx(),
00367 other.m12(), other.m22(), other.dy(),
00368 other.m13(), other.m23(), other.m33();
00369 return *this;
00370 }
00371
00376 template<typename Scalar, int Dim>
00377 QTransform Transform<Scalar,Dim>::toQTransform(void) const
00378 {
00379 EIGEN_STATIC_ASSERT(Dim==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00380 return QTransform(m_matrix.coeff(0,0), m_matrix.coeff(1,0), m_matrix.coeff(2,0),
00381 m_matrix.coeff(0,1), m_matrix.coeff(1,1), m_matrix.coeff(2,1),
00382 m_matrix.coeff(0,2), m_matrix.coeff(1,2), m_matrix.coeff(2,2));
00383 }
00384 #endif
00385
00386
00387
00388
00389
00394 template<typename Scalar, int Dim>
00395 template<typename OtherDerived>
00396 Transform<Scalar,Dim>&
00397 Transform<Scalar,Dim>::scale(const MatrixBase<OtherDerived> &other)
00398 {
00399 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00400 linear() = (linear() * other.asDiagonal()).lazy();
00401 return *this;
00402 }
00403
00408 template<typename Scalar, int Dim>
00409 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::scale(Scalar s)
00410 {
00411 linear() *= s;
00412 return *this;
00413 }
00414
00419 template<typename Scalar, int Dim>
00420 template<typename OtherDerived>
00421 Transform<Scalar,Dim>&
00422 Transform<Scalar,Dim>::prescale(const MatrixBase<OtherDerived> &other)
00423 {
00424 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00425 m_matrix.template block<Dim,HDim>(0,0) = (other.asDiagonal() * m_matrix.template block<Dim,HDim>(0,0)).lazy();
00426 return *this;
00427 }
00428
00433 template<typename Scalar, int Dim>
00434 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::prescale(Scalar s)
00435 {
00436 m_matrix.template corner<Dim,HDim>(TopLeft) *= s;
00437 return *this;
00438 }
00439
00444 template<typename Scalar, int Dim>
00445 template<typename OtherDerived>
00446 Transform<Scalar,Dim>&
00447 Transform<Scalar,Dim>::translate(const MatrixBase<OtherDerived> &other)
00448 {
00449 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00450 translation() += linear() * other;
00451 return *this;
00452 }
00453
00458 template<typename Scalar, int Dim>
00459 template<typename OtherDerived>
00460 Transform<Scalar,Dim>&
00461 Transform<Scalar,Dim>::pretranslate(const MatrixBase<OtherDerived> &other)
00462 {
00463 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,int(Dim))
00464 translation() += other;
00465 return *this;
00466 }
00467
00485 template<typename Scalar, int Dim>
00486 template<typename RotationType>
00487 Transform<Scalar,Dim>&
00488 Transform<Scalar,Dim>::rotate(const RotationType& rotation)
00489 {
00490 linear() *= ei_toRotationMatrix<Scalar,Dim>(rotation);
00491 return *this;
00492 }
00493
00501 template<typename Scalar, int Dim>
00502 template<typename RotationType>
00503 Transform<Scalar,Dim>&
00504 Transform<Scalar,Dim>::prerotate(const RotationType& rotation)
00505 {
00506 m_matrix.template block<Dim,HDim>(0,0) = ei_toRotationMatrix<Scalar,Dim>(rotation)
00507 * m_matrix.template block<Dim,HDim>(0,0);
00508 return *this;
00509 }
00510
00516 template<typename Scalar, int Dim>
00517 Transform<Scalar,Dim>&
00518 Transform<Scalar,Dim>::shear(Scalar sx, Scalar sy)
00519 {
00520 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00521 VectorType tmp = linear().col(0)*sy + linear().col(1);
00522 linear() << linear().col(0) + linear().col(1)*sx, tmp;
00523 return *this;
00524 }
00525
00531 template<typename Scalar, int Dim>
00532 Transform<Scalar,Dim>&
00533 Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy)
00534 {
00535 EIGEN_STATIC_ASSERT(int(Dim)==2, YOU_MADE_A_PROGRAMMING_MISTAKE)
00536 m_matrix.template block<Dim,HDim>(0,0) = LinearMatrixType(1, sx, sy, 1) * m_matrix.template block<Dim,HDim>(0,0);
00537 return *this;
00538 }
00539
00540
00541
00542
00543
00544 template<typename Scalar, int Dim>
00545 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t)
00546 {
00547 linear().setIdentity();
00548 translation() = t.vector();
00549 m_matrix.template block<1,Dim>(Dim,0).setZero();
00550 m_matrix(Dim,Dim) = Scalar(1);
00551 return *this;
00552 }
00553
00554 template<typename Scalar, int Dim>
00555 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const
00556 {
00557 Transform res = *this;
00558 res.translate(t.vector());
00559 return res;
00560 }
00561
00562 template<typename Scalar, int Dim>
00563 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s)
00564 {
00565 m_matrix.setZero();
00566 linear().diagonal() = s.coeffs();
00567 m_matrix.coeffRef(Dim,Dim) = Scalar(1);
00568 return *this;
00569 }
00570
00571 template<typename Scalar, int Dim>
00572 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const
00573 {
00574 Transform res = *this;
00575 res.scale(s.coeffs());
00576 return res;
00577 }
00578
00579 template<typename Scalar, int Dim>
00580 template<typename Derived>
00581 inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const RotationBase<Derived,Dim>& r)
00582 {
00583 linear() = ei_toRotationMatrix<Scalar,Dim>(r);
00584 translation().setZero();
00585 m_matrix.template block<1,Dim>(Dim,0).setZero();
00586 m_matrix.coeffRef(Dim,Dim) = Scalar(1);
00587 return *this;
00588 }
00589
00590 template<typename Scalar, int Dim>
00591 template<typename Derived>
00592 inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const RotationBase<Derived,Dim>& r) const
00593 {
00594 Transform res = *this;
00595 res.rotate(r.derived());
00596 return res;
00597 }
00598
00599
00600
00601
00602
00610 template<typename Scalar, int Dim>
00611 typename Transform<Scalar,Dim>::LinearMatrixType
00612 Transform<Scalar,Dim>::rotation() const
00613 {
00614 LinearMatrixType result;
00615 computeRotationScaling(&result, (LinearMatrixType*)0);
00616 return result;
00617 }
00618
00619
00631 template<typename Scalar, int Dim>
00632 template<typename RotationMatrixType, typename ScalingMatrixType>
00633 void Transform<Scalar,Dim>::computeRotationScaling(RotationMatrixType *rotation, ScalingMatrixType *scaling) const
00634 {
00635 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
00636 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant();
00637 Matrix<Scalar, Dim, 1> sv(svd.singularValues());
00638 sv.coeffRef(0) *= x;
00639 if(scaling)
00640 {
00641 scaling->noalias() = svd.matrixV() * sv.asDiagonal() * svd.matrixV().adjoint();
00642 }
00643 if(rotation)
00644 {
00645 LinearMatrixType m(svd.matrixU());
00646 m.col(0) /= x;
00647 rotation->noalias() = m * svd.matrixV().adjoint();
00648 }
00649 }
00650
00662 template<typename Scalar, int Dim>
00663 template<typename ScalingMatrixType, typename RotationMatrixType>
00664 void Transform<Scalar,Dim>::computeScalingRotation(ScalingMatrixType *scaling, RotationMatrixType *rotation) const
00665 {
00666 JacobiSVD<LinearMatrixType> svd(linear(), ComputeFullU|ComputeFullV);
00667 Scalar x = (svd.matrixU() * svd.matrixV().adjoint()).determinant();
00668 Matrix<Scalar, Dim, 1> sv(svd.singularValues());
00669 sv.coeffRef(0) *= x;
00670 if(scaling)
00671 {
00672 scaling->noalias() = svd.matrixU() * sv.asDiagonal() * svd.matrixU().adjoint();
00673 }
00674 if(rotation)
00675 {
00676 LinearMatrixType m(svd.matrixU());
00677 m.col(0) /= x;
00678 rotation->noalias() = m * svd.matrixV().adjoint();
00679 }
00680 }
00681
00685 template<typename Scalar, int Dim>
00686 template<typename PositionDerived, typename OrientationType, typename ScaleDerived>
00687 Transform<Scalar,Dim>&
00688 Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDerived> &position,
00689 const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale)
00690 {
00691 linear() = ei_toRotationMatrix<Scalar,Dim>(orientation);
00692 linear() *= scale.asDiagonal();
00693 translation() = position;
00694 m_matrix.template block<1,Dim>(Dim,0).setZero();
00695 m_matrix(Dim,Dim) = Scalar(1);
00696 return *this;
00697 }
00698
00718 template<typename Scalar, int Dim>
00719 inline const typename Transform<Scalar,Dim>::MatrixType
00720 Transform<Scalar,Dim>::inverse(TransformTraits traits) const
00721 {
00722 if (traits == Projective)
00723 {
00724 return m_matrix.inverse();
00725 }
00726 else
00727 {
00728 MatrixType res;
00729 if (traits == Affine)
00730 {
00731 res.template corner<Dim,Dim>(TopLeft) = linear().inverse();
00732 }
00733 else if (traits == Isometry)
00734 {
00735 res.template corner<Dim,Dim>(TopLeft) = linear().transpose();
00736 }
00737 else
00738 {
00739 ei_assert("invalid traits value in Transform::inverse()");
00740 }
00741
00742 res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation();
00743 res.template corner<1,Dim>(BottomLeft).setZero();
00744 res.coeffRef(Dim,Dim) = Scalar(1);
00745 return res;
00746 }
00747 }
00748
00749
00750
00751
00752
00753 template<typename Other, int Dim, int HDim>
00754 struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
00755 {
00756 typedef Transform<typename Other::Scalar,Dim> TransformType;
00757 typedef typename TransformType::MatrixType MatrixType;
00758 typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
00759 static ResultType run(const TransformType& tr, const Other& other)
00760 { return tr.matrix() * other; }
00761 };
00762
00763 template<typename Other, int Dim, int HDim>
00764 struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
00765 {
00766 typedef Transform<typename Other::Scalar,Dim> TransformType;
00767 typedef typename TransformType::MatrixType MatrixType;
00768 typedef TransformType ResultType;
00769 static ResultType run(const TransformType& tr, const Other& other)
00770 {
00771 TransformType res;
00772 res.translation() = tr.translation();
00773 res.matrix().row(Dim) = tr.matrix().row(Dim);
00774 res.linear() = (tr.linear() * other).lazy();
00775 return res;
00776 }
00777 };
00778
00779 template<typename Other, int Dim, int HDim>
00780 struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
00781 {
00782 typedef Transform<typename Other::Scalar,Dim> TransformType;
00783 typedef typename TransformType::MatrixType MatrixType;
00784 typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
00785 static ResultType run(const TransformType& tr, const Other& other)
00786 { return tr.matrix() * other; }
00787 };
00788
00789 template<typename Other, int Dim, int HDim>
00790 struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
00791 {
00792 typedef typename Other::Scalar Scalar;
00793 typedef Transform<Scalar,Dim> TransformType;
00794 typedef Matrix<Scalar,Dim,1> ResultType;
00795 static ResultType run(const TransformType& tr, const Other& other)
00796 { return ((tr.linear() * other) + tr.translation())
00797 * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
00798 };