nalgebra/geometry/rotation_interpolation.rs
1use crate::{RealField, Rotation2, Rotation3, SimdRealField, UnitComplex, UnitQuaternion};
2
3/// # Interpolation
4impl<T: SimdRealField> Rotation2<T> {
5 /// Spherical linear interpolation between two rotation matrices.
6 ///
7 /// # Examples:
8 ///
9 /// ```
10 /// # #[macro_use] extern crate approx;
11 /// # use nalgebra::geometry::Rotation2;
12 ///
13 /// let rot1 = Rotation2::new(std::f32::consts::FRAC_PI_4);
14 /// let rot2 = Rotation2::new(-std::f32::consts::PI);
15 ///
16 /// let rot = rot1.slerp(&rot2, 1.0 / 3.0);
17 ///
18 /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2);
19 /// ```
20 #[inline]
21 #[must_use]
22 pub fn slerp(&self, other: &Self, t: T) -> Self
23 where
24 T::Element: SimdRealField,
25 {
26 let c1 = UnitComplex::from(self.clone());
27 let c2 = UnitComplex::from(other.clone());
28 c1.slerp(&c2, t).into()
29 }
30}
31
32impl<T: SimdRealField> Rotation3<T> {
33 /// Spherical linear interpolation between two rotation matrices.
34 ///
35 /// Panics if the angle between both rotations is 180 degrees (in which case the interpolation
36 /// is not well-defined). Use `.try_slerp` instead to avoid the panic.
37 ///
38 /// # Examples:
39 ///
40 /// ```
41 /// # use nalgebra::geometry::Rotation3;
42 ///
43 /// let q1 = Rotation3::from_euler_angles(std::f32::consts::FRAC_PI_4, 0.0, 0.0);
44 /// let q2 = Rotation3::from_euler_angles(-std::f32::consts::PI, 0.0, 0.0);
45 ///
46 /// let q = q1.slerp(&q2, 1.0 / 3.0);
47 ///
48 /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0));
49 /// ```
50 #[inline]
51 #[must_use]
52 pub fn slerp(&self, other: &Self, t: T) -> Self
53 where
54 T: RealField,
55 {
56 let q1 = UnitQuaternion::from(self.clone());
57 let q2 = UnitQuaternion::from(other.clone());
58 q1.slerp(&q2, t).into()
59 }
60
61 /// Computes the spherical linear interpolation between two rotation matrices or returns `None`
62 /// if both rotations are approximately 180 degrees apart (in which case the interpolation is
63 /// not well-defined).
64 ///
65 /// # Arguments
66 /// * `self`: the first rotation to interpolate from.
67 /// * `other`: the second rotation to interpolate toward.
68 /// * `t`: the interpolation parameter. Should be between 0 and 1.
69 /// * `epsilon`: the value below which the sinus of the angle separating both rotations
70 /// must be to return `None`.
71 #[inline]
72 #[must_use]
73 pub fn try_slerp(&self, other: &Self, t: T, epsilon: T) -> Option<Self>
74 where
75 T: RealField,
76 {
77 let q1 = UnitQuaternion::from(self.clone());
78 let q2 = UnitQuaternion::from(other.clone());
79 q1.try_slerp(&q2, t, epsilon).map(|q| q.into())
80 }
81}