use super::curve::*;
use super::basis::*;
use super::derivative::*;
use super::super::geo::*;
pub trait Normalize {
fn to_normal(point: &Self, tangent: &Self) -> Vec<f64>;
}
impl<Point: Coordinate2D> Normalize for Point {
#[inline]
fn to_normal(_point: &Self, tangent: &Self) -> Vec<f64> {
vec![-tangent.y(), tangent.x()]
}
}
pub trait NormalCurve : BezierCurve {
fn tangent_at_pos(&self, t: f64) -> Self::Point;
fn normal_at_pos(&self, t: f64) -> Self::Point;
}
impl<Curve: BezierCurve> NormalCurve for Curve
where
Curve::Point: Normalize,
{
fn tangent_at_pos(&self, t: f64) -> Curve::Point {
let w1 = self.start_point();
let (w2, w3) = self.control_points();
let w4 = self.end_point();
let t = if t == 0.0 { f64::EPSILON } else { t };
let t = if t == 1.0 { 1.0-f64::EPSILON } else { t };
let (d1, d2, d3) = derivative4(w1, w2, w3, w4);
let tangent = de_casteljau3(t, d1, d2, d3);
tangent
}
fn normal_at_pos(&self, t: f64) -> Curve::Point {
let w1 = self.start_point();
let (w2, w3) = self.control_points();
let w4 = self.end_point();
let t = if t == 0.0 { f64::EPSILON } else { t };
let t = if t == 1.0 { 1.0-f64::EPSILON } else { t };
let (d1, d2, d3) = derivative4(w1, w2, w3, w4);
let point = de_casteljau4(t, w1, w2, w3, w4);
let tangent = de_casteljau3(t, d1, d2, d3);
let normal = Curve::Point::to_normal(&point, &tangent);
Curve::Point::from_components(&normal)
}
}