clean up some crosswalks generated near roads with sidewalks only on one side

This commit is contained in:
Dustin Carlino 2019-11-12 15:54:47 -08:00
parent c0eeb8848a
commit 03d599775f
5 changed files with 116 additions and 46 deletions

View File

@ -3,12 +3,12 @@
8c1227160b6a8244bbdb7c8b504d69aa ../data/screenshots/pending_montlake/03x01_i0.png
abad174a1a96560ae30c2db15ab6c2cb ../data/screenshots/pending_montlake/01x02_i5.png
5e0e26848557b3386a8aa1839ad58560 ../data/screenshots/pending_montlake/02x02_i9.png
0a109c274e02027fe355611dc354b74e ../data/screenshots/pending_montlake/03x02_i8.png
ff1f5a0a4efd4d6048de5a3703082695 ../data/screenshots/pending_montlake/01x03_i20.png
b8e121a435731b3c105c9bd7052775dc ../data/screenshots/pending_montlake/03x02_i8.png
a128166f4fc8c404c1043032ce426b40 ../data/screenshots/pending_montlake/01x03_i20.png
9162c2429dace890c01b9f1106af7bfe ../data/screenshots/pending_montlake/02x03_i71.png
6b7de9c100ca476a4aa2fe12830dd44a ../data/screenshots/pending_montlake/03x03_i77.png
e62c06cbcc8b82714009fcc3360d5377 ../data/screenshots/pending_montlake/01x04_i4.png
2d0ad4590f8ceeaf33f0d785bbcc4cd2 ../data/screenshots/pending_montlake/02x04_i1.png
5c633da7efc5540631743241e00a1220 ../data/screenshots/pending_montlake/02x04_i1.png
4a7d05e039eea28b7009d1e78203a3da ../data/screenshots/pending_montlake/03x04_i58.png
a9eb423970fc9ec9029ce839b6d45913 ../data/screenshots/pending_montlake/01x05_i31.png
bdc20ec3835d5ea97dfe876c7e91b409 ../data/screenshots/pending_montlake/02x05_i25.png

View File

@ -25,6 +25,9 @@
- slowly hone away at problems currently with errors printed (like bad pl shift angles)
- eventually: every intersection has at least a turn, minimum lengths enforced, etc
- useful unit tests
- for a given intersection with lanes, check all the turns generated
## Code to release
- (from before august 2019) tmp_gfx as a 2D-with-camera glium sample

26
docs/assumptions.md Normal file
View File

@ -0,0 +1,26 @@
# Modeling assumptions
This is pretty disorganized right now, just need to start something.
## Sidewalk connectivity
Should it be possible to close sidewalks for construction? Right now, this
breaks too many assumptions that're hard to recompute. Building front paths and
bus stops are associated with a sidewalk, so that makes applying the edit way
more unclear. Closing intersections is still useful -- remove all of the vehicle
turns, but allow the walking turns.
## Graph connectivity
For now, no map edits should be able to impact any of the trips possible in the
baseline -- so no impacting graph connectivity, no killing bus stops, etc.
## Over-taking
Unsupported right now, but it should happen.
## Left turns in the middle of a road
Into a driveway, or using the shared left turn lanes. This should be supported.
Parking and unparking already have the ability to block one queue -- extend
that.

View File

