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
103
104
105
use serde::{Deserialize, Serialize};
use abstutil::Timer;
use geom::Duration;
use crate::pathfind::dijkstra;
use crate::pathfind::vehicles::VehiclePathfinder;
use crate::pathfind::walking::SidewalkPathfinder;
use crate::{BusRouteID, BusStopID, Map, PathConstraints, PathRequest, PathV2, Position};
#[derive(Serialize, Deserialize)]
pub struct ContractionHierarchyPathfinder {
car_graph: VehiclePathfinder,
bike_graph: VehiclePathfinder,
bus_graph: VehiclePathfinder,
walking_graph: SidewalkPathfinder,
walking_with_transit_graph: SidewalkPathfinder,
}
impl ContractionHierarchyPathfinder {
pub fn new(map: &Map, timer: &mut Timer) -> ContractionHierarchyPathfinder {
timer.start("prepare pathfinding for cars");
let car_graph = VehiclePathfinder::new(map, PathConstraints::Car, None);
timer.stop("prepare pathfinding for cars");
timer.start("prepare pathfinding for bikes");
let bike_graph = VehiclePathfinder::new(map, PathConstraints::Bike, None);
timer.stop("prepare pathfinding for bikes");
timer.start("prepare pathfinding for buses");
let bus_graph = VehiclePathfinder::new(map, PathConstraints::Bus, Some(&car_graph));
timer.stop("prepare pathfinding for buses");
timer.start("prepare pathfinding for pedestrians");
let walking_graph = SidewalkPathfinder::new(map, false, &bus_graph);
timer.stop("prepare pathfinding for pedestrians");
timer.start("prepare pathfinding for pedestrians using transit");
let walking_with_transit_graph = SidewalkPathfinder::new(map, true, &bus_graph);
timer.stop("prepare pathfinding for pedestrians using transit");
ContractionHierarchyPathfinder {
car_graph,
bike_graph,
bus_graph,
walking_graph,
walking_with_transit_graph,
}
}
pub fn pathfind(&self, req: PathRequest, map: &Map) -> Option<PathV2> {
match req.constraints {
PathConstraints::Pedestrian => self.walking_graph.pathfind(req, map),
PathConstraints::Car => self.car_graph.pathfind(req, map),
PathConstraints::Bike => self.bike_graph.pathfind(req, map),
PathConstraints::Bus => self.bus_graph.pathfind(req, map),
PathConstraints::Train => dijkstra::pathfind(req, map.routing_params(), map),
}
}
pub fn should_use_transit(
&self,
map: &Map,
start: Position,
end: Position,
) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)> {
self.walking_with_transit_graph
.should_use_transit(map, start, end)
}
pub fn apply_edits(&mut self, map: &Map, timer: &mut Timer) {
timer.start("apply edits to car pathfinding");
self.car_graph.apply_edits(map);
timer.stop("apply edits to car pathfinding");
timer.start("apply edits to bike pathfinding");
self.bike_graph.apply_edits(map);
timer.stop("apply edits to bike pathfinding");
timer.start("apply edits to bus pathfinding");
self.bus_graph.apply_edits(map);
timer.stop("apply edits to bus pathfinding");
timer.start("apply edits to pedestrian pathfinding");
self.walking_graph.apply_edits(map, &self.bus_graph);
timer.stop("apply edits to pedestrian pathfinding");
timer.start("apply edits to pedestrian using transit pathfinding");
self.walking_with_transit_graph
.apply_edits(map, &self.bus_graph);
timer.stop("apply edits to pedestrian using transit pathfinding");
}
}
pub fn round(cost: Duration) -> usize {
(cost.inner_seconds().round() as usize).max(1)
}