1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
5use std::sync::{Arc, RwLock};
6
7use structopt::StructOpt;
8
9use abstutil::{MultiMap, Tags, Timer};
10use geom::{
11 Distance, FindClosest, HashablePt2D, Line, PolyLine, Polygon, Pt2D, Speed, EPSILON_DIST,
12};
13use osm2streets::Transformation;
14use raw_map::RawMap;
15
16pub use self::parking_lots::snap_driveway;
17use crate::pathfind::{CreateEngine, Pathfinder};
18use crate::{
19 connectivity, osm, AccessRestrictions, Area, AreaID, ControlStopSign, ControlTrafficSignal,
20 Intersection, IntersectionControl, IntersectionID, IntersectionKind, Lane, LaneID, Map,
21 MapEdits, OriginalRoad, PathConstraints, Position, Road, RoadID, RoutingParams, Zone,
22};
23
24mod bridges;
25mod buildings;
26mod parking_lots;
27pub mod traffic_signals;
28pub mod transit;
29pub mod turns;
30mod walking_turns;
31
32#[derive(Clone, Default, StructOpt)]
34pub struct RawToMapOptions {
35 #[structopt(long)]
38 pub skip_ch: bool,
39 #[structopt(long)]
41 pub keep_bldg_tags: bool,
42}
43
44impl Map {
45 pub fn create_from_raw(mut raw: RawMap, opts: RawToMapOptions, timer: &mut Timer) -> Map {
46 raw.streets
47 .apply_transformations(Transformation::abstreet(), timer);
48
49 let mut map = Map {
50 roads: Vec::new(),
51 intersections: Vec::new(),
52 intersection_quad_tree: Arc::new(RwLock::new(None)),
53 buildings: Vec::new(),
54 transit_stops: BTreeMap::new(),
55 transit_routes: Vec::new(),
56 areas: Vec::new(),
57 parking_lots: Vec::new(),
58 zones: Vec::new(),
59 census_zones: raw.census_zones.clone(),
60 extra_pois: raw.extra_pois.clone(),
61 boundary_polygon: raw.streets.boundary_polygon.clone(),
62 stop_signs: BTreeMap::new(),
63 traffic_signals: BTreeMap::new(),
64 bus_routes_on_roads: std::mem::take(&mut raw.bus_routes_on_roads),
65 gps_bounds: raw.streets.gps_bounds.clone(),
66 bounds: raw.streets.gps_bounds.to_bounds(),
67 config: raw.streets.config.clone(),
68 pathfinder: Pathfinder::empty(),
69 pathfinder_dirty: false,
70 routing_params: RoutingParams::default(),
71 name: raw.name.clone(),
72 edits: MapEdits::new(),
73 edits_generation: 0,
74 road_to_buildings: MultiMap::new(),
75 };
76 map.edits = map.new_edits();
77
78 let road_id_mapping: BTreeMap<osm2streets::RoadID, RoadID> = raw
79 .streets
80 .roads
81 .keys()
82 .enumerate()
83 .map(|(idx, id)| (*id, RoadID(idx)))
84 .collect();
85 let mut intersection_id_mapping: BTreeMap<osm2streets::IntersectionID, IntersectionID> =
86 BTreeMap::new();
87 for (idx, i) in raw.streets.intersections.values().enumerate() {
88 let id = IntersectionID(idx);
89 map.intersections.push(Intersection {
90 id,
91 polygon: i.polygon.clone(),
92 turns: Vec::new(),
93 movements: BTreeMap::new(),
94 elevation: raw.elevation_per_intersection[&i.id],
95 kind: i.kind,
97 control: match i.control {
98 IntersectionControl::Uncontrolled => IntersectionControl::Signed,
100 x => x,
101 },
102 orig_id: i
104 .osm_ids
105 .get(0)
106 .cloned()
107 .unwrap_or(osm::NodeID(-1 * (map.intersections.len() as i64))),
108 incoming_lanes: Vec::new(),
109 outgoing_lanes: Vec::new(),
110 roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
111 modal_filter: None,
112 merged: !raw.streets.intersections[&i.id]
113 .trim_roads_for_merging
114 .is_empty(),
115 });
116 intersection_id_mapping.insert(i.id, id);
117 }
118
119 timer.start_iter("expand roads to lanes", raw.streets.roads.len());
120 for r in raw.streets.roads.values_mut() {
121 timer.next();
122
123 let road_id = road_id_mapping[&r.id];
124 let i1 = intersection_id_mapping[&r.src_i];
125 let i2 = intersection_id_mapping[&r.dst_i];
126
127 let extra = &raw.extra_road_data[&r.id];
128 let barrier_nodes = snap_nodes_to_line(&extra.barrier_nodes, &r.center_line);
129 let crossing_nodes =
130 snap_nodes_with_data_to_line(&extra.crossing_nodes, &r.center_line);
131
132 let orig_id = OriginalRoad {
134 osm_way_id: r
135 .osm_ids
136 .get(0)
137 .cloned()
138 .unwrap_or(osm::WayID(-1 * (map.roads.len() as i64))),
139 i1: map.intersections[i1.0].orig_id,
140 i2: map.intersections[i2.0].orig_id,
141 };
142
143 let mut road = Road {
144 id: road_id,
145 osm_tags: if let Some(id) = r.osm_ids.get(0) {
149 raw.osm_tags[id].clone()
150 } else {
151 Tags::empty()
152 },
153 orig_id,
154 turn_restrictions: r
155 .turn_restrictions
156 .iter()
157 .filter_map(|(rt, to)| {
158 road_id_mapping.get(to).map(|to| (*rt, *to))
160 })
161 .collect(),
162 complicated_turn_restrictions: r
163 .complicated_turn_restrictions
164 .iter()
165 .filter_map(|(via, to)| {
166 if let (Some(via), Some(to)) =
167 (road_id_mapping.get(via), road_id_mapping.get(to))
168 {
169 Some((*via, *to))
170 } else {
171 warn!(
172 "Complicated turn restriction from {} has invalid via {} or dst {}",
173 r.id, via, to
174 );
175 None
176 }
177 })
178 .collect(),
179 lanes: Vec::new(),
180 center_pts: r.center_line.clone(),
181 untrimmed_center_pts: r.get_untrimmed_center_line(raw.streets.config.driving_side),
182 trim_start: r.trim_start,
183 trim_end: r.trim_end,
184 src_i: i1,
185 dst_i: i2,
186 speed_limit: Speed::ZERO,
187 zorder: r.layer,
188 access_restrictions: AccessRestrictions::new(),
189 percent_incline: extra.percent_incline,
190 crosswalk_forward: extra.crosswalk_forward,
191 crosswalk_backward: extra.crosswalk_backward,
192 transit_stops: BTreeSet::new(),
193 modal_filter: None,
194 barrier_nodes,
195 crossing_nodes,
196 crossings: Vec::new(),
197 };
198 road.speed_limit = road.speed_limit_from_osm();
199 road.access_restrictions = road.access_restrictions_from_osm();
200
201 road.recreate_lanes(r.lane_specs_ltr.clone());
202 for lane in &road.lanes {
203 map.intersections[lane.src_i.0].outgoing_lanes.push(lane.id);
204 map.intersections[lane.dst_i.0].incoming_lanes.push(lane.id);
205 }
206
207 map.roads.push(road);
208 }
209
210 for i in map.intersections.iter_mut() {
211 if i.is_border() && i.roads.len() != 1 {
212 let border_roads = i
214 .roads
215 .iter()
216 .map(|r| map.roads[r.0].orig_id.osm_way_id.to_string())
217 .collect::<Vec<_>>();
218 panic!(
219 "{} ({}) is a border, but is connected to >1 road: {:?}",
220 i.id, i.orig_id, border_roads
221 );
222 }
223 if i.control == IntersectionControl::Signalled {
224 let mut ok = true;
225 for r in &i.roads {
226 let road = &map.roads[r.0];
227 if road.osm_tags.is(osm::HIGHWAY, "construction") || road.is_light_rail() {
230 ok = false;
231 break;
232 }
233 if road.trim_start == Distance::ZERO || road.trim_end == Distance::ZERO {
235 ok = false;
236 break;
237 }
238 }
239 if !ok {
240 i.control = IntersectionControl::Signed;
241 }
242 }
243 }
244
245 let mut all_turns = Vec::new();
246 let mut connectivity_problems = 0;
247 for i in &map.intersections {
248 if i.is_border() || i.is_closed() {
249 continue;
250 }
251 if !i.is_footway(&map) && (i.incoming_lanes.is_empty() || i.outgoing_lanes.is_empty()) {
252 warn!("{} is orphaned!", i.orig_id);
253 continue;
254 }
255
256 let results = turns::make_all_turns(&map, i);
257 if turns::verify_vehicle_connectivity(&results, i, &map).is_err() {
258 connectivity_problems += 1;
259 }
260 all_turns.extend(results);
261 }
262 error!(
263 "{} total intersections have some connectivity problem",
264 connectivity_problems
265 );
266 for t in all_turns {
267 assert!(map.maybe_get_t(t.id).is_none());
268 if t.geom.length() < geom::EPSILON_DIST {
269 warn!("{} is a very short turn", t.id);
270 }
271 map.intersections[t.id.parent.0].turns.push(t);
272 }
273
274 timer.start("find blackholes");
275 for l in connectivity::find_scc(&map, PathConstraints::Car).1 {
276 map.mut_lane(l).driving_blackhole = true;
277 }
278 for l in connectivity::find_scc(&map, PathConstraints::Bike).1 {
279 map.mut_lane(l).biking_blackhole = true;
280 }
281 timer.stop("find blackholes");
282
283 map.buildings =
284 buildings::make_all_buildings(&raw.buildings, &map, opts.keep_bldg_tags, timer);
285
286 map.parking_lots = parking_lots::make_all_parking_lots(
287 &raw.parking_lots,
288 &raw.parking_aisles,
289 &map,
290 timer,
291 );
292
293 map.zones = Zone::make_all(&map);
294
295 for a in &raw.areas {
296 map.areas.push(Area {
297 id: AreaID(map.areas.len()),
298 area_type: a.area_type,
299 polygon: a.polygon.clone(),
300 osm_tags: a.osm_tags.clone(),
301 osm_id: Some(a.osm_id),
302 });
303 }
304
305 bridges::find_bridges(&mut map.roads, timer);
306
307 map.recalculate_all_movements(timer);
308
309 let mut stop_signs: BTreeMap<IntersectionID, ControlStopSign> = BTreeMap::new();
310 let mut traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal> = BTreeMap::new();
311 for i in &map.intersections {
312 if i.kind == IntersectionKind::MapEdge {
313 continue;
314 }
315 match i.control {
316 IntersectionControl::Signed | IntersectionControl::Uncontrolled => {
317 stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
318 }
319 IntersectionControl::Signalled => {
320 if i.movements.is_empty() {
321 error!("Traffic signal at {} downgraded to stop sign, because it has no movements -- probably roads under construction", i.orig_id);
322 stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
323 } else {
324 traffic_signals.insert(
325 i.id,
326 ControlTrafficSignal::get_possible_policies(&map, i.id)
327 .remove(0)
328 .1,
329 );
330 }
331 }
332 IntersectionControl::Construction => {}
333 };
334 }
335 map.stop_signs = stop_signs;
336 map.traffic_signals = traffic_signals;
337 for i in map.stop_signs.keys() {
339 map.intersections[i.0].control = IntersectionControl::Signed;
340 }
341
342 traffic_signals::synchronize(&mut map);
343
344 timer.start("setup pathfinding");
345 let engine = if opts.skip_ch {
346 CreateEngine::Dijkstra
347 } else {
348 CreateEngine::CH
349 };
350 map.pathfinder = Pathfinder::new(&map, map.routing_params().clone(), &engine, timer);
351 timer.stop("setup pathfinding");
352
353 transit::finalize_transit(&mut map, &raw, timer);
354 timer.start("setup pathfinding for people using transit");
355 let mut pathfinder = std::mem::replace(&mut map.pathfinder, Pathfinder::empty());
356 pathfinder.finalize_transit(&map, &engine);
357 map.pathfinder = pathfinder;
358 timer.stop("setup pathfinding for people using transit");
359
360 map
361 }
362}
363
364pub fn match_points_to_lanes<F: Fn(&Lane) -> bool>(
367 map: &Map,
368 pts: HashSet<HashablePt2D>,
369 filter: F,
370 buffer: Distance,
371 max_dist_away: Distance,
372 timer: &mut Timer,
373) -> HashMap<HashablePt2D, Position> {
374 if pts.is_empty() {
375 return HashMap::new();
376 }
377
378 let mut closest: FindClosest<LaneID> = FindClosest::new();
379 timer.start_iter("index lanes", map.all_lanes().count());
380 for l in map.all_lanes() {
381 timer.next();
382 if filter(l) && l.length() > (buffer + EPSILON_DIST) * 2.0 {
383 closest.add(
384 l.id,
385 l.lane_center_pts
386 .exact_slice(buffer, l.length() - buffer)
387 .points(),
388 );
389 }
390 }
391
392 timer
395 .parallelize(
396 "find closest lane point",
397 pts.into_iter().collect(),
398 |query_pt| {
399 if let Some((l, pt)) = closest.closest_pt(query_pt.to_pt2d(), max_dist_away) {
400 if let Some(dist_along) = map.get_l(l).dist_along_of_point(pt) {
401 Some((query_pt, Position::new(l, dist_along)))
402 } else {
403 panic!(
404 "{} isn't on {} according to dist_along_of_point, even though \
405 closest_point thinks it is.\n{}",
406 pt,
407 l,
408 map.get_l(l).lane_center_pts
409 );
410 }
411 } else {
412 None
413 }
414 },
415 )
416 .into_iter()
417 .flatten()
418 .collect()
419}
420
421pub fn trim_path(poly: &Polygon, path: Line) -> Line {
423 for line in poly.get_outer_ring().points().windows(2) {
424 if let Ok(l1) = Line::new(line[0], line[1]) {
425 if let Some(hit) = l1.intersection(&path) {
426 if let Ok(l2) = Line::new(hit, path.pt2()) {
427 return l2;
428 }
429 }
430 }
431 }
432 path
434}
435
436fn snap_nodes_to_line(pts: &[Pt2D], pl: &PolyLine) -> Vec<Distance> {
439 let mut results = Vec::new();
440 for pt in pts {
441 let projected = pl.project_pt(*pt);
442 if let Some((dist, _)) = pl.dist_along_of_point(projected) {
444 results.push(dist);
445 }
446 }
447 results
448}
449
450fn snap_nodes_with_data_to_line<T: Clone>(
451 input: &[(Pt2D, T)],
452 pl: &PolyLine,
453) -> Vec<(Distance, T)> {
454 let mut results = Vec::new();
455 for (pt, data) in input {
456 let projected = pl.project_pt(*pt);
457 if let Some((dist, _)) = pl.dist_along_of_point(projected) {
459 results.push((dist, data.clone()));
460 }
461 }
462 results
463}