Big change in DiagonalMatrix and Geometry/Scaling:

* previous DiagonalMatrix expression is now DiagonalMatrixWrapper
* DiagonalMatrix class is now for storage
* add the DiagonalMatrixBase class to factorize code of the
  two previous classes
* remove Scaling class (it is now a global function)
* add UniformScaling helper class
  (don't use it directly, use the Scaling function)
* add the Scaling global function to simplify the creation
  of scaling objects
There is still a lot to do, in particular about DiagonalProduct for which
the goal is to get rid of the "if()" in the coeff() function. At least
it is not worse than before ! Also need to uptade the tutorial and add more doc.
This commit is contained in:
Gael Guennebaud 2009-01-28 16:26:06 +00:00
parent da555585e2
commit 1b194193ef
13 changed files with 439 additions and 237 deletions

View File

@ -25,22 +25,208 @@
#ifndef EIGEN_DIAGONALMATRIX_H #ifndef EIGEN_DIAGONALMATRIX_H
#define EIGEN_DIAGONALMATRIX_H #define EIGEN_DIAGONALMATRIX_H
template<typename CoeffsVectorType, typename Derived>
class DiagonalMatrixBase : ei_no_assignment_operator,
public MatrixBase<Derived>
{
public:
typedef MatrixBase<Derived> Base;
typedef typename ei_traits<Derived>::Scalar Scalar;
typedef typename Base::PacketScalar PacketScalar;
using Base::derived;
protected:
typedef typename ei_cleantype<CoeffsVectorType>::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<typename OtherDerived>
inline DiagonalMatrixBase(const MatrixBase<OtherDerived>& other)
{
construct_from_expression<OtherDerived>::run(derived(),other.derived());
}
template<typename OtherDerived,
bool IsVector = OtherDerived::IsVectorAtCompileTime,
bool IsDiagonal = (OtherDerived::Flags&Diagonal)==Diagonal>
struct construct_from_expression;
// = vector
template<typename OtherDerived>
struct construct_from_expression<OtherDerived,true,false>
{
static void run(Derived& dst, const OtherDerived& src)
{ dst.m_coeffs = src; }
};
// = diagonal
template<typename OtherDerived, bool IsVector>
struct construct_from_expression<OtherDerived,IsVector,true>
{
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<typename OtherDerived, bool IsVector=OtherDerived::IsVectorAtCompileTime>
struct ei_diagonal_product_ctor {
static void run(DiagonalMatrixBase& dst, const OtherDerived& src)
{ dst.m_coeffs = src; }
};
template<typename OtherDerived>
struct ei_diagonal_product_ctor<OtherDerived,false> {
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<typename NewType>
inline DiagonalMatrixWrapper<NestByValue<CwiseUnaryOp<ei_scalar_cast_op<Scalar, NewType>, _CoeffsVectorType> > > cast() const
{
return m_coeffs.template cast<NewType>().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<typename OtherDerived>
inline Derived& operator=(const MatrixBase<OtherDerived>& other)
{
construct_from_expression<OtherDerived>::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<Scalar>(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 /** \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<typename _Scalar,int _Size>
struct ei_traits<DiagonalMatrix<_Scalar,_Size> > : ei_traits<Matrix<_Scalar,_Size,_Size> >
{
enum {
Flags = (ei_traits<Matrix<_Scalar,_Size,_Size> >::Flags & HereditaryBits) | Diagonal
};
};
template<typename _Scalar, int _Size>
class DiagonalMatrix
: public DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, DiagonalMatrix<_Scalar,_Size> >
{
public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix)
typedef DiagonalMatrixBase<Matrix<_Scalar,_Size,1>, 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<typename OtherDerived>
explicit inline DiagonalMatrix(const MatrixBase<OtherDerived>& other) : DiagonalBase(other)
{}
DiagonalMatrix& operator=(const DiagonalMatrix& other)
{
m_coeffs = other.m_coeffs;
return *this;
}
template<typename OtherDerived>
DiagonalMatrix& operator=(const MatrixBase<OtherDerived>& 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 * \brief Expression of a diagonal matrix
* *
* \param CoeffsVectorType the type of the vector of diagonal coefficients * \param CoeffsVectorType the type of the vector of diagonal coefficients
* *
* This class is an expression of a diagonal matrix with given vector of diagonal * This class is an expression of a diagonal matrix with given vector of diagonal
* coefficients. It is the return * coefficients. It is the return type of MatrixBase::diagonal(const OtherDerived&)
* type of MatrixBase::diagonal(const OtherDerived&) and most of the time this is * and most of the time this is the only way it is used.
* the only way it is used.
* *
* \sa MatrixBase::diagonal(const OtherDerived&) * \sa class DiagonalMatrixBase, class DiagonalMatrix, MatrixBase::asDiagonal()
*/ */
template<typename CoeffsVectorType> template<typename CoeffsVectorType>
struct ei_traits<DiagonalMatrix<CoeffsVectorType> > struct ei_traits<DiagonalMatrixWrapper<CoeffsVectorType> >
{ {
typedef typename CoeffsVectorType::Scalar Scalar; typedef typename CoeffsVectorType::Scalar Scalar;
typedef typename ei_nested<CoeffsVectorType>::type CoeffsVectorTypeNested; typedef typename ei_nested<CoeffsVectorType>::type CoeffsVectorTypeNested;
@ -54,45 +240,19 @@ struct ei_traits<DiagonalMatrix<CoeffsVectorType> >
CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost CoeffReadCost = _CoeffsVectorTypeNested::CoeffReadCost
}; };
}; };
template<typename CoeffsVectorType> template<typename CoeffsVectorType>
class DiagonalMatrix : ei_no_assignment_operator, class DiagonalMatrixWrapper
public MatrixBase<DiagonalMatrix<CoeffsVectorType> > : public DiagonalMatrixBase<typename CoeffsVectorType::Nested, DiagonalMatrixWrapper<CoeffsVectorType> >
{ {
typedef typename CoeffsVectorType::Nested CoeffsVectorTypeNested;
typedef DiagonalMatrixBase<CoeffsVectorTypeNested, DiagonalMatrixWrapper<CoeffsVectorType> > DiagonalBase;
public: public:
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrixWrapper)
EIGEN_GENERIC_PUBLIC_INTERFACE(DiagonalMatrix) inline DiagonalMatrixWrapper(const CoeffsVectorType& coeffs) : DiagonalBase(coeffs)
{}
// needed to evaluate a DiagonalMatrix<Xpr> to a DiagonalMatrix<NestByValue<Vector> >
template<typename OtherCoeffsVectorType>
inline DiagonalMatrix(const DiagonalMatrix<OtherCoeffsVectorType>& 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<Scalar>(0);
}
inline const CoeffsVectorType& diagonal() const { return m_coeffs; }
protected:
const typename CoeffsVectorType::Nested m_coeffs;
}; };
/** \nonstableyet /** \nonstableyet
* \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients * \returns an expression of a diagonal matrix with *this as vector of diagonal coefficients
* *
* \only_for_vectors * \only_for_vectors
@ -105,13 +265,13 @@ class DiagonalMatrix : ei_no_assignment_operator,
* \sa class DiagonalMatrix, isDiagonal() * \sa class DiagonalMatrix, isDiagonal()
**/ **/
template<typename Derived> template<typename Derived>
inline const DiagonalMatrix<Derived> inline const DiagonalMatrixWrapper<Derived>
MatrixBase<Derived>::asDiagonal() const MatrixBase<Derived>::asDiagonal() const
{ {
return derived(); return derived();
} }
/** \nonstableyet /** \nonstableyet
* \returns true if *this is approximately equal to a diagonal matrix, * \returns true if *this is approximately equal to a diagonal matrix,
* within the precision given by \a prec. * within the precision given by \a prec.
* *

View File

@ -30,9 +30,9 @@
* Unlike ei_nested, if the argument is a DiagonalMatrix and if it must be evaluated, * 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. * then it evaluated to a DiagonalMatrix having its own argument evaluated.
*/ */
template<typename T, int N> struct ei_nested_diagonal : ei_nested<T,N> {}; template<typename T, int N, bool IsDiagonal = (T::Flags&Diagonal)==Diagonal> struct ei_nested_diagonal : ei_nested<T,N> {};
template<typename T, int N> struct ei_nested_diagonal<DiagonalMatrix<T>,N > template<typename T, int N> struct ei_nested_diagonal<T,N,true>
: ei_nested<DiagonalMatrix<T>, N, DiagonalMatrix<NestByValue<typename ei_plain_matrix_type<T>::type> > > : ei_nested<T, N, DiagonalMatrix<typename T::Scalar, EIGEN_ENUM_MIN(T::RowsAtCompileTime,T::ColsAtCompileTime)> >
{}; {};
// specialization of ProductReturnType // specialization of ProductReturnType

View File

@ -443,7 +443,7 @@ template<typename Derived> class MatrixBase
static const BasisReturnType UnitZ(); static const BasisReturnType UnitZ();
static const BasisReturnType UnitW(); static const BasisReturnType UnitW();
const DiagonalMatrix<Derived> asDiagonal() const; const DiagonalMatrixWrapper<Derived> asDiagonal() const;
void fill(const Scalar& value); void fill(const Scalar& value);
Derived& setConstant(const Scalar& value); Derived& setConstant(const Scalar& value);

View File

@ -97,6 +97,8 @@ template<typename ExpressionType> class NestByValue
{ {
m_expression.const_cast_derived().template writePacket<LoadMode>(index, x); m_expression.const_cast_derived().template writePacket<LoadMode>(index, x);
} }
operator const ExpressionType&() const { return m_expression; }
protected: protected:
const ExpressionType m_expression; const ExpressionType m_expression;

View File

@ -45,7 +45,9 @@ template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp;
template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp; template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp;
template<typename BinaryOp, typename Lhs, typename Rhs> class CwiseBinaryOp; template<typename BinaryOp, typename Lhs, typename Rhs> class CwiseBinaryOp;
template<typename Lhs, typename Rhs, int ProductMode> class Product; template<typename Lhs, typename Rhs, int ProductMode> class Product;
template<typename CoeffsVectorType> class DiagonalMatrix; template<typename CoeffsVectorType, typename Derived> class DiagonalMatrixBase;
template<typename CoeffsVectorType> class DiagonalMatrixWrapper;
template<typename _Scalar, int _Size> class DiagonalMatrix;
template<typename MatrixType> class DiagonalCoeffs; template<typename MatrixType> class DiagonalCoeffs;
template<typename MatrixType, int PacketAccess = AsRequested> class Map; template<typename MatrixType, int PacketAccess = AsRequested> class Map;
template<typename MatrixType, unsigned int Mode> class Part; template<typename MatrixType, unsigned int Mode> class Part;
@ -117,7 +119,7 @@ template<typename Scalar,int Dim> class Transform;
template <typename _Scalar, int _AmbientDim> class ParametrizedLine; template <typename _Scalar, int _AmbientDim> class ParametrizedLine;
template <typename _Scalar, int _AmbientDim> class Hyperplane; template <typename _Scalar, int _AmbientDim> class Hyperplane;
template<typename Scalar,int Dim> class Translation; template<typename Scalar,int Dim> class Translation;
template<typename Scalar,int Dim> class Scaling; template<typename Scalar> class UniformScaling;
// Sparse module: // Sparse module:
template<typename Lhs, typename Rhs, int ProductMode> class SparseProduct; template<typename Lhs, typename Rhs, int ProductMode> class SparseProduct;

View File

@ -74,7 +74,8 @@
THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES, THIS_METHOD_IS_ONLY_FOR_COLUMN_MAJOR_MATRICES,
THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES, THIS_METHOD_IS_ONLY_FOR_ROW_MAJOR_MATRICES,
INVALID_MATRIX_TEMPLATE_PARAMETERS, 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
}; };
}; };

