Skip to content

Commit

Permalink
Get rid of the TrimDeadendCycleways transformation
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Apr 4, 2024
1 parent a7a53ad commit 3912a24
Show file tree
Hide file tree
Showing 23 changed files with 26,510 additions and 10,872 deletions.
4 changes: 0 additions & 4 deletions docs/how_it_works.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ But it's also confusing in a few ways:

Specific transformations are described below in no particular order. (But that's confusing; they should be)

### TrimDeadendCycleways

We sometimes wind up with short dead-end roads that're nice to remove. One example is short service roads -- I recall these happening in Seattle, maybe related to how driveways are tagged there. Another is also a bit Seattle-specific -- when we try to import separate cyclepaths but not footways there, there are some dangling "stubs" of cycleway leftover sometimes.

### SnapCycleways (experimental)

See <https://github.com/a-b-street/osm2streets/pull/61> for now
Expand Down
1 change: 0 additions & 1 deletion osm2streets-js/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ impl JsStreetNetwork {
}
if input.sidepath_zipping_experiment {
transformations.push(Transformation::ZipSidepaths);
transformations.push(Transformation::TrimDeadendCycleways);
transformations.push(Transformation::CollapseDegenerateIntersections);
}
if input.debug_each_step {
Expand Down
3 changes: 1 addition & 2 deletions osm2streets/src/operations/zip_sidepath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ impl Sidepath {
}

// After this transformation, we should run CollapseDegenerateIntersections to handle the
// intersection where the side road originally crossed the sidepath, and TrimDeadendCycleways
// to clean up any small cycle connection roads.
// intersection where the side road originally crossed the sidepath
}
}

Expand Down
43 changes: 1 addition & 42 deletions osm2streets/src/transform/collapse_intersections.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use std::collections::BTreeSet;

use anyhow::Result;

use geom::Distance;

use crate::{IntersectionID, IntersectionKind, Placement, Road, StreetNetwork};
use crate::{IntersectionID, Placement, Road, StreetNetwork};

/// Collapse degenerate intersections:
/// - between two cycleways
Expand Down Expand Up @@ -89,40 +85,3 @@ fn should_collapse(road1: &Road, road2: &Road) -> Result<()> {

Ok(())
}

const SHORT_THRESHOLD: Distance = Distance::const_meters(30.0);

/// Some cycleways intersect footways with detailed curb mapping. The current rules for figuring
/// out which walking paths also allow bikes are imperfect, so we wind up with short dead-end
/// "stubs." Trim those.
///
/// Also do the same thing for extremely short dead-end service roads.
pub fn trim_deadends(streets: &mut StreetNetwork) {
let mut remove_roads = BTreeSet::new();
let mut remove_intersections = BTreeSet::new();
for i in streets.intersections.values() {
let roads = streets.roads_per_intersection(i.id);
if roads.len() != 1 || i.kind == IntersectionKind::MapEdge {
continue;
}
let road = &roads[0];
if road.untrimmed_length() < SHORT_THRESHOLD && (road.is_cycleway() || road.is_service()) {
remove_roads.insert(roads[0].id);
remove_intersections.insert(i.id);
}
}

for r in remove_roads {
streets.remove_road(r);
}
for i in remove_intersections {
streets.remove_intersection(i);
}

// It's possible we need to do this in a fixed-point until there are no changes, but meh.
// Results look good so far.

// We may have created orphaned intersections. Clean up here.
// TODO Anywhere calling remove_road potentially causes this too
streets.intersections.retain(|_, i| !i.roads.is_empty());
}
9 changes: 0 additions & 9 deletions osm2streets/src/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ mod sausage_links;

