mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
refactoring some trip spawning stuff from importer, using it in the new agent spawner too
This commit is contained in:
parent
ac752fccfe
commit
aceadef79f
@ -1,7 +1,7 @@
|
|||||||
use crate::app::{App, ShowEverything};
|
use crate::app::{App, ShowEverything};
|
||||||
use crate::common::{CityPicker, CommonState};
|
use crate::common::{CityPicker, CommonState};
|
||||||
use crate::edit::EditMode;
|
use crate::edit::EditMode;
|
||||||
use crate::game::{msg, State, Transition, WizardState};
|
use crate::game::{State, Transition, WizardState};
|
||||||
use crate::helpers::{nice_map_name, ID};
|
use crate::helpers::{nice_map_name, ID};
|
||||||
use crate::sandbox::gameplay::{GameplayMode, GameplayState};
|
use crate::sandbox::gameplay::{GameplayMode, GameplayState};
|
||||||
use crate::sandbox::SandboxControls;
|
use crate::sandbox::SandboxControls;
|
||||||
@ -15,8 +15,10 @@ use geom::{Distance, Duration, Polygon};
|
|||||||
use map_model::{
|
use map_model::{
|
||||||
IntersectionID, Map, PathConstraints, PathRequest, Position, NORMAL_LANE_THICKNESS,
|
IntersectionID, Map, PathConstraints, PathRequest, Position, NORMAL_LANE_THICKNESS,
|
||||||
};
|
};
|
||||||
use rand_xorshift::XorShiftRng;
|
use sim::{
|
||||||
use sim::{DontDrawAgents, SidewalkSpot, Sim, TripEndpoint, TripMode, TripSpawner, TripSpec};
|
DontDrawAgents, IndividTrip, PersonID, PersonSpec, Scenario, SidewalkSpot, SpawnTrip,
|
||||||
|
TripEndpoint, TripMode,
|
||||||
|
};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
// TODO Maybe remember what things were spawned, offer to replay this later
|
// TODO Maybe remember what things were spawned, offer to replay this later
|
||||||
@ -304,27 +306,31 @@ impl State for AgentSpawner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.goal.is_some() && app.per_obj.left_click(ctx, "end here") {
|
if self.goal.is_some() && app.per_obj.left_click(ctx, "end here") {
|
||||||
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
|
||||||
let map = &app.primary.map;
|
let map = &app.primary.map;
|
||||||
let sim = &mut app.primary.sim;
|
let mut scenario = Scenario::empty(map, "one-shot");
|
||||||
let mut spawner = sim.make_spawner();
|
scenario.people.push(PersonSpec {
|
||||||
let err = schedule_trip(
|
id: PersonID(app.primary.sim.get_all_people().len()),
|
||||||
self.source.take().unwrap(),
|
orig_id: None,
|
||||||
self.goal.take().unwrap().0,
|
trips: vec![IndividTrip {
|
||||||
self.composite.dropdown_value("mode"),
|
depart: app.primary.sim.time(),
|
||||||
|
trip: SpawnTrip::new(
|
||||||
|
self.source.take().unwrap(),
|
||||||
|
self.goal.take().unwrap().0,
|
||||||
|
self.composite.dropdown_value("mode"),
|
||||||
|
map,
|
||||||
|
),
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
||||||
|
scenario.instantiate(
|
||||||
|
&mut app.primary.sim,
|
||||||
map,
|
map,
|
||||||
sim,
|
|
||||||
&mut spawner,
|
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
&mut Timer::new("spawn trip"),
|
||||||
);
|
);
|
||||||
sim.flush_spawner(spawner, map, &mut Timer::new("spawn trip"));
|
app.primary.sim.normal_step(map, SMALL_DT);
|
||||||
sim.normal_step(map, SMALL_DT);
|
|
||||||
app.recalculate_current_selection(ctx);
|
app.recalculate_current_selection(ctx);
|
||||||
if let Some(e) = err {
|
return Transition::Pop;
|
||||||
return Transition::Replace(msg("Spawning error", vec![e]));
|
|
||||||
} else {
|
|
||||||
return Transition::Pop;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,17 +404,3 @@ fn pos(endpt: TripEndpoint, mode: TripMode, from: bool, map: &Map) -> Option<Pos
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns optional error message
|
|
||||||
fn schedule_trip(
|
|
||||||
from: TripEndpoint,
|
|
||||||
to: TripEndpoint,
|
|
||||||
mode: TripMode,
|
|
||||||
map: &Map,
|
|
||||||
sim: &mut Sim,
|
|
||||||
spawner: &mut TripSpawner,
|
|
||||||
rng: &mut XorShiftRng,
|
|
||||||
) -> Option<String> {
|
|
||||||
// TODO
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
@ -3,223 +3,135 @@ use abstutil::{prettyprint_usize, MultiMap, Timer};
|
|||||||
use geom::LonLat;
|
use geom::LonLat;
|
||||||
use map_model::{BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep};
|
use map_model::{BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep};
|
||||||
use sim::{
|
use sim::{
|
||||||
DrivingGoal, IndividTrip, OffMapLocation, OrigPersonID, PersonID, PersonSpec, Scenario,
|
IndividTrip, OffMapLocation, OrigPersonID, PersonID, PersonSpec, Scenario, SpawnTrip,
|
||||||
SidewalkSpot, SpawnTrip, TripMode,
|
TripEndpoint, TripMode,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Trip {
|
struct Trip {
|
||||||
from: TripEndpt,
|
from: TripEndpoint,
|
||||||
to: TripEndpt,
|
to: TripEndpoint,
|
||||||
orig: OrigTrip,
|
orig: OrigTrip,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
// TODO Saying this function exploded in complexity is like saying I have coffee occasionally.
|
||||||
enum TripEndpt {
|
fn endpoints(
|
||||||
Building(BuildingID),
|
from: &Endpoint,
|
||||||
Border(IntersectionID, OffMapLocation),
|
to: &Endpoint,
|
||||||
}
|
map: &Map,
|
||||||
|
osm_id_to_bldg: &HashMap<i64, BuildingID>,
|
||||||
impl Trip {
|
(in_borders, out_borders): (
|
||||||
fn to_spawn_trip(&self, map: &Map) -> SpawnTrip {
|
&Vec<(IntersectionID, LonLat)>,
|
||||||
match self.orig.mode {
|
&Vec<(IntersectionID, LonLat)>,
|
||||||
TripMode::Drive => match self.from {
|
),
|
||||||
TripEndpt::Border(i, ref origin) => SpawnTrip::FromBorder {
|
constraints: PathConstraints,
|
||||||
dr: map.get_i(i).some_outgoing_road(map),
|
maybe_huge_map: Option<&(&Map, HashMap<i64, BuildingID>)>,
|
||||||
goal: self.to.driving_goal(PathConstraints::Car, map),
|
) -> Option<(TripEndpoint, TripEndpoint)> {
|
||||||
is_bike: false,
|
let from_bldg = from
|
||||||
origin: Some(origin.clone()),
|
.osm_building
|
||||||
},
|
.and_then(|id| osm_id_to_bldg.get(&id))
|
||||||
TripEndpt::Building(b) => {
|
.cloned();
|
||||||
SpawnTrip::UsingParkedCar(b, self.to.driving_goal(PathConstraints::Car, map))
|
let to_bldg = to
|
||||||
}
|
.osm_building
|
||||||
},
|
.and_then(|id| osm_id_to_bldg.get(&id))
|
||||||
TripMode::Bike => match self.from {
|
.cloned();
|
||||||
TripEndpt::Building(b) => SpawnTrip::UsingBike(
|
let border_endpt = match (from_bldg, to_bldg) {
|
||||||
SidewalkSpot::building(b, map),
|
(Some(b1), Some(b2)) => {
|
||||||
self.to.driving_goal(PathConstraints::Bike, map),
|
return Some((TripEndpoint::Bldg(b1), TripEndpoint::Bldg(b2)));
|
||||||
),
|
|
||||||
TripEndpt::Border(i, ref origin) => SpawnTrip::FromBorder {
|
|
||||||
dr: map.get_i(i).some_outgoing_road(map),
|
|
||||||
goal: self.to.driving_goal(PathConstraints::Bike, map),
|
|
||||||
is_bike: true,
|
|
||||||
origin: Some(origin.clone()),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
TripMode::Walk => SpawnTrip::JustWalking(
|
|
||||||
self.from.start_sidewalk_spot(map),
|
|
||||||
self.to.end_sidewalk_spot(map),
|
|
||||||
),
|
|
||||||
TripMode::Transit => {
|
|
||||||
let start = self.from.start_sidewalk_spot(map);
|
|
||||||
let goal = self.to.end_sidewalk_spot(map);
|
|
||||||
if let Some((stop1, stop2, route)) =
|
|
||||||
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
|
||||||
{
|
|
||||||
SpawnTrip::UsingTransit(start, goal, route, stop1, stop2)
|
|
||||||
} else {
|
|
||||||
//timer.warn(format!("{:?} not actually using transit, because pathfinding
|
|
||||||
// didn't find any useful route", trip));
|
|
||||||
SpawnTrip::JustWalking(start, goal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
(Some(_), None) => to,
|
||||||
}
|
(None, Some(_)) => from,
|
||||||
|
(None, None) => {
|
||||||
|
// TODO Detect and handle pass-through trips
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let usable_borders = if from_bldg.is_some() {
|
||||||
|
out_borders
|
||||||
|
} else {
|
||||||
|
in_borders
|
||||||
|
};
|
||||||
|
|
||||||
impl TripEndpt {
|
// The trip begins or ends at a border.
|
||||||
// TODO Saying this function exploded in complexity is like saying I have coffee occasionally.
|
// TODO It'd be nice to fix depart_at, trip_time, and trip_dist. Assume constant speed
|
||||||
fn new(
|
// through the trip. But when I last tried this, the distance was way off. :\
|
||||||
from: &Endpoint,
|
|
||||||
to: &Endpoint,
|
// If this isn't huge_seattle, use the large map to find the real path somebody might take,
|
||||||
map: &Map,
|
// then try to match that to a border in the smaller map.
|
||||||
osm_id_to_bldg: &HashMap<i64, BuildingID>,
|
let maybe_other_border = if let Some((huge_map, huge_osm_id_to_bldg)) = maybe_huge_map {
|
||||||
(in_borders, out_borders): (
|
let maybe_b1 = from
|
||||||
&Vec<(IntersectionID, LonLat)>,
|
|
||||||
&Vec<(IntersectionID, LonLat)>,
|
|
||||||
),
|
|
||||||
constraints: PathConstraints,
|
|
||||||
maybe_huge_map: Option<&(&Map, HashMap<i64, BuildingID>)>,
|
|
||||||
) -> Option<(TripEndpt, TripEndpt)> {
|
|
||||||
let from_bldg = from
|
|
||||||
.osm_building
|
.osm_building
|
||||||
.and_then(|id| osm_id_to_bldg.get(&id))
|
.and_then(|id| huge_osm_id_to_bldg.get(&id))
|
||||||
.cloned();
|
.cloned();
|
||||||
let to_bldg = to
|
let maybe_b2 = to
|
||||||
.osm_building
|
.osm_building
|
||||||
.and_then(|id| osm_id_to_bldg.get(&id))
|
.and_then(|id| huge_osm_id_to_bldg.get(&id))
|
||||||
.cloned();
|
.cloned();
|
||||||
let border_endpt = match (from_bldg, to_bldg) {
|
if let (Some(b1), Some(b2)) = (maybe_b1, maybe_b2) {
|
||||||
(Some(b1), Some(b2)) => {
|
// TODO Super rough...
|
||||||
return Some((TripEndpt::Building(b1), TripEndpt::Building(b2)));
|
let start = if constraints == PathConstraints::Pedestrian {
|
||||||
}
|
Some(huge_map.get_b(b1).front_path.sidewalk)
|
||||||
(Some(_), None) => to,
|
} else {
|
||||||
(None, Some(_)) => from,
|
huge_map.get_b(b1).parking.as_ref().map(|p| p.driving_pos)
|
||||||
(None, None) => {
|
};
|
||||||
// TODO Detect and handle pass-through trips
|
let end = if constraints == PathConstraints::Pedestrian {
|
||||||
return None;
|
Some(huge_map.get_b(b2).front_path.sidewalk)
|
||||||
}
|
} else {
|
||||||
};
|
huge_map.get_b(b2).parking.as_ref().map(|p| p.driving_pos)
|
||||||
let usable_borders = if from_bldg.is_some() {
|
};
|
||||||
out_borders
|
if let Some(path) = start.and_then(|start| {
|
||||||
} else {
|
end.and_then(|end| {
|
||||||
in_borders
|
huge_map.pathfind(PathRequest {
|
||||||
};
|
start,
|
||||||
|
end,
|
||||||
// The trip begins or ends at a border.
|
constraints,
|
||||||
// TODO It'd be nice to fix depart_at, trip_time, and trip_dist. Assume constant speed
|
|
||||||
// through the trip. But when I last tried this, the distance was way off. :\
|
|
||||||
|
|
||||||
// If this isn't huge_seattle, use the large map to find the real path somebody might take,
|
|
||||||
// then try to match that to a border in the smaller map.
|
|
||||||
let maybe_other_border = if let Some((huge_map, huge_osm_id_to_bldg)) = maybe_huge_map {
|
|
||||||
let maybe_b1 = from
|
|
||||||
.osm_building
|
|
||||||
.and_then(|id| huge_osm_id_to_bldg.get(&id))
|
|
||||||
.cloned();
|
|
||||||
let maybe_b2 = to
|
|
||||||
.osm_building
|
|
||||||
.and_then(|id| huge_osm_id_to_bldg.get(&id))
|
|
||||||
.cloned();
|
|
||||||
if let (Some(b1), Some(b2)) = (maybe_b1, maybe_b2) {
|
|
||||||
// TODO Super rough...
|
|
||||||
let start = if constraints == PathConstraints::Pedestrian {
|
|
||||||
Some(huge_map.get_b(b1).front_path.sidewalk)
|
|
||||||
} else {
|
|
||||||
huge_map.get_b(b1).parking.as_ref().map(|p| p.driving_pos)
|
|
||||||
};
|
|
||||||
let end = if constraints == PathConstraints::Pedestrian {
|
|
||||||
Some(huge_map.get_b(b2).front_path.sidewalk)
|
|
||||||
} else {
|
|
||||||
huge_map.get_b(b2).parking.as_ref().map(|p| p.driving_pos)
|
|
||||||
};
|
|
||||||
if let Some(path) = start.and_then(|start| {
|
|
||||||
end.and_then(|end| {
|
|
||||||
huge_map.pathfind(PathRequest {
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
constraints,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}) {
|
})
|
||||||
// Do any of the usable borders match the path?
|
}) {
|
||||||
// TODO Calculate this once
|
// Do any of the usable borders match the path?
|
||||||
let mut node_id_to_border = HashMap::new();
|
// TODO Calculate this once
|
||||||
for (i, _) in usable_borders {
|
let mut node_id_to_border = HashMap::new();
|
||||||
node_id_to_border.insert(map.get_i(*i).orig_id, *i);
|
for (i, _) in usable_borders {
|
||||||
}
|
node_id_to_border.insert(map.get_i(*i).orig_id, *i);
|
||||||
let mut found_border = None;
|
}
|
||||||
for step in path.get_steps() {
|
let mut found_border = None;
|
||||||
if let PathStep::Turn(t) = step {
|
for step in path.get_steps() {
|
||||||
if let Some(i) =
|
if let PathStep::Turn(t) = step {
|
||||||
node_id_to_border.get(&huge_map.get_i(t.parent).orig_id)
|
if let Some(i) = node_id_to_border.get(&huge_map.get_i(t.parent).orig_id) {
|
||||||
{
|
found_border = Some(*i);
|
||||||
found_border = Some(*i);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
found_border
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
found_border
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
|
||||||
// Fallback to finding the nearest border with straight-line distance
|
|
||||||
let border_i = maybe_other_border.or_else(|| {
|
|
||||||
usable_borders
|
|
||||||
.iter()
|
|
||||||
.min_by_key(|(_, pt)| pt.fast_dist(border_endpt.pos))
|
|
||||||
.map(|(id, _)| *id)
|
|
||||||
})?;
|
|
||||||
let border = TripEndpt::Border(
|
|
||||||
border_i,
|
|
||||||
OffMapLocation {
|
|
||||||
gps: border_endpt.pos,
|
|
||||||
parcel_id: border_endpt.parcel_id,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if let Some(b) = from_bldg {
|
|
||||||
Some((TripEndpt::Building(b), border))
|
|
||||||
} else {
|
|
||||||
Some((border, TripEndpt::Building(to_bldg.unwrap())))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn start_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
|
|
||||||
match self {
|
|
||||||
TripEndpt::Building(b) => SidewalkSpot::building(*b, map),
|
|
||||||
TripEndpt::Border(i, origin) => {
|
|
||||||
SidewalkSpot::start_at_border(*i, Some(origin.clone()), map).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
|
|
||||||
match self {
|
|
||||||
TripEndpt::Building(b) => SidewalkSpot::building(*b, map),
|
|
||||||
TripEndpt::Border(i, destination) => {
|
|
||||||
SidewalkSpot::end_at_border(*i, Some(destination.clone()), map).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn driving_goal(&self, constraints: PathConstraints, map: &Map) -> DrivingGoal {
|
|
||||||
match self {
|
|
||||||
TripEndpt::Building(b) => DrivingGoal::ParkNear(*b),
|
|
||||||
TripEndpt::Border(i, destination) => DrivingGoal::end_at_border(
|
|
||||||
map.get_i(*i).some_incoming_road(map),
|
|
||||||
constraints,
|
|
||||||
Some(destination.clone()),
|
|
||||||
map,
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
// Fallback to finding the nearest border with straight-line distance
|
||||||
|
let border_i = maybe_other_border.or_else(|| {
|
||||||
|
usable_borders
|
||||||
|
.iter()
|
||||||
|
.min_by_key(|(_, pt)| pt.fast_dist(border_endpt.pos))
|
||||||
|
.map(|(id, _)| *id)
|
||||||
|
})?;
|
||||||
|
let border = TripEndpoint::Border(
|
||||||
|
border_i,
|
||||||
|
Some(OffMapLocation {
|
||||||
|
gps: border_endpt.pos,
|
||||||
|
parcel_id: border_endpt.parcel_id,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if let Some(b) = from_bldg {
|
||||||
|
Some((TripEndpoint::Bldg(b), border))
|
||||||
|
} else {
|
||||||
|
Some((border, TripEndpoint::Bldg(to_bldg.unwrap())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +198,7 @@ fn clip_trips(map: &Map, popdat: &PopDat, huge_map: &Map, timer: &mut Timer) ->
|
|||||||
let total_trips = popdat.trips.len();
|
let total_trips = popdat.trips.len();
|
||||||
let maybe_results: Vec<Option<Trip>> =
|
let maybe_results: Vec<Option<Trip>> =
|
||||||
timer.parallelize("clip trips", popdat.trips.iter().collect(), |orig| {
|
timer.parallelize("clip trips", popdat.trips.iter().collect(), |orig| {
|
||||||
let (from, to) = TripEndpt::new(
|
let (from, to) = endpoints(
|
||||||
&orig.from,
|
&orig.from,
|
||||||
&orig.to,
|
&orig.to,
|
||||||
map,
|
map,
|
||||||
@ -338,7 +250,7 @@ pub fn make_weekday_scenario(
|
|||||||
for (trip, depart, person, seq) in
|
for (trip, depart, person, seq) in
|
||||||
timer.parallelize("turn Soundcast trips into SpawnTrips", trips, |trip| {
|
timer.parallelize("turn Soundcast trips into SpawnTrips", trips, |trip| {
|
||||||
(
|
(
|
||||||
trip.to_spawn_trip(map),
|
SpawnTrip::new(trip.from, trip.to, trip.orig.mode, map),
|
||||||
trip.orig.depart_at,
|
trip.orig.depart_at,
|
||||||
trip.orig.person,
|
trip.orig.person,
|
||||||
trip.orig.seq,
|
trip.orig.seq,
|
||||||
|
@ -471,6 +471,50 @@ impl SpawnTrip {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new(from: TripEndpoint, to: TripEndpoint, mode: TripMode, map: &Map) -> SpawnTrip {
|
||||||
|
match mode {
|
||||||
|
TripMode::Drive => match from {
|
||||||
|
TripEndpoint::Bldg(b) => {
|
||||||
|
SpawnTrip::UsingParkedCar(b, to.driving_goal(PathConstraints::Car, map))
|
||||||
|
}
|
||||||
|
TripEndpoint::Border(i, ref origin) => SpawnTrip::FromBorder {
|
||||||
|
dr: map.get_i(i).some_outgoing_road(map),
|
||||||
|
goal: to.driving_goal(PathConstraints::Car, map),
|
||||||
|
is_bike: false,
|
||||||
|
origin: origin.clone(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TripMode::Bike => match from {
|
||||||
|
TripEndpoint::Bldg(b) => SpawnTrip::UsingBike(
|
||||||
|
SidewalkSpot::building(b, map),
|
||||||
|
to.driving_goal(PathConstraints::Bike, map),
|
||||||
|
),
|
||||||
|
TripEndpoint::Border(i, ref origin) => SpawnTrip::FromBorder {
|
||||||
|
dr: map.get_i(i).some_outgoing_road(map),
|
||||||
|
goal: to.driving_goal(PathConstraints::Bike, map),
|
||||||
|
is_bike: true,
|
||||||
|
origin: origin.clone(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TripMode::Walk => {
|
||||||
|
SpawnTrip::JustWalking(from.start_sidewalk_spot(map), to.end_sidewalk_spot(map))
|
||||||
|
}
|
||||||
|
TripMode::Transit => {
|
||||||
|
let start = from.start_sidewalk_spot(map);
|
||||||
|
let goal = to.end_sidewalk_spot(map);
|
||||||
|
if let Some((stop1, stop2, route)) =
|
||||||
|
map.should_use_transit(start.sidewalk_pos, goal.sidewalk_pos)
|
||||||
|
{
|
||||||
|
SpawnTrip::UsingTransit(start, goal, route, stop1, stop2)
|
||||||
|
} else {
|
||||||
|
//timer.warn(format!("{:?} not actually using transit, because pathfinding
|
||||||
|
// didn't find any useful route", trip));
|
||||||
|
SpawnTrip::JustWalking(start, goal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PersonSpec {
|
impl PersonSpec {
|
||||||
|
@ -1415,3 +1415,36 @@ pub enum PersonState {
|
|||||||
Inside(BuildingID),
|
Inside(BuildingID),
|
||||||
OffMap,
|
OffMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TripEndpoint {
|
||||||
|
pub(crate) fn start_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
|
||||||
|
match self {
|
||||||
|
TripEndpoint::Bldg(b) => SidewalkSpot::building(*b, map),
|
||||||
|
TripEndpoint::Border(i, origin) => {
|
||||||
|
SidewalkSpot::start_at_border(*i, origin.clone(), map).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn end_sidewalk_spot(&self, map: &Map) -> SidewalkSpot {
|
||||||
|
match self {
|
||||||
|
TripEndpoint::Bldg(b) => SidewalkSpot::building(*b, map),
|
||||||
|
TripEndpoint::Border(i, destination) => {
|
||||||
|
SidewalkSpot::end_at_border(*i, destination.clone(), map).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn driving_goal(&self, constraints: PathConstraints, map: &Map) -> DrivingGoal {
|
||||||
|
match self {
|
||||||
|
TripEndpoint::Bldg(b) => DrivingGoal::ParkNear(*b),
|
||||||
|
TripEndpoint::Border(i, destination) => DrivingGoal::end_at_border(
|
||||||
|
map.get_i(*i).some_incoming_road(map),
|
||||||
|
constraints,
|
||||||
|
destination.clone(),
|
||||||
|
map,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user