mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 00:12:55 +03:00
recording and applying fixes to create new synthetic intersections and roads
This commit is contained in:
parent
1e4f36dec1
commit
e52fa1fc1a
@ -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,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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),
|
|
||||||
}
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user