mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
gracefully degrade if we cant make TurnGroups for a traffic signal. this
gets SF, Tokyo, and London to import!!!
This commit is contained in:
parent
7a0dbb28b1
commit
3b49353df2
@ -221,8 +221,12 @@ pub fn snap_bus_stops(
|
||||
for idx in (0..idx_in_route).rev() {
|
||||
let (i, pt) = route.all_pts[idx];
|
||||
if !raw.intersections.contains_key(&i) {
|
||||
found = Some(pt_to_road[&pt.to_hashable()]);
|
||||
break;
|
||||
if let Some(r) = pt_to_road.get(&pt.to_hashable()) {
|
||||
found = Some(*r);
|
||||
break;
|
||||
} else {
|
||||
return Err(format!("Some point on the route isn't even on a road?!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(r) = found {
|
||||
|
@ -9,7 +9,7 @@ pub struct Line(Pt2D, Pt2D);
|
||||
|
||||
impl Line {
|
||||
pub fn new(pt1: Pt2D, pt2: Pt2D) -> Option<Line> {
|
||||
if pt1.dist_to(pt2) < EPSILON_DIST {
|
||||
if pt1.dist_to(pt2) <= EPSILON_DIST {
|
||||
return None;
|
||||
}
|
||||
Some(Line(pt1, pt2))
|
||||
|
@ -120,7 +120,7 @@ impl Ring {
|
||||
for pt in pts.iter().cloned() {
|
||||
current.push(pt);
|
||||
if intersections.contains(&pt.to_hashable()) && current.len() > 1 {
|
||||
if current[0] == pt {
|
||||
if current[0] == pt && current.len() >= 3 {
|
||||
rings.push(Ring::must_new(current.drain(..).collect()));
|
||||
} else {
|
||||
polylines.push(PolyLine::new(current.drain(..).collect())?);
|
||||
|
@ -13,7 +13,7 @@ use crate::raw::{OriginalIntersection, OriginalRoad, RawMap};
|
||||
use crate::{
|
||||
connectivity, osm, Area, AreaID, ControlStopSign, ControlTrafficSignal, Intersection,
|
||||
IntersectionID, IntersectionType, Lane, LaneID, Map, MapEdits, PathConstraints, Position, Road,
|
||||
RoadID, Zone,
|
||||
RoadID, TurnGroup, Zone,
|
||||
};
|
||||
use abstutil::{Parallelism, Timer};
|
||||
use enumset::EnumSet;
|
||||
@ -141,7 +141,9 @@ impl Map {
|
||||
}
|
||||
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
|
||||
// there.
|
||||
let road_left_pts = map.must_left_shift(road.center_pts.clone(), r.half_width);
|
||||
let road_left_pts = map
|
||||
.left_shift(road.center_pts.clone(), r.half_width)
|
||||
.unwrap_or_else(|_| road.center_pts.clone());
|
||||
|
||||
let mut fwd_width_so_far = Distance::ZERO;
|
||||
let mut back_width_so_far = Distance::ZERO;
|
||||
@ -306,14 +308,28 @@ impl Map {
|
||||
IntersectionType::StopSign => {
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
||||
}
|
||||
IntersectionType::TrafficSignal => {
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&map, i.id, timer));
|
||||
}
|
||||
IntersectionType::TrafficSignal => match TurnGroup::for_i(i.id, &map) {
|
||||
Ok(_) => {
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&map, i.id, timer));
|
||||
}
|
||||
Err(err) => {
|
||||
timer.error(format!(
|
||||
"Traffic signal at {} downgraded to stop sign because of weird \
|
||||
problem: {}",
|
||||
i.orig_id, err
|
||||
));
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
||||
}
|
||||
},
|
||||
IntersectionType::Border | IntersectionType::Construction => {}
|
||||
};
|
||||
}
|
||||
map.stop_signs = stop_signs;
|
||||
map.traffic_signals = traffic_signals;
|
||||
// Fix up the type for any problematic traffic signals
|
||||
for i in map.stop_signs.keys() {
|
||||
map.intersections[i.0].intersection_type = IntersectionType::StopSign;
|
||||
}
|
||||
|
||||
traffic_signals::synchronize(&mut map);
|
||||
|
||||
|
@ -70,7 +70,7 @@ fn new(id: IntersectionID, map: &Map) -> ControlTrafficSignal {
|
||||
id,
|
||||
phases: Vec::new(),
|
||||
offset: Duration::ZERO,
|
||||
turn_groups: TurnGroup::for_i(id, map),
|
||||
turn_groups: TurnGroup::for_i(id, map).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,6 +428,7 @@ fn make_phases(
|
||||
|
||||
pub fn brute_force(map: &Map, i: IntersectionID) {
|
||||
let turn_groups: Vec<TurnGroup> = TurnGroup::for_i(i, map)
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.filter_map(|(id, tg)| if id.crosswalk { None } else { Some(tg) })
|
||||
.collect();
|
||||
|
@ -306,7 +306,7 @@ impl ControlTrafficSignal {
|
||||
id,
|
||||
phases,
|
||||
offset: Duration::seconds(raw.offset_seconds as f64),
|
||||
turn_groups: TurnGroup::for_i(id, map),
|
||||
turn_groups: TurnGroup::for_i(id, map).unwrap(),
|
||||
}
|
||||
.validate()
|
||||
}
|
||||
|
@ -197,7 +197,10 @@ pub struct TurnGroup {
|
||||
}
|
||||
|
||||
impl TurnGroup {
|
||||
pub(crate) fn for_i(i: IntersectionID, map: &Map) -> BTreeMap<TurnGroupID, TurnGroup> {
|
||||
pub(crate) fn for_i(
|
||||
i: IntersectionID,
|
||||
map: &Map,
|
||||
) -> Result<BTreeMap<TurnGroupID, TurnGroup>, Box<dyn Error>> {
|
||||
let mut results = BTreeMap::new();
|
||||
let mut groups: MultiMap<(DirectedRoadID, DirectedRoadID), TurnID> = MultiMap::new();
|
||||
for turn in map.get_turns_in_intersection(i) {
|
||||
@ -233,11 +236,7 @@ impl TurnGroup {
|
||||
members.iter().map(|t| &map.get_t(*t).geom).collect(),
|
||||
from,
|
||||
to,
|
||||
)
|
||||
.expect(&format!(
|
||||
"Weird turn group geometry near {}",
|
||||
map.get_i(i).orig_id
|
||||
));
|
||||
)?;
|
||||
let turn_types: BTreeSet<TurnType> =
|
||||
members.iter().map(|t| map.get_t(*t).turn_type).collect();
|
||||
if turn_types.len() > 1 {
|
||||
@ -265,9 +264,11 @@ impl TurnGroup {
|
||||
);
|
||||
}
|
||||
if results.is_empty() {
|
||||
panic!("{} has no TurnGroups!", map.get_i(i).orig_id);
|
||||
return Err(
|
||||
format!("No TurnGroups! Does the intersection have at least 2 roads?").into(),
|
||||
);
|
||||
}
|
||||
results
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
// Polyline points FROM intersection
|
||||
|
Loading…
Reference in New Issue
Block a user