mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Toggle bike network layer too in the new tool; we're probably using this
for a workshop presentation mode, and it's not always necessary And also, remove the 'nearby stuff' layer -- the isochrone is super broken, and it's unclear how this is supposed to help contextualize.
This commit is contained in:
parent
5a840810d6
commit
f3a216e935
@ -1,12 +1,10 @@
|
||||
mod layers;
|
||||
mod magnifying;
|
||||
mod nearby;
|
||||
mod quick_sketch;
|
||||
mod share;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use abstutil::prettyprint_usize;
|
||||
use geom::Distance;
|
||||
use map_gui::tools::{nice_map_name, CityPicker, ColorLegend, PopupMsg, URLManager};
|
||||
use map_gui::ID;
|
||||
@ -20,7 +18,6 @@ use widgetry::{
|
||||
|
||||
use self::layers::{render_edits, DrawNetworkLayer};
|
||||
use self::magnifying::MagnifyingGlass;
|
||||
use self::nearby::Nearby;
|
||||
use crate::app::{App, Transition};
|
||||
use crate::edit::{LoadEdits, RoadEditor, SaveEdits};
|
||||
use crate::sandbox::gameplay::GameplayMode;
|
||||
@ -31,11 +28,9 @@ pub struct ExploreMap {
|
||||
top_panel: Panel,
|
||||
legend: Panel,
|
||||
magnifying_glass: MagnifyingGlass,
|
||||
network_layer: DrawNetworkLayer,
|
||||
bike_network_layer: Option<DrawNetworkLayer>,
|
||||
edits_layer: Drawable,
|
||||
elevation: bool,
|
||||
// TODO Also cache Nearby, but recalculate it after edits
|
||||
nearby: Option<Nearby>,
|
||||
// TODO Once widgetry buttons can take custom enums, that'd be perfect here
|
||||
road_types: HashMap<String, Drawable>,
|
||||
|
||||
@ -60,12 +55,11 @@ impl ExploreMap {
|
||||
|
||||
Box::new(ExploreMap {
|
||||
top_panel: Panel::empty(ctx),
|
||||
legend: make_legend(ctx, app, false, false),
|
||||
legend: make_legend(ctx, app, true, false),
|
||||
magnifying_glass: MagnifyingGlass::new(ctx),
|
||||
network_layer: DrawNetworkLayer::new(),
|
||||
bike_network_layer: Some(DrawNetworkLayer::new()),
|
||||
edits_layer: Drawable::empty(ctx),
|
||||
elevation: false,
|
||||
nearby: None,
|
||||
road_types: HashMap::new(),
|
||||
|
||||
// Start with a bogus value, so we fix up the URL when changing maps
|
||||
@ -75,7 +69,7 @@ impl ExploreMap {
|
||||
|
||||
fn highlight_road_type(&mut self, ctx: &mut EventCtx, app: &App, name: &str) {
|
||||
// TODO Button enums would rock
|
||||
if name == "elevation" || name == "things nearby" || name.starts_with("about ") {
|
||||
if name == "bike network" || name == "elevation" || name.starts_with("about ") {
|
||||
return;
|
||||
}
|
||||
if self.road_types.contains_key(name) {
|
||||
@ -120,7 +114,9 @@ impl State<App> for ExploreMap {
|
||||
let key = app.primary.map.get_edits_change_key();
|
||||
if self.map_edit_key != key {
|
||||
self.map_edit_key = key;
|
||||
self.network_layer.clear();
|
||||
if let Some(ref mut n) = self.bike_network_layer {
|
||||
n.clear();
|
||||
}
|
||||
self.edits_layer = render_edits(ctx, app);
|
||||
self.top_panel = make_top_panel(ctx, app);
|
||||
self.road_types.clear();
|
||||
@ -250,14 +246,21 @@ impl State<App> for ExploreMap {
|
||||
"greenway" => PopupMsg::new_state(ctx, "Stay Healthy Streets and neighborhood greenways", vec!["Residential streets with additional signage and light barriers. These are intended to be low traffic, dedicated for people walking and biking."]),
|
||||
// TODO Add URLs
|
||||
"about the elevation data" => PopupMsg::new_state(ctx, "About the elevation data", vec!["Biking uphill next to traffic without any dedicated space isn't fun.", "Biking downhill next to traffic, especially in the door-zone of parked cars, and especially on Seattle's bumpy roads... is downright terrifying.", "", "Note the elevation data is incorrect near bridges.", "Thanks to King County LIDAR for the data, and Eldan Goldenberg for processing it."]),
|
||||
"about the things nearby" => PopupMsg::new_state(ctx, "About the things nearby", vec!["Population data from ?", "Amenities from OpenStreetMap", "A 1-minute biking buffer around the bike network is shown.", "Note 1 minutes depends on direction, especially with steep hills -- this starts FROM the network."]),
|
||||
_ => unreachable!(),
|
||||
});
|
||||
}
|
||||
Outcome::Changed(x) => match x.as_ref() {
|
||||
"bike network" => {
|
||||
if self.legend.is_checked("bike network") {
|
||||
self.bike_network_layer = Some(DrawNetworkLayer::new());
|
||||
} else {
|
||||
self.bike_network_layer = None;
|
||||
}
|
||||
}
|
||||
"elevation" => {
|
||||
self.elevation = self.legend.is_checked("elevation");
|
||||
self.legend = make_legend(ctx, app, self.elevation, self.nearby.is_some());
|
||||
self.legend =
|
||||
make_legend(ctx, app, self.bike_network_layer.is_some(), self.elevation);
|
||||
if self.elevation {
|
||||
let name = app.primary.map.get_name().clone();
|
||||
if app.session.elevation_contours.key() != Some(name.clone()) {
|
||||
@ -275,23 +278,6 @@ impl State<App> for ExploreMap {
|
||||
}
|
||||
}
|
||||
}
|
||||
"things nearby" => {
|
||||
if self.legend.is_checked("things nearby") {
|
||||
let nearby = Nearby::new(ctx, app);
|
||||
let label = Text::from(Line(format!(
|
||||
"{} residents, {} shops",
|
||||
prettyprint_usize(nearby.population),
|
||||
prettyprint_usize(nearby.total_amenities)
|
||||
)))
|
||||
.into_widget(ctx);
|
||||
self.legend.replace(ctx, "nearby info", label);
|
||||
self.nearby = Some(nearby);
|
||||
} else {
|
||||
let label = Text::new().into_widget(ctx);
|
||||
self.legend.replace(ctx, "nearby info", label);
|
||||
self.nearby = None;
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => {}
|
||||
@ -307,17 +293,15 @@ impl State<App> for ExploreMap {
|
||||
self.top_panel.draw(g);
|
||||
self.legend.draw(g);
|
||||
if g.canvas.cam_zoom < app.opts.min_zoom_for_detail {
|
||||
self.network_layer.draw(g, app);
|
||||
if let Some(ref n) = self.bike_network_layer {
|
||||
n.draw(g, app);
|
||||
}
|
||||
|
||||
if self.elevation {
|
||||
if let Some((_, ref draw)) = app.session.elevation_contours.value() {
|
||||
g.redraw(draw);
|
||||
}
|
||||
}
|
||||
if let Some(ref nearby) = self.nearby {
|
||||
g.redraw(&nearby.draw_buffer);
|
||||
}
|
||||
|
||||
self.magnifying_glass.draw(g, app);
|
||||
|
||||
if let Some(name) = self.legend.currently_hovering() {
|
||||
@ -431,7 +415,7 @@ fn make_top_panel(ctx: &mut EventCtx, app: &App) -> Panel {
|
||||
.build(ctx)
|
||||
}
|
||||
|
||||
fn make_legend(ctx: &mut EventCtx, app: &App, elevation: bool, nearby: bool) -> Panel {
|
||||
fn make_legend(ctx: &mut EventCtx, app: &App, bike_network: bool, elevation: bool) -> Panel {
|
||||
Panel::new_builder(Widget::col(vec![
|
||||
Widget::custom_row(vec![
|
||||
// TODO Looks too close to access restrictions
|
||||
@ -440,6 +424,7 @@ fn make_legend(ctx: &mut EventCtx, app: &App, elevation: bool, nearby: bool) ->
|
||||
legend(ctx, app.cs.unzoomed_residential, "minor street"),
|
||||
]),
|
||||
Widget::custom_row(vec![
|
||||
Toggle::checkbox(ctx, "bike network", Key::B, bike_network),
|
||||
legend(ctx, *layers::DEDICATED_TRAIL, "trail"),
|
||||
legend(ctx, *layers::PROTECTED_BIKE_LANE, "protected bike lane"),
|
||||
legend(ctx, *layers::PAINTED_BIKE_LANE, "painted bike lane"),
|
||||
@ -461,18 +446,7 @@ fn make_legend(ctx: &mut EventCtx, app: &App, elevation: bool, nearby: bool) ->
|
||||
.named("current elevation")
|
||||
.centered_vert(),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
Toggle::checkbox(ctx, "things nearby", None, nearby),
|
||||
ctx.style()
|
||||
.btn_plain
|
||||
.icon("system/assets/tools/info.svg")
|
||||
.build_widget(ctx, "about the things nearby")
|
||||
.centered_vert(),
|
||||
Text::new()
|
||||
.into_widget(ctx)
|
||||
.named("nearby info")
|
||||
.centered_vert(),
|
||||
]),
|
||||
// TODO Probably a collisions layer, or the alternate "steep streets"
|
||||
])
|
||||
.evenly_spaced(),
|
||||
]))
|
||||
|
@ -1,73 +0,0 @@
|
||||
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;
|
||||
|
||||
// TODO This is a more limited version of 15m's Isochrone.
|
||||
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 {
|
||||
// Deliberately tiny
|
||||
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)
|
||||
{
|
||||
// Just start from both directions
|
||||
results.extend(r.id.both_directions());
|
||||
}
|
||||
}
|
||||
results
|
||||
}
|
Loading…
Reference in New Issue
Block a user