mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 19:27:11 +03:00
flatten some of the map building code
This commit is contained in:
parent
3acec91f51
commit
ebe1f486f7
@ -16,7 +16,7 @@ use crate::{
|
||||
PathConstraints, Road, RoadID, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use geom::{Bounds, Distance, GPSBounds, PolyLine, Polygon, Speed};
|
||||
use geom::{Distance, PolyLine, Polygon, Speed};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
|
||||
impl Map {
|
||||
@ -30,47 +30,289 @@ impl Map {
|
||||
let initial_map = initial::InitialMap::new(&raw, &bounds, timer);
|
||||
timer.stop("raw_map to InitialMap");
|
||||
|
||||
timer.start("InitialMap to half of Map");
|
||||
let mut m = make_half_map(&raw, initial_map, gps_bounds, bounds, timer);
|
||||
timer.stop("InitialMap to half of Map");
|
||||
let mut map = Map {
|
||||
roads: Vec::new(),
|
||||
lanes: Vec::new(),
|
||||
intersections: Vec::new(),
|
||||
turns: BTreeMap::new(),
|
||||
buildings: Vec::new(),
|
||||
bus_stops: BTreeMap::new(),
|
||||
bus_routes: Vec::new(),
|
||||
areas: Vec::new(),
|
||||
parking_lots: Vec::new(),
|
||||
zones: Vec::new(),
|
||||
boundary_polygon: raw.boundary_polygon.clone(),
|
||||
stop_signs: BTreeMap::new(),
|
||||
traffic_signals: BTreeMap::new(),
|
||||
gps_bounds,
|
||||
bounds,
|
||||
driving_side: raw.driving_side,
|
||||
pathfinder: None,
|
||||
pathfinder_dirty: false,
|
||||
city_name: raw.city_name.clone(),
|
||||
name: raw.name.clone(),
|
||||
edits: MapEdits::new(),
|
||||
};
|
||||
|
||||
timer.start("finalize Map");
|
||||
|
||||
// TODO Can probably move this into make_half_map.
|
||||
{
|
||||
let mut stop_signs: BTreeMap<IntersectionID, ControlStopSign> = BTreeMap::new();
|
||||
let mut traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal> =
|
||||
BTreeMap::new();
|
||||
for i in &m.intersections {
|
||||
match i.intersection_type {
|
||||
IntersectionType::StopSign => {
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&m, i.id));
|
||||
}
|
||||
IntersectionType::TrafficSignal => {
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&m, i.id, timer));
|
||||
}
|
||||
IntersectionType::Border | IntersectionType::Construction => {}
|
||||
};
|
||||
}
|
||||
m.stop_signs = stop_signs;
|
||||
m.traffic_signals = traffic_signals;
|
||||
let road_id_mapping: BTreeMap<OriginalRoad, RoadID> = initial_map
|
||||
.roads
|
||||
.keys()
|
||||
.enumerate()
|
||||
.map(|(idx, id)| (*id, RoadID(idx)))
|
||||
.collect();
|
||||
let mut intersection_id_mapping: BTreeMap<OriginalIntersection, IntersectionID> =
|
||||
BTreeMap::new();
|
||||
for (idx, i) in initial_map.intersections.values().enumerate() {
|
||||
let id = IntersectionID(idx);
|
||||
map.intersections.push(Intersection {
|
||||
id,
|
||||
// IMPORTANT! We're relying on the triangulation algorithm not to mess with the
|
||||
// order of the points. Sidewalk corner rendering depends on it
|
||||
// later.
|
||||
polygon: Polygon::new(&i.polygon),
|
||||
turns: BTreeSet::new(),
|
||||
elevation: i.elevation,
|
||||
// Might change later
|
||||
intersection_type: i.intersection_type,
|
||||
orig_id: i.id,
|
||||
incoming_lanes: Vec::new(),
|
||||
outgoing_lanes: Vec::new(),
|
||||
roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
|
||||
});
|
||||
intersection_id_mapping.insert(i.id, id);
|
||||
}
|
||||
|
||||
timer.start_iter("expand roads to lanes", initial_map.roads.len());
|
||||
for r in initial_map.roads.values() {
|
||||
timer.next();
|
||||
|
||||
let road_id = road_id_mapping[&r.id];
|
||||
let i1 = intersection_id_mapping[&r.src_i];
|
||||
let i2 = intersection_id_mapping[&r.dst_i];
|
||||
|
||||
let mut road = Road {
|
||||
id: road_id,
|
||||
osm_tags: raw.roads[&r.id].osm_tags.clone(),
|
||||
turn_restrictions: raw.roads[&r.id]
|
||||
.turn_restrictions
|
||||
.iter()
|
||||
.filter_map(|(rt, to)| {
|
||||
if let Some(to) = road_id_mapping.get(to) {
|
||||
Some((*rt, *to))
|
||||
} else {
|
||||
timer.warn(format!(
|
||||
"Turn restriction from {} points to invalid dst {}",
|
||||
r.id, to
|
||||
));
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
complicated_turn_restrictions: raw.roads[&r.id]
|
||||
.complicated_turn_restrictions
|
||||
.iter()
|
||||
.filter_map(|(via, to)| {
|
||||
if let (Some(via), Some(to)) =
|
||||
(road_id_mapping.get(via), road_id_mapping.get(to))
|
||||
{
|
||||
Some((*via, *to))
|
||||
} else {
|
||||
timer.warn(format!(
|
||||
"Complicated turn restriction from {} has invalid via {} or dst {}",
|
||||
r.id, via, to
|
||||
));
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
orig_id: r.id,
|
||||
children_forwards: Vec::new(),
|
||||
children_backwards: Vec::new(),
|
||||
center_pts: r.trimmed_center_pts.clone(),
|
||||
src_i: i1,
|
||||
dst_i: i2,
|
||||
speed_limit: Speed::ZERO,
|
||||
zorder: if let Some(layer) = raw.roads[&r.id].osm_tags.get("layer") {
|
||||
layer.parse::<isize>().unwrap()
|
||||
} else {
|
||||
0
|
||||
},
|
||||
zone: None,
|
||||
};
|
||||
road.speed_limit = road.speed_limit_from_osm();
|
||||
|
||||
for lane in &r.lane_specs {
|
||||
let id = LaneID(map.lanes.len());
|
||||
|
||||
let (src_i, dst_i) = if lane.reverse_pts { (i2, i1) } else { (i1, i2) };
|
||||
map.intersections[src_i.0].outgoing_lanes.push(id);
|
||||
map.intersections[dst_i.0].incoming_lanes.push(id);
|
||||
|
||||
let (unshifted_pts, other_lanes_width): (PolyLine, Distance) = {
|
||||
let dir = lane.reverse_pts;
|
||||
let w = road.width(&map, !dir);
|
||||
road.children_mut(!dir).push((id, lane.lane_type));
|
||||
if dir {
|
||||
(road.center_pts.reversed(), w)
|
||||
} else {
|
||||
(road.center_pts.clone(), w)
|
||||
}
|
||||
};
|
||||
// TODO probably different behavior for oneways
|
||||
// TODO need to factor in yellow center lines (but what's the right thing to even
|
||||
// do?
|
||||
let width = if lane.lane_type == LaneType::Sidewalk {
|
||||
SIDEWALK_THICKNESS
|
||||
} else {
|
||||
NORMAL_LANE_THICKNESS
|
||||
};
|
||||
let lane_center_pts = map
|
||||
.right_shift(unshifted_pts, other_lanes_width + width / 2.0)
|
||||
.with_context(timer, format!("shift for {}", id));
|
||||
|
||||
map.lanes.push(Lane {
|
||||
id,
|
||||
lane_center_pts,
|
||||
width,
|
||||
src_i,
|
||||
dst_i,
|
||||
lane_type: lane.lane_type,
|
||||
parent: road_id,
|
||||
building_paths: Vec::new(),
|
||||
bus_stops: Vec::new(),
|
||||
parking_blackhole: None,
|
||||
});
|
||||
}
|
||||
if road.get_name() == "???" {
|
||||
timer.warn(format!(
|
||||
"{} has no name. Tags: {:?}",
|
||||
road.id, road.osm_tags
|
||||
));
|
||||
}
|
||||
map.roads.push(road);
|
||||
}
|
||||
|
||||
for i in map.intersections.iter_mut() {
|
||||
if is_border(i, &map.lanes) {
|
||||
i.intersection_type = IntersectionType::Border;
|
||||
}
|
||||
if i.is_border() {
|
||||
if i.roads.len() != 1 {
|
||||
panic!(
|
||||
"{} ({}) is a border, but is connected to >1 road: {:?}",
|
||||
i.id, i.orig_id, i.roads
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if i.is_closed() {
|
||||
continue;
|
||||
}
|
||||
if i.intersection_type == IntersectionType::TrafficSignal {
|
||||
let mut ok = false;
|
||||
for r in &i.roads {
|
||||
if map.roads[r.0].osm_tags.get(osm::HIGHWAY)
|
||||
!= Some(&"construction".to_string())
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
i.intersection_type = IntersectionType::StopSign;
|
||||
}
|
||||
}
|
||||
|
||||
if i.incoming_lanes.is_empty() || i.outgoing_lanes.is_empty() {
|
||||
timer.warn(format!("{:?} is orphaned!", i));
|
||||
continue;
|
||||
}
|
||||
|
||||
for t in turns::make_all_turns(map.driving_side, i, &map.roads, &map.lanes, timer) {
|
||||
assert!(!map.turns.contains_key(&t.id));
|
||||
i.turns.insert(t.id);
|
||||
if t.geom.length() < geom::EPSILON_DIST {
|
||||
timer.warn(format!("{} is a very short turn", t.id));
|
||||
}
|
||||
map.turns.insert(t.id, t);
|
||||
}
|
||||
}
|
||||
|
||||
timer.start("find parking blackholes");
|
||||
for (l, redirect) in connectivity::redirect_parking_blackholes(&map, timer) {
|
||||
map.lanes[l.0].parking_blackhole = Some(redirect);
|
||||
}
|
||||
timer.stop("find parking blackholes");
|
||||
|
||||
map.buildings = buildings::make_all_buildings(&raw.buildings, &map, timer);
|
||||
for b in &map.buildings {
|
||||
let lane = b.sidewalk();
|
||||
|
||||
// TODO Could be more performant and cleanly written
|
||||
let mut bldgs = map.lanes[lane.0].building_paths.clone();
|
||||
bldgs.push(b.id);
|
||||
bldgs.sort_by_key(|b| map.buildings[b.0].front_path.sidewalk.dist_along());
|
||||
map.lanes[lane.0].building_paths = bldgs;
|
||||
}
|
||||
|
||||
map.parking_lots =
|
||||
buildings::make_all_parking_lots(&raw.parking_lots, &raw.parking_aisles, &map, timer);
|
||||
|
||||
map.zones = zones::make_all_zones(&map);
|
||||
for z in &map.zones {
|
||||
for r in &z.members {
|
||||
map.roads[r.0].zone = Some(z.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, a) in raw.areas.iter().enumerate() {
|
||||
map.areas.push(Area {
|
||||
id: AreaID(idx),
|
||||
area_type: a.area_type,
|
||||
polygon: a.polygon.clone(),
|
||||
osm_tags: a.osm_tags.clone(),
|
||||
osm_id: a.osm_id,
|
||||
});
|
||||
}
|
||||
|
||||
bridges::find_bridges(&mut map.roads, &map.bounds, timer);
|
||||
|
||||
let mut stop_signs: BTreeMap<IntersectionID, ControlStopSign> = BTreeMap::new();
|
||||
let mut traffic_signals: BTreeMap<IntersectionID, ControlTrafficSignal> = BTreeMap::new();
|
||||
for i in &map.intersections {
|
||||
match i.intersection_type {
|
||||
IntersectionType::StopSign => {
|
||||
stop_signs.insert(i.id, ControlStopSign::new(&map, i.id));
|
||||
}
|
||||
IntersectionType::TrafficSignal => {
|
||||
traffic_signals.insert(i.id, ControlTrafficSignal::new(&map, i.id, timer));
|
||||
}
|
||||
IntersectionType::Border | IntersectionType::Construction => {}
|
||||
};
|
||||
}
|
||||
map.stop_signs = stop_signs;
|
||||
map.traffic_signals = traffic_signals;
|
||||
|
||||
// Here's a fun one: we can't set up walking_using_transit yet, because we haven't
|
||||
// finalized bus stops and routes. We need the bus graph in place for that. So setup
|
||||
// pathfinding in two stages.
|
||||
if build_ch {
|
||||
timer.start("setup (most of) Pathfinder");
|
||||
m.pathfinder = Some(Pathfinder::new_without_transit(&m, timer));
|
||||
map.pathfinder = Some(Pathfinder::new_without_transit(&map, timer));
|
||||
timer.stop("setup (most of) Pathfinder");
|
||||
|
||||
{
|
||||
let (stops, routes) =
|
||||
bus_stops::make_bus_stops(&m, &raw.bus_routes, &m.gps_bounds, &m.bounds, timer);
|
||||
m.bus_stops = stops;
|
||||
let (stops, routes) = bus_stops::make_bus_stops(
|
||||
&map,
|
||||
&raw.bus_routes,
|
||||
&map.gps_bounds,
|
||||
&map.bounds,
|
||||
timer,
|
||||
);
|
||||
map.bus_stops = stops;
|
||||
// The IDs are sorted in the BTreeMap, so this order winds up correct.
|
||||
for id in m.bus_stops.keys() {
|
||||
m.lanes[id.sidewalk.0].bus_stops.push(*id);
|
||||
for id in map.bus_stops.keys() {
|
||||
map.lanes[id.sidewalk.0].bus_stops.push(*id);
|
||||
}
|
||||
|
||||
timer.start_iter("verify bus routes are connected", routes.len());
|
||||
@ -79,9 +321,9 @@ impl Map {
|
||||
if r.stops.is_empty() {
|
||||
continue;
|
||||
}
|
||||
if bus_stops::fix_bus_route(&m, &mut r) {
|
||||
r.id = BusRouteID(m.bus_routes.len());
|
||||
m.bus_routes.push(r);
|
||||
if bus_stops::fix_bus_route(&map, &mut r) {
|
||||
r.id = BusRouteID(map.bus_routes.len());
|
||||
map.bus_routes.push(r);
|
||||
} else {
|
||||
timer.warn(format!("Skipping route {}", r.name));
|
||||
}
|
||||
@ -89,27 +331,27 @@ impl Map {
|
||||
|
||||
// Remove orphaned bus stops
|
||||
let mut remove_stops = HashSet::new();
|
||||
for id in m.bus_stops.keys() {
|
||||
if m.get_routes_serving_stop(*id).is_empty() {
|
||||
for id in map.bus_stops.keys() {
|
||||
if map.get_routes_serving_stop(*id).is_empty() {
|
||||
remove_stops.insert(*id);
|
||||
}
|
||||
}
|
||||
for id in &remove_stops {
|
||||
m.bus_stops.remove(id);
|
||||
m.lanes[id.sidewalk.0]
|
||||
map.bus_stops.remove(id);
|
||||
map.lanes[id.sidewalk.0]
|
||||
.bus_stops
|
||||
.retain(|stop| !remove_stops.contains(stop))
|
||||
}
|
||||
}
|
||||
|
||||
timer.start("setup rest of Pathfinder (walking with transit)");
|
||||
let mut pathfinder = m.pathfinder.take().unwrap();
|
||||
pathfinder.setup_walking_with_transit(&m);
|
||||
m.pathfinder = Some(pathfinder);
|
||||
let mut pathfinder = map.pathfinder.take().unwrap();
|
||||
pathfinder.setup_walking_with_transit(&map);
|
||||
map.pathfinder = Some(pathfinder);
|
||||
timer.stop("setup rest of Pathfinder (walking with transit)");
|
||||
}
|
||||
|
||||
let (_, disconnected) = connectivity::find_scc(&m, PathConstraints::Pedestrian);
|
||||
let (_, disconnected) = connectivity::find_scc(&map, PathConstraints::Pedestrian);
|
||||
if !disconnected.is_empty() {
|
||||
timer.warn(format!(
|
||||
"{} sidewalks are disconnected!",
|
||||
@ -122,264 +364,10 @@ impl Map {
|
||||
}
|
||||
}
|
||||
|
||||
timer.stop("finalize Map");
|
||||
m
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
fn make_half_map(
|
||||
raw: &RawMap,
|
||||
initial_map: initial::InitialMap,
|
||||
gps_bounds: GPSBounds,
|
||||
bounds: Bounds,
|
||||
timer: &mut Timer,
|
||||
) -> Map {
|
||||
let mut map = Map {
|
||||
roads: Vec::new(),
|
||||
lanes: Vec::new(),
|
||||
intersections: Vec::new(),
|
||||
turns: BTreeMap::new(),
|
||||
buildings: Vec::new(),
|
||||
bus_stops: BTreeMap::new(),
|
||||
bus_routes: Vec::new(),
|
||||
areas: Vec::new(),
|
||||
parking_lots: Vec::new(),
|
||||
zones: Vec::new(),
|
||||
boundary_polygon: raw.boundary_polygon.clone(),
|
||||
stop_signs: BTreeMap::new(),
|
||||
traffic_signals: BTreeMap::new(),
|
||||
gps_bounds,
|
||||
bounds,
|
||||
driving_side: raw.driving_side,
|
||||
pathfinder: None,
|
||||
pathfinder_dirty: false,
|
||||
city_name: raw.city_name.clone(),
|
||||
name: raw.name.clone(),
|
||||
edits: MapEdits::new(),
|
||||
};
|
||||
|
||||
let road_id_mapping: BTreeMap<OriginalRoad, RoadID> = initial_map
|
||||
.roads
|
||||
.keys()
|
||||
.enumerate()
|
||||
.map(|(idx, id)| (*id, RoadID(idx)))
|
||||
.collect();
|
||||
let mut intersection_id_mapping: BTreeMap<OriginalIntersection, IntersectionID> =
|
||||
BTreeMap::new();
|
||||
for (idx, i) in initial_map.intersections.values().enumerate() {
|
||||
let id = IntersectionID(idx);
|
||||
map.intersections.push(Intersection {
|
||||
id,
|
||||
// IMPORTANT! We're relying on the triangulation algorithm not to mess with the order
|
||||
// of the points. Sidewalk corner rendering depends on it later.
|
||||
polygon: Polygon::new(&i.polygon),
|
||||
turns: BTreeSet::new(),
|
||||
elevation: i.elevation,
|
||||
// Might change later
|
||||
intersection_type: i.intersection_type,
|
||||
orig_id: i.id,
|
||||
incoming_lanes: Vec::new(),
|
||||
outgoing_lanes: Vec::new(),
|
||||
roads: i.roads.iter().map(|id| road_id_mapping[id]).collect(),
|
||||
});
|
||||
intersection_id_mapping.insert(i.id, id);
|
||||
}
|
||||
|
||||
timer.start_iter("expand roads to lanes", initial_map.roads.len());
|
||||
for r in initial_map.roads.values() {
|
||||
timer.next();
|
||||
|
||||
let road_id = road_id_mapping[&r.id];
|
||||
let i1 = intersection_id_mapping[&r.src_i];
|
||||
let i2 = intersection_id_mapping[&r.dst_i];
|
||||
|
||||
let mut road = Road {
|
||||
id: road_id,
|
||||
osm_tags: raw.roads[&r.id].osm_tags.clone(),
|
||||
turn_restrictions: raw.roads[&r.id]
|
||||
.turn_restrictions
|
||||
.iter()
|
||||
.filter_map(|(rt, to)| {
|
||||
if let Some(to) = road_id_mapping.get(to) {
|
||||
Some((*rt, *to))
|
||||
} else {
|
||||
timer.warn(format!(
|
||||
"Turn restriction from {} points to invalid dst {}",
|
||||
r.id, to
|
||||
));
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
complicated_turn_restrictions: raw.roads[&r.id]
|
||||
.complicated_turn_restrictions
|
||||
.iter()
|
||||
.filter_map(|(via, to)| {
|
||||
if let (Some(via), Some(to)) =
|
||||
(road_id_mapping.get(via), road_id_mapping.get(to))
|
||||
{
|
||||
Some((*via, *to))
|
||||
} else {
|
||||
timer.warn(format!(
|
||||
"Complicated turn restriction from {} has invalid via {} or dst {}",
|
||||
r.id, via, to
|
||||
));
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
orig_id: r.id,
|
||||
children_forwards: Vec::new(),
|
||||
children_backwards: Vec::new(),
|
||||
center_pts: r.trimmed_center_pts.clone(),
|
||||
src_i: i1,
|
||||
dst_i: i2,
|
||||
speed_limit: Speed::ZERO,
|
||||
zorder: if let Some(layer) = raw.roads[&r.id].osm_tags.get("layer") {
|
||||
layer.parse::<isize>().unwrap()
|
||||
} else {
|
||||
0
|
||||
},
|
||||
zone: None,
|
||||
};
|
||||
road.speed_limit = road.speed_limit_from_osm();
|
||||
|
||||
for lane in &r.lane_specs {
|
||||
let id = LaneID(map.lanes.len());
|
||||
|
||||
let (src_i, dst_i) = if lane.reverse_pts { (i2, i1) } else { (i1, i2) };
|
||||
map.intersections[src_i.0].outgoing_lanes.push(id);
|
||||
map.intersections[dst_i.0].incoming_lanes.push(id);
|
||||
|
||||
let (unshifted_pts, other_lanes_width): (PolyLine, Distance) = {
|
||||
let dir = lane.reverse_pts;
|
||||
let w = road.width(&map, !dir);
|
||||
road.children_mut(!dir).push((id, lane.lane_type));
|
||||
if dir {
|
||||
(road.center_pts.reversed(), w)
|
||||
} else {
|
||||
(road.center_pts.clone(), w)
|
||||
}
|
||||
};
|
||||
// TODO probably different behavior for oneways
|
||||
// TODO need to factor in yellow center lines (but what's the right thing to even do?
|
||||
let width = if lane.lane_type == LaneType::Sidewalk {
|
||||
SIDEWALK_THICKNESS
|
||||
} else {
|
||||
NORMAL_LANE_THICKNESS
|
||||
};
|
||||
let lane_center_pts = map
|
||||
.right_shift(unshifted_pts, other_lanes_width + width / 2.0)
|
||||
.with_context(timer, format!("shift for {}", id));
|
||||
|
||||
map.lanes.push(Lane {
|
||||
id,
|
||||
lane_center_pts,
|
||||
width,
|
||||
src_i,
|
||||
dst_i,
|
||||
lane_type: lane.lane_type,
|
||||
parent: road_id,
|
||||
building_paths: Vec::new(),
|
||||
bus_stops: Vec::new(),
|
||||
parking_blackhole: None,
|
||||
});
|
||||
}
|
||||
if road.get_name() == "???" {
|
||||
timer.warn(format!(
|
||||
"{} has no name. Tags: {:?}",
|
||||
road.id, road.osm_tags
|
||||
));
|
||||
}
|
||||
map.roads.push(road);
|
||||
}
|
||||
|
||||
for i in map.intersections.iter_mut() {
|
||||
if is_border(i, &map.lanes) {
|
||||
i.intersection_type = IntersectionType::Border;
|
||||
}
|
||||
if i.is_border() {
|
||||
if i.roads.len() != 1 {
|
||||
panic!(
|
||||
"{} ({}) is a border, but is connected to >1 road: {:?}",
|
||||
i.id, i.orig_id, i.roads
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if i.is_closed() {
|
||||
continue;
|
||||
}
|
||||
if i.intersection_type == IntersectionType::TrafficSignal {
|
||||
let mut ok = false;
|
||||
for r in &i.roads {
|
||||
if map.roads[r.0].osm_tags.get(osm::HIGHWAY) != Some(&"construction".to_string()) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
i.intersection_type = IntersectionType::StopSign;
|
||||
}
|
||||
}
|
||||
|
||||
if i.incoming_lanes.is_empty() || i.outgoing_lanes.is_empty() {
|
||||
timer.warn(format!("{:?} is orphaned!", i));
|
||||
continue;
|
||||
}
|
||||
|
||||
for t in turns::make_all_turns(map.driving_side, i, &map.roads, &map.lanes, timer) {
|
||||
assert!(!map.turns.contains_key(&t.id));
|
||||
i.turns.insert(t.id);
|
||||
if t.geom.length() < geom::EPSILON_DIST {
|
||||
timer.warn(format!("{} is a very short turn", t.id));
|
||||
}
|
||||
map.turns.insert(t.id, t);
|
||||
}
|
||||
}
|
||||
|
||||
timer.start("find parking blackholes");
|
||||
for (l, redirect) in connectivity::redirect_parking_blackholes(&map, timer) {
|
||||
map.lanes[l.0].parking_blackhole = Some(redirect);
|
||||
}
|
||||
timer.stop("find parking blackholes");
|
||||
|
||||
map.buildings = buildings::make_all_buildings(&raw.buildings, &map, timer);
|
||||
for b in &map.buildings {
|
||||
let lane = b.sidewalk();
|
||||
|
||||
// TODO Could be more performant and cleanly written
|
||||
let mut bldgs = map.lanes[lane.0].building_paths.clone();
|
||||
bldgs.push(b.id);
|
||||
bldgs.sort_by_key(|b| map.buildings[b.0].front_path.sidewalk.dist_along());
|
||||
map.lanes[lane.0].building_paths = bldgs;
|
||||
}
|
||||
|
||||
map.parking_lots =
|
||||
buildings::make_all_parking_lots(&raw.parking_lots, &raw.parking_aisles, &map, timer);
|
||||
|
||||
map.zones = zones::make_all_zones(&map);
|
||||
for z in &map.zones {
|
||||
for r in &z.members {
|
||||
map.roads[r.0].zone = Some(z.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, a) in raw.areas.iter().enumerate() {
|
||||
map.areas.push(Area {
|
||||
id: AreaID(idx),
|
||||
area_type: a.area_type,
|
||||
polygon: a.polygon.clone(),
|
||||
osm_tags: a.osm_tags.clone(),
|
||||
osm_id: a.osm_id,
|
||||
});
|
||||
}
|
||||
|
||||
bridges::find_bridges(&mut map.roads, &map.bounds, timer);
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
fn is_border(intersection: &Intersection, lanes: &Vec<Lane>) -> bool {
|
||||
// RawIntersection said it is.
|
||||
if intersection.is_border() {
|
||||
|
Loading…
Reference in New Issue
Block a user