neco_edge_routing_wasm/
lib.rs1use js_sys::{Array, Object, Reflect};
4use neco_edge_routing::{route, PathKind, RouteRequest, RouteStyle};
5use wasm_bindgen::prelude::*;
6
7#[wasm_bindgen]
9pub fn route_edge(
10 style: &str,
11 from_x: f64,
12 from_y: f64,
13 to_x: f64,
14 to_y: f64,
15) -> Result<JsValue, JsValue> {
16 let request = RouteRequest {
17 from: (from_x, from_y),
18 to: (to_x, to_y),
19 from_tangent: (1.0, 0.0),
20 to_tangent: (-1.0, 0.0),
21 style: parse_style(style)?,
22 };
23
24 let path = route(&request).map_err(|error| JsValue::from_str(&error.to_string()))?;
25 path_to_js(style, path)
26}
27
28fn parse_style(style: &str) -> Result<RouteStyle, JsValue> {
29 match style {
30 "bezier" => Ok(RouteStyle::Bezier { curvature: 0.25 }),
31 "orthogonal" => Ok(RouteStyle::Orthogonal {
32 corner_radius: 16.0,
33 }),
34 "spline" => Ok(RouteStyle::Spline),
35 "nurbs" => Ok(RouteStyle::Nurbs { degree: 3 }),
36 other => Err(JsValue::from_str(&format!(
37 "unsupported route style: {other}"
38 ))),
39 }
40}
41
42fn path_to_js(style: &str, path: neco_edge_routing::PathData) -> Result<JsValue, JsValue> {
43 let object = Object::new();
44 Reflect::set(
45 &object,
46 &JsValue::from_str("style"),
47 &JsValue::from_str(style),
48 )?;
49 Reflect::set(
50 &object,
51 &JsValue::from_str("kind"),
52 &JsValue::from_str(kind_name(&path.kind)),
53 )?;
54
55 let points = Array::new();
56 for (x, y) in path.points {
57 let point = Object::new();
58 Reflect::set(&point, &JsValue::from_str("x"), &JsValue::from_f64(x))?;
59 Reflect::set(&point, &JsValue::from_str("y"), &JsValue::from_f64(y))?;
60 points.push(&point);
61 }
62 Reflect::set(&object, &JsValue::from_str("points"), &points)?;
63
64 if let PathKind::Nurbs { knots, weights } = path.kind {
65 Reflect::set(&object, &JsValue::from_str("knots"), &vec_to_js(knots))?;
66 Reflect::set(&object, &JsValue::from_str("weights"), &vec_to_js(weights))?;
67 }
68
69 Ok(JsValue::from(object))
70}
71
72fn vec_to_js(values: Vec<f64>) -> JsValue {
73 let array = Array::new();
74 for value in values {
75 array.push(&JsValue::from_f64(value));
76 }
77 JsValue::from(array)
78}
79
80fn kind_name(kind: &PathKind) -> &'static str {
81 match kind {
82 PathKind::Polyline => "polyline",
83 PathKind::Cubic => "cubic",
84 PathKind::Quadratic => "quadratic",
85 PathKind::Nurbs { .. } => "nurbs",
86 }
87}