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

This commit is contained in:
Dustin Carlino 2020-11-17 10:50:42 -08:00
parent 5ea3c2ba6f
commit 2abeebc55e
9 changed files with 61 additions and 22 deletions

View File

@ -383,6 +383,7 @@ pub fn schedule(
} }
} }
TripEndpoint::Border(_) => "off-map".to_string(), TripEndpoint::Border(_) => "off-map".to_string(),
TripEndpoint::SuddenlyAppear(_) => "suddenly appear".to_string(),
}; };
rows.push( rows.push(
Text::from(Line(format!( Text::from(Line(format!(
@ -412,6 +413,7 @@ pub fn schedule(
} }
} }
TripEndpoint::Border(_) => "off-map".to_string(), TripEndpoint::Border(_) => "off-map".to_string(),
TripEndpoint::SuddenlyAppear(_) => "suddenly disappear".to_string(),
}; };
rows.push( rows.push(
Text::from(Line(format!( Text::from(Line(format!(

View File

@ -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)
),
),
} }
} }

View File

@ -85,10 +85,12 @@ impl CommuterPatterns {
let block1 = match trip.start { let block1 = match trip.start {
TripEndpoint::Bldg(b) => bldg_to_block[&b], TripEndpoint::Bldg(b) => bldg_to_block[&b],
TripEndpoint::Border(i) => border_to_block[&i], TripEndpoint::Border(i) => border_to_block[&i],
TripEndpoint::SuddenlyAppear(_) => continue,
}; };
let block2 = match trip.end { let block2 = match trip.end {
TripEndpoint::Bldg(b) => bldg_to_block[&b], TripEndpoint::Bldg(b) => bldg_to_block[&b],
TripEndpoint::Border(i) => border_to_block[&i], TripEndpoint::Border(i) => border_to_block[&i],
TripEndpoint::SuddenlyAppear(_) => continue,
}; };
// Totally ignore trips within the same block // Totally ignore trips within the same block
if block1 != block2 { if block1 != block2 {
@ -151,6 +153,7 @@ impl CommuterPatterns {
count.inc(self.border_to_block[&i]); count.inc(self.border_to_block[&i]);
} }
} }
TripEndpoint::SuddenlyAppear(_) => {}
} }
} else { } else {
match trip.start { match trip.start {
@ -162,6 +165,7 @@ impl CommuterPatterns {
count.inc(self.border_to_block[&i]); count.inc(self.border_to_block[&i]);
} }
} }
TripEndpoint::SuddenlyAppear(_) => {}
} }
} }
} }

View File

@ -169,6 +169,7 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch {
.centered_on(match trip.start { .centered_on(match trip.start {
TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center, TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center,
TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(), TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(),
TripEndpoint::SuddenlyAppear(pos) => pos.pt(&app.primary.map),
}), }),
); );
batch.append( batch.append(
@ -182,6 +183,7 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch {
.centered_on(match trip.end { .centered_on(match trip.end {
TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center, TripEndpoint::Bldg(b) => app.primary.map.get_b(b).label_center,
TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(), TripEndpoint::Border(i) => app.primary.map.get_i(i).polygon.center(),
TripEndpoint::SuddenlyAppear(pos) => pos.pt(&app.primary.map),
}), }),
); );

View File

@ -433,6 +433,7 @@ impl State<App> for AgentSpawner {
match endpt { match endpt {
TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(), TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(),
TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(), TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(),
TripEndpoint::SuddenlyAppear(_) => unreachable!(),
}, },
); );
} }
@ -442,6 +443,7 @@ impl State<App> for AgentSpawner {
match endpt { match endpt {
TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(), TripEndpoint::Border(i) => app.primary.map.get_i(*i).polygon.clone(),
TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(), TripEndpoint::Bldg(b) => app.primary.map.get_b(*b).polygon.clone(),
TripEndpoint::SuddenlyAppear(_) => unreachable!(),
}, },
); );
if let Some(p) = poly { if let Some(p) = poly {
@ -513,8 +515,14 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
now, now,
TripSpec::JustWalking { TripSpec::JustWalking {
start: SidewalkSpot::suddenly_appear( start: SidewalkSpot::suddenly_appear(
lane.id, Position::new(
Scenario::rand_dist(&mut rng, 0.1 * lane.length(), 0.9 * lane.length()), lane.id,
Scenario::rand_dist(
&mut rng,
0.1 * lane.length(),
0.9 * lane.length(),
),
),
map, map,
), ),
goal: SidewalkSpot::building( goal: SidewalkSpot::building(

View File

@ -523,12 +523,12 @@ impl SidewalkSpot {
}) })
} }
pub fn suddenly_appear(l: LaneID, dist: Distance, map: &Map) -> SidewalkSpot { pub fn suddenly_appear(pos: Position, map: &Map) -> SidewalkSpot {
let lane = map.get_l(l); let lane = map.get_l(pos.lane());
assert!(lane.is_walkable()); assert!(lane.is_walkable());
assert!(dist <= lane.length()); assert!(pos.dist_along() <= lane.length());
SidewalkSpot { SidewalkSpot {
sidewalk_pos: Position::new(l, dist), sidewalk_pos: pos,
connection: SidewalkPOI::SuddenlyAppear, connection: SidewalkPOI::SuddenlyAppear,
} }
} }

View File

@ -159,6 +159,8 @@ impl ScenarioGenerator {
(TripEndpoint::Border(_), TripEndpoint::Border(_)) => { (TripEndpoint::Border(_), TripEndpoint::Border(_)) => {
num_trips_passthru += 1; num_trips_passthru += 1;
} }
(TripEndpoint::SuddenlyAppear(_), _) => unreachable!(),
(_, TripEndpoint::SuddenlyAppear(_)) => unreachable!(),
}; };
(home, work, fork_rng(rng)) (home, work, fork_rng(rng))

