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
106
107
108
109
110
111
112
113
114
115
116
use std::collections::{HashMap, HashSet};
use petgraph::graphmap::DiGraphMap;
use geom::{Distance, Duration, Speed};
pub use crate::pathfind::{
build_graph_for_pedestrians, build_graph_for_vehicles, driving_cost, WalkingNode,
};
use crate::{BuildingID, LaneID, Map, PathConstraints};
pub fn find_scc(map: &Map, constraints: PathConstraints) -> (HashSet<LaneID>, HashSet<LaneID>) {
let mut graph = DiGraphMap::new();
for turn in map.all_turns().values() {
if constraints.can_use(map.get_l(turn.id.src), map)
&& constraints.can_use(map.get_l(turn.id.dst), map)
{
graph.add_edge(turn.id.src, turn.id.dst, 1);
}
}
let components = petgraph::algo::kosaraju_scc(&graph);
if components.is_empty() {
return (HashSet::new(), HashSet::new());
}
let largest_group: HashSet<LaneID> = components
.into_iter()
.max_by_key(|c| c.len())
.unwrap()
.into_iter()
.collect();
let disconnected = map
.all_lanes()
.iter()
.filter_map(|l| {
if constraints.can_use(l, map) && !largest_group.contains(&l.id) {
Some(l.id)
} else {
None
}
})
.collect();
(largest_group, disconnected)
}
pub fn all_costs_from(
map: &Map,
start: BuildingID,
time_limit: Duration,
constraints: PathConstraints,
) -> HashMap<BuildingID, Duration> {
let mut results = HashMap::new();
if constraints == PathConstraints::Pedestrian {
let graph = build_graph_for_pedestrians(map);
let start = WalkingNode::closest(map.get_b(start).sidewalk_pos, map);
let cost_per_node = petgraph::algo::dijkstra(&graph, start, None, |(_, _, cost)| *cost);
for b in map.all_buildings() {
if let Some(seconds) = cost_per_node.get(&WalkingNode::closest(b.sidewalk_pos, map)) {
let duration = Duration::seconds(*seconds as f64);
if duration <= time_limit {
results.insert(b.id, duration);
}
}
}
} else {
let mut bldg_to_lane = HashMap::new();
for b in map.all_buildings() {
if constraints == PathConstraints::Car {
if let Some((pos, _)) = b.driving_connection(map) {
bldg_to_lane.insert(b.id, pos.lane());
}
} else if constraints == PathConstraints::Bike {
if let Some((pos, _)) = b.biking_connection(map) {
bldg_to_lane.insert(b.id, pos.lane());
}
}
}
let max_bike_speed = Speed::miles_per_hour(10.0);
if let Some(start_lane) = bldg_to_lane.get(&start) {
let graph = build_graph_for_vehicles(map, constraints);
let cost_per_lane =
petgraph::algo::dijkstra(&graph, *start_lane, None, |(_, _, turn)| {
driving_cost(map.get_l(turn.src), map.get_t(*turn), constraints, map)
});
for (b, lane) in bldg_to_lane {
if let Some(meters) = cost_per_lane.get(&lane) {
let distance = Distance::meters(*meters as f64);
let duration = distance / max_bike_speed;
if duration <= time_limit {
results.insert(b, duration);
}
}
}
}
}
results
}