From 64082501ebc9556c8fece446afde2267a7ac96c3 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Sun, 15 Mar 2020 12:47:14 -0700 Subject: [PATCH] plot elevation over time for bikes and peds, guarded behind dev mode --- game/src/common/info.rs | 71 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/game/src/common/info.rs b/game/src/common/info.rs index 449cf923c3..9b1c35729c 100644 --- a/game/src/common/info.rs +++ b/game/src/common/info.rs @@ -13,7 +13,7 @@ use ezgui::{ VerticalAlignment, }; use geom::{Angle, Circle, Distance, Duration, Polygon, Pt2D, Statistic, Time}; -use map_model::{BuildingID, IntersectionID, IntersectionType}; +use map_model::{BuildingID, IntersectionID, IntersectionType, Map, Path, PathStep}; use sim::{ AgentID, Analytics, CarID, PersonID, PersonState, TripEnd, TripID, TripMode, TripPhaseType, TripResult, TripStart, VehicleType, @@ -446,6 +446,7 @@ fn info_for( )); } + // TODO Simplify and expose everywhere after there's better data kv.push(( "Elevation change".to_string(), format!( @@ -454,6 +455,18 @@ fn info_for( map.get_i(l.dst_i).elevation ), )); + kv.push(( + "Incline / grade".to_string(), + format!("{:.1}%", l.percent_grade(map) * 100.0), + )); + kv.push(( + "Elevation details".to_string(), + format!( + "{} over {}", + map.get_i(l.dst_i).elevation - map.get_i(l.src_i).elevation, + l.length() + ), + )); for (k, v) in &r.osm_tags { kv.push((k.to_string(), v.to_string())); @@ -1127,6 +1140,7 @@ fn trip_details( let total_width = 0.3 * ctx.canvas.window_width; let mut timeline = Vec::new(); let num_phases = phases.len(); + let mut elevation = Vec::new(); for (idx, p) in phases.into_iter().enumerate() { let color = match p.phase_type { TripPhaseType::Driving => Color::hex("#D63220"), @@ -1215,6 +1229,18 @@ fn trip_details( // TODO Could really cache this between live updates if let Some((dist, ref path)) = p.path { + if app.opts.dev + && (p.phase_type == TripPhaseType::Walking || p.phase_type == TripPhaseType::Biking) + { + elevation.push(make_elevation( + ctx, + color, + p.phase_type == TripPhaseType::Walking, + path, + map, + )); + } + if let Some(trace) = path.trace(map, dist, None) { unzoomed.push(color, trace.make_polygons(Distance::meters(10.0))); zoomed.extend( @@ -1244,6 +1270,7 @@ fn trip_details( .evenly_spaced() .margin_above(25)]; col.extend(make_table(ctx, table)); + col.extend(elevation); if let Some(p) = app.primary.sim.trip_to_person(trip) { col.push( ManagedWidget::btn(Button::text_bg( @@ -1318,3 +1345,45 @@ fn strip_prefix_usize(x: &String, prefix: &str) -> Option { None } } + +fn make_elevation( + ctx: &EventCtx, + color: Color, + walking: bool, + path: &Path, + map: &Map, +) -> ManagedWidget { + let mut pts: Vec<(Distance, Distance)> = Vec::new(); + let mut dist = Distance::ZERO; + for step in path.get_steps() { + if let PathStep::Turn(t) = step { + pts.push((dist, map.get_i(t.parent).elevation)); + } + dist += step.as_traversable().length(map); + } + // TODO Plot needs to support Distance as both X and Y axis. :P + // TODO Show roughly where we are in the trip; use distance covered by current path for this + Plot::new_usize( + ctx, + vec![Series { + label: if walking { + "Elevation for walking" + } else { + "Elevation for biking" + } + .to_string(), + color, + pts: pts + .into_iter() + .map(|(x, y)| { + ( + Time::START_OF_DAY + Duration::seconds(x.inner_meters()), + y.inner_meters() as usize, + ) + }) + .collect(), + }], + PlotOptions::new(), + ) + .bg(colors::PANEL_BG) +}