View File

@ -193,8 +193,7 @@ public:
Quaternion slerp(Scalar t, const Quaternion& other) const; Quaternion slerp(Scalar t, const Quaternion& other) const;
template<typename Derived> Vector3 operator* (const Vector3& vec) const;
Vector3 operator* (const MatrixBase<Derived>& vec) const;
/** \returns \c *this with scalar type casted to \a NewScalarType /** \returns \c *this with scalar type casted to \a NewScalarType
* *
@ -256,17 +255,15 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::operator*= (const Quaternion& oth
* - Via a Matrix3: 24 + 15n * - Via a Matrix3: 24 + 15n
*/ */
template <typename Scalar> template <typename Scalar>
template<typename Derived>
inline typename Quaternion<Scalar>::Vector3 inline typename Quaternion<Scalar>::Vector3
Quaternion<Scalar>::operator* (const MatrixBase<Derived>& v) const Quaternion<Scalar>::operator* (const Vector3& v) const
{ {
// Note that this algorithm comes from the optimization by hand // Note that this algorithm comes from the optimization by hand
// of the conversion to a Matrix followed by a Matrix/Vector product. // of the conversion to a Matrix followed by a Matrix/Vector product.
// It appears to be much faster than the common algorithm found // It appears to be much faster than the common algorithm found
// in the litterature (30 versus 39 flops). It also requires two // in the litterature (30 versus 39 flops). It also requires two
// Vector3 as temporaries. // Vector3 as temporaries.
Vector3 uv; Vector3 uv = Scalar(2) * this->vec().cross(v);
uv = 2 * this->vec().cross(v);
return v + this->w() * uv + this->vec().cross(uv); return v + this->w() * uv + this->vec().cross(uv);
} }