/// An in-place transformation of a `StreetNetwork`.
pub enum Transformation {
TrimDeadendCycleways,
ZipSidepaths,
RemoveDisconnectedRoads,
CollapseShortRoads,
Expand All @@ -24,7 +23,6 @@ impl Transformation {
/// Useful for test cases and small clipped areas. Doesn't remove disconnected roads.
pub fn standard_for_clipped_areas() -> Vec<Self> {
vec![
Transformation::TrimDeadendCycleways,
Transformation::CollapseSausageLinks,
Transformation::CollapseShortRoads,
Transformation::CollapseDegenerateIntersections,
Expand All @@ -44,9 +42,6 @@ impl Transformation {
if false {
let mut prepend = vec![
Transformation::ZipSidepaths,
// More dead-ends can be created after zipping sidepaths. But also, zipping can be
// easier to do after trimming some dead-ends. So... just run it twice.
Transformation::TrimDeadendCycleways,
Transformation::RemoveDisconnectedRoads,
];
prepend.extend(list);
Expand All @@ -60,7 +55,6 @@ impl Transformation {

fn name(&self) -> &'static str {
match self {
Transformation::TrimDeadendCycleways => "trim dead-end cycleways",
Transformation::ZipSidepaths => "zip parallel sidepaths",
Transformation::RemoveDisconnectedRoads => "remove disconnected roads",
Transformation::CollapseShortRoads => "collapse short roads",
Expand All @@ -73,9 +67,6 @@ impl Transformation {
fn apply(&self, streets: &mut StreetNetwork, timer: &mut Timer) {
timer.start(self.name());
match self {
Transformation::TrimDeadendCycleways => {
collapse_intersections::trim_deadends(streets);
}
Transformation::ZipSidepaths => {
parallel_sidepaths::zip_sidepaths(streets);
}
Expand Down
240 changes: 240 additions & 0 deletions tests/src/arizona_highways/geometry.json
Original file line number Diff line number Diff line change
Expand Up @@ -2961,6 +2961,46 @@
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.88935146004431,
33.630373029200165
],
[
-111.88941114185506,
33.63037224948837
],
[
-111.88941046356675,
33.630336280222885
],
[
-111.88935078175601,
33.63033705993469
],
[
-111.88935146004431,
33.630373029200165
]
]
],
"type": "Polygon"
},
"properties": {
"dst_i": 70,
"id": 76,
"layer": 0,
"osm_way_ids": [
582739016
],
"src_i": 69,
"type": "road"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
Expand Down Expand Up @@ -3377,6 +3417,46 @@
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.89204681901728,
33.63019735122825
],
[
-111.89211667515269,
33.63021490958256
],
[
-111.89212916084196,
33.6301804709624
],
[
-111.89205930470656,
33.630162912608085
],
[
-111.89204681901728,
33.63019735122825
]
]
],
"type": "Polygon"
},
"properties": {
"dst_i": 77,
"id": 86,
"layer": 0,
"osm_way_ids": [
665499817
],
"src_i": 76,
"type": "road"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
Expand Down Expand Up @@ -6398,6 +6478,86 @@
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.88930826236762,
33.63037359397411
],
[
-111.8893075840793,
33.63033762470863
],
[
-111.88935078175601,
33.63033705993469
],
[
-111.88935146004431,
33.630373029200165
],
[
-111.88930826236762,
33.63037359397411
]
]
],
"type": "Polygon"
},
"properties": {
"control": "Uncontrolled",
"crossing": null,
"id": 69,
"intersection_kind": "MapEdge",
"movements": [],
"osm_node_ids": [],
"type": "intersection"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.88945366124344,
33.63033571544894
],
[
-111.88945433953175,
33.63037168471442
],
[
-111.88941114185506,
33.63037224948837
],
[
-111.88941046356675,
33.630336280222885
],
[
-111.88945366124344,
33.63033571544894
]
]
],
"type": "Polygon"
},
"properties": {
"control": "Signed",
"crossing": null,
"id": 70,
"intersection_kind": "Terminus",
"movements": [],
"osm_node_ids": [
5572469734
],
"type": "intersection"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
Expand Down Expand Up @@ -6608,6 +6768,86 @@
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.89203395854132,
33.63019411906653
],
[
-111.89204644207044,
33.63015968044636
],
[
-111.89205930470656,
33.630162912608085
],
[
-111.89204681901728,
33.63019735122825
],
[
-111.89203395854132,
33.63019411906653
]
]
],
"type": "Polygon"
},
"properties": {
"control": "Signed",
"crossing": null,
"id": 76,
"intersection_kind": "Terminus",
"movements": [],
"osm_node_ids": [
6228919911
],
"type": "intersection"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
[
-111.8921705213078,
33.63019086532109
],
[
-111.89215803777869,
33.63022530394126
],
[
-111.89211667731284,
33.63021490868324
],
[
-111.89212916084196,
33.630180470063074
],
[
-111.8921705213078,
33.63019086532109
]
]
],
"type": "Polygon"
},
"properties": {
"control": "Uncontrolled",
"crossing": null,
"id": 77,
"intersection_kind": "MapEdge",
"movements": [],
"osm_node_ids": [],
"type": "intersection"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
Expand Down
Loading

0 comments on commit 3912a24

Please sign in to comment.