rip out old mapfixes code. pure OSM is more maintainable. keep map_editor for drawing synthetic maps and debugging raw maps

This commit is contained in:
Dustin Carlino 2020-05-10 10:39:08 -07:00
parent b756edb36f
commit 182f5139a5
15 changed files with 85 additions and 438 deletions

View File

@ -145,10 +145,6 @@ pub fn path_all_shortcuts() -> String {
// Input data (For developers to build maps, not needed at runtime)
pub fn path_fixes(city: &str, map: &str) -> String {
format!("../data/input/{}/fixes/{}.json", city, map)
}
pub fn path_pending_screenshots(map_name: &str) -> String {
format!("../data/input/screenshots/pending_{}", map_name)
}

View File

@ -1,4 +1,5 @@
{
"city_name": "synthetic",
"name": "signal_double",
"roads": [
[
@ -31,7 +32,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -64,7 +66,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -97,7 +100,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -130,7 +134,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -163,7 +168,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -196,7 +202,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -229,7 +236,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
]
],
@ -384,4 +392,4 @@
"max_lat": 47.7155
},
"driving_side": "Right"
}
}

View File

@ -1,4 +1,5 @@
{
"city_name": "synthetic",
"name": "signal_fan_in",
"roads": [
[
@ -32,7 +33,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -66,7 +68,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -100,7 +103,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -134,7 +138,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -168,7 +173,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -206,7 +212,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -244,7 +251,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -278,7 +286,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -316,7 +325,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -350,7 +360,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -388,7 +399,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
]
],
@ -595,4 +607,4 @@
"max_lat": 47.7155
},
"driving_side": "Right"
}
}

View File

@ -1,4 +1,5 @@
{
"city_name": "synthetic",
"name": "signal_single",
"roads": [
[
@ -31,7 +32,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -64,7 +66,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -97,7 +100,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -130,7 +134,8 @@
"maxspeed": "25 mph",
"name": "Streety McStreetFace"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -165,7 +170,8 @@
"name": "Streety McStreetFace",
"turn:lanes:backward": "left|through;right"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -199,7 +205,8 @@
"name": "Streety McStreetFace",
"turn:lanes:backward": "left|through;right"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -234,7 +241,8 @@
"name": "Streety McStreetFace",
"turn:lanes:backward": "left|through;right"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
],
[
@ -269,7 +277,8 @@
"name": "Streety McStreetFace",
"turn:lanes:backward": "left|through;right"
},
"turn_restrictions": []
"turn_restrictions": [],
"complicated_turn_restrictions": []
}
]
],
@ -437,4 +446,4 @@
"max_lat": 47.7155
},
"driving_side": "Right"
}
}

View File

