map_model/objects/
transit.rs1use std::fmt;
4
5use anyhow::Result;
6use serde::{Deserialize, Serialize};
7
8use abstutil::{deserialize_usize, serialize_usize};
9use geom::Time;
10
11use crate::{LaneID, Map, Path, PathConstraints, PathRequest, Position, RoadID};
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
14pub struct TransitStopID {
15 pub road: RoadID,
16 pub(crate) idx: usize,
19}
20
21impl fmt::Display for TransitStopID {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 write!(f, "TransitStopID({0}, {1})", self.road, self.idx)
24 }
25}
26
27#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
28pub struct TransitRouteID(
29 #[serde(
30 serialize_with = "serialize_usize",
31 deserialize_with = "deserialize_usize"
32 )]
33 pub usize,
34);
35
36impl fmt::Display for TransitRouteID {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f, "TransitRoute #{}", self.0)
39 }
40}
41
42#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
43pub struct TransitStop {
44 pub id: TransitStopID,
45 pub name: String,
46 pub gtfs_id: String,
47 pub driving_pos: Position,
49 pub sidewalk_pos: Position,
50 pub is_train_stop: bool,
52}
53
54#[derive(Serialize, Deserialize, Clone, Debug)]
55pub struct TransitRoute {
56 pub id: TransitRouteID,
57 pub long_name: String,
58 pub short_name: String,
59 pub gtfs_id: String,
60 pub stops: Vec<TransitStopID>,
61 pub start: LaneID,
64 pub end_border: Option<LaneID>,
66 pub route_type: PathConstraints,
67 pub spawn_times: Vec<Time>,
69 pub orig_spawn_times: Vec<Time>,
72}
73
74impl TransitRoute {
75 fn all_path_requests(&self, map: &Map) -> Vec<PathRequest> {
76 let mut steps = vec![PathRequest::vehicle(
77 Position::start(self.start),
78 map.get_ts(self.stops[0]).driving_pos,
79 self.route_type,
80 )];
81 for pair in self.stops.windows(2) {
82 steps.push(PathRequest::vehicle(
83 map.get_ts(pair[0]).driving_pos,
84 map.get_ts(pair[1]).driving_pos,
85 self.route_type,
86 ));
87 }
88
89 let last_stop_pos = map.get_ts(*self.stops.last().unwrap()).driving_pos;
90 if let Some(end) = self.end_border {
91 steps.push(PathRequest::vehicle(
92 last_stop_pos,
93 Position::end(end, map),
94 self.route_type,
95 ));
96 } else {
97 steps.push(PathRequest::vehicle(
99 last_stop_pos,
100 Position::end(last_stop_pos.lane(), map),
101 self.route_type,
102 ));
103 }
104 steps
105 }
106
107 pub fn all_paths(&self, map: &Map) -> Result<Vec<Path>> {
110 let mut paths = Vec::new();
111 for req in self.all_path_requests(map) {
112 if req.start.lane().road == req.end.lane().road
113 && req.start.dist_along() > req.end.dist_along()
114 {
115 bail!(
116 "Two consecutive stops are on the same road, but they travel backwards: {}",
117 req
118 );
119 }
120
121 let path = map.pathfind(req)?;
122 if path.is_empty() {
123 bail!("Empty path between stops: {}", path.get_req());
124 }
125 paths.push(path);
126 }
127
128 for pair in paths.windows(2) {
129 if pair[0].get_req().end != pair[1].get_req().start {
130 bail!(
131 "Transit route will warp from {} to {}",
132 pair[0].get_req().end,
133 pair[1].get_req().start
134 );
135 }
136 }
137
138 Ok(paths)
139 }
140
141 pub fn plural_noun(&self) -> &'static str {
142 if self.route_type == PathConstraints::Bus {
143 "buses"
144 } else {
145 "trains"
146 }
147 }
148}