Bezier-rs: Add lookup table function for subpath and make it support euclidean parameterization (#1082)

* Add euclidean option for lut

* Add lut for subpath

* Fix rust formatting

* Fixed breakages caused by UI updates

* Code cleanup

* Make ProjectionOptions optional

---------

Co-authored-by: Rob Nadal <robnadal44@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Linda Zheng
2023-03-27 21:05:00 -04:00
committed by Keavon Chambers
parent d0ac86b713
commit 3733804d18
11 changed files with 99 additions and 37 deletions

View File

@@ -76,10 +76,11 @@ const bezierFeatures = {
},
"lookup-table": {
name: "Lookup Table",
callback: (bezier: WasmBezierInstance, options: Record<string, number>): string => bezier.compute_lookup_table(options.steps),
callback: (bezier: WasmBezierInstance, options: Record<string, number>, _: undefined): string => bezier.compute_lookup_table(options.steps, BEZIER_T_VALUE_VARIANTS[options.TVariant]),
demoOptions: {
Quadratic: {
inputOptions: [
bezierTValueVariantOptions,
{
min: 2,
max: 15,

View File

@@ -20,6 +20,20 @@ const subpathFeatures = {
callback: (subpath: WasmSubpathInstance, options: Record<string, number>, _: undefined): string => subpath.evaluate(options.t, SUBPATH_T_VALUE_VARIANTS[options.TVariant]),
inputOptions: [subpathTValueVariantOptions, tSliderOptions],
},
"lookup-table": {
name: "Lookup Table",
callback: (subpath: WasmSubpathInstance, options: Record<string, number>, _: undefined): string => subpath.compute_lookup_table(options.steps, SUBPATH_T_VALUE_VARIANTS[options.TVariant]),
inputOptions: [
subpathTValueVariantOptions,
{
min: 2,
max: 30,
step: 1,
default: 5,
variable: "steps",
},
],
},
project: {
name: "Project",
callback: (subpath: WasmSubpathInstance, _: Record<string, number>, mouseLocation?: [number, number]): string =>

View File

@@ -1,7 +1,7 @@
use crate::svg_drawing::*;
use crate::utils::parse_cap;
use bezier_rs::{ArcStrategy, ArcsOptions, Bezier, Identifier, ProjectionOptions, TValue};
use bezier_rs::{ArcStrategy, ArcsOptions, Bezier, Identifier, TValue, TValueType};
use glam::DVec2;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
@@ -156,9 +156,14 @@ impl WasmBezier {
wrap_svg_tag(content)
}
pub fn compute_lookup_table(&self, steps: usize) -> String {
pub fn compute_lookup_table(&self, steps: usize, t_variant: String) -> String {
let bezier = self.get_bezier_path();
let table_values: Vec<DVec2> = self.0.compute_lookup_table(Some(steps));
let tvalue_type = match t_variant.as_str() {
"Parametric" => TValueType::Parametric,
"Euclidean" => TValueType::Euclidean,
_ => panic!("Unexpected TValue string: '{}'", t_variant),
};
let table_values: Vec<DVec2> = self.0.compute_lookup_table(Some(steps), Some(tvalue_type));
let circles: String = table_values
.iter()
.map(|point| draw_circle(*point, 3., RED, 1.5, WHITE))
@@ -287,7 +292,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_t_value = self.0.project(DVec2::new(x, y), None);
let projected_point = self.0.evaluate(TValue::Parametric(projected_t_value));
let bezier = self.get_bezier_path();

View File

@@ -1,7 +1,7 @@
use crate::svg_drawing::*;
use crate::utils::{parse_cap, parse_join};
use bezier_rs::{Bezier, ManipulatorGroup, ProjectionOptions, Subpath, SubpathTValue};
use bezier_rs::{Bezier, ManipulatorGroup, Subpath, SubpathTValue, TValueType};
use glam::DVec2;
use std::fmt::Write;
@@ -99,6 +99,22 @@ impl WasmSubpath {
wrap_svg_tag(format!("{}{}", self.to_default_svg(), point_text))
}
pub fn compute_lookup_table(&self, steps: usize, t_variant: String) -> String {
let subpath = self.to_default_svg();
let tvalue_type = match t_variant.as_str() {
"GlobalParametric" => TValueType::Parametric,
"GlobalEuclidean" => TValueType::Euclidean,
_ => panic!("Unexpected TValue string: '{}'", t_variant),
};
let table_values: Vec<DVec2> = self.0.compute_lookup_table(Some(steps), Some(tvalue_type));
let circles: String = table_values
.iter()
.map(|point| draw_circle(*point, 3., RED, 1.5, WHITE))
.fold("".to_string(), |acc, circle| acc + &circle);
let content = format!("{subpath}{circles}");
wrap_svg_tag(content)
}
pub fn tangent(&self, t: f64, t_variant: String) -> String {
let t = parse_t_variant(&t_variant, t);
@@ -204,7 +220,7 @@ impl WasmSubpath {
}
pub fn project(&self, x: f64, y: f64) -> String {
let (segment_index, projected_t) = self.0.project(DVec2::new(x, y), ProjectionOptions::default()).unwrap();
let (segment_index, projected_t) = self.0.project(DVec2::new(x, y), None).unwrap();
let projected_point = self.0.evaluate(SubpathTValue::Parametric { segment_index, t: projected_t });
let subpath_svg = self.to_default_svg();

View File

@@ -10,7 +10,7 @@ pub const WHITE: &str = "white";
pub const GRAY: &str = "gray";
pub const RED: &str = "red";
pub const ORANGE: &str = "orange";
pub const PINK: &str = "pink";
// pub const PINK: &str = "pink";
pub const GREEN: &str = "green";
pub const NONE: &str = "none";