mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
parent
16b561a408
commit
61cd74767a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -755,6 +755,7 @@ dependencies = [
|
|||||||
"contour",
|
"contour",
|
||||||
"geojson",
|
"geojson",
|
||||||
"geom",
|
"geom",
|
||||||
|
"log",
|
||||||
"map_gui",
|
"map_gui",
|
||||||
"map_model",
|
"map_model",
|
||||||
"widgetry",
|
"widgetry",
|
||||||
|
@ -12,6 +12,7 @@ abstutil = { path = "../abstutil" }
|
|||||||
contour = { git = "https://github.com/dabreegster/contour-rs" }
|
contour = { git = "https://github.com/dabreegster/contour-rs" }
|
||||||
geojson = "0.20.1"
|
geojson = "0.20.1"
|
||||||
geom = { path = "../geom" }
|
geom = { path = "../geom" }
|
||||||
|
log = "0.4"
|
||||||
map_gui = { path = "../map_gui" }
|
map_gui = { path = "../map_gui" }
|
||||||
map_model = { path = "../map_model" }
|
map_model = { path = "../map_model" }
|
||||||
widgetry = { path = "../widgetry" }
|
widgetry = { path = "../widgetry" }
|
||||||
|
@ -4,7 +4,7 @@ use abstutil::MultiMap;
|
|||||||
use geom::{Duration, Polygon};
|
use geom::{Duration, Polygon};
|
||||||
use map_gui::tools::{amenity_type, Grid};
|
use map_gui::tools::{amenity_type, Grid};
|
||||||
use map_gui::SimpleApp;
|
use map_gui::SimpleApp;
|
||||||
use map_model::{connectivity, BuildingID, PathConstraints};
|
use map_model::{connectivity, BuildingID, Map, PathConstraints, PathRequest};
|
||||||
use widgetry::{Color, Drawable, EventCtx, GeomBatch};
|
use widgetry::{Color, Drawable, EventCtx, GeomBatch};
|
||||||
|
|
||||||
/// Represents the area reachable from a single building.
|
/// Represents the area reachable from a single building.
|
||||||
@ -50,6 +50,28 @@ impl Isochrone {
|
|||||||
amenities_reachable,
|
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(
|
fn draw_isochrone(
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
mod isochrone;
|
mod isochrone;
|
||||||
mod viewer;
|
mod viewer;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
widgetry::run(widgetry::Settings::new("15-minute neighborhoods"), |ctx| {
|
widgetry::run(widgetry::Settings::new("15-minute neighborhoods"), |ctx| {
|
||||||
let app = map_gui::SimpleApp::new(ctx, abstutil::CmdArgs::new());
|
let app = map_gui::SimpleApp::new(ctx, abstutil::CmdArgs::new());
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
//!
|
//!
|
||||||
//! See https://github.com/dabreegster/abstreet/issues/393 for more context.
|
//! 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::tools::{amenity_type, nice_map_name, CityPicker, PopupMsg};
|
||||||
use map_gui::{SimpleApp, ID};
|
use map_gui::{SimpleApp, ID};
|
||||||
use map_model::{Building, BuildingID, PathConstraints};
|
use map_model::{Building, BuildingID, PathConstraints};
|
||||||
@ -27,7 +27,8 @@ pub struct Viewer {
|
|||||||
struct HoverOnBuilding {
|
struct HoverOnBuilding {
|
||||||
id: BuildingID,
|
id: BuildingID,
|
||||||
tooltip: Text,
|
tooltip: Text,
|
||||||
// TODO Draw a route preview
|
drawn_route: Option<Drawable>,
|
||||||
|
scale_factor: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Viewer {
|
impl Viewer {
|
||||||
@ -53,7 +54,6 @@ impl Viewer {
|
|||||||
panel,
|
panel,
|
||||||
highlight_start: highlight_start,
|
highlight_start: highlight_start,
|
||||||
isochrone,
|
isochrone,
|
||||||
|
|
||||||
hovering_on_bldg: None,
|
hovering_on_bldg: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -65,15 +65,49 @@ impl State<SimpleApp> for Viewer {
|
|||||||
ctx.canvas_movement();
|
ctx.canvas_movement();
|
||||||
|
|
||||||
if ctx.redo_mouseover() {
|
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) {
|
self.hovering_on_bldg = match app.mouseover_unzoomed_buildings(ctx) {
|
||||||
Some(ID::Building(id)) => Some(HoverOnBuilding {
|
Some(ID::Building(hover_id)) => match self.hovering_on_bldg.take() {
|
||||||
id,
|
Some(previous_hover)
|
||||||
tooltip: if let Some(time) = self.isochrone.time_to_reach_building.get(&id) {
|
if (previous_hover.id, previous_hover.scale_factor)
|
||||||
Text::from(Line(format!("{} away", time)))
|
== (hover_id, scale_factor) =>
|
||||||
} else {
|
{
|
||||||
Text::from(Line("This is more than 15 minutes away"))
|
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,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,10 +119,14 @@ impl State<SimpleApp> for Viewer {
|
|||||||
// panel.event never sees clicks.
|
// panel.event never sees clicks.
|
||||||
if let Some(ref hover) = self.hovering_on_bldg {
|
if let Some(ref hover) = self.hovering_on_bldg {
|
||||||
if ctx.normal_left_click() {
|
if ctx.normal_left_click() {
|
||||||
|
debug!("selected new");
|
||||||
let start = app.map.get_b(hover.id);
|
let start = app.map.get_b(hover.id);
|
||||||
self.isochrone = Isochrone::new(ctx, app, start.id, self.isochrone.constraints);
|
self.isochrone = Isochrone::new(ctx, app, start.id, self.isochrone.constraints);
|
||||||
self.highlight_start = draw_star(ctx, start.polygon.center());
|
self.highlight_start = draw_star(ctx, start.polygon.center());
|
||||||
self.panel = build_panel(ctx, app, start, &self.isochrone);
|
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);
|
self.panel.draw(g);
|
||||||
if let Some(ref hover) = self.hovering_on_bldg {
|
if let Some(ref hover) = self.hovering_on_bldg {
|
||||||
g.draw_mouse_tooltip(hover.tooltip.clone());
|
g.draw_mouse_tooltip(hover.tooltip.clone());
|
||||||
|
if let Some(ref drawn_route) = hover.drawn_route {
|
||||||
|
g.redraw(drawn_route);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user