recording and applying fixes to create new synthetic intersections and roads

This commit is contained in:
Dustin Carlino 2019-09-17 16:16:19 -07:00
parent 1e4f36dec1
commit e52fa1fc1a
3 changed files with 101 additions and 34 deletions

View File

@ -71,6 +71,7 @@ pub fn split_up_roads(
IntersectionType::StopSign IntersectionType::StopSign
}, },
label: None, label: None,
synthetic: false,
}, },
); );
} }
@ -89,6 +90,7 @@ pub fn split_up_roads(
IntersectionType::StopSign IntersectionType::StopSign
}, },
label: None, label: None,
synthetic: false,
}, },
); );
} }

View File

@ -89,24 +89,65 @@ impl Map {
} }
pub fn apply_fixes(&mut self, fixes: &MapFixes, timer: &mut Timer) { pub fn apply_fixes(&mut self, fixes: &MapFixes, timer: &mut Timer) {
let mut cnt = 0; let mut applied = 0;
for fix in &fixes.fixes { let mut skipped = 0;
match fix {
MapFix::DeleteRoad(orig) => { for orig in &fixes.delete_roads {
if let Some(r) = self.find_r(*orig) { if let Some(r) = self.find_r(*orig) {
self.roads.remove(&r).unwrap(); self.roads.remove(&r).unwrap();
cnt += 1; applied += 1;
} else {
skipped += 1;
} }
} }
MapFix::DeleteIntersection(orig) => {
for orig in &fixes.delete_intersections {
if let Some(i) = self.find_i(*orig) { if let Some(i) = self.find_i(*orig) {
self.intersections.remove(&i).unwrap(); self.intersections.remove(&i).unwrap();
cnt += 1; applied += 1;
} else {
skipped += 1;
}
}
for i in &fixes.add_intersections {
if self.gps_bounds.contains(i.orig_id.point) {
let id = StableIntersectionID(self.intersections.keys().max().unwrap().0 + 1);
self.intersections.insert(id, i.clone());
applied += 1;
} else {
skipped += 1;
}
}
for r in &fixes.add_roads {
match (
self.find_i(OriginalIntersection {
point: r.orig_id.pt1,
}),
self.find_i(OriginalIntersection {
point: r.orig_id.pt2,
}),
) {
(Some(i1), Some(i2)) => {
let mut road = r.clone();
road.i1 = i1;
road.i2 = i2;
let id = StableRoadID(self.roads.keys().max().unwrap().0 + 1);
self.roads.insert(id, road);
applied += 1;
}
_ => {
skipped += 1;
} }
} }
} }
}
timer.note(format!("Applied {} of {} fixes ", cnt, fixes.fixes.len())); timer.note(format!(
"Applied {} of {} fixes ",
applied,
applied + skipped
));
} }
} }
@ -144,6 +185,7 @@ pub struct Intersection {
pub intersection_type: IntersectionType, pub intersection_type: IntersectionType,
pub label: Option<String>, pub label: Option<String>,
pub orig_id: OriginalIntersection, pub orig_id: OriginalIntersection,
pub synthetic: bool,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
@ -243,9 +285,12 @@ impl Ord for OriginalIntersection {
} }
// Directives from the synthetic crate to apply to the raw_data layer. // Directives from the synthetic crate to apply to the raw_data layer.
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Clone)]
pub struct MapFixes { pub struct MapFixes {
pub fixes: Vec<MapFix>, pub delete_roads: Vec<OriginalRoad>,
pub delete_intersections: Vec<OriginalIntersection>,
pub add_intersections: Vec<Intersection>,
pub add_roads: Vec<Road>,
} }
impl MapFixes { impl MapFixes {
@ -253,13 +298,12 @@ impl MapFixes {
if let Ok(f) = abstutil::read_json::<MapFixes>("../data/fixes.json") { if let Ok(f) = abstutil::read_json::<MapFixes>("../data/fixes.json") {
f f
} else { } else {
MapFixes { fixes: Vec::new() } MapFixes {
delete_roads: Vec::new(),
delete_intersections: Vec::new(),
add_intersections: Vec::new(),
add_roads: Vec::new(),
}
} }
} }
} }
#[derive(Serialize, Deserialize)]
pub enum MapFix {
DeleteIntersection(OriginalIntersection),
DeleteRoad(OriginalRoad),
}

View File

