mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
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:
parent
b756edb36f
commit
182f5139a5
@ -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)
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user