mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Optionally import sidewalks and separate footpaths exactly as they're in OSM, instead of attempting any inference. This is a way to move forward on #161 without having to cutover to it all at once.
This commit is contained in:
parent
b1f4ca0b1b
commit
bf0dce2c18
@ -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")
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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 },
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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 },
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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<LaneSpec> {
|
||||
pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> {
|
||||
// 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<LaneSpe
|
||||
}
|
||||
|
||||
if driving_lane == LaneType::Construction {
|
||||
return assemble_ltr(fwd_side, back_side, driving_side);
|
||||
return assemble_ltr(fwd_side, back_side, cfg.driving_side);
|
||||
}
|
||||
|
||||
let fwd_bus_spec = if let Some(s) = tags.get("bus:lanes:forward") {
|
||||
@ -228,13 +228,13 @@ pub fn get_lane_specs_ltr(tags: &Tags, driving_side: DrivingSide) -> Vec<LaneSpe
|
||||
back_side.push(back(LaneType::Sidewalk));
|
||||
}
|
||||
} else if tags.is(osm::SIDEWALK, "right") {
|
||||
if driving_side == DrivingSide::Right {
|
||||
if cfg.driving_side == DrivingSide::Right {
|
||||
fwd_side.push(fwd(LaneType::Sidewalk));
|
||||
} else {
|
||||
back_side.push(back(LaneType::Sidewalk));
|
||||
}
|
||||
} else if tags.is(osm::SIDEWALK, "left") {
|
||||
if driving_side == DrivingSide::Right {
|
||||
if cfg.driving_side == DrivingSide::Right {
|
||||
back_side.push(back(LaneType::Sidewalk));
|
||||
} else {
|
||||
fwd_side.push(fwd(LaneType::Sidewalk));
|
||||
@ -272,14 +272,16 @@ pub fn get_lane_specs_ltr(tags: &Tags, driving_side: DrivingSide) -> Vec<LaneSpe
|
||||
need_back_shoulder = false;
|
||||
}
|
||||
|
||||
if cfg.inferred_sidewalks {
|
||||
if need_fwd_shoulder {
|
||||
fwd_side.push(fwd(LaneType::Shoulder));
|
||||
}
|
||||
if need_back_shoulder {
|
||||
back_side.push(back(LaneType::Shoulder));
|
||||
}
|
||||
}
|
||||
|
||||
assemble_ltr(fwd_side, back_side, driving_side)
|
||||
assemble_ltr(fwd_side, back_side, cfg.driving_side)
|
||||
}
|
||||
|
||||
fn assemble_ltr(
|
||||
@ -428,7 +430,12 @@ mod tests {
|
||||
"^^^",
|
||||
),
|
||||
] {
|
||||
let actual = get_lane_specs_ltr(&tags(input.clone()), driving_side);
|
||||
let cfg = MapConfig {
|
||||
driving_side,
|
||||
bikes_can_use_bus_lanes: true,
|
||||
inferred_sidewalks: true,
|
||||
};
|
||||
let actual = get_lane_specs_ltr(&tags(input.clone()), &cfg);
|
||||
let actual_lt = actual
|
||||
.iter()
|
||||
.map(|s| lt_to_char(s.lt))
|
||||
|
@ -10,7 +10,7 @@ use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
|
||||
|
||||
pub use self::geometry::intersection_polygon;
|
||||
use crate::raw::{OriginalRoad, RawMap, RawRoad};
|
||||
use crate::{osm, DrivingSide, IntersectionType};
|
||||
use crate::{osm, IntersectionType, MapConfig};
|
||||
|
||||
mod geometry;
|
||||
pub mod lane_specs;
|
||||
@ -35,9 +35,9 @@ pub struct Road {
|
||||
}
|
||||
|
||||
impl Road {
|
||||
pub fn new(id: OriginalRoad, r: &RawRoad, driving_side: DrivingSide) -> 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());
|
||||
|
@ -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::<isize>().unwrap()
|
||||
// Just drop .5 for now
|
||||
layer.parse::<f64>().unwrap() as isize
|
||||
} else {
|
||||
0
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user