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
use std::collections::{HashMap, HashSet};
use aabb_quadtree::QuadTree;
use abstutil::Timer;
use crate::{osm, StreetNetwork};
pub fn shrink(raw: &mut StreetNetwork, timer: &mut Timer) {
let mut road_centers = HashMap::new();
let mut road_polygons = HashMap::new();
let mut overlapping = Vec::new();
let mut quadtree = QuadTree::default(raw.gps_bounds.to_bounds().as_bbox());
timer.start_iter("find overlapping roads", raw.roads.len());
for (id, road) in &raw.roads {
timer.next();
if road.is_light_rail() {
continue;
}
if road.oneway_for_driving().is_none() {
continue;
}
let (center, total_width) = road.untrimmed_road_geometry();
let polygon = center.make_polygons(total_width);
for (other_id, _, _) in quadtree.query(polygon.get_bounds().as_bbox()) {
if road.osm_tags.get(osm::NAME) != raw.roads[other_id].osm_tags.get(osm::NAME) {
continue;
}
if !id.has_common_endpoint(*other_id) && polygon.intersects(&road_polygons[other_id]) {
if center.intersection(&road_centers[other_id]).is_none() {
overlapping.push((*id, *other_id));
}
}
}
quadtree.insert_with_box(*id, polygon.get_bounds().as_bbox());
road_centers.insert(*id, center);
road_polygons.insert(*id, polygon);
}
timer.start_iter("shrink overlapping roads", overlapping.len());
let mut shrunk = HashSet::new();
for (r1, r2) in overlapping {
timer.next();
for id in [r1, r2] {
if shrunk.contains(&id) {
continue;
}
shrunk.insert(id);
for spec in &mut raw.roads.get_mut(&id).unwrap().lane_specs_ltr {
spec.width *= 0.5;
}
}
}
}