From cd58c0ee0665a116c9881781c1c5aa4e008ead88 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Sun, 27 Jul 2025 02:49:39 +0200 Subject: [PATCH] feat(math): added acceleration, curvature and arclength to the members of the Bezier curve. Split tangent and velocity functions. --- crates/comet_math/src/bezier.rs | 60 +++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/crates/comet_math/src/bezier.rs b/crates/comet_math/src/bezier.rs index b9034b7..6ca3ee3 100644 --- a/crates/comet_math/src/bezier.rs +++ b/crates/comet_math/src/bezier.rs @@ -12,6 +12,7 @@ impl Bezier { Self { points, degree } } + /// Returns the point at the position `t` along the curve. pub fn evaluate(&self, t: f32) -> V { let mut new_points = self.points.clone(); for i in 0..self.degree { @@ -22,7 +23,8 @@ impl Bezier { new_points[0].clone() } - pub fn evaluate_tangent(&self, t: f32) -> V { + /// Returns the velocity at the position `t` along the curve. + pub fn velocity(&self, t: f32) -> V { let n = self.degree as f32; let mut d_pts: Vec = self @@ -37,6 +39,60 @@ impl Bezier { } } - d_pts[0].clone().normalize() + d_pts[0].clone() + } + + /// Returns the tangent at the position `t` along the curve. + pub fn tangent(&self, t: f32) -> V { + self.velocity(t).normalize() + } + + /// Returns the acceleration at the position `t` along the curve. + pub fn acceleration(&self, t: f32) -> V { + let n = self.degree as f32; + + let mut dd_pts: Vec = self + .points + .windows(3) + .map(|w| (w[2] - w[1] * 2.0 + w[0]) * (n * (n - 1.0))) + .collect(); + + for i in 0..(self.degree - 2) { + for j in 0..(self.degree - 2 - i) { + dd_pts[j] = dd_pts[j].lerp(&dd_pts[j + 1], t); + } + } + + dd_pts[0].clone() + } + + /// Returns the curvature at the position `t` along the curve. + pub fn curvature(&self, t: f32) -> f32 { + let v = self.velocity(t); + let a = self.acceleration(t); + + let s2 = v.dot(&v); + if s2 == 0.0 { + return 0.0; + } + + let a_para = v.clone() * (a.dot(&v) / s2); + let a_perp = a - a_para; + + a_perp.length() / s2.sqrt().powi(2) + } + + /// Returns the arclength of the curve. + pub fn arclength(&self) -> f32 { + let mut length = 0.0; + let dt = 1.0 / 1000.0; + let mut prev = self.evaluate(0.0); + for i in 1..=1000 { + let t = i as f32 * dt; + let curr = self.evaluate(t); + length += (curr - prev).length(); + prev = curr; + } + length } }