View File

@ -59,9 +59,19 @@ class RotationBase
inline Transform<Scalar,Dim> operator*(const Translation<Scalar,Dim>& t) const inline Transform<Scalar,Dim> operator*(const Translation<Scalar,Dim>& t) const
{ return toRotationMatrix() * t; } { return toRotationMatrix() * t; }
/** \returns the concatenation of the rotation \c *this with a scaling \a s */ /** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */
inline RotationMatrixType operator*(const Scaling<Scalar,Dim>& s) const inline RotationMatrixType operator*(const UniformScaling<Scalar>& s) const
{ return toRotationMatrix() * s; } { return toRotationMatrix() * s.factor(); }
/** \returns the concatenation of the rotation \c *this with a linear transformation \a l */
template<typename OtherDerived>
inline RotationMatrixType operator*(const MatrixBase<OtherDerived>& l) const
{ return toRotationMatrix() * l.derived(); }
/** \returns the concatenation of a linear transformation \a l with the rotation \a r */
template<typename OtherDerived> friend
inline RotationMatrixType operator*(const MatrixBase<OtherDerived>& l, const Derived& r)
{ return l.derived() * r.toRotationMatrix(); }
/** \returns the concatenation of the rotation \c *this with an affine transformation \a t */ /** \returns the concatenation of the rotation \c *this with an affine transformation \a t */
inline Transform<Scalar,Dim> operator*(const Transform<Scalar,Dim>& t) const inline Transform<Scalar,Dim> operator*(const Transform<Scalar,Dim>& t) const

View File

