-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start importing all footways and shared-use paths! #87, #77 #90
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,9 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> { | |
|
||
// TODO This hides a potentially expensive (on a hot-path) clone | ||
let mut tags = tags.clone(); | ||
// This'll do weird things for the special cases of railways and cycleways/footways, but the | ||
// added tags will be ignored, so it doesn't matter too much. Running this later causes borrow | ||
// checker problems. | ||
infer_sidewalk_tags(&mut tags, cfg); | ||
|
||
let fwd = |lt: LaneType| LaneSpec { | ||
|
@@ -31,33 +34,20 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> { | |
if tags.is_any("railway", vec!["light_rail", "rail"]) { | ||
return vec![fwd(LaneType::LightRail)]; | ||
} | ||
if tags.is(osm::HIGHWAY, "steps") { | ||
return vec![fwd(LaneType::Sidewalk)]; | ||
} | ||
// Eventually, we should have some kind of special LaneType for shared walking/cycling paths of | ||
// different kinds. Until then, model by making bike lanes and a shoulder for walking. | ||
if tags.is_any( | ||
osm::HIGHWAY, | ||
vec!["cycleway", "footway", "path", "pedestrian", "track"], | ||
) { | ||
// If it just allows foot traffic, simply make it a sidewalk. For most of the above highway | ||
// types, assume bikes are allowed, except for footways, where they must be explicitly | ||
// allowed. | ||
if tags.is("bicycle", "no") | ||
|| (tags.is(osm::HIGHWAY, "footway") | ||
&& !tags.is_any("bicycle", vec!["designated", "yes", "dismount"])) | ||
{ | ||
return vec![fwd(LaneType::Sidewalk)]; | ||
} | ||
// Otherwise, there'll always be a bike lane. | ||
|
||
// If it's a primarily cycleway, have directional bike lanes and add a shoulder for walking | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's still odd to use two directional lanes for this case. I think There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I agree. An "alternates" case too. Most reads of the value will boil down to "is travel supported in this direction", right? Routing could implement "alternating" and use that for "both ways" too. I called it |
||
// TODO Consider variations of SharedUse that specify the priority is cyclists over pedestrians | ||
// in this case? | ||
if tags.is(osm::HIGHWAY, "cycleway") { | ||
let mut fwd_side = vec![fwd(LaneType::Biking)]; | ||
let mut back_side = if tags.is("oneway", "yes") { | ||
vec![] | ||
} else { | ||
vec![back(LaneType::Biking)] | ||
}; | ||
|
||
// TODO If this cycleway is parallel to a main road, we might end up with double sidewalks. | ||
// Once snapping works well, this problem will improve | ||
if !tags.is("foot", "no") { | ||
fwd_side.push(fwd(LaneType::Shoulder)); | ||
if !back_side.is_empty() { | ||
|
@@ -67,6 +57,28 @@ pub fn get_lane_specs_ltr(tags: &Tags, cfg: &MapConfig) -> Vec<LaneSpec> { | |
return LaneSpec::assemble_ltr(fwd_side, back_side, cfg.driving_side); | ||
} | ||
|
||
// These roads will only exist if cfg.inferred_sidewalks is false | ||
if tags.is(osm::HIGHWAY, "footway") && tags.is_any("footway", vec!["crossing", "sidewalk"]) { | ||
// Treating a crossing as a sidewalk for now. Eventually crossings need to be dealt with | ||
// completely differently. | ||
return vec![fwd(LaneType::Sidewalk)]; | ||
} | ||
|
||
// Handle pedestrian-oriented spaces | ||
if tags.is_any( | ||
osm::HIGHWAY, | ||
vec!["footway", "path", "pedestrian", "steps", "track"], | ||
) { | ||
// Assume no bikes unless they're explicitly allowed | ||
if tags.is_any("bicycle", vec!["designated", "yes", "dismount"]) { | ||
return vec![fwd(LaneType::SharedUse)]; | ||
} | ||
|
||
return vec![fwd(LaneType::Footway)]; | ||
} | ||
|
||
// Most cases are below -- it's a "normal road" | ||
|
||
// TODO Reversible roads should be handled differently? | ||
let oneway = | ||
tags.is_any("oneway", vec!["yes", "reversible"]) || tags.is("junction", "roundabout"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,11 @@ pub enum LaneType { | |
Construction, | ||
LightRail, | ||
Buffer(BufferType), | ||
/// Some kind of pedestrian-only path unassociated with a road | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very related to #77. I'm not happy with this classification as "only pedestrians" and "both pedestrians and cyclists." Things like living streets or alleyways, where motor vehicles are also allowed, aren't captured yet. Maybe we just need one shared use lane type, with a way to specify the legal or cultural priority between vehicles. For instance, I know many streets in the US without pavement, where it's effectively shared use and motor vehicles get priority. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think when it comes down to it, every lane is a list of specific designations and restrictions. There are also classifications, informed by the locale, I suppose, like "only pedestrians", "bike lane" or "bus lane (bikes allowed)" that inform markup decisions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this way of thinking about it. Going to start a fresh issue on this soon to consolidate all of the thoughts around this... |
||
Footway, | ||
/// Some kind of shared pedestrian+bicycle space. May be associated with a road or not. Unclear | ||
/// which mode has effective priority. | ||
SharedUse, | ||
} | ||
|
||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] | ||
|
@@ -61,6 +66,8 @@ impl LaneType { | |
LaneType::Construction => false, | ||
LaneType::LightRail => true, | ||
LaneType::Buffer(_) => false, | ||
LaneType::Footway => false, | ||
LaneType::SharedUse => true, | ||
} | ||
} | ||
|
||
|
@@ -76,17 +83,22 @@ impl LaneType { | |
LaneType::Construction => false, | ||
LaneType::LightRail => true, | ||
LaneType::Buffer(_) => false, | ||
LaneType::Footway => true, | ||
LaneType::SharedUse => true, | ||
} | ||
} | ||
|
||
pub fn is_walkable(self) -> bool { | ||
self == LaneType::Sidewalk || self == LaneType::Shoulder | ||
matches!( | ||
self, | ||
LaneType::Sidewalk | LaneType::Shoulder | LaneType::Footway | LaneType::SharedUse | ||
) | ||
} | ||
|
||
pub fn describe(self) -> &'static str { | ||
match self { | ||
LaneType::Driving => "a general-purpose driving lane", | ||
LaneType::Biking => "a protected bike lane", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "protected" never ever made sense, I erroneously wrote this long ago. Also this is a localization issue... "cycling lane" or "cycle lane" would fit better in the UK. But anyway. |
||
LaneType::Biking => "a bike lane", | ||
LaneType::Bus => "a bus-only lane", | ||
LaneType::Parking => "an on-street parking lane", | ||
LaneType::Sidewalk => "a sidewalk", | ||
|
@@ -99,6 +111,8 @@ impl LaneType { | |
LaneType::Buffer(BufferType::Planters) => "planter barriers", | ||
LaneType::Buffer(BufferType::JerseyBarrier) => "a Jersey barrier", | ||
LaneType::Buffer(BufferType::Curb) => "a raised curb", | ||
LaneType::Footway => "a footway", | ||
LaneType::SharedUse => "a shared-use walking/cycling path", | ||
} | ||
} | ||
|
||
|
@@ -118,6 +132,8 @@ impl LaneType { | |
LaneType::Buffer(BufferType::Planters) => "planters", | ||
LaneType::Buffer(BufferType::JerseyBarrier) => "Jersey barrier", | ||
LaneType::Buffer(BufferType::Curb) => "curb", | ||
LaneType::Footway => "footway", | ||
LaneType::SharedUse => "shared-use path", | ||
} | ||
} | ||
|
||
|
@@ -137,6 +153,8 @@ impl LaneType { | |
"planters" => Some(LaneType::Buffer(BufferType::Planters)), | ||
"Jersey barrier" => Some(LaneType::Buffer(BufferType::JerseyBarrier)), | ||
"curb" => Some(LaneType::Buffer(BufferType::Curb)), | ||
"footway" => Some(LaneType::Footway), | ||
"shared-use path" => Some(LaneType::SharedUse), | ||
_ => None, | ||
} | ||
} | ||
|
@@ -154,6 +172,8 @@ impl LaneType { | |
LaneType::Construction => 'x', | ||
LaneType::LightRail => 'l', | ||
LaneType::Buffer(_) => '|', | ||
LaneType::Footway => 'f', | ||
LaneType::SharedUse => 'V', | ||
dabreegster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
|
@@ -170,6 +190,8 @@ impl LaneType { | |
'x' => LaneType::Construction, | ||
'l' => LaneType::LightRail, | ||
'|' => LaneType::Buffer(BufferType::FlexPosts), | ||
'f' => LaneType::Footway, | ||
'V' => LaneType::SharedUse, | ||
_ => panic!("from_char({}) undefined", x), | ||
} | ||
} | ||
|
@@ -249,6 +271,8 @@ impl LaneSpec { | |
vec![(Distance::meters(1.5), "default")] | ||
} | ||
LaneType::Buffer(BufferType::Curb) => vec![(Distance::meters(0.5), "default")], | ||
LaneType::Footway => vec![(Distance::meters(2.0), "default")], | ||
LaneType::SharedUse => vec![(Distance::meters(3.0), "default")], | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,25 @@ export const makeLanePolygonLayer = (text) => { | |
|
||
return new L.geoJSON(JSON.parse(text), { | ||
style: function (feature) { | ||
if (feature.properties.type == "Footway") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The styling is not great. Any ideas for distinguishing the two? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's time to start copying design from the strassenraumkarte-neukoelln :P There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I already lifted the dashed outline idea and path color from there ;) |
||
return { | ||
fill: true, | ||
fillColor: "#DDDDE8", | ||
stroke: true, | ||
color: "black", | ||
dashArray: "5,10", | ||
}; | ||
} | ||
if (feature.properties.type == "SharedUse") { | ||
return { | ||
fill: true, | ||
fillColor: "#E5E1BB", | ||
stroke: true, | ||
color: "black", | ||
dashArray: "5,10", | ||
}; | ||
} | ||
|
||
return { | ||
fill: true, | ||
fillColor: colors[feature.properties.type] || "red", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this experiment now just means "bring in
highway=footway, footway={sidewalk,crossing}
ways". All of the new stuff in this PR works both with and without this experiment