diff options
author | Gael Guennebaud <g.gael@free.fr> | 2008-08-30 12:42:06 +0000 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2008-08-30 12:42:06 +0000 |
commit | 236b7a545d139a32b6cd0984044ce91d737094a5 (patch) | |
tree | 4392f9104cdaace755cc8a7c56cf70a01f36a891 /Eigen | |
parent | 9e7a9cde14fc8d20e9aaf41619a23dfb420fc973 (diff) |
update Transform::inverse() to take an optional argument stating whether the transformation is:
NonAffine, Affine (default), contains NoShear, contains NoScaling
that allows significant speed improvements. If you like it, this concept could be applied to
Transform::extractRotation (or to a more advanced decomposition function) and to Hyperplane::transformed()
and maybe to some other places... e.g., I think a Transform::normalMatrix() function would not harm and
warn user that the transformation of normals is not that trivial (I saw this mistake much too often)
Diffstat (limited to 'Eigen')
-rw-r--r-- | Eigen/Geometry | 1 | ||||
-rw-r--r-- | Eigen/src/Geometry/Scaling.h | 9 | ||||
-rw-r--r-- | Eigen/src/Geometry/Transform.h | 109 | ||||
-rw-r--r-- | Eigen/src/Geometry/Translation.h | 7 |
4 files changed, 120 insertions, 6 deletions
diff --git a/Eigen/Geometry b/Eigen/Geometry index b5037306d..ab3a9b9d6 100644 --- a/Eigen/Geometry +++ b/Eigen/Geometry @@ -25,6 +25,7 @@ namespace Eigen { // the Geometry module use cwiseCos and cwiseSin which are defined in the Array module #include "src/Array/CwiseOperators.h" #include "src/Array/Functors.h" +#include "src/Array/PartialRedux.h" #include "src/Geometry/OrthoMethods.h" #include "src/Geometry/Quaternion.h" diff --git a/Eigen/src/Geometry/Scaling.h b/Eigen/src/Geometry/Scaling.h index fcf1c0437..73938ac8b 100644 --- a/Eigen/src/Geometry/Scaling.h +++ b/Eigen/src/Geometry/Scaling.h @@ -35,18 +35,23 @@ * \param _Dim the dimension of the space, can be a compile time value or Dynamic * * - * \sa class Translate, class Transform + * \sa class Translation, class Transform */ template<typename _Scalar, int _Dim> class Scaling { public: + /** dimension of the space */ enum { Dim = _Dim }; /** the scalar type of the coefficients */ typedef _Scalar Scalar; - typedef Matrix<Scalar,Dim,Dim> LinearMatrixType; + /** corresponding vector type */ typedef Matrix<Scalar,Dim,1> VectorType; + /** corresponding linear transformation matrix type */ + typedef Matrix<Scalar,Dim,Dim> LinearMatrixType; + /** corresponding translation type */ typedef Translation<Scalar,Dim> TranslationType; + /** corresponding affine transformation type */ typedef Transform<Scalar,Dim> TransformType; protected: diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index f32577e88..fd5fd66ba 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -25,6 +25,14 @@ #ifndef EIGEN_TRANSFORM_H #define EIGEN_TRANSFORM_H +/** Represents some traits of a transformation */ +enum TransformationKnowledge { + NoScaling, ///< the transformation is a concatenation of translations, rotations + NoShear, ///< the transformation is a concatenation of translations, rotations and scalings + GenericAffine, ///< the transformation is affine (linear transformation + translation) + NonAffine ///< the transformation might not be affine +}; + // Note that we have to pass Dim and HDim because it is not allowed to use a template // parameter to define a template specialization. To be more precise, in the following // specializations, it is not allowed to use Dim+1 instead of HDim. @@ -73,7 +81,9 @@ public: typedef Matrix<Scalar,Dim,1> VectorType; /** type of a read/write reference to the translation part of the rotation */ typedef Block<MatrixType,Dim,1> TranslationPart; + /** corresponding translation type */ typedef Translation<Scalar,Dim> TranslationType; + /** corresponding scaling transformation type */ typedef Scaling<Scalar,Dim> ScalingType; protected: @@ -193,8 +203,11 @@ public: Transform& shear(Scalar sx, Scalar sy); Transform& preshear(Scalar sx, Scalar sy); + inline Transform& operator=(const TranslationType& t); inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); } inline Transform operator*(const TranslationType& t) const; + + inline Transform& operator=(const ScalingType& t); inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); } inline Transform operator*(const ScalingType& s) const; friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t) @@ -212,9 +225,7 @@ public: Transform& fromPositionOrientationScale(const MatrixBase<PositionDerived> &position, const OrientationType& orientation, const MatrixBase<ScaleDerived> &scale); - /** \sa MatrixBase::inverse() */ - const MatrixType inverse() const - { return m_matrix.inverse(); } + inline const MatrixType inverse(TransformationKnowledge knowledge = GenericAffine) const; const Scalar* data() const { return m_matrix.data(); } Scalar* data() { return m_matrix.data(); } @@ -232,6 +243,10 @@ typedef Transform<double,2> Transform2d; /** \ingroup GeometryModule */ typedef Transform<double,3> Transform3d; +/************************** +*** Optional QT support *** +**************************/ + #ifdef EIGEN_QT_SUPPORT /** Initialises \c *this from a QMatrix assuming the dimension is 2. * @@ -271,6 +286,10 @@ QMatrix Transform<Scalar,Dim>::toQMatrix(void) const } #endif +/********************* +*** Procedural API *** +*********************/ + /** Applies on the right the non uniform scale transformation represented * by the vector \a other to \c *this and returns a reference to \c *this. * \sa prescale() @@ -399,6 +418,18 @@ Transform<Scalar,Dim>::preshear(Scalar sx, Scalar sy) return *this; } +/****************************************************** +*** Scaling, Translation and Rotation compatibility *** +******************************************************/ + +template<typename Scalar, int Dim> +inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const TranslationType& t) +{ + setIdentity(); + translation() = t.vector(); + return *this; +} + template<typename Scalar, int Dim> inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationType& t) const { @@ -408,6 +439,15 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationT } template<typename Scalar, int Dim> +inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s) +{ + m_matrix.setZero(); + linear().diagonal() = s.coeffs(); + m_matrix(Dim,Dim) = Scalar(1); + return *this; +} + +template<typename Scalar, int Dim> inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const { Transform res = *this; @@ -415,6 +455,10 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& return res; } +/*************************** +*** Specialial functions *** +***************************/ + /** \returns the rotation part of the transformation using a QR decomposition. * \sa extractRotationNoShear(), class QR */ @@ -454,6 +498,65 @@ Transform<Scalar,Dim>::fromPositionOrientationScale(const MatrixBase<PositionDer return *this; } +/** \returns the inverse transformation matrix according to some given knowledge + * on \c *this. + * + * \param knowledge allozs to optimize the inversion process when the transformion + * is known to be not a general transformation. The possible values are: + * - NonAffine if the transformation is not necessarily affines, i.e., if the + * last row is not guaranteed to be [0 ... 0 1] + * - GenericAffine is the default, the last row is assumed to be [0 ... 0 1] + * - NoShear if the transformation is only a concatenations of translations, + * rotations, and scalings. + * - NoScaling if the transformation is only a concatenations of translations + * and rotations. + * + * \sa MatrixBase::inverse() + */ +template<typename Scalar, int Dim> +inline const typename Transform<Scalar,Dim>::MatrixType +Transform<Scalar,Dim>::inverse(TransformationKnowledge knowledge) const +{ + if (knowledge == NonAffine) + { + return m_matrix.inverse(); + } + else + { + MatrixType res; + if (knowledge == GenericAffine) + { + res.template corner<Dim,Dim>(TopLeft) = linear().inverse(); + } + else if (knowledge == NoShear) + { + // extract linear = rotation * scaling + // then inv(linear) = inv(scaling) * inv(rotation) + // = inv(scaling) * trans(rotation) + // = inv(scaling) * trans(inv(scaling)) * trans(A) + // = inv(scaling) * inv(scaling) * trans(A) + // = inv(scaling)^2 * trans(A) + // = scaling^-2 * trans(A) + // with scaling[i] = A.col(i).norm() + VectorType invScaling2 = linear().colwise().norm2().cwise().inverse(); + res.template corner<Dim,Dim>(TopLeft) = (invScaling2.asDiagonal() * linear().transpose()).lazy(); + } + else if (knowledge == NoScaling) + { + res.template corner<Dim,Dim>(TopLeft) = linear().transpose(); + } + else + { + ei_assert("invalid knowledge value in Transform::inverse()"); + } + // translation and remaining parts + res.template corner<Dim,1>(TopRight) = - res.template corner<Dim,Dim>(TopLeft) * translation(); + res.template corner<1,Dim>(BottomLeft).setZero(); + res.coeffRef(Dim,Dim) = Scalar(1); + return res; + } +} + /*********************************** *** Specializations of operator* *** ***********************************/ diff --git a/Eigen/src/Geometry/Translation.h b/Eigen/src/Geometry/Translation.h index ad63b835f..b65aca9eb 100644 --- a/Eigen/src/Geometry/Translation.h +++ b/Eigen/src/Geometry/Translation.h @@ -41,12 +41,17 @@ template<typename _Scalar, int _Dim> class Translation { public: + /** dimension of the space */ enum { Dim = _Dim }; /** the scalar type of the coefficients */ typedef _Scalar Scalar; - typedef Matrix<Scalar,Dim,Dim> LinearMatrixType; + /** corresponding vector type */ typedef Matrix<Scalar,Dim,1> VectorType; + /** corresponding linear transformation matrix type */ + typedef Matrix<Scalar,Dim,Dim> LinearMatrixType; + /** corresponding scaling transformation type */ typedef Scaling<Scalar,Dim> ScalingType; + /** corresponding affine transformation type */ typedef Transform<Scalar,Dim> TransformType; protected: |