avoid crash in make_shared_sidewalk_corner

This commit is contained in:
Dustin Carlino 2019-04-12 13:15:04 -07:00
parent 11a1c3543e
commit 2ecd8a0edb
8 changed files with 35 additions and 10 deletions

View File

@ -76,3 +76,14 @@ pub fn retain_btreemap<K: Ord + Clone, V, F: Fn(&K, &V) -> bool>(
map.remove(&k); map.remove(&k);
} }
} }
pub fn contains_duplicates<T: Ord>(vec: &Vec<T>) -> bool {
let mut set = BTreeSet::new();
for item in vec {
if set.contains(item) {
return true;
}
set.insert(item);
}
false
}

View File

@ -8,7 +8,7 @@ mod random;
mod time; mod time;
pub use crate::clone::Cloneable; pub use crate::clone::Cloneable;
pub use crate::collections::{retain_btreemap, wraparound_get, MultiMap}; pub use crate::collections::{contains_duplicates, retain_btreemap, wraparound_get, MultiMap};
pub use crate::error::Error; pub use crate::error::Error;
pub use crate::io::{ pub use crate::io::{
deserialize_btreemap, deserialize_multimap, find_next_file, find_prev_file, list_all_objects, deserialize_btreemap, deserialize_multimap, find_next_file, find_prev_file, list_all_objects,

View File

@ -3,7 +3,6 @@
## Boundary clipping ## Boundary clipping
- roads - roads
- why does i96 break on new walking code? it's totally interior...
- what if they start/end in bounds, but briefly dip out? arboretum place east - what if they start/end in bounds, but briefly dip out? arboretum place east
- intersections - intersections

View File

@ -30,6 +30,7 @@ functionality
- stop signs (some directions stop and others dont), traffic signals with - stop signs (some directions stop and others dont), traffic signals with
multiple phases multiple phases
- "reasonable" defaults inferred, editor for the rest - "reasonable" defaults inferred, editor for the rest
- weird highway on-ramps fixed
- WIP: small intersections, roundabouts merged - WIP: small intersections, roundabouts merged
- Buildings - Buildings
- classified by use, notion of residential density - classified by use, notion of residential density

View File

@ -175,6 +175,10 @@ impl Pt2D {
// Didn't find end // Didn't find end
None None
} }
pub fn to_hashable(self) -> HashablePt2D {
HashablePt2D::new(self.x(), self.y())
}
} }
impl fmt::Display for Pt2D { impl fmt::Display for Pt2D {

View File

@ -2,7 +2,7 @@ use crate::{
Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Road, Turn, TurnID, Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Road, Turn, TurnID,
TurnType, LANE_THICKNESS, TurnType, LANE_THICKNESS,
}; };
use abstutil::{wraparound_get, Timer, Warn}; use abstutil::{Timer, Warn};
use geom::{Distance, Line, PolyLine, Pt2D}; use geom::{Distance, Line, PolyLine, Pt2D};
use nbez::{Bez3o, BezCurve, Point2d}; use nbez::{Bez3o, BezCurve, Point2d};
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
@ -217,7 +217,7 @@ fn make_walking_turns(
// TODO -1 and not +1 is brittle... must be the angle sorting // TODO -1 and not +1 is brittle... must be the angle sorting
if let Some(l2) = get_sidewalk( if let Some(l2) = get_sidewalk(
lanes, lanes,
wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id), abstutil::wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
) { ) {
if !l1.last_pt().epsilon_eq(l2.first_pt()) { if !l1.last_pt().epsilon_eq(l2.first_pt()) {
let geom = make_shared_sidewalk_corner(i, l1, l2, timer); let geom = make_shared_sidewalk_corner(i, l1, l2, timer);
@ -240,7 +240,7 @@ fn make_walking_turns(
// ramps to get to the next sidewalk. // ramps to get to the next sidewalk.
if let Some(l2) = get_sidewalk( if let Some(l2) = get_sidewalk(
lanes, lanes,
wraparound_get(&roads, (idx1 as isize) - 2).outgoing_lanes(i.id), abstutil::wraparound_get(&roads, (idx1 as isize) - 2).outgoing_lanes(i.id),
) { ) {
result.extend(make_crosswalks(i.id, l1, l2)); result.extend(make_crosswalks(i.id, l1, l2));
} }
@ -282,6 +282,8 @@ fn make_shared_sidewalk_corner(
l2: &Lane, l2: &Lane,
timer: &mut Timer, timer: &mut Timer,
) -> PolyLine { ) -> PolyLine {
let baseline = PolyLine::new(vec![l1.last_pt(), l2.first_pt()]);
// Find all of the points on the intersection polygon between the two sidewalks. // Find all of the points on the intersection polygon between the two sidewalks.
let corner1 = l1.last_line().shift_right(LANE_THICKNESS / 2.0).pt2(); let corner1 = l1.last_line().shift_right(LANE_THICKNESS / 2.0).pt2();
let corner2 = l2.first_line().shift_right(LANE_THICKNESS / 2.0).pt1(); let corner2 = l2.first_line().shift_right(LANE_THICKNESS / 2.0).pt1();
@ -295,6 +297,11 @@ fn make_shared_sidewalk_corner(
{ {
let deduped = Pt2D::approx_dedupe(pts, geom::EPSILON_DIST); let deduped = Pt2D::approx_dedupe(pts, geom::EPSILON_DIST);
if deduped.len() >= 2 { if deduped.len() >= 2 {
if abstutil::contains_duplicates(&deduped.iter().map(|pt| pt.to_hashable()).collect()) {
timer.warn(format!("SharedSidewalkCorner between {} and {} has weird duplicate geometry, so just doing straight line", l1.id, l2.id));
return baseline;
}
pts_between.extend( pts_between.extend(
PolyLine::new(deduped) PolyLine::new(deduped)
.shift_right(LANE_THICKNESS / 2.0) .shift_right(LANE_THICKNESS / 2.0)
@ -312,8 +319,11 @@ fn make_shared_sidewalk_corner(
final_pts.pop(); final_pts.pop();
final_pts.push(l2.first_pt()); final_pts.push(l2.first_pt());
} }
if abstutil::contains_duplicates(&final_pts.iter().map(|pt| pt.to_hashable()).collect()) {
timer.warn(format!("SharedSidewalkCorner between {} and {} has weird duplicate geometry, so just doing straight line", l1.id, l2.id));
return baseline;
}
let result = PolyLine::new(final_pts); let result = PolyLine::new(final_pts);
let baseline = PolyLine::new(vec![l1.last_pt(), l2.first_pt()]);
if result.length() > 10.0 * baseline.length() { if result.length() > 10.0 * baseline.length() {
timer.warn(format!("SharedSidewalkCorner between {} and {} explodes to {} long, so just doing straight line", l1.id, l2.id, result.length())); timer.warn(format!("SharedSidewalkCorner between {} and {} explodes to {} long, so just doing straight line", l1.id, l2.id, result.length()));
return baseline; return baseline;

View File

@ -50,11 +50,11 @@ impl VehiclePathfinder {
g.add_turn(t, map); g.add_turn(t, map);
} }
println!( /*println!(
"{} nodes, {} edges", "{} nodes, {} edges",
g.graph.node_count(), g.graph.node_count(),
g.graph.edge_count() g.graph.edge_count()
); );*/
g g
} }

View File

@ -71,11 +71,11 @@ impl SidewalkPathfinder {
} }
} }
println!( /*println!(
"{} nodes, {} edges", "{} nodes, {} edges",
g.graph.node_count(), g.graph.node_count(),
g.graph.edge_count() g.graph.edge_count()
); );*/
g g
} }