Implement bezier local_extrema function (#693)

* Implement backend of extrema in bezier-rs

* Added extrema frontend

* Added extrema interface

* Wrapped extrema in filter function to remove points not on the curve

* Saved intermediate results while computing extrema

* Fixed extrema bug when a in cubic formula is 0

* Removed extra prints

* Fixed quadratic extrema regression

* Moved helper functions to utils file

* Fixed bug in solve linear

* Stylistic changes per review

* Sentence comments

Co-authored-by: Linda Zheng <thelindazheng@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Rob Nadal
2022-07-02 02:00:51 -04:00
committed by Keavon Chambers
co-authored by Linda Zheng Keavon Chambers
parent 3ab47418d2
commit c343aaa3ab
4 changed files with 119 additions and 38 deletions
+29 -2
View File
@@ -20,8 +20,8 @@ pub fn compute_abc_for_quadratic_through_points(start_point: DVec2, point_on_cur
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.
/// 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;
@@ -37,3 +37,30 @@ pub fn get_closest_point_in_lut(lut: &[DVec2], point: DVec2) -> (i32, f64) {
.min_by(|x, y| (&(x.1)).partial_cmp(&(y.1)).unwrap())
.unwrap()
}
/// Find the roots of the linear equation `ax + b`
pub fn solve_linear(a: f64, b: f64) -> Vec<f64> {
let mut roots = Vec::new();
if a != 0. {
roots.push(-b / a);
}
roots
}
/// Find the roots of the linear equation `ax^2 + bx + c`
/// Precompute the `discriminant` (`b^2 - 4ac`) and `two_times_a` arguments prior to calling this function for efficiency purposes
pub fn solve_quadratic(discriminant: f64, two_times_a: f64, b: f64, c: f64) -> Vec<f64> {
let mut roots = Vec::new();
if two_times_a != 0. {
if discriminant > 0. {
let root_discriminant = discriminant.sqrt();
roots.push((-b + root_discriminant) / (two_times_a));
roots.push((-b - root_discriminant) / (two_times_a));
} else if discriminant == 0. {
roots.push(-b / (two_times_a));
}
} else {
roots = solve_linear(b, c);
}
roots
}