Skip to content

Commit

Permalink
Add two new experimental APIs for more stateless usage
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Oct 17, 2024
1 parent 9603d48 commit bb7618a
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ changes.

## Unreleased

- Add two new experimental stateless APIs. Do not use yet.

## 0.4.3

- Upgrade Rust geo dependencies
Expand Down
80 changes: 80 additions & 0 deletions route-snapper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,79 @@ impl JsRouteSnapper {
self.previous_states.remove(0);
}
}

// TODO If this new style works well, either ditch the old stateful API entirely, or export a
// different stateless class
/// Experimental new stateless API. From a list of waypoints, return a Feature with the full
/// geometry and properties. Note this internally modifies state.
#[wasm_bindgen(js_name = calculateRoute)]
pub fn calculate_route(&mut self, raw_waypoints: JsValue) -> Result<String, JsValue> {
self.clear_state();

let waypoints: Vec<NewRouteWaypoint> = serde_wasm_bindgen::from_value(raw_waypoints)?;
for waypt in waypoints {
let pt = Coord {
x: waypt.point[0],
y: waypt.point[1],
};
if waypt.snapped {
if let Some(node) = self.mouseover_node(pt) {
self.route
.add_waypoint(&self.router, Waypoint::Snapped(node));
} else {
return Err(JsValue::from_str("A waypoint didn't snap"));
}
} else {
self.route.add_waypoint(&self.router, Waypoint::Free(pt));
}
}

match self.to_final_feature() {
Some(gj) => Ok(gj),
None => Err(JsValue::from_str("no route")),
}
}

/// Experimental new stateless API. From exactly two waypoints, return a list of extra
/// intermediate snappable nodes. Note this internally modifies state.
#[wasm_bindgen(js_name = getExtraNodes)]
pub fn get_extra_nodes(
&mut self,
raw_waypt1: JsValue,
raw_waypt2: JsValue,
) -> Result<String, JsValue> {
self.clear_state();

let waypt1: NewRouteWaypoint = serde_wasm_bindgen::from_value(raw_waypt1)?;
let waypt2: NewRouteWaypoint = serde_wasm_bindgen::from_value(raw_waypt2)?;
// TODO Dedupe code, if this all works out
for waypt in [waypt1, waypt2] {
let pt = Coord {
x: waypt.point[0],
y: waypt.point[1],
};
if waypt.snapped {
if let Some(node) = self.mouseover_node(pt) {
self.route
.add_waypoint(&self.router, Waypoint::Snapped(node));
} else {
return Err(JsValue::from_str("A waypoint didn't snap"));
}
} else {
self.route.add_waypoint(&self.router, Waypoint::Free(pt));
}
}

let mut extra_nodes: Vec<[f64; 2]> = Vec::new();
for entry in &self.route.full_path {
// TODO Skip the first and last, so we only show intermediate nodes?
if let PathEntry::SnappedPoint(node) = entry {
let pt = self.router.map.node(*node);
extra_nodes.push([pt.x, pt.y]);
}
}
serde_json::to_string(&extra_nodes).map_err(err_to_js)
}
}

impl JsRouteSnapper {
Expand Down Expand Up @@ -1146,6 +1219,13 @@ struct RouteWaypoint {
snapped: bool,
}

// TODO A variation of RouteWaypoint that's easier to make work with MapLibre markers
#[derive(Deserialize)]
struct NewRouteWaypoint {
point: [f64; 2],
snapped: bool,
}

// Per https://datatracker.ietf.org/doc/html/rfc7946#section-11.2, 6 decimal places (10cm) is
// plenty of precision
fn trim_lon_lat(x: f64) -> f64 {
Expand Down

0 comments on commit bb7618a

Please sign in to comment.