diff --git a/abstutil/src/collections.rs b/abstutil/src/collections.rs index 4427462b0f..ba352839aa 100644 --- a/abstutil/src/collections.rs +++ b/abstutil/src/collections.rs @@ -76,3 +76,14 @@ pub fn retain_btreemap bool>( map.remove(&k); } } + +pub fn contains_duplicates(vec: &Vec) -> bool { + let mut set = BTreeSet::new(); + for item in vec { + if set.contains(item) { + return true; + } + set.insert(item); + } + false +} diff --git a/abstutil/src/lib.rs b/abstutil/src/lib.rs index fa10dd610c..f92d14861b 100644 --- a/abstutil/src/lib.rs +++ b/abstutil/src/lib.rs @@ -8,7 +8,7 @@ mod random; mod time; 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::io::{ deserialize_btreemap, deserialize_multimap, find_next_file, find_prev_file, list_all_objects, diff --git a/docs/TODO_quality.md b/docs/TODO_quality.md index 60e16179ac..ca2671259f 100644 --- a/docs/TODO_quality.md +++ b/docs/TODO_quality.md @@ -3,7 +3,6 @@ ## Boundary clipping - 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 - intersections diff --git a/docs/design/map.md b/docs/design/map.md index 841bb600d4..796ef6ee31 100644 --- a/docs/design/map.md +++ b/docs/design/map.md @@ -30,6 +30,7 @@ functionality - stop signs (some directions stop and others dont), traffic signals with multiple phases - "reasonable" defaults inferred, editor for the rest + - weird highway on-ramps fixed - WIP: small intersections, roundabouts merged - Buildings - classified by use, notion of residential density diff --git a/geom/src/pt.rs b/geom/src/pt.rs index dae1fbc575..8f16ac7f07 100644 --- a/geom/src/pt.rs +++ b/geom/src/pt.rs @@ -175,6 +175,10 @@ impl Pt2D { // Didn't find end None } + + pub fn to_hashable(self) -> HashablePt2D { + HashablePt2D::new(self.x(), self.y()) + } } impl fmt::Display for Pt2D { diff --git a/map_model/src/make/turns.rs b/map_model/src/make/turns.rs index 3b39847242..10e54e4c5e 100644 --- a/map_model/src/make/turns.rs +++ b/map_model/src/make/turns.rs @@ -2,7 +2,7 @@ use crate::{ Intersection, IntersectionID, IntersectionType, Lane, LaneID, LaneType, Road, Turn, TurnID, TurnType, LANE_THICKNESS, }; -use abstutil::{wraparound_get, Timer, Warn}; +use abstutil::{Timer, Warn}; use geom::{Distance, Line, PolyLine, Pt2D}; use nbez::{Bez3o, BezCurve, Point2d}; 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 if let Some(l2) = get_sidewalk( 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()) { 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. if let Some(l2) = get_sidewalk( 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)); } @@ -282,6 +282,8 @@ fn make_shared_sidewalk_corner( l2: &Lane, timer: &mut Timer, ) -> 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. let corner1 = l1.last_line().shift_right(LANE_THICKNESS / 2.0).pt2(); 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); 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( PolyLine::new(deduped) .shift_right(LANE_THICKNESS / 2.0) @@ -312,8 +319,11 @@ fn make_shared_sidewalk_corner( final_pts.pop(); 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 baseline = PolyLine::new(vec![l1.last_pt(), l2.first_pt()]); 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())); return baseline; diff --git a/map_model/src/pathfind/driving.rs b/map_model/src/pathfind/driving.rs index 1e2cdeab65..7c799d50f0 100644 --- a/map_model/src/pathfind/driving.rs +++ b/map_model/src/pathfind/driving.rs @@ -50,11 +50,11 @@ impl VehiclePathfinder { g.add_turn(t, map); } - println!( + /*println!( "{} nodes, {} edges", g.graph.node_count(), g.graph.edge_count() - ); + );*/ g } diff --git a/map_model/src/pathfind/walking.rs b/map_model/src/pathfind/walking.rs index 05a6a05e29..3431ef1566 100644 --- a/map_model/src/pathfind/walking.rs +++ b/map_model/src/pathfind/walking.rs @@ -71,11 +71,11 @@ impl SidewalkPathfinder { } } - println!( + /*println!( "{} nodes, {} edges", g.graph.node_count(), g.graph.edge_count() - ); + );*/ g }