Make the LTN impact UI easier to see. Draw less stuff, only focus on roads with changes [rebuild] [release]

This commit is contained in:
Dustin Carlino 2022-03-28 11:13:17 +01:00
parent 33eac8cba8
commit d6dc4332b0
3 changed files with 30 additions and 21 deletions

View File

@ -73,7 +73,7 @@ impl SimpleState<App> for GenericCompareCounts {
Transition::Keep Transition::Keep
} }
fn draw(&self, g: &mut GfxCtx, _: &App) { fn draw(&self, g: &mut GfxCtx, app: &App) {
self.compare.draw(g); self.compare.draw(g, app);
} }
} }

View File

@ -5,8 +5,8 @@ use map_model::{Path, NORMAL_LANE_THICKNESS};
use synthpop::{Scenario, TripMode}; use synthpop::{Scenario, TripMode};
use widgetry::tools::{FileLoader, PopupMsg}; use widgetry::tools::{FileLoader, PopupMsg};
use widgetry::{ use widgetry::{
Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, Slider, Color, DrawBaselayer, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
State, Text, TextExt, Toggle, VerticalAlignment, Widget, Outcome, Panel, Slider, State, Text, TextExt, Toggle, VerticalAlignment, Widget,
}; };
use crate::impact::{end_of_day, Filters, Impact}; use crate::impact::{end_of_day, Filters, Impact};
@ -18,7 +18,6 @@ use crate::{colors, App, BrowseNeighborhoods, Transition};
pub struct ShowResults { pub struct ShowResults {
top_panel: Panel, top_panel: Panel,
left_panel: Panel, left_panel: Panel,
draw_all_neighborhoods: Drawable,
} }
impl ShowResults { impl ShowResults {
@ -53,7 +52,14 @@ impl ShowResults {
.hotkey(Key::Escape) .hotkey(Key::Escape)
.build_def(ctx), .build_def(ctx),
Line("Impact prediction").small_heading().into_widget(ctx), Line("Impact prediction").small_heading().into_widget(ctx),
Text::from(Line("This tool starts with a travel demand model, calculates the route every trip takes before and after changes, and displays volumes along roads and intersections")).wrap_to_pct(ctx, 20).into_widget(ctx), Text::from(Line("This tool starts with a travel demand model, calculates the route every trip takes before and after changes, and displays volumes along roads")).wrap_to_pct(ctx, 20).into_widget(ctx),
Text::from_all(vec![
Line("Red").fg(Color::RED),
Line(" roads have increased volume, and "),
Line("green").fg(Color::GREEN),
Line(" roads have less. Width of the road shows how much baseline traffic it has."),
]).wrap_to_pct(ctx, 20).into_widget(ctx),
"Click a road to see changed routes through it.".text_widget(ctx),
// TODO Dropdown for the scenario, and explain its source/limitations // TODO Dropdown for the scenario, and explain its source/limitations
app.session.impact.filters.to_panel(ctx, app), app.session.impact.filters.to_panel(ctx, app),
app.session.impact.compare_counts.get_panel_widget(ctx).named("compare counts"), app.session.impact.compare_counts.get_panel_widget(ctx).named("compare counts"),
@ -62,15 +68,9 @@ impl ShowResults {
let top_panel = crate::common::app_top_panel(ctx, app); let top_panel = crate::common::app_top_panel(ctx, app);
let left_panel = crate::common::left_panel_builder(ctx, &top_panel, contents).build(ctx); let left_panel = crate::common::left_panel_builder(ctx, &top_panel, contents).build(ctx);
let mut batch = GeomBatch::new();
for (_, (block, color)) in app.session.partitioning.all_neighborhoods() {
batch.push(color.alpha(0.2), block.polygon.clone());
}
let draw_all_neighborhoods = batch.upload(ctx);
Box::new(Self { Box::new(Self {
top_panel, top_panel,
left_panel, left_panel,
draw_all_neighborhoods,
}) })
} }
} }
@ -145,12 +145,21 @@ impl State<App> for ShowResults {
Transition::Keep Transition::Keep
} }
fn draw_baselayer(&self) -> DrawBaselayer {
DrawBaselayer::Custom
}
fn draw(&self, g: &mut GfxCtx, app: &App) { fn draw(&self, g: &mut GfxCtx, app: &App) {
// Just emphasize roads that've changed, so don't draw the baselayer of roads. Even
// buildings are a distraction.
g.clear(app.cs.void_background);
g.redraw(&app.draw_map.boundary_polygon);
g.redraw(&app.draw_map.draw_all_areas);
app.session.impact.compare_counts.draw(g, app);
app.session.draw_all_filters.draw(g);
self.top_panel.draw(g); self.top_panel.draw(g);
self.left_panel.draw(g); self.left_panel.draw(g);
g.redraw(&self.draw_all_neighborhoods);
app.session.impact.compare_counts.draw(g);
app.session.draw_all_filters.draw(g);
} }
} }

