diff --git a/game/src/abtest/mod.rs b/game/src/abtest/mod.rs index 5abb3e57c3..811c584e3c 100644 --- a/game/src/abtest/mod.rs +++ b/game/src/abtest/mod.rs @@ -6,6 +6,7 @@ use crate::debug::DebugMode; use crate::game::{State, Transition}; use crate::render::MIN_ZOOM_FOR_DETAIL; use crate::ui::{PerMapUI, UI}; +use abstutil::Timer; use ezgui::{ hotkey, lctrl, Color, EventCtx, EventLoopMode, GeomBatch, GfxCtx, Key, Line, ModalMenu, Text, }; @@ -268,12 +269,12 @@ impl ABTestMode { primary_map: std::mem::replace(&mut ui.primary.map, Map::blank()), primary_sim: std::mem::replace( &mut ui.primary.sim, - Sim::new(&blank_map, SimOptions::new("tmp")), + Sim::new(&blank_map, SimOptions::new("tmp"), &mut Timer::throwaway()), ), secondary_map: std::mem::replace(&mut secondary.map, Map::blank()), secondary_sim: std::mem::replace( &mut secondary.sim, - Sim::new(&blank_map, SimOptions::new("tmp")), + Sim::new(&blank_map, SimOptions::new("tmp"), &mut Timer::throwaway()), ), }; diff --git a/game/src/ui.rs b/game/src/ui.rs index c054630939..e876b133cf 100644 --- a/game/src/ui.rs +++ b/game/src/ui.rs @@ -470,6 +470,10 @@ impl PerMapUI { } pub fn reset_sim(&mut self) { - self.sim = Sim::new(&self.map, self.current_flags.sim_flags.opts.clone()); + self.sim = Sim::new( + &self.map, + self.current_flags.sim_flags.opts.clone(), + &mut Timer::new("reset simulation"), + ); } } diff --git a/map_model/src/raw.rs b/map_model/src/raw.rs index 22214ca597..03d2054393 100644 --- a/map_model/src/raw.rs +++ b/map_model/src/raw.rs @@ -126,9 +126,10 @@ impl RawMap { } } + let remap_pts = !self.gps_bounds.approx_eq(&fixes.gps_bounds); + for mut i in fixes.add_intersections.clone() { - // Fix up the geometry, maybe. - if !self.gps_bounds.approx_eq(&fixes.gps_bounds) { + if remap_pts { i.point = Pt2D::forcibly_from_gps( i.point.to_gps(&fixes.gps_bounds).unwrap(), &self.gps_bounds, @@ -143,8 +144,7 @@ impl RawMap { } for mut r in fixes.add_roads.clone() { - // Fix up the geometry, maybe. - if !self.gps_bounds.approx_eq(&fixes.gps_bounds) { + if remap_pts { r.center_points = self .gps_bounds .forcibly_convert(&fixes.gps_bounds.must_convert_back(&r.center_points)); diff --git a/sim/src/make/load.rs b/sim/src/make/load.rs index 7c6d3ca054..60cf3ecc15 100644 --- a/sim/src/make/load.rs +++ b/sim/src/make/load.rs @@ -92,7 +92,7 @@ impl SimFlags { if opts.run_name == "unnamed" { opts.run_name = scenario.scenario_name.clone(); } - let mut sim = Sim::new(&map, opts); + let mut sim = Sim::new(&map, opts, timer); scenario.instantiate(&mut sim, &map, &mut rng, timer); (map, sim, rng) @@ -103,7 +103,7 @@ impl SimFlags { .expect(&format!("Couldn't load map from {}", self.load)); timer.start("create sim"); - let sim = Sim::new(&map, opts); + let sim = Sim::new(&map, opts, timer); timer.stop("create sim"); (map, sim, rng) @@ -114,7 +114,7 @@ impl SimFlags { .expect(&format!("Couldn't load map from {}", self.load)); timer.start("create sim"); - let sim = Sim::new(&map, opts); + let sim = Sim::new(&map, opts, timer); timer.stop("create sim"); (map, sim, rng) diff --git a/sim/src/mechanics/parking.rs b/sim/src/mechanics/parking.rs index a43c17643c..1e4b0cb51e 100644 --- a/sim/src/mechanics/parking.rs +++ b/sim/src/mechanics/parking.rs @@ -1,6 +1,7 @@ use crate::{AgentMetadata, CarID, CarStatus, DrawCarInput, ParkedCar, ParkingSpot, Vehicle}; use abstutil::{ deserialize_btreemap, deserialize_multimap, serialize_btreemap, serialize_multimap, MultiMap, + Timer, }; use geom::{Distance, Duration, Pt2D}; use map_model; @@ -49,7 +50,7 @@ pub struct ParkingSimState { impl ParkingSimState { // Counterintuitive: any spots located in blackholes are just not represented here. If somebody // tries to drive from a blackholed spot, they couldn't reach most places. - pub fn new(map: &Map) -> ParkingSimState { + pub fn new(map: &Map, timer: &mut Timer) -> ParkingSimState { let mut sim = ParkingSimState { parked_cars: BTreeMap::new(), occupants: BTreeMap::new(), @@ -63,7 +64,7 @@ impl ParkingSimState { driving_to_offstreet: MultiMap::new(), }; for l in map.all_lanes() { - if let Some(lane) = ParkingLane::new(l, map) { + if let Some(lane) = ParkingLane::new(l, map, timer) { sim.driving_to_parking_lanes.insert(lane.driving_lane, l.id); sim.onstreet_lanes.insert(lane.parking_lane, lane); } @@ -284,15 +285,13 @@ impl ParkingSimState { pub fn spot_to_sidewalk_pos(&self, spot: ParkingSpot, map: &Map) -> Position { match spot { ParkingSpot::Onstreet(l, idx) => { - // TODO Consider precomputing this. - let sidewalk = map.find_closest_lane(l, vec![LaneType::Sidewalk]).unwrap(); + let lane = &self.onstreet_lanes[&l]; // Always centered in the entire parking spot Position::new( l, - self.onstreet_lanes[&l].spot_dist_along[idx] - - (map_model::PARKING_SPOT_LENGTH / 2.0), + lane.spot_dist_along[idx] - (map_model::PARKING_SPOT_LENGTH / 2.0), ) - .equiv_pos(sidewalk, Distance::ZERO, map) + .equiv_pos(lane.sidewalk, Distance::ZERO, map) } ParkingSpot::Offstreet(b, _) => map.get_b(b).front_path.sidewalk, } @@ -359,29 +358,38 @@ impl ParkingSimState { struct ParkingLane { parking_lane: LaneID, driving_lane: LaneID, + sidewalk: LaneID, // The front of the parking spot (farthest along the lane) spot_dist_along: Vec, } impl ParkingLane { - fn new(l: &Lane, map: &Map) -> Option { - if l.lane_type != LaneType::Parking { + fn new(lane: &Lane, map: &Map, timer: &mut Timer) -> Option { + if lane.lane_type != LaneType::Parking { return None; } - let driving_lane = if let Some(l) = map.get_parent(l.id).parking_to_driving(l.id) { + let driving_lane = if let Some(l) = map.get_parent(lane.id).parking_to_driving(lane.id) { l } else { - panic!("Parking lane {} has no driving lane!", l.id); + // Serious enough to blow up loudly. + panic!("Parking lane {} has no driving lane!", lane.id); }; if map.get_l(driving_lane).parking_blackhole.is_some() { return None; } + let sidewalk = if let Ok(l) = map.find_closest_lane(lane.id, vec![LaneType::Sidewalk]) { + l + } else { + timer.warn(format!("Parking lane {} has no sidewalk!", lane.id)); + return None; + }; Some(ParkingLane { - parking_lane: l.id, + parking_lane: lane.id, driving_lane, - spot_dist_along: (0..l.number_parking_spots()) + sidewalk, + spot_dist_along: (0..lane.number_parking_spots()) .map(|idx| map_model::PARKING_SPOT_LENGTH * (2.0 + idx as f64)) .collect(), }) diff --git a/sim/src/sim.rs b/sim/src/sim.rs index 545b671f1f..c3e824e2c9 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -81,7 +81,7 @@ impl SimOptions { // Setup impl Sim { - pub fn new(map: &Map, opts: SimOptions) -> Sim { + pub fn new(map: &Map, opts: SimOptions, timer: &mut Timer) -> Sim { let mut scheduler = Scheduler::new(); // TODO Gridlock detection doesn't add value right now. if false { @@ -92,7 +92,7 @@ impl Sim { } Sim { driving: DrivingSimState::new(map, opts.recalc_lanechanging), - parking: ParkingSimState::new(map), + parking: ParkingSimState::new(map, timer), walking: WalkingSimState::new(), intersections: IntersectionSimState::new( map, diff --git a/tests/src/sim_determinism.rs b/tests/src/sim_determinism.rs index e6e5a9b350..3a0d158056 100644 --- a/tests/src/sim_determinism.rs +++ b/tests/src/sim_determinism.rs @@ -19,7 +19,11 @@ pub fn run(t: &mut TestRunner) { println!("Creating two simulations"); let flags = SimFlags::for_test("from_scratch_1"); let (map, mut sim1, _) = flags.load(&mut Timer::throwaway()); - let mut sim2 = Sim::new(&map, SimOptions::new("from_scratch_2")); + let mut sim2 = Sim::new( + &map, + SimOptions::new("from_scratch_2"), + &mut Timer::throwaway(), + ); Scenario::small_run(&map).instantiate( &mut sim1, &map, @@ -52,7 +56,11 @@ pub fn run(t: &mut TestRunner) { println!("Creating two simulations"); let flags = SimFlags::for_test("with_savestating_1"); let (map, mut sim1, _) = flags.load(&mut Timer::throwaway()); - let mut sim2 = Sim::new(&map, SimOptions::new("with_savestating_2")); + let mut sim2 = Sim::new( + &map, + SimOptions::new("with_savestating_2"), + &mut Timer::throwaway(), + ); Scenario::small_run(&map).instantiate( &mut sim1, &map,