use crate::math::{Pose, Real, Rotation, Vector};
#[inline]
pub(crate) fn rotate_vec(q: &Rotation, v: Vector) -> Vector {
#[cfg(feature = "dim2")]
{
q.transform_vector(v)
}
#[cfg(feature = "dim3")]
{
*q * v
}
}
#[inline]
pub(crate) fn inv_rotate_vec(q: &Rotation, v: Vector) -> Vector {
#[cfg(feature = "dim2")]
{
q.inverse_transform_vector(v)
}
#[cfg(feature = "dim3")]
{
q.inverse() * v
}
}
#[inline]
pub(crate) fn nlerp(q1: &Rotation, q2: &Rotation, t: Real) -> Rotation {
#[cfg(feature = "dim2")]
{
q1.lerp(*q2, t).normalize()
}
#[cfg(feature = "dim3")]
{
let q1 = if q1.dot(*q2) < 0.0 { -*q1 } else { *q1 };
(q1 * (1.0 - t) + *q2 * t).normalize()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(
feature = "serde-serialize",
derive(serde::Serialize, serde::Deserialize)
)]
pub struct Sweep {
pub local_center: Vector,
pub c1: Vector,
pub c2: Vector,
pub q1: Rotation,
pub q2: Rotation,
}
impl Sweep {
pub fn from_poses(start: &Pose, end: &Pose, local_center: Vector) -> Self {
Self {
local_center,
c1: start.transform_point(local_center),
c2: end.transform_point(local_center),
q1: start.rotation,
q2: end.rotation,
}
}
pub fn constant(pose: &Pose, local_center: Vector) -> Self {
Self::from_poses(pose, pose, local_center)
}
pub fn transform_at(&self, t: Real) -> Pose {
let q = nlerp(&self.q1, &self.q2, t);
let p = self.c1.lerp(self.c2, t) - rotate_vec(&q, self.local_center);
Pose::from_parts(p, q)
}
pub fn final_transform(&self) -> Pose {
let p = self.c2 - rotate_vec(&self.q2, self.local_center);
Pose::from_parts(p, self.q2)
}
pub fn shifted(&self, origin: Vector) -> Self {
Self {
local_center: self.local_center,
c1: self.c1 - origin,
c2: self.c2 - origin,
q1: self.q1,
q2: self.q2,
}
}
}