@ -290,7 +290,7 @@ pub fn prebake_all() {
let mut timer = Timer::new("prebake all challenge results");
{
let map = map_model::Map::new(abstutil::path_map("montlake"), false, &mut timer);
let map = map_model::Map::new(abstutil::path_map("montlake"), &mut timer);
let scenario: Scenario =
abstutil::read_binary(abstutil::path_scenario("montlake", "weekday"), &mut timer);
prebake(&map, scenario, None, &mut timer);
@ -306,7 +306,7 @@ pub fn prebake_all() {
}
{
let map = map_model::Map::new(abstutil::path_map("lakeslice"), false, &mut timer);
let map = map_model::Map::new(abstutil::path_map("lakeslice"), &mut timer);
let scenario: Scenario =
abstutil::read_binary(abstutil::path_scenario("lakeslice", "weekday"), &mut timer);
prebake(&map, scenario, None, &mut timer);
@ -329,7 +329,7 @@ pub fn generic_prebake_all() {
}
for (map_path, list) in per_map {
timer.start(format!("prebake for {}", map_path));
let map = map_model::Map::new(map_path.clone(), false, &mut timer);
let map = map_model::Map::new(map_path.clone(), &mut timer);
let mut done_scenarios = HashSet::new();
for challenge in list {

View File

@ -13,7 +13,6 @@ struct Job {
scenario: bool,
scenario_everyone: bool,
use_fixes: bool,
only_map: Option<String>,
}
@ -30,8 +29,6 @@ fn main() {
// Produce a variation of the weekday scenario including off-map trips.
scenario_everyone: args.enabled("--scenario_everyone"),
// By default, use geometry fixes from map_editor.
use_fixes: !args.enabled("--nofixes"),
// Only process one map. If not specified, process all maps defined by clipping polygons in
// data/input/$city/polygons/.
only_map: args.optional_free(),
@ -66,28 +63,27 @@ fn main() {
if job.raw_to_map {
let name = name.clone();
let use_fixes = job.use_fixes;
let handle = thread::spawn(move || {
utils::raw_to_map(&name, use_fixes);
utils::raw_to_map(&name);
});
handles.push(handle);
}
if job.scenario {
assert_eq!(job.city, "seattle");
seattle::ensure_popdat_exists(job.use_fixes);
seattle::ensure_popdat_exists();
let mut timer = abstutil::Timer::new(format!("Scenario for {}", name));
let map = map_model::Map::new(abstutil::path_map(&name), job.use_fixes, &mut timer);
let map = map_model::Map::new(abstutil::path_map(&name), &mut timer);
soundcast::make_weekday_scenario(&map, &mut timer).save();
}
if job.scenario_everyone {
assert_eq!(job.city, "seattle");
seattle::ensure_popdat_exists(job.use_fixes);
seattle::ensure_popdat_exists();
let mut timer = abstutil::Timer::new(format!("Scenario for {}", name));
let map = map_model::Map::new(abstutil::path_map(&name), job.use_fixes, &mut timer);
let map = map_model::Map::new(abstutil::path_map(&name), &mut timer);
soundcast::make_weekday_scenario_with_everyone(&map, &mut timer).save();
}
}

View File

@ -69,7 +69,7 @@ pub fn osm_to_raw(name: &str) {
}
// Download and pre-process data needed to generate Seattle scenarios.
pub fn ensure_popdat_exists(use_fixes: bool) {
pub fn ensure_popdat_exists() {
if abstutil::file_exists(abstutil::path_popdat()) {
println!("- {} exists, not regenerating it", abstutil::path_popdat());
return;
@ -79,7 +79,7 @@ pub fn ensure_popdat_exists(use_fixes: bool) {
osm_to_raw("huge_seattle");
}
if !abstutil::file_exists(abstutil::path_map("huge_seattle")) {
crate::utils::raw_to_map("huge_seattle", use_fixes);
crate::utils::raw_to_map("huge_seattle");
}
crate::soundcast::import_data();

View File

@ -111,7 +111,7 @@ fn import_parcels(
path: &str,
timer: &mut Timer,
) -> Result<(HashMap<usize, Endpoint>, BTreeMap<i64, Parcel>), failure::Error> {
let map = Map::new(abstutil::path_map("huge_seattle"), false, timer);
let map = Map::new(abstutil::path_map("huge_seattle"), timer);
// TODO I really just want to do polygon containment with a quadtree. FindClosest only does
// line-string stuff right now, which'll be weird for the last->first pt line and stuff.

View File

@ -228,7 +228,7 @@ fn clip_trips(map: &Map, timer: &mut Timer) -> Vec<Trip> {
let maybe_huge_map = if map.get_name() == "huge_seattle" {
None
} else {
let huge_map = Map::new(abstutil::path_map("huge_seattle"), false, timer);
let huge_map = Map::new(abstutil::path_map("huge_seattle"), timer);
let mut huge_osm_id_to_bldg = HashMap::new();
for b in huge_map.all_buildings() {

View File

@ -91,9 +91,9 @@ fn run(cmd: &mut Command) {
}
// Converts a RawMap to a Map.
pub fn raw_to_map(name: &str, use_fixes: bool) {
pub fn raw_to_map(name: &str) {
let mut timer = abstutil::Timer::new(format!("Raw->Map for {}", name));
let map = map_model::Map::new(abstutil::path_raw_map(name), use_fixes, &mut timer);
let map = map_model::Map::new(abstutil::path_raw_map(name), &mut timer);
timer.start("save map");
map.save();
timer.stop("save map");

View File

@ -57,17 +57,10 @@ impl UI {
let load = args.optional_free();
let include_bldgs = args.enabled("--bldgs");
let intersection_geom = args.enabled("--geom");
let no_fixes = args.enabled("--nofixes");
args.done();
let model = if let Some(path) = load {
Model::import(
path,
include_bldgs,
intersection_geom,
no_fixes,
ctx.prerender,
)
Model::import(path, include_bldgs, intersection_geom, ctx.prerender)
} else {
Model::blank()
};
@ -87,7 +80,6 @@ impl UI {
vec![
(hotkey(Key::Escape), "quit"),
(None, "save raw map"),
(hotkey(Key::F), "save map fixes"),
(hotkey(Key::J), "warp to something"),
(None, "produce OSM parking+sidewalk diff"),
(hotkey(Key::G), "preview all intersections"),
@ -231,9 +223,6 @@ impl GUI for UI {
} else if could_swap && ctx.input.key_pressed(Key::S, "swap lanes") {
self.model.swap_lanes(r, ctx.prerender);
self.model.world.handle_mouseover(ctx);
} else if ctx.input.key_pressed(Key::M, "merge road") {
self.model.merge_r(r, ctx.prerender);
self.model.world.handle_mouseover(ctx);
} else if ctx.input.key_pressed(Key::T, "toggle parking") {
self.model.toggle_r_parking(r, ctx.prerender);
self.model.world.handle_mouseover(ctx);
@ -310,9 +299,6 @@ impl GUI for UI {
self.state = State::SavingModel(Wizard::new());
}
}
"save map fixes" => {
self.model.save_fixes();
}
"warp to something" => {
self.state = State::EnteringWarp(Wizard::new());
}

View File

@ -44,7 +44,6 @@ impl Model {
path: String,
include_bldgs: bool,
intersection_geom: bool,
mut no_fixes: bool,
prerender: &Prerender,
) -> Model {
let mut timer = Timer::new("import map");
@ -55,14 +54,9 @@ impl Model {
} else {
// Synthetic map!
model.map = abstutil::read_json(path, &mut timer);
no_fixes = true;
}
model.intersection_geom = intersection_geom;
if !no_fixes {
model.map.apply_all_fixes(&mut timer);
}
if model.include_bldgs {
for id in model.map.buildings.keys().cloned().collect::<Vec<_>>() {
model.bldg_added(id, prerender);
@ -128,15 +122,6 @@ impl Model {
abstutil::write_json(abstutil::path_synthetic_map(&self.map.name), &self.map);
}
pub fn save_fixes(&mut self) {
abstutil::write_json(
abstutil::path_fixes(&self.map.city_name, &self.map.name),
&self
.map
.generate_fixes(&mut Timer::new("calculate MapFixes")),
);
}
fn compute_bounds(&self) -> Bounds {
let mut bounds = Bounds::new();
for b in self.map.buildings.values() {
@ -393,6 +378,7 @@ impl Model {
],
osm_tags,
turn_restrictions: Vec::new(),
complicated_turn_restrictions: Vec::new(),
},
);
self.road_added(id, prerender);
@ -795,35 +781,6 @@ impl Model {
self.show_r_points(id, prerender);
}
// TODO Need to show_r_points of the thing we wind up selecting after this.
pub fn merge_r(&mut self, id: OriginalRoad, prerender: &Prerender) {
if let Err(e) = self.map.can_merge_short_road(id) {
println!("Can't merge this road: {}", e);
return;
}
self.stop_showing_pts(id);
let (retained_i, deleted_i, deleted_roads, created_roads, deleted_trs) =
self.map.merge_short_road(id).unwrap();
for tr in deleted_trs {
self.world.delete(ID::TurnRestriction(tr));
}
self.world.delete(ID::Intersection(retained_i));
self.intersection_added(retained_i, prerender);
self.world.delete(ID::Intersection(deleted_i));
for r in deleted_roads {
// This is safe, can_merge_short_road checks for turn restrictions.
self.world.delete(ID::Road(r));
}
for r in created_roads {
self.road_added(r, prerender);
}
}
pub fn get_r_center(&self, id: OriginalRoad) -> Pt2D {
PolyLine::new(self.map.roads[&id].center_points.clone()).middle()
}

View File

@ -52,7 +52,7 @@ pub struct Map {
}
impl Map {
pub fn new(path: String, mut use_map_fixes: bool, timer: &mut Timer) -> Map {
pub fn new(path: String, timer: &mut Timer) -> Map {
if path.starts_with(&abstutil::path_all_maps()) {
match abstutil::maybe_read_binary(path.clone(), timer) {
Ok(map) => {
@ -108,13 +108,9 @@ impl Map {
abstutil::read_binary(path, timer)
} else {
// Synthetic
use_map_fixes = false;
abstutil::read_json(path, timer)
};
if use_map_fixes {
raw.apply_all_fixes(timer);
}
// Do this after applying fixes, which might split off pieces of the map.
// Better to defer this and see RawMaps with more debug info in map_editor
make::remove_disconnected_roads(&mut raw, timer);
Map::create_from_raw(raw, timer)
}

View File

@ -1,6 +1,6 @@
use crate::make::get_lane_types;
use crate::{osm, AreaType, IntersectionType, RoadSpec};
use abstutil::{deserialize_btreemap, retain_btreemap, serialize_btreemap, Error, Timer, Warn};
use abstutil::{deserialize_btreemap, serialize_btreemap, Timer, Warn};
use geom::{Angle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
use gtfs::Route;
use serde_derive::{Deserialize, Serialize};
@ -36,15 +36,11 @@ pub struct RawMap {
pub driving_side: DrivingSide,
}
// A way to refer to roads across many maps.
//
// Previously, OriginalRoad and OriginalIntersection used LonLat to reference objects across maps.
// This had some problems:
// - f64's need to be trimmed and compared carefully with epsilon checks.
// - It was confusing to modify these IDs when applying MapFixes.
// Using OSM IDs could also have problems as new OSM input is used over time, because MapFixes may
// refer to stale IDs.
// TODO Look at some stable ID standard like linear referencing
// A way to refer to roads across many maps and over time. Also trivial to relate with OSM to find
// upstream problems.
// - Using LonLat is more indirect, and f64's need to be trimmed and compared carefully with epsilon
// checks.
// - TODO Look at some stable ID standard like linear referencing
// (https://github.com/opentraffic/architecture/issues/1).
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct OriginalRoad {
@ -104,174 +100,6 @@ impl RawMap {
}
}
pub fn apply_all_fixes(&mut self, timer: &mut Timer) {
// TODO Not using fixes anywhere right now. Maybe delete all of this code.
if true {
return;
}
if self.name == "huge_seattle" {
let master_fixes: MapFixes = abstutil::maybe_read_json(
abstutil::path_fixes(&self.city_name, "huge_seattle"),
timer,
)
.unwrap_or_else(|_| MapFixes::new(self.gps_bounds.clone()));
self.apply_fixes("huge_seattle", &master_fixes, timer);
} else {
let mut master_fixes: MapFixes =
abstutil::read_json(abstutil::path_fixes(&self.city_name, "huge_seattle"), timer);
master_fixes.remap_pts(&self.gps_bounds);
let local_fixes: MapFixes =
abstutil::maybe_read_json(abstutil::path_fixes(&self.city_name, &self.name), timer)
.unwrap_or_else(|_| MapFixes::new(self.gps_bounds.clone()));
self.apply_fixes("huge_seattle", &master_fixes, timer);
self.apply_fixes(&self.name.clone(), &local_fixes, timer);
}
// Validation round afterwards
for (id, r) in &self.roads {
if r.center_points[0] != self.intersections[&id.i1].point
|| *r.center_points.last().unwrap() != self.intersections[&id.i2].point
{
timer.warn(format!("{} geomtry doesn't match intersections", id));
}
}
}
fn apply_fixes(&mut self, name: &str, fixes: &MapFixes, timer: &mut Timer) {
assert!(self.gps_bounds.approx_eq(&fixes.gps_bounds));
let mut applied = 0;
let mut skipped = 0;
for r in &fixes.delete_roads {
if self.roads.contains_key(r) {
self.delete_road(*r);
applied += 1;
} else {
skipped += 1;
}
}
for i in &fixes.delete_intersections {
if self.intersections.contains_key(i) {
if self.can_delete_intersection(*i) {
self.delete_intersection(*i);
} else {
println!("Can't delete {}, roads are connected, skipping", i);
skipped += 1;
}
applied += 1;
} else {
skipped += 1;
}
}
for (id, i) in &fixes.override_intersections {
if self
.gps_bounds
.contains(i.point.forcibly_to_gps(&self.gps_bounds))
{
self.intersections.insert(*id, i.clone());
applied += 1;
} else {
skipped += 1;
}
}
for (id, r) in &fixes.override_roads {
if self.intersections.contains_key(&id.i1) && self.intersections.contains_key(&id.i2) {
self.roads.insert(*id, r.clone());
applied += 1;
} else {
skipped += 1;
}
}
timer.note(format!(
"Applied {} of {} {} fixes",
applied,
applied + skipped,
name
));
}
// TODO Ignores buildings right now.
pub fn generate_fixes(&self, timer: &mut Timer) -> MapFixes {
// TODO Need to generalize this a bit
assert_eq!(self.city_name, "seattle");
let orig: RawMap = abstutil::read_binary(abstutil::path_raw_map(&self.name), timer);
let mut fixes = MapFixes::new(self.gps_bounds.clone());
// What'd we delete?
fixes.delete_roads.extend(
orig.roads
.keys()
.cloned()
.collect::<BTreeSet<_>>()
.difference(&self.roads.keys().cloned().collect::<BTreeSet<_>>()),
);
fixes.delete_intersections.extend(
orig.intersections
.keys()
.cloned()
.collect::<BTreeSet<_>>()
.difference(&self.intersections.keys().cloned().collect::<BTreeSet<_>>()),
);
// What'd we create or modify?
for (id, i) in &self.intersections {
if orig
.intersections
.get(id)
.map(|orig_i| orig_i != i)
.unwrap_or(true)
{
fixes.override_intersections.insert(*id, i.clone());
}
}
for (id, r) in &self.roads {
if orig.roads.get(id).map(|orig_r| orig_r != r).unwrap_or(true) {
fixes.override_roads.insert(*id, r.clone());
}
}
if self.name != "huge_seattle" {
// Filter out things that we just inherited from the master fixes.
let mut master_fixes: MapFixes =
abstutil::read_json(abstutil::path_fixes(&self.city_name, "huge_seattle"), timer);
master_fixes.remap_pts(&self.gps_bounds);
fixes.delete_roads = fixes
.delete_roads
.difference(&master_fixes.delete_roads)
.cloned()
.collect();
fixes.delete_intersections = fixes
.delete_intersections
.difference(&master_fixes.delete_intersections)
.cloned()
.collect();
retain_btreemap(&mut fixes.override_intersections, |id, i| {
master_fixes
.override_intersections
.get(id)
.map(|orig| orig != i)
.unwrap_or(true)
});
retain_btreemap(&mut fixes.override_roads, |id, r| {
master_fixes
.override_roads
.get(id)
.map(|orig| orig != r)
.unwrap_or(true)
});
}
fixes
}
// TODO Might be better to maintain this instead of doing a search everytime.
pub fn roads_per_intersection(&self, i: OriginalIntersection) -> Vec<OriginalRoad> {
let mut results = Vec::new();
@ -398,92 +226,6 @@ impl RawMap {
self.intersections.remove(&id).unwrap();
}
pub fn can_merge_short_road(&self, id: OriginalRoad) -> Result<(), Error> {
let i1 = &self.intersections[&id.i1];
let i2 = &self.intersections[&id.i2];
if i1.intersection_type == IntersectionType::Border
|| i2.intersection_type == IntersectionType::Border
{
return Err(Error::new(format!("{} touches a border", id)));
}
Ok(())
}
// (the surviving intersection, the deleted intersection, deleted roads, new roads, deleted
// turn restrictions)
pub fn merge_short_road(
&mut self,
short: OriginalRoad,
) -> Option<(
OriginalIntersection,
OriginalIntersection,
Vec<OriginalRoad>,
Vec<OriginalRoad>,
BTreeSet<TurnRestriction>,
)> {
assert!(self.can_merge_short_road(short).is_ok());
let mut orig_restrictions = BTreeSet::new();
for r in self
.roads_per_intersection(short.i1)
.into_iter()
.chain(self.roads_per_intersection(short.i2))
{
orig_restrictions.extend(self.turn_restrictions_involving(r));
}
// Clear out these restrictions first
for tr in &orig_restrictions {
println!("Warning: deleting turn restriction");
self.delete_turn_restriction(*tr);
}
let (i1, i2) = (short.i1, short.i2);
let i1_pt = self.intersections[&i1].point;
self.roads.remove(&short).unwrap();
// Arbitrarily keep i1 and destroy i2. If the intersection types differ, upgrade the
// surviving interesting.
{
// Don't use delete_intersection; we're manually fixing up connected roads
let i = self.intersections.remove(&i2).unwrap();
if i.intersection_type == IntersectionType::TrafficSignal {
self.intersections.get_mut(&i1).unwrap().intersection_type =
IntersectionType::TrafficSignal;
}
}
// Fix up all roads connected to i2. Delete them and create a new copy; the ID changes,
// since one intersection changes.
let mut deleted = vec![short];
let mut created = Vec::new();
for r in self.roads_per_intersection(i2) {
deleted.push(r);
let mut road = self.roads.remove(&r).unwrap();
let mut new_id = r;
if r.i1 == i2 {
new_id.i1 = i1;
road.center_points[0] = i1_pt;
// TODO More extreme: All of the points of the short road. Except there usually
// aren't many, since they're short.
//road.center_points.insert(0, i1_pt);
} else {
assert_eq!(r.i2, i2);
new_id.i2 = i1;
*road.center_points.last_mut().unwrap() = i1_pt;
//road.center_points.push(i1_pt);
}
self.roads.insert(new_id, road);
created.push(new_id);
}
Some((i1, i2, deleted, created, orig_restrictions))
}
pub fn can_add_turn_restriction(&self, from: OriginalRoad, to: OriginalRoad) -> bool {
let (i1, i2) = (from.i1, from.i2);
let (i3, i4) = (to.i1, to.i2);
@ -618,58 +360,6 @@ impl RestrictionType {
}
}
// Directives from the map_editor crate to apply to the RawMap layer.
#[derive(Serialize, Deserialize, Clone)]
pub struct MapFixes {
// Any Pt2Ds in the rest of the fixes are relative to these GPSBounds.
pub gps_bounds: GPSBounds,
pub delete_roads: BTreeSet<OriginalRoad>,
pub delete_intersections: BTreeSet<OriginalIntersection>,
// Create or modify
#[serde(
serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap"
)]
pub override_intersections: BTreeMap<OriginalIntersection, RawIntersection>,
#[serde(
serialize_with = "serialize_btreemap",
deserialize_with = "deserialize_btreemap"
)]
pub override_roads: BTreeMap<OriginalRoad, RawRoad>,
}
impl MapFixes {
fn new(gps_bounds: GPSBounds) -> MapFixes {
MapFixes {
gps_bounds,
delete_roads: BTreeSet::new(),
delete_intersections: BTreeSet::new(),
override_intersections: BTreeMap::new(),
override_roads: BTreeMap::new(),
}
}
// Only makes sense to call for huge_seattle fixes
fn remap_pts(&mut self, local_gps_bounds: &GPSBounds) {
let master_gps_bounds = &self.gps_bounds;
assert!(!master_gps_bounds.approx_eq(local_gps_bounds));
for i in self.override_intersections.values_mut() {
i.point = Pt2D::forcibly_from_gps(
i.point.to_gps(master_gps_bounds).unwrap(),
local_gps_bounds,
);
}
for mut r in self.override_roads.values_mut() {
r.center_points = local_gps_bounds
.forcibly_convert(&master_gps_bounds.must_convert_back(&r.center_points));
}
self.gps_bounds = local_gps_bounds.clone();
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
pub enum DrivingSide {
Right,

View File

@ -10,7 +10,6 @@ const RNG_SEED: u8 = 42;
#[derive(Clone)]
pub struct SimFlags {
pub load: String,
pub use_map_fixes: bool,
pub rng_seed: u8,
pub opts: SimOptions,
}
@ -25,7 +24,6 @@ impl SimFlags {
load: args
.optional_free()
.unwrap_or_else(|| "../data/system/maps/montlake.bin".to_string()),
use_map_fixes: !args.enabled("--nofixes"),
rng_seed,
opts: SimOptions {
run_name: args
@ -62,7 +60,6 @@ impl SimFlags {
pub fn synthetic_test(map: &str, run_name: &str) -> SimFlags {
SimFlags {
load: abstutil::path_map(map),
use_map_fixes: true,
rng_seed: RNG_SEED,
opts: SimOptions::new(run_name),
}
@ -83,7 +80,7 @@ impl SimFlags {
let mut sim: Sim = abstutil::read_binary(self.load.clone(), timer);
let mut map = Map::new(abstutil::path_map(&sim.map_name), false, timer);
let mut map = Map::new(abstutil::path_map(&sim.map_name), timer);
if sim.edits_name != "untitled edits" {
map.apply_edits(MapEdits::load(&map, &sim.edits_name, timer).unwrap(), timer);
map.recalculate_pathfinding_after_edits(timer);
@ -99,7 +96,7 @@ impl SimFlags {
let scenario: Scenario = abstutil::read_binary(self.load.clone(), timer);
let map = Map::new(abstutil::path_map(&scenario.map_name), false, timer);
let map = Map::new(abstutil::path_map(&scenario.map_name), timer);
if opts.run_name == "unnamed" {
opts.run_name = scenario.scenario_name.clone();
@ -114,7 +111,7 @@ impl SimFlags {
{
timer.note(format!("Loading map {}", self.load));
let map = Map::new(self.load.clone(), self.use_map_fixes, timer);
let map = Map::new(self.load.clone(), timer);
timer.start("create sim");
let sim = Sim::new(&map, opts, timer);