Skip to content

Commit

Permalink
Change the definition of severances for driving -- look for pedestria…
Browse files Browse the repository at this point in the history
…n shortcuts. #18
  • Loading branch information
dabreegster committed Aug 26, 2024
1 parent 89883e1 commit f406831
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 9 deletions.
2 changes: 1 addition & 1 deletion backend/src/fix_osm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn find_separate_sidewalks(map: &MapModel, duplicates_only: bool) -> GeoJson
}

// Along this road, if we project away, do we hit a footway?
for line in crate::heatmap::make_perpendicular_offsets(&r.linestring, 25.0, 15.0) {
for line in crate::scores::make_perpendicular_offsets(&r.linestring, 25.0, 15.0) {
for footway in footways.locate_in_envelope_intersecting(&line.envelope()) {
if footway.intersects(&line) {
features.push(r.to_gj(&map.graph.mercator));
Expand Down
9 changes: 4 additions & 5 deletions backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use crate::profiles::Profile;

mod disconnected;
mod fix_osm;
mod heatmap;
mod profiles;
mod route;
mod scores;

static START: Once = Once::new();

Expand Down Expand Up @@ -109,11 +109,10 @@ impl MapModel {
Ok(out)
}

#[wasm_bindgen(js_name = makeHeatmap)]
pub fn make_heatmap(&self, mode: String) -> Result<String, JsValue> {
#[wasm_bindgen(js_name = scoreDetours)]
pub fn score_detours(&self, mode: String) -> Result<String, JsValue> {
let mode = Mode::parse(&mode).map_err(err_to_js)?;
// TODO Different strategy for driving
let samples = heatmap::along_severances(self, mode);
let samples = scores::for_mode(self, mode);
let out = serde_json::to_string(&samples).map_err(err_to_js)?;
Ok(out)
}
Expand Down
27 changes: 25 additions & 2 deletions backend/src/heatmap.rs → backend/src/scores.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
use geo::{Coord, Densify, Line, LineString};
use geojson::FeatureCollection;
use graph::Mode;
use graph::{Direction, Mode};

use crate::{MapModel, RoadKind};

pub fn for_mode(map: &MapModel, mode: Mode) -> FeatureCollection {
match mode {
Mode::Foot => along_severances(map, mode),
// Makes less sense
Mode::Bicycle => along_severances(map, mode),
Mode::Car => non_crossable_roads(map, mode),
}
}

// Walk along severances. Every X meters, try to cross from one side to the other.
//
// We could focus where footways connect to severances, but that's probably a crossing. Ideally we
// want to find footpaths parallel(ish) to severances. If we had some kind of generalized edge
// bundling...
pub fn along_severances(map: &MapModel, mode: Mode) -> FeatureCollection {
fn along_severances(map: &MapModel, mode: Mode) -> FeatureCollection {
let mut requests = Vec::new();
for r in &map.graph.roads {
if map.road_kinds[r.id.0] == Some(RoadKind::Severance) {
Expand All @@ -21,6 +30,20 @@ pub fn along_severances(map: &MapModel, mode: Mode) -> FeatureCollection {
calculate(map, mode, requests)
}

// Look for roads cars can't cross. Ideally if there were was an entire component of non-driveable
// road, the endpoints would be used.
fn non_crossable_roads(map: &MapModel, mode: Mode) -> FeatureCollection {
let mut requests = Vec::new();
for r in &map.graph.roads {
// Filter out sidewalks; results are too noisy, and sidewalks are usually parallel to a
// driveable road
if r.access[mode] == Direction::None && !r.osm_tags.is("footway", "sidewalk") {
requests.push((r.linestring.0[0], *r.linestring.0.last().unwrap()));
}
}
calculate(map, mode, requests)
}

fn calculate(map: &MapModel, mode: Mode, requests: Vec<(Coord, Coord)>) -> FeatureCollection {
let mut samples = Vec::new();
let mut max_score = 0.0_f64;
Expand Down
2 changes: 1 addition & 1 deletion web/src/ScoreMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
let highestScore = 0;
function update(_mode: string) {
scoreGj = JSON.parse($model!.makeHeatmap($travelMode));
scoreGj = JSON.parse($model!.scoreDetours($travelMode));
highestScore = Math.round(
Math.max(...scoreGj.features.map((f) => f.properties.score)),
);
Expand Down

0 comments on commit f406831

Please sign in to comment.