diff --git a/Eigen/src/Core/CommaInitializer.h b/Eigen/src/Core/CommaInitializer.h index 0a555e1b7..61a004780 100644 --- a/Eigen/src/Core/CommaInitializer.h +++ b/Eigen/src/Core/CommaInitializer.h @@ -93,6 +93,15 @@ struct MatrixBase::CommaInitializer && "Too few coefficients passed to Matrix::operator<<"); } + /** \returns the built matrix once all its coefficients have been set. + * Calling finished is 100% optional. Its purpose is to write expressions + * like this: + * \code + * quaternion.fromRotationMatrix((Matrix3f() << axis0, axis1, axis2).finished()); + * \endcode + */ + inline Derived& finished() { return m_matrix; } + Derived& m_matrix; int m_row; // current row id int m_col; // current col id diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 1ae2c4562..ea693b7a9 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -71,14 +71,14 @@ template class MatrixBase : public ArrayBase * by the \a Derived type. If a value is not known at compile-time, * it is set to the \a Dynamic constant. * \sa MatrixBase::rows(), MatrixBase::cols(), RowsAtCompileTime, SizeAtCompileTime */ - + SizeAtCompileTime = (ei_size_at_compile_time::RowsAtCompileTime, ei_traits::ColsAtCompileTime>::ret), /**< This is equal to the number of coefficients, i.e. the number of * rows times the number of columns, or to \a Dynamic if this is not * known at compile-time. \sa RowsAtCompileTime, ColsAtCompileTime */ - + MaxRowsAtCompileTime = ei_traits::MaxRowsAtCompileTime, /**< This value is equal to the maximum possible number of rows that this expression * might have. If this expression might have an arbitrarily high number of rows, @@ -89,7 +89,7 @@ template class MatrixBase : public ArrayBase * * \sa RowsAtCompileTime, MaxColsAtCompileTime, MaxSizeAtCompileTime */ - + MaxColsAtCompileTime = ei_traits::MaxColsAtCompileTime, /**< This value is equal to the maximum possible number of columns that this expression * might have. If this expression might have an arbitrarily high number of columns, @@ -100,7 +100,7 @@ template class MatrixBase : public ArrayBase * * \sa ColsAtCompileTime, MaxRowsAtCompileTime, MaxSizeAtCompileTime */ - + MaxSizeAtCompileTime = (ei_size_at_compile_time::MaxRowsAtCompileTime, ei_traits::MaxColsAtCompileTime>::ret), /**< This value is equal to the maximum possible number of coefficients that this expression @@ -119,7 +119,7 @@ template class MatrixBase : public ArrayBase * columns is known at compile-time to be equal to 1. Indeed, in that case, * we are dealing with a column-vector (if there is only one column) or with * a row-vector (if there is only one row). */ - + Flags = ei_traits::Flags, /**< This stores expression \ref flags flags which may or may not be inherited by new expressions * constructed from this one. See the \ref flags "list of flags". diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index 40b1ccdbd..1d0a3294f 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -168,7 +168,7 @@ public: inline Quaternion& operator*= (const Quaternion& q); Quaternion inverse(void) const; - Quaternion unitInverse(void) const; + Quaternion conjugate(void) const; Quaternion slerp(Scalar t, const Quaternion& other) const; @@ -226,6 +226,11 @@ template inline typename Quaternion::Matrix3 Quaternion::toRotationMatrix(void) const { + // FIXME another option would be to declare toRotationMatrix like that: + // OtherDerived& toRotationMatrix(MatrixBase& m) + // it would fill m and returns a ref to m. + // the advantages is that way we can accept 4x4 and 3x4 matrices filling the rest of the + // matrix with I... ?? Matrix3 res; Scalar tx = 2*this->x(); @@ -261,6 +266,7 @@ template template Quaternion& Quaternion::fromRotationMatrix(const MatrixBase& m) { + // FIXME maybe this function could accept 4x4 and 3x4 matrices as well ? (simply update the assert) ei_assert(Derived::RowsAtCompileTime==3 && Derived::ColsAtCompileTime==3); // This algorithm comes from "Quaternion Calculus and Fast Animation", // Ken Shoemake, 1987 SIGGRAPH course notes @@ -398,13 +404,19 @@ inline Quaternion& Quaternion::fromTwoVectors(const MatrixBase inline Quaternion Quaternion::inverse() const { + // FIXME should this funtion be called multiplicativeInverse and conjugate() be called inverse() or opposite() ?? Scalar n2 = this->norm2(); if (n2 > 0) - return (*this) / norm; + return conjugate() / n2; else { // return an invalid result to flag the error @@ -412,9 +424,14 @@ inline Quaternion Quaternion::inverse() const } } -/** Like Quaternion::inverse() but assumes the quaternion is normalized */ +/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse + * if the quaternion is normalized. + * The conjugate of a quaternion represents the opposite rotation. + * + * \sa Quaternion::inverse() + */ template -inline Quaternion Quaternion::unitInverse() const +inline Quaternion Quaternion::conjugate() const { return Quaternion(this->w(),-this->x(),-this->y(),-this->z()); } @@ -425,6 +442,12 @@ inline Quaternion Quaternion::unitInverse() const template Quaternion Quaternion::slerp(Scalar t, const Quaternion& other) const { + // FIXME options for this function would be: + // 1 - Quaternion& fromSlerp(Scalar t, const Quaternion& q0, const Quaternion& q1); + // which set *this from the s-lerp and returns *this + // 2 - Quaternion slerp(Scalar t, const Quaternion& other) const + // which returns the s-lerp between this and other + // ?? if (*this == other) return *this; diff --git a/test/geometry.cpp b/test/geometry.cpp index 6a1926ed0..aee86c03f 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -71,6 +71,10 @@ template void geometry(void) VERIFY_IS_APPROX(v2.normalized(),(q2.fromTwoVectors(v1,v2)*v1).normalized()); VERIFY_IS_APPROX(v2.normalized(),(q2.fromTwoVectors(v1,v2)*v1).normalized()); + // inverse and conjugate + VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1); + VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1); + // cross product VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1)); Matrix3 m;