Skip to content

Commit

Permalink
Remove unused contextual layers from the sketch page
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Sep 25, 2023
1 parent 8ec65bb commit e67d03a
Show file tree
Hide file tree
Showing 17 changed files with 4 additions and 608 deletions.
2 changes: 0 additions & 2 deletions route_info/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions route_info/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ geojson = "0.24.1"
geom = { git = "https://github.com/a-b-street/abstreet" }
log = "0.4.17"
osm2streets = { git = "https://github.com/a-b-street/osm2streets" }
petgraph = "0.6.3"
serde = "1.0.163"
serde-wasm-bindgen = "0.5.0"
wasm-bindgen = "0.2.84"
web-sys = "0.3.62"
125 changes: 2 additions & 123 deletions route_info/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ mod map_matching;

use std::collections::BTreeSet;

use geojson::{feature::Id, Feature};
use geom::{Distance, FindClosest, Pt2D};
use osm2streets::{Filter, IntersectionID, StreetNetwork};
use serde::Deserialize;
use geom::{Distance, FindClosest};
use osm2streets::{IntersectionID, StreetNetwork};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
Expand Down Expand Up @@ -82,127 +80,8 @@ impl RouteInfo {
.collect::<BTreeSet<_>>();
abstutil::plain_list_names(road_names)
}

/// Given the JSON waypoints array produced by route-snapper, generate GeoJSON LineStrings
/// covering each segment of the route where `speed_limit` (in mph, rounded) is defined.
/// Freehand and unknown segments are not returned.
#[wasm_bindgen(js_name = speedLimitForRoute)]
pub fn speed_limit_for_route(&self, raw_waypoints: JsValue) -> Result<String, JsValue> {
let raw_waypoints: Vec<RawRouteWaypoint> = serde_wasm_bindgen::from_value(raw_waypoints)?;
let waypoints = self.parse_waypoints(raw_waypoints).map_err(err_to_js)?;

let mut features = Vec::new();
for pair in waypoints.windows(2) {
if let (Waypoint::Snapped(_, i1), Waypoint::Snapped(_, i2)) = (&pair[0], &pair[1]) {
if let Some(path) = self.geometric_path(*i1, *i2) {
// Add one LineString per Road where speed_limit is defined.
// We could try to glue together contiguous LineStrings where the speed is the
// same, but there's no benefit.
for (r, _) in path {
let road = &self.network.roads[&r];
if let Some(speed) = road.speed_limit {
let mut feature = Feature::from(
road.reference_line
.to_geojson(Some(&self.network.gps_bounds)),
);
feature.id = Some(Id::Number((1 + features.len()).into()));
feature.set_property("speed_limit", speed.to_miles_per_hour().round());
features.push(feature);
}
}
} else {
return Err(err_to_js("no path between two waypoints"));
}
}
}

let gj = geojson::GeoJson::from(geojson::FeatureCollection {
bbox: None,
features,
foreign_members: None,
});
Ok(abstutil::to_json(&gj))
}

/// Return GeoJSON LineStrings with all known `speed_limit`s.
#[wasm_bindgen(js_name = allSpeedLimits)]
pub fn all_speed_limits(&self) -> Result<String, JsValue> {
let mut features = Vec::new();
for r in self.network.roads.values() {
if r.is_light_rail() {
continue;
}
if let Some(speed) = r.speed_limit {
let mut feature =
Feature::from(r.reference_line.to_geojson(Some(&self.network.gps_bounds)));
feature.set_property("speed_limit", speed.to_miles_per_hour().round());
feature.id = Some(Id::Number((1 + features.len()).into()));
features.push(feature);
}
}
let gj = geojson::GeoJson::from(geojson::FeatureCollection {
bbox: None,
features,
foreign_members: None,
});
Ok(abstutil::to_json(&gj))
}

/// Return 4 GeoJSON layers for rendering lane details, limited to just roads along a route.
/// Due to encoding limitations, returns it as a JSON string containing 4 more JSON strings.
/// The order returned is [lane polygons, lane markings, intersection polygons, intersection
/// markings], and the properties of each feature isn't documented anywhere clearly yet.
#[wasm_bindgen(js_name = renderLaneDetailsForRoute)]
pub fn render_lane_details_for_route(&self, raw_waypoints: JsValue) -> Result<String, JsValue> {
let raw_waypoints: Vec<RawRouteWaypoint> = serde_wasm_bindgen::from_value(raw_waypoints)?;
let waypoints = self.parse_waypoints(raw_waypoints).map_err(err_to_js)?;

let mut roads = BTreeSet::new();
let mut intersections = BTreeSet::new();

for pair in waypoints.windows(2) {
if let (Waypoint::Snapped(_, i1), Waypoint::Snapped(_, i2)) = (&pair[0], &pair[1]) {
if let Some(path) = self.geometric_path(*i1, *i2) {
for (r, _) in path {
let road = &self.network.roads[&r];
roads.insert(r);
intersections.insert(road.src_i);
intersections.insert(road.dst_i);
}
}
}
}
let filter = Filter::Filtered(roads, intersections);

Ok(abstutil::to_json(&vec![
self.network
.to_lane_polygons_geojson(&filter)
.map_err(err_to_js)?,
self.network
.to_lane_markings_geojson(&filter)
.map_err(err_to_js)?,
self.network.to_geojson(&filter).map_err(err_to_js)?,
self.network
.to_intersection_markings_geojson(&filter)
.map_err(err_to_js)?,
]))
}
}

