From 1e3708f9b4de509391bcc42fe6cbe78a25381140 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Mon, 5 Apr 2021 10:05:27 -0700 Subject: [PATCH] Remove UberTurnGroup and the prototype of editing a cluster of traffic signals using uber turn groups. #555 This was an old half-baked experiment for handling a cluster of traffic signals. Since then, merging intersections (by manually tagging them in OSM for now, maybe automatically in the future) has proven better. Removing this old code in preparation for pathfinding v2. --- game/src/debug/uber_turns.rs | 20 ----- game/src/edit/cluster_traffic_signals.rs | 101 ----------------------- game/src/edit/mod.rs | 2 - map_gui/src/render/mod.rs | 2 +- map_gui/src/render/turn.rs | 67 +-------------- map_model/src/lib.rs | 2 +- map_model/src/pathfind/dijkstra.rs | 2 + map_model/src/pathfind/uber_turns.rs | 101 +---------------------- 8 files changed, 7 insertions(+), 290 deletions(-) delete mode 100644 game/src/edit/cluster_traffic_signals.rs diff --git a/game/src/debug/uber_turns.rs b/game/src/debug/uber_turns.rs index 82f8311fbf..9356103ab5 100644 --- a/game/src/debug/uber_turns.rs +++ b/game/src/debug/uber_turns.rs @@ -12,7 +12,6 @@ use widgetry::{ use crate::app::{App, ShowEverything, Transition}; use crate::common::CommonState; -use crate::edit::ClusterTrafficSignalEditor; pub struct UberTurnPicker { members: BTreeSet, @@ -39,11 +38,6 @@ impl UberTurnPicker { .text("View uber-turns") .hotkey(Key::Enter) .build_def(ctx), - ctx.style() - .btn_outline - .text("Edit") - .hotkey(Key::E) - .build_def(ctx), ctx.style() .btn_outline .text("Detect all clusters") @@ -70,20 +64,6 @@ impl SimpleState for UberTurnPicker { } Transition::Replace(UberTurnViewer::new(ctx, app, self.members.clone(), 0, true)) } - "Edit" => { - if self.members.len() < 2 { - return Transition::Push(PopupMsg::new( - ctx, - "Error", - vec!["Select at least two intersections"], - )); - } - Transition::Replace(ClusterTrafficSignalEditor::new( - ctx, - app, - &IntersectionCluster::new(self.members.clone(), &app.primary.map).0, - )) - } "Detect all clusters" => { self.members.clear(); for ic in IntersectionCluster::find_all(&app.primary.map) { diff --git a/game/src/edit/cluster_traffic_signals.rs b/game/src/edit/cluster_traffic_signals.rs deleted file mode 100644 index cc5c526f58..0000000000 --- a/game/src/edit/cluster_traffic_signals.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::collections::BTreeSet; - -use geom::ArrowCap; -use map_gui::render::{DrawOptions, DrawUberTurnGroup, BIG_ARROW_THICKNESS}; -use map_model::{IntersectionCluster, IntersectionID}; -use widgetry::{ - DrawBaselayer, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Outcome, Panel, State, - VerticalAlignment, Widget, -}; - -use crate::app::Transition; -use crate::app::{App, ShowEverything}; - -pub struct ClusterTrafficSignalEditor { - panel: Panel, - - members: BTreeSet, - groups: Vec, - group_selected: Option, -} - -impl ClusterTrafficSignalEditor { - pub fn new(ctx: &mut EventCtx, app: &mut App, ic: &IntersectionCluster) -> Box> { - app.primary.current_selection = None; - Box::new(ClusterTrafficSignalEditor { - panel: Panel::new(Widget::row(vec![ctx - .style() - .btn_solid_primary - .text("Finish") - .hotkey(Key::Escape) - .build_def(ctx)])) - .aligned(HorizontalAlignment::Center, VerticalAlignment::Top) - .build(ctx), - groups: DrawUberTurnGroup::new(ic, &app.primary.map), - group_selected: None, - members: ic.members.clone(), - }) - } -} - -impl State for ClusterTrafficSignalEditor { - fn event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Transition { - match self.panel.event(ctx) { - Outcome::Clicked(x) => match x.as_ref() { - "Finish" => { - return Transition::Pop; - } - _ => unreachable!(), - }, - _ => {} - } - - ctx.canvas_movement(); - if ctx.redo_mouseover() { - self.group_selected = None; - if let Some(pt) = ctx.canvas.get_cursor_in_map_space() { - for (idx, g) in self.groups.iter().enumerate() { - if g.block.contains_pt(pt) { - self.group_selected = Some(idx); - break; - } - } - } - } - - Transition::Keep - } - - fn draw_baselayer(&self) -> DrawBaselayer { - DrawBaselayer::Custom - } - - fn draw(&self, g: &mut GfxCtx, app: &App) { - { - let mut opts = DrawOptions::new(); - opts.suppress_traffic_signal_details - .extend(self.members.clone()); - app.draw(g, opts, &ShowEverything::new()); - } - - let mut batch = GeomBatch::new(); - for (idx, g) in self.groups.iter().enumerate() { - if Some(idx) == self.group_selected { - batch.push(app.cs.selected, g.block.clone()); - batch.push( - app.cs.selected, - g.group - .geom - .make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle), - ); - } else { - batch.push(app.cs.signal_turn_block_bg, g.block.clone()); - } - let arrow_color = app.cs.signal_protected_turn; - batch.push(arrow_color, g.arrow.clone()); - } - batch.draw(g); - - self.panel.draw(g); - } -} diff --git a/game/src/edit/mod.rs b/game/src/edit/mod.rs index d3ae074ab2..88f68037c3 100644 --- a/game/src/edit/mod.rs +++ b/game/src/edit/mod.rs @@ -14,7 +14,6 @@ use widgetry::{ Key, Line, Menu, Outcome, Panel, State, Text, TextExt, VerticalAlignment, Widget, }; -pub use self::cluster_traffic_signals::ClusterTrafficSignalEditor; pub use self::lanes::LaneEditor; pub use self::routes::RouteEditor; pub use self::stop_signs::StopSignEditor; @@ -26,7 +25,6 @@ use crate::debug::DebugMode; use crate::sandbox::{GameplayMode, SandboxMode, TimeWarpScreen}; mod bulk; -mod cluster_traffic_signals; mod lanes; mod routes; mod select; diff --git a/map_gui/src/render/mod.rs b/map_gui/src/render/mod.rs index 871a1bb686..35bdd8f070 100644 --- a/map_gui/src/render/mod.rs +++ b/map_gui/src/render/mod.rs @@ -14,7 +14,7 @@ use crate::render::car::DrawCar; pub use crate::render::intersection::{calculate_corners, DrawIntersection}; pub use crate::render::map::DrawMap; pub use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian}; -pub use crate::render::turn::{DrawMovement, DrawUberTurnGroup}; +pub use crate::render::turn::DrawMovement; use crate::{AppLike, ID}; mod agents; diff --git a/map_gui/src/render/turn.rs b/map_gui/src/render/turn.rs index 71a519bd88..239b95ee4a 100644 --- a/map_gui/src/render/turn.rs +++ b/map_gui/src/render/turn.rs @@ -1,10 +1,7 @@ use std::collections::{HashMap, HashSet}; use geom::{Angle, ArrowCap, Circle, Distance, PolyLine, Polygon}; -use map_model::{ - IntersectionCluster, IntersectionID, LaneID, Map, MovementID, TurnPriority, UberTurnGroup, - SIDEWALK_THICKNESS, -}; +use map_model::{IntersectionID, LaneID, Map, MovementID, TurnPriority, SIDEWALK_THICKNESS}; use widgetry::{Color, GeomBatch, Prerender}; use crate::colors::ColorScheme; @@ -181,68 +178,6 @@ impl DrawMovement { } } -pub struct DrawUberTurnGroup { - pub group: UberTurnGroup, - pub block: Polygon, - pub arrow: Polygon, -} - -impl DrawUberTurnGroup { - pub fn new(ic: &IntersectionCluster, map: &Map) -> Vec { - let mut offset_per_lane: HashMap = HashMap::new(); - let mut draw = Vec::new(); - for group in ic.uber_turn_groups(map) { - let offset = group - .members - .iter() - .map(|ut| *offset_per_lane.entry(ut.entry()).or_insert(0)) - .max() - .unwrap(); - let (pl, width) = group.src_center_and_width(map); - let (block, arrow) = make_block_geom(offset as f64, pl, width, group.angle()); - let mut seen_lanes = HashSet::new(); - for ut in &group.members { - if !seen_lanes.contains(&ut.entry()) { - *offset_per_lane.get_mut(&ut.entry()).unwrap() = offset + 1; - seen_lanes.insert(ut.entry()); - } - } - - draw.push(DrawUberTurnGroup { - group, - block, - arrow, - }); - } - draw - } -} - -// Produces (block, arrow) -fn make_block_geom(offset: f64, pl: PolyLine, width: Distance, angle: Angle) -> (Polygon, Polygon) { - let height = TURN_ICON_ARROW_LENGTH; - // Always extend the pl first to handle short entry lanes - let extension = PolyLine::must_new(vec![ - pl.last_pt(), - pl.last_pt() - .project_away(Distance::meters(500.0), pl.last_line().angle()), - ]); - let pl = pl.must_extend(extension); - let slice = pl.exact_slice(offset * height, (offset + 1.0) * height); - let block = slice.make_polygons(width); - - let arrow = { - let center = slice.middle(); - PolyLine::must_new(vec![ - center.project_away(TURN_ICON_ARROW_LENGTH / 2.0, angle.opposite()), - center.project_away(TURN_ICON_ARROW_LENGTH / 2.0, angle), - ]) - .make_arrow(Distance::meters(0.5), ArrowCap::Triangle) - }; - - (block, arrow) -} - // Produces (circle, arrow) fn make_circle_geom(offset: f64, pl: PolyLine, angle: Angle) -> (Polygon, Polygon) { let height = 2.0 * TURN_ICON_ARROW_LENGTH; diff --git a/map_model/src/lib.rs b/map_model/src/lib.rs index 9ebfc55427..0adda4ca1f 100644 --- a/map_model/src/lib.rs +++ b/map_model/src/lib.rs @@ -54,7 +54,7 @@ pub use crate::objects::turn::{ CompressedMovementID, Movement, MovementID, Turn, TurnID, TurnPriority, TurnType, }; pub use crate::objects::zone::{AccessRestrictions, Zone}; -pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn, UberTurnGroup}; +pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn}; use crate::pathfind::Pathfinder; pub use crate::pathfind::{Path, PathConstraints, PathRequest, PathStep, RoutingParams}; pub use crate::traversable::{Position, Traversable, MAX_BIKE_SPEED, MAX_WALKING_SPEED}; diff --git a/map_model/src/pathfind/dijkstra.rs b/map_model/src/pathfind/dijkstra.rs index c5cc3bd484..1cfa22ea8c 100644 --- a/map_model/src/pathfind/dijkstra.rs +++ b/map_model/src/pathfind/dijkstra.rs @@ -1,5 +1,7 @@ //! Pathfinding without needing to build a separate contraction hierarchy. +// TODO Dijkstra's for vehicles currently ignores uber-turns! + use std::collections::BTreeSet; use petgraph::graphmap::DiGraphMap; diff --git a/map_model/src/pathfind/uber_turns.rs b/map_model/src/pathfind/uber_turns.rs index 2dd505a08f..2031edf257 100644 --- a/map_model/src/pathfind/uber_turns.rs +++ b/map_model/src/pathfind/uber_turns.rs @@ -6,14 +6,12 @@ use std::collections::{BTreeMap, BTreeSet}; use petgraph::graphmap::UnGraphMap; use serde::{Deserialize, Serialize}; -use abstutil::MultiMap; -use geom::{Angle, Distance, PolyLine, Pt2D}; +use geom::{Distance, PolyLine}; -use crate::{DirectedRoadID, Direction, IntersectionID, LaneID, Map, TurnID}; +use crate::{IntersectionID, LaneID, Map, TurnID}; /// This only applies to VehiclePathfinder; walking through these intersections is nothing special. // TODO I haven't seen any cases yet with "interior" intersections. Some stuff might break. -#[derive(Clone, Serialize, Deserialize)] pub struct IntersectionCluster { pub members: BTreeSet, pub uber_turns: Vec, @@ -256,98 +254,3 @@ impl UberTurn { pl } } - -pub struct UberTurnGroup { - pub from: DirectedRoadID, - pub to: DirectedRoadID, - pub members: Vec, - pub geom: PolyLine, -} - -impl IntersectionCluster { - pub fn uber_turn_groups(&self, map: &Map) -> Vec { - // TODO LaneType should also be part of the grouping... the entry? exit? everything in - // between? What about mixes? - let mut groups: MultiMap<(DirectedRoadID, DirectedRoadID), usize> = MultiMap::new(); - for (idx, ut) in self.uber_turns.iter().enumerate() { - groups.insert( - ( - map.get_l(ut.entry()).get_directed_parent(map), - map.get_l(ut.exit()).get_directed_parent(map), - ), - idx, - ); - } - - let mut result = Vec::new(); - for ((from, to), member_indices) in groups.consume() { - let mut members = Vec::new(); - let mut polylines = Vec::new(); - for idx in member_indices { - polylines.push(self.uber_turns[idx].geom(map)); - members.push(self.uber_turns[idx].clone()); - } - result.push(UberTurnGroup { - from, - to, - members, - geom: group_geom(polylines), - }); - } - result - } -} - -impl UberTurnGroup { - // TODO Share code with TurnGroup - /// Polyline points FROM intersection - pub fn src_center_and_width(&self, map: &Map) -> (PolyLine, Distance) { - let r = map.get_r(self.from.id); - - let mut leftmost = Distance::meters(99999.0); - let mut rightmost = Distance::ZERO; - let mut left = Distance::ZERO; - - for (l, _, _) in r.lanes_ltr() { - let right = left + map.get_l(l).width; - - if self.members.iter().any(|ut| ut.entry() == l) { - leftmost = leftmost.min(left); - rightmost = rightmost.max(right); - } - - left = right; - } - - let mut pl = r - .get_left_side(map) - .must_shift_right((leftmost + rightmost) / 2.0); - // Point towards the intersection - if self.from.dir == Direction::Back { - pl = pl.reversed(); - } - // Flip direction, so we point away from the intersection - (pl.reversed(), rightmost - leftmost) - } - - pub fn angle(&self) -> Angle { - self.geom.first_pt().angle_to(self.geom.last_pt()) - } -} - -fn group_geom(mut polylines: Vec) -> PolyLine { - let num_pts = polylines[0].points().len(); - for pl in &polylines { - if num_pts != pl.points().len() { - return polylines.remove(0); - } - } - - let mut pts = Vec::new(); - for idx in 0..num_pts { - pts.push(Pt2D::center( - &polylines.iter().map(|pl| pl.points()[idx]).collect(), - )); - } - PolyLine::must_new(pts) -}