From 2abeebc55ee2912df23b2a263e8e472226cb4656 Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Tue, 17 Nov 2020 10:50:42 -0800 Subject: [PATCH] Add a third TripEndpoint case to appear at an exact Position (lane + distance). This is a necessary step before simplifying Scenario's IndividTrip to use TripEndpoints and mode instead of SpawnTrip. #258 --- game/src/info/person.rs | 2 ++ game/src/info/trip.rs | 8 +++++++ game/src/sandbox/dashboards/commuter.rs | 4 ++++ .../sandbox/dashboards/generic_trip_table.rs | 2 ++ game/src/sandbox/gameplay/freeform.rs | 12 ++++++++-- sim/src/lib.rs | 8 +++---- sim/src/make/activity_model.rs | 2 ++ sim/src/make/scenario.rs | 22 +++++++++++------- sim/src/trips.rs | 23 ++++++++++++------- 9 files changed, 61 insertions(+), 22 deletions(-) diff --git a/game/src/info/person.rs b/game/src/info/person.rs index 218a2a482f..a153100272 100644 --- a/game/src/info/person.rs +++ b/game/src/info/person.rs @@ -383,6 +383,7 @@ pub fn schedule( } } TripEndpoint::Border(_) => "off-map".to_string(), + TripEndpoint::SuddenlyAppear(_) => "suddenly appear".to_string(), }; rows.push( Text::from(Line(format!( @@ -412,6 +413,7 @@ pub fn schedule( } } TripEndpoint::Border(_) => "off-map".to_string(), + TripEndpoint::SuddenlyAppear(_) => "suddenly disappear".to_string(), }; rows.push( Text::from(Line(format!( diff --git a/game/src/info/trip.rs b/game/src/info/trip.rs index 05a6e8d89a..80f05c7016 100644 --- a/game/src/info/trip.rs +++ b/game/src/info/trip.rs @@ -899,5 +899,13 @@ fn endpoint(endpt: &TripEndpoint, app: &App) -> (ID, Pt2D, String) { ), ) } + TripEndpoint::SuddenlyAppear(pos) => ( + ID::Lane(pos.lane()), + pos.pt(&app.primary.map), + format!( + "suddenly appear {} along", + pos.dist_along().to_string(&app.opts.units) + ), + ), } } diff --git a/game/src/sandbox/dashboards/commuter.rs b/game/src/sandbox/dashboards/commuter.rs index 22ec54017e..a13b003b3c 100644 --- a/game/src/sandbox/dashboards/commuter.rs +++ b/game/src/sandbox/dashboards/commuter.rs @@ -85,10 +85,12 @@ impl CommuterPatterns { let block1 = match trip.start { TripEndpoint::Bldg(b) => bldg_to_block[&b], TripEndpoint::Border(i) => border_to_block[&i], + TripEndpoint::SuddenlyAppear(_) => continue, }; let block2 = match trip.end { TripEndpoint::Bldg(b) => bldg_to_block[&b], TripEndpoint::Border(i) => border_to_block[&i], + TripEndpoint::SuddenlyAppear(_) => continue, }; // Totally ignore trips within the same block if block1 != block2 { @@ -151,6 +153,7 @@ impl CommuterPatterns { count.inc(self.border_to_block[&i]); } } + TripEndpoint::SuddenlyAppear(_) => {} } } else { match trip.start { @@ -162,6 +165,7 @@ impl CommuterPatterns { count.inc(self.border_to_block[&i]); } } + TripEndpoint::SuddenlyAppear(_) => {} } } } diff --git a/game/src/sandbox/dashboards/generic_trip_table.rs b/game/src/sandbox/dashboards/generic_trip_table.rs index 6d661770b4..97ff0c302b 100644 --- a/game/src/sandbox/dashboards/generic_trip_table.rs +++ b/game/src/sandbox/dashboards/generic_trip_table.rs @@ -169,6 +169,7 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch { .centered_on(match trip.start { TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center, TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(), + TripEndpoint::SuddenlyAppear(pos) => pos.pt(&app.primary.map), }), ); batch.append( @@ -182,6 +183,7 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch { .centered_on(match trip.end { TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center, TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(), + TripEndpoint::SuddenlyAppear(pos) => pos.pt(&app.primary.map), }), ); diff --git a/game/src/sandbox/gameplay/freeform.rs b/game/src/sandbox/gameplay/freeform.rs index 8da470db18..6a0300c088 100644 --- a/game/src/sandbox/gameplay/freeform.rs +++ b/game/src/sandbox/gameplay/freeform.rs @@ -433,6 +433,7 @@ impl State for AgentSpawner { match endpt { TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(), TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(), + TripEndpoint::SuddenlyAppear(_) => unreachable!(), }, ); } @@ -442,6 +443,7 @@ impl State for AgentSpawner { match endpt { TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(), TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(), + TripEndpoint::SuddenlyAppear(_) => unreachable!(), }, ); if let Some(p) = poly { @@ -513,8 +515,14 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) { now, TripSpec::JustWalking { start: SidewalkSpot::suddenly_appear( - lane.id, - Scenario::rand_dist(&mut rng, 0.1 * lane.length(), 0.9 * lane.length()), + Position::new( + lane.id, + Scenario::rand_dist( + &mut rng, + 0.1 * lane.length(), + 0.9 * lane.length(), + ), + ), map, ), goal: SidewalkSpot::building( diff --git a/sim/src/lib.rs b/sim/src/lib.rs index 5a2362b7ee..43333667cd 100644 --- a/sim/src/lib.rs +++ b/sim/src/lib.rs @@ -523,12 +523,12 @@ impl SidewalkSpot { }) } - pub fn suddenly_appear(l: LaneID, dist: Distance, map: &Map) -> SidewalkSpot { - let lane = map.get_l(l); + pub fn suddenly_appear(pos: Position, map: &Map) -> SidewalkSpot { + let lane = map.get_l(pos.lane()); assert!(lane.is_walkable()); - assert!(dist <= lane.length()); + assert!(pos.dist_along() <= lane.length()); SidewalkSpot { - sidewalk_pos: Position::new(l, dist), + sidewalk_pos: pos, connection: SidewalkPOI::SuddenlyAppear, } } diff --git a/sim/src/make/activity_model.rs b/sim/src/make/activity_model.rs index ab2264b56b..9f7074ee7b 100644 --- a/sim/src/make/activity_model.rs +++ b/sim/src/make/activity_model.rs @@ -159,6 +159,8 @@ impl ScenarioGenerator { (TripEndpoint::Border(_), TripEndpoint::Border(_)) => { num_trips_passthru += 1; } + (TripEndpoint::SuddenlyAppear(_), _) => unreachable!(), + (_, TripEndpoint::SuddenlyAppear(_)) => unreachable!(), }; (home, work, fork_rng(rng)) diff --git a/sim/src/make/scenario.rs b/sim/src/make/scenario.rs index 594ddfc1a9..ae76eee946 100644 --- a/sim/src/make/scenario.rs +++ b/sim/src/make/scenario.rs @@ -511,9 +511,7 @@ impl SpawnTrip { pub fn start(&self, map: &Map) -> TripEndpoint { match self { - SpawnTrip::VehicleAppearing { ref start, .. } => { - TripEndpoint::Border(map.get_l(start.lane()).src_i) - } + SpawnTrip::VehicleAppearing { start, .. } => TripEndpoint::SuddenlyAppear(*start), SpawnTrip::FromBorder { dr, .. } => TripEndpoint::Border(dr.src_i(map)), SpawnTrip::UsingParkedCar(b, _) => TripEndpoint::Bldg(*b), SpawnTrip::UsingBike(b, _) => TripEndpoint::Bldg(*b), @@ -521,9 +519,7 @@ impl SpawnTrip { match spot.connection { SidewalkPOI::Building(b) => TripEndpoint::Bldg(b), SidewalkPOI::Border(i) => TripEndpoint::Border(i), - SidewalkPOI::SuddenlyAppear => { - TripEndpoint::Border(map.get_l(spot.sidewalk_pos.lane()).src_i) - } + SidewalkPOI::SuddenlyAppear => TripEndpoint::SuddenlyAppear(spot.sidewalk_pos), _ => unreachable!(), } } @@ -565,6 +561,11 @@ impl SpawnTrip { goal: to.driving_goal(PathConstraints::Car, map)?, is_bike: false, }, + TripEndpoint::SuddenlyAppear(start) => SpawnTrip::VehicleAppearing { + start, + goal: to.driving_goal(PathConstraints::Bike, map)?, + is_bike: false, + }, }, TripMode::Bike => match from { TripEndpoint::Bldg(b) => { @@ -575,6 +576,11 @@ impl SpawnTrip { goal: to.driving_goal(PathConstraints::Bike, map)?, is_bike: true, }, + TripEndpoint::SuddenlyAppear(start) => SpawnTrip::VehicleAppearing { + start, + goal: to.driving_goal(PathConstraints::Bike, map)?, + is_bike: true, + }, }, TripMode::Walk => { SpawnTrip::JustWalking(from.start_sidewalk_spot(map)?, to.end_sidewalk_spot(map)?) @@ -610,11 +616,11 @@ impl PersonSpec { // Once off-map, re-enter via any border node. let end_bldg = match pair.0.trip.end(map) { TripEndpoint::Bldg(b) => Some(b), - TripEndpoint::Border(_) => None, + TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => None, }; let start_bldg = match pair.1.trip.start(map) { TripEndpoint::Bldg(b) => Some(b), - TripEndpoint::Border(_) => None, + TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => None, }; if end_bldg != start_bldg { diff --git a/sim/src/trips.rs b/sim/src/trips.rs index f1872a130c..339c6d5e45 100644 --- a/sim/src/trips.rs +++ b/sim/src/trips.rs @@ -150,7 +150,7 @@ impl TripManager { .push(Event::PersonEntersBuilding(trip.person, b)); PersonState::Inside(b) } - TripEndpoint::Border(_) => PersonState::OffMap, + TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => PersonState::OffMap, }; } if let Some(t) = person.trips.last() { @@ -715,20 +715,20 @@ impl TripManager { if let PersonState::Inside(b) = self.people[person.0].state { self.events.push(Event::PersonLeavesBuilding(person, b)); } - match trip.info.end { + // Warp to the destination + self.people[person.0].state = match trip.info.end { TripEndpoint::Bldg(b) => { self.events.push(Event::PersonEntersBuilding(person, b)); + PersonState::Inside(b) } TripEndpoint::Border(i) => { self.events.push(Event::PersonLeavesMap(person, None, i)); + PersonState::OffMap } - } - - // Warp to the destination - self.people[person.0].state = match trip.info.end { - TripEndpoint::Bldg(b) => PersonState::Inside(b), - TripEndpoint::Border(_) => PersonState::OffMap, + // Can't end trips here yet + TripEndpoint::SuddenlyAppear(_) => unreachable!(), }; + // Don't forget the car! if let Some(vehicle) = abandoned_vehicle { if vehicle.vehicle_type == VehicleType::Car { @@ -1515,10 +1515,13 @@ impl TripMode { } } +/// Specifies where a trip begins or ends. #[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)] pub enum TripEndpoint { Bldg(BuildingID), Border(IntersectionID), + /// Used for interactive spawning, tests, etc. For now, only valid as a trip's start. + SuddenlyAppear(Position), } impl TripEndpoint { @@ -1576,6 +1579,7 @@ fn pos(endpt: TripEndpoint, mode: TripMode, from: bool, map: &Map) -> Option Some(pos), } } @@ -1643,6 +1647,7 @@ impl TripEndpoint { match self { TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)), TripEndpoint::Border(i) => SidewalkSpot::start_at_border(*i, map), + TripEndpoint::SuddenlyAppear(pos) => Some(SidewalkSpot::suddenly_appear(*pos, map)), } } @@ -1650,6 +1655,7 @@ impl TripEndpoint { match self { TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)), TripEndpoint::Border(i) => SidewalkSpot::end_at_border(*i, map), + TripEndpoint::SuddenlyAppear(_) => unreachable!(), } } @@ -1663,6 +1669,7 @@ impl TripEndpoint { TripEndpoint::Border(i) => { DrivingGoal::end_at_border(map.get_i(*i).some_incoming_road(map)?, constraints, map) } + TripEndpoint::SuddenlyAppear(_) => unreachable!(), } } }