From 8e7d54f13584d16fd1ab944e492e697484f8af67 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Sun, 21 Nov 2021 11:54:29 -0800 Subject: [PATCH] Add some explanation to the LTN route tool --- game/src/ltn/route.rs | 37 ++++++++++++++++++++++-------- map_model/src/pathfind/mod.rs | 3 ++- map_model/src/pathfind/vehicles.rs | 17 ++++++-------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/game/src/ltn/route.rs b/game/src/ltn/route.rs index f3a2c212f2..bf00993663 100644 --- a/game/src/ltn/route.rs +++ b/game/src/ltn/route.rs @@ -44,28 +44,32 @@ impl RoutePlanner { } fn update(&mut self, ctx: &mut EventCtx, app: &App) { - let mut new = Panel::new_builder(Widget::col(vec![ + let mut panel = Panel::new_builder(Widget::col(vec![ ctx.style() .btn_outline .text("Back to editing modal filters") .hotkey(Key::Escape) .build_def(ctx), + self.waypoints.get_panel_widget(ctx), Widget::row(vec![ - Line("Main Road Penalty").into_widget(ctx), + Line("Slow-down factor for main roads:") + .into_widget(ctx) + .centered_vert(), Spinner::f64_widget(ctx, "main road penalty", (1.0, 10.0), 1.0, 0.5), ]), - Line("Warning: Time estimates assume freeflow conditions (no traffic)") - .fg(Color::RED) - .into_widget(ctx), - self.waypoints.get_panel_widget(ctx), + Text::from_multiline(vec![ + Line("1 means free-flow traffic conditions").secondary(), + Line("Increase to see how vehicles may try to detour in heavy traffic").secondary(), + ]) + .into_widget(ctx), + Text::new().into_widget(ctx).named("note"), ])) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) // Hovering on waypoint cards .ignore_initial_events() .build(ctx); - - new.restore(ctx, &self.panel); - self.panel = new; + panel.restore(ctx, &self.panel); + self.panel = panel; let mut world = self.calculate_paths(ctx, app); self.waypoints @@ -75,7 +79,8 @@ impl RoutePlanner { self.world = world; } - fn calculate_paths(&self, ctx: &mut EventCtx, app: &App) -> World { + /// Also has the side effect of changing a note in the panel + fn calculate_paths(&mut self, ctx: &mut EventCtx, app: &App) -> World { let map = &app.primary.map; let mut world = World::bounded(map.get_bounds()); @@ -168,6 +173,9 @@ impl RoutePlanner { )); txt.add_line(Line(format!("Time: {}", total_time))); txt.add_line(Line(format!("Distance: {}", total_dist))); + + let label = Text::new().into_widget(ctx); + self.panel.replace(ctx, "note", label); } else { txt.add_line(Line("Route before the new modal filters")); txt.add_line(Line(format!("Time: {}", total_time))); @@ -186,6 +194,15 @@ impl RoutePlanner { "shorter", "longer", ); + + let label = Text::from_all(vec![ + Line("Blue path").fg(Color::BLUE), + Line(" before adding filters, "), + Line("red path").fg(Color::RED), + Line(" after new filters"), + ]) + .into_widget(ctx); + self.panel.replace(ctx, "note", label); } world diff --git a/map_model/src/pathfind/mod.rs b/map_model/src/pathfind/mod.rs index d65fc18b96..735ad388ad 100644 --- a/map_model/src/pathfind/mod.rs +++ b/map_model/src/pathfind/mod.rs @@ -178,7 +178,8 @@ pub struct RoutingParams { // If the road is `high_stress_for_bikes`, multiply by the base cost. pub avoid_high_stress: f64, - // How much to avoid main roads + /// When crossing an arterial or highway road, multiply the base cost by this penalty. When + /// greater than 1, this will encourage routes to use local roads more. #[serde(skip_serializing, skip_deserializing)] pub main_road_penalty: f64, diff --git a/map_model/src/pathfind/vehicles.rs b/map_model/src/pathfind/vehicles.rs index 20a6210982..68f88ef15e 100644 --- a/map_model/src/pathfind/vehicles.rs +++ b/map_model/src/pathfind/vehicles.rs @@ -275,14 +275,14 @@ pub fn vehicle_cost( params: &RoutingParams, map: &Map, ) -> Duration { + let road = map.get_r(dr.road); let movement = &map.get_i(mvmnt.parent).movements[&mvmnt]; let max_speed = match constraints { PathConstraints::Car | PathConstraints::Bus | PathConstraints::Train => None, PathConstraints::Bike => Some(crate::MAX_BIKE_SPEED), PathConstraints::Pedestrian => unreachable!(), }; - let t1 = map.get_r(dr.road).length() - / Traversable::max_speed_along_road(dr, max_speed, constraints, map).0; + let t1 = road.length() / Traversable::max_speed_along_road(dr, max_speed, constraints, map).0; let t2 = movement.geom.length() / Traversable::max_speed_along_movement(mvmnt, max_speed, constraints, map); @@ -320,7 +320,6 @@ pub fn vehicle_cost( if constraints == PathConstraints::Bike && (params.avoid_steep_incline_penalty - 1.0).abs() > f64::EPSILON { - let road = map.get_r(dr.road); let percent_incline = if dr.dir == Direction::Fwd { road.percent_incline } else { @@ -333,7 +332,7 @@ pub fn vehicle_cost( if constraints == PathConstraints::Bike && (params.avoid_high_stress - 1.0).abs() > f64::EPSILON - && map.get_r(dr.road).high_stress_for_bikes(map, dr.dir) + && road.high_stress_for_bikes(map, dr.dir) { multiplier *= params.avoid_high_stress; } @@ -344,12 +343,10 @@ pub fn vehicle_cost( extra += params.unprotected_turn_penalty } - // Slowdown factor, how much slower the traffic is compared to the - // original estimate. - if (params.main_road_penalty - 1.0).abs() > f64::EPSILON { - if map.get_r(dr.road).get_rank() != osm::RoadRank::Local { - multiplier *= params.main_road_penalty; - } + if (params.main_road_penalty - 1.0).abs() > f64::EPSILON + && road.get_rank() != osm::RoadRank::Local + { + multiplier *= params.main_road_penalty; } if params.avoid_roads.contains(&dr.road) {