mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Mechanical refactor: bus {stop, route} -> transit. #372
(Mostly renaming map_model code everywhere, not yet sim layer and above)
This commit is contained in:
parent
82471dd9d6
commit
6e11c386ac
@ -374,7 +374,7 @@ impl App {
|
||||
let mut roads: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut intersections: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut buildings: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut bus_stops: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut transit_stops: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut agents_on: Vec<Traversable> = Vec::new();
|
||||
|
||||
for id in draw_map.get_matching_objects(bounds) {
|
||||
@ -387,9 +387,9 @@ impl App {
|
||||
let road = draw_map.get_r(id);
|
||||
for lane in &road.lanes {
|
||||
agents_on.push(Traversable::Lane(lane.id));
|
||||
for bs in &map.get_l(lane.id).bus_stops {
|
||||
if show_objs.show(&ID::BusStop(*bs)) {
|
||||
bus_stops.push(draw_map.get_bs(*bs));
|
||||
for ts in &map.get_l(lane.id).transit_stops {
|
||||
if show_objs.show(&ID::TransitStop(*ts)) {
|
||||
transit_stops.push(draw_map.get_ts(*ts));
|
||||
}
|
||||
}
|
||||
lanes.push(lane);
|
||||
@ -409,7 +409,11 @@ impl App {
|
||||
agents_on.push(Traversable::Lane(map.get_pl(id).driving_pos.lane()));
|
||||
}
|
||||
|
||||
ID::Lane(_) | ID::BusStop(_) | ID::Car(_) | ID::Pedestrian(_) | ID::PedCrowd(_) => {
|
||||
ID::Lane(_)
|
||||
| ID::TransitStop(_)
|
||||
| ID::Car(_)
|
||||
| ID::Pedestrian(_)
|
||||
| ID::PedCrowd(_) => {
|
||||
panic!("{:?} shouldn't be in the quadtree", id)
|
||||
}
|
||||
}
|
||||
@ -423,7 +427,7 @@ impl App {
|
||||
borrows.extend(roads);
|
||||
borrows.extend(intersections);
|
||||
borrows.extend(buildings);
|
||||
borrows.extend(bus_stops);
|
||||
borrows.extend(transit_stops);
|
||||
|
||||
// Expand all of the Traversables into agents, populating the cache if needed.
|
||||
for on in &agents_on {
|
||||
@ -734,9 +738,9 @@ impl PerMap {
|
||||
ID::PedCrowd(ref members) => self
|
||||
.sim
|
||||
.canonical_pt_for_agent(AgentID::Pedestrian(members[0]), &self.map),
|
||||
ID::BusStop(id) => self
|
||||
ID::TransitStop(id) => self
|
||||
.map
|
||||
.maybe_get_bs(id)
|
||||
.maybe_get_ts(id)
|
||||
.map(|bs| bs.sidewalk_pos.pt(&self.map)),
|
||||
ID::Area(id) => self.map.maybe_get_a(id).map(|a| a.polygon.center()),
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ impl CommonState {
|
||||
if let Some(r) = app.primary.sim.bus_route_id(c) {
|
||||
osd.append_all(vec![
|
||||
Line(" serving "),
|
||||
Line(&map.get_br(r).full_name).underlined(),
|
||||
Line(&map.get_tr(r).long_name).underlined(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -197,12 +197,12 @@ impl CommonState {
|
||||
ID::PedCrowd(list) => {
|
||||
osd.append(Line(format!("a crowd of {} pedestrians", list.len())));
|
||||
}
|
||||
ID::BusStop(bs) => {
|
||||
ID::TransitStop(bs) => {
|
||||
if app.opts.dev {
|
||||
osd.append(Line(bs.to_string()).bold_body());
|
||||
} else {
|
||||
osd.append(Line("transit stop "));
|
||||
osd.append(Line(&map.get_bs(bs).name).underlined());
|
||||
osd.append(Line(&map.get_ts(bs).name).underlined());
|
||||
}
|
||||
osd.append(Line(" served by "));
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
||||
use geom::Pt2D;
|
||||
use map_gui::tools::{grey_out_map, PopupMsg};
|
||||
use map_gui::ID;
|
||||
use map_model::{AreaID, BuildingID, BusRouteID, IntersectionID, LaneID, ParkingLotID, RoadID};
|
||||
use map_model::{AreaID, BuildingID, IntersectionID, LaneID, ParkingLotID, RoadID, TransitRouteID};
|
||||
use sim::{PedestrianID, PersonID, TripID};
|
||||
use widgetry::{
|
||||
EventCtx, GfxCtx, Key, Line, Outcome, Panel, State, Text, TextBox, TextExt, Warper, Widget,
|
||||
@ -186,8 +186,8 @@ fn inner_warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Tra
|
||||
ID::Lane(r.lanes[0].id)
|
||||
}
|
||||
'R' => {
|
||||
let r = BusRouteID(idx);
|
||||
app.primary.map.maybe_get_br(r)?;
|
||||
let r = TransitRouteID(idx);
|
||||
app.primary.map.maybe_get_tr(r)?;
|
||||
return Some(Transition::Multi(vec![
|
||||
Transition::Pop,
|
||||
Transition::ModifyState(Box::new(move |state, ctx, app| {
|
||||
@ -197,7 +197,7 @@ fn inner_warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Tra
|
||||
s.controls.common.as_mut().unwrap().launch_info_panel(
|
||||
ctx,
|
||||
app,
|
||||
Tab::BusRoute(r),
|
||||
Tab::TransitRoute(r),
|
||||
&mut actions,
|
||||
);
|
||||
}
|
||||
|
@ -624,7 +624,7 @@ impl ContextualActions for Actions {
|
||||
ID::ParkingLot(_) => {
|
||||
actions.push((Key::H, "hide this".to_string()));
|
||||
}
|
||||
ID::BusStop(_) => {
|
||||
ID::TransitStop(_) => {
|
||||
actions.push((Key::H, "hide this".to_string()));
|
||||
}
|
||||
ID::Building(_) => {
|
||||
|
@ -90,8 +90,8 @@ impl ObjectDebugger {
|
||||
sim.debug_ped(p);
|
||||
}
|
||||
}
|
||||
ID::BusStop(id) => {
|
||||
println!("{}", abstutil::to_json(map.get_bs(id)));
|
||||
ID::TransitStop(id) => {
|
||||
println!("{}", abstutil::to_json(map.get_ts(id)));
|
||||
}
|
||||
ID::Area(id) => {
|
||||
println!("{}", abstutil::to_json(map.get_a(id)));
|
||||
@ -110,7 +110,7 @@ impl ObjectDebugger {
|
||||
ID::Pedestrian(id) => sim.debug_agent_json(AgentID::Pedestrian(id)),
|
||||
// Just show the first...
|
||||
ID::PedCrowd(members) => sim.debug_agent_json(AgentID::Pedestrian(members[0])),
|
||||
ID::BusStop(id) => abstutil::to_json(map.get_bs(id)),
|
||||
ID::TransitStop(id) => abstutil::to_json(map.get_ts(id)),
|
||||
ID::Area(id) => abstutil::to_json(map.get_a(id)),
|
||||
ID::Road(_) => unreachable!(),
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
use geom::{Duration, Time};
|
||||
use map_model::{BusRouteID, EditCmd};
|
||||
use map_model::{EditCmd, TransitRouteID};
|
||||
use widgetry::{
|
||||
EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, Spinner, State, TextExt,
|
||||
VerticalAlignment, Widget,
|
||||
@ -11,21 +11,21 @@ use crate::edit::apply_map_edits;
|
||||
|
||||
pub struct RouteEditor {
|
||||
panel: Panel,
|
||||
route: BusRouteID,
|
||||
route: TransitRouteID,
|
||||
}
|
||||
|
||||
impl RouteEditor {
|
||||
pub fn new_state(ctx: &mut EventCtx, app: &mut App, id: BusRouteID) -> Box<dyn State<App>> {
|
||||
pub fn new_state(ctx: &mut EventCtx, app: &mut App, id: TransitRouteID) -> Box<dyn State<App>> {
|
||||
app.primary.current_selection = None;
|
||||
|
||||
let route = app.primary.map.get_br(id);
|
||||
let route = app.primary.map.get_tr(id);
|
||||
Box::new(RouteEditor {
|
||||
panel: Panel::new_builder(Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Route editor").small_heading().into_widget(ctx),
|
||||
ctx.style().btn_close_widget(ctx),
|
||||
]),
|
||||
Line(&route.full_name).into_widget(ctx),
|
||||
Line(&route.long_name).into_widget(ctx),
|
||||
// TODO This UI needs design, just something to start plumbing the edits
|
||||
Widget::row(vec![
|
||||
"Frequency".text_widget(ctx),
|
||||
@ -71,7 +71,7 @@ impl State<App> for RouteEditor {
|
||||
let mut edits = app.primary.map.get_edits().clone();
|
||||
edits.commands.push(EditCmd::ChangeRouteSchedule {
|
||||
id: self.route,
|
||||
old: app.primary.map.get_br(self.route).spawn_times.clone(),
|
||||
old: app.primary.map.get_tr(self.route).spawn_times.clone(),
|
||||
new: hourly_times,
|
||||
});
|
||||
apply_map_edits(ctx, app, edits);
|
||||
|
@ -5,7 +5,9 @@ pub use trip::OpenTrip;
|
||||
use geom::{Circle, Distance, Polygon, Time};
|
||||
use map_gui::tools::open_browser;
|
||||
use map_gui::ID;
|
||||
use map_model::{AreaID, BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, ParkingLotID};
|
||||
use map_model::{
|
||||
AreaID, BuildingID, IntersectionID, LaneID, ParkingLotID, TransitRouteID, TransitStopID,
|
||||
};
|
||||
use sim::{
|
||||
AgentID, AgentType, Analytics, CarID, ParkingSpot, PedestrianID, PersonID, PersonState, TripID,
|
||||
VehicleType,
|
||||
@ -24,12 +26,12 @@ use crate::layer::PANEL_PLACEMENT;
|
||||
use crate::sandbox::{dashboards, GameplayMode, SandboxMode, TimeWarpScreen};
|
||||
|
||||
mod building;
|
||||
mod bus;
|
||||
mod debug;
|
||||
mod intersection;
|
||||
mod lane;
|
||||
mod parking_lot;
|
||||
mod person;
|
||||
mod transit;
|
||||
mod trip;
|
||||
|
||||
pub struct InfoPanel {
|
||||
@ -57,9 +59,9 @@ pub enum Tab {
|
||||
PersonBio(PersonID),
|
||||
PersonSchedule(PersonID),
|
||||
|
||||
BusStatus(CarID),
|
||||
BusStop(BusStopID),
|
||||
BusRoute(BusRouteID),
|
||||
TransitVehicleStatus(CarID),
|
||||
TransitStop(TransitStopID),
|
||||
TransitRoute(TransitRouteID),
|
||||
|
||||
ParkedCar(CarID),
|
||||
|
||||
@ -151,7 +153,7 @@ impl Tab {
|
||||
} else if c.vehicle_type == VehicleType::Bus || c.vehicle_type == VehicleType::Train
|
||||
{
|
||||
match app.session.info_panel_tab["bus"] {
|
||||
"status" => Tab::BusStatus(c),
|
||||
"status" => Tab::TransitVehicleStatus(c),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
@ -180,7 +182,7 @@ impl Tab {
|
||||
}
|
||||
}
|
||||
ID::PedCrowd(members) => Tab::Crowd(members),
|
||||
ID::BusStop(bs) => Tab::BusStop(bs),
|
||||
ID::TransitStop(bs) => Tab::TransitStop(bs),
|
||||
ID::Area(a) => Tab::Area(a),
|
||||
}
|
||||
}
|
||||
@ -196,9 +198,9 @@ impl Tab {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
Tab::BusStatus(c) => Some(ID::Car(*c)),
|
||||
Tab::BusStop(bs) => Some(ID::BusStop(*bs)),
|
||||
Tab::BusRoute(_) => None,
|
||||
Tab::TransitVehicleStatus(c) => Some(ID::Car(*c)),
|
||||
Tab::TransitStop(bs) => Some(ID::TransitStop(*bs)),
|
||||
Tab::TransitRoute(_) => None,
|
||||
// TODO If a parked car becomes in use while the panel is open, should update the
|
||||
// panel better.
|
||||
Tab::ParkedCar(c) => match app.primary.sim.lookup_parked_car(*c)?.spot {
|
||||
@ -262,9 +264,9 @@ impl Tab {
|
||||
Tab::PersonTrips(_, _) => ("person", "trips"),
|
||||
Tab::PersonBio(_) => ("person", "bio"),
|
||||
Tab::PersonSchedule(_) => ("person", "schedule"),
|
||||
Tab::BusStatus(_) => ("bus", "status"),
|
||||
Tab::BusStop(_) => ("bus stop", "info"),
|
||||
Tab::BusRoute(_) => ("bus route", "info"),
|
||||
Tab::TransitVehicleStatus(_) => ("bus", "status"),
|
||||
Tab::TransitStop(_) => ("bus stop", "info"),
|
||||
Tab::TransitRoute(_) => ("bus route", "info"),
|
||||
Tab::ParkedCar(_) => ("parked car", "info"),
|
||||
Tab::BldgInfo(_) => ("bldg", "info"),
|
||||
Tab::BldgPeople(_) => ("bldg", "people"),
|
||||
@ -332,9 +334,9 @@ impl InfoPanel {
|
||||
person::schedule(ctx, app, &mut details, p, ctx_actions.is_paused()),
|
||||
false,
|
||||
),
|
||||
Tab::BusStatus(c) => (bus::bus_status(ctx, app, &mut details, c), true),
|
||||
Tab::BusStop(bs) => (bus::stop(ctx, app, &mut details, bs), true),
|
||||
Tab::BusRoute(br) => (bus::route(ctx, app, &mut details, br), true),
|
||||
Tab::TransitVehicleStatus(c) => (transit::bus_status(ctx, app, &mut details, c), true),
|
||||
Tab::TransitStop(bs) => (transit::stop(ctx, app, &mut details, bs), true),
|
||||
Tab::TransitRoute(br) => (transit::route(ctx, app, &mut details, br), true),
|
||||
Tab::ParkedCar(c) => (
|
||||
person::parked_car(ctx, app, &mut details, c, ctx_actions.is_paused()),
|
||||
true,
|
||||
@ -571,7 +573,7 @@ impl InfoPanel {
|
||||
} else if let Some(url) = action.strip_prefix("open ") {
|
||||
open_browser(url);
|
||||
(false, None)
|
||||
} else if let Some(x) = action.strip_prefix("edit BusRoute #") {
|
||||
} else if let Some(x) = action.strip_prefix("edit TransitRoute #") {
|
||||
(
|
||||
false,
|
||||
Some(Transition::Multi(vec![
|
||||
@ -583,7 +585,7 @@ impl InfoPanel {
|
||||
Transition::Push(RouteEditor::new_state(
|
||||
ctx,
|
||||
app,
|
||||
BusRouteID(x.parse::<usize>().unwrap()),
|
||||
TransitRouteID(x.parse::<usize>().unwrap()),
|
||||
)),
|
||||
])),
|
||||
)
|
||||
|
@ -2,14 +2,14 @@ use abstutil::{prettyprint_usize, Counter};
|
||||
use geom::{Circle, Distance, Time};
|
||||
use map_gui::tools::ColorNetwork;
|
||||
use map_gui::ID;
|
||||
use map_model::{BusRoute, BusRouteID, BusStopID, PathStep};
|
||||
use map_model::{PathStep, TransitRoute, TransitRouteID, TransitStopID};
|
||||
use sim::{AgentID, CarID};
|
||||
use widgetry::{Color, ControlState, EventCtx, Key, Line, RewriteColor, Text, TextExt, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::info::{header_btns, make_tabs, Details, Tab};
|
||||
|
||||
pub fn stop(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID) -> Widget {
|
||||
pub fn stop(ctx: &mut EventCtx, app: &App, details: &mut Details, id: TransitStopID) -> Widget {
|
||||
let header = Widget::row(vec![
|
||||
Line("Bus stop").small_heading().into_widget(ctx),
|
||||
header_btns(ctx),
|
||||
@ -18,25 +18,25 @@ pub fn stop(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID)
|
||||
Widget::custom_col(vec![header, stop_body(ctx, app, details, id).tab_body(ctx)])
|
||||
}
|
||||
|
||||
fn stop_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID) -> Widget {
|
||||
fn stop_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: TransitStopID) -> Widget {
|
||||
let mut rows = vec![];
|
||||
|
||||
let bs = app.primary.map.get_bs(id);
|
||||
let ts = app.primary.map.get_ts(id);
|
||||
let sim = &app.primary.sim;
|
||||
|
||||
rows.push(Line(&bs.name).into_widget(ctx));
|
||||
rows.push(Line(&ts.name).into_widget(ctx));
|
||||
|
||||
let all_arrivals = &sim.get_analytics().bus_arrivals;
|
||||
for r in app.primary.map.get_routes_serving_stop(id) {
|
||||
// Full names can overlap, so include the ID
|
||||
let label = format!("{} ({})", r.full_name, r.id);
|
||||
let label = format!("{} ({})", r.long_name, r.id);
|
||||
rows.push(
|
||||
ctx.style()
|
||||
.btn_outline
|
||||
.text(format!("Route {}", r.short_name))
|
||||
.build_widget(ctx, &label),
|
||||
);
|
||||
details.hyperlinks.insert(label, Tab::BusRoute(r.id));
|
||||
details.hyperlinks.insert(label, Tab::TransitRoute(r.id));
|
||||
|
||||
let arrivals: Vec<(Time, CarID)> = all_arrivals
|
||||
.iter()
|
||||
@ -53,8 +53,8 @@ fn stop_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID
|
||||
rows.push(txt.into_widget(ctx));
|
||||
}
|
||||
|
||||
let mut boardings: Counter<BusRouteID> = Counter::new();
|
||||
let mut alightings: Counter<BusRouteID> = Counter::new();
|
||||
let mut boardings: Counter<TransitRouteID> = Counter::new();
|
||||
let mut alightings: Counter<TransitRouteID> = Counter::new();
|
||||
if let Some(list) = app.primary.sim.get_analytics().passengers_boarding.get(&id) {
|
||||
for (_, r, _) in list {
|
||||
boardings.inc(*r);
|
||||
@ -97,7 +97,7 @@ fn stop_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID
|
||||
// Draw where the bus/train stops
|
||||
details.draw_extra.zoomed.push(
|
||||
app.cs.bus_body.alpha(0.5),
|
||||
Circle::new(bs.driving_pos.pt(&app.primary.map), Distance::meters(2.5)).to_polygon(),
|
||||
Circle::new(ts.driving_pos.pt(&app.primary.map), Distance::meters(2.5)).to_polygon(),
|
||||
);
|
||||
|
||||
Widget::col(rows)
|
||||
@ -105,7 +105,7 @@ fn stop_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID
|
||||
|
||||
pub fn bus_status(ctx: &mut EventCtx, app: &App, details: &mut Details, id: CarID) -> Widget {
|
||||
Widget::custom_col(vec![
|
||||
bus_header(ctx, app, details, id, Tab::BusStatus(id)),
|
||||
bus_header(ctx, app, details, id, Tab::TransitVehicleStatus(id)),
|
||||
bus_status_body(ctx, app, details, id).tab_body(ctx),
|
||||
])
|
||||
}
|
||||
@ -116,7 +116,7 @@ fn bus_status_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Car
|
||||
let route = app
|
||||
.primary
|
||||
.map
|
||||
.get_br(app.primary.sim.bus_route_id(id).unwrap());
|
||||
.get_tr(app.primary.sim.bus_route_id(id).unwrap());
|
||||
|
||||
rows.push(
|
||||
ctx.style()
|
||||
@ -126,7 +126,7 @@ fn bus_status_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Car
|
||||
);
|
||||
details.hyperlinks.insert(
|
||||
format!("Serves route {}", route.short_name),
|
||||
Tab::BusRoute(route.id),
|
||||
Tab::TransitRoute(route.id),
|
||||
);
|
||||
|
||||
rows.push(
|
||||
@ -156,7 +156,7 @@ fn bus_header(ctx: &mut EventCtx, app: &App, details: &mut Details, id: CarID, t
|
||||
Line(format!(
|
||||
"{} (route {})",
|
||||
id,
|
||||
app.primary.map.get_br(route).short_name
|
||||
app.primary.map.get_tr(route).short_name
|
||||
))
|
||||
.small_heading()
|
||||
.into_widget(ctx),
|
||||
@ -166,16 +166,16 @@ fn bus_header(ctx: &mut EventCtx, app: &App, details: &mut Details, id: CarID, t
|
||||
ctx,
|
||||
&mut details.hyperlinks,
|
||||
tab,
|
||||
vec![("Status", Tab::BusStatus(id))],
|
||||
vec![("Status", Tab::TransitVehicleStatus(id))],
|
||||
));
|
||||
|
||||
Widget::custom_col(rows)
|
||||
}
|
||||
|
||||
pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteID) -> Widget {
|
||||
pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: TransitRouteID) -> Widget {
|
||||
let header = {
|
||||
let map = &app.primary.map;
|
||||
let route = map.get_br(id);
|
||||
let route = map.get_tr(id);
|
||||
|
||||
Widget::row(vec![
|
||||
Line(format!("Route {}", route.short_name))
|
||||
@ -191,13 +191,13 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
|
||||
])
|
||||
}
|
||||
|
||||
fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteID) -> Widget {
|
||||
fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: TransitRouteID) -> Widget {
|
||||
let mut rows = vec![];
|
||||
|
||||
let map = &app.primary.map;
|
||||
let route = map.get_br(id);
|
||||
let route = map.get_tr(id);
|
||||
rows.push(
|
||||
Text::from(&route.full_name)
|
||||
Text::from(&route.long_name)
|
||||
.wrap_to_pct(ctx, 20)
|
||||
.into_widget(ctx),
|
||||
);
|
||||
@ -220,33 +220,33 @@ fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRoute
|
||||
rows.push(ctx.style().btn_outline.text(bus.to_string()).build_def(ctx));
|
||||
details
|
||||
.hyperlinks
|
||||
.insert(bus.to_string(), Tab::BusStatus(bus));
|
||||
.insert(bus.to_string(), Tab::TransitVehicleStatus(bus));
|
||||
bus_locations.push(pt);
|
||||
}
|
||||
}
|
||||
|
||||
let mut boardings: Counter<BusStopID> = Counter::new();
|
||||
let mut alightings: Counter<BusStopID> = Counter::new();
|
||||
let mut waiting: Counter<BusStopID> = Counter::new();
|
||||
for bs in &route.stops {
|
||||
if let Some(list) = app.primary.sim.get_analytics().passengers_boarding.get(bs) {
|
||||
let mut boardings: Counter<TransitStopID> = Counter::new();
|
||||
let mut alightings: Counter<TransitStopID> = Counter::new();
|
||||
let mut waiting: Counter<TransitStopID> = Counter::new();
|
||||
for ts in &route.stops {
|
||||
if let Some(list) = app.primary.sim.get_analytics().passengers_boarding.get(ts) {
|
||||
for (_, r, _) in list {
|
||||
if *r == id {
|
||||
boardings.inc(*bs);
|
||||
boardings.inc(*ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(list) = app.primary.sim.get_analytics().passengers_alighting.get(bs) {
|
||||
if let Some(list) = app.primary.sim.get_analytics().passengers_alighting.get(ts) {
|
||||
for (_, r) in list {
|
||||
if *r == id {
|
||||
alightings.inc(*bs);
|
||||
alightings.inc(*ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (_, r, _, _) in app.primary.sim.get_people_waiting_at_stop(*bs) {
|
||||
for (_, r, _, _) in app.primary.sim.get_people_waiting_at_stop(*ts) {
|
||||
if *r == id {
|
||||
waiting.inc(*bs);
|
||||
waiting.inc(*ts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,27 +279,27 @@ fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRoute
|
||||
]));
|
||||
details.warpers.insert(name, ID::Intersection(i.id));
|
||||
}
|
||||
for (idx, bs) in route.stops.iter().enumerate() {
|
||||
let bs = map.get_bs(*bs);
|
||||
let name = format!("Stop {}: {}", idx + 1, bs.name);
|
||||
for (idx, ts) in route.stops.iter().enumerate() {
|
||||
let ts = map.get_ts(*ts);
|
||||
let name = format!("Stop {}: {}", idx + 1, ts.name);
|
||||
rows.push(Widget::row(vec![
|
||||
ctx.style()
|
||||
.btn_plain
|
||||
.icon("system/assets/tools/pin.svg")
|
||||
.build_widget(ctx, &name),
|
||||
Text::from_all(vec![
|
||||
Line(&bs.name),
|
||||
Line(&ts.name),
|
||||
Line(format!(
|
||||
": {} boardings, {} alightings, {} currently waiting",
|
||||
prettyprint_usize(boardings.get(bs.id)),
|
||||
prettyprint_usize(alightings.get(bs.id)),
|
||||
prettyprint_usize(waiting.get(bs.id))
|
||||
prettyprint_usize(boardings.get(ts.id)),
|
||||
prettyprint_usize(alightings.get(ts.id)),
|
||||
prettyprint_usize(waiting.get(ts.id))
|
||||
))
|
||||
.secondary(),
|
||||
])
|
||||
.into_widget(ctx),
|
||||
]));
|
||||
details.warpers.insert(name, ID::BusStop(bs.id));
|
||||
details.warpers.insert(name, ID::TransitStop(ts.id));
|
||||
}
|
||||
if let Some(l) = route.end_border {
|
||||
let i = map.get_i(map.get_l(l).dst_i);
|
||||
@ -351,20 +351,20 @@ fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRoute
|
||||
);
|
||||
}
|
||||
|
||||
for (idx, bs) in route.stops.iter().enumerate() {
|
||||
let bs = map.get_bs(*bs);
|
||||
for (idx, ts) in route.stops.iter().enumerate() {
|
||||
let ts = map.get_ts(*ts);
|
||||
details.draw_extra.unzoomed.append(
|
||||
Text::from(format!("{}) {}", idx + 1, bs.name))
|
||||
Text::from(format!("{}) {}", idx + 1, ts.name))
|
||||
.bg(app.cs.bus_layer)
|
||||
.render_autocropped(ctx)
|
||||
.centered_on(bs.sidewalk_pos.pt(map)),
|
||||
.centered_on(ts.sidewalk_pos.pt(map)),
|
||||
);
|
||||
details.draw_extra.zoomed.append(
|
||||
Text::from(format!("{}) {}", idx + 1, bs.name))
|
||||
Text::from(format!("{}) {}", idx + 1, ts.name))
|
||||
.bg(app.cs.bus_layer)
|
||||
.render_autocropped(ctx)
|
||||
.scale(0.1)
|
||||
.centered_on(bs.sidewalk_pos.pt(map)),
|
||||
.centered_on(ts.sidewalk_pos.pt(map)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -373,7 +373,7 @@ fn route_body(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRoute
|
||||
}
|
||||
|
||||
// TODO Unit test
|
||||
fn describe_schedule(route: &BusRoute) -> Text {
|
||||
fn describe_schedule(route: &TransitRoute) -> Text {
|
||||
let mut txt = Text::new();
|
||||
txt.add_line(format!(
|
||||
"{} {}s run this route daily",
|
@ -71,23 +71,23 @@ impl TransitNetwork {
|
||||
colorer.add_l(l.id, "bus lanes / rails");
|
||||
}
|
||||
}
|
||||
for bs in map.all_bus_stops().values() {
|
||||
if !bs.is_train_stop && show_buses {
|
||||
colorer.add_bs(bs.id, "transit stops");
|
||||
for ts in map.all_transit_stops().values() {
|
||||
if !ts.is_train_stop && show_buses {
|
||||
colorer.add_ts(ts.id, "transit stops");
|
||||
}
|
||||
if bs.is_train_stop && show_trains {
|
||||
colorer.add_bs(bs.id, "transit stops");
|
||||
if ts.is_train_stop && show_trains {
|
||||
colorer.add_ts(ts.id, "transit stops");
|
||||
}
|
||||
}
|
||||
if show_all_routes {
|
||||
for br in map.all_bus_routes() {
|
||||
if !show_buses && br.route_type == PathConstraints::Bus {
|
||||
for tr in map.all_transit_routes() {
|
||||
if !show_buses && tr.route_type == PathConstraints::Bus {
|
||||
continue;
|
||||
}
|
||||
if !show_trains && br.route_type == PathConstraints::Train {
|
||||
if !show_trains && tr.route_type == PathConstraints::Train {
|
||||
continue;
|
||||
}
|
||||
for req in br.all_steps(map) {
|
||||
for req in tr.all_steps(map) {
|
||||
if let Ok(path) = map.pathfind(req) {
|
||||
for step in path.get_steps() {
|
||||
if let PathStep::Lane(l) = step {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil::{prettyprint_usize, Counter};
|
||||
use geom::Time;
|
||||
use map_model::BusRouteID;
|
||||
use map_model::TransitRouteID;
|
||||
use widgetry::{
|
||||
Autocomplete, EventCtx, GfxCtx, Image, Line, LinePlot, Outcome, Panel, PlotOptions, Series,
|
||||
State, TextExt, Widget,
|
||||
@ -132,20 +132,20 @@ impl TransitRoutes {
|
||||
}
|
||||
}
|
||||
let mut waiting = Counter::new();
|
||||
for bs in app.primary.map.all_bus_stops().keys() {
|
||||
for (_, r, _, _) in app.primary.sim.get_people_waiting_at_stop(*bs) {
|
||||
for ts in app.primary.map.all_transit_stops().keys() {
|
||||
for (_, r, _, _) in app.primary.sim.get_people_waiting_at_stop(*ts) {
|
||||
waiting.inc(*r);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort descending by count, but ascending by name. Hence the funny negation.
|
||||
let mut routes: Vec<(isize, isize, isize, String, BusRouteID)> = Vec::new();
|
||||
for r in app.primary.map.all_bus_routes() {
|
||||
let mut routes: Vec<(isize, isize, isize, String, TransitRouteID)> = Vec::new();
|
||||
for r in app.primary.map.all_transit_routes() {
|
||||
routes.push((
|
||||
-(boardings.get(r.id) as isize),
|
||||
-(alightings.get(r.id) as isize),
|
||||
-(waiting.get(r.id) as isize),
|
||||
r.full_name.clone(),
|
||||
r.long_name.clone(),
|
||||
r.id,
|
||||
));
|
||||
}
|
||||
@ -204,8 +204,8 @@ impl State<App> for TransitRoutes {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
let route = match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => {
|
||||
if let Some(x) = x.strip_prefix("BusRoute #") {
|
||||
BusRouteID(x.parse::<usize>().unwrap())
|
||||
if let Some(x) = x.strip_prefix("TransitRoute #") {
|
||||
TransitRouteID(x.parse::<usize>().unwrap())
|
||||
} else if x == "close" {
|
||||
return Transition::Pop;
|
||||
} else {
|
||||
@ -240,7 +240,7 @@ impl State<App> for TransitRoutes {
|
||||
sandbox.controls.common.as_mut().unwrap().launch_info_panel(
|
||||
ctx,
|
||||
app,
|
||||
Tab::BusRoute(route),
|
||||
Tab::TransitRoute(route),
|
||||
&mut actions,
|
||||
)
|
||||
})),
|
||||
|
@ -11,7 +11,9 @@ extern crate log;
|
||||
|
||||
use abstutil::Timer;
|
||||
use geom::{Duration, Pt2D, Time};
|
||||
use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID};
|
||||
use map_model::{
|
||||
AreaID, BuildingID, IntersectionID, LaneID, Map, ParkingLotID, RoadID, TransitStopID,
|
||||
};
|
||||
use sim::{AgentID, CarID, PedestrianID, Sim};
|
||||
use widgetry::{EventCtx, GfxCtx, State};
|
||||
|
||||
@ -88,7 +90,7 @@ pub enum ID {
|
||||
Car(CarID),
|
||||
Pedestrian(PedestrianID),
|
||||
PedCrowd(Vec<PedestrianID>),
|
||||
BusStop(BusStopID),
|
||||
TransitStop(TransitStopID),
|
||||
Area(AreaID),
|
||||
}
|
||||
|
||||
@ -173,9 +175,9 @@ impl From<Vec<PedestrianID>> for ID {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BusStopID> for ID {
|
||||
fn from(b: BusStopID) -> Self {
|
||||
Self::BusStop(b)
|
||||
impl From<TransitStopID> for ID {
|
||||
fn from(b: TransitStopID) -> Self {
|
||||
Self::TransitStop(b)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,18 +5,18 @@ use aabb_quadtree::QuadTree;
|
||||
use abstutil::Timer;
|
||||
use geom::{Bounds, Distance, Polygon};
|
||||
use map_model::{
|
||||
AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, Road, RoadID,
|
||||
AreaID, BuildingID, IntersectionID, LaneID, Map, ParkingLotID, Road, RoadID, TransitStopID,
|
||||
};
|
||||
use widgetry::{Color, Drawable, EventCtx, GeomBatch};
|
||||
|
||||
use crate::colors::ColorScheme;
|
||||
use crate::options::Options;
|
||||
use crate::render::building::DrawBuilding;
|
||||
use crate::render::bus_stop::DrawBusStop;
|
||||
use crate::render::intersection::DrawIntersection;
|
||||
use crate::render::lane::DrawLane;
|
||||
use crate::render::parking_lot::DrawParkingLot;
|
||||
use crate::render::road::DrawRoad;
|
||||
use crate::render::transit_stop::DrawTransitStop;
|
||||
use crate::render::{AgentCache, DrawArea, Renderable};
|
||||
use crate::{AppLike, ID};
|
||||
|
||||
@ -25,7 +25,7 @@ pub struct DrawMap {
|
||||
pub intersections: Vec<DrawIntersection>,
|
||||
pub buildings: Vec<DrawBuilding>,
|
||||
pub parking_lots: Vec<DrawParkingLot>,
|
||||
pub bus_stops: HashMap<BusStopID, DrawBusStop>,
|
||||
pub bus_stops: HashMap<TransitStopID, DrawTransitStop>,
|
||||
pub areas: Vec<DrawArea>,
|
||||
|
||||
pub boundary_polygon: Drawable,
|
||||
@ -107,11 +107,11 @@ impl DrawMap {
|
||||
let draw_all_unzoomed_parking_lots = all_unzoomed_parking_lots.upload(ctx);
|
||||
timer.stop("make DrawParkingLot");
|
||||
|
||||
timer.start_iter("make DrawBusStop", map.all_bus_stops().len());
|
||||
let mut bus_stops: HashMap<BusStopID, DrawBusStop> = HashMap::new();
|
||||
for s in map.all_bus_stops().values() {
|
||||
timer.start_iter("make DrawTransitStop", map.all_transit_stops().len());
|
||||
let mut bus_stops: HashMap<TransitStopID, DrawTransitStop> = HashMap::new();
|
||||
for s in map.all_transit_stops().values() {
|
||||
timer.next();
|
||||
bus_stops.insert(s.id, DrawBusStop::new(ctx, s, map, cs));
|
||||
bus_stops.insert(s.id, DrawTransitStop::new(ctx, s, map, cs));
|
||||
}
|
||||
|
||||
let mut areas: Vec<DrawArea> = Vec::new();
|
||||
@ -150,7 +150,7 @@ impl DrawMap {
|
||||
for obj in &parking_lots {
|
||||
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
|
||||
}
|
||||
// Don't put BusStops in the quadtree
|
||||
// Don't put TransitStops in the quadtree
|
||||
for obj in &areas {
|
||||
quadtree.insert_with_box(obj.get_id(), obj.get_outline(map).get_bounds().as_bbox());
|
||||
}
|
||||
@ -298,7 +298,7 @@ impl DrawMap {
|
||||
&self.parking_lots[id.0]
|
||||
}
|
||||
|
||||
pub fn get_bs(&self, id: BusStopID) -> &DrawBusStop {
|
||||
pub fn get_ts(&self, id: TransitStopID) -> &DrawTransitStop {
|
||||
&self.bus_stops[&id]
|
||||
}
|
||||
|
||||
@ -338,8 +338,8 @@ impl DrawMap {
|
||||
// If the first member has vanished, just give up
|
||||
app.sim().get_draw_ped(members[0], app.map())?.on
|
||||
}
|
||||
ID::BusStop(id) => {
|
||||
return Some(self.get_bs(id));
|
||||
ID::TransitStop(id) => {
|
||||
return Some(self.get_ts(id));
|
||||
}
|
||||
ID::Area(id) => {
|
||||
return Some(self.get_a(id));
|
||||
@ -370,7 +370,7 @@ impl DrawMap {
|
||||
let mut roads: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut intersections: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut buildings: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut bus_stops: Vec<&dyn Renderable> = Vec::new();
|
||||
let mut transit_stops: Vec<&dyn Renderable> = Vec::new();
|
||||
|
||||
for id in self.get_matching_objects(bounds) {
|
||||
match id {
|
||||
@ -378,8 +378,8 @@ impl DrawMap {
|
||||
ID::Road(id) => {
|
||||
let road = self.get_r(id);
|
||||
for lane in &road.lanes {
|
||||
for bs in &map.get_l(lane.id).bus_stops {
|
||||
bus_stops.push(self.get_bs(*bs));
|
||||
for ts in &map.get_l(lane.id).transit_stops {
|
||||
transit_stops.push(self.get_ts(*ts));
|
||||
}
|
||||
lanes.push(lane);
|
||||
}
|
||||
@ -393,7 +393,11 @@ impl DrawMap {
|
||||
parking_lots.push(self.get_pl(id));
|
||||
}
|
||||
|
||||
ID::Lane(_) | ID::BusStop(_) | ID::Car(_) | ID::Pedestrian(_) | ID::PedCrowd(_) => {
|
||||
ID::Lane(_)
|
||||
| ID::TransitStop(_)
|
||||
| ID::Car(_)
|
||||
| ID::Pedestrian(_)
|
||||
| ID::PedCrowd(_) => {
|
||||
panic!("{:?} shouldn't be in the quadtree", id)
|
||||
}
|
||||
}
|
||||
@ -407,7 +411,7 @@ impl DrawMap {
|
||||
borrows.extend(roads);
|
||||
borrows.extend(intersections);
|
||||
borrows.extend(buildings);
|
||||
borrows.extend(bus_stops);
|
||||
borrows.extend(transit_stops);
|
||||
|
||||
borrows.retain(|x| x.get_zorder() <= self.show_zorder);
|
||||
|
||||
|
@ -21,7 +21,6 @@ mod agents;
|
||||
mod area;
|
||||
mod bike;
|
||||
mod building;
|
||||
mod bus_stop;
|
||||
mod car;
|
||||
mod intersection;
|
||||
mod lane;
|
||||
@ -30,6 +29,7 @@ mod parking_lot;
|
||||
mod pedestrian;
|
||||
mod road;
|
||||
pub mod traffic_signal;
|
||||
mod transit_stop;
|
||||
mod turn;
|
||||
|
||||
pub const BIG_ARROW_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||
|
@ -1,5 +1,5 @@
|
||||
use geom::{Angle, Circle, Distance, Line, Polygon, Pt2D};
|
||||
use map_model::{BusStop, BusStopID, Map};
|
||||
use map_model::{Map, TransitStop, TransitStopID};
|
||||
use widgetry::{Drawable, EventCtx, GeomBatch, GfxCtx};
|
||||
|
||||
use crate::colors::ColorScheme;
|
||||
@ -8,16 +8,16 @@ use crate::{AppLike, ID};
|
||||
|
||||
const RADIUS: Distance = Distance::const_meters(1.0);
|
||||
|
||||
pub struct DrawBusStop {
|
||||
pub id: BusStopID,
|
||||
pub struct DrawTransitStop {
|
||||
pub id: TransitStopID,
|
||||
center: Pt2D,
|
||||
zorder: isize,
|
||||
|
||||
draw_default: Drawable,
|
||||
}
|
||||
|
||||
impl DrawBusStop {
|
||||
pub fn new(ctx: &EventCtx, stop: &BusStop, map: &Map, cs: &ColorScheme) -> DrawBusStop {
|
||||
impl DrawTransitStop {
|
||||
pub fn new(ctx: &EventCtx, stop: &TransitStop, map: &Map, cs: &ColorScheme) -> DrawTransitStop {
|
||||
let (pt, angle) = stop.sidewalk_pos.pt_and_angle(map);
|
||||
let center = pt.project_away(
|
||||
map.get_l(stop.sidewalk_pos.lane()).width / 2.0,
|
||||
@ -53,7 +53,7 @@ impl DrawBusStop {
|
||||
.make_polygons(Distance::meters(0.3)),
|
||||
);
|
||||
|
||||
DrawBusStop {
|
||||
DrawTransitStop {
|
||||
id: stop.id,
|
||||
center,
|
||||
zorder: map.get_parent(stop.sidewalk_pos.lane()).zorder,
|
||||
@ -62,9 +62,9 @@ impl DrawBusStop {
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderable for DrawBusStop {
|
||||
impl Renderable for DrawTransitStop {
|
||||
fn get_id(&self) -> ID {
|
||||
ID::BusStop(self.id)
|
||||
ID::TransitStop(self.id)
|
||||
}
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, _: &dyn AppLike, _: &DrawOptions) {
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use abstutil::Counter;
|
||||
use geom::{Circle, Distance, Line, Polygon, Pt2D};
|
||||
use map_model::{BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID};
|
||||
use map_model::{BuildingID, IntersectionID, LaneID, Map, ParkingLotID, RoadID, TransitStopID};
|
||||
use widgetry::mapspace::ToggleZoomed;
|
||||
use widgetry::{Color, EventCtx, Fill, GeomBatch, Line, LinearGradient, Text, Widget};
|
||||
|
||||
@ -78,9 +78,9 @@ impl<'a> ColorDiscrete<'a> {
|
||||
.push(color.alpha(0.4), self.map.get_b(b).polygon.clone());
|
||||
}
|
||||
|
||||
pub fn add_bs<I: AsRef<str>>(&mut self, bs: BusStopID, category: I) {
|
||||
pub fn add_ts<I: AsRef<str>>(&mut self, ts: TransitStopID, category: I) {
|
||||
let color = self.colors[category.as_ref()];
|
||||
let pt = self.map.get_bs(bs).sidewalk_pos.pt(self.map);
|
||||
let pt = self.map.get_ts(ts).sidewalk_pos.pt(self.map);
|
||||
self.zoomed.push(
|
||||
color.alpha(0.4),
|
||||
Circle::new(pt, Distance::meters(5.0)).to_polygon(),
|
||||
|
@ -14,10 +14,9 @@ pub use self::perma::PermanentMapEdits;
|
||||
use crate::make::initial::lane_specs::get_lane_specs_ltr;
|
||||
use crate::make::{match_points_to_lanes, snap_driveway, trim_path};
|
||||
use crate::{
|
||||
connectivity, AccessRestrictions, BuildingID, BusRouteID, ControlStopSign,
|
||||
ControlTrafficSignal, Direction, IntersectionID, IntersectionType, LaneID, LaneSpec, LaneType,
|
||||
Map, MapConfig, Movement, ParkingLotID, PathConstraints, Pathfinder, Road, RoadID, TurnID,
|
||||
Zone,
|
||||
connectivity, AccessRestrictions, BuildingID, ControlStopSign, ControlTrafficSignal, Direction,
|
||||
IntersectionID, IntersectionType, LaneID, LaneSpec, LaneType, Map, MapConfig, Movement,
|
||||
ParkingLotID, PathConstraints, Pathfinder, Road, RoadID, TransitRouteID, TurnID, Zone,
|
||||
};
|
||||
|
||||
mod compat;
|
||||
@ -39,7 +38,7 @@ pub struct MapEdits {
|
||||
/// Derived from commands, kept up to date by update_derived
|
||||
pub changed_roads: BTreeSet<RoadID>,
|
||||
pub original_intersections: BTreeMap<IntersectionID, EditIntersection>,
|
||||
pub changed_routes: BTreeSet<BusRouteID>,
|
||||
pub changed_routes: BTreeSet<TransitRouteID>,
|
||||
|
||||
/// Some edits are included in the game by default, in data/system/proposals, as "community
|
||||
/// proposals." They require a description and may have a link to a write-up.
|
||||
@ -186,7 +185,7 @@ pub enum EditCmd {
|
||||
old: EditIntersection,
|
||||
},
|
||||
ChangeRouteSchedule {
|
||||
id: BusRouteID,
|
||||
id: TransitRouteID,
|
||||
old: Vec<Time>,
|
||||
new: Vec<Time>,
|
||||
},
|
||||
@ -297,7 +296,7 @@ impl MapEdits {
|
||||
self.original_intersections
|
||||
.retain(|i, orig| map.get_i_edit(*i) != orig.clone());
|
||||
self.changed_routes.retain(|br| {
|
||||
let r = map.get_br(*br);
|
||||
let r = map.get_tr(*br);
|
||||
r.spawn_times != r.orig_spawn_times
|
||||
});
|
||||
}
|
||||
@ -319,7 +318,7 @@ impl MapEdits {
|
||||
});
|
||||
}
|
||||
for r in &self.changed_routes {
|
||||
let r = map.get_br(*r);
|
||||
let r = map.get_tr(*r);
|
||||
self.commands.push(EditCmd::ChangeRouteSchedule {
|
||||
id: r.id,
|
||||
new: r.spawn_times.clone(),
|
||||
@ -396,7 +395,7 @@ impl EditCmd {
|
||||
EditIntersection::Closed => format!("close {}", i),
|
||||
},
|
||||
EditCmd::ChangeRouteSchedule { id, .. } => {
|
||||
format!("reschedule route {}", map.get_br(*id).short_name)
|
||||
format!("reschedule route {}", map.get_tr(*id).short_name)
|
||||
}
|
||||
};
|
||||
(summary, details)
|
||||
@ -472,7 +471,7 @@ impl EditCmd {
|
||||
}
|
||||
}
|
||||
EditCmd::ChangeRouteSchedule { id, new, .. } => {
|
||||
map.bus_routes[id.0].spawn_times = new.clone();
|
||||
map.transit_routes[id.0].spawn_times = new.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -905,9 +904,9 @@ impl Map {
|
||||
// Might need to update bus stops.
|
||||
if enforce_valid {
|
||||
for id in &effects.changed_roads {
|
||||
let stops = self.get_r(*id).all_bus_stops();
|
||||
let stops = self.get_r(*id).all_transit_stops();
|
||||
for s in stops {
|
||||
let sidewalk_pos = self.get_bs(s).sidewalk_pos;
|
||||
let sidewalk_pos = self.get_ts(s).sidewalk_pos;
|
||||
// Must exist, because we aren't allowed to orphan a bus stop.
|
||||
let driving_lane = self
|
||||
.get_r(*id)
|
||||
@ -916,7 +915,7 @@ impl Map {
|
||||
})
|
||||
.unwrap();
|
||||
let driving_pos = sidewalk_pos.equiv_pos(driving_lane, self);
|
||||
self.bus_stops.get_mut(&s).unwrap().driving_pos = driving_pos;
|
||||
self.transit_stops.get_mut(&s).unwrap().driving_pos = driving_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ impl EditCmd {
|
||||
},
|
||||
EditCmd::ChangeRouteSchedule { id, old, new } => {
|
||||
PermanentEditCmd::ChangeRouteSchedule {
|
||||
osm_rel_id: map.get_br(*id).osm_rel_id,
|
||||
osm_rel_id: map.get_tr(*id).osm_rel_id,
|
||||
old: old.clone(),
|
||||
new: new.clone(),
|
||||
}
|
||||
@ -124,7 +124,7 @@ impl PermanentEditCmd {
|
||||
new,
|
||||
} => {
|
||||
let id = map
|
||||
.find_br(osm_rel_id)
|
||||
.find_tr(osm_rel_id)
|
||||
.ok_or_else(|| anyhow!("can't find {}", osm_rel_id))?;
|
||||
Ok(EditCmd::ChangeRouteSchedule { id, old, new })
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
//! Map objects are usually abbreviated in method names:
|
||||
//! - a = area
|
||||
//! - b = building
|
||||
//! - br = bus route
|
||||
//! - bs = bus stop
|
||||
//! - tr = transit route
|
||||
//! - ts = transit stop
|
||||
//! - i = intersection
|
||||
//! - l = lane
|
||||
//! - pl = parking lot
|
||||
@ -47,7 +47,6 @@ pub use crate::objects::block::{Block, Perimeter};
|
||||
pub use crate::objects::building::{
|
||||
Amenity, AmenityType, Building, BuildingID, BuildingType, NamePerLanguage, OffstreetParking,
|
||||
};
|
||||
pub use crate::objects::bus_stop::{BusRoute, BusRouteID, BusStop, BusStopID};
|
||||
pub use crate::objects::intersection::{Intersection, IntersectionID, IntersectionType};
|
||||
pub use crate::objects::lane::{
|
||||
BufferType, Lane, LaneID, LaneSpec, LaneType, NORMAL_LANE_THICKNESS, PARKING_LOT_SPOT_LENGTH,
|
||||
@ -58,6 +57,7 @@ pub use crate::objects::parking_lot::{ParkingLot, ParkingLotID};
|
||||
pub use crate::objects::road::{DirectedRoadID, Direction, Road, RoadID, RoadSideID, SideOfRoad};
|
||||
pub use crate::objects::stop_signs::{ControlStopSign, RoadWithStopSign};
|
||||
pub use crate::objects::traffic_signals::{ControlTrafficSignal, Stage, StageType};
|
||||
pub use crate::objects::transit::{TransitRoute, TransitRouteID, TransitStop, TransitStopID};
|
||||
pub use crate::objects::turn::{Turn, TurnID, TurnPriority, TurnType};
|
||||
pub use crate::objects::zone::{AccessRestrictions, Zone};
|
||||
pub use crate::pathfind::uber_turns::{IntersectionCluster, UberTurn};
|
||||
@ -89,8 +89,8 @@ pub struct Map {
|
||||
serialize_with = "serialize_btreemap",
|
||||
deserialize_with = "deserialize_btreemap"
|
||||
)]
|
||||
bus_stops: BTreeMap<BusStopID, BusStop>,
|
||||
bus_routes: Vec<BusRoute>,
|
||||
transit_stops: BTreeMap<TransitStopID, TransitStop>,
|
||||
transit_routes: Vec<TransitRoute>,
|
||||
areas: Vec<Area>,
|
||||
parking_lots: Vec<ParkingLot>,
|
||||
boundary_polygon: Polygon,
|
||||
|
@ -58,8 +58,8 @@ impl Map {
|
||||
roads: Vec::new(),
|
||||
intersections: Vec::new(),
|
||||
buildings: Vec::new(),
|
||||
bus_stops: BTreeMap::new(),
|
||||
bus_routes: Vec::new(),
|
||||
transit_stops: BTreeMap::new(),
|
||||
transit_routes: Vec::new(),
|
||||
areas: Vec::new(),
|
||||
parking_lots: Vec::new(),
|
||||
zones: Vec::new(),
|
||||
|
@ -12,11 +12,12 @@ use geom::{Bounds, Distance, Duration, GPSBounds, Polygon, Pt2D, Ring, Time};
|
||||
|
||||
use crate::raw::{OriginalRoad, RawMap};
|
||||
use crate::{
|
||||
osm, Area, AreaID, AreaType, Building, BuildingID, BuildingType, BusRoute, BusRouteID, BusStop,
|
||||
BusStopID, CompressedMovementID, ControlStopSign, ControlTrafficSignal, DirectedRoadID,
|
||||
Direction, Intersection, IntersectionID, Lane, LaneID, LaneType, Map, MapEdits, Movement,
|
||||
MovementID, OffstreetParking, ParkingLot, ParkingLotID, Path, PathConstraints, PathRequest,
|
||||
PathV2, Pathfinder, Position, Road, RoadID, RoutingParams, Turn, TurnID, TurnType, Zone,
|
||||
osm, Area, AreaID, AreaType, Building, BuildingID, BuildingType, CompressedMovementID,
|
||||
ControlStopSign, ControlTrafficSignal, DirectedRoadID, Direction, Intersection, IntersectionID,
|
||||
Lane, LaneID, LaneType, Map, MapEdits, Movement, MovementID, OffstreetParking, ParkingLot,
|
||||
ParkingLotID, Path, PathConstraints, PathRequest, PathV2, Pathfinder, Position, Road, RoadID,
|
||||
RoutingParams, TransitRoute, TransitRouteID, TransitStop, TransitStopID, Turn, TurnID,
|
||||
TurnType, Zone,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -154,8 +155,8 @@ impl Map {
|
||||
roads: Vec::new(),
|
||||
intersections: Vec::new(),
|
||||
buildings: Vec::new(),
|
||||
bus_stops: BTreeMap::new(),
|
||||
bus_routes: Vec::new(),
|
||||
transit_stops: BTreeMap::new(),
|
||||
transit_routes: Vec::new(),
|
||||
areas: Vec::new(),
|
||||
parking_lots: Vec::new(),
|
||||
zones: Vec::new(),
|
||||
@ -254,8 +255,8 @@ impl Map {
|
||||
self.areas.get(id.0)
|
||||
}
|
||||
|
||||
pub fn maybe_get_bs(&self, id: BusStopID) -> Option<&BusStop> {
|
||||
self.bus_stops.get(&id)
|
||||
pub fn maybe_get_ts(&self, id: TransitStopID) -> Option<&TransitStop> {
|
||||
self.transit_stops.get(&id)
|
||||
}
|
||||
|
||||
pub fn maybe_get_stop_sign(&self, id: IntersectionID) -> Option<&ControlStopSign> {
|
||||
@ -266,8 +267,8 @@ impl Map {
|
||||
self.traffic_signals.get(&id)
|
||||
}
|
||||
|
||||
pub fn maybe_get_br(&self, route: BusRouteID) -> Option<&BusRoute> {
|
||||
self.bus_routes.get(route.0)
|
||||
pub fn maybe_get_tr(&self, route: TransitRouteID) -> Option<&TransitRoute> {
|
||||
self.transit_routes.get(route.0)
|
||||
}
|
||||
|
||||
pub fn get_r(&self, id: RoadID) -> &Road {
|
||||
@ -450,29 +451,29 @@ impl Map {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> {
|
||||
&self.bus_stops
|
||||
pub fn all_transit_stops(&self) -> &BTreeMap<TransitStopID, TransitStop> {
|
||||
&self.transit_stops
|
||||
}
|
||||
|
||||
pub fn get_bs(&self, stop: BusStopID) -> &BusStop {
|
||||
&self.bus_stops[&stop]
|
||||
pub fn get_ts(&self, stop: TransitStopID) -> &TransitStop {
|
||||
&self.transit_stops[&stop]
|
||||
}
|
||||
|
||||
pub fn get_br(&self, route: BusRouteID) -> &BusRoute {
|
||||
&self.bus_routes[route.0]
|
||||
pub fn get_tr(&self, route: TransitRouteID) -> &TransitRoute {
|
||||
&self.transit_routes[route.0]
|
||||
}
|
||||
|
||||
pub fn all_bus_routes(&self) -> &Vec<BusRoute> {
|
||||
&self.bus_routes
|
||||
pub fn all_transit_routes(&self) -> &Vec<TransitRoute> {
|
||||
&self.transit_routes
|
||||
}
|
||||
|
||||
pub fn get_bus_route(&self, name: &str) -> Option<&BusRoute> {
|
||||
self.bus_routes.iter().find(|r| r.full_name == name)
|
||||
pub fn get_transit_route(&self, name: &str) -> Option<&TransitRoute> {
|
||||
self.transit_routes.iter().find(|r| r.long_name == name)
|
||||
}
|
||||
|
||||
pub fn get_routes_serving_stop(&self, stop: BusStopID) -> Vec<&BusRoute> {
|
||||
pub fn get_routes_serving_stop(&self, stop: TransitStopID) -> Vec<&TransitRoute> {
|
||||
let mut routes = Vec::new();
|
||||
for r in &self.bus_routes {
|
||||
for r in &self.transit_routes {
|
||||
if r.stops.contains(&stop) {
|
||||
routes.push(r);
|
||||
}
|
||||
@ -603,7 +604,7 @@ impl Map {
|
||||
&self,
|
||||
start: Position,
|
||||
end: Position,
|
||||
) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)> {
|
||||
) -> Option<(TransitStopID, Option<TransitStopID>, TransitRouteID)> {
|
||||
assert!(!self.pathfinder_dirty);
|
||||
self.pathfinder.should_use_transit(self, start, end)
|
||||
}
|
||||
@ -663,10 +664,10 @@ impl Map {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn find_br(&self, id: osm::RelationID) -> Option<BusRouteID> {
|
||||
for br in self.all_bus_routes() {
|
||||
if br.osm_rel_id == id {
|
||||
return Some(br.id);
|
||||
pub fn find_tr(&self, id: osm::RelationID) -> Option<TransitRouteID> {
|
||||
for tr in self.all_transit_routes() {
|
||||
if tr.osm_rel_id == id {
|
||||
return Some(tr.id);
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -691,9 +692,9 @@ impl Map {
|
||||
self.buildings[b.0].bldg_type = bldg_type;
|
||||
}
|
||||
|
||||
pub fn hack_override_orig_spawn_times(&mut self, br: BusRouteID, times: Vec<Time>) {
|
||||
self.bus_routes[br.0].orig_spawn_times = times.clone();
|
||||
self.bus_routes[br.0].spawn_times = times;
|
||||
pub fn hack_override_orig_spawn_times(&mut self, br: TransitRouteID, times: Vec<Time>) {
|
||||
self.transit_routes[br.0].orig_spawn_times = times.clone();
|
||||
self.transit_routes[br.0].spawn_times = times;
|
||||
}
|
||||
|
||||
pub fn hack_add_area(&mut self, area_type: AreaType, polygon: Polygon, osm_tags: Tags) {
|
||||
@ -890,12 +891,12 @@ impl Map {
|
||||
timer,
|
||||
);
|
||||
|
||||
// Remove all bus routes, since we remove that pathfinder
|
||||
self.bus_stops.clear();
|
||||
self.bus_routes.clear();
|
||||
// Remove all routes, since we remove that pathfinder
|
||||
self.transit_stops.clear();
|
||||
self.transit_routes.clear();
|
||||
for r in &mut self.roads {
|
||||
for l in &mut r.lanes {
|
||||
l.bus_stops.clear();
|
||||
l.transit_stops.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,8 @@ use abstutil::Tags;
|
||||
use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
|
||||
|
||||
use crate::{
|
||||
osm, BusStopID, DirectedRoadID, Direction, DrivingSide, IntersectionID, Map, MapConfig, Road,
|
||||
RoadID, RoadSideID, SideOfRoad, TurnType,
|
||||
osm, DirectedRoadID, Direction, DrivingSide, IntersectionID, Map, MapConfig, Road, RoadID,
|
||||
RoadSideID, SideOfRoad, TransitStopID, TurnType,
|
||||
};
|
||||
|
||||
/// From some manually audited cases in Seattle, the length of parallel street parking spots is a
|
||||
@ -248,7 +248,7 @@ pub struct Lane {
|
||||
pub dst_i: IntersectionID,
|
||||
|
||||
/// Meaningless order
|
||||
pub bus_stops: BTreeSet<BusStopID>,
|
||||
pub transit_stops: BTreeSet<TransitStopID>,
|
||||
|
||||
/// {Cars, bikes} trying to start or end here might not be able to reach most lanes in the
|
||||
/// graph, because this is near a border.
|
||||
|
@ -1,7 +1,6 @@
|
||||
pub mod area;
|
||||
pub mod block;
|
||||
pub mod building;
|
||||
pub mod bus_stop;
|
||||
pub mod intersection;
|
||||
pub mod lane;
|
||||
pub mod movement;
|
||||
@ -9,5 +8,6 @@ pub mod parking_lot;
|
||||
pub mod road;
|
||||
pub mod stop_signs;
|
||||
pub mod traffic_signals;
|
||||
pub mod transit;
|
||||
pub mod turn;
|
||||
pub mod zone;
|
||||
|
@ -10,8 +10,8 @@ use geom::{Distance, PolyLine, Polygon, Speed};
|
||||
|
||||
use crate::raw::{OriginalRoad, RestrictionType};
|
||||
use crate::{
|
||||
osm, AccessRestrictions, BusStopID, DrivingSide, IntersectionID, Lane, LaneID, LaneSpec,
|
||||
LaneType, Map, PathConstraints, Zone,
|
||||
osm, AccessRestrictions, DrivingSide, IntersectionID, Lane, LaneID, LaneSpec, LaneType, Map,
|
||||
PathConstraints, TransitStopID, Zone,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
@ -412,10 +412,10 @@ impl Road {
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn all_bus_stops(&self) -> Vec<BusStopID> {
|
||||
pub fn all_transit_stops(&self) -> Vec<TransitStopID> {
|
||||
self.lanes
|
||||
.iter()
|
||||
.flat_map(|l| l.bus_stops.iter())
|
||||
.flat_map(|l| l.transit_stops.iter())
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
@ -581,7 +581,7 @@ impl Road {
|
||||
dst_i,
|
||||
lane_type: lane.lt,
|
||||
dir: lane.dir,
|
||||
bus_stops: BTreeSet::new(),
|
||||
transit_stops: BTreeSet::new(),
|
||||
driving_blackhole: false,
|
||||
biking_blackhole: false,
|
||||
});
|
||||
|
@ -1,6 +1,4 @@
|
||||
//! Bus stops and routes.
|
||||
// TODO Rename public transit -- these also cover light rail now.
|
||||
// TODO No code creates any of these structures right now.
|
||||
//! Public transit stops and routes.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@ -12,21 +10,21 @@ use geom::Time;
|
||||
use crate::{osm, LaneID, Map, PathConstraints, PathRequest, Position};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct BusStopID {
|
||||
pub struct TransitStopID {
|
||||
pub sidewalk: LaneID,
|
||||
/// As long as this is unique per lane, this value is otherwise meaningless. Not contiguous or
|
||||
/// ordered in any way.
|
||||
pub(crate) idx: usize,
|
||||
}
|
||||
|
||||
impl fmt::Display for BusStopID {
|
||||
impl fmt::Display for TransitStopID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "BusStopID({0}, {1})", self.sidewalk, self.idx)
|
||||
write!(f, "TransitStopID({0}, {1})", self.sidewalk, self.idx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct BusRouteID(
|
||||
pub struct TransitRouteID(
|
||||
#[serde(
|
||||
serialize_with = "serialize_usize",
|
||||
deserialize_with = "deserialize_usize"
|
||||
@ -34,31 +32,31 @@ pub struct BusRouteID(
|
||||
pub usize,
|
||||
);
|
||||
|
||||
impl fmt::Display for BusRouteID {
|
||||
impl fmt::Display for TransitRouteID {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "BusRoute #{}", self.0)
|
||||
write!(f, "TransitRoute #{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
pub struct BusStop {
|
||||
pub id: BusStopID,
|
||||
pub struct TransitStop {
|
||||
pub id: TransitStopID,
|
||||
pub name: String,
|
||||
/// These may be on different roads entirely, like for light rail platforms.
|
||||
pub driving_pos: Position,
|
||||
pub sidewalk_pos: Position,
|
||||
/// If it's both, train overrides bus
|
||||
/// If false, only buses serve this stop
|
||||
pub is_train_stop: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct BusRoute {
|
||||
pub id: BusRouteID,
|
||||
pub full_name: String,
|
||||
pub struct TransitRoute {
|
||||
pub id: TransitRouteID,
|
||||
pub long_name: String,
|
||||
pub short_name: String,
|
||||
pub gtfs_trip_marker: Option<String>,
|
||||
pub osm_rel_id: osm::RelationID,
|
||||
pub stops: Vec<BusStopID>,
|
||||
pub stops: Vec<TransitStopID>,
|
||||
/// May be a border or not. If not, is long enough for buses to spawn fully.
|
||||
pub start: LaneID,
|
||||
pub end_border: Option<LaneID>,
|
||||
@ -70,23 +68,23 @@ pub struct BusRoute {
|
||||
pub orig_spawn_times: Vec<Time>,
|
||||
}
|
||||
|
||||
impl BusRoute {
|
||||
impl TransitRoute {
|
||||
pub fn all_steps(&self, map: &Map) -> Vec<PathRequest> {
|
||||
let mut steps = vec![PathRequest::vehicle(
|
||||
Position::start(self.start),
|
||||
map.get_bs(self.stops[0]).driving_pos,
|
||||
map.get_ts(self.stops[0]).driving_pos,
|
||||
self.route_type,
|
||||
)];
|
||||
for pair in self.stops.windows(2) {
|
||||
steps.push(PathRequest::vehicle(
|
||||
map.get_bs(pair[0]).driving_pos,
|
||||
map.get_bs(pair[1]).driving_pos,
|
||||
map.get_ts(pair[0]).driving_pos,
|
||||
map.get_ts(pair[1]).driving_pos,
|
||||
self.route_type,
|
||||
));
|
||||
}
|
||||
if let Some(end) = self.end_border {
|
||||
steps.push(PathRequest::vehicle(
|
||||
map.get_bs(*self.stops.last().unwrap()).driving_pos,
|
||||
map.get_ts(*self.stops.last().unwrap()).driving_pos,
|
||||
Position::end(end, map),
|
||||
self.route_type,
|
||||
));
|
@ -11,8 +11,8 @@ use crate::pathfind::engine::CreateEngine;
|
||||
use crate::pathfind::vehicles::VehiclePathfinder;
|
||||
use crate::pathfind::walking::SidewalkPathfinder;
|
||||
use crate::{
|
||||
BusRouteID, BusStopID, DirectedRoadID, Map, PathConstraints, PathRequest, PathV2, Position,
|
||||
RoutingParams,
|
||||
DirectedRoadID, Map, PathConstraints, PathRequest, PathV2, Position, RoutingParams,
|
||||
TransitRouteID, TransitStopID,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -241,7 +241,7 @@ impl Pathfinder {
|
||||
map: &Map,
|
||||
start: Position,
|
||||
end: Position,
|
||||
) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)> {
|
||||
) -> Option<(TransitStopID, Option<TransitStopID>, TransitRouteID)> {
|
||||
self.walking_with_transit_graph
|
||||
.should_use_transit(map, start, end)
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ use crate::pathfind::vehicles::VehiclePathfinder;
|
||||
use crate::pathfind::zone_cost;
|
||||
use crate::pathfind::{round, unround};
|
||||
use crate::{
|
||||
BusRoute, BusRouteID, BusStopID, DirectedRoadID, IntersectionID, Map, MovementID,
|
||||
PathConstraints, PathRequest, PathStep, PathStepV2, PathV2, Position, TurnType,
|
||||
DirectedRoadID, IntersectionID, Map, MovementID, PathConstraints, PathRequest, PathStep,
|
||||
PathStepV2, PathV2, Position, TransitRoute, TransitRouteID, TransitStopID, TurnType,
|
||||
};
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
@ -29,9 +29,9 @@ pub struct SidewalkPathfinder {
|
||||
pub enum WalkingNode {
|
||||
/// false is src_i, true is dst_i
|
||||
SidewalkEndpoint(DirectedRoadID, bool),
|
||||
// TODO Lots of complexity below could be avoided by explicitly sticking BusRouteID here too.
|
||||
// TODO Lots of complexity below could be avoided by explicitly sticking TransitRouteID here too.
|
||||
// Worth it?
|
||||
RideBus(BusStopID),
|
||||
RideTransit(TransitStopID),
|
||||
LeaveMap(IntersectionID),
|
||||
}
|
||||
|
||||
@ -79,9 +79,9 @@ impl SidewalkPathfinder {
|
||||
}
|
||||
}
|
||||
if use_transit.is_some() {
|
||||
// Add a node for each bus stop.
|
||||
for bs in map.all_bus_stops().keys() {
|
||||
nodes.get_or_insert(WalkingNode::RideBus(*bs));
|
||||
// Add a node for each stop.
|
||||
for ts in map.all_transit_stops().keys() {
|
||||
nodes.get_or_insert(WalkingNode::RideTransit(*ts));
|
||||
}
|
||||
for i in map.all_outgoing_borders() {
|
||||
// We could filter for those with sidewalks, but eh
|
||||
@ -134,14 +134,14 @@ impl SidewalkPathfinder {
|
||||
Some(PathV2::new(steps, req, cost, Vec::new()))
|
||||
}
|
||||
|
||||
/// Attempt the pathfinding and see if we should ride a bus. If so, says (stop1, optional stop
|
||||
/// 2, route). If there's no stop 2, then ride the bus off the border.
|
||||
/// Attempt the pathfinding and see if we should ride public transit. If so, says (stop1,
|
||||
/// optional stop 2, route). If there's no stop 2, then ride transit off the border.
|
||||
pub fn should_use_transit(
|
||||
&self,
|
||||
map: &Map,
|
||||
start: Position,
|
||||
end: Position,
|
||||
) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)> {
|
||||
) -> Option<(TransitStopID, Option<TransitStopID>, TransitRouteID)> {
|
||||
if matches!(self.engine, PathfindEngine::Empty) {
|
||||
return None;
|
||||
}
|
||||
@ -166,10 +166,10 @@ impl SidewalkPathfinder {
|
||||
|
||||
let mut first_stop = None;
|
||||
let mut last_stop = None;
|
||||
let mut possible_routes: Vec<&BusRoute> = Vec::new();
|
||||
let mut possible_routes: Vec<&TransitRoute> = Vec::new();
|
||||
for n in &nodes {
|
||||
match n {
|
||||
WalkingNode::RideBus(stop2) => {
|
||||
WalkingNode::RideTransit(stop2) => {
|
||||
if let Some(stop1) = first_stop {
|
||||
// Keep riding the same route?
|
||||
// We need to do this check, because some transfers might be instantaneous
|
||||
@ -334,9 +334,9 @@ fn transit_input_graph(
|
||||
train_graph: &VehiclePathfinder,
|
||||
) {
|
||||
let max_speed = Some(crate::MAX_WALKING_SPEED);
|
||||
// Connect bus stops with both sidewalk endpoints, using the appropriate distance.
|
||||
for stop in map.all_bus_stops().values() {
|
||||
let ride_bus = nodes.get(WalkingNode::RideBus(stop.id));
|
||||
// Connect stops with both sidewalk endpoints, using the appropriate distance.
|
||||
for stop in map.all_transit_stops().values() {
|
||||
let ride_transit = nodes.get(WalkingNode::RideTransit(stop.id));
|
||||
let lane = map.get_l(stop.sidewalk_pos.lane());
|
||||
for (endpt, step) in [
|
||||
(false, PathStep::Lane(lane.id)),
|
||||
@ -348,24 +348,24 @@ fn transit_input_graph(
|
||||
stop.sidewalk_pos.dist_along()
|
||||
};
|
||||
let cost = dist / step.max_speed_along(max_speed, PathConstraints::Pedestrian, map);
|
||||
// Add some extra penalty to using a bus stop. Otherwise a path might try to pass
|
||||
// through it uselessly.
|
||||
// Add some extra penalty to using a stop. Otherwise a path might try to pass through
|
||||
// it uselessly.
|
||||
let penalty = Duration::seconds(10.0);
|
||||
let sidewalk = nodes.get(WalkingNode::SidewalkEndpoint(
|
||||
lane.get_directed_parent(),
|
||||
endpt,
|
||||
));
|
||||
input_graph.add_edge(sidewalk, ride_bus, round(cost + penalty));
|
||||
input_graph.add_edge(ride_bus, sidewalk, round(cost + penalty));
|
||||
input_graph.add_edge(sidewalk, ride_transit, round(cost + penalty));
|
||||
input_graph.add_edge(ride_transit, sidewalk, round(cost + penalty));
|
||||
}
|
||||
}
|
||||
|
||||
// Connect each adjacent stop along a route, with the cost based on how long it'll take a
|
||||
// bus to drive between the stops. Optimistically assume no waiting time at a stop.
|
||||
for route in map.all_bus_routes() {
|
||||
// transit vehicle to drive between the stops. Optimistically assume no waiting time at a stop.
|
||||
for route in map.all_transit_routes() {
|
||||
// TODO Also plug in border starts
|
||||
for pair in route.stops.windows(2) {
|
||||
let (stop1, stop2) = (map.get_bs(pair[0]), map.get_bs(pair[1]));
|
||||
let (stop1, stop2) = (map.get_ts(pair[0]), map.get_ts(pair[1]));
|
||||
let req = PathRequest::vehicle(stop1.driving_pos, stop2.driving_pos, route.route_type);
|
||||
let maybe_driving_cost = match route.route_type {
|
||||
PathConstraints::Bus => bus_graph.pathfind(req, map).map(|p| p.get_cost()),
|
||||
@ -374,20 +374,20 @@ fn transit_input_graph(
|
||||
};
|
||||
if let Some(driving_cost) = maybe_driving_cost {
|
||||
input_graph.add_edge(
|
||||
nodes.get(WalkingNode::RideBus(stop1.id)),
|
||||
nodes.get(WalkingNode::RideBus(stop2.id)),
|
||||
nodes.get(WalkingNode::RideTransit(stop1.id)),
|
||||
nodes.get(WalkingNode::RideTransit(stop2.id)),
|
||||
round(driving_cost),
|
||||
);
|
||||
} else {
|
||||
panic!(
|
||||
"No bus route from {} to {} now for {}! Prevent this edit",
|
||||
stop1.driving_pos, stop2.driving_pos, route.full_name,
|
||||
"No transit route from {} to {} now for {}! Prevent this edit",
|
||||
stop1.driving_pos, stop2.driving_pos, route.long_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(l) = route.end_border {
|
||||
let stop1 = map.get_bs(*route.stops.last().unwrap());
|
||||
let stop1 = map.get_ts(*route.stops.last().unwrap());
|
||||
let req =
|
||||
PathRequest::vehicle(stop1.driving_pos, Position::end(l, map), route.route_type);
|
||||
let maybe_driving_cost = match route.route_type {
|
||||
@ -398,14 +398,14 @@ fn transit_input_graph(
|
||||
if let Some(driving_cost) = maybe_driving_cost {
|
||||
let border = map.get_i(map.get_l(l).dst_i);
|
||||
input_graph.add_edge(
|
||||
nodes.get(WalkingNode::RideBus(stop1.id)),
|
||||
nodes.get(WalkingNode::RideTransit(stop1.id)),
|
||||
nodes.get(WalkingNode::LeaveMap(border.id)),
|
||||
round(driving_cost),
|
||||
);
|
||||
} else {
|
||||
panic!(
|
||||
"No bus route from {} to end of {} now for {}! Prevent this edit",
|
||||
stop1.driving_pos, l, route.full_name,
|
||||
"No transit route from {} to end of {} now for {}! Prevent this edit",
|
||||
stop1.driving_pos, l, route.long_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -419,12 +419,12 @@ fn walking_path_to_steps(path: Vec<WalkingNode>, map: &Map) -> Vec<PathStepV2> {
|
||||
for pair in path.windows(2) {
|
||||
let (r1, r1_endpt) = match pair[0] {
|
||||
WalkingNode::SidewalkEndpoint(r, endpt) => (r, endpt),
|
||||
WalkingNode::RideBus(_) => unreachable!(),
|
||||
WalkingNode::RideTransit(_) => unreachable!(),
|
||||
WalkingNode::LeaveMap(_) => unreachable!(),
|
||||
};
|
||||
let r2 = match pair[1] {
|
||||
WalkingNode::SidewalkEndpoint(r, _) => r,
|
||||
WalkingNode::RideBus(_) => unreachable!(),
|
||||
WalkingNode::RideTransit(_) => unreachable!(),
|
||||
WalkingNode::LeaveMap(_) => unreachable!(),
|
||||
};
|
||||
|
||||
@ -490,8 +490,8 @@ fn walking_path_to_steps(path: Vec<WalkingNode>, map: &Map) -> Vec<PathStepV2> {
|
||||
// TODO Do we even need this at all?
|
||||
fn one_step_walking_path(req: PathRequest, map: &Map) -> PathV2 {
|
||||
let l = req.start.lane();
|
||||
// Weird case, but it can happen for walking from a building path to a bus stop that're
|
||||
// actually at the same spot.
|
||||
// Weird case, but it can happen for walking from a building path to a stop that're actually at
|
||||
// the same spot.
|
||||
let (step_v2, step_v1) = if req.start.dist_along() <= req.end.dist_along() {
|
||||
(
|
||||
PathStepV2::Along(map.get_l(l).get_directed_parent()),
|
||||
|
@ -8,8 +8,8 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::Counter;
|
||||
use geom::{Duration, Time};
|
||||
use map_model::{
|
||||
BusRouteID, BusStopID, CompressedMovementID, IntersectionID, LaneID, Map, MovementID,
|
||||
ParkingLotID, Path, PathRequest, RoadID, Traversable, TurnID,
|
||||
CompressedMovementID, IntersectionID, LaneID, Map, MovementID, ParkingLotID, Path, PathRequest,
|
||||
RoadID, TransitRouteID, TransitStopID, Traversable, TurnID,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -38,10 +38,10 @@ pub struct Analytics {
|
||||
pub demand: BTreeMap<MovementID, usize>,
|
||||
|
||||
// TODO Reconsider this one
|
||||
pub bus_arrivals: Vec<(Time, CarID, BusRouteID, BusStopID)>,
|
||||
pub bus_arrivals: Vec<(Time, CarID, TransitRouteID, TransitStopID)>,
|
||||
/// For each passenger boarding, how long did they wait at the stop?
|
||||
pub passengers_boarding: BTreeMap<BusStopID, Vec<(Time, BusRouteID, Duration)>>,
|
||||
pub passengers_alighting: BTreeMap<BusStopID, Vec<(Time, BusRouteID)>>,
|
||||
pub passengers_boarding: BTreeMap<TransitStopID, Vec<(Time, TransitRouteID, Duration)>>,
|
||||
pub passengers_alighting: BTreeMap<TransitStopID, Vec<(Time, TransitRouteID)>>,
|
||||
|
||||
pub started_trips: BTreeMap<TripID, Time>,
|
||||
/// Finish time, ID, mode, trip duration if successful (or None if cancelled)
|
||||
|
@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use geom::Duration;
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, Map, Path, PathRequest, Traversable,
|
||||
TurnID,
|
||||
BuildingID, IntersectionID, LaneID, Map, Path, PathRequest, TransitRouteID, TransitStopID,
|
||||
Traversable, TurnID,
|
||||
};
|
||||
|
||||
use crate::{AgentID, CarID, ParkingSpot, PedestrianID, PersonID, Problem, TripID, TripMode};
|
||||
@ -21,11 +21,11 @@ pub enum Event {
|
||||
CarReachedParkingSpot(CarID, ParkingSpot),
|
||||
CarLeftParkingSpot(CarID, ParkingSpot),
|
||||
|
||||
BusArrivedAtStop(CarID, BusRouteID, BusStopID),
|
||||
BusDepartedFromStop(CarID, BusRouteID, BusStopID),
|
||||
BusArrivedAtStop(CarID, TransitRouteID, TransitStopID),
|
||||
BusDepartedFromStop(CarID, TransitRouteID, TransitStopID),
|
||||
/// How long waiting at the stop?
|
||||
PassengerBoardsTransit(PersonID, CarID, BusRouteID, BusStopID, Duration),
|
||||
PassengerAlightsTransit(PersonID, CarID, BusRouteID, BusStopID),
|
||||
PassengerBoardsTransit(PersonID, CarID, TransitRouteID, TransitStopID, Duration),
|
||||
PassengerAlightsTransit(PersonID, CarID, TransitRouteID, TransitStopID),
|
||||
|
||||
PersonEntersBuilding(PersonID, BuildingID),
|
||||
PersonLeavesBuilding(PersonID, BuildingID),
|
||||
@ -75,9 +75,9 @@ pub enum TripPhaseType {
|
||||
Walking,
|
||||
Biking,
|
||||
Parking,
|
||||
WaitingForBus(BusRouteID, BusStopID),
|
||||
WaitingForBus(TransitRouteID, TransitStopID),
|
||||
/// What stop did they board at?
|
||||
RidingBus(BusRouteID, BusStopID, CarID),
|
||||
RidingBus(TransitRouteID, TransitStopID, CarID),
|
||||
Cancelled,
|
||||
Finished,
|
||||
DelayedStart,
|
||||
@ -91,9 +91,9 @@ impl TripPhaseType {
|
||||
TripPhaseType::Biking => "Biking".to_string(),
|
||||
TripPhaseType::Parking => "Parking".to_string(),
|
||||
TripPhaseType::WaitingForBus(r, _) => {
|
||||
format!("Waiting for bus {}", map.get_br(r).full_name)
|
||||
format!("Waiting for transit route {}", map.get_tr(r).long_name)
|
||||
}
|
||||
TripPhaseType::RidingBus(r, _, _) => format!("Riding bus {}", map.get_br(r).full_name),
|
||||
TripPhaseType::RidingBus(r, _, _) => format!("Riding route {}", map.get_tr(r).long_name),
|
||||
TripPhaseType::Cancelled => "Trip was cancelled due to some bug".to_string(),
|
||||
TripPhaseType::Finished => "Trip finished".to_string(),
|
||||
TripPhaseType::DelayedStart => "Delayed by a previous trip taking too long".to_string(),
|
||||
|
@ -24,8 +24,8 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::{deserialize_usize, serialize_usize};
|
||||
use geom::{Distance, Speed, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, Path,
|
||||
PathConstraints, Position,
|
||||
BuildingID, IntersectionID, LaneID, Map, ParkingLotID, Path, PathConstraints, Position,
|
||||
TransitRouteID, TransitStopID,
|
||||
};
|
||||
|
||||
pub use crate::render::{
|
||||
@ -423,7 +423,7 @@ pub(crate) enum SidewalkPOI {
|
||||
/// Don't actually know where this goes yet!
|
||||
DeferredParkingSpot,
|
||||
Building(BuildingID),
|
||||
BusStop(BusStopID),
|
||||
TransitStop(TransitStopID),
|
||||
Border(IntersectionID),
|
||||
/// The bikeable position
|
||||
BikeRack(Position),
|
||||
@ -467,10 +467,10 @@ impl SidewalkSpot {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn bus_stop(stop: BusStopID, map: &Map) -> SidewalkSpot {
|
||||
pub fn bus_stop(stop: TransitStopID, map: &Map) -> SidewalkSpot {
|
||||
SidewalkSpot {
|
||||
sidewalk_pos: map.get_bs(stop).sidewalk_pos,
|
||||
connection: SidewalkPOI::BusStop(stop),
|
||||
sidewalk_pos: map.get_ts(stop).sidewalk_pos,
|
||||
connection: SidewalkPOI::TransitStop(stop),
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ pub(crate) struct CreateCar {
|
||||
pub maybe_parked_car: Option<ParkedCar>,
|
||||
/// None for buses
|
||||
pub trip_and_person: Option<(TripID, PersonID)>,
|
||||
pub maybe_route: Option<BusRouteID>,
|
||||
pub maybe_route: Option<TransitRouteID>,
|
||||
}
|
||||
|
||||
impl CreateCar {
|
||||
|
@ -131,14 +131,14 @@ impl Scenario {
|
||||
timer.start(format!("Instantiating {}", self.scenario_name));
|
||||
|
||||
if let Some(ref routes) = self.only_seed_buses {
|
||||
for route in map.all_bus_routes() {
|
||||
if routes.contains(&route.full_name) {
|
||||
for route in map.all_transit_routes() {
|
||||
if routes.contains(&route.long_name) {
|
||||
sim.seed_bus_route(route);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// All of them
|
||||
for route in map.all_bus_routes() {
|
||||
for route in map.all_transit_routes() {
|
||||
sim.seed_bus_route(route);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use geom::Pt2D;
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, IntersectionID, Map, PathConstraints, PathRequest, Position,
|
||||
BuildingID, IntersectionID, Map, PathConstraints, PathRequest, Position, TransitRouteID,
|
||||
TransitStopID,
|
||||
};
|
||||
|
||||
use crate::{CarID, DrivingGoal, SidewalkSpot, TripLeg, TripMode, VehicleType, SPAWN_DIST};
|
||||
@ -53,9 +54,9 @@ pub(crate) enum TripSpec {
|
||||
UsingTransit {
|
||||
start: SidewalkSpot,
|
||||
goal: SidewalkSpot,
|
||||
route: BusRouteID,
|
||||
stop1: BusStopID,
|
||||
maybe_stop2: Option<BusStopID>,
|
||||
route: TransitRouteID,
|
||||
stop1: TransitStopID,
|
||||
maybe_stop2: Option<TransitStopID>,
|
||||
},
|
||||
}
|
||||
|
||||
@ -107,7 +108,7 @@ impl TripSpec {
|
||||
// TODO The legs are a lie. Since the trip gets cancelled, this doesn't matter.
|
||||
// I'm not going to bother doing better because I think TripLeg will get
|
||||
// revamped soon anyway.
|
||||
legs.push(TripLeg::RideBus(BusRouteID(0), None));
|
||||
legs.push(TripLeg::RideBus(TransitRouteID(0), None));
|
||||
}
|
||||
TripSpec::UsingParkedCar { car, goal, .. } => {
|
||||
legs.push(TripLeg::Walk(SidewalkSpot::deferred_parking_spot()));
|
||||
|
@ -292,7 +292,7 @@ impl Car {
|
||||
|| self.vehicle.vehicle_type == VehicleType::Train
|
||||
{
|
||||
Some(
|
||||
map.get_br(transit.bus_route(self.vehicle.id))
|
||||
map.get_tr(transit.bus_route(self.vehicle.id))
|
||||
.short_name
|
||||
.clone(),
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::{deserialize_multimap, serialize_multimap, FixedMap, IndexableKey, MultiMap};
|
||||
use geom::{Distance, Duration, Line, PolyLine, Speed, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, DrivingSide, Map, ParkingLotID, Path, PathConstraints, PathStep,
|
||||
BuildingID, DrivingSide, Map, ParkingLotID, Path, PathConstraints, PathStep, TransitRouteID,
|
||||
Traversable, SIDEWALK_THICKNESS,
|
||||
};
|
||||
|
||||
@ -169,7 +169,7 @@ impl WalkingSimState {
|
||||
ctx.scheduler
|
||||
.push(ped.state.get_end_time(), Command::UpdatePed(ped.id));
|
||||
}
|
||||
SidewalkPOI::BusStop(stop) => {
|
||||
SidewalkPOI::TransitStop(stop) => {
|
||||
if let Some(route) = trips.ped_reached_bus_stop(
|
||||
now,
|
||||
ped.id,
|
||||
@ -368,7 +368,7 @@ impl WalkingSimState {
|
||||
let time_spent_waiting = p.state.time_spent_waiting(now);
|
||||
// TODO Incorporate this somewhere
|
||||
/*if let PedState::WaitingForBus(r, _) = p.state {
|
||||
extra.push(format!("Waiting for bus {}", map.get_br(r).name));
|
||||
extra.push(format!("Waiting for bus {}", map.get_tr(r).name));
|
||||
}*/
|
||||
|
||||
let current_state_dist = match p.state {
|
||||
@ -577,7 +577,7 @@ impl WalkingSimState {
|
||||
SidewalkPOI::ParkingSpot(_) | SidewalkPOI::DeferredParkingSpot => {
|
||||
cnts.walking_to_from_car += 1;
|
||||
}
|
||||
SidewalkPOI::BusStop(_) => {
|
||||
SidewalkPOI::TransitStop(_) => {
|
||||
cnts.walking_to_from_transit += 1;
|
||||
}
|
||||
SidewalkPOI::BikeRack(_) => {
|
||||
@ -587,7 +587,7 @@ impl WalkingSimState {
|
||||
SidewalkPOI::ParkingSpot(_) | SidewalkPOI::DeferredParkingSpot => {
|
||||
cnts.walking_to_from_car += 1;
|
||||
}
|
||||
SidewalkPOI::BusStop(_) => {
|
||||
SidewalkPOI::TransitStop(_) => {
|
||||
cnts.walking_to_from_transit += 1;
|
||||
}
|
||||
SidewalkPOI::BikeRack(_) => {
|
||||
@ -850,7 +850,7 @@ enum PedState {
|
||||
EnteringParkingLot(ParkingLotID, TimeInterval),
|
||||
StartingToBike(SidewalkSpot, Line, TimeInterval),
|
||||
FinishingBiking(SidewalkSpot, Line, TimeInterval),
|
||||
WaitingForBus(BusRouteID, Time),
|
||||
WaitingForBus(TransitRouteID, Time),
|
||||
}
|
||||
|
||||
impl PedState {
|
||||
|
@ -5,7 +5,7 @@ use rand_xorshift::XorShiftRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use geom::{Duration, Time};
|
||||
use map_model::{BuildingID, BusStopID};
|
||||
use map_model::{BuildingID, TransitStopID};
|
||||
|
||||
use crate::pandemic::{AnyTime, State};
|
||||
use crate::{CarID, Event, Person, PersonID, Scheduler, TripPhaseType};
|
||||
@ -19,7 +19,7 @@ pub struct PandemicModel {
|
||||
pop: BTreeMap<PersonID, State>,
|
||||
|
||||
bldgs: SharedSpace<BuildingID>,
|
||||
bus_stops: SharedSpace<BusStopID>,
|
||||
bus_stops: SharedSpace<TransitStopID>,
|
||||
buses: SharedSpace<CarID>,
|
||||
person_to_bus: BTreeMap<PersonID, CarID>,
|
||||
|
||||
|
@ -52,7 +52,7 @@ enum Goal {
|
||||
BikeThenStop {
|
||||
goal: SidewalkSpot,
|
||||
},
|
||||
FollowBusRoute {
|
||||
FollowTransitRoute {
|
||||
end_dist: Distance,
|
||||
},
|
||||
}
|
||||
@ -108,7 +108,7 @@ impl Router {
|
||||
|
||||
pub fn follow_bus_route(owner: CarID, path: Path) -> Router {
|
||||
Router {
|
||||
goal: Goal::FollowBusRoute {
|
||||
goal: Goal::FollowTransitRoute {
|
||||
end_dist: path.get_req().end.dist_along(),
|
||||
},
|
||||
path,
|
||||
@ -143,7 +143,7 @@ impl Router {
|
||||
..
|
||||
} => stuck_end_dist.unwrap_or_else(|| spot.unwrap().1),
|
||||
Goal::BikeThenStop { ref goal } => goal.sidewalk_pos.dist_along(),
|
||||
Goal::FollowBusRoute { end_dist } => end_dist,
|
||||
Goal::FollowTransitRoute { end_dist } => end_dist,
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,7 +325,7 @@ impl Router {
|
||||
None
|
||||
}
|
||||
}
|
||||
Goal::FollowBusRoute { end_dist } => {
|
||||
Goal::FollowTransitRoute { end_dist } => {
|
||||
if end_dist == front {
|
||||
Some(ActionAtEnd::BusAtStop)
|
||||
} else {
|
||||
|
@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use abstutil::Counter;
|
||||
use geom::{Duration, Histogram, Time};
|
||||
use map_model::{BusRouteID, IntersectionID};
|
||||
use map_model::{IntersectionID, TransitRouteID};
|
||||
|
||||
use crate::{
|
||||
pandemic, AgentID, CarID, CreateCar, CreatePedestrian, PedestrianID, StartTripArgs, TripID,
|
||||
@ -26,7 +26,7 @@ pub(crate) enum Command {
|
||||
Callback(Duration),
|
||||
Pandemic(pandemic::Cmd),
|
||||
/// The Time is redundant, just used to dedupe commands
|
||||
StartBus(BusRouteID, Time),
|
||||
StartBus(TransitRouteID, Time),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
@ -80,7 +80,7 @@ enum CommandType {
|
||||
Intersection(IntersectionID),
|
||||
Callback,
|
||||
Pandemic(pandemic::Cmd),
|
||||
StartBus(BusRouteID, Time),
|
||||
StartBus(TransitRouteID, Time),
|
||||
}
|
||||
|
||||
/// A more compressed form of CommandType, just used for keeping stats on event processing.
|
||||
|
@ -13,8 +13,8 @@ use abstio::{CityName, MapName};
|
||||
use abstutil::{prettyprint_usize, serialized_size_bytes, Timer};
|
||||
use geom::{Distance, Duration, Speed, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRoute, IntersectionID, LaneID, Map, ParkingLotID, Path, PathConstraints,
|
||||
PathRequest, Position, Traversable,
|
||||
BuildingID, IntersectionID, LaneID, Map, ParkingLotID, Path, PathConstraints, PathRequest,
|
||||
Position, TransitRoute, Traversable,
|
||||
};
|
||||
|
||||
pub use self::queries::{AgentProperties, DelayCause};
|
||||
@ -323,13 +323,13 @@ impl Sim {
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn seed_bus_route(&mut self, route: &BusRoute) {
|
||||
pub(crate) fn seed_bus_route(&mut self, route: &TransitRoute) {
|
||||
for t in &route.spawn_times {
|
||||
self.scheduler.push(*t, Command::StartBus(route.id, *t));
|
||||
}
|
||||
}
|
||||
|
||||
fn start_bus(&mut self, route: &BusRoute, map: &Map) {
|
||||
fn start_bus(&mut self, route: &TransitRoute, map: &Map) {
|
||||
// Spawn one bus for the first leg.
|
||||
let path = self.transit.create_empty_route(route, map);
|
||||
|
||||
@ -627,7 +627,7 @@ impl Sim {
|
||||
.handle_cmd(self.time, cmd, &mut self.scheduler);
|
||||
}
|
||||
Command::StartBus(r, _) => {
|
||||
self.start_bus(map.get_br(r), map);
|
||||
self.start_bus(map.get_tr(r), map);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use abstutil::Counter;
|
||||
use geom::{Distance, Duration, PolyLine, Pt2D, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, IntersectionID, Lane, LaneID, Map, Path, Position,
|
||||
BuildingID, IntersectionID, Lane, LaneID, Map, Path, Position, TransitRouteID, TransitStopID,
|
||||
Traversable, TurnID,
|
||||
};
|
||||
|
||||
@ -100,7 +100,7 @@ impl Sim {
|
||||
self.transit.get_passengers(car).len()
|
||||
}
|
||||
|
||||
pub fn bus_route_id(&self, maybe_bus: CarID) -> Option<BusRouteID> {
|
||||
pub fn bus_route_id(&self, maybe_bus: CarID) -> Option<TransitRouteID> {
|
||||
if maybe_bus.vehicle_type == VehicleType::Bus
|
||||
|| maybe_bus.vehicle_type == VehicleType::Train
|
||||
{
|
||||
@ -294,7 +294,7 @@ impl Sim {
|
||||
/// (bus, stop index it's coming from, percent to next stop, location)
|
||||
pub fn status_of_buses(
|
||||
&self,
|
||||
route: BusRouteID,
|
||||
route: TransitRouteID,
|
||||
map: &Map,
|
||||
) -> Vec<(CarID, Option<usize>, f64, Pt2D)> {
|
||||
let mut results = Vec::new();
|
||||
@ -381,8 +381,8 @@ impl Sim {
|
||||
|
||||
pub fn get_people_waiting_at_stop(
|
||||
&self,
|
||||
at: BusStopID,
|
||||
) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)> {
|
||||
at: TransitStopID,
|
||||
) -> &Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)> {
|
||||
self.transit.get_people_waiting_at_stop(at)
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap};
|
||||
use geom::Time;
|
||||
use map_model::{BusRoute, BusRouteID, BusStopID, Map, Path, PathRequest, Position};
|
||||
use map_model::{Map, Path, PathRequest, Position, TransitRoute, TransitRouteID, TransitStopID};
|
||||
|
||||
use crate::sim::Ctx;
|
||||
use crate::{
|
||||
@ -17,7 +17,7 @@ type StopIdx = usize;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
struct Stop {
|
||||
id: BusStopID,
|
||||
id: TransitStopID,
|
||||
driving_pos: Position,
|
||||
next_stop: Option<Path>,
|
||||
}
|
||||
@ -33,9 +33,9 @@ struct Route {
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
struct Bus {
|
||||
car: CarID,
|
||||
route: BusRouteID,
|
||||
route: TransitRouteID,
|
||||
/// Where does each passenger want to deboard?
|
||||
passengers: Vec<(PersonID, Option<BusStopID>)>,
|
||||
passengers: Vec<(PersonID, Option<TransitStopID>)>,
|
||||
state: BusState,
|
||||
}
|
||||
|
||||
@ -60,13 +60,14 @@ pub(crate) struct TransitSimState {
|
||||
serialize_with = "serialize_btreemap",
|
||||
deserialize_with = "deserialize_btreemap"
|
||||
)]
|
||||
routes: BTreeMap<BusRouteID, Route>,
|
||||
routes: BTreeMap<TransitRouteID, Route>,
|
||||
/// waiting at => (ped, route, bound for, started waiting)
|
||||
#[serde(
|
||||
serialize_with = "serialize_btreemap",
|
||||
deserialize_with = "deserialize_btreemap"
|
||||
)]
|
||||
peds_waiting: BTreeMap<BusStopID, Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)>>,
|
||||
peds_waiting:
|
||||
BTreeMap<TransitStopID, Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)>>,
|
||||
|
||||
events: Vec<Event>,
|
||||
}
|
||||
@ -75,8 +76,8 @@ impl TransitSimState {
|
||||
pub fn new(map: &Map) -> TransitSimState {
|
||||
// Keep this filled out always so get_passengers can return &Vec without a hassle
|
||||
let mut peds_waiting = BTreeMap::new();
|
||||
for bs in map.all_bus_stops().keys() {
|
||||
peds_waiting.insert(*bs, Vec::new());
|
||||
for ts in map.all_transit_stops().keys() {
|
||||
peds_waiting.insert(*ts, Vec::new());
|
||||
}
|
||||
|
||||
TransitSimState {
|
||||
@ -88,12 +89,12 @@ impl TransitSimState {
|
||||
}
|
||||
|
||||
/// Returns the path for the first leg.
|
||||
pub fn create_empty_route(&mut self, bus_route: &BusRoute, map: &Map) -> Path {
|
||||
pub fn create_empty_route(&mut self, bus_route: &TransitRoute, map: &Map) -> Path {
|
||||
self.routes.entry(bus_route.id).or_insert_with(|| {
|
||||
assert!(bus_route.stops.len() > 1);
|
||||
let mut stops = Vec::new();
|
||||
for (idx, stop1_id) in bus_route.stops.iter().enumerate() {
|
||||
let stop1 = map.get_bs(*stop1_id);
|
||||
let stop1 = map.get_ts(*stop1_id);
|
||||
if idx == bus_route.stops.len() - 1 {
|
||||
stops.push(Stop {
|
||||
id: stop1.id,
|
||||
@ -104,7 +105,7 @@ impl TransitSimState {
|
||||
}
|
||||
let req = PathRequest::vehicle(
|
||||
stop1.driving_pos,
|
||||
map.get_bs(bus_route.stops[idx + 1]).driving_pos,
|
||||
map.get_ts(bus_route.stops[idx + 1]).driving_pos,
|
||||
bus_route.route_type,
|
||||
);
|
||||
match map.pathfind(req) {
|
||||
@ -125,13 +126,13 @@ impl TransitSimState {
|
||||
}
|
||||
let start_req = PathRequest::vehicle(
|
||||
Position::start(bus_route.start),
|
||||
map.get_bs(bus_route.stops[0]).driving_pos,
|
||||
map.get_ts(bus_route.stops[0]).driving_pos,
|
||||
bus_route.route_type,
|
||||
);
|
||||
let start = map.pathfind(start_req).expect("no route to first stop");
|
||||
let end_at_border = if let Some(l) = bus_route.end_border {
|
||||
let req = PathRequest::vehicle(
|
||||
map.get_bs(*bus_route.stops.last().unwrap()).driving_pos,
|
||||
map.get_ts(*bus_route.stops.last().unwrap()).driving_pos,
|
||||
Position::end(l, map),
|
||||
bus_route.route_type,
|
||||
);
|
||||
@ -153,7 +154,7 @@ impl TransitSimState {
|
||||
self.routes[&bus_route.id].start.clone()
|
||||
}
|
||||
|
||||
pub fn bus_created(&mut self, bus: CarID, r: BusRouteID) {
|
||||
pub fn bus_created(&mut self, bus: CarID, r: TransitRouteID) {
|
||||
let route = self.routes.get_mut(&r).unwrap();
|
||||
route.active_vehicles.insert(bus);
|
||||
self.buses.insert(
|
||||
@ -223,9 +224,9 @@ impl TransitSimState {
|
||||
trip,
|
||||
person,
|
||||
Some(PathRequest::vehicle(
|
||||
ctx.map.get_bs(stop1).driving_pos,
|
||||
ctx.map.get_ts(stop1).driving_pos,
|
||||
if let Some(stop2) = maybe_stop2 {
|
||||
ctx.map.get_bs(stop2).driving_pos
|
||||
ctx.map.get_ts(stop2).driving_pos
|
||||
} else {
|
||||
self.routes[&route]
|
||||
.end_at_border
|
||||
@ -307,9 +308,9 @@ impl TransitSimState {
|
||||
ped: PedestrianID,
|
||||
trip: TripID,
|
||||
person: PersonID,
|
||||
stop1: BusStopID,
|
||||
route_id: BusRouteID,
|
||||
maybe_stop2: Option<BusStopID>,
|
||||
stop1: TransitStopID,
|
||||
route_id: TransitRouteID,
|
||||
maybe_stop2: Option<TransitStopID>,
|
||||
map: &Map,
|
||||
) -> Option<CarID> {
|
||||
assert!(Some(stop1) != maybe_stop2);
|
||||
@ -326,9 +327,9 @@ impl TransitSimState {
|
||||
trip,
|
||||
person,
|
||||
Some(PathRequest::vehicle(
|
||||
map.get_bs(stop1).driving_pos,
|
||||
map.get_ts(stop1).driving_pos,
|
||||
if let Some(stop2) = maybe_stop2 {
|
||||
map.get_bs(stop2).driving_pos
|
||||
map.get_ts(stop2).driving_pos
|
||||
} else {
|
||||
route.end_at_border.as_ref().unwrap().get_req().end
|
||||
},
|
||||
@ -358,16 +359,16 @@ impl TransitSimState {
|
||||
self.events.drain(..).collect()
|
||||
}
|
||||
|
||||
pub fn get_passengers(&self, bus: CarID) -> &Vec<(PersonID, Option<BusStopID>)> {
|
||||
pub fn get_passengers(&self, bus: CarID) -> &Vec<(PersonID, Option<TransitStopID>)> {
|
||||
&self.buses[&bus].passengers
|
||||
}
|
||||
|
||||
pub fn bus_route(&self, bus: CarID) -> BusRouteID {
|
||||
pub fn bus_route(&self, bus: CarID) -> TransitRouteID {
|
||||
self.buses[&bus].route
|
||||
}
|
||||
|
||||
/// also stop idx that the bus is coming from
|
||||
pub fn buses_for_route(&self, route: BusRouteID) -> Vec<(CarID, Option<usize>)> {
|
||||
pub fn buses_for_route(&self, route: TransitRouteID) -> Vec<(CarID, Option<usize>)> {
|
||||
if let Some(r) = self.routes.get(&route) {
|
||||
r.active_vehicles
|
||||
.iter()
|
||||
@ -411,8 +412,8 @@ impl TransitSimState {
|
||||
|
||||
pub fn get_people_waiting_at_stop(
|
||||
&self,
|
||||
at: BusStopID,
|
||||
) -> &Vec<(PedestrianID, BusRouteID, Option<BusStopID>, Time)> {
|
||||
at: TransitStopID,
|
||||
) -> &Vec<(PedestrianID, TransitRouteID, Option<TransitStopID>, Time)> {
|
||||
&self.peds_waiting[&at]
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Counter};
|
||||
use geom::{Distance, Duration, Speed, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, IntersectionID, Map, PathConstraints, PathRequest, Position,
|
||||
BuildingID, IntersectionID, Map, PathConstraints, PathRequest, Position, TransitRouteID,
|
||||
TransitStopID,
|
||||
};
|
||||
|
||||
use crate::sim::Ctx;
|
||||
@ -698,12 +699,12 @@ impl TripManager {
|
||||
&mut self,
|
||||
now: Time,
|
||||
ped: PedestrianID,
|
||||
stop: BusStopID,
|
||||
stop: TransitStopID,
|
||||
blocked_time: Duration,
|
||||
distance_crossed: Distance,
|
||||
ctx: &mut Ctx,
|
||||
transit: &mut TransitSimState,
|
||||
) -> Option<BusRouteID> {
|
||||
) -> Option<TransitRouteID> {
|
||||
let trip = &mut self.trips[self.active_trip_mode[&AgentID::Pedestrian(ped)].0];
|
||||
trip.total_blocked_time += blocked_time;
|
||||
trip.total_distance += distance_crossed;
|
||||
@ -1348,7 +1349,7 @@ pub(crate) enum TripLeg {
|
||||
/// A person may own many vehicles, so specify which they use
|
||||
Drive(CarID, DrivingGoal),
|
||||
/// Maybe get off at a stop, maybe ride off-map
|
||||
RideBus(BusRouteID, Option<BusStopID>),
|
||||
RideBus(TransitRouteID, Option<TransitStopID>),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy, PartialOrd, Ord)]
|
||||
|
@ -126,18 +126,18 @@ fn dump_route_goldenfile(map: &map_model::Map) -> Result<()> {
|
||||
map.get_name().as_filename()
|
||||
));
|
||||
let mut f = File::create(path)?;
|
||||
for br in map.all_bus_routes() {
|
||||
for tr in map.all_transit_routes() {
|
||||
writeln!(
|
||||
f,
|
||||
"{} from {} to {:?}",
|
||||
br.osm_rel_id, br.start, br.end_border
|
||||
tr.osm_rel_id, tr.start, tr.end_border
|
||||
)?;
|
||||
for bs in &br.stops {
|
||||
let bs = map.get_bs(*bs);
|
||||
for ts in &tr.stops {
|
||||
let ts = map.get_ts(*ts);
|
||||
writeln!(
|
||||
f,
|
||||
" {}: {} driving, {} sidewalk",
|
||||
bs.name, bs.driving_pos, bs.sidewalk_pos
|
||||
ts.name, ts.driving_pos, ts.sidewalk_pos
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user