@ -29,102 +29,72 @@
* *
* \class Scaling * \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 _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. * 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<typename _Scalar, int _Dim> template<typename _Scalar>
class Scaling class UniformScaling
{ {
public: 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 */ /** the scalar type of the coefficients */
typedef _Scalar Scalar; typedef _Scalar Scalar;
/** 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: protected:
VectorType m_coeffs; Scalar m_factor;
public: public:
/** Default constructor without initialization. */ /** Default constructor without initialization. */
Scaling() {} UniformScaling() {}
/** Constructs and initialize a uniform scaling transformation */ /** Constructs and initialize a uniform scaling transformation */
explicit inline Scaling(const Scalar& s) { m_coeffs.setConstant(s); } explicit inline UniformScaling(const Scalar& s) : m_factor(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) {}
const VectorType& coeffs() const { return m_coeffs; } const Scalar& factor() const { return m_factor; }
VectorType& coeffs() { return m_coeffs; } Scalar& factor() { return m_factor; }
/** Concatenates two scaling */ /** Concatenates two uniform scaling */
inline Scaling operator* (const Scaling& other) const inline UniformScaling operator* (const UniformScaling& other) const
{ return Scaling(coeffs().cwise() * other.coeffs()); } { return UniformScaling(m_factor * other.factor()); }
/** Concatenates a scaling and a translation */ /** Concatenates a uniform scaling and a translation */
inline TransformType operator* (const TranslationType& t) const; template<int Dim>
inline Transform<Scalar,Dim> operator* (const Translation<Scalar,Dim>& t) const;
/** Concatenates a scaling and an affine transformation */ /** Concatenates a uniform scaling and an affine transformation */
inline TransformType operator* (const TransformType& t) const; template<int Dim>
inline Transform<Scalar,Dim> operator* (const Transform<Scalar,Dim>& t) const;
/** Concatenates a scaling and a linear transformation matrix */ /** Concatenates a uniform scaling and a linear transformation matrix */
// TODO returns an expression // 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<typename Derived> template<typename Derived>
inline LinearMatrixType operator*(const RotationBase<Derived,Dim>& r) const inline typename ei_eval<Derived>::type operator* (const MatrixBase<Derived>& other) const
{ return *this * r.toRotationMatrix(); } { return other * m_factor; }
/** Applies scaling to vector */ /** Concatenates a linear transformation matrix and a uniform scaling */
inline VectorType operator* (const VectorType& other) const // TODO returns an expression
{ return coeffs().asDiagonal() * other; } template<typename Derived>
friend inline typename ei_eval<Derived>::type
operator* (const MatrixBase<Derived>& other, const UniformScaling& s)
{ return other * s.factor(); }
template<typename Derived,int Dim>
inline Matrix<Scalar,Dim,Dim> operator*(const RotationBase<Derived,Dim>& r) const
{ return r.toRotationMatrix() * m_factor; }
/** \returns the inverse scaling */ /** \returns the inverse scaling */
inline Scaling inverse() const inline UniformScaling inverse() const
{ return Scaling(coeffs().cwise().inverse()); } { return UniformScaling(Scalar(1)/m_factor); }
inline Scaling& operator=(const Scaling& other)
{
m_coeffs = other.m_coeffs;
return *this;
}
/** \returns \c *this with scalar type casted to \a NewScalarType /** \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. * then this function smartly returns a const reference to \c *this.
*/ */
template<typename NewScalarType> template<typename NewScalarType>
inline typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type cast() const inline UniformScaling<NewScalarType> cast() const
{ return typename ei_cast_return_type<Scaling,Scaling<NewScalarType,Dim> >::type(*this); } { return UniformScaling<NewScalarType>(NewScalarType(m_factor)); }
/** Copy constructor with scalar type conversion */ /** Copy constructor with scalar type conversion */
template<typename OtherScalarType> template<typename OtherScalarType>
inline explicit Scaling(const Scaling<OtherScalarType,Dim>& other) inline explicit UniformScaling(const UniformScaling<OtherScalarType>& other)
{ m_coeffs = other.coeffs().template cast<Scalar>(); } { m_factor = Scalar(other.factor()); }
/** \returns \c true if \c *this is approximately equal to \a other, within the precision /** \returns \c true if \c *this is approximately equal to \a other, within the precision
* determined by \a prec. * determined by \a prec.
* *
* \sa MatrixBase::isApprox() */ * \sa MatrixBase::isApprox() */
bool isApprox(const Scaling& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const bool isApprox(const UniformScaling& other, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) const
{ return m_coeffs.isApprox(other.m_coeffs, prec); } { return ei_isApprox(m_factor, other.factor(), prec); }
}; };
/** Constructs a uniform scaling from scale factor \a s */
UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
/** Constructs a uniform scaling from scale factor \a s */
UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
/** Constructs a uniform scaling from scale factor \a s */
template<typename RealScalar> UniformScaling<std::complex<RealScalar> >
Scaling(const std::complex<RealScalar>& s)
{ return UniformScaling<std::complex<RealScalar> >(s); }
/** Constructs a 2D axis aligned scaling */
template<typename Scalar> DiagonalMatrix<Scalar,2>
Scaling(Scalar sx, Scalar sy)
{ return DiagonalMatrix<Scalar,2>(sx, sy); }
/** Constructs a 3D axis aligned scaling */
template<typename Scalar> DiagonalMatrix<Scalar,3>
Scaling(Scalar sx, Scalar sy, Scalar sz)
{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
* This is an alias for coeffs.asDiagonal()
*/
template<typename Derived>
const DiagonalMatrixWrapper<Derived> Scaling(const MatrixBase<Derived>& coeffs)
{ return coeffs.asDiagonal(); }
/** \addtogroup GeometryModule */ /** \addtogroup GeometryModule */
//@{ //@{
typedef Scaling<float, 2> Scaling2f; /** \deprecated */
typedef Scaling<double,2> Scaling2d; typedef DiagonalMatrix<float, 2> AlignedScaling2f;
typedef Scaling<float, 3> Scaling3f; /** \deprecated */
typedef Scaling<double,3> Scaling3d; typedef DiagonalMatrix<double,2> AlignedScaling2d;
/** \deprecated */
typedef DiagonalMatrix<float, 3> AlignedScaling3f;
/** \deprecated */
typedef DiagonalMatrix<double,3> AlignedScaling3d;
//@} //@}
template<typename Scalar, int Dim>
inline typename Scaling<Scalar,Dim>::TransformType
Scaling<Scalar,Dim>::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<typename Scalar, int Dim>
inline typename Scaling<Scalar,Dim>::TransformType
Scaling<Scalar,Dim>::operator* (const TransformType& t) const
{
TransformType res = t;
res.prescale(m_coeffs);
return res;
}
#endif // EIGEN_SCALING_H #endif // EIGEN_SCALING_H

View File

@ -41,7 +41,14 @@ template< typename Other,
int HDim, int HDim,
int OtherRows=Other::RowsAtCompileTime, int OtherRows=Other::RowsAtCompileTime,
int OtherCols=Other::ColsAtCompileTime> 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 /** \geometry_module \ingroup GeometryModule
* *
@ -83,8 +90,6 @@ public:
typedef Block<MatrixType,Dim,1> TranslationPart; typedef Block<MatrixType,Dim,1> TranslationPart;
/** corresponding translation type */ /** corresponding translation type */
typedef Translation<Scalar,Dim> TranslationType; typedef Translation<Scalar,Dim> TranslationType;
/** corresponding scaling transformation type */
typedef Scaling<Scalar,Dim> ScalingType;
protected: protected:
@ -104,7 +109,7 @@ public:
} }
inline explicit Transform(const TranslationType& t) { *this = t; } inline explicit Transform(const TranslationType& t) { *this = t; }
inline explicit Transform(const ScalingType& s) { *this = s; } inline explicit Transform(const UniformScaling<Scalar>& s) { *this = s; }
template<typename Derived> template<typename Derived>
inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; } inline explicit Transform(const RotationBase<Derived, Dim>& r) { *this = r; }
@ -138,10 +143,13 @@ public:
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other); construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::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<typename OtherDerived> template<typename OtherDerived>
inline Transform& operator=(const MatrixBase<OtherDerived>& other) inline Transform& operator=(const MatrixBase<OtherDerived>& other)
{ m_matrix = other; return *this; } {
construct_from_matrix<OtherDerived, int(OtherDerived::RowsAtCompileTime) == Dim>::run(this, other);
return *this;
}
#ifdef EIGEN_QT_SUPPORT #ifdef EIGEN_QT_SUPPORT
inline Transform(const QMatrix& other); inline Transform(const QMatrix& other);
@ -175,24 +183,32 @@ public:
inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); } inline TranslationPart translation() { return m_matrix.template block<Dim,1>(0,Dim); }
/** \returns an expression of the product between the transform \c *this and a matrix expression \a other /** \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: * The right hand side \a other might be either:
* \li a vector of size Dim, * \li a vector of size Dim,
* \li an homogeneous vector of size Dim+1, * \li an homogeneous vector of size Dim+1,
* \li a transformation matrix of size Dim+1 x 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 // note: this function is defined here because some compilers cannot find the respective declaration
template<typename OtherDerived> template<typename OtherDerived>
inline const typename ei_transform_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType inline const typename ei_transform_right_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
operator * (const MatrixBase<OtherDerived> &other) const operator * (const MatrixBase<OtherDerived> &other) const
{ return ei_transform_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); } { return ei_transform_right_product_impl<OtherDerived,Dim,HDim>::run(*this,other.derived()); }
/** \returns the product expression of a transformation matrix \a a times a transform \a b /** \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<typename OtherDerived> * The right hand side \a other might be either:
friend inline const typename ProductReturnType<OtherDerived,MatrixType>::Type * \li a linear transformation matrix of size Dim x Dim
* \li a transformation matrix of size Dim+1 x Dim+1.
*/
template<typename OtherDerived> friend
inline const typename ei_transform_left_product_impl<OtherDerived,_Dim,_Dim+1>::ResultType
operator * (const MatrixBase<OtherDerived> &a, const Transform &b) operator * (const MatrixBase<OtherDerived> &a, const Transform &b)
{ return a.derived() * b.matrix(); } { return ei_transform_left_product_impl<OtherDerived,Dim,HDim>::run(a.derived(),b); }
template<typename OtherDerived>
inline Transform& operator*=(const MatrixBase<OtherDerived>& other) { return *this = *this * other; }
/** Contatenates two transformations */ /** Contatenates two transformations */
inline const Transform inline const Transform
@ -230,16 +246,17 @@ public:
inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); } inline Transform& operator*=(const TranslationType& t) { return translate(t.vector()); }
inline Transform operator*(const TranslationType& t) const; inline Transform operator*(const TranslationType& t) const;
inline Transform& operator=(const ScalingType& t); inline Transform& operator=(const UniformScaling<Scalar>& t);
inline Transform& operator*=(const ScalingType& s) { return scale(s.coeffs()); } inline Transform& operator*=(const UniformScaling<Scalar>& s) { return scale(s.factor()); }
inline Transform operator*(const ScalingType& s) const; inline Transform operator*(const UniformScaling<Scalar>& s) const;
friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
{ // friend inline Transform operator*(const LinearMatrixType& mat, const Transform& t)
Transform res = t; // {
res.matrix().row(Dim) = t.matrix().row(Dim); // Transform res = t;
res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy(); // res.matrix().row(Dim) = t.matrix().row(Dim);
return res; // res.matrix().template block<Dim,HDim>(0,0) = (mat * t.matrix().template block<Dim,HDim>(0,0)).lazy();
} // return res;
// }
template<typename Derived> template<typename Derived>
inline Transform& operator=(const RotationBase<Derived,Dim>& r); inline Transform& operator=(const RotationBase<Derived,Dim>& r);
@ -558,19 +575,19 @@ inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const TranslationT
} }
template<typename Scalar, int Dim> template<typename Scalar, int Dim>
inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const ScalingType& s) inline Transform<Scalar,Dim>& Transform<Scalar,Dim>::operator=(const UniformScaling<Scalar>& s)
{ {
m_matrix.setZero(); m_matrix.setZero();
linear().diagonal() = s.coeffs(); linear().diagonal().fill(s.factor());
m_matrix.coeffRef(Dim,Dim) = Scalar(1); m_matrix.coeffRef(Dim,Dim) = Scalar(1);
return *this; return *this;
} }
template<typename Scalar, int Dim> template<typename Scalar, int Dim>
inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const ScalingType& s) const inline Transform<Scalar,Dim> Transform<Scalar,Dim>::operator*(const UniformScaling<Scalar>& s) const
{ {
Transform res = *this; Transform res = *this;
res.scale(s.coeffs()); res.scale(s.factor());
return res; return res;
} }
@ -722,8 +739,9 @@ Transform<Scalar,Dim>::inverse(TransformTraits traits) const
*** Specializations of operator* with a MatrixBase *** *** Specializations of operator* with a MatrixBase ***
*****************************************************/ *****************************************************/
// T * affine matrix
template<typename Other, int Dim, int HDim> template<typename Other, int Dim, int HDim>
struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim> struct ei_transform_right_product_impl<Other,Dim,HDim, HDim,HDim>
{ {
typedef Transform<typename Other::Scalar,Dim> TransformType; typedef Transform<typename Other::Scalar,Dim> TransformType;
typedef typename TransformType::MatrixType MatrixType; typedef typename TransformType::MatrixType MatrixType;
@ -732,8 +750,9 @@ struct ei_transform_product_impl<Other,Dim,HDim, HDim,HDim>
{ return tr.matrix() * other; } { return tr.matrix() * other; }
}; };
// T * linear matrix
template<typename Other, int Dim, int HDim> template<typename Other, int Dim, int HDim>
struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim> struct ei_transform_right_product_impl<Other,Dim,HDim, Dim,Dim>
{ {
typedef Transform<typename Other::Scalar,Dim> TransformType; typedef Transform<typename Other::Scalar,Dim> TransformType;
typedef typename TransformType::MatrixType MatrixType; typedef typename TransformType::MatrixType MatrixType;
@ -748,8 +767,9 @@ struct ei_transform_product_impl<Other,Dim,HDim, Dim,Dim>
} }
}; };
// T * homogeneous vector
template<typename Other, int Dim, int HDim> template<typename Other, int Dim, int HDim>
struct ei_transform_product_impl<Other,Dim,HDim, HDim,1> struct ei_transform_right_product_impl<Other,Dim,HDim, HDim,1>
{ {
typedef Transform<typename Other::Scalar,Dim> TransformType; typedef Transform<typename Other::Scalar,Dim> TransformType;
typedef typename TransformType::MatrixType MatrixType; typedef typename TransformType::MatrixType MatrixType;
@ -758,8 +778,9 @@ struct ei_transform_product_impl<Other,Dim,HDim, HDim,1>
{ return tr.matrix() * other; } { return tr.matrix() * other; }
}; };
// T * vector
template<typename Other, int Dim, int HDim> template<typename Other, int Dim, int HDim>
struct ei_transform_product_impl<Other,Dim,HDim, Dim,1> struct ei_transform_right_product_impl<Other,Dim,HDim, Dim,1>
{ {
typedef typename Other::Scalar Scalar; typedef typename Other::Scalar Scalar;
typedef Transform<Scalar,Dim> TransformType; typedef Transform<Scalar,Dim> TransformType;
@ -777,4 +798,31 @@ struct ei_transform_product_impl<Other,Dim,HDim, Dim,1>
* (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); } * (Scalar(1) / ( (tr.matrix().template block<1,Dim>(Dim,0) * other).coeff(0) + tr.matrix().coeff(Dim,Dim))); }
}; };
// affine matrix * T
template<typename Other, int Dim, int HDim>
struct ei_transform_left_product_impl<Other,Dim,HDim, HDim,HDim>
{
typedef Transform<typename Other::Scalar,Dim> TransformType;
typedef typename TransformType::MatrixType MatrixType;
typedef typename ProductReturnType<MatrixType,Other>::Type ResultType;
static ResultType run(const Other& other,const TransformType& tr)
{ return other * tr.matrix(); }
};
// linear matrix * T
template<typename Other, int Dim, int HDim>
struct ei_transform_left_product_impl<Other,Dim,HDim, Dim,Dim>
{
typedef Transform<typename Other::Scalar,Dim> 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<Dim,HDim>(TopLeft) = (other * tr.matrix().template corner<Dim,HDim>(TopLeft)).lazy();
return res;
}
};
#endif // EIGEN_TRANSFORM_H #endif // EIGEN_TRANSFORM_H

