mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-26 07:52:05 +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
|
||||
},
|
||||
label: None,
|
||||
synthetic: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -89,6 +90,7 @@ pub fn split_up_roads(
|
||||
IntersectionType::StopSign
|
||||
},
|
||||
label: None,
|
||||
synthetic: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -89,24 +89,65 @@ impl Map {
|
||||
}
|
||||
|
||||
pub fn apply_fixes(&mut self, fixes: &MapFixes, timer: &mut Timer) {
|
||||
let mut cnt = 0;
|
||||
for fix in &fixes.fixes {
|
||||
match fix {
|
||||
MapFix::DeleteRoad(orig) => {
|
||||
if let Some(r) = self.find_r(*orig) {
|
||||
self.roads.remove(&r).unwrap();
|
||||
cnt += 1;
|
||||
}
|
||||
let mut applied = 0;
|
||||
let mut skipped = 0;
|
||||
|
||||
for orig in &fixes.delete_roads {
|
||||
if let Some(r) = self.find_r(*orig) {
|
||||
self.roads.remove(&r).unwrap();
|
||||
applied += 1;
|
||||
} else {
|
||||
skipped += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for orig in &fixes.delete_intersections {
|
||||
if let Some(i) = self.find_i(*orig) {
|
||||
self.intersections.remove(&i).unwrap();
|
||||
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;
|
||||
}
|
||||
MapFix::DeleteIntersection(orig) => {
|
||||
if let Some(i) = self.find_i(*orig) {
|
||||
self.intersections.remove(&i).unwrap();
|
||||
cnt += 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 label: Option<String>,
|
||||
pub orig_id: OriginalIntersection,
|
||||
pub synthetic: bool,
|
||||
}
|
||||
|
||||
#[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.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
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 {
|
||||
@ -253,13 +298,12 @@ impl MapFixes {
|
||||
if let Ok(f) = abstutil::read_json::<MapFixes>("../data/fixes.json") {
|
||||
f
|
||||
} 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::{Color, EventCtx, GfxCtx, Line, Prerender, Text};
|
||||
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 std::collections::BTreeMap;
|
||||
use std::mem;
|
||||
@ -111,7 +111,22 @@ impl Model {
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@ -163,15 +178,16 @@ impl Model {
|
||||
impl Model {
|
||||
fn intersection_added(&mut self, id: StableIntersectionID, prerender: &Prerender) {
|
||||
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(
|
||||
prerender,
|
||||
Object::new(
|
||||
ID::Intersection(id),
|
||||
match i.intersection_type {
|
||||
IntersectionType::TrafficSignal => Color::GREEN,
|
||||
IntersectionType::StopSign => Color::RED,
|
||||
IntersectionType::Border => Color::BLUE,
|
||||
},
|
||||
if i.synthetic { color.alpha(0.5) } else { color },
|
||||
Circle::new(i.point, INTERSECTION_RADIUS).to_polygon(),
|
||||
)
|
||||
.maybe_label(i.label.clone()),
|
||||
@ -190,6 +206,7 @@ impl Model {
|
||||
orig_id: raw_data::OriginalIntersection {
|
||||
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) {
|
||||
self.world.delete(ID::Intersection(id));
|
||||
|
||||
{
|
||||
let gps_pt = {
|
||||
let i = self.map.intersections.get_mut(&id).unwrap();
|
||||
i.point = point;
|
||||
i.orig_id.point = point.forcibly_to_gps(&self.map.gps_bounds);
|
||||
}
|
||||
i.orig_id.point
|
||||
};
|
||||
|
||||
self.intersection_added(id, prerender);
|
||||
|
||||
@ -214,9 +232,12 @@ impl Model {
|
||||
let road = self.map.roads.get_mut(&r).unwrap();
|
||||
if road.i1 == id {
|
||||
road.center_points[0] = point;
|
||||
// TODO This is valid for synthetic roads, but maybe weird otherwise...
|
||||
road.orig_id.pt1 = gps_pt;
|
||||
} else {
|
||||
assert_eq!(road.i2, id);
|
||||
*road.center_points.last_mut().unwrap() = point;
|
||||
road.orig_id.pt2 = gps_pt;
|
||||
}
|
||||
|
||||
self.road_added(r, prerender);
|
||||
@ -263,7 +284,7 @@ impl Model {
|
||||
|
||||
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 {
|
||||
@ -420,7 +441,7 @@ impl Model {
|
||||
self.roads_per_intersection.remove(r.i1, 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user