mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 02:33:54 +03:00
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:
parent
de4b026920
commit
9bc761f98e
@ -110,7 +110,7 @@ impl DrawCar {
|
|||||||
|
|
||||||
if let Some(t) = input.waiting_for_turn {
|
if let Some(t) = input.waiting_for_turn {
|
||||||
match map.get_t(t).turn_type {
|
match map.get_t(t).turn_type {
|
||||||
TurnType::Left => {
|
TurnType::Left | TurnType::UTurn => {
|
||||||
let (pos, angle) = input
|
let (pos, angle) = input
|
||||||
.body
|
.body
|
||||||
.must_dist_along(input.body.length() - Distance::meters(2.5));
|
.must_dist_along(input.body.length() - Distance::meters(2.5));
|
||||||
|
@ -162,6 +162,11 @@ impl TurnExplorer {
|
|||||||
TurnExplorer::color_turn_type(TurnType::Left),
|
TurnExplorer::color_turn_type(TurnType::Left),
|
||||||
"left turn",
|
"left turn",
|
||||||
));
|
));
|
||||||
|
col.push(ColorLegend::row(
|
||||||
|
ctx,
|
||||||
|
TurnExplorer::color_turn_type(TurnType::UTurn),
|
||||||
|
"U-turn",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (lt, lc, slow_lane) = turns[idx - 1].penalty(app.map());
|
let (lt, lc, slow_lane) = turns[idx - 1].penalty(app.map());
|
||||||
@ -194,6 +199,7 @@ impl TurnExplorer {
|
|||||||
TurnType::Straight => Color::BLUE,
|
TurnType::Straight => Color::BLUE,
|
||||||
TurnType::Right => Color::GREEN,
|
TurnType::Right => Color::GREEN,
|
||||||
TurnType::Left => Color::RED,
|
TurnType::Left => Color::RED,
|
||||||
|
TurnType::UTurn => Color::PURPLE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
// 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.
|
// 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
|
// 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;
|
let mut changes = false;
|
||||||
for (id, road) in &map.roads {
|
for (id, road) in &map.roads {
|
||||||
// See https://wiki.openstreetmap.org/wiki/Proposed_features/junction%3Dintersection
|
// See https://wiki.openstreetmap.org/wiki/Proposed_features/junction%3Dintersection
|
||||||
// Hardcoding some Montlake intersections to test
|
if road.osm_tags.is("junction", "intersection") {
|
||||||
if road.osm_tags.is("junction", "intersection")
|
|
||||||
|| *id == OriginalRoad::new(459084309, (4550007325, 4550007326))
|
|
||||||
|| *id == OriginalRoad::new(332060258, (3391701875, 1635790583))
|
|
||||||
{
|
|
||||||
let id = *id;
|
let id = *id;
|
||||||
map.merge_short_road(id).unwrap();
|
merged.insert(map.merge_short_road(id).unwrap().0);
|
||||||
changes = true;
|
changes = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -26,4 +27,6 @@ pub fn merge_short_roads(map: &mut RawMap) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merged
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl Map {
|
|||||||
// Better to defer this and see RawMaps with more debug info in map_editor
|
// Better to defer this and see RawMaps with more debug info in map_editor
|
||||||
remove_disconnected::remove_disconnected_roads(&mut raw, timer);
|
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");
|
timer.start("raw_map to InitialMap");
|
||||||
let gps_bounds = raw.gps_bounds.clone();
|
let gps_bounds = raw.gps_bounds.clone();
|
||||||
@ -88,6 +88,7 @@ impl Map {
|
|||||||
incoming_lanes: Vec::new(),
|
incoming_lanes: Vec::new(),
|
||||||
outgoing_lanes: Vec::new(),
|
outgoing_lanes: Vec::new(),
|
||||||
roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
|
roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
|
||||||
|
merged: merged_intersections.contains(&i.id),
|
||||||
});
|
});
|
||||||
intersection_id_mapping.insert(i.id, id);
|
intersection_id_mapping.insert(i.id, id);
|
||||||
}
|
}
|
||||||
|
@ -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::Right);
|
||||||
final_turns = remove_merging_turns(map, final_turns, TurnType::Left);
|
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();
|
let mut outgoing_missing: HashSet<LaneID> = HashSet::new();
|
||||||
for l in &i.outgoing_lanes {
|
for l in &i.outgoing_lanes {
|
||||||
if map.get_l(*l).lane_type.supports_any_movement() {
|
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.
|
// some observed cases.
|
||||||
if diff.abs() < 30.0 {
|
if diff.abs() < 30.0 {
|
||||||
TurnType::Straight
|
TurnType::Straight
|
||||||
|
} else if diff.abs() > 135.0 {
|
||||||
|
TurnType::UTurn
|
||||||
} else if diff < 0.0 {
|
} else if diff < 0.0 {
|
||||||
// Clockwise rotation
|
// Clockwise rotation
|
||||||
TurnType::Right
|
TurnType::Right
|
||||||
|
@ -54,6 +54,9 @@ pub struct Intersection {
|
|||||||
|
|
||||||
// TODO Maybe DirectedRoadIDs
|
// TODO Maybe DirectedRoadIDs
|
||||||
pub roads: BTreeSet<RoadID>,
|
pub roads: BTreeSet<RoadID>,
|
||||||
|
|
||||||
|
/// Was a short road adjacent to this intersection merged?
|
||||||
|
pub merged: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Intersection {
|
impl Intersection {
|
||||||
|
@ -33,6 +33,7 @@ pub enum TurnType {
|
|||||||
Straight,
|
Straight,
|
||||||
Right,
|
Right,
|
||||||
Left,
|
Left,
|
||||||
|
UTurn,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO This concept may be dated, now that Movements exist. Within a movement, the lane-changing
|
// TODO This concept may be dated, now that Movements exist. Within a movement, the lane-changing
|
||||||
|
Loading…
Reference in New Issue
Block a user