Mechanical refactor: bus {stop, route} -> transit. #372

(Mostly renaming map_model code everywhere, not yet sim layer and above)
This commit is contained in:
Dustin Carlino 2021-12-02 13:22:34 +00:00
parent 82471dd9d6
commit 6e11c386ac
41 changed files with 368 additions and 355 deletions

View File

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

View File

@ -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 "));

View File

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

View File

@ -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(_) => {

View File

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

View File

@ -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);

View File

@ -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()),
)),
])),
)

View File

@ -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",

View File

@ -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 {

View File

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

View File

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

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

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

View File

@ -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;
}
}
}

View File

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

View File

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

View File

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

View File

@ -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();
}
}
}

View File

@ -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.

View File

@ -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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 {

View File

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

View File

@ -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()));

View File

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

View File

@ -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 {

View File

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

View File

@ -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 {

View File

@ -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.

View File

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

View File

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

View File

@ -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]
}

View File

@ -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)]

View File

@ -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
)?;
}
}