Add rotation_between_axis/scaled_rotation_between_axis.
This commit is contained in:
parent
dc41b55e5a
commit
52598de44c
|
@ -12,6 +12,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||
`::from_element(...)`.
|
||||
* The `.iamin()` methods that returns the index of the vector entry with
|
||||
smallest absolute value.
|
||||
* `UnitQuaternion::scaled_rotation_between_axis` and
|
||||
`UnitQuaternion::rotation_between_axis` that take Unit vectors instead of
|
||||
Vector as arguments.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -207,25 +207,63 @@ impl<N: Real> UnitQuaternion<N> {
|
|||
where SB: Storage<N, U3>,
|
||||
SC: Storage<N, U3> {
|
||||
// FIXME: code duplication with Rotation.
|
||||
if let (Some(na), Some(nb)) = (a.try_normalize(N::zero()), b.try_normalize(N::zero())) {
|
||||
if let (Some(na), Some(nb)) = (Unit::try_new(a.clone_owned(), N::zero()),
|
||||
Unit::try_new(b.clone_owned(), N::zero())) {
|
||||
Self::scaled_rotation_between_axis(&na, &nb, s)
|
||||
}
|
||||
else {
|
||||
Some(Self::identity())
|
||||
}
|
||||
}
|
||||
|
||||
/// The unit quaternion needed to make `a` and `b` be collinear and point toward the same
|
||||
/// direction.
|
||||
#[inline]
|
||||
pub fn rotation_between_axis<SB, SC>(a: &Unit<Vector<N, U3, SB>>, b: &Unit<Vector<N, U3, SC>>) -> Option<Self>
|
||||
where SB: Storage<N, U3>,
|
||||
SC: Storage<N, U3> {
|
||||
Self::scaled_rotation_between_axis(a, b, N::one())
|
||||
}
|
||||
|
||||
/// The smallest rotation needed to make `a` and `b` collinear and point toward the same
|
||||
/// direction, raised to the power `s`.
|
||||
#[inline]
|
||||
pub fn scaled_rotation_between_axis<SB, SC>(na: &Unit<Vector<N, U3, SB>>,
|
||||
nb: &Unit<Vector<N, U3, SC>>,
|
||||
s: N)
|
||||
-> Option<Self>
|
||||
where SB: Storage<N, U3>,
|
||||
SC: Storage<N, U3> {
|
||||
|
||||
// FIXME: code duplication with Rotation.
|
||||
let c = na.cross(&nb);
|
||||
|
||||
if let Some(axis) = Unit::try_new(c, N::default_epsilon()) {
|
||||
return Some(Self::from_axis_angle(&axis, na.dot(&nb).acos() * s))
|
||||
}
|
||||
let cos = na.dot(&nb);
|
||||
|
||||
// Zero or PI.
|
||||
if na.dot(&nb) < N::zero() {
|
||||
// The cosinus may be out of [-1, 1] because of innacuracies.
|
||||
if cos <= -N::one() {
|
||||
return None
|
||||
}
|
||||
else if cos >= N::one() {
|
||||
return Some(Self::identity())
|
||||
}
|
||||
else {
|
||||
return Some(Self::from_axis_angle(&axis, cos.acos() * s))
|
||||
}
|
||||
}
|
||||
else if na.dot(&nb) < N::zero() {
|
||||
// PI
|
||||
//
|
||||
// The rotation axis is undefined but the angle not zero. This is not a
|
||||
// simple rotation.
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// Zero
|
||||
Some(Self::identity())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Creates an unit quaternion that corresponds to the local frame of an observer standing at the
|
||||
|
|
Loading…
Reference in New Issue