1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::collections::HashSet;
use crate::make::initial::lane_specs::get_lane_specs_ltr;
use crate::osm::NodeID;
use crate::raw::{OriginalRoad, RawMap, RawRoad};
use crate::LaneType;
pub fn collapse(raw: &mut RawMap) {
let mut merge: Vec<NodeID> = Vec::new();
for id in raw.intersections.keys() {
let roads = raw.roads_per_intersection(*id);
if roads.len() == 2 && roads.iter().all(|r| is_cycleway(&raw.roads[r], raw)) {
merge.push(*id);
}
}
for i in merge {
collapse_intersection(raw, i);
}
}
fn is_cycleway(road: &RawRoad, raw: &RawMap) -> bool {
if !road.turn_restrictions.is_empty() || !road.complicated_turn_restrictions.is_empty() {
return false;
}
let mut bike = false;
for spec in get_lane_specs_ltr(&road.osm_tags, &raw.config) {
if spec.lt == LaneType::Biking {
bike = true;
} else if spec.lt != LaneType::Shoulder {
return false;
}
}
bike
}
fn collapse_intersection(raw: &mut RawMap, i: NodeID) {
let roads = raw.roads_per_intersection(i);
assert_eq!(roads.len(), 2);
let r1 = roads[0];
let r2 = roads[1];
let mut endpts = HashSet::new();
endpts.insert(r1.i1);
endpts.insert(r1.i2);
endpts.insert(r2.i1);
endpts.insert(r2.i2);
if endpts.len() != 3 {
info!("Not collapsing degenerate {}, because it's a loop", i);
return;
}
info!("Collapsing degenerate {}", i);
raw.intersections.remove(&i).unwrap();
let mut new_road = raw.roads.remove(&r1).unwrap();
let mut road2 = raw.roads.remove(&r2).unwrap();
let (new_i1, new_i2) = if r1.i2 == r2.i1 {
new_road.center_points.extend(road2.center_points);
(r1.i1, r2.i2)
} else if r1.i2 == r2.i2 {
road2.center_points.reverse();
new_road.center_points.extend(road2.center_points);
(r1.i1, r2.i1)
} else if r1.i1 == r2.i1 {
road2.center_points.reverse();
road2.center_points.extend(new_road.center_points);
new_road.center_points = road2.center_points;
(r2.i2, r1.i2)
} else if r1.i1 == r2.i2 {
road2.center_points.extend(new_road.center_points);
new_road.center_points = road2.center_points;
(r2.i1, r1.i2)
} else {
unreachable!()
};
assert!(i != new_i1 && i != new_i2);
new_road.center_points.dedup();
raw.roads.insert(
OriginalRoad {
osm_way_id: r1.osm_way_id,
i1: new_i1,
i2: new_i2,
},
new_road,
);
}