map_gui/render/
transit_stop.rs

1use geom::{Angle, Bounds, Circle, Distance, Line, Pt2D, Tessellation};
2use map_model::{Map, TransitStop, TransitStopID};
3use widgetry::{Drawable, EventCtx, GeomBatch, GfxCtx};
4
5use crate::colors::ColorScheme;
6use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
7use crate::{AppLike, ID};
8
9const RADIUS: Distance = Distance::const_meters(1.0);
10
11pub struct DrawTransitStop {
12    pub id: TransitStopID,
13    center: Pt2D,
14    zorder: isize,
15
16    draw_default: Drawable,
17}
18
19impl DrawTransitStop {
20    pub fn new(ctx: &EventCtx, stop: &TransitStop, map: &Map, cs: &ColorScheme) -> DrawTransitStop {
21        let (pt, angle) = stop.sidewalk_pos.pt_and_angle(map);
22        let center = pt.project_away(
23            map.get_l(stop.sidewalk_pos.lane()).width / 2.0,
24            angle.rotate_degs(90.0),
25        );
26
27        let mut icon = GeomBatch::new();
28        icon.append(
29            GeomBatch::load_svg(
30                ctx.prerender,
31                if stop.is_train_stop {
32                    "system/assets/map/light_rail.svg"
33                } else {
34                    "system/assets/meters/bus.svg"
35                },
36            )
37            .scale(0.05)
38            .centered_on(center),
39        );
40        let mut batch = GeomBatch::new();
41        batch.push(
42            cs.bus_layer.alpha(0.8),
43            Circle::new(center, RADIUS).to_polygon(),
44        );
45        batch.append(icon.autocrop().centered_on(center));
46        batch.push(
47            cs.stop_sign_pole,
48            Line::must_new(
49                center.project_away(RADIUS, Angle::degrees(90.0)),
50                center.project_away(1.5 * RADIUS, Angle::degrees(90.0)),
51            )
52            .make_polygons(Distance::meters(0.3)),
53        );
54
55        DrawTransitStop {
56            id: stop.id,
57            center,
58            zorder: map.get_parent(stop.sidewalk_pos.lane()).zorder,
59            draw_default: ctx.upload(batch),
60        }
61    }
62}
63
64impl Renderable for DrawTransitStop {
65    fn get_id(&self) -> ID {
66        ID::TransitStop(self.id)
67    }
68
69    fn draw(&self, g: &mut GfxCtx, _: &dyn AppLike, _: &DrawOptions) {
70        g.redraw(&self.draw_default);
71    }
72
73    fn get_outline(&self, _: &Map) -> Tessellation {
74        Tessellation::from(
75            Circle::new(self.center, RADIUS)
76                .to_outline(OUTLINE_THICKNESS)
77                .expect("constants defined wrong"),
78        )
79    }
80
81    fn get_bounds(&self, _: &Map) -> Bounds {
82        Circle::new(self.center, RADIUS).get_bounds()
83    }
84
85    fn contains_pt(&self, pt: Pt2D, _: &Map) -> bool {
86        Circle::new(self.center, RADIUS).contains_pt(pt)
87    }
88
89    fn get_zorder(&self) -> isize {
90        self.zorder
91    }
92}