mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-18 20:02:18 +03:00
Add elevation details to routing results
This commit is contained in:
parent
a05a4f534c
commit
7e3802a519
@ -893,14 +893,6 @@ fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map:
|
|||||||
dist += step.as_traversable().get_polyline(map).length();
|
dist += step.as_traversable().get_polyline(map).length();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Cache this value?
|
|
||||||
let max_elevation = map
|
|
||||||
.all_intersections()
|
|
||||||
.iter()
|
|
||||||
.max_by_key(|i| i.elevation)
|
|
||||||
.unwrap()
|
|
||||||
.elevation;
|
|
||||||
|
|
||||||
// TODO Show roughly where we are in the trip; use distance covered by current path for this
|
// TODO Show roughly where we are in the trip; use distance covered by current path for this
|
||||||
LinePlot::new_widget(
|
LinePlot::new_widget(
|
||||||
ctx,
|
ctx,
|
||||||
@ -921,7 +913,7 @@ fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map:
|
|||||||
// If we use the max elevation encountered along the route, then no matter how we
|
// If we use the max elevation encountered along the route, then no matter how we
|
||||||
// round, there are always edge cases where the scale will jump. So just use the
|
// round, there are always edge cases where the scale will jump. So just use the
|
||||||
// maximum elevation from the entire map.
|
// maximum elevation from the entire map.
|
||||||
max_y: Some(max_elevation.round_up_for_axis()),
|
max_y: Some(map.max_elevation().round_up_for_axis()),
|
||||||
disabled: HashSet::new(),
|
disabled: HashSet::new(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
|
||||||
use geom::{Circle, Distance, Duration, FindClosest, Polygon};
|
use geom::{Circle, Distance, Duration, FindClosest, Polygon};
|
||||||
use map_model::NORMAL_LANE_THICKNESS;
|
use map_model::{PathStep, NORMAL_LANE_THICKNESS};
|
||||||
use sim::{TripEndpoint, TripMode};
|
use sim::{TripEndpoint, TripMode};
|
||||||
use widgetry::{
|
use widgetry::{
|
||||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel,
|
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, LinePlot,
|
||||||
State, Text, TextExt, VerticalAlignment, Widget,
|
Outcome, Panel, PlotOptions, Series, State, Text, TextExt, VerticalAlignment, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::app::{App, Transition};
|
use crate::app::{App, Transition};
|
||||||
@ -167,6 +169,9 @@ impl RoutePlanner {
|
|||||||
let mut total_distance = Distance::ZERO;
|
let mut total_distance = Distance::ZERO;
|
||||||
let mut total_time = Duration::ZERO;
|
let mut total_time = Duration::ZERO;
|
||||||
|
|
||||||
|
let mut elevation_pts: Vec<(Distance, Distance)> = Vec::new();
|
||||||
|
let mut current_dist = Distance::ZERO;
|
||||||
|
|
||||||
for pair in self.waypoints.windows(2) {
|
for pair in self.waypoints.windows(2) {
|
||||||
if let Some((path, draw_path)) =
|
if let Some((path, draw_path)) =
|
||||||
TripEndpoint::path_req(pair[0].at, pair[1].at, TripMode::Bike, map)
|
TripEndpoint::path_req(pair[0].at, pair[1].at, TripMode::Bike, map)
|
||||||
@ -179,11 +184,29 @@ impl RoutePlanner {
|
|||||||
batch.push(Color::CYAN, draw_path);
|
batch.push(Color::CYAN, draw_path);
|
||||||
total_distance += path.total_length();
|
total_distance += path.total_length();
|
||||||
total_time += path.estimate_duration(map, Some(map_model::MAX_BIKE_SPEED));
|
total_time += path.estimate_duration(map, Some(map_model::MAX_BIKE_SPEED));
|
||||||
|
|
||||||
|
for step in path.get_steps() {
|
||||||
|
if let PathStep::Turn(t) = step {
|
||||||
|
elevation_pts.push((current_dist, map.get_i(t.parent).elevation));
|
||||||
|
}
|
||||||
|
current_dist += step.as_traversable().get_polyline(map).length();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.draw_route = ctx.upload(batch);
|
self.draw_route = ctx.upload(batch);
|
||||||
|
|
||||||
|
let mut total_up = Distance::ZERO;
|
||||||
|
let mut total_down = Distance::ZERO;
|
||||||
|
for pair in elevation_pts.windows(2) {
|
||||||
|
let dy = pair[1].1 - pair[0].1;
|
||||||
|
if dy < Distance::ZERO {
|
||||||
|
total_down -= dy;
|
||||||
|
} else {
|
||||||
|
total_up += dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.results_panel = Panel::new_builder(Widget::col(vec![
|
self.results_panel = Panel::new_builder(Widget::col(vec![
|
||||||
Line("Your route").small_heading().into_widget(ctx),
|
Line("Your route").small_heading().into_widget(ctx),
|
||||||
Text::from_all(vec![
|
Text::from_all(vec![
|
||||||
@ -196,6 +219,29 @@ impl RoutePlanner {
|
|||||||
Line(total_time.to_string(&app.opts.units)),
|
Line(total_time.to_string(&app.opts.units)),
|
||||||
])
|
])
|
||||||
.into_widget(ctx),
|
.into_widget(ctx),
|
||||||
|
Text::from_all(vec![
|
||||||
|
Line("Elevation change: ").secondary(),
|
||||||
|
Line(format!(
|
||||||
|
"{}↑, {}↓",
|
||||||
|
total_up.to_string(&app.opts.units),
|
||||||
|
total_down.to_string(&app.opts.units)
|
||||||
|
)),
|
||||||
|
])
|
||||||
|
.into_widget(ctx),
|
||||||
|
LinePlot::new_widget(
|
||||||
|
ctx,
|
||||||
|
vec![Series {
|
||||||
|
label: "Elevation".to_string(),
|
||||||
|
color: Color::RED,
|
||||||
|
pts: elevation_pts,
|
||||||
|
}],
|
||||||
|
PlotOptions {
|
||||||
|
filterable: false,
|
||||||
|
max_x: Some(current_dist.round_up_for_axis()),
|
||||||
|
max_y: Some(map.max_elevation().round_up_for_axis()),
|
||||||
|
disabled: HashSet::new(),
|
||||||
|
},
|
||||||
|
),
|
||||||
]))
|
]))
|
||||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||||
.build(ctx);
|
.build(ctx);
|
||||||
|
@ -789,4 +789,14 @@ impl Map {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the highest elevation in the map
|
||||||
|
pub fn max_elevation(&self) -> Distance {
|
||||||
|
// TODO Cache?
|
||||||
|
self.all_intersections()
|
||||||
|
.iter()
|
||||||
|
.max_by_key(|i| i.elevation)
|
||||||
|
.unwrap()
|
||||||
|
.elevation
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user