use super::*;
mod cardinal;
mod trajectory;
pub use cardinal::*;
pub use trajectory::*;
pub trait Curve<F> {
fn chain(&self, resolution: usize) -> Chain<F>
where
F: Float;
}
pub trait CubicHermiteCurve<T> {
fn intervals(&self) -> Vec<CurveInterval<T>>;
fn chain(&self, resolution: usize) -> Chain<T>
where
T: Float,
{
let intervals = self.intervals();
let mut vertices = Vec::with_capacity(resolution * intervals.len());
let mut intervals = intervals.into_iter();
if let Some(interval) = intervals.next() {
let step = 1. / resolution as f32;
for i in 0..=resolution {
let t = T::from_f32(step * i as f32);
vertices.push(interval.get(t));
}
}
for interval in intervals {
let step = 1. / resolution as f32;
for i in 1..=resolution {
let t = T::from_f32(step * i as f32);
vertices.push(interval.get(t));
}
}
Chain { vertices }
}
}
#[derive(Debug)]
pub struct CurveInterval<T> {
pub point_start: vec2<T>,
pub point_end: vec2<T>,
pub tangent_start: vec2<T>,
pub tangent_end: vec2<T>,
}
impl<F: Float> CurveInterval<F> {
pub fn get(&self, t: F) -> vec2<F> {
let p0 = self.point_start;
let p1 = self.point_end;
let m0 = self.tangent_start;
let m1 = self.tangent_end;
let t2 = t * t; let t3 = t2 * t; let one = F::ONE;
let two = one + F::ONE;
let three = two + F::ONE;
p0 * (two * t3 - three * t2 + one)
+ m0 * (t3 - two * t2 + t)
+ p1 * (-two * t3 + three * t2)
+ m1 * (t3 - t2)
}
}