View File

@ -511,9 +511,7 @@ impl SpawnTrip {
pub fn start(&self, map: &Map) -> TripEndpoint { pub fn start(&self, map: &Map) -> TripEndpoint {
match self { match self {
SpawnTrip::VehicleAppearing { ref start, .. } => { SpawnTrip::VehicleAppearing { start, .. } => TripEndpoint::SuddenlyAppear(*start),
TripEndpoint::Border(map.get_l(start.lane()).src_i)
}
SpawnTrip::FromBorder { dr, .. } => TripEndpoint::Border(dr.src_i(map)), SpawnTrip::FromBorder { dr, .. } => TripEndpoint::Border(dr.src_i(map)),
SpawnTrip::UsingParkedCar(b, _) => TripEndpoint::Bldg(*b), SpawnTrip::UsingParkedCar(b, _) => TripEndpoint::Bldg(*b),
SpawnTrip::UsingBike(b, _) => TripEndpoint::Bldg(*b), SpawnTrip::UsingBike(b, _) => TripEndpoint::Bldg(*b),
@ -521,9 +519,7 @@ impl SpawnTrip {
match spot.connection { match spot.connection {
SidewalkPOI::Building(b) => TripEndpoint::Bldg(b), SidewalkPOI::Building(b) => TripEndpoint::Bldg(b),
SidewalkPOI::Border(i) => TripEndpoint::Border(i), SidewalkPOI::Border(i) => TripEndpoint::Border(i),
SidewalkPOI::SuddenlyAppear => { SidewalkPOI::SuddenlyAppear => TripEndpoint::SuddenlyAppear(spot.sidewalk_pos),
TripEndpoint::Border(map.get_l(spot.sidewalk_pos.lane()).src_i)
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -565,6 +561,11 @@ impl SpawnTrip {
goal: to.driving_goal(PathConstraints::Car, map)?, goal: to.driving_goal(PathConstraints::Car, map)?,
is_bike: false, is_bike: false,
}, },
TripEndpoint::SuddenlyAppear(start) => SpawnTrip::VehicleAppearing {
start,
goal: to.driving_goal(PathConstraints::Bike, map)?,
is_bike: false,
},
}, },
TripMode::Bike => match from { TripMode::Bike => match from {
TripEndpoint::Bldg(b) => { TripEndpoint::Bldg(b) => {
@ -575,6 +576,11 @@ impl SpawnTrip {
goal: to.driving_goal(PathConstraints::Bike, map)?, goal: to.driving_goal(PathConstraints::Bike, map)?,
is_bike: true, is_bike: true,
}, },
TripEndpoint::SuddenlyAppear(start) => SpawnTrip::VehicleAppearing {
start,
goal: to.driving_goal(PathConstraints::Bike, map)?,
is_bike: true,
},
}, },
TripMode::Walk => { TripMode::Walk => {
SpawnTrip::JustWalking(from.start_sidewalk_spot(map)?, to.end_sidewalk_spot(map)?) 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. // Once off-map, re-enter via any border node.
let end_bldg = match pair.0.trip.end(map) { let end_bldg = match pair.0.trip.end(map) {
TripEndpoint::Bldg(b) => Some(b), TripEndpoint::Bldg(b) => Some(b),
TripEndpoint::Border(_) => None, TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => None,
}; };
let start_bldg = match pair.1.trip.start(map) { let start_bldg = match pair.1.trip.start(map) {
TripEndpoint::Bldg(b) => Some(b), TripEndpoint::Bldg(b) => Some(b),
TripEndpoint::Border(_) => None, TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => None,
}; };
if end_bldg != start_bldg { if end_bldg != start_bldg {

View File

@ -150,7 +150,7 @@ impl TripManager {
.push(Event::PersonEntersBuilding(trip.person, b)); .push(Event::PersonEntersBuilding(trip.person, b));
PersonState::Inside(b) PersonState::Inside(b)
} }
TripEndpoint::Border(_) => PersonState::OffMap, TripEndpoint::Border(_) | TripEndpoint::SuddenlyAppear(_) => PersonState::OffMap,
}; };
} }
if let Some(t) = person.trips.last() { if let Some(t) = person.trips.last() {
@ -715,20 +715,20 @@ impl TripManager {
if let PersonState::Inside(b) = self.people[person.0].state { if let PersonState::Inside(b) = self.people[person.0].state {
self.events.push(Event::PersonLeavesBuilding(person, b)); 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) => { TripEndpoint::Bldg(b) => {
self.events.push(Event::PersonEntersBuilding(person, b)); self.events.push(Event::PersonEntersBuilding(person, b));
PersonState::Inside(b)
} }
TripEndpoint::Border(i) => { TripEndpoint::Border(i) => {
self.events.push(Event::PersonLeavesMap(person, None, i)); self.events.push(Event::PersonLeavesMap(person, None, i));
PersonState::OffMap
} }
} // Can't end trips here yet
TripEndpoint::SuddenlyAppear(_) => unreachable!(),
// Warp to the destination
self.people[person.0].state = match trip.info.end {
TripEndpoint::Bldg(b) => PersonState::Inside(b),
TripEndpoint::Border(_) => PersonState::OffMap,
}; };
// Don't forget the car! // Don't forget the car!
if let Some(vehicle) = abandoned_vehicle { if let Some(vehicle) = abandoned_vehicle {
if vehicle.vehicle_type == VehicleType::Car { 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)] #[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
pub enum TripEndpoint { pub enum TripEndpoint {
Bldg(BuildingID), Bldg(BuildingID),
Border(IntersectionID), Border(IntersectionID),
/// Used for interactive spawning, tests, etc. For now, only valid as a trip's start.
SuddenlyAppear(Position),
} }
impl TripEndpoint { impl TripEndpoint {
@ -1576,6 +1579,7 @@ fn pos(endpt: TripEndpoint, mode: TripMode, from: bool, map: &Map) -> Option<Pos
.map(|l| Position::start(*l)) .map(|l| Position::start(*l))
}), }),
}, },
TripEndpoint::SuddenlyAppear(pos) => Some(pos),
} }
} }
@ -1643,6 +1647,7 @@ impl TripEndpoint {
match self { match self {
TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)), TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)),
TripEndpoint::Border(i) => SidewalkSpot::start_at_border(*i, 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 { match self {
TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)), TripEndpoint::Bldg(b) => Some(SidewalkSpot::building(*b, map)),
TripEndpoint::Border(i) => SidewalkSpot::end_at_border(*i, map), TripEndpoint::Border(i) => SidewalkSpot::end_at_border(*i, map),
TripEndpoint::SuddenlyAppear(_) => unreachable!(),
} }
} }
@ -1663,6 +1669,7 @@ impl TripEndpoint {
TripEndpoint::Border(i) => { TripEndpoint::Border(i) => {
DrivingGoal::end_at_border(map.get_i(*i).some_incoming_road(map)?, constraints, map) DrivingGoal::end_at_border(map.get_i(*i).some_incoming_road(map)?, constraints, map)
} }
TripEndpoint::SuddenlyAppear(_) => unreachable!(),
} }
} }
} }