Explicitly model U-turns. Sometimes they're legal, often they get

generated incorrectly, but regardless, calling them TurnType::Left is
just confusing.

For the moment, always filter out U-turns from merged intersections.
When connections across merged one-ways are handled properly, we won't
need this, but in the meantime, it moves forward. #114

Not regenerating just yet, but will bundle it with the next commit.
This commit is contained in:
Dustin Carlino 2020-12-30 11:11:20 -08:00
parent de4b026920
commit 9bc761f98e
7 changed files with 42 additions and 12 deletions

View File

@ -110,7 +110,7 @@ impl DrawCar {
if let Some(t) = input.waiting_for_turn {
match map.get_t(t).turn_type {
TurnType::Left => {
TurnType::Left | TurnType::UTurn => {
let (pos, angle) = input
.body
.must_dist_along(input.body.length() - Distance::meters(2.5));

View File

@ -162,6 +162,11 @@ impl TurnExplorer {
TurnExplorer::color_turn_type(TurnType::Left),
"left turn",
));
col.push(ColorLegend::row(
ctx,
TurnExplorer::color_turn_type(TurnType::UTurn),
"U-turn",
));
}
} else {
let (lt, lc, slow_lane) = turns[idx - 1].penalty(app.map());
@ -194,6 +199,7 @@ impl TurnExplorer {
TurnType::Straight => Color::BLUE,
TurnType::Right => Color::GREEN,
TurnType::Left => Color::RED,
TurnType::UTurn => Color::PURPLE,
}
}
}

View File

@ -1,8 +1,13 @@
use crate::raw::{OriginalRoad, RawMap};
use std::collections::BTreeSet;
use crate::osm::NodeID;
use crate::raw::RawMap;
/// Merge tiny "roads" that're actually just part of a complicated intersection. Returns all
/// surviving intersections adjacent to one of these merged roads.
pub fn merge_short_roads(map: &mut RawMap) -> BTreeSet<NodeID> {
let mut merged = BTreeSet::new();
/// Experimentally try to merge tiny "roads" that're actually just part of a complicated
/// intersection.
pub fn merge_short_roads(map: &mut RawMap) {
// An expensive fixed-point approach. When we merge one road, the IDs of some other roads might
// change, so it's simplest just to start over.
// TODO But since merge_short_road tells us what road IDs were deleted and created, it wouldn't
@ -11,13 +16,9 @@ pub fn merge_short_roads(map: &mut RawMap) {
let mut changes = false;
for (id, road) in &map.roads {
// See https://wiki.openstreetmap.org/wiki/Proposed_features/junction%3Dintersection
// Hardcoding some Montlake intersections to test
if road.osm_tags.is("junction", "intersection")
|| *id == OriginalRoad::new(459084309, (4550007325, 4550007326))
|| *id == OriginalRoad::new(332060258, (3391701875, 1635790583))
{
if road.osm_tags.is("junction", "intersection") {
let id = *id;
map.merge_short_road(id).unwrap();
merged.insert(map.merge_short_road(id).unwrap().0);
changes = true;
break;
}
@ -26,4 +27,6 @@ pub fn merge_short_roads(map: &mut RawMap) {
break;
}
}
merged
}

View File

@ -36,7 +36,7 @@ impl Map {
// Better to defer this and see RawMaps with more debug info in map_editor
remove_disconnected::remove_disconnected_roads(&mut raw, timer);
merge_intersections::merge_short_roads(&mut raw);
let merged_intersections = merge_intersections::merge_short_roads(&mut raw);
timer.start("raw_map to InitialMap");
let gps_bounds = raw.gps_bounds.clone();
@ -88,6 +88,7 @@ impl Map {
incoming_lanes: Vec::new(),
outgoing_lanes: Vec::new(),
roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
merged: merged_intersections.contains(&i.id),
});
intersection_id_mapping.insert(i.id, id);
}

View File

@ -93,6 +93,20 @@ pub fn make_all_turns(map: &Map, i: &Intersection, timer: &mut Timer) -> Vec<Tur
final_turns = remove_merging_turns(map, final_turns, TurnType::Right);
final_turns = remove_merging_turns(map, final_turns, TurnType::Left);
if i.merged {
final_turns.retain(|turn| {
if turn.turn_type == TurnType::UTurn {
timer.warn(format!(
"Removing u-turn from merged intersection: {}",
turn.id
));
false
} else {
true
}
});
}
let mut outgoing_missing: HashSet<LaneID> = HashSet::new();
for l in &i.outgoing_lanes {
if map.get_l(*l).lane_type.supports_any_movement() {
@ -373,6 +387,8 @@ fn turn_type_from_angles(from: Angle, to: Angle) -> TurnType {
// some observed cases.
if diff.abs() < 30.0 {
TurnType::Straight
} else if diff.abs() > 135.0 {
TurnType::UTurn
} else if diff < 0.0 {
// Clockwise rotation
TurnType::Right

View File

@ -54,6 +54,9 @@ pub struct Intersection {
// TODO Maybe DirectedRoadIDs
pub roads: BTreeSet<RoadID>,
/// Was a short road adjacent to this intersection merged?
pub merged: bool,
}
impl Intersection {

View File

@ -33,6 +33,7 @@ pub enum TurnType {
Straight,
Right,
Left,
UTurn,
}
// TODO This concept may be dated, now that Movements exist. Within a movement, the lane-changing