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
use crate::app::App;
use crate::colors::ColorScheme;
use crate::helpers::ID;
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
use ezgui::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Text};
use geom::{Distance, Polygon, Pt2D};
use map_model::{Building, BuildingID, Map, OffstreetParking, NORMAL_LANE_THICKNESS};
use std::cell::RefCell;
pub struct DrawBuilding {
pub id: BuildingID,
label: RefCell<Option<Drawable>>,
}
impl DrawBuilding {
pub fn new(
ctx: &EventCtx,
bldg: &Building,
map: &Map,
cs: &ColorScheme,
bldg_batch: &mut GeomBatch,
paths_batch: &mut GeomBatch,
outlines_batch: &mut GeomBatch,
) -> DrawBuilding {
let orig_pl = &bldg.driveway_geom;
let driveway = orig_pl
.slice(
Distance::ZERO,
orig_pl.length() - map.get_l(bldg.sidewalk()).width / 2.0,
)
.map(|(pl, _)| pl)
.unwrap_or_else(|_| orig_pl.clone());
if bldg.amenities.is_empty() {
bldg_batch.push(cs.residential_building, bldg.polygon.clone());
} else {
bldg_batch.push(cs.commerical_building, bldg.polygon.clone());
}
paths_batch.push(cs.sidewalk, driveway.make_polygons(NORMAL_LANE_THICKNESS));
if let Ok(p) = bldg.polygon.to_outline(Distance::meters(0.1)) {
outlines_batch.push(cs.building_outline, p);
}
let parking_icon = match bldg.parking {
OffstreetParking::PublicGarage(_, _) => true,
OffstreetParking::Private(n) => n > 10,
};
if parking_icon {
bldg_batch.append(
GeomBatch::load_svg(ctx.prerender, "system/assets/map/parking.svg")
.scale(0.1)
.centered_on(bldg.label_center),
);
}
DrawBuilding {
id: bldg.id,
label: RefCell::new(None),
}
}
}
impl Renderable for DrawBuilding {
fn get_id(&self) -> ID {
ID::Building(self.id)
}
fn draw(&self, g: &mut GfxCtx, app: &App, opts: &DrawOptions) {
if opts.label_buildings {
let mut label = self.label.borrow_mut();
if label.is_none() {
let mut batch = GeomBatch::new();
let b = app.primary.map.get_b(self.id);
if let Some((name, _)) = b.amenities.iter().next() {
let mut txt = Text::from(Line(name).fg(Color::BLACK));
if b.amenities.len() > 1 {
txt.append(Line(format!(" (+{})", b.amenities.len() - 1)).fg(Color::BLACK));
}
batch.append(
txt.render_to_batch(g.prerender)
.scale(0.1)
.centered_on(b.label_center),
);
}
*label = Some(g.prerender.upload(batch));
}
g.redraw(label.as_ref().unwrap());
}
}
fn get_zorder(&self) -> isize {
0
}
fn get_outline(&self, map: &Map) -> Polygon {
let b = map.get_b(self.id);
if let Ok(p) = b.polygon.to_outline(OUTLINE_THICKNESS) {
p
} else {
b.polygon.clone()
}
}
fn contains_pt(&self, pt: Pt2D, map: &Map) -> bool {
map.get_b(self.id).polygon.contains_pt(pt)
}
}