mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-08 02:28:12 +08:00
Bezier-rs: Add parametric evaluate and line intersect to subpath (#852)
* add slider to subpath component + change evaluate to take an enum Co-authored-by: Rob Nadal <RobNadal@users.noreply.github.com> wip - add intersect to subpath, TODO fix bug Co-authored-by: Rob Nadal <RobNadal@users.noreply.github.com> add unit tests to subpath intersections stress, testing Co-authored-by: Hannah Li <hannahli2010@gmail.com> * add parametric eval impl to subpath * add line intersection to subpath * Uncomment and #[ignore] disabled tests * Reorder a few imports * change subpath:eval slider to radio button * fixed bug with solve_cubic, fixed unit tests, improved intersection accuracy * fix failing test Co-authored-by: Hannah Li <hannahli2010@gmail.com> Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
committed by
Keavon Chambers
co-authored by
Rob Nadal
Hannah Li
Keavon Chambers
parent
9a4af4f87a
commit
52cc770a1e
@@ -1,9 +1,10 @@
|
||||
use bezier_rs::{ManipulatorGroup, Subpath};
|
||||
use crate::svg_drawing::*;
|
||||
|
||||
use bezier_rs::{Bezier, ComputeType, ManipulatorGroup, Subpath};
|
||||
|
||||
use glam::DVec2;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::svg_drawing::*;
|
||||
|
||||
/// Wrapper of the `Subpath` struct to be used in JS.
|
||||
#[wasm_bindgen]
|
||||
pub struct WasmSubpath(Subpath);
|
||||
@@ -54,6 +55,103 @@ impl WasmSubpath {
|
||||
|
||||
pub fn length(&self) -> String {
|
||||
let length_text = draw_text(format!("Length: {:.2}", self.0.length(None)), 5., 193., BLACK);
|
||||
format!("{}{}{}{}", SVG_OPEN_TAG, self.to_default_svg(), length_text, SVG_CLOSE_TAG)
|
||||
wrap_svg_tag(format!("{}{}", self.to_default_svg(), length_text))
|
||||
}
|
||||
|
||||
pub fn evaluate(&self, t: f64, compute_type: String) -> String {
|
||||
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 point_text = draw_circle(point, 4., RED, 1.5, WHITE);
|
||||
wrap_svg_tag(format!("{}{}", self.to_default_svg(), point_text))
|
||||
}
|
||||
|
||||
pub fn intersect_line_segment(&self, js_points: &JsValue) -> String {
|
||||
let points: [DVec2; 2] = js_points.into_serde().unwrap();
|
||||
let line = Bezier::from_linear_dvec2(points[0], points[1]);
|
||||
|
||||
let subpath_svg = self.to_default_svg();
|
||||
|
||||
let empty_string = String::new();
|
||||
let mut line_svg = String::new();
|
||||
line.to_svg(
|
||||
&mut line_svg,
|
||||
CURVE_ATTRIBUTES.to_string().replace(BLACK, RED),
|
||||
empty_string.clone(),
|
||||
empty_string.clone(),
|
||||
empty_string,
|
||||
);
|
||||
|
||||
let intersections_svg = self
|
||||
.0
|
||||
.intersections(&line, None, None)
|
||||
.iter()
|
||||
.map(|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}"));
|
||||
|
||||
wrap_svg_tag(format!("{subpath_svg}{line_svg}{intersections_svg}"))
|
||||
}
|
||||
|
||||
pub fn intersect_quadratic_segment(&self, js_points: &JsValue) -> String {
|
||||
let points: [DVec2; 3] = js_points.into_serde().unwrap();
|
||||
let line = Bezier::from_quadratic_dvec2(points[0], points[1], points[2]);
|
||||
|
||||
let subpath_svg = self.to_default_svg();
|
||||
|
||||
let empty_string = String::new();
|
||||
let mut line_svg = String::new();
|
||||
line.to_svg(
|
||||
&mut line_svg,
|
||||
CURVE_ATTRIBUTES.to_string().replace(BLACK, RED),
|
||||
empty_string.clone(),
|
||||
empty_string.clone(),
|
||||
empty_string,
|
||||
);
|
||||
|
||||
let intersections_svg = self
|
||||
.0
|
||||
.intersections(&line, None, None)
|
||||
.iter()
|
||||
.map(|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}"));
|
||||
|
||||
wrap_svg_tag(format!("{subpath_svg}{line_svg}{intersections_svg}"))
|
||||
}
|
||||
|
||||
pub fn intersect_cubic_segment(&self, js_points: &JsValue) -> String {
|
||||
let points: [DVec2; 4] = js_points.into_serde().unwrap();
|
||||
let line = Bezier::from_cubic_dvec2(points[0], points[1], points[2], points[3]);
|
||||
|
||||
let subpath_svg = self.to_default_svg();
|
||||
|
||||
let empty_string = String::new();
|
||||
let mut line_svg = String::new();
|
||||
line.to_svg(
|
||||
&mut line_svg,
|
||||
CURVE_ATTRIBUTES.to_string().replace(BLACK, RED),
|
||||
empty_string.clone(),
|
||||
empty_string.clone(),
|
||||
empty_string,
|
||||
);
|
||||
|
||||
let intersections_svg = self
|
||||
.0
|
||||
.intersections(&line, None, None)
|
||||
.iter()
|
||||
.map(|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}"));
|
||||
|
||||
wrap_svg_tag(format!("{subpath_svg}{line_svg}{intersections_svg}"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user