generalize the R253 fix

This commit is contained in:
Dustin Carlino 2019-02-08 13:18:07 -08:00
parent 18391811e4
commit 949b184678
3 changed files with 129 additions and 92 deletions

View File

@ -8,16 +8,10 @@
- bad polyline shifting causes jagged lane endings in generalized_trim_back
- handle small roads again somehow?
- what's going on with R253 generally?
- automate the manual fix. check it in larger 23rd map.
- I40 has a long cut when merged, why not hit in the middle?
- what if we allow intersections between infinite lines for merged cases?
- try it bigger
- deal with loop roads?
- manually draw a picture of the weird intersection to see what would look reasonable. i think we need original road bands from deleted stuff to make decent polygons.
- model U-turns
- degenerate-2's should only have one crosswalk

View File

@ -0,0 +1,125 @@
use crate::make::initial::{geometry, InitialMap};
use crate::raw_data::{StableIntersectionID, StableRoadID};
use abstutil::Timer;
use std::collections::{BTreeSet, HashSet};
pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
// Look for road center lines that hit an intersection polygon that isn't one of their
// endpoints.
timer.start_iter(
"look for roads crossing intersections in strange ways",
m.roads.len(),
);
let mut fixme: Vec<(StableRoadID, StableIntersectionID)> = Vec::new();
for r in m.roads.values() {
timer.next();
// TODO Prune search.
for i in m.intersections.values() {
if r.src_i == i.id || r.dst_i == i.id {
continue;
}
if !r.trimmed_center_pts.crosses_polygon(&i.polygon) {
continue;
}
// TODO Avoid some false positives by seeing if this road is "close" to the
// intersection it crosses. This probably needs more tuning. It avoids expected
// tunnel/bridge crossings.
if !floodfill(m, i.id, 5).contains(&r.id) {
continue;
}
// TODO Still seeing false positives due to lack of short road merging.
fixme.push((r.id, i.id));
}
}
for (r, i) in fixme {
if fix_ramp(m, r, i) {
info!("Fixed ramp {} crossing {}", r, i);
} else {
info!("{} crosses {} strangely, but didn't change anything", r, i);
}
}
}
fn floodfill(m: &InitialMap, start: StableIntersectionID, steps: usize) -> HashSet<StableRoadID> {
let mut seen: HashSet<StableRoadID> = HashSet::new();
let mut queue: Vec<(StableRoadID, usize)> = m.intersections[&start]
.roads
.iter()
.map(|r| (*r, 1))
.collect();
while !queue.is_empty() {
let (r, count) = queue.pop().unwrap();
if seen.contains(&r) {
continue;
}
seen.insert(r);
if count < steps {
for next in m.intersections[&m.roads[&r].src_i]
.roads
.iter()
.chain(m.intersections[&m.roads[&r].dst_i].roads.iter())
{
queue.push((*next, count + 1));
}
}
}
seen
}
fn fix_ramp(m: &mut InitialMap, ramp: StableRoadID, new_src: StableIntersectionID) -> bool {
// Trace backwards...
let mut delete_roads: Vec<StableRoadID> = Vec::new();
let mut delete_intersections: Vec<StableIntersectionID> = Vec::new();
let last_normal_intersection = {
let mut current_road = ramp;
loop {
let src_i = &m.intersections[&m.roads[&current_road].src_i];
if let Some(other_road) = get_one_other(&src_i.roads, current_road) {
delete_intersections.push(src_i.id);
current_road = other_road;
delete_roads.push(current_road);
} else {
break src_i.id;
}
}
};
if let Some(last_road) = delete_roads.last() {
let mut i = m.intersections.get_mut(&last_normal_intersection).unwrap();
i.roads.remove(&last_road);
i.polygon = geometry::intersection_polygon(i, &mut m.roads);
} else {
// TODO Not really sure why, but when there's not a road in between, don't apply the fix.
return false;
}
for r in delete_roads {
m.roads.remove(&r);
}
for i in delete_intersections {
m.intersections.remove(&i);
}
{
m.roads.get_mut(&ramp).unwrap().src_i = new_src;
let mut i = m.intersections.get_mut(&new_src).unwrap();
i.roads.insert(ramp);
i.polygon = geometry::intersection_polygon(i, &mut m.roads);
}
true
}
fn get_one_other<X: PartialEq + Clone>(set: &BTreeSet<X>, item: X) -> Option<X> {
if set.len() != 2 {
return None;
}
let items: Vec<X> = set.iter().cloned().collect();
if items[0] == item {
return Some(items[1].clone());
}
return Some(items[0].clone());
}

