use crate::ops::Skew;
use math::{Matrix3, RealField, Vector3};
use num_traits::Zero;
pub trait Scale<T: Clone> {
fn scale(&mut self, s: [T; 3]);
fn uniform_scale(&mut self, s: T) {
self.scale([s.clone(), s.clone(), s]);
}
}
pub trait Rotate<T: RealField> {
fn rotate_by_matrix(&mut self, mtx: [[T; 3]; 3]);
fn rotate(&mut self, axis: [T; 3], theta: T) {
let u = Vector3::from(axis.clone());
let [x, y, z] = axis;
let id = Matrix3::identity();
let u_skew = u.skew();
let cos_theta = theta.clone().cos();
let u_v_t = {
let [a, b, c]: [T; 3] = (u * (T::one() - cos_theta.clone())).into();
Matrix3::from([
[x.clone() * a.clone(), x.clone() * b.clone(), x * c.clone()],
[y.clone() * a.clone(), y.clone() * b.clone(), y * c.clone()],
[z.clone() * a, z.clone() * b, z * c],
])
};
let mtx = id * cos_theta + u_skew * theta.sin() + u_v_t;
self.rotate_by_matrix(mtx.into());
}
fn rotate_by_vector(&mut self, e: [T; 3])
where
T: Zero,
{
let e = Vector3::from(e);
let theta = e.norm();
if theta == T::zero() {
return;
}
let u = e / theta.clone();
self.rotate(u.into(), theta);
}
}
pub trait Translate<T> {
fn translate(&mut self, t: [T; 3]);
}
pub trait Scaled<T>
where
Self: Sized,
{
fn scaled(self, s: [T; 3]) -> Self;
fn uniformly_scaled(self, s: T) -> Self;
}
pub trait Rotated<T>
where
Self: Sized,
{
fn rotated(self, u: [T; 3], theta: T) -> Self;
fn rotated_by_matrix(self, mtx: [[T; 3]; 3]) -> Self;
fn rotated_by_vector(self, e: [T; 3]) -> Self;
}
pub trait Translated<T>
where
Self: Sized,
{
fn translated(self, t: [T; 3]) -> Self;
}
impl<S, T: Copy> Scaled<T> for S
where
S: Scale<T> + Sized,
{
fn scaled(mut self, s: [T; 3]) -> Self {
self.scale(s);
self
}
fn uniformly_scaled(mut self, s: T) -> Self {
self.uniform_scale(s);
self
}
}
impl<S, T: RealField> Rotated<T> for S
where
S: Rotate<T> + Sized,
{
fn rotated(mut self, u: [T; 3], theta: T) -> Self {
self.rotate(u, theta);
self
}
fn rotated_by_matrix(mut self, mtx: [[T; 3]; 3]) -> Self {
self.rotate_by_matrix(mtx);
self
}
fn rotated_by_vector(mut self, e: [T; 3]) -> Self {
self.rotate_by_vector(e);
self
}
}
impl<S, T> Translated<T> for S
where
S: Translate<T> + Sized,
{
fn translated(mut self, t: [T; 3]) -> Self {
self.translate(t);
self
}
}