diff --git a/convert_osm/src/extract.rs b/convert_osm/src/extract.rs index 6620b38c29..7cfeadf55d 100644 --- a/convert_osm/src/extract.rs +++ b/convert_osm/src/extract.rs @@ -9,8 +9,7 @@ use map_model::raw::{RawArea, RawBuilding, RawMap, RawParkingLot, RawRoad, Restr use map_model::{osm, Amenity, AreaType, NamePerLanguage}; use crate::osm_geom::{get_multipolygon_members, glue_multipolygon, multipoly_geometry}; -use crate::transit; -use crate::Options; +use crate::{transit, Options}; pub struct OsmExtract { /// Unsplit roads @@ -409,6 +408,7 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool { }; if !vec![ + "footway", "living_street", "motorway", "motorway_link", @@ -418,6 +418,7 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool { "secondary", "secondary_link", "service", + "steps", "tertiary", "tertiary_link", "trunk", @@ -429,6 +430,10 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool { return false; } + if (highway == "footway" || highway == "steps") && opts.map_config.inferred_sidewalks { + return false; + } + // Service roads can represent lots of things, most of which we don't want to keep yet. What's // allowed here is just based on what's been encountered so far in Seattle and Kraków. if highway == "service" { @@ -459,7 +464,7 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool { // If there's no sidewalk data in OSM already, then make an assumption and mark that // it's inferred. - if !tags.contains_key(osm::SIDEWALK) { + if !tags.contains_key(osm::SIDEWALK) && opts.map_config.inferred_sidewalks { tags.insert(osm::INFERRED_SIDEWALKS, "true"); if tags.is_any(osm::HIGHWAY, vec!["motorway", "motorway_link"]) || tags.is("junction", "roundabout") diff --git a/convert_osm/src/snappy.rs b/convert_osm/src/snappy.rs index 8367c4a6f8..cea8a3fd0d 100644 --- a/convert_osm/src/snappy.rs +++ b/convert_osm/src/snappy.rs @@ -41,7 +41,7 @@ pub fn snap_cycleways(map: &RawMap, timer: &mut Timer) { if r.is_light_rail() || r.is_footway() || r.is_service() { continue; } - let (pl, total_width) = r.get_geometry(*id, map.config.driving_side); + let (pl, total_width) = r.get_geometry(*id, &map.config); road_edges.insert( (*id, Direction::Fwd), pl.must_shift_right(total_width / 2.0), diff --git a/importer/src/berlin.rs b/importer/src/berlin.rs index 282fef0fb2..2e078643e9 100644 --- a/importer/src/berlin.rs +++ b/importer/src/berlin.rs @@ -72,6 +72,7 @@ pub fn osm_to_raw(name: &str, timer: &mut Timer, config: &ImporterConfiguration) map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::JustOSM, diff --git a/importer/src/krakow.rs b/importer/src/krakow.rs index 590f934ef4..cb1eeb19c3 100644 --- a/importer/src/krakow.rs +++ b/importer/src/krakow.rs @@ -31,6 +31,7 @@ pub fn osm_to_raw(name: &str, timer: &mut abstutil::Timer, config: &ImporterConf map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Right, bikes_can_use_bus_lanes: false, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::SomeAdditionalWhereNoData { pct: 90 }, diff --git a/importer/src/london.rs b/importer/src/london.rs index dd5c002c23..aaf4b451f2 100644 --- a/importer/src/london.rs +++ b/importer/src/london.rs @@ -31,6 +31,7 @@ pub fn osm_to_raw(name: &str, timer: &mut abstutil::Timer, config: &ImporterConf map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Left, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::JustOSM, diff --git a/importer/src/main.rs b/importer/src/main.rs index 20ff18bbba..d9f6065e03 100644 --- a/importer/src/main.rs +++ b/importer/src/main.rs @@ -225,6 +225,7 @@ fn oneshot( map_model::DrivingSide::Left }, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::JustOSM, diff --git a/importer/src/seattle.rs b/importer/src/seattle.rs index 162e5d7992..acc0a39266 100644 --- a/importer/src/seattle.rs +++ b/importer/src/seattle.rs @@ -81,6 +81,7 @@ pub fn osm_to_raw(name: &str, timer: &mut abstutil::Timer, config: &ImporterConf map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::Blockface(abstutil::path( diff --git a/importer/src/tel_aviv.rs b/importer/src/tel_aviv.rs index 5af060363c..543dc4aeda 100644 --- a/importer/src/tel_aviv.rs +++ b/importer/src/tel_aviv.rs @@ -31,6 +31,7 @@ pub fn osm_to_raw(name: &str, timer: &mut abstutil::Timer, config: &ImporterConf map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::SomeAdditionalWhereNoData { pct: 50 }, diff --git a/importer/src/xian.rs b/importer/src/xian.rs index 61c0d41426..f3858c2b8c 100644 --- a/importer/src/xian.rs +++ b/importer/src/xian.rs @@ -28,6 +28,7 @@ pub fn osm_to_raw(name: &str, timer: &mut abstutil::Timer, config: &ImporterConf map_config: map_model::MapConfig { driving_side: map_model::DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, onstreet_parking: convert_osm::OnstreetParking::JustOSM, diff --git a/map_model/src/edits/mod.rs b/map_model/src/edits/mod.rs index 2541568b14..cb12146ef2 100644 --- a/map_model/src/edits/mod.rs +++ b/map_model/src/edits/mod.rs @@ -13,7 +13,7 @@ use geom::{Speed, Time}; use crate::make::initial::lane_specs::get_lane_specs_ltr; use crate::{ connectivity, AccessRestrictions, BusRouteID, ControlStopSign, ControlTrafficSignal, Direction, - DrivingSide, IntersectionID, IntersectionType, LaneID, LaneType, Map, PathConstraints, + IntersectionID, IntersectionType, LaneID, LaneType, Map, MapConfig, PathConstraints, Pathfinder, Road, RoadID, TurnID, Zone, }; @@ -61,9 +61,9 @@ pub struct EditRoad { } impl EditRoad { - pub fn get_orig_from_osm(r: &Road, driving_side: DrivingSide) -> EditRoad { + pub fn get_orig_from_osm(r: &Road, cfg: &MapConfig) -> EditRoad { EditRoad { - lanes_ltr: get_lane_specs_ltr(&r.osm_tags, driving_side) + lanes_ltr: get_lane_specs_ltr(&r.osm_tags, cfg) .into_iter() .map(|spec| (spec.lt, spec.dir)) .collect(), @@ -194,8 +194,7 @@ impl MapEdits { } retain_btreeset(&mut self.changed_roads, |r| { - map.get_r_edit(*r) - != EditRoad::get_orig_from_osm(map.get_r(*r), map.config.driving_side) + map.get_r_edit(*r) != EditRoad::get_orig_from_osm(map.get_r(*r), &map.config) }); retain_btreemap(&mut self.original_intersections, |i, orig| { map.get_i_edit(*i) != orig.clone() @@ -211,7 +210,7 @@ impl MapEdits { for r in &self.changed_roads { self.commands.push(EditCmd::ChangeRoad { r: *r, - old: EditRoad::get_orig_from_osm(map.get_r(*r), map.config.driving_side), + old: EditRoad::get_orig_from_osm(map.get_r(*r), &map.config), new: map.get_r_edit(*r), }); } @@ -238,7 +237,7 @@ impl MapEdits { let mut roads = BTreeSet::new(); for r in &self.changed_roads { let r = map.get_r(*r); - let orig = EditRoad::get_orig_from_osm(r, map.get_config().driving_side); + let orig = EditRoad::get_orig_from_osm(r, map.get_config()); // What exactly changed? if r.speed_limit != orig.speed_limit || r.access_restrictions != orig.access_restrictions diff --git a/map_model/src/make/initial/lane_specs.rs b/map_model/src/make/initial/lane_specs.rs index d64ef09d74..1c830c5e30 100644 --- a/map_model/src/make/initial/lane_specs.rs +++ b/map_model/src/make/initial/lane_specs.rs @@ -5,8 +5,8 @@ use abstutil::Tags; use geom::Distance; use crate::{ - osm, Direction, DrivingSide, LaneType, NORMAL_LANE_THICKNESS, SERVICE_ROAD_LANE_THICKNESS, - SHOULDER_THICKNESS, SIDEWALK_THICKNESS, + osm, Direction, DrivingSide, LaneType, MapConfig, NORMAL_LANE_THICKNESS, + SERVICE_ROAD_LANE_THICKNESS, SHOULDER_THICKNESS, SIDEWALK_THICKNESS, }; #[derive(PartialEq)] @@ -40,12 +40,12 @@ fn back(lt: LaneType) -> LaneSpec { } } -pub fn get_lane_specs_ltr(tags: &Tags, driving_side: DrivingSide) -> Vec { +pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec { // Easy special cases first. if tags.is_any("railway", vec!["light_rail", "rail"]) { return vec![fwd(LaneType::LightRail)]; } - if tags.is(osm::HIGHWAY, "footway") { + if tags.is_any(osm::HIGHWAY, vec!["footway", "pedestrian", "steps"]) { return vec![fwd(LaneType::Sidewalk)]; } @@ -127,7 +127,7 @@ pub fn get_lane_specs_ltr(tags: &Tags, driving_side: DrivingSide) -> Vec Vec Vec Road { - let lane_specs_ltr = lane_specs::get_lane_specs_ltr(&r.osm_tags, driving_side); - let (trimmed_center_pts, total_width) = r.get_geometry(id, driving_side); + pub fn new(id: OriginalRoad, r: &RawRoad, cfg: &MapConfig) -> Road { + let lane_specs_ltr = lane_specs::get_lane_specs_ltr(&r.osm_tags, cfg); + let (trimmed_center_pts, total_width) = r.get_geometry(id, cfg); Road { id, @@ -95,8 +95,7 @@ impl InitialMap { m.intersections.get_mut(&id.i1).unwrap().roads.insert(*id); m.intersections.get_mut(&id.i2).unwrap().roads.insert(*id); - m.roads - .insert(*id, Road::new(*id, r, raw.config.driving_side)); + m.roads.insert(*id, Road::new(*id, r, &raw.config)); } timer.start_iter("find each intersection polygon", m.intersections.len()); diff --git a/map_model/src/make/mod.rs b/map_model/src/make/mod.rs index d47d0a57c6..9a6a39779d 100644 --- a/map_model/src/make/mod.rs +++ b/map_model/src/make/mod.rs @@ -132,7 +132,8 @@ impl Map { dst_i: i2, speed_limit: Speed::ZERO, zorder: if let Some(layer) = raw.roads[&r.id].osm_tags.get("layer") { - layer.parse::().unwrap() + // Just drop .5 for now + layer.parse::().unwrap() as isize } else { 0 }, diff --git a/map_model/src/map.rs b/map_model/src/map.rs index 2ff6507a9d..0b87576817 100644 --- a/map_model/src/map.rs +++ b/map_model/src/map.rs @@ -22,6 +22,10 @@ pub struct MapConfig { /// (Australia). pub driving_side: DrivingSide, pub bikes_can_use_bus_lanes: bool, + /// If true, roads without explicitly tagged sidewalks may have sidewalks or shoulders. If + /// false, no sidewalks will be inferred if not tagged in OSM, and separate sidewalks will be + /// included. + pub inferred_sidewalks: bool, } #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)] @@ -158,6 +162,7 @@ impl Map { config: MapConfig { driving_side: DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, pathfinder: Pathfinder::Dijkstra, pathfinder_dirty: false, diff --git a/map_model/src/raw.rs b/map_model/src/raw.rs index 5c883cb941..f466db59ab 100644 --- a/map_model/src/raw.rs +++ b/map_model/src/raw.rs @@ -102,6 +102,7 @@ impl RawMap { config: MapConfig { driving_side: DrivingSide::Right, bikes_can_use_bus_lanes: true, + inferred_sidewalks: true, }, } } @@ -163,10 +164,7 @@ impl RawMap { }; let mut roads = BTreeMap::new(); for r in &i.roads { - roads.insert( - *r, - initial::Road::new(*r, &self.roads[r], self.config.driving_side), - ); + roads.insert(*r, initial::Road::new(*r, &self.roads[r], &self.config)); } let (poly, debug) = initial::intersection_polygon(&i, &mut roads, timer).unwrap(); @@ -262,12 +260,8 @@ pub struct RawRoad { impl RawRoad { /// Returns the corrected center and total width - pub fn get_geometry( - &self, - id: OriginalRoad, - driving_side: DrivingSide, - ) -> (PolyLine, Distance) { - let lane_specs = get_lane_specs_ltr(&self.osm_tags, driving_side); + pub fn get_geometry(&self, id: OriginalRoad, cfg: &MapConfig) -> (PolyLine, Distance) { + let lane_specs = get_lane_specs_ltr(&self.osm_tags, cfg); let mut total_width = Distance::ZERO; let mut sidewalk_right = None; let mut sidewalk_left = None; @@ -303,7 +297,8 @@ impl RawRoad { } pub fn is_footway(&self) -> bool { - self.osm_tags.is(osm::HIGHWAY, "pedestrian") + self.osm_tags + .is_any(osm::HIGHWAY, vec!["footway", "pedestrian", "steps"]) } pub fn is_service(&self) -> bool {