View File

@ -1,13 +1,14 @@
mod fix_ramps;
mod geometry;
pub mod lane_specs;
mod merge;
use crate::raw_data::{StableIntersectionID, StableRoadID};
use crate::{raw_data, MapEdits, LANE_THICKNESS};
use abstutil::{note, Timer};
use abstutil::Timer;
use geom::{Bounds, Distance, GPSBounds, PolyLine, Pt2D};
use serde_derive::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::collections::{BTreeMap, BTreeSet};
#[derive(Serialize, Deserialize)]
pub struct InitialMap {
@ -139,64 +140,7 @@ impl InitialMap {
i.polygon = geometry::intersection_polygon(i, &mut m.roads);
}
// TODO Move to a module if this grows.
// Look for road center lines that hit an intersection polygon that isn't one of their
// endpoints.
timer.start_iter(
"look for roads crossing intersections in strange ways",
m.roads.len(),
);
for r in m.roads.values() {
timer.next();
// TODO Prune search.
for i in m.intersections.values() {
if r.src_i == i.id || r.dst_i == i.id {
continue;
}
if !r.trimmed_center_pts.crosses_polygon(&i.polygon) {
continue;
}
// TODO Avoid some false positives by seeing if this road is "close" to the
// intersection it crosses. This probably needs more tuning. It avoids expected
// tunnel/bridge crossings.
if !m.floodfill(i.id, 5).contains(&r.id) {
continue;
}
// TODO Still seeing false positives due to lack of short road merging.
note(format!("{} is suspicious -- it hits {}", r.id, i.id));
}
}
if false {
// Delete I247 and R370. remove connection of R370 from I309.
m.intersections.remove(&StableIntersectionID(247));
m.roads.remove(&StableRoadID(370));
m.intersections
.get_mut(&StableIntersectionID(309))
.unwrap()
.roads
.remove(&StableRoadID(370));
// make R253's src be the intersection it hits. recalculate that intersection.
m.roads.get_mut(&StableRoadID(253)).unwrap().src_i = StableIntersectionID(119);
m.intersections
.get_mut(&StableIntersectionID(119))
.unwrap()
.roads
.insert(StableRoadID(253));
// TODO reset geometry or not?
{
let i = m.intersections.get_mut(&StableIntersectionID(119)).unwrap();
i.polygon = geometry::intersection_polygon(i, &mut m.roads);
}
{
// Also fix up this one.
let i = m.intersections.get_mut(&StableIntersectionID(309)).unwrap();
i.polygon = geometry::intersection_polygon(i, &mut m.roads);
}
}
fix_ramps::fix_ramps(&mut m, timer);
merge::short_roads(&mut m);
@ -213,30 +157,4 @@ impl InitialMap {
abstutil::write_binary(&path, self).expect(&format!("Saving {} failed", path));
info!("Saved {}", path);
}
fn floodfill(&self, start: StableIntersectionID, steps: usize) -> HashSet<StableRoadID> {
let mut seen: HashSet<StableRoadID> = HashSet::new();
let mut queue: Vec<(StableRoadID, usize)> = self.intersections[&start]
.roads
.iter()
.map(|r| (*r, 1))
.collect();
while !queue.is_empty() {
let (r, count) = queue.pop().unwrap();
if seen.contains(&r) {
continue;
}
seen.insert(r);
if count < steps {
for next in self.intersections[&self.roads[&r].src_i]
.roads
.iter()
.chain(self.intersections[&self.roads[&r].dst_i].roads.iter())
{
queue.push((*next, count + 1));
}
}
}
seen
}
}