Improve precision of UnitQuaternion::angle (#569)
The previous implementation had stability problems for small angles due to the behaviour of the arccosine it used. In particular, it needs a hack to handle "cosines" greater than 1 and the smallest obtainable nonzero angle for e.g. f32 is acos(1-2^-22) = 0.00069... These problems can be fixed by using an arctangent-based formula.
This commit is contained in:
parent
b4d800f3e2
commit
74aefd9c23
|
@ -602,13 +602,7 @@ impl<N: Real> UnitQuaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn angle(&self) -> N {
|
pub fn angle(&self) -> N {
|
||||||
let w = self.quaternion().scalar().abs();
|
let w = self.quaternion().scalar().abs();
|
||||||
|
self.quaternion().imag().norm().atan2(w) * ::convert(2.0f64)
|
||||||
// Handle inaccuracies that make break `.acos`.
|
|
||||||
if w >= N::one() {
|
|
||||||
N::zero()
|
|
||||||
} else {
|
|
||||||
w.acos() * ::convert(2.0f64)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The underlying quaternion.
|
/// The underlying quaternion.
|
||||||
|
|
Loading…
Reference in New Issue