@ -2,7 +2,7 @@ use abstutil::{read_binary, MultiMap, Timer};
use ezgui::world::{Object, ObjectID, World}; use ezgui::world::{Object, ObjectID, World};
use ezgui::{Color, EventCtx, GfxCtx, Line, Prerender, Text}; use ezgui::{Color, EventCtx, GfxCtx, Line, Prerender, Text};
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D}; use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
use map_model::raw_data::{MapFix, MapFixes, StableBuildingID, StableIntersectionID, StableRoadID}; use map_model::raw_data::{MapFixes, StableBuildingID, StableIntersectionID, StableRoadID};
use map_model::{raw_data, IntersectionType, LaneType, RoadSpec, LANE_THICKNESS}; use map_model::{raw_data, IntersectionType, LaneType, RoadSpec, LANE_THICKNESS};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::mem; use std::mem;
@ -111,7 +111,22 @@ impl Model {
} }
pub fn save_fixes(&self) { pub fn save_fixes(&self) {
abstutil::write_json("../data/fixes.json", &self.fixes).unwrap(); let mut fixes = self.fixes.clone();
// It's easiest to just go back and detect all of these
fixes.add_intersections.clear();
fixes.add_roads.clear();
for i in self.map.intersections.values() {
if i.synthetic {
fixes.add_intersections.push(i.clone());
}
}
for r in self.map.roads.values() {
if r.osm_tags.get("abst:synthetic") == Some(&"true".to_string()) {
fixes.add_roads.push(r.clone());
}
}
abstutil::write_json("../data/fixes.json", &fixes).unwrap();
println!("Wrote ../data/fixes.json"); println!("Wrote ../data/fixes.json");
} }
@ -163,15 +178,16 @@ impl Model {
impl Model { impl Model {
fn intersection_added(&mut self, id: StableIntersectionID, prerender: &Prerender) { fn intersection_added(&mut self, id: StableIntersectionID, prerender: &Prerender) {
let i = &self.map.intersections[&id]; let i = &self.map.intersections[&id];
let color = match i.intersection_type {
IntersectionType::TrafficSignal => Color::GREEN,
IntersectionType::StopSign => Color::RED,
IntersectionType::Border => Color::BLUE,
};
self.world.add( self.world.add(
prerender, prerender,
Object::new( Object::new(
ID::Intersection(id), ID::Intersection(id),
match i.intersection_type { if i.synthetic { color.alpha(0.5) } else { color },
IntersectionType::TrafficSignal => Color::GREEN,
IntersectionType::StopSign => Color::RED,
IntersectionType::Border => Color::BLUE,
},
Circle::new(i.point, INTERSECTION_RADIUS).to_polygon(), Circle::new(i.point, INTERSECTION_RADIUS).to_polygon(),
) )
.maybe_label(i.label.clone()), .maybe_label(i.label.clone()),
@ -190,6 +206,7 @@ impl Model {
orig_id: raw_data::OriginalIntersection { orig_id: raw_data::OriginalIntersection {
point: point.forcibly_to_gps(&self.map.gps_bounds), point: point.forcibly_to_gps(&self.map.gps_bounds),
}, },
synthetic: true,
}, },
); );
@ -199,11 +216,12 @@ impl Model {
pub fn move_i(&mut self, id: StableIntersectionID, point: Pt2D, prerender: &Prerender) { pub fn move_i(&mut self, id: StableIntersectionID, point: Pt2D, prerender: &Prerender) {
self.world.delete(ID::Intersection(id)); self.world.delete(ID::Intersection(id));
{ let gps_pt = {
let i = self.map.intersections.get_mut(&id).unwrap(); let i = self.map.intersections.get_mut(&id).unwrap();
i.point = point; i.point = point;
i.orig_id.point = point.forcibly_to_gps(&self.map.gps_bounds); i.orig_id.point = point.forcibly_to_gps(&self.map.gps_bounds);
} i.orig_id.point
};
self.intersection_added(id, prerender); self.intersection_added(id, prerender);
@ -214,9 +232,12 @@ impl Model {
let road = self.map.roads.get_mut(&r).unwrap(); let road = self.map.roads.get_mut(&r).unwrap();
if road.i1 == id { if road.i1 == id {
road.center_points[0] = point; road.center_points[0] = point;
// TODO This is valid for synthetic roads, but maybe weird otherwise...
road.orig_id.pt1 = gps_pt;
} else { } else {
assert_eq!(road.i2, id); assert_eq!(road.i2, id);
*road.center_points.last_mut().unwrap() = point; *road.center_points.last_mut().unwrap() = point;
road.orig_id.pt2 = gps_pt;
} }
self.road_added(r, prerender); self.road_added(r, prerender);
@ -263,7 +284,7 @@ impl Model {
self.world.delete(ID::Intersection(id)); self.world.delete(ID::Intersection(id));
self.fixes.fixes.push(MapFix::DeleteIntersection(i.orig_id)); self.fixes.delete_intersections.push(i.orig_id);
} }
pub fn get_i_center(&self, id: StableIntersectionID) -> Pt2D { pub fn get_i_center(&self, id: StableIntersectionID) -> Pt2D {
@ -420,7 +441,7 @@ impl Model {
self.roads_per_intersection.remove(r.i1, id); self.roads_per_intersection.remove(r.i1, id);
self.roads_per_intersection.remove(r.i2, id); self.roads_per_intersection.remove(r.i2, id);
self.fixes.fixes.push(MapFix::DeleteRoad(r.orig_id)); self.fixes.delete_roads.push(r.orig_id);
} }
pub fn get_road_spec(&self, id: StableRoadID) -> String { pub fn get_road_spec(&self, id: StableRoadID) -> String {