1 use crate::raw::{DrivingSide, OriginalRoad, RawMap};
2 use crate::{
3     osm, Area, AreaID, Building, BuildingID, BuildingType, BusRoute, BusRouteID, BusStop,
4     BusStopID, ControlStopSign, ControlTrafficSignal, Intersection, IntersectionID, Lane, LaneID,
5     LaneType, Map, MapEdits, MovementID, OffstreetParking, ParkingLot, ParkingLotID, Path,
6     PathConstraints, PathRequest, Pathfinder, Position, Road, RoadID, Turn, TurnID, TurnType, Zone,
7 };
8 use abstutil::Timer;
9 use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Ring, Time};
10 use serde::{Deserialize, Serialize};
11 use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque};
12 
13 #[derive(Clone, Debug, Serialize, Deserialize)]
14 pub struct MapConfig {
15     // If true, driving happens on the right side of the road (USA). If false, on the left
16     // (Australia).
17     pub driving_side: DrivingSide,
18     pub bikes_can_use_bus_lanes: bool,
19 }
20 
21 impl Map {
new(path: String, timer: &mut Timer) -> Map22     pub fn new(path: String, timer: &mut Timer) -> Map {
23         if path.starts_with(&abstutil::path_all_maps()) {
24             match abstutil::maybe_read_binary(path.clone(), timer) {
25                 Ok(map) => {
26                     let map: Map = map;
27 
28                     if false {
29                         use abstutil::{prettyprint_usize, serialized_size_bytes};
30                         println!(
31                             "- {} roads: {} bytes",
32                             prettyprint_usize(map.roads.len()),
33                             prettyprint_usize(serialized_size_bytes(&map.roads))
34                         );
35                         println!(
36                             "- {} lanes: {} bytes",
37                             prettyprint_usize(map.lanes.len()),
38                             prettyprint_usize(serialized_size_bytes(&map.lanes))
39                         );
40                         println!(
41                             "- {} intersections: {} bytes",
42                             prettyprint_usize(map.intersections.len()),
43                             prettyprint_usize(serialized_size_bytes(&map.intersections))
44                         );
45                         println!(
46                             "- {} turns: {} bytes",
47                             prettyprint_usize(map.turns.len()),
48                             prettyprint_usize(serialized_size_bytes(&map.turns))
49                         );
50                         println!(
51                             "- {} buildings: {} bytes",
52                             prettyprint_usize(map.buildings.len()),
53                             prettyprint_usize(serialized_size_bytes(&map.buildings))
54                         );
55                         println!(
56                             "- {} areas: {} bytes",
57                             prettyprint_usize(map.areas.len()),
58                             prettyprint_usize(serialized_size_bytes(&map.areas))
59                         );
60                         println!(
61                             "- {} parking lots: {} bytes",
62                             prettyprint_usize(map.parking_lots.len()),
63                             prettyprint_usize(serialized_size_bytes(&map.parking_lots))
64                         );
65                         println!(
66                             "- {} zones: {} bytes",
67                             prettyprint_usize(map.zones.len()),
68                             prettyprint_usize(serialized_size_bytes(&map.zones))
69                         );
70                         // This is the partridge in the pear tree, I suppose
71                         println!(
72                             "- pathfinder: {} bytes",
73                             prettyprint_usize(serialized_size_bytes(&map.pathfinder))
74                         );
75                     }
76 
77                     return map;
78                 }
79                 Err(err) => {
80                     Map::corrupt_err(path, err);
81                     std::process::exit(1);
82                 }
83             }
84         }
85 
86         let raw: RawMap = if path.starts_with(&abstutil::path_all_raw_maps()) {
87             abstutil::read_binary(path, timer)
88         } else {
89             // Synthetic
90             abstutil::read_json(path, timer)
91         };
92         Map::create_from_raw(raw, true, timer)
93     }
94 
corrupt_err(path: String, err: std::io::Error)95     pub fn corrupt_err(path: String, err: std::io::Error) {
96         println!("\nError loading {}: {}\n", path, err);
97         if err.to_string().contains("No such file") {
98             println!(
99                 "{} is missing. You may need to do: cargo run --bin updater",
100                 path
101             );
102         } else {
103             println!(
104                 "{} is out-of-date. You may need to update your build (git pull) or download new \
105                  data (cargo run --bin updater). If this is a custom map, you need to import it \
106                  again.",
107                 path
108             );
109         }
110         println!(
111             "Check https://dabreegster.github.io/abstreet/howto/dev.html and file an issue if you \
112              have trouble."
113         );
114     }
115 
116     // Just for temporary std::mem::replace tricks.
blank() -> Map117     pub fn blank() -> Map {
118         Map {
119             roads: Vec::new(),
120             lanes: Vec::new(),
121             intersections: Vec::new(),
122             turns: BTreeMap::new(),
123             buildings: Vec::new(),
124             bus_stops: BTreeMap::new(),
125             bus_routes: Vec::new(),
126             areas: Vec::new(),
127             parking_lots: Vec::new(),
128             zones: Vec::new(),
129             boundary_polygon: Ring::must_new(vec![
130                 Pt2D::new(0.0, 0.0),
131                 Pt2D::new(1.0, 0.0),
132                 Pt2D::new(1.0, 1.0),
133                 Pt2D::new(0.0, 0.0),
134             ])
135             .to_polygon(),
136             stop_signs: BTreeMap::new(),
137             traffic_signals: BTreeMap::new(),
138             gps_bounds: GPSBounds::new(),
139             bounds: Bounds::new(),
140             config: MapConfig {
141                 driving_side: DrivingSide::Right,
142                 bikes_can_use_bus_lanes: true,
143             },
144             pathfinder: Pathfinder::Dijkstra,
145             pathfinder_dirty: false,
146             city_name: "blank city".to_string(),
147             name: "blank".to_string(),
148             edits: MapEdits::new(),
149         }
150     }
151 
all_roads(&self) -> &Vec<Road>152     pub fn all_roads(&self) -> &Vec<Road> {
153         &self.roads
154     }
155 
all_lanes(&self) -> &Vec<Lane>156     pub fn all_lanes(&self) -> &Vec<Lane> {
157         &self.lanes
158     }
159 
all_intersections(&self) -> &Vec<Intersection>160     pub fn all_intersections(&self) -> &Vec<Intersection> {
161         &self.intersections
162     }
163 
all_turns(&self) -> &BTreeMap<TurnID, Turn>164     pub fn all_turns(&self) -> &BTreeMap<TurnID, Turn> {
165         &self.turns
166     }
167 
all_buildings(&self) -> &Vec<Building>168     pub fn all_buildings(&self) -> &Vec<Building> {
169         &self.buildings
170     }
171 
all_areas(&self) -> &Vec<Area>172     pub fn all_areas(&self) -> &Vec<Area> {
173         &self.areas
174     }
175 
all_parking_lots(&self) -> &Vec<ParkingLot>176     pub fn all_parking_lots(&self) -> &Vec<ParkingLot> {
177         &self.parking_lots
178     }
179 
all_zones(&self) -> &Vec<Zone>180     pub fn all_zones(&self) -> &Vec<Zone> {
181         &self.zones
182     }
183 
maybe_get_r(&self, id: RoadID) -> Option<&Road>184     pub fn maybe_get_r(&self, id: RoadID) -> Option<&Road> {
185         self.roads.get(id.0)
186     }
187 
maybe_get_l(&self, id: LaneID) -> Option<&Lane>188     pub fn maybe_get_l(&self, id: LaneID) -> Option<&Lane> {
189         self.lanes.get(id.0)
190     }
191 
maybe_get_i(&self, id: IntersectionID) -> Option<&Intersection>192     pub fn maybe_get_i(&self, id: IntersectionID) -> Option<&Intersection> {
193         self.intersections.get(id.0)
194     }
195 
maybe_get_t(&self, id: TurnID) -> Option<&Turn>196     pub fn maybe_get_t(&self, id: TurnID) -> Option<&Turn> {
197         self.turns.get(&id)
198     }
199 
maybe_get_b(&self, id: BuildingID) -> Option<&Building>200     pub fn maybe_get_b(&self, id: BuildingID) -> Option<&Building> {
201         self.buildings.get(id.0)
202     }
203 
maybe_get_pl(&self, id: ParkingLotID) -> Option<&ParkingLot>204     pub fn maybe_get_pl(&self, id: ParkingLotID) -> Option<&ParkingLot> {
205         self.parking_lots.get(id.0)
206     }
207 
maybe_get_a(&self, id: AreaID) -> Option<&Area>208     pub fn maybe_get_a(&self, id: AreaID) -> Option<&Area> {
209         self.areas.get(id.0)
210     }
211 
maybe_get_bs(&self, id: BusStopID) -> Option<&BusStop>212     pub fn maybe_get_bs(&self, id: BusStopID) -> Option<&BusStop> {
213         self.bus_stops.get(&id)
214     }
215 
maybe_get_stop_sign(&self, id: IntersectionID) -> Option<&ControlStopSign>216     pub fn maybe_get_stop_sign(&self, id: IntersectionID) -> Option<&ControlStopSign> {
217         self.stop_signs.get(&id)
218     }
219 
maybe_get_traffic_signal(&self, id: IntersectionID) -> Option<&ControlTrafficSignal>220     pub fn maybe_get_traffic_signal(&self, id: IntersectionID) -> Option<&ControlTrafficSignal> {
221         self.traffic_signals.get(&id)
222     }
223 
maybe_get_br(&self, route: BusRouteID) -> Option<&BusRoute>224     pub fn maybe_get_br(&self, route: BusRouteID) -> Option<&BusRoute> {
225         self.bus_routes.get(route.0)
226     }
227 
get_r(&self, id: RoadID) -> &Road228     pub fn get_r(&self, id: RoadID) -> &Road {
229         &self.roads[id.0]
230     }
231 
get_l(&self, id: LaneID) -> &Lane232     pub fn get_l(&self, id: LaneID) -> &Lane {
233         &self.lanes[id.0]
234     }
235 
get_i(&self, id: IntersectionID) -> &Intersection236     pub fn get_i(&self, id: IntersectionID) -> &Intersection {
237         &self.intersections[id.0]
238     }
239 
get_t(&self, id: TurnID) -> &Turn240     pub fn get_t(&self, id: TurnID) -> &Turn {
241         // When pathfinding breaks, seeing this TurnID is useful.
242         if let Some(ref t) = self.turns.get(&id) {
243             t
244         } else {
245             panic!("Can't get_t({})", id);
246         }
247     }
248 
get_b(&self, id: BuildingID) -> &Building249     pub fn get_b(&self, id: BuildingID) -> &Building {
250         &self.buildings[id.0]
251     }
252 
get_a(&self, id: AreaID) -> &Area253     pub fn get_a(&self, id: AreaID) -> &Area {
254         &self.areas[id.0]
255     }
256 
get_pl(&self, id: ParkingLotID) -> &ParkingLot257     pub fn get_pl(&self, id: ParkingLotID) -> &ParkingLot {
258         &self.parking_lots[id.0]
259     }
260 
get_stop_sign(&self, id: IntersectionID) -> &ControlStopSign261     pub fn get_stop_sign(&self, id: IntersectionID) -> &ControlStopSign {
262         &self.stop_signs[&id]
263     }
264 
get_traffic_signal(&self, id: IntersectionID) -> &ControlTrafficSignal265     pub fn get_traffic_signal(&self, id: IntersectionID) -> &ControlTrafficSignal {
266         &self.traffic_signals[&id]
267     }
268 
269     // All these helpers should take IDs and return objects.
270 
get_turns_in_intersection<'a>( &'a self, id: IntersectionID, ) -> impl Iterator<Item = &'a Turn> + 'a271     pub fn get_turns_in_intersection<'a>(
272         &'a self,
273         id: IntersectionID,
274     ) -> impl Iterator<Item = &'a Turn> + 'a {
275         self.get_i(id).turns.iter().map(move |t| self.get_t(*t))
276     }
277 
278     // The turns may belong to two different intersections!
get_turns_from_lane(&self, l: LaneID) -> Vec<&Turn>279     pub fn get_turns_from_lane(&self, l: LaneID) -> Vec<&Turn> {
280         let lane = self.get_l(l);
281         let mut turns: Vec<&Turn> = self
282             .get_i(lane.dst_i)
283             .turns
284             .iter()
285             .map(|t| self.get_t(*t))
286             .filter(|t| t.id.src == l)
287             .collect();
288         // Sidewalks/shoulders are bidirectional
289         if lane.is_walkable() {
290             for t in &self.get_i(lane.src_i).turns {
291                 if t.src == l {
292                     turns.push(self.get_t(*t));
293                 }
294             }
295         }
296         turns
297     }
298 
get_turns_to_lane(&self, l: LaneID) -> Vec<&Turn>299     pub fn get_turns_to_lane(&self, l: LaneID) -> Vec<&Turn> {
300         let lane = self.get_l(l);
301         let mut turns: Vec<&Turn> = self
302             .get_i(lane.src_i)
303             .turns
304             .iter()
305             .map(|t| self.get_t(*t))
306             .filter(|t| t.id.dst == l)
307             .collect();
308         // Sidewalks/shoulders are bidirectional
309         if lane.is_walkable() {
310             for t in &self.get_i(lane.dst_i).turns {
311                 if t.dst == l {
312                     turns.push(self.get_t(*t));
313                 }
314             }
315         }
316         turns
317     }
318 
get_turn_between( &self, from: LaneID, to: LaneID, parent: IntersectionID, ) -> Option<TurnID>319     pub fn get_turn_between(
320         &self,
321         from: LaneID,
322         to: LaneID,
323         parent: IntersectionID,
324     ) -> Option<TurnID> {
325         self.get_i(parent)
326             .turns
327             .iter()
328             .find(|t| t.src == from && t.dst == to)
329             .cloned()
330     }
331 
get_next_turns_and_lanes<'a>( &'a self, from: LaneID, parent: IntersectionID, ) -> impl Iterator<Item = (&'a Turn, &'a Lane)> + 'a332     pub fn get_next_turns_and_lanes<'a>(
333         &'a self,
334         from: LaneID,
335         parent: IntersectionID,
336     ) -> impl Iterator<Item = (&'a Turn, &'a Lane)> + 'a {
337         self.get_i(parent)
338             .turns
339             .iter()
340             .filter(move |t| t.src == from)
341             .map(move |t| (self.get_t(*t), self.get_l(t.dst)))
342     }
343 
get_turns_for(&self, from: LaneID, constraints: PathConstraints) -> Vec<&Turn>344     pub fn get_turns_for(&self, from: LaneID, constraints: PathConstraints) -> Vec<&Turn> {
345         let mut turns: Vec<&Turn> = self
346             .get_next_turns_and_lanes(from, self.get_l(from).dst_i)
347             .into_iter()
348             .filter(|(_, l)| constraints.can_use(l, self))
349             .map(|(t, _)| t)
350             .collect();
351         // Sidewalks are bidirectional
352         if constraints == PathConstraints::Pedestrian {
353             turns.extend(
354                 self.get_next_turns_and_lanes(from, self.get_l(from).src_i)
355                     .into_iter()
356                     .filter(|(_, l)| constraints.can_use(l, self))
357                     .map(|(t, _)| t),
358             );
359         }
360         turns
361     }
362 
363     // These come back sorted
get_next_roads(&self, from: RoadID) -> impl Iterator<Item = RoadID>364     pub fn get_next_roads(&self, from: RoadID) -> impl Iterator<Item = RoadID> {
365         let mut roads: BTreeSet<RoadID> = BTreeSet::new();
366 
367         let r = self.get_r(from);
368         for id in vec![r.src_i, r.dst_i].into_iter() {
369             roads.extend(self.get_i(id).roads.clone());
370         }
371 
372         roads.into_iter()
373     }
374 
get_parent(&self, id: LaneID) -> &Road375     pub fn get_parent(&self, id: LaneID) -> &Road {
376         let l = self.get_l(id);
377         self.get_r(l.parent)
378     }
379 
get_gps_bounds(&self) -> &GPSBounds380     pub fn get_gps_bounds(&self) -> &GPSBounds {
381         &self.gps_bounds
382     }
383 
get_bounds(&self) -> &Bounds384     pub fn get_bounds(&self) -> &Bounds {
385         &self.bounds
386     }
387 
get_city_name(&self) -> &String388     pub fn get_city_name(&self) -> &String {
389         &self.city_name
390     }
391 
get_name(&self) -> &String392     pub fn get_name(&self) -> &String {
393         &self.name
394     }
395 
all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop>396     pub fn all_bus_stops(&self) -> &BTreeMap<BusStopID, BusStop> {
397         &self.bus_stops
398     }
399 
get_bs(&self, stop: BusStopID) -> &BusStop400     pub fn get_bs(&self, stop: BusStopID) -> &BusStop {
401         &self.bus_stops[&stop]
402     }
403 
get_br(&self, route: BusRouteID) -> &BusRoute404     pub fn get_br(&self, route: BusRouteID) -> &BusRoute {
405         &self.bus_routes[route.0]
406     }
407 
all_bus_routes(&self) -> &Vec<BusRoute>408     pub fn all_bus_routes(&self) -> &Vec<BusRoute> {
409         &self.bus_routes
410     }
411 
get_bus_route(&self, name: &str) -> Option<&BusRoute>412     pub fn get_bus_route(&self, name: &str) -> Option<&BusRoute> {
413         self.bus_routes.iter().find(|r| r.full_name == name)
414     }
415 
get_routes_serving_stop(&self, stop: BusStopID) -> Vec<&BusRoute>416     pub fn get_routes_serving_stop(&self, stop: BusStopID) -> Vec<&BusRoute> {
417         let mut routes = Vec::new();
418         for r in &self.bus_routes {
419             if r.stops.contains(&stop) {
420                 routes.push(r);
421             }
422         }
423         routes
424     }
425 
building_to_road(&self, id: BuildingID) -> &Road426     pub fn building_to_road(&self, id: BuildingID) -> &Road {
427         self.get_parent(self.get_b(id).sidewalk())
428     }
429 
430     // This and all_outgoing_borders are expensive to constantly repeat
all_incoming_borders(&self) -> Vec<&Intersection>431     pub fn all_incoming_borders(&self) -> Vec<&Intersection> {
432         let mut result: Vec<&Intersection> = Vec::new();
433         for i in &self.intersections {
434             if i.is_incoming_border() {
435                 result.push(i);
436             }
437         }
438         result
439     }
440 
all_outgoing_borders(&self) -> Vec<&Intersection>441     pub fn all_outgoing_borders(&self) -> Vec<&Intersection> {
442         let mut result: Vec<&Intersection> = Vec::new();
443         for i in &self.intersections {
444             if i.is_outgoing_border() {
445                 result.push(i);
446             }
447         }
448         result
449     }
450 
unsaved_edits(&self) -> bool451     pub fn unsaved_edits(&self) -> bool {
452         self.edits.edits_name == "untitled edits" && !self.edits.commands.is_empty()
453     }
454 
save(&self)455     pub fn save(&self) {
456         assert_eq!(self.edits.edits_name, "untitled edits");
457         assert!(self.edits.commands.is_empty());
458         assert!(!self.pathfinder_dirty);
459         abstutil::write_binary(abstutil::path_map(&self.name), self);
460     }
461 
462     // Cars trying to park near this building should head for the driving lane returned here, then
463     // start their search. Some parking lanes are connected to driving lanes that're "parking
464     // blackholes" -- if there are no free spots on that lane, then the roads force cars to a
465     // border.
466     // TODO Making driving_connection do this.
find_driving_lane_near_building(&self, b: BuildingID) -> LaneID467     pub fn find_driving_lane_near_building(&self, b: BuildingID) -> LaneID {
468         let sidewalk = self.get_b(b).sidewalk();
469         if let Some(l) = self.get_parent(sidewalk).find_closest_lane(
470             sidewalk,
471             |l| PathConstraints::Car.can_use(l, self),
472             self,
473         ) {
474             if !self.get_l(l).driving_blackhole {
475                 return l;
476             }
477         }
478 
479         let mut roads_queue: VecDeque<RoadID> = VecDeque::new();
480         let mut visited: HashSet<RoadID> = HashSet::new();
481         {
482             let start = self.building_to_road(b).id;
483             roads_queue.push_back(start);
484             visited.insert(start);
485         }
486 
487         loop {
488             if roads_queue.is_empty() {
489                 panic!(
490                     "Giving up looking for a driving lane near {}, searched {} roads: {:?}",
491                     b,
492                     visited.len(),
493                     visited
494                 );
495             }
496             let r = self.get_r(roads_queue.pop_front().unwrap());
497 
498             for (l, lt) in r
499                 .children_forwards()
500                 .into_iter()
501                 .chain(r.children_backwards().into_iter())
502             {
503                 if lt == LaneType::Driving {
504                     if !self.get_l(l).driving_blackhole {
505                         return l;
506                     }
507                 }
508             }
509 
510             for next_r in self.get_next_roads(r.id).into_iter() {
511                 if !visited.contains(&next_r) {
512                     roads_queue.push_back(next_r);
513                     visited.insert(next_r);
514                 }
515             }
516         }
517     }
518 
get_boundary_polygon(&self) -> &Polygon519     pub fn get_boundary_polygon(&self) -> &Polygon {
520         &self.boundary_polygon
521     }
522 
pathfind(&self, req: PathRequest) -> Option<Path>523     pub fn pathfind(&self, req: PathRequest) -> Option<Path> {
524         assert!(!self.pathfinder_dirty);
525         self.pathfinder.pathfind(req, self)
526     }
527 
should_use_transit( &self, start: Position, end: Position, ) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)>528     pub fn should_use_transit(
529         &self,
530         start: Position,
531         end: Position,
532     ) -> Option<(BusStopID, Option<BusStopID>, BusRouteID)> {
533         self.pathfinder.should_use_transit(self, start, end)
534     }
535 
536     // None for SharedSidewalkCorners
get_movement(&self, t: TurnID) -> Option<MovementID>537     pub fn get_movement(&self, t: TurnID) -> Option<MovementID> {
538         if let Some(ref ts) = self.maybe_get_traffic_signal(t.parent) {
539             if self.get_t(t).turn_type == TurnType::SharedSidewalkCorner {
540                 return None;
541             }
542             for m in ts.movements.values() {
543                 if m.members.contains(&t) {
544                     return Some(m.id);
545                 }
546             }
547             panic!("{} doesn't belong to any movements", t);
548         }
549         None
550     }
551 
find_r_by_osm_id(&self, id: OriginalRoad) -> Result<RoadID, String>552     pub fn find_r_by_osm_id(&self, id: OriginalRoad) -> Result<RoadID, String> {
553         for r in self.all_roads() {
554             if r.orig_id == id {
555                 return Ok(r.id);
556             }
557         }
558         Err(format!("Can't find {}", id))
559     }
560 
find_i_by_osm_id(&self, id: osm::NodeID) -> Result<IntersectionID, String>561     pub fn find_i_by_osm_id(&self, id: osm::NodeID) -> Result<IntersectionID, String> {
562         for i in self.all_intersections() {
563             if i.orig_id == id {
564                 return Ok(i.id);
565             }
566         }
567         Err(format!("Can't find {}", id))
568     }
569 
find_b_by_osm_id(&self, id: osm::OsmID) -> Option<BuildingID>570     pub fn find_b_by_osm_id(&self, id: osm::OsmID) -> Option<BuildingID> {
571         for b in self.all_buildings() {
572             if b.orig_id == id {
573                 return Some(b.id);
574             }
575         }
576         None
577     }
578 
find_br(&self, id: osm::RelationID) -> Option<BusRouteID>579     pub fn find_br(&self, id: osm::RelationID) -> Option<BusRouteID> {
580         for br in self.all_bus_routes() {
581             if br.osm_rel_id == id {
582                 return Some(br.id);
583             }
584         }
585         None
586     }
587 
right_shift(&self, pl: PolyLine, width: Distance) -> Result<PolyLine, String>588     pub fn right_shift(&self, pl: PolyLine, width: Distance) -> Result<PolyLine, String> {
589         self.config.driving_side.right_shift(pl, width)
590     }
must_right_shift(&self, pl: PolyLine, width: Distance) -> PolyLine591     pub fn must_right_shift(&self, pl: PolyLine, width: Distance) -> PolyLine {
592         self.right_shift(pl, width).unwrap()
593     }
left_shift(&self, pl: PolyLine, width: Distance) -> Result<PolyLine, String>594     pub fn left_shift(&self, pl: PolyLine, width: Distance) -> Result<PolyLine, String> {
595         self.config.driving_side.left_shift(pl, width)
596     }
must_left_shift(&self, pl: PolyLine, width: Distance) -> PolyLine597     pub fn must_left_shift(&self, pl: PolyLine, width: Distance) -> PolyLine {
598         self.left_shift(pl, width).unwrap()
599     }
right_shift_line(&self, line: Line, width: Distance) -> Line600     pub fn right_shift_line(&self, line: Line, width: Distance) -> Line {
601         self.config.driving_side.right_shift_line(line, width)
602     }
left_shift_line(&self, line: Line, width: Distance) -> Line603     pub fn left_shift_line(&self, line: Line, width: Distance) -> Line {
604         self.config.driving_side.left_shift_line(line, width)
605     }
driving_side_angle(&self, a: Angle) -> Angle606     pub fn driving_side_angle(&self, a: Angle) -> Angle {
607         self.config.driving_side.angle_offset(a)
608     }
609     // Last resort
get_driving_side(&self) -> DrivingSide610     pub fn get_driving_side(&self) -> DrivingSide {
611         self.config.driving_side
612     }
613 
614     // TODO Sort of a temporary hack
hack_override_offstreet_spots(&mut self, spots_per_bldg: usize)615     pub fn hack_override_offstreet_spots(&mut self, spots_per_bldg: usize) {
616         for b in &mut self.buildings {
617             if let OffstreetParking::Private(ref mut num_spots, _) = b.parking {
618                 *num_spots = spots_per_bldg;
619             }
620         }
621     }
hack_override_offstreet_spots_individ(&mut self, b: BuildingID, spots: usize)622     pub fn hack_override_offstreet_spots_individ(&mut self, b: BuildingID, spots: usize) {
623         let b = &mut self.buildings[b.0];
624         if let OffstreetParking::Private(ref mut num_spots, _) = b.parking {
625             *num_spots = spots;
626         }
627     }
628 
hack_override_bldg_type(&mut self, b: BuildingID, bldg_type: BuildingType)629     pub fn hack_override_bldg_type(&mut self, b: BuildingID, bldg_type: BuildingType) {
630         self.buildings[b.0].bldg_type = bldg_type;
631     }
632 
hack_override_orig_spawn_times(&mut self, br: BusRouteID, times: Vec<Time>)633     pub fn hack_override_orig_spawn_times(&mut self, br: BusRouteID, times: Vec<Time>) {
634         self.bus_routes[br.0].orig_spawn_times = times.clone();
635         self.bus_routes[br.0].spawn_times = times;
636     }
637 
get_languages(&self) -> BTreeSet<&str>638     pub fn get_languages(&self) -> BTreeSet<&str> {
639         let mut languages = BTreeSet::new();
640         for r in self.all_roads() {
641             for key in r.osm_tags.inner().keys() {
642                 if let Some(x) = key.strip_prefix("name:") {
643                     languages.insert(x);
644                 }
645             }
646         }
647         for b in self.all_buildings() {
648             for (names, _) in &b.amenities {
649                 for key in names.0.keys() {
650                     if let Some(lang) = key {
651                         languages.insert(lang);
652                     }
653                 }
654             }
655         }
656         languages
657     }
658 }
659