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
use geom::Duration;
use map_gui::tools::draw_isochrone;
use map_model::{BuildingType, DirectedRoadID, LaneType, Map, PathConstraints};
use widgetry::{Color, Drawable, EventCtx};
use crate::app::App;
pub struct Nearby {
pub draw_buffer: Drawable,
pub population: usize,
pub total_amenities: usize,
}
impl Nearby {
pub fn new(ctx: &mut EventCtx, app: &App) -> Nearby {
let threshold = Duration::minutes(1);
let map = &app.primary.map;
let time_to_reach_building = map_model::connectivity::all_vehicle_costs_from(
map,
bike_network_roads(map)
.into_iter()
.map(map_model::connectivity::Spot::DirectedRoad)
.collect(),
threshold,
PathConstraints::Bike,
);
let mut population = 0;
let mut total_amenities = 0;
for b in time_to_reach_building.keys() {
let bldg = map.get_b(*b);
total_amenities += bldg.amenities.len();
match bldg.bldg_type {
BuildingType::Residential { num_residents, .. }
| BuildingType::ResidentialCommercial(num_residents, _) => {
population += num_residents;
}
_ => {}
}
}
let draw_buffer = draw_isochrone(
map,
&time_to_reach_building,
&[0.1, threshold.inner_seconds()],
&[Color::BLUE.alpha(0.5)],
)
.upload(ctx);
Nearby {
draw_buffer,
population,
total_amenities,
}
}
}
fn bike_network_roads(map: &Map) -> Vec<DirectedRoadID> {
let mut results = Vec::new();
for r in map.all_roads() {
if r.is_cycleway()
|| crate::ungap::layers::is_greenway(r)
|| r.lanes_ltr.iter().any(|(_, _, lt)| *lt == LaneType::Biking)
{
results.extend(r.id.both_directions());
}
}
results
}