Bezier-rs: Add Euclidean parameterization to Bezier::evaluate (#828)

* Add enum to evaluate for differenciating compute type

* Add euclidean parameterization and update styling in the UI

Co-authored-by: Rob Nadal <robnadal44@gmail.com>

* Update usage of evaluate in graphite

* Add description

* Code review changes

* Update tests

* Improve ComputeType ergonomics

* Large code review/cleanup pass

Co-authored-by: Rob Nadal <robnadal44@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Hannah Li
2022-11-18 20:37:52 -08:00
committed by Keavon Chambers
co-authored by Rob Nadal Keavon Chambers
parent a220bfa759
commit 01a9724389
15 changed files with 341 additions and 276 deletions
@@ -1,5 +1,5 @@
use crate::svg_drawing::*;
use bezier_rs::{ArcStrategy, ArcsOptions, Bezier, ProjectionOptions};
use bezier_rs::{ArcStrategy, ArcsOptions, Bezier, ComputeType, ProjectionOptions};
use glam::DVec2;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
@@ -132,10 +132,14 @@ impl WasmBezier {
wrap_svg_tag(format!("{bezier}{}", draw_text(format!("Length: {:.2}", self.0.length(None)), TEXT_OFFSET_X, TEXT_OFFSET_Y, BLACK)))
}
pub fn evaluate(&self, t: f64) -> String {
pub fn evaluate(&self, t: f64, compute_type: String) -> String {
let bezier = self.get_bezier_path();
let point = &self.0.evaluate(t);
let content = format!("{bezier}{}", draw_circle(*point, 4., RED, 1.5, WHITE));
let point = match compute_type.as_str() {
"Euclidean" => self.0.evaluate(ComputeType::Euclidean(t)),
"Parametric" => self.0.evaluate(ComputeType::Parametric(t)),
_ => panic!("Unexpected ComputeType string: '{}'", compute_type),
};
let content = format!("{bezier}{}", draw_circle(point, 4., RED, 1.5, WHITE));
wrap_svg_tag(content)
}
@@ -173,7 +177,7 @@ impl WasmBezier {
let bezier = self.get_bezier_path();
let tangent_point = self.0.tangent(t);
let intersection_point = self.0.evaluate(t);
let intersection_point = self.0.evaluate(ComputeType::Parametric(t));
let tangent_end = intersection_point + tangent_point * SCALE_UNIT_VECTOR_FACTOR;
let content = format!(
@@ -189,7 +193,7 @@ impl WasmBezier {
let bezier = self.get_bezier_path();
let normal_point = self.0.normal(t);
let intersection_point = self.0.evaluate(t);
let intersection_point = self.0.evaluate(ComputeType::Parametric(t));
let normal_end = intersection_point + normal_point * SCALE_UNIT_VECTOR_FACTOR;
let content = format!(
@@ -205,7 +209,7 @@ impl WasmBezier {
let bezier = self.get_bezier_path();
let radius = 1. / self.0.curvature(t);
let normal_point = self.0.normal(t);
let intersection_point = self.0.evaluate(t);
let intersection_point = self.0.evaluate(ComputeType::Parametric(t));
let curvature_center = intersection_point + normal_point * radius;
@@ -269,7 +273,7 @@ impl WasmBezier {
pub fn project(&self, x: f64, y: f64) -> String {
let projected_t_value = self.0.project(DVec2::new(x, y), ProjectionOptions::default());
let projected_point = self.0.evaluate(projected_t_value);
let projected_point = self.0.evaluate(ComputeType::Parametric(projected_t_value));
let bezier = self.get_bezier_path();
let content = format!("{bezier}{}", draw_line(projected_point.x, projected_point.y, x, y, RED, 1.),);
@@ -285,7 +289,7 @@ impl WasmBezier {
.zip([RED, GREEN])
.flat_map(|(t_value_list, color)| {
t_value_list.iter().map(|&t_value| {
let point = self.0.evaluate(t_value);
let point = self.0.evaluate(ComputeType::Parametric(t_value));
draw_circle(point, 3., color, 1.5, WHITE)
})
})
@@ -320,7 +324,7 @@ impl WasmBezier {
let circles: String = inflections
.iter()
.map(|&t_value| {
let point = self.0.evaluate(t_value);
let point = self.0.evaluate(ComputeType::Parametric(t_value));
draw_circle(point, 3., RED, 1.5, WHITE)
})
.fold("".to_string(), |acc, circle| acc + &circle);
@@ -413,7 +417,7 @@ impl WasmBezier {
.intersect(&line, None)
.iter()
.map(|intersection_t| {
let point = &self.0.evaluate(*intersection_t);
let point = &self.0.evaluate(ComputeType::Parametric(*intersection_t));
draw_circle(*point, 4., RED, 1.5, WHITE)
})
.fold(String::new(), |acc, item| format!("{acc}{item}"));
@@ -433,7 +437,7 @@ impl WasmBezier {
.intersect(&quadratic, Some(error))
.iter()
.map(|intersection_t| {
let point = &self.0.evaluate(*intersection_t);
let point = &self.0.evaluate(ComputeType::Parametric(*intersection_t));
draw_circle(*point, 4., RED, 1.5, WHITE)
})
.fold(String::new(), |acc, item| format!("{acc}{item}"));
@@ -453,7 +457,7 @@ impl WasmBezier {
.intersect(&cubic, Some(error))
.iter()
.map(|intersection_t| {
let point = &self.0.evaluate(*intersection_t);
let point = &self.0.evaluate(ComputeType::Parametric(*intersection_t));
draw_circle(*point, 4., RED, 1.5, WHITE)
})
.fold(String::new(), |acc, item| format!("{acc}{item}"));
@@ -469,7 +473,7 @@ impl WasmBezier {
.self_intersections(Some(error))
.iter()
.map(|intersection_t| {
let point = &self.0.evaluate(intersection_t[0]);
let point = &self.0.evaluate(ComputeType::Parametric(intersection_t[0]));
draw_circle(*point, 4., RED, 1.5, WHITE)
})
.fold(bezier_curve_svg, |acc, item| format!("{acc}{item}"));