Skip to content

Commit

Permalink
Detect and remove disconnected roads upfront
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Jan 18, 2025
1 parent 807f619 commit ed90709
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ tool):

```
function json_diff {
cat $1 | jq > /tmp/before.json
git show HEAD^:./$1 | jq > /tmp/after.json
cat $1 | jq > /tmp/after.json
git show HEAD^:./$1 | jq > /tmp/before.json
meld /tmp/before.json /tmp/after.json
}
Expand Down
31 changes: 27 additions & 4 deletions backend/Cargo.lock

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

1 change: 1 addition & 0 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ utils = { git = "https://github.com/a-b-street/utils", features = ["serde"] }
wasm-bindgen = "0.2.87"
web-sys = { version = "0.3.64", features = ["console"] }
web-time = "1.0.0"
petgraph = "0.7.1"

# For local development, build dependencies in release mode once, but otherwise
# use dev profile and avoid wasm-opt.
Expand Down
43 changes: 41 additions & 2 deletions backend/src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
use anyhow::Result;
use geo::{Coord, LineInterpolatePoint, LineString, Polygon};
use osm_reader::{Element, NodeID};
use petgraph::graphmap::UnGraphMap;
use rstar::{primitives::GeomWithData, RTree};
use utils::Tags;
use utils::{
osm2graph::{EdgeID, Graph},
Tags,
};

use crate::{
impact::Impact, Direction, FilterKind, Intersection, IntersectionID, MapModel, Road, RoadID,
Expand Down Expand Up @@ -98,7 +102,8 @@ pub fn create_from_osm(
})?;

info!("Splitting {} ways into edges", highways.len());
let mut graph = utils::osm2graph::Graph::from_scraped_osm(node_mapping, highways);
let mut graph = Graph::from_scraped_osm(node_mapping, highways);
remove_disconnected_components(&mut graph);
graph.compact_ids();

// Copy all the fields
Expand Down Expand Up @@ -321,3 +326,37 @@ fn parse_maxspeed_mph(tags: &Tags) -> Option<f64> {
}
None
}

// TODO Consider upstreaming to osm2graph
fn remove_disconnected_components(graph: &mut Graph) {
let mut scc_graph: UnGraphMap<utils::osm2graph::IntersectionID, EdgeID> = UnGraphMap::new();
for edge in graph.edges.values() {
scc_graph.add_edge(edge.src, edge.dst, edge.id);
}

let mut components: Vec<BTreeSet<EdgeID>> = Vec::new();
for nodes in petgraph::algo::kosaraju_scc(&scc_graph) {
components.push(nodes_to_edges(graph, nodes));
}
components.sort_by_key(|scc| scc.len());
components.reverse();

let mut remove_edges = BTreeSet::new();
// Keep only the largest component
for scc in components.into_iter().skip(1) {
info!("Removing component with only {} roads", scc.len());
remove_edges.extend(scc);
}

info!("Removing {} disconnected roads", remove_edges.len());
graph.remove_edges(remove_edges);
}

// Note this only works for connected components of nodes!
fn nodes_to_edges(graph: &Graph, nodes: Vec<utils::osm2graph::IntersectionID>) -> BTreeSet<EdgeID> {
let mut edges = BTreeSet::new();
for i in nodes {
edges.extend(graph.intersections[&i].edges.clone());
}
edges
}
2 changes: 1 addition & 1 deletion tests/output/bristol_east.geojson

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/output/bristol_west.geojson

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/output/strasbourg.geojson

Large diffs are not rendered by default.

0 comments on commit ed90709

Please sign in to comment.