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
use std::collections::BTreeSet;
use abstutil::Timer;
use map_gui::tools::PopupMsg;
use map_model::{connectivity, EditCmd, PathConstraints};
use widgetry::{EventCtx, State};
use crate::app::App;
pub fn check_sidewalk_connectivity(
ctx: &mut EventCtx,
app: &mut App,
cmd: EditCmd,
) -> Option<Box<dyn State<App>>> {
let orig_edits = app.primary.map.get_edits().clone();
let (_, disconnected_before) =
connectivity::find_scc(&app.primary.map, PathConstraints::Pedestrian);
let mut edits = orig_edits.clone();
edits.commands.push(cmd);
app.primary
.map
.try_apply_edits(edits, &mut Timer::throwaway());
let (_, disconnected_after) =
connectivity::find_scc(&app.primary.map, PathConstraints::Pedestrian);
app.primary
.map
.must_apply_edits(orig_edits, &mut Timer::throwaway());
let newly_disconnected = disconnected_after
.difference(&disconnected_before)
.collect::<Vec<_>>();
if newly_disconnected.is_empty() {
return None;
}
Some(PopupMsg::new_state(
ctx,
"Error",
vec![format!(
"Can't close this intersection; {} sidewalks disconnected",
newly_disconnected.len()
)],
))
}
#[allow(unused)]
pub fn check_blackholes(
ctx: &mut EventCtx,
app: &mut App,
cmd: EditCmd,
) -> Option<Box<dyn State<App>>> {
let orig_edits = app.primary.map.get_edits().clone();
let mut driving_ok_originally = BTreeSet::new();
let mut biking_ok_originally = BTreeSet::new();
for l in app.primary.map.all_lanes() {
if !l.driving_blackhole {
driving_ok_originally.insert(l.id);
}
if !l.biking_blackhole {
biking_ok_originally.insert(l.id);
}
}
let mut edits = orig_edits.clone();
edits.commands.push(cmd);
app.primary
.map
.try_apply_edits(edits, &mut Timer::throwaway());
let mut newly_disconnected = BTreeSet::new();
for l in connectivity::find_scc(&app.primary.map, PathConstraints::Car).1 {
if driving_ok_originally.contains(&l) {
newly_disconnected.insert(l);
}
}
for l in connectivity::find_scc(&app.primary.map, PathConstraints::Bike).1 {
if biking_ok_originally.contains(&l) {
newly_disconnected.insert(l);
}
}
app.primary
.map
.must_apply_edits(orig_edits, &mut Timer::throwaway());
if newly_disconnected.is_empty() {
return None;
}
Some(PopupMsg::new_state(
ctx,
"Error",
vec![format!(
"{} lanes have been disconnected",
newly_disconnected.len()
)],
))
}