use glam::DVec2; /// Helper to perform the computation of a and c, where b is the provided point on the curve. /// Given the correct power of `t` and `(1-t)`, the computation is the same for quadratic and cubic cases. /// Relevant derivation and the definitions of a, b, and c can be found in [the projection identity section](https://pomax.github.io/bezierinfo/#abc) of Pomax's bezier curve primer. fn compute_abc_through_points(start_point: DVec2, point_on_curve: DVec2, end_point: DVec2, t_to_nth_power: f64, nth_power_of_one_minus_t: f64) -> [DVec2; 3] { let point_c_ratio = nth_power_of_one_minus_t / (t_to_nth_power + nth_power_of_one_minus_t); let c = point_c_ratio * start_point + (1. - point_c_ratio) * end_point; let ab_bc_ratio = (t_to_nth_power + nth_power_of_one_minus_t - 1.).abs() / (t_to_nth_power + nth_power_of_one_minus_t); let a = point_on_curve + (point_on_curve - c) / ab_bc_ratio; [a, point_on_curve, c] } /// Compute a, b, and c for a quadratic curve that fits the start, end and point on curve at `t`. /// The definition for the a, b, c points are defined in [the projection identity section](https://pomax.github.io/bezierinfo/#abc) of Pomax's bezier curve primer. pub fn compute_abc_for_quadratic_through_points(start_point: DVec2, point_on_curve: DVec2, end_point: DVec2, t: f64) -> [DVec2; 3] { let t_squared = t * t; let one_minus_t = 1. - t; let squared_one_minus_t = one_minus_t * one_minus_t; compute_abc_through_points(start_point, point_on_curve, end_point, t_squared, squared_one_minus_t) } /// Compute a, b, and c for a cubic curve that fits the start, end and point on curve at `t`. /// The definition for the a, b, c points are defined in [the projection identity section](https://pomax.github.io/bezierinfo/#abc) of Pomax's bezier curve primer. pub fn compute_abc_for_cubic_through_points(start_point: DVec2, point_on_curve: DVec2, end_point: DVec2, t: f64) -> [DVec2; 3] { let t_cubed = t * t * t; let one_minus_t = 1. - t; let cubed_one_minus_t = one_minus_t * one_minus_t * one_minus_t; compute_abc_through_points(start_point, point_on_curve, end_point, t_cubed, cubed_one_minus_t) } pub fn get_closest_point_in_lut(lut: &[DVec2], point: DVec2) -> (i32, f64) { lut.iter() .enumerate() .map(|(i, p)| (i as i32, point.distance(*p))) .min_by(|x, y| (&(x.1)).partial_cmp(&(y.1)).unwrap()) .unwrap() }