draw route to hovered building (#402)

for #393
This commit is contained in:
Michael Kirk 2020-11-24 11:30:03 -08:00 committed by GitHub
parent 16b561a408
commit 61cd74767a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 12 deletions

1
Cargo.lock generated
View File

@ -755,6 +755,7 @@ dependencies = [
"contour",
"geojson",
"geom",
"log",
"map_gui",
"map_model",
"widgetry",

View File

@ -12,6 +12,7 @@ abstutil = { path = "../abstutil" }
contour = { git = "https://github.com/dabreegster/contour-rs" }
geojson = "0.20.1"
geom = { path = "../geom" }
log = "0.4"
map_gui = { path = "../map_gui" }
map_model = { path = "../map_model" }
widgetry = { path = "../widgetry" }

View File

@ -4,7 +4,7 @@ use abstutil::MultiMap;
use geom::{Duration, Polygon};
use map_gui::tools::{amenity_type, Grid};
use map_gui::SimpleApp;
use map_model::{connectivity, BuildingID, PathConstraints};
use map_model::{connectivity, BuildingID, Map, PathConstraints, PathRequest};
use widgetry::{Color, Drawable, EventCtx, GeomBatch};
/// Represents the area reachable from a single building.
@ -50,6 +50,28 @@ impl Isochrone {
amenities_reachable,
}
}
pub fn path_to(&self, map: &Map, destination_id: BuildingID) -> Option<map_model::Path> {
let (start, end) = match self.constraints {
PathConstraints::Pedestrian => (
map.get_b(self.start).sidewalk_pos,
map.get_b(destination_id).sidewalk_pos,
),
PathConstraints::Bike => (
map.get_b(self.start).biking_connection(map)?.0,
map.get_b(destination_id).biking_connection(map)?.0,
),
_ => unimplemented!("unhandled constraints: {:?}", self.constraints),
};
let path_request = PathRequest {
start,
end,
constraints: self.constraints,
};
map.pathfind(path_request)
}
}
fn draw_isochrone(

View File

@ -1,6 +1,9 @@
mod isochrone;
mod viewer;
#[macro_use]
extern crate log;
fn main() {
widgetry::run(widgetry::Settings::new("15-minute neighborhoods"), |ctx| {
let app = map_gui::SimpleApp::new(ctx, abstutil::CmdArgs::new());

View File

@ -4,7 +4,7 @@
//!
//! See https://github.com/dabreegster/abstreet/issues/393 for more context.
use geom::Pt2D;
use geom::{Distance, Pt2D};
use map_gui::tools::{amenity_type, nice_map_name, CityPicker, PopupMsg};
use map_gui::{SimpleApp, ID};
use map_model::{Building, BuildingID, PathConstraints};
@ -27,7 +27,8 @@ pub struct Viewer {
struct HoverOnBuilding {
id: BuildingID,
tooltip: Text,
// TODO Draw a route preview
drawn_route: Option<Drawable>,
scale_factor: f64,
}
impl Viewer {
@ -53,7 +54,6 @@ impl Viewer {
panel,
highlight_start: highlight_start,
isochrone,
hovering_on_bldg: None,
})
}
@ -65,15 +65,49 @@ impl State<SimpleApp> for Viewer {
ctx.canvas_movement();
if ctx.redo_mouseover() {
let scale_factor = if ctx.canvas.cam_zoom >= app.opts.min_zoom_for_detail {
1.0
} else {
10.0
};
self.hovering_on_bldg = match app.mouseover_unzoomed_buildings(ctx) {
Some(ID::Building(id)) => Some(HoverOnBuilding {
id,
tooltip: if let Some(time) = self.isochrone.time_to_reach_building.get(&id) {
Text::from(Line(format!("{} away", time)))
} else {
Text::from(Line("This is more than 15 minutes away"))
},
}),
Some(ID::Building(hover_id)) => match self.hovering_on_bldg.take() {
Some(previous_hover)
if (previous_hover.id, previous_hover.scale_factor)
== (hover_id, scale_factor) =>
{
Some(previous_hover)
}
_ => {
debug!("drawing new hover");
let drawn_route = self
.isochrone
.path_to(&app.map, hover_id)
.and_then(|path| path.trace(&app.map, Distance::ZERO, None))
.map(|polyline| {
let dashed_lines = polyline.dashed_lines(
Distance::meters(0.75 * scale_factor),
Distance::meters(1.0 * scale_factor),
Distance::meters(0.4 * scale_factor),
);
let mut batch = GeomBatch::new();
batch.extend(Color::BLACK, dashed_lines);
ctx.prerender.upload(batch)
});
Some(HoverOnBuilding {
id: hover_id,
tooltip: if let Some(time) =
self.isochrone.time_to_reach_building.get(&hover_id)
{
Text::from(Line(format!("{} away", time)))
} else {
Text::from(Line("This is more than 15 minutes away"))
},
scale_factor,
drawn_route,
})
}
},
_ => None,
};
@ -85,10 +119,14 @@ impl State<SimpleApp> for Viewer {
// panel.event never sees clicks.
if let Some(ref hover) = self.hovering_on_bldg {
if ctx.normal_left_click() {
debug!("selected new");
let start = app.map.get_b(hover.id);
self.isochrone = Isochrone::new(ctx, app, start.id, self.isochrone.constraints);
self.highlight_start = draw_star(ctx, start.polygon.center());
self.panel = build_panel(ctx, app, start, &self.isochrone);
// Any previous hover is from the perspective of the old `highlight_start`.
// Remove it so we don't have a dotted line to the previous isochrone's origin
self.hovering_on_bldg = None;
}
}
@ -171,6 +209,9 @@ impl State<SimpleApp> for Viewer {
self.panel.draw(g);
if let Some(ref hover) = self.hovering_on_bldg {
g.draw_mouse_tooltip(hover.tooltip.clone());
if let Some(ref drawn_route) = hover.drawn_route {
g.redraw(drawn_route);
}
}
}
}