View File

@ -118,7 +118,7 @@ impl CompareCounts {
.section(ctx) .section(ctx)
} }
pub fn draw(&self, g: &mut GfxCtx) { pub fn draw(&self, g: &mut GfxCtx, app: &dyn AppLike) {
match self.layer { match self.layer {
Layer::A => { Layer::A => {
self.heatmap_a.draw(g); self.heatmap_a.draw(g);
@ -138,7 +138,7 @@ impl CompareCounts {
Layer::A => self.counts_a.per_road.get(r), Layer::A => self.counts_a.per_road.get(r),
Layer::B => self.counts_b.per_road.get(r), Layer::B => self.counts_b.per_road.get(r),
Layer::Compare => { Layer::Compare => {
g.draw_mouse_tooltip(self.relative_road_tooltip(r)); g.draw_mouse_tooltip(self.relative_road_tooltip(app, r));
return; return;
} }
}, },
@ -154,12 +154,13 @@ impl CompareCounts {
} }
} }
fn relative_road_tooltip(&self, r: RoadID) -> Text { fn relative_road_tooltip(&self, app: &dyn AppLike, r: RoadID) -> Text {
let a = self.counts_a.per_road.get(r); let a = self.counts_a.per_road.get(r);
let b = self.counts_b.per_road.get(r); let b = self.counts_b.per_road.get(r);
let ratio = (b as f64) / (a as f64); let ratio = (b as f64) / (a as f64);
let mut txt = Text::from_multiline(vec![ let mut txt = Text::from_multiline(vec![
Line(app.map().get_r(r).get_name(app.opts().language.as_ref())),
Line(format!( Line(format!(
"{}: {}", "{}: {}",
self.counts_a.description, self.counts_a.description,
@ -242,8 +243,7 @@ fn calculate_relative_heatmap(
info!("Physical road widths: {}", hgram_width.describe()); info!("Physical road widths: {}", hgram_width.describe());
// TODO This is still a bit arbitrary // TODO This is still a bit arbitrary
let scale = DivergingScale::new(Color::hex("#5D9630"), Color::WHITE, Color::hex("#A32015")) let scale = DivergingScale::new(Color::GREEN, Color::grey(0.2), Color::RED).range(0.0, 2.0);
.range(0.0, 2.0);
// Draw road width based on the count before // Draw road width based on the count before
// TODO unwrap will crash on an empty demand model // TODO unwrap will crash on an empty demand model
@ -266,7 +266,7 @@ fn calculate_relative_heatmap(
(before - min_count) as f64 / (max_count - min_count) as f64 (before - min_count) as f64 / (max_count - min_count) as f64
}; };
// TODO Pretty arbitrary. Ideally we'd hide roads and intersections underneath... // TODO Pretty arbitrary. Ideally we'd hide roads and intersections underneath...
let width = Distance::meters(2.0) + pct_count * Distance::meters(10.0); let width = Distance::meters(6.0) + pct_count * Distance::meters(15.0);
draw_roads.push(color, app.map().get_r(r).center_pts.make_polygons(width)); draw_roads.push(color, app.map().get_r(r).center_pts.make_polygons(width));
} }