mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-30 19:48:11 +08:00
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:
co-authored by
Linda Zheng
Keavon Chambers
parent
4775a23c17
commit
0ad6e41a59
@@ -228,7 +228,7 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
name: "Project",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record<string, number>, mouseLocation: Point | null): void => {
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record<string, number>, mouseLocation?: Point): void => {
|
||||
if (mouseLocation != null) {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const closestPoint = JSON.parse(bezier.project(mouseLocation.x, mouseLocation.y));
|
||||
@@ -236,6 +236,20 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Local Extrema",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const dimensionColors = [COLORS.NON_INTERACTIVE.STROKE_1, COLORS.NON_INTERACTIVE.STROKE_2];
|
||||
const extrema: number[][] = JSON.parse(bezier.local_extrema());
|
||||
extrema.forEach((tValues, index) => {
|
||||
tValues.forEach((t) => {
|
||||
const point = JSON.parse(bezier.compute(t));
|
||||
drawPoint(context, point, 4, dimensionColors[index]);
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
@@ -14,20 +14,20 @@ struct Point {
|
||||
#[derive(Clone)]
|
||||
pub struct WasmBezier(Bezier);
|
||||
|
||||
/// Convert a `DVec2` into a `JsValue`
|
||||
/// Convert a `DVec2` into a `JsValue`.
|
||||
pub fn vec_to_point(p: &DVec2) -> JsValue {
|
||||
JsValue::from_serde(&serde_json::to_string(&Point { x: p.x, y: p.y }).unwrap()).unwrap()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl WasmBezier {
|
||||
/// Expect js_points to be a list of 3 pairs
|
||||
/// Expect js_points to be a list of 3 pairs.
|
||||
pub fn new_quadratic(js_points: &JsValue) -> WasmBezier {
|
||||
let points: [DVec2; 3] = js_points.into_serde().unwrap();
|
||||
WasmBezier(Bezier::from_quadratic_dvec2(points[0], points[1], points[2]))
|
||||
}
|
||||
|
||||
/// Expect js_points to be a list of 4 pairs
|
||||
/// Expect js_points to be a list of 4 pairs.
|
||||
pub fn new_cubic(js_points: &JsValue) -> WasmBezier {
|
||||
let points: [DVec2; 4] = js_points.into_serde().unwrap();
|
||||
WasmBezier(Bezier::from_cubic_dvec2(points[0], points[1], points[2], points[3]))
|
||||
@@ -102,4 +102,9 @@ impl WasmBezier {
|
||||
pub fn project(&self, x: f64, y: f64) -> JsValue {
|
||||
vec_to_point(&self.0.project(DVec2::new(x, y), 20, 1e-4, 3, 10))
|
||||
}
|
||||
|
||||
pub fn local_extrema(&self) -> JsValue {
|
||||
let local_extrema = self.0.local_extrema();
|
||||
JsValue::from_serde(&serde_json::to_string(&local_extrema).unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user