diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index 07eaf0747..975a80bd3 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -25,22 +25,208 @@ #ifndef EIGEN_DIAGONALMATRIX_H #define EIGEN_DIAGONALMATRIX_H + +template +class DiagonalMatrixBase : ei_no_assignment_operator, + public MatrixBase +{ + public: + typedef MatrixBase Base; + typedef typename ei_traits::Scalar Scalar; + typedef typename Base::PacketScalar PacketScalar; + using Base::derived; + + protected: + typedef typename ei_cleantype::type _CoeffsVectorType; + + /** Default constructor without initialization */ + inline DiagonalMatrixBase() {} + /** Constructs a diagonal matrix with given dimension */ + inline DiagonalMatrixBase(int dim) : m_coeffs(dim) {} + /** Generic constructor from an expression */ + template + inline DiagonalMatrixBase(const MatrixBase& other) + { + construct_from_expression::run(derived(),other.derived()); + } + + template + struct construct_from_expression; + + // = vector + template + struct construct_from_expression + { + static void run(Derived& dst, const OtherDerived& src) + { dst.m_coeffs = src; } + }; + + // = diagonal + template + struct construct_from_expression + { + static void run(Derived& dst, const OtherDerived& src) + { dst.m_coeffs = src.diagonal(); } + }; + + public: + + inline DiagonalMatrixBase(const _CoeffsVectorType& coeffs) : m_coeffs(coeffs) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(_CoeffsVectorType); + ei_assert(coeffs.size() > 0); + } + + template + struct ei_diagonal_product_ctor { + static void run(DiagonalMatrixBase& dst, const OtherDerived& src) + { dst.m_coeffs = src; } + }; + + template + struct ei_diagonal_product_ctor { + static void run(DiagonalMatrixBase& dst, const OtherDerived& src) + { + EIGEN_STATIC_ASSERT((OtherDerived::Flags&Diagonal)==Diagonal, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX); + dst.m_coeffs = src.diagonal(); + } + }; + + template + inline DiagonalMatrixWrapper, _CoeffsVectorType> > > cast() const + { + return m_coeffs.template cast().nestByValue().asDiagonal(); + } + + /** Assignment operator. + * The right-hand-side \a other must be either a vector representing the diagonal + * coefficients or a diagonal matrix expression. + */ + template + inline Derived& operator=(const MatrixBase& other) + { + construct_from_expression::run(derived(),other); + return derived(); + } + + inline int rows() const { return m_coeffs.size(); } + inline int cols() const { return m_coeffs.size(); } + + inline const Scalar coeff(int row, int col) const + { + return row == col ? m_coeffs.coeff(row) : static_cast(0); + } + + inline const Scalar coeffRef(int row, int col) const + { + ei_assert(row==col); + return m_coeffs.coeffRef(row); + } + + inline _CoeffsVectorType& diagonal() { return m_coeffs; } + inline const _CoeffsVectorType& diagonal() const { return m_coeffs; } + + protected: + CoeffsVectorType m_coeffs; +}; + /** \class DiagonalMatrix - * \nonstableyet + * \nonstableyet + * + * \brief Represent a diagonal matrix with its storage + * + * \param _Scalar the type of coefficients + * \param _Size the dimension of the matrix + * + * \sa class Matrix + */ +template +struct ei_traits > : ei_traits > +{ + enum { + Flags = (ei_traits >::Flags & HereditaryBits) | Diagonal + }; +}; + +template +class DiagonalMatrix + : public DiagonalMatrixBase, DiagonalMatrix<_Scalar,_Size> > +{ + public: + EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix) + typedef DiagonalMatrixBase, DiagonalMatrix<_Scalar,_Size> > DiagonalBase; + + protected: + typedef Matrix<_Scalar,_Size,1> CoeffVectorType; + using DiagonalBase::m_coeffs; + + public: + + /** Default constructor without initialization */ + inline DiagonalMatrix() : DiagonalBase() + {} + + /** Constructs a diagonal matrix with given dimension */ + inline DiagonalMatrix(int dim) : DiagonalBase(dim) + {} + + /** 2D only */ + inline DiagonalMatrix(const Scalar& sx, const Scalar& sy) + { + EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,2,2); + m_coeffs.x() = sx; + m_coeffs.y() = sy; + } + /** 3D only */ + inline DiagonalMatrix(const Scalar& sx, const Scalar& sy, const Scalar& sz) + { + EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DiagonalMatrix,3,3); + m_coeffs.x() = sx; + m_coeffs.y() = sy; + m_coeffs.z() = sz; + } + + /** copy constructor */ + inline DiagonalMatrix(const DiagonalMatrix& other) : DiagonalBase(other.m_coeffs) + {} + + /** generic constructor from expression */ + template + explicit inline DiagonalMatrix(const MatrixBase& other) : DiagonalBase(other) + {} + + DiagonalMatrix& operator=(const DiagonalMatrix& other) + { + m_coeffs = other.m_coeffs; + return *this; + } + + template + DiagonalMatrix& operator=(const MatrixBase& other) + { + EIGEN_STATIC_ASSERT((OtherDerived::Flags&Diagonal)==Diagonal, THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX); + m_coeffs = other.diagonal(); + return *this; + } +}; + +/** \class DiagonalMatrixWrapper + * \nonstableyet * * \brief Expression of a diagonal matrix * * \param CoeffsVectorType the type of the vector of diagonal coefficients * * This class is an expression of a diagonal matrix with given vector of diagonal - * coefficients. It is the return - * type of MatrixBase::diagonal(const OtherDerived&) and most of the time this is - * the only way it is used. + * coefficients. It is the return type of MatrixBase::diagonal(const OtherDerived&) + * and most of the time this is the only way it is used. * - * \sa MatrixBase::diagonal(const OtherDerived&) + * \sa class DiagonalMatrixBase, class DiagonalMatrix, MatrixBase::asDiagonal() */ template -struct ei_traits > +struct ei_traits > { typedef typename CoeffsVectorType::Scalar Scalar; typedef typename ei_nested::type CoeffsVectorTypeNested; @@ -54,45 +240,19 @@ struct ei_traits > CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost }; }; - template -class DiagonalMatrix : ei_no_assignment_operator, - public MatrixBase > +class DiagonalMatrixWrapper + : public DiagonalMatrixBase > { + typedef typename CoeffsVectorType::Nested CoeffsVectorTypeNested; + typedef DiagonalMatrixBase > DiagonalBase; public: - - EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix) - - // needed to evaluate a DiagonalMatrix to a DiagonalMatrix > - template - inline DiagonalMatrix(const DiagonalMatrix& other) : m_coeffs(other.diagonal()) - { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType); - EIGEN_STATIC_ASSERT_VECTOR_ONLY(OtherCoeffsVectorType); - ei_assert(m_coeffs.size() > 0); - } - - inline DiagonalMatrix(const CoeffsVectorType& coeffs) : m_coeffs(coeffs) - { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(CoeffsVectorType); - ei_assert(coeffs.size() > 0); - } - - inline int rows() const { return m_coeffs.size(); } - inline int cols() const { return m_coeffs.size(); } - - inline const Scalar coeff(int row, int col) const - { - return row == col ? m_coeffs.coeff(row) : static_cast(0); - } - - inline const CoeffsVectorType& diagonal() const { return m_coeffs; } - - protected: - const typename CoeffsVectorType::Nested m_coeffs; + EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrixWrapper) + inline DiagonalMatrixWrapper(const CoeffsVectorType& coeffs) : DiagonalBase(coeffs) + {} }; -/** \nonstableyet +/** \nonstableyet * \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients * * \only_for_vectors @@ -105,13 +265,13 @@ class DiagonalMatrix : ei_no_assignment_operator, * \sa class DiagonalMatrix, isDiagonal() **/ template -inline const DiagonalMatrix +inline const DiagonalMatrixWrapper MatrixBase::asDiagonal() const { return derived(); } -/** \nonstableyet +/** \nonstableyet * \returns true if *this is approximately equal to a diagonal matrix, * within the precision given by \a prec. * diff --git a/Eigen/src/Core/DiagonalProduct.h b/Eigen/src/Core/DiagonalProduct.h index f33a26f98..83ba96c3c 100644 --- a/Eigen/src/Core/DiagonalProduct.h +++ b/Eigen/src/Core/DiagonalProduct.h @@ -30,9 +30,9 @@ * Unlike ei_nested, if the argument is a DiagonalMatrix and if it must be evaluated, * then it evaluated to a DiagonalMatrix having its own argument evaluated. */ -template struct ei_nested_diagonal : ei_nested {}; -template struct ei_nested_diagonal,N > - : ei_nested, N, DiagonalMatrix::type> > > +template struct ei_nested_diagonal : ei_nested {}; +template struct ei_nested_diagonal + : ei_nested > {}; // specialization of ProductReturnType diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 1fd02b0af..4dd319985 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -443,7 +443,7 @@ template class MatrixBase static const BasisReturnType UnitZ(); static const BasisReturnType UnitW(); - const DiagonalMatrix asDiagonal() const; + const DiagonalMatrixWrapper asDiagonal() const; void fill(const Scalar& value); Derived& setConstant(const Scalar& value); diff --git a/Eigen/src/Core/NestByValue.h b/Eigen/src/Core/NestByValue.h index da79315bf..dfe757447 100644 --- a/Eigen/src/Core/NestByValue.h +++ b/Eigen/src/Core/NestByValue.h @@ -97,6 +97,8 @@ template class NestByValue { m_expression.const_cast_derived().template writePacket(index, x); } + + operator const ExpressionType&() const { return m_expression; } protected: const ExpressionType m_expression; diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index a72a40b1b..83c42442b 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -45,7 +45,9 @@ template class CwiseNullaryOp; template class CwiseUnaryOp; template class CwiseBinaryOp; template class Product; -template class DiagonalMatrix; +template class DiagonalMatrixBase; +template class DiagonalMatrixWrapper; +template class DiagonalMatrix; template class DiagonalCoeffs; template class Map; template class Part; @@ -117,7 +119,7 @@ template class Transform; template class ParametrizedLine; template class Hyperplane; template class Translation; -template class Scaling; +template class UniformScaling; // Sparse module: template class SparseProduct; diff --git a/Eigen/src/Core/util/StaticAssert.h b/Eigen/src/Core/util/StaticAssert.h index 7ceeabb5f..2c13098a2 100644 --- a/Eigen/src/Core/util/StaticAssert.h +++ b/Eigen/src/Core/util/StaticAssert.h @@ -74,7 +74,8 @@ THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, INVALID_MATRIX_TEMPLATE_PARAMETERS, - BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER + BOTH_MATRICES_MUST_HAVE_THE_SAME_STORAGE_ORDER, + THIS_METHOD_IS_ONLY_FOR_DIAGONAL_MATRIX }; }; diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index 9504962d5..71bf13297 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -193,8 +193,7 @@ public: Quaternion slerp(Scalar t, const Quaternion& other) const; - template - Vector3 operator* (const MatrixBase& vec) const; + Vector3 operator* (const Vector3& vec) const; /** \returns \c *this with scalar type casted to \a NewScalarType * @@ -256,17 +255,15 @@ inline Quaternion& Quaternion::operator*= (const Quaternion& oth * - Via a Matrix3: 24 + 15n */ template -template inline typename Quaternion::Vector3 -Quaternion::operator* (const MatrixBase& v) const +Quaternion::operator* (const Vector3& v) const { // Note that this algorithm comes from the optimization by hand // of the conversion to a Matrix followed by a Matrix/Vector product. // It appears to be much faster than the common algorithm found // in the litterature (30 versus 39 flops). It also requires two // Vector3 as temporaries. - Vector3 uv; - uv = 2 * this->vec().cross(v); + Vector3 uv = Scalar(2) * this->vec().cross(v); return v + this->w() * uv + this->vec().cross(uv); } diff --git a/Eigen/src/Geometry/RotationBase.h b/Eigen/src/Geometry/RotationBase.h index 5fec0f18d..9d5f16e3f 100644 --- a/Eigen/src/Geometry/RotationBase.h +++ b/Eigen/src/Geometry/RotationBase.h @@ -59,9 +59,19 @@ class RotationBase inline Transform operator*(const Translation& t) const { return toRotationMatrix() * t; } - /** \returns the concatenation of the rotation \c *this with a scaling \a s */ - inline RotationMatrixType operator*(const Scaling& s) const - { return toRotationMatrix() * s; } + /** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */ + inline RotationMatrixType operator*(const UniformScaling& s) const + { return toRotationMatrix() * s.factor(); } + + /** \returns the concatenation of the rotation \c *this with a linear transformation \a l */ + template + inline RotationMatrixType operator*(const MatrixBase& l) const + { return toRotationMatrix() * l.derived(); } + + /** \returns the concatenation of a linear transformation \a l with the rotation \a r */ + template friend + inline RotationMatrixType operator*(const MatrixBase& l, const Derived& r) + { return l.derived() * r.toRotationMatrix(); } /** \returns the concatenation of the rotation \c *this with an affine transformation \a t */ inline Transform operator*(const Transform& t) const diff --git a/Eigen/src/Geometry/Scaling.h b/Eigen/src/Geometry/Scaling.h index 25d76157a..a07e118f0 100644 --- a/Eigen/src/Geometry/Scaling.h +++ b/Eigen/src/Geometry/Scaling.h @@ -29,102 +29,72 @@ * * \class Scaling * - * \brief Represents a possibly non uniform scaling transformation + * \brief Represents a generic uniform scaling transformation * * \param _Scalar the scalar type, i.e., the type of the coefficients. - * \param _Dim the dimension of the space, can be a compile time value or Dynamic * - * \note This class is not aimed to be used to store a scaling transformation, + * This class represent a uniform scaling transformation. It is the return + * type of Scaling(Scalar), and most of the time this is the only way it + * is used. In particular, this class is not aimed to be used to store a scaling transformation, * but rather to make easier the constructions and updates of Transform objects. * - * \sa class Translation, class Transform + * To represent an axis aligned scaling, use the DiagonalMatrix class. + * + * \sa Scaling(), class DiagonalMatrix, MatrixBase::asDiagonal(), class Translation, class Transform */ -template -class Scaling +template +class UniformScaling { public: - EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim) - /** dimension of the space */ - enum { Dim = _Dim }; /** the scalar type of the coefficients */ typedef _Scalar Scalar; - /** corresponding vector type */ - typedef Matrix VectorType; - /** corresponding linear transformation matrix type */ - typedef Matrix LinearMatrixType; - /** corresponding translation type */ - typedef Translation TranslationType; - /** corresponding affine transformation type */ - typedef Transform TransformType; protected: - VectorType m_coeffs; + Scalar m_factor; public: /** Default constructor without initialization. */ - Scaling() {} + UniformScaling() {} /** Constructs and initialize a uniform scaling transformation */ - explicit inline Scaling(const Scalar& s) { m_coeffs.setConstant(s); } - /** 2D only */ - inline Scaling(const Scalar& sx, const Scalar& sy) - { - ei_assert(Dim==2); - m_coeffs.x() = sx; - m_coeffs.y() = sy; - } - /** 3D only */ - inline Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz) - { - ei_assert(Dim==3); - m_coeffs.x() = sx; - m_coeffs.y() = sy; - m_coeffs.z() = sz; - } - /** Constructs and initialize the scaling transformation from a vector of scaling coefficients */ - explicit inline Scaling(const VectorType& coeffs) : m_coeffs(coeffs) {} + explicit inline UniformScaling(const Scalar& s) : m_factor(s) {} - const VectorType& coeffs() const { return m_coeffs; } - VectorType& coeffs() { return m_coeffs; } + const Scalar& factor() const { return m_factor; } + Scalar& factor() { return m_factor; } - /** Concatenates two scaling */ - inline Scaling operator* (const Scaling& other) const - { return Scaling(coeffs().cwise() * other.coeffs()); } + /** Concatenates two uniform scaling */ + inline UniformScaling operator* (const UniformScaling& other) const + { return UniformScaling(m_factor * other.factor()); } - /** Concatenates a scaling and a translation */ - inline TransformType operator* (const TranslationType& t) const; + /** Concatenates a uniform scaling and a translation */ + template + inline Transform operator* (const Translation& t) const; - /** Concatenates a scaling and an affine transformation */ - inline TransformType operator* (const TransformType& t) const; + /** Concatenates a uniform scaling and an affine transformation */ + template + inline Transform operator* (const Transform& t) const; - /** Concatenates a scaling and a linear transformation matrix */ + /** Concatenates a uniform scaling and a linear transformation matrix */ // TODO returns an expression - inline LinearMatrixType operator* (const LinearMatrixType& other) const - { return coeffs().asDiagonal() * other; } - - /** Concatenates a linear transformation matrix and a scaling */ - // TODO returns an expression - friend inline LinearMatrixType operator* (const LinearMatrixType& other, const Scaling& s) - { return other * s.coeffs().asDiagonal(); } - template - inline LinearMatrixType operator*(const RotationBase& r) const - { return *this * r.toRotationMatrix(); } + inline typename ei_eval::type operator* (const MatrixBase& other) const + { return other * m_factor; } - /** Applies scaling to vector */ - inline VectorType operator* (const VectorType& other) const - { return coeffs().asDiagonal() * other; } + /** Concatenates a linear transformation matrix and a uniform scaling */ + // TODO returns an expression + template + friend inline typename ei_eval::type + operator* (const MatrixBase& other, const UniformScaling& s) + { return other * s.factor(); } + + template + inline Matrix operator*(const RotationBase& r) const + { return r.toRotationMatrix() * m_factor; } /** \returns the inverse scaling */ - inline Scaling inverse() const - { return Scaling(coeffs().cwise().inverse()); } - - inline Scaling& operator=(const Scaling& other) - { - m_coeffs = other.m_coeffs; - return *this; - } + inline UniformScaling inverse() const + { return UniformScaling(Scalar(1)/m_factor); } /** \returns \c *this with scalar type casted to \a NewScalarType * @@ -132,50 +102,58 @@ public: * then this function smartly returns a const reference to \c *this. */ template - inline typename ei_cast_return_type >::type cast() const - { return typename ei_cast_return_type >::type(*this); } + inline UniformScaling cast() const + { return UniformScaling(NewScalarType(m_factor)); } /** Copy constructor with scalar type conversion */ template - inline explicit Scaling(const Scaling& other) - { m_coeffs = other.coeffs().template cast(); } + inline explicit UniformScaling(const UniformScaling& other) + { m_factor = Scalar(other.factor()); } /** \returns \c true if \c *this is approximately equal to \a other, within the precision * determined by \a prec. * * \sa MatrixBase::isApprox() */ - bool isApprox(const Scaling& other, typename NumTraits::Real prec = precision()) const - { return m_coeffs.isApprox(other.m_coeffs, prec); } + bool isApprox(const UniformScaling& other, typename NumTraits::Real prec = precision()) const + { return ei_isApprox(m_factor, other.factor(), prec); } }; +/** Constructs a uniform scaling from scale factor \a s */ +UniformScaling Scaling(float s) { return UniformScaling(s); } +/** Constructs a uniform scaling from scale factor \a s */ +UniformScaling Scaling(double s) { return UniformScaling(s); } +/** Constructs a uniform scaling from scale factor \a s */ +template UniformScaling > +Scaling(const std::complex& s) +{ return UniformScaling >(s); } + +/** Constructs a 2D axis aligned scaling */ +template DiagonalMatrix +Scaling(Scalar sx, Scalar sy) +{ return DiagonalMatrix(sx, sy); } +/** Constructs a 3D axis aligned scaling */ +template DiagonalMatrix +Scaling(Scalar sx, Scalar sy, Scalar sz) +{ return DiagonalMatrix(sx, sy, sz); } + +/** Constructs an axis aligned scaling expression from vector expression \a coeffs + * This is an alias for coeffs.asDiagonal() + */ +template +const DiagonalMatrixWrapper Scaling(const MatrixBase& coeffs) +{ return coeffs.asDiagonal(); } + /** \addtogroup GeometryModule */ //@{ -typedef Scaling Scaling2f; -typedef Scaling Scaling2d; -typedef Scaling Scaling3f; -typedef Scaling Scaling3d; +/** \deprecated */ +typedef DiagonalMatrix AlignedScaling2f; +/** \deprecated */ +typedef DiagonalMatrix AlignedScaling2d; +/** \deprecated */ +typedef DiagonalMatrix AlignedScaling3f; +/** \deprecated */ +typedef DiagonalMatrix AlignedScaling3d; //@} -template -inline typename Scaling::TransformType -Scaling::operator* (const TranslationType& t) const -{ - TransformType res; - res.matrix().setZero(); - res.linear().diagonal() = coeffs(); - res.translation() = m_coeffs.cwise() * t.vector(); - res(Dim,Dim) = Scalar(1); - return res; -} - -template -inline typename Scaling::TransformType -Scaling::operator* (const TransformType& t) const -{ - TransformType res = t; - res.prescale(m_coeffs); - return res; -} - #endif // EIGEN_SCALING_H diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index 80e16a450..040988e22 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -41,7 +41,14 @@ template< typename Other, int HDim, int OtherRows=Other::RowsAtCompileTime, int OtherCols=Other::ColsAtCompileTime> -struct ei_transform_product_impl; +struct ei_transform_right_product_impl; + +template< typename Other, + int Dim, + int HDim, + int OtherRows=Other::RowsAtCompileTime, + int OtherCols=Other::ColsAtCompileTime> +struct ei_transform_left_product_impl; /** \geometry_module \ingroup GeometryModule * @@ -83,8 +90,6 @@ public: typedef Block TranslationPart; /** corresponding translation type */ typedef Translation TranslationType; - /** corresponding scaling transformation type */ - typedef Scaling ScalingType; protected: @@ -104,7 +109,7 @@ public: } inline explicit Transform(const TranslationType& t) { *this = t; } - inline explicit Transform(const ScalingType& s) { *this = s; } + inline explicit Transform(const UniformScaling& s) { *this = s; } template inline explicit Transform(const RotationBase& r) { *this = r; } @@ -138,10 +143,13 @@ public: construct_from_matrix::run(this, other); } - /** Set \c *this from a (Dim+1)^2 matrix. */ + /** Set \c *this from a Dim^2 or (Dim+1)^2 matrix. */ template inline Transform& operator=(const MatrixBase& other) - { m_matrix = other; return *this; } + { + construct_from_matrix::run(this, other); + return *this; + } #ifdef EIGEN_QT_SUPPORT inline Transform(const QMatrix& other); @@ -175,24 +183,32 @@ public: inline TranslationPart translation() { return m_matrix.template block(0,Dim); } /** \returns an expression of the product between the transform \c *this and a matrix expression \a other - * - * The right hand side \a other might be either: - * \li a vector of size Dim, - * \li an homogeneous vector of size Dim+1, - * \li a transformation matrix of size Dim+1 x Dim+1. - */ + * + * The right hand side \a other might be either: + * \li a vector of size Dim, + * \li an homogeneous vector of size Dim+1, + * \li a linear transformation matrix of size Dim x Dim + * \li a transformation matrix of size Dim+1 x Dim+1. + */ // note: this function is defined here because some compilers cannot find the respective declaration template - inline const typename ei_transform_product_impl::ResultType + inline const typename ei_transform_right_product_impl::ResultType operator * (const MatrixBase &other) const - { return ei_transform_product_impl::run(*this,other.derived()); } + { return ei_transform_right_product_impl::run(*this,other.derived()); } /** \returns the product expression of a transformation matrix \a a times a transform \a b - * The transformation matrix \a a must have a Dim+1 x Dim+1 sizes. */ - template - friend inline const typename ProductReturnType::Type + * + * The right hand side \a other might be either: + * \li a linear transformation matrix of size Dim x Dim + * \li a transformation matrix of size Dim+1 x Dim+1. + */ + template friend + inline const typename ei_transform_left_product_impl::ResultType operator * (const MatrixBase &a, const Transform &b) - { return a.derived() * b.matrix(); } + { return ei_transform_left_product_impl::run(a.derived(),b); } + + template + inline Transform& operator*=(const MatrixBase& other) { return *this = *this * other; } /** Contatenates two transformations */ inline const Transform @@ -230,16 +246,17 @@ public: 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) - { - Transform res = t; - res.matrix().row(Dim) = t.matrix().row(Dim); - res.matrix().template block(0,0) = (mat * t.matrix().template block(0,0)).lazy(); - return res; - } + inline Transform& operator=(const UniformScaling& t); + inline Transform& operator*=(const UniformScaling& s) { return scale(s.factor()); } + inline Transform operator*(const UniformScaling& s) const; + +// friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t) +// { +// Transform res = t; +// res.matrix().row(Dim) = t.matrix().row(Dim); +// res.matrix().template block(0,0) = (mat * t.matrix().template block(0,0)).lazy(); +// return res; +// } template inline Transform& operator=(const RotationBase& r); @@ -558,19 +575,19 @@ inline Transform Transform::operator*(const TranslationT } template -inline Transform& Transform::operator=(const ScalingType& s) +inline Transform& Transform::operator=(const UniformScaling& s) { m_matrix.setZero(); - linear().diagonal() = s.coeffs(); + linear().diagonal().fill(s.factor()); m_matrix.coeffRef(Dim,Dim) = Scalar(1); return *this; } template -inline Transform Transform::operator*(const ScalingType& s) const +inline Transform Transform::operator*(const UniformScaling& s) const { Transform res = *this; - res.scale(s.coeffs()); + res.scale(s.factor()); return res; } @@ -722,8 +739,9 @@ Transform::inverse(TransformTraits traits) const *** Specializations of operator* with a MatrixBase *** *****************************************************/ +// T * affine matrix template -struct ei_transform_product_impl +struct ei_transform_right_product_impl { typedef Transform TransformType; typedef typename TransformType::MatrixType MatrixType; @@ -732,8 +750,9 @@ struct ei_transform_product_impl { return tr.matrix() * other; } }; +// T * linear matrix template -struct ei_transform_product_impl +struct ei_transform_right_product_impl { typedef Transform TransformType; typedef typename TransformType::MatrixType MatrixType; @@ -748,8 +767,9 @@ struct ei_transform_product_impl } }; +// T * homogeneous vector template -struct ei_transform_product_impl +struct ei_transform_right_product_impl { typedef Transform TransformType; typedef typename TransformType::MatrixType MatrixType; @@ -758,8 +778,9 @@ struct ei_transform_product_impl { return tr.matrix() * other; } }; +// T * vector template -struct ei_transform_product_impl +struct ei_transform_right_product_impl { typedef typename Other::Scalar Scalar; typedef Transform TransformType; @@ -777,4 +798,31 @@ struct ei_transform_product_impl * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); } }; +// affine matrix * T +template +struct ei_transform_left_product_impl +{ + typedef Transform TransformType; + typedef typename TransformType::MatrixType MatrixType; + typedef typename ProductReturnType::Type ResultType; + static ResultType run(const Other& other,const TransformType& tr) + { return other * tr.matrix(); } +}; + +// linear matrix * T +template +struct ei_transform_left_product_impl +{ + typedef Transform TransformType; + typedef typename TransformType::MatrixType MatrixType; + typedef TransformType ResultType; + static ResultType run(const Other& other, const TransformType& tr) + { + TransformType res; + res.matrix().row(Dim) = tr.matrix().row(Dim); + res.matrix().template corner(TopLeft) = (other * tr.matrix().template corner(TopLeft)).lazy(); + return res; + } +}; + #endif // EIGEN_TRANSFORM_H diff --git a/Eigen/src/Geometry/Translation.h b/Eigen/src/Geometry/Translation.h index ba8f728c3..2e90b19ce 100644 --- a/Eigen/src/Geometry/Translation.h +++ b/Eigen/src/Geometry/Translation.h @@ -52,8 +52,6 @@ public: typedef Matrix VectorType; /** corresponding linear transformation matrix type */ typedef Matrix LinearMatrixType; - /** corresponding scaling transformation type */ - typedef Scaling ScalingType; /** corresponding affine transformation type */ typedef Transform TransformType; @@ -80,7 +78,7 @@ public: m_coeffs.y() = sy; m_coeffs.z() = sz; } - /** Constructs and initialize the scaling transformation from a vector of scaling coefficients */ + /** Constructs and initialize the translation transformation from a vector of translation coefficients */ explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {} const VectorType& vector() const { return m_coeffs; } @@ -90,24 +88,27 @@ public: inline Translation operator* (const Translation& other) const { return Translation(m_coeffs + other.m_coeffs); } - /** Concatenates a translation and a scaling */ - inline TransformType operator* (const ScalingType& other) const; + /** Concatenates a translation and a uniform scaling */ + inline TransformType operator* (const UniformScaling& other) const; /** Concatenates a translation and a linear transformation */ - inline TransformType operator* (const LinearMatrixType& linear) const; + template + inline TransformType operator* (const MatrixBase& linear) const; + /** Concatenates a translation and a rotation */ template inline TransformType operator*(const RotationBase& r) const { return *this * r.toRotationMatrix(); } - /** Concatenates a linear transformation and a translation */ + /** \returns the concatenation of a linear transformation \a l with the translation \a t */ // its a nightmare to define a templated friend function outside its declaration - friend inline TransformType operator* (const LinearMatrixType& linear, const Translation& t) + template friend + inline TransformType operator*(const MatrixBase& linear, const Translation& t) { TransformType res; res.matrix().setZero(); - res.linear() = linear; - res.translation() = linear * t.m_coeffs; + res.linear() = linear.derived(); + res.translation() = linear.derived() * t.m_coeffs; res.matrix().row(Dim).setZero(); res(Dim,Dim) = Scalar(1); return res; @@ -160,26 +161,26 @@ typedef Translation Translation3f; typedef Translation Translation3d; //@} - template inline typename Translation::TransformType -Translation::operator* (const ScalingType& other) const +Translation::operator* (const UniformScaling& other) const { TransformType res; res.matrix().setZero(); - res.linear().diagonal() = other.coeffs(); + res.linear().diagonal().fill(other.factor()); res.translation() = m_coeffs; res(Dim,Dim) = Scalar(1); return res; } template +template inline typename Translation::TransformType -Translation::operator* (const LinearMatrixType& linear) const +Translation::operator* (const MatrixBase& linear) const { TransformType res; res.matrix().setZero(); - res.linear() = linear; + res.linear() = linear.derived(); res.translation() = m_coeffs; res.matrix().row(Dim).setZero(); res(Dim,Dim) = Scalar(1); diff --git a/test/geometry.cpp b/test/geometry.cpp index c76054322..b80f9a4c4 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -43,8 +43,8 @@ template void geometry(void) typedef AngleAxis AngleAxisx; typedef Transform Transform2; typedef Transform Transform3; - typedef Scaling Scaling2; - typedef Scaling Scaling3; + typedef DiagonalMatrix AlignedScaling2; + typedef DiagonalMatrix AlignedScaling3; typedef Translation Translation2; typedef Translation Translation3; @@ -220,7 +220,7 @@ template void geometry(void) t4 *= tv3; VERIFY_IS_APPROX(t5.matrix(), t4.matrix()); - Scaling3 sv3(v3); + AlignedScaling3 sv3(v3); Transform3 t6(sv3); t4 = sv3; VERIFY_IS_APPROX(t6.matrix(), t4.matrix()); @@ -260,30 +260,34 @@ template void geometry(void) // 3D t0.setIdentity(); t0.rotate(q1).scale(v0).translate(v0); - // mat * scaling and mat * translation - t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0); + // mat * aligned scaling and mat * translation + t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - // mat * transformation and scaling * translation - t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0)); + t1 = (Matrix3(q1) * Scaling(v0)) * Translation3(v0); + VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); + t1 = (q1 * Scaling(v0)) * Translation3(v0); + VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); + // mat * transformation and aligned scaling * translation + t1 = Matrix3(q1) * (AlignedScaling3(v0) * Translation3(v0)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); t0.setIdentity(); t0.prerotate(q1).prescale(v0).pretranslate(v0); - // translation * scaling and transformation * mat - t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1); + // translation * aligned scaling and transformation * mat + t1 = (Translation3(v0) * AlignedScaling3(v0)) * Matrix3(q1); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); // scaling * mat and translation * mat - t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1)); + t1 = Translation3(v0) * (AlignedScaling3(v0) * Matrix3(q1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); t0.setIdentity(); t0.scale(v0).translate(v0).rotate(q1); - // translation * mat and scaling * transformation - t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1)); + // translation * mat and aligned scaling * transformation + t1 = AlignedScaling3(v0) * (Translation3(v0) * Matrix3(q1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - // transformation * scaling + // transformation * aligned scaling t0.scale(v0); - t1 = t1 * Scaling3(v0); + t1 = t1 * AlignedScaling3(v0); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); // transformation * translation t0.translate(v0); @@ -304,9 +308,9 @@ template void geometry(void) t1 = t1 * (Translation3(v1) * q1); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - // scaling * quaternion + // aligned scaling * quaternion t0.scale(v1).rotate(q1); - t1 = t1 * (Scaling3(v1) * q1); + t1 = t1 * (AlignedScaling3(v1) * q1); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); // quaternion * transform @@ -319,9 +323,9 @@ template void geometry(void) t1 = t1 * (q1 * Translation3(v1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - // quaternion * scaling + // quaternion * aligned scaling t0.rotate(q1).scale(v1); - t1 = t1 * (q1 * Scaling3(v1)); + t1 = t1 * (q1 * AlignedScaling3(v1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); // translation * vector @@ -329,10 +333,10 @@ template void geometry(void) t0.translate(v0); VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1); - // scaling * vector + // AlignedScaling * vector t0.setIdentity(); t0.scale(v0); - VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1); + VERIFY_IS_APPROX(t0 * v1, AlignedScaling3(v0) * v1); // test transform inversion t0.setIdentity(); @@ -343,10 +347,10 @@ template void geometry(void) t0.translate(v0).rotate(q1); VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse()); - // test extract rotation and scaling - t0.setIdentity(); - t0.translate(v0).rotate(q1).scale(v1); - VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1); + // test extract rotation and aligned scaling +// t0.setIdentity(); +// t0.translate(v0).rotate(q1).scale(v1); +// VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1); Matrix3 mat_rotation, mat_scaling; t0.setIdentity(); @@ -372,10 +376,10 @@ template void geometry(void) Translation tr1d = tr1.template cast(); VERIFY_IS_APPROX(tr1d.template cast(),tr1); - Scaling3 sc1(v0); - Scaling sc1f = sc1.template cast(); + AlignedScaling3 sc1(v0); + DiagonalMatrix sc1f; sc1f = sc1.template cast(); VERIFY_IS_APPROX(sc1f.template cast(),sc1); - Scaling sc1d = sc1.template cast(); + DiagonalMatrix sc1d; sc1d = (sc1.template cast()); VERIFY_IS_APPROX(sc1d.template cast(),sc1); Quaternion q1f = q1.template cast(); @@ -428,7 +432,6 @@ template void geometry(void) mcross = mat3.rowwise().cross(vec3); VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3)); - } void test_geometry() diff --git a/test/hyperplane.cpp b/test/hyperplane.cpp index 927553f8e..fdb32f75c 100644 --- a/test/hyperplane.cpp +++ b/test/hyperplane.cpp @@ -65,7 +65,7 @@ template void hyperplane(const HyperplaneType& _plane) if (!NumTraits::IsComplex) { MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ(); - Scaling scaling(VectorType::Random()); + DiagonalMatrix scaling(VectorType::Random()); Translation translation(VectorType::Random()); pl2 = pl1;