mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
avoid crash in make_shared_sidewalk_corner
This commit is contained in:
parent
11a1c3543e
commit
2ecd8a0edb
@ -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
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user