View File

@ -52,8 +52,6 @@ public:
typedef Matrix<Scalar,Dim,1> VectorType; typedef Matrix<Scalar,Dim,1> VectorType;
/** corresponding linear transformation matrix type */ /** corresponding linear transformation matrix type */
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType; typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
/** corresponding scaling transformation type */
typedef Scaling<Scalar,Dim> ScalingType;
/** corresponding affine transformation type */ /** corresponding affine transformation type */
typedef Transform<Scalar,Dim> TransformType; typedef Transform<Scalar,Dim> TransformType;
@ -80,7 +78,7 @@ public:
m_coeffs.y() = sy; m_coeffs.y() = sy;
m_coeffs.z() = sz; 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) {} explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
const VectorType& vector() const { return m_coeffs; } const VectorType& vector() const { return m_coeffs; }
@ -90,24 +88,27 @@ public:
inline Translation operator* (const Translation& other) const inline Translation operator* (const Translation& other) const
{ return Translation(m_coeffs + other.m_coeffs); } { return Translation(m_coeffs + other.m_coeffs); }
/** Concatenates a translation and a scaling */ /** Concatenates a translation and a uniform scaling */
inline TransformType operator* (const ScalingType& other) const; inline TransformType operator* (const UniformScaling<Scalar>& other) const;
/** Concatenates a translation and a linear transformation */ /** Concatenates a translation and a linear transformation */
inline TransformType operator* (const LinearMatrixType& linear) const; template<typename OtherDerived>
inline TransformType operator* (const MatrixBase<OtherDerived>& linear) const;
/** Concatenates a translation and a rotation */
template<typename Derived> template<typename Derived>
inline TransformType operator*(const RotationBase<Derived,Dim>& r) const inline TransformType operator*(const RotationBase<Derived,Dim>& r) const
{ return *this * r.toRotationMatrix(); } { 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 // its a nightmare to define a templated friend function outside its declaration
friend inline TransformType operator* (const LinearMatrixType& linear, const Translation& t) template<typename OtherDerived> friend
inline TransformType operator*(const MatrixBase<OtherDerived>& linear, const Translation& t)
{ {
TransformType res; TransformType res;
res.matrix().setZero(); res.matrix().setZero();
res.linear() = linear; res.linear() = linear.derived();
res.translation() = linear * t.m_coeffs; res.translation() = linear.derived() * t.m_coeffs;
res.matrix().row(Dim).setZero(); res.matrix().row(Dim).setZero();
res(Dim,Dim) = Scalar(1); res(Dim,Dim) = Scalar(1);
return res; return res;
@ -160,26 +161,26 @@ typedef Translation<float, 3> Translation3f;
typedef Translation<double,3> Translation3d; typedef Translation<double,3> Translation3d;
//@} //@}
template<typename Scalar, int Dim> template<typename Scalar, int Dim>
inline typename Translation<Scalar,Dim>::TransformType inline typename Translation<Scalar,Dim>::TransformType
Translation<Scalar,Dim>::operator* (const ScalingType& other) const Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
{ {
TransformType res; TransformType res;
res.matrix().setZero(); res.matrix().setZero();
res.linear().diagonal() = other.coeffs(); res.linear().diagonal().fill(other.factor());
res.translation() = m_coeffs; res.translation() = m_coeffs;
res(Dim,Dim) = Scalar(1); res(Dim,Dim) = Scalar(1);
return res; return res;
} }
template<typename Scalar, int Dim> template<typename Scalar, int Dim>
template<typename OtherDerived>
inline typename Translation<Scalar,Dim>::TransformType inline typename Translation<Scalar,Dim>::TransformType
Translation<Scalar,Dim>::operator* (const LinearMatrixType& linear) const Translation<Scalar,Dim>::operator* (const MatrixBase<OtherDerived>& linear) const
{ {
TransformType res; TransformType res;
res.matrix().setZero(); res.matrix().setZero();
res.linear() = linear; res.linear() = linear.derived();
res.translation() = m_coeffs; res.translation() = m_coeffs;
res.matrix().row(Dim).setZero(); res.matrix().row(Dim).setZero();
res(Dim,Dim) = Scalar(1); res(Dim,Dim) = Scalar(1);

View File

@ -43,8 +43,8 @@ template<typename Scalar> void geometry(void)
typedef AngleAxis<Scalar> AngleAxisx; typedef AngleAxis<Scalar> AngleAxisx;
typedef Transform<Scalar,2> Transform2; typedef Transform<Scalar,2> Transform2;
typedef Transform<Scalar,3> Transform3; typedef Transform<Scalar,3> Transform3;
typedef Scaling<Scalar,2> Scaling2; typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
typedef Scaling<Scalar,3> Scaling3; typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
typedef Translation<Scalar,2> Translation2; typedef Translation<Scalar,2> Translation2;
typedef Translation<Scalar,3> Translation3; typedef Translation<Scalar,3> Translation3;
@ -220,7 +220,7 @@ template<typename Scalar> void geometry(void)
t4 *= tv3; t4 *= tv3;
VERIFY_IS_APPROX(t5.matrix(), t4.matrix()); VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
Scaling3 sv3(v3); AlignedScaling3 sv3(v3);
Transform3 t6(sv3); Transform3 t6(sv3);
t4 = sv3; t4 = sv3;
VERIFY_IS_APPROX(t6.matrix(), t4.matrix()); VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
@ -260,30 +260,34 @@ template<typename Scalar> void geometry(void)
// 3D // 3D
t0.setIdentity(); t0.setIdentity();
t0.rotate(q1).scale(v0).translate(v0); t0.rotate(q1).scale(v0).translate(v0);
// mat * scaling and mat * translation // mat * aligned scaling and mat * translation
t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0); t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0);
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// mat * transformation and scaling * translation t1 = (Matrix3(q1) * Scaling(v0)) * Translation3(v0);
t1 = Matrix3(q1) * (Scaling3(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()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
t0.setIdentity(); t0.setIdentity();
t0.prerotate(q1).prescale(v0).pretranslate(v0); t0.prerotate(q1).prescale(v0).pretranslate(v0);
// translation * scaling and transformation * mat // translation * aligned scaling and transformation * mat
t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1); t1 = (Translation3(v0) * AlignedScaling3(v0)) * Matrix3(q1);
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// scaling * mat and translation * mat // 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()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
t0.setIdentity(); t0.setIdentity();
t0.scale(v0).translate(v0).rotate(q1); t0.scale(v0).translate(v0).rotate(q1);
// translation * mat and scaling * transformation // translation * mat and aligned scaling * transformation
t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1)); t1 = AlignedScaling3(v0) * (Translation3(v0) * Matrix3(q1));
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// transformation * scaling // transformation * aligned scaling
t0.scale(v0); t0.scale(v0);
t1 = t1 * Scaling3(v0); t1 = t1 * AlignedScaling3(v0);
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// transformation * translation // transformation * translation
t0.translate(v0); t0.translate(v0);
@ -304,9 +308,9 @@ template<typename Scalar> void geometry(void)
t1 = t1 * (Translation3(v1) * q1); t1 = t1 * (Translation3(v1) * q1);
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// scaling * quaternion // aligned scaling * quaternion
t0.scale(v1).rotate(q1); t0.scale(v1).rotate(q1);
t1 = t1 * (Scaling3(v1) * q1); t1 = t1 * (AlignedScaling3(v1) * q1);
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// quaternion * transform // quaternion * transform
@ -319,9 +323,9 @@ template<typename Scalar> void geometry(void)
t1 = t1 * (q1 * Translation3(v1)); t1 = t1 * (q1 * Translation3(v1));
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// quaternion * scaling // quaternion * aligned scaling
t0.rotate(q1).scale(v1); t0.rotate(q1).scale(v1);
t1 = t1 * (q1 * Scaling3(v1)); t1 = t1 * (q1 * AlignedScaling3(v1));
VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
// translation * vector // translation * vector
@ -329,10 +333,10 @@ template<typename Scalar> void geometry(void)
t0.translate(v0); t0.translate(v0);
VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1); VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1);
// scaling * vector // AlignedScaling * vector
t0.setIdentity(); t0.setIdentity();
t0.scale(v0); t0.scale(v0);
VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1); VERIFY_IS_APPROX(t0 * v1, AlignedScaling3(v0) * v1);
// test transform inversion // test transform inversion
t0.setIdentity(); t0.setIdentity();
@ -343,10 +347,10 @@ template<typename Scalar> void geometry(void)
t0.translate(v0).rotate(q1); t0.translate(v0).rotate(q1);
VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse()); VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse());
// test extract rotation and scaling // test extract rotation and aligned scaling
t0.setIdentity(); // t0.setIdentity();
t0.translate(v0).rotate(q1).scale(v1); // t0.translate(v0).rotate(q1).scale(v1);
VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1); // VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1);
Matrix3 mat_rotation, mat_scaling; Matrix3 mat_rotation, mat_scaling;
t0.setIdentity(); t0.setIdentity();
@ -372,10 +376,10 @@ template<typename Scalar> void geometry(void)
Translation<double,3> tr1d = tr1.template cast<double>(); Translation<double,3> tr1d = tr1.template cast<double>();
VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1); VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
Scaling3 sc1(v0); AlignedScaling3 sc1(v0);
Scaling<float,3> sc1f = sc1.template cast<float>(); DiagonalMatrix<float,3> sc1f; sc1f = sc1.template cast<float>();
VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1); VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1);
Scaling<double,3> sc1d = sc1.template cast<double>(); DiagonalMatrix<double,3> sc1d; sc1d = (sc1.template cast<double>());
VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1); VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
Quaternion<float> q1f = q1.template cast<float>(); Quaternion<float> q1f = q1.template cast<float>();
@ -428,7 +432,6 @@ template<typename Scalar> void geometry(void)
mcross = mat3.rowwise().cross(vec3); mcross = mat3.rowwise().cross(vec3);
VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3)); VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
} }
void test_geometry() void test_geometry()

View File

@ -65,7 +65,7 @@ template<typename HyperplaneType> void hyperplane(const HyperplaneType& _plane)
if (!NumTraits<Scalar>::IsComplex) if (!NumTraits<Scalar>::IsComplex)
{ {
MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ(); MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ();
Scaling<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random()); DiagonalMatrix<Scalar,HyperplaneType::AmbientDimAtCompileTime> scaling(VectorType::Random());
Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random()); Translation<Scalar,HyperplaneType::AmbientDimAtCompileTime> translation(VectorType::Random());
pl2 = pl1; pl2 = pl1;