use super::generated::types::{Bivector, Rotor, Trivector, Vector};
use crate::ops::{RightComplement, Wedge};
use crate::scalar::Float;
impl<T: Float> Vector<T> {
#[inline]
pub fn dot(self, other: Self) -> T {
self.x() * other.x() + self.y() * other.y() + self.z() * other.z()
}
#[inline]
pub fn cross(self, other: Self) -> Self {
self.wedge(&other).dual()
}
#[inline]
pub fn normalized(&self) -> Self {
let n = self.norm();
Self::new(self.x() / n, self.y() / n, self.z() / n)
}
}
impl<T: Float> Bivector<T> {
#[inline]
pub fn dual(&self) -> Vector<T> {
self.right_complement()
}
#[inline]
pub fn normalized(&self) -> Self {
let n = self.norm();
Self::new(self.rz() / n, self.ry() / n, self.rx() / n)
}
}
impl<T: Float> Trivector<T> {
#[inline]
pub fn unit() -> Self {
Self::unit_ps()
}
#[inline]
pub fn value(&self) -> T {
self.ps()
}
}
impl<T: Float> Rotor<T> {
#[inline]
pub fn bivector(&self) -> Bivector<T> {
Bivector::new(self.rz(), self.ry(), self.rx())
}
#[inline]
pub fn from_angle_plane(angle: T, plane: Bivector<T>) -> Self {
let half = angle / T::TWO;
let (sin_half, cos_half) = (half.sin(), half.cos());
let b = plane.normalized();
Self::new_unchecked(
cos_half,
sin_half * b.rz(),
sin_half * b.ry(),
sin_half * b.rx(),
)
}
#[inline]
pub fn from_vectors(a: Vector<T>, b: Vector<T>) -> Self {
let a_norm = a.normalized();
let b_norm = b.normalized();
let dot = b_norm.dot(a_norm);
let wedge = b_norm.wedge(&a_norm);
let r = Self::new_unchecked(T::one() + dot, wedge.rz(), wedge.ry(), wedge.rx());
r.normalize()
}
#[inline]
pub fn compose(&self, other: Self) -> Self {
other * *self
}
#[inline]
pub fn slerp(&self, other: Self, t: T) -> Self {
let dot = self.s() * other.s()
+ self.rz() * other.rz()
+ self.ry() * other.ry()
+ self.rx() * other.rx();
let dot = if dot > T::one() {
T::one()
} else if dot < -T::one() {
-T::one()
} else {
dot
};
let theta = dot.acos();
if theta.abs() < T::epsilon() {
return Self::new_unchecked(
self.s() * (T::one() - t) + other.s() * t,
self.rz() * (T::one() - t) + other.rz() * t,
self.ry() * (T::one() - t) + other.ry() * t,
self.rx() * (T::one() - t) + other.rx() * t,
)
.normalize();
}
let sin_theta = theta.sin();
let s1 = ((T::one() - t) * theta).sin() / sin_theta;
let s2 = (t * theta).sin() / sin_theta;
Self::new_unchecked(
self.s() * s1 + other.s() * s2,
self.rz() * s1 + other.rz() * s2,
self.ry() * s1 + other.ry() * s2,
self.rx() * s1 + other.rx() * s2,
)
}
}