fn err_to_js<E: std::fmt::Display>(err: E) -> JsValue {
JsValue::from_str(&err.to_string())
}

// Defined by https://github.com/dabreegster/route_snapper/blob/main/route-snapper/src/lib.rs. Too
// simple to take a dependency.
#[derive(Deserialize)]
struct RawRouteWaypoint {
lon: f64,
lat: f64,
snapped: bool,
}

enum Waypoint {
Free(Pt2D),
Snapped(Pt2D, IntersectionID),
}
57 changes: 2 additions & 55 deletions route_info/src/map_matching.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use anyhow::Result;
use geom::{Distance, LonLat, Pt2D};
use osm2streets::{Direction, IntersectionID, RoadID};
use petgraph::prelude::DiGraphMap;
use geom::{LonLat, Pt2D};

use super::{RawRouteWaypoint, RouteInfo, Waypoint};
use super::RouteInfo;

impl RouteInfo {
/// Extract the endpoints of a LineString in map-space.
Expand All @@ -27,55 +25,4 @@ impl RouteInfo {
bail!("not a LineString");
}
}

/// Interpret waypoints from route-snapper in the context of this StreetNetwork.
pub(crate) fn parse_waypoints(
&self,
raw_waypoints: Vec<RawRouteWaypoint>,
) -> Result<Vec<Waypoint>> {
// Naively match snapped waypoints up with this StreetNetwork's intersections. If
// route-snapper is using a graph built from the same version of OSM data as the current
// StreetNetwork, everything should be fine.
let threshold = Distance::meters(100.0);
let mut waypoints = Vec::new();
for waypt in raw_waypoints {
let pt = LonLat::new(waypt.lon, waypt.lat).to_pt(&self.network.gps_bounds);
if waypt.snapped {
let (i, _) = self
.closest_intersection
.closest_pt(pt, threshold)
.ok_or_else(|| anyhow!("no intersection close to waypoint"))?;
waypoints.push(Waypoint::Snapped(pt, i));
} else {
waypoints.push(Waypoint::Free(pt));
}
}
Ok(waypoints)
}

/// Calculates a path between intersections, ignoring all semantics of the roads (lane types,
/// direction) just like route-snapper. The result says which direction to cross each road.
pub fn geometric_path(
&self,
from: IntersectionID,
to: IntersectionID,
) -> Option<Vec<(RoadID, Direction)>> {
let mut graph = DiGraphMap::new();
for r in self.network.roads.values() {
graph.add_edge(r.src_i, r.dst_i, (r.id, Direction::Fwd));
graph.add_edge(r.dst_i, r.src_i, (r.id, Direction::Back));
}
let (_, path) = petgraph::algo::astar(
&graph,
from,
|i| i == to,
|(_, _, (r, _))| self.network.roads[r].untrimmed_length(),
|_| Distance::ZERO,
)?;
let roads: Vec<(RoadID, Direction)> = path
.windows(2)
.map(|pair| *graph.edge_weight(pair[0], pair[1]).unwrap())
.collect();
Some(roads)
}
}
2 changes: 0 additions & 2 deletions src/lib/forms/FormV1.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { FormElement, Radio, SecondaryButton, TextArea } from "lib/govuk";
import { prettyPrintMeters } from "lib/maplibre";
import { gjScheme, routeInfo } from "stores";
import RouteInfoLayers from "./RouteInfoLayers.svelte";
export let id: number;
export let name: string;
Expand Down Expand Up @@ -52,5 +51,4 @@

{#if length_meters}
<p>Length: {prettyPrintMeters(length_meters)}</p>
<RouteInfoLayers {id} />
{/if}
30 changes: 0 additions & 30 deletions src/lib/forms/RouteInfoLayers.svelte

This file was deleted.

32 changes: 0 additions & 32 deletions src/lib/layers/ContextualLayers.svelte

This file was deleted.

55 changes: 0 additions & 55 deletions src/lib/layers/LaneDetails.svelte

This file was deleted.

Loading

0 comments on commit e67d03a

Please sign in to comment.