@ -102,7 +102,7 @@ impl Line {
)
}
pub(crate) fn shift_either_direction(&self, width: Distance) -> Line {
pub fn shift_either_direction(&self, width: Distance) -> Line {
if width >= Distance::ZERO {
self.shift_right(width)
} else {

View File

@ -301,20 +301,15 @@ fn make_walking_turns(
.into_iter()
.map(|id| &all_roads[id.0])
.collect();
let mut result: Vec<Turn> = Vec::new();
for idx1 in 0..roads.len() {
if let Some(l1) = get_sidewalk(lanes, roads[idx1].incoming_lanes(i.id)) {
// Make the crosswalk to the other side
if let Some(l2) = get_sidewalk(lanes, roads[idx1].outgoing_lanes(i.id)) {
if roads.len() > 2 {
result.extend(make_crosswalks(i.id, l1, l2));
}
}
// Find the shared corner
if roads.len() > 1 {
// TODO -1 and not +1 is brittle... must be the angle sorting
if roads.len() == 2 {
if let Some(turns) = make_degenerate_crosswalks(i.id, lanes, roads[0], roads[1]) {
result.extend(turns);
}
// TODO Argh, duplicate logic for SharedSidewalkCorners
for idx1 in 0..roads.len() {
if let Some(l1) = get_sidewalk(lanes, roads[idx1].incoming_lanes(i.id)) {
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
@ -336,35 +331,10 @@ fn make_walking_turns(
lookup_idx: 0,
});
}
} else if roads.len() > 2 {
// See if we need to add a crosswalk over this adjacent road.
// TODO This is brittle; I could imagine having to cross two adjacent highway
// ramps to get to the next sidewalk.
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 2).outgoing_lanes(i.id),
) {
result.extend(make_crosswalks(i.id, l1, l2));
}
// TODO Yup, the hack has come to pass.
if roads.len() > 3 {
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 3)
.outgoing_lanes(i.id),
) {
result.extend(make_crosswalks(i.id, l1, l2));
}
}
}
}
}
}
if roads.len() == 2 {
if let Some(turns) = make_degenerate_crosswalks(i.id, lanes, roads[0], roads[1]) {
result.extend(turns);
}
return result;
}
if roads.len() == 1 {
if let Some(l1) = get_sidewalk(lanes, roads[0].incoming_lanes(i.id)) {
@ -386,19 +356,90 @@ fn make_walking_turns(
});
}
}
return result;
}
for idx1 in 0..roads.len() {
if let Some(l1) = get_sidewalk(lanes, roads[idx1].incoming_lanes(i.id)) {
// Make the crosswalk to the other side
if let Some(l2) = get_sidewalk(lanes, roads[idx1].outgoing_lanes(i.id)) {
result.extend(make_crosswalks(i.id, l1, l2));
}
// Find the shared corner
// TODO -1 and not +1 is brittle... must be the angle sorting
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
) {
if l1.last_pt() != l2.first_pt() {
let geom = make_shared_sidewalk_corner(i, l1, l2, timer);
result.push(Turn {
id: turn_id(i.id, l1.id, l2.id),
turn_type: TurnType::SharedSidewalkCorner,
other_crosswalk_ids: BTreeSet::new(),
geom: geom.clone(),
lookup_idx: 0,
});
result.push(Turn {
id: turn_id(i.id, l2.id, l1.id),
turn_type: TurnType::SharedSidewalkCorner,
other_crosswalk_ids: BTreeSet::new(),
geom: geom.reversed(),
lookup_idx: 0,
});
}
} else if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 1).incoming_lanes(i.id),
) {
// Adjacent road is missing a sidewalk on the near side, but has one on the far
// side
result.extend(make_crosswalks(i.id, l1, l2));
} else {
// We may need to add a crosswalk over this intermediate road that has no
// sidewalks at all. There might be a few in the way -- think highway onramps.
// TODO Refactor and loop until we find something to connect it to?
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 2).outgoing_lanes(i.id),
) {
result.extend(make_crosswalks(i.id, l1, l2));
} else if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 2).incoming_lanes(i.id),
) {
result.extend(make_crosswalks(i.id, l1, l2));
} else if roads.len() > 3 {
if let Some(l2) = get_sidewalk(
lanes,
abstutil::wraparound_get(&roads, (idx1 as isize) - 3).outgoing_lanes(i.id),
) {
result.extend(make_crosswalks(i.id, l1, l2));
}
}
}
}
}
result
}
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
if l1.last_pt() == l2.first_pt() {
let l1_pt = l1.endpoint(i);
let l2_pt = l2.endpoint(i);
if l1_pt == l2_pt {
return Vec::new();
}
// TODO Not sure this is always right.
let direction = if (l1.dst_i == i) == (l2.dst_i == i) {
-1.0
} else {
1.0
};
// Jut out a bit into the intersection, cross over, then jut back in.
let line = Line::new(l1.last_pt(), l2.first_pt()).shift_right(LANE_THICKNESS / 2.0);
let geom_fwds = PolyLine::new(vec![l1.last_pt(), line.pt1(), line.pt2(), l2.first_pt()]);
let line = Line::new(l1_pt, l2_pt).shift_either_direction(direction * LANE_THICKNESS / 2.0);
let geom_fwds = PolyLine::new(vec![l1_pt, line.pt1(), line.pt2(), l2_pt]);
vec![
Turn {