fix bug #439: add Quaternion::FromTwoVectors() static constructor

This commit is contained in:
Gael Guennebaud 2012-03-26 18:30:04 +02:00
parent 6c3b8b2ebc
commit fd2f399c18
2 changed files with 35 additions and 0 deletions

View File

@ -284,6 +284,9 @@ public:
explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
template<typename Derived1, typename Derived2>
static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
inline Coefficients& coeffs() { return m_coeffs;}
inline const Coefficients& coeffs() const { return m_coeffs;}
@ -624,6 +627,27 @@ inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Deri
return derived();
}
/** Returns a quaternion representing a rotation between
* the two arbitrary vectors \a a and \a b. In other words, the built
* rotation represent a rotation sending the line of direction \a a
* to the line of direction \a b, both lines passing through the origin.
*
* \returns resulting quaternion
*
* Note that the two input vectors do \b not have to be normalized, and
* do not need to have the same norm.
*/
template<typename Scalar, int Options>
template<typename Derived1, typename Derived2>
Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
{
Quaternion quat;
quat.setFromTwoVectors(a, b);
return quat;
}
/** \returns the multiplicative inverse of \c *this
* Note that in most cases, i.e., if you simply want the opposite rotation,
* and/or the quaternion is normalized, then it is enough to use the conjugate.

View File

@ -142,6 +142,17 @@ template<typename Scalar, int Options> void quaternion(void)
VERIFY_IS_APPROX(-v3.normalized(),(q2.setFromTwoVectors(v1,-v3)*v1).normalized());
}
// from two vector creation static function
VERIFY_IS_APPROX( v2.normalized(),(Quaternionx::FromTwoVectors(v1, v2)*v1).normalized());
VERIFY_IS_APPROX( v1.normalized(),(Quaternionx::FromTwoVectors(v1, v1)*v1).normalized());
VERIFY_IS_APPROX(-v1.normalized(),(Quaternionx::FromTwoVectors(v1,-v1)*v1).normalized());
if (internal::is_same<Scalar,double>::value)
{
v3 = (v1.array()+eps).matrix();
VERIFY_IS_APPROX( v3.normalized(),(Quaternionx::FromTwoVectors(v1, v3)*v1).normalized());
VERIFY_IS_APPROX(-v3.normalized(),(Quaternionx::FromTwoVectors(v1,-v3)*v1).normalized());
}
// inverse and conjugate
VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);