mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
Start a very basic binary classifier for high-stress cycling road, with a layer to check it. Use this to filter the mode shift dashboard -- effectively revealing PCT-esque gaps in the infrastructure. #448, #494
This commit is contained in:
parent
06429d0d5f
commit
c5e769d276
@ -339,4 +339,27 @@ impl Static {
|
||||
Widget::nothing(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn high_stress(ctx: &mut EventCtx, app: &App) -> Static {
|
||||
let mut colorer = ColorDiscrete::new(app, vec![("high stress", app.cs.edits_layer)]);
|
||||
|
||||
for r in app.primary.map.all_roads() {
|
||||
if r.high_stress_for_bikes(&app.primary.map) {
|
||||
colorer.add_r(r.id, "high stress");
|
||||
}
|
||||
}
|
||||
|
||||
Static::new(
|
||||
ctx,
|
||||
colorer,
|
||||
"high stress",
|
||||
"High stress roads for biking".to_string(),
|
||||
Text::from_multiline(vec![
|
||||
Line("High stress defined as:"),
|
||||
Line("- arterial classification"),
|
||||
Line("- no dedicated cycle lane"),
|
||||
])
|
||||
.into_widget(ctx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ impl PickLayer {
|
||||
btn("parking efficiency", Key::O),
|
||||
btn("blackholes", Key::L),
|
||||
btn("problem map", Key::K),
|
||||
btn("high stress", Key::H),
|
||||
if app.primary.sim.get_pandemic_model().is_some() {
|
||||
btn("pandemic model", Key::Y)
|
||||
} else {
|
||||
@ -184,6 +185,9 @@ impl State<App> for PickLayer {
|
||||
"no sidewalks" => {
|
||||
app.primary.layer = Some(Box::new(map::Static::no_sidewalks(ctx, app)));
|
||||
}
|
||||
"high stress" => {
|
||||
app.primary.layer = Some(Box::new(map::Static::high_stress(ctx, app)));
|
||||
}
|
||||
"favorite buildings" => {
|
||||
app.primary.layer = Some(Box::new(favorites::ShowFavorites::new(ctx, app)));
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use abstutil::Counter;
|
||||
use geom::{Distance, Duration};
|
||||
use map_gui::tools::ColorNetwork;
|
||||
use map_model::PathStepV2;
|
||||
use map_model::{PathStepV2, RoadID};
|
||||
use sim::{TripEndpoint, TripID, TripMode};
|
||||
use widgetry::table::{Col, Filter, Table};
|
||||
use widgetry::{
|
||||
@ -289,6 +291,20 @@ fn show_route_gaps(ctx: &mut EventCtx, app: &App, table: &Table<App, Entry, Filt
|
||||
ctx.loading_screen("calculate all routes", |ctx, timer| {
|
||||
let map = &app.primary.map;
|
||||
let sim = &app.primary.sim;
|
||||
|
||||
// Find all high-stress roads, since we'll filter by them next
|
||||
let high_stress: HashSet<RoadID> = map
|
||||
.all_roads()
|
||||
.into_iter()
|
||||
.filter_map(|r| {
|
||||
if r.high_stress_for_bikes(map) {
|
||||
Some(r.id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut road_counter = Counter::new();
|
||||
for path in timer
|
||||
.parallelize("calculate routes", table.get_filtered_data(app), |entry| {
|
||||
@ -302,8 +318,9 @@ fn show_route_gaps(ctx: &mut EventCtx, app: &App, table: &Table<App, Entry, Filt
|
||||
for step in path.get_steps() {
|
||||
// No Contraflow steps for bike paths
|
||||
if let PathStepV2::Along(dr) = step {
|
||||
// TODO Filter by high-stress roads only!
|
||||
road_counter.inc(dr.id);
|
||||
if high_stress.contains(&dr.id) {
|
||||
road_counter.inc(dr.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -592,6 +592,31 @@ impl Road {
|
||||
}
|
||||
panic!("{} doesn't contain both {} and {}", self.id, l1, l2);
|
||||
}
|
||||
|
||||
/// A simple classification of if the road is stressful or not for cycling. Arterial roads
|
||||
/// without a bike lane match this. Why arterial, instead of looking at speed limits? Even on
|
||||
/// arterial roads with official speed limits lowered, in practice vehicles still travel at the
|
||||
/// speed suggested by the design of the road.
|
||||
// TODO No treatment of direction
|
||||
// TODO Should elevation matter or not? Flat high-speed roads are still terrifying, but there's
|
||||
// something about slogging up (or flying down!) a pothole-filled road inches from cars.
|
||||
pub fn high_stress_for_bikes(&self, map: &Map) -> bool {
|
||||
let mut bike_lanes = false;
|
||||
let mut can_use = false;
|
||||
// Can a bike even use it, or is it a highway?
|
||||
for (l, _, lt) in self.lanes_ltr() {
|
||||
if lt == LaneType::Biking {
|
||||
bike_lanes = true;
|
||||
}
|
||||
if PathConstraints::Bike.can_use(map.get_l(l), map) {
|
||||
can_use = true;
|
||||
}
|
||||
}
|
||||
if !can_use || bike_lanes {
|
||||
return false;
|
||||
}
|
||||
self.get_rank() == osm::RoadRank::Arterial
|
||||
}
|
||||
}
|
||||
|
||||
// TODO All of this is kind of deprecated? During the transiton towards lanes_ltr, some pieces
|
||||
|
Loading…
Reference in New Issue
Block a user