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:
Simon Puchert 2019-03-31 10:32:34 +02:00 committed by Sébastien Crozet
parent b4d800f3e2
commit 74aefd9c23
1 changed files with 1 additions and 7 deletions

View File

@ -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.