From 9c92b2e6489d8b9cb6133de75155e57fa4994464 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Fri, 11 Oct 2024 18:01:20 +0200 Subject: [PATCH 01/15] Obey configured tag mapping in walkable area processing Walkable area builder used hardcoded bike+pedestrial default permissions for area edges. Now default permissions take tag mapping into account. --- .../graph_builder/module/osm/OsmDatabase.java | 8 +-- .../module/osm/WalkableAreaBuilder.java | 51 ++++++++----------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java b/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java index 88b1fe9f7da..c1c70f17fac 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java @@ -791,9 +791,11 @@ private void processMultipolygonRelations() { * Handler for a new Area (single way area or multipolygon relations) */ private void newArea(Area area) { - StreetTraversalPermission permissions = area.parent.overridePermissions( - StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE - ); + StreetTraversalPermission permissions = area.parent + .getOsmProvider() + .getWayPropertySet() + .getDataForWay(area.parent) + .getPermission(); if (area.parent.isRoutable() && permissions != StreetTraversalPermission.NONE) { walkableAreas.add(area); } diff --git a/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java b/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java index f27d80d5617..81f59287939 100644 --- a/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java +++ b/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java @@ -49,6 +49,8 @@ import org.opentripplanner.street.search.StreetSearchBuilder; import org.opentripplanner.street.search.state.State; import org.opentripplanner.street.search.strategy.DominanceFunctions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Theoretically, it is not correct to build the visibility graph on the joined polygon of areas @@ -70,6 +72,8 @@ */ class WalkableAreaBuilder { + private static final Logger LOG = LoggerFactory.getLogger(WalkableAreaBuilder.class); + private final DataImportIssueStore issueStore; private final int maxAreaNodes; @@ -499,9 +503,14 @@ private Set createSegments( Area area = intersects.getFirst(); OsmWithTags areaEntity = area.parent; - StreetTraversalPermission areaPermissions = areaEntity.overridePermissions( - StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE - ); + WayProperties wayData; + if (!wayPropertiesCache.containsKey(areaEntity)) { + wayData = areaEntity.getOsmProvider().getWayPropertySet().getDataForWay(areaEntity); + wayPropertiesCache.put(areaEntity, wayData); + } else { + wayData = wayPropertiesCache.get(areaEntity); + } + StreetTraversalPermission areaPermissions = wayData.getPermission(); float carSpeed = areaEntity .getOsmProvider() @@ -520,8 +529,8 @@ private Set createSegments( startEndpoint.getLabel() + " to " + endEndpoint.getLabel(); - I18NString name = namer.getNameForWay(areaEntity, label); + I18NString name = namer.getNameForWay(areaEntity, label); AreaEdgeBuilder streetEdgeBuilder = new AreaEdgeBuilder() .withFromVertex(startEndpoint) .withToVertex(endEndpoint) @@ -543,8 +552,8 @@ private Set createSegments( endEndpoint.getLabel() + " to " + startEndpoint.getLabel(); - name = namer.getNameForWay(areaEntity, label); + name = namer.getNameForWay(areaEntity, label); AreaEdgeBuilder backStreetEdgeBuilder = new AreaEdgeBuilder() .withFromVertex(endEndpoint) .withToVertex(startEndpoint) @@ -559,22 +568,10 @@ private Set createSegments( .withWheelchairAccessible(areaEntity.isWheelchairAccessible()) .withLink(areaEntity.isLink()); - if (!wayPropertiesCache.containsKey(areaEntity)) { - WayProperties wayData = areaEntity - .getOsmProvider() - .getWayPropertySet() - .getDataForWay(areaEntity); - wayPropertiesCache.put(areaEntity, wayData); - } - AreaEdge street = streetEdgeBuilder.buildAndConnect(); + AreaEdge backStreet = backStreetEdgeBuilder.buildAndConnect(); - normalizer.applyWayProperties( - street, - backStreet, - wayPropertiesCache.get(areaEntity), - areaEntity - ); + normalizer.applyWayProperties(street, backStreet, wayData, areaEntity); return Set.of(street, backStreet); } else { // take the part that intersects with the start vertex @@ -640,12 +637,12 @@ private void createNamedAreas(AreaEdgeList edgeList, Ring ring, Collection I18NString name = namer.getNameForWay(areaEntity, id); namedArea.setName(name); + WayProperties wayData; if (!wayPropertiesCache.containsKey(areaEntity)) { - WayProperties wayData = areaEntity - .getOsmProvider() - .getWayPropertySet() - .getDataForWay(areaEntity); + wayData = areaEntity.getOsmProvider().getWayPropertySet().getDataForWay(areaEntity); wayPropertiesCache.put(areaEntity, wayData); + } else { + wayData = wayPropertiesCache.get(areaEntity); } double bicycleSafety = wayPropertiesCache.get(areaEntity).bicycleSafety().forward(); @@ -653,14 +650,8 @@ private void createNamedAreas(AreaEdgeList edgeList, Ring ring, Collection double walkSafety = wayPropertiesCache.get(areaEntity).walkSafety().forward(); namedArea.setWalkSafetyMultiplier(walkSafety); - namedArea.setOriginalEdges(intersection); - - StreetTraversalPermission permission = areaEntity.overridePermissions( - StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE - ); - namedArea.setPermission(permission); - + namedArea.setPermission(wayData.getPermission()); edgeList.addArea(namedArea); } } From aaf304d44da2a03b49f8ce5d1b5da5babd843922 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 14 Oct 2024 11:52:25 +0300 Subject: [PATCH 02/15] Do not allow cycling on public transit platforms Rule whicgh assigns pedestrian permissions to transit platforms is not enough, because another rule which contains more tags overrules it. --- .../java/org/opentripplanner/osm/tagmapping/DefaultMapper.java | 1 + .../java/org/opentripplanner/osm/tagmapping/FinlandMapper.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java index faa666c750a..c0b786d02e8 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java @@ -65,6 +65,7 @@ public void populateProperties(WayPropertySet props) { props.setProperties("highway=crossing", pedestrianWayProperties); props.setProperties("highway=platform", pedestrianWayProperties); props.setProperties("public_transport=platform", pedestrianWayProperties); + props.setProperties("public_transport=platform;area=yes", pedestrianWayProperties); props.setProperties("railway=platform", pedestrianWayProperties); props.setProperties("footway=sidewalk;highway=footway", pedestrianWayProperties); props.setProperties("mtb:scale=1", pedestrianWayProperties); diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java index e796ebff17f..86d80605ca6 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java @@ -91,6 +91,8 @@ else if (speedLimit <= 16.65f) { // No biking on designated footways/sidewalks props.setProperties("highway=footway", withModes(PEDESTRIAN)); + props.setProperties("highway=footway;area=yes", withModes(PEDESTRIAN)); + //props.setProperties("public_transport=platform;area=yes", withModes(PEDESTRIAN)); props.setProperties("footway=sidewalk;highway=footway", withModes(PEDESTRIAN)); // Walking on segregated ways is safer than when cycling and walking happens on the same lane From 2fde06af6beaec097491bfe449c20e7877ad811f Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 14 Oct 2024 11:57:41 +0300 Subject: [PATCH 03/15] Update permission docs --- doc/user/osm/Default.md | 1 + doc/user/osm/Finland.md | 2 ++ doc/user/osm/Germany.md | 1 + doc/user/osm/UK.md | 1 + 4 files changed, 5 insertions(+) diff --git a/doc/user/osm/Default.md b/doc/user/osm/Default.md index 814420b791f..a77ebb41b82 100644 --- a/doc/user/osm/Default.md +++ b/doc/user/osm/Default.md @@ -33,6 +33,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | +| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | diff --git a/doc/user/osm/Finland.md b/doc/user/osm/Finland.md index 8a60b5f0b13..cdf56dab057 100644 --- a/doc/user/osm/Finland.md +++ b/doc/user/osm/Finland.md @@ -49,6 +49,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `present(highway); ice_road=yes` | `NONE` | | | | `present(highway); winter_road=yes` | `NONE` | | | | `highway=footway` | `PEDESTRIAN` | | | +| `highway=footway; area=yes` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `highway=cycleway; segregated=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | 1.1 | | `highway=footway; bridge=yes` | `PEDESTRIAN` | | | @@ -77,6 +78,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | +| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | diff --git a/doc/user/osm/Germany.md b/doc/user/osm/Germany.md index 922aa3af836..fb6581a8d3b 100644 --- a/doc/user/osm/Germany.md +++ b/doc/user/osm/Germany.md @@ -42,6 +42,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | +| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | diff --git a/doc/user/osm/UK.md b/doc/user/osm/UK.md index 4a640caf95c..1eebd08c880 100644 --- a/doc/user/osm/UK.md +++ b/doc/user/osm/UK.md @@ -47,6 +47,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | +| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | From 1dc168adbd9f55f4b02840e550df7584151f1f36 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 14 Oct 2024 15:48:04 +0300 Subject: [PATCH 04/15] Extend mappers from default mapper OSM tag mappers now use normal OOP inheritance. It is usually a bad idea to implement classes directly from an inteface. --- .../org/opentripplanner/osm/tagmapping/AtlantaMapper.java | 5 ++--- .../opentripplanner/osm/tagmapping/ConstantSpeedMapper.java | 5 ++--- .../org/opentripplanner/osm/tagmapping/FinlandMapper.java | 5 ++--- .../org/opentripplanner/osm/tagmapping/GermanyMapper.java | 5 ++--- .../org/opentripplanner/osm/tagmapping/HoustonMapper.java | 6 ++---- .../org/opentripplanner/osm/tagmapping/NorwayMapper.java | 4 ++-- .../org/opentripplanner/osm/tagmapping/PortlandMapper.java | 5 ++--- .../java/org/opentripplanner/osm/tagmapping/UKMapper.java | 5 ++--- 8 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java index 4d190c0b667..7ae6d985785 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java @@ -16,7 +16,7 @@ * @see DefaultMapper */ -class AtlantaMapper implements OsmTagMapper { +class AtlantaMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -27,7 +27,6 @@ public void populateProperties(WayPropertySet props) { // Max speed limit in Georgia is 70 mph ~= 113kmh ~= 31.3m/s props.maxPossibleCarSpeed = 31.4f; - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } } diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/ConstantSpeedMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/ConstantSpeedMapper.java index 9f1b1ac0ade..e2ecb998159 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/ConstantSpeedMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/ConstantSpeedMapper.java @@ -6,7 +6,7 @@ /** * OSM way properties for optimizing distance (not traveling time) in routing. */ -class ConstantSpeedFinlandMapper implements OsmTagMapper { +class ConstantSpeedFinlandMapper extends FinlandMapper { private float speed; @@ -23,8 +23,7 @@ public ConstantSpeedFinlandMapper(float speed) { @Override public void populateProperties(WayPropertySet props) { props.setCarSpeed("highway=*", speed); - // Read the rest from the default set - new FinlandMapper().populateProperties(props); + super.populateProperties(props); props.maxPossibleCarSpeed = speed; } diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java index 86d80605ca6..1d9479e8fc3 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java @@ -25,7 +25,7 @@ * @see OsmTagMapper * @see DefaultMapper */ -class FinlandMapper implements OsmTagMapper { +class FinlandMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -205,8 +205,7 @@ else if (speedLimit <= 16.65f) { // ~= 16 kph props.setCarSpeed("highway=track", 4.5f); - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } @Override diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java index 70a5bd593aa..bad6f8f651e 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java @@ -17,7 +17,7 @@ * @see OsmTagMapper * @see DefaultMapper */ -class GermanyMapper implements OsmTagMapper { +class GermanyMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -88,7 +88,6 @@ public void populateProperties(WayPropertySet props) { props.setProperties("highway=unclassified;cycleway=lane", withModes(ALL).bicycleSafety(0.87)); - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } } diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java index 7e4aba9da4e..6d03e7aea65 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java @@ -14,7 +14,7 @@ * 1. In Houston we want to disallow usage of downtown pedestrian tunnel system. */ -class HoustonMapper implements OsmTagMapper { +class HoustonMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -26,11 +26,9 @@ public void populateProperties(WayPropertySet props) { new ExactMatchSpecifier("highway=footway;layer=-1;tunnel=yes;indoor=yes"), withModes(NONE) ); - // Max speed limit in Texas is 38 m/s ~= 85 mph ~= 137 kph props.maxPossibleCarSpeed = 38f; - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } } diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java index 9e06c0aa591..21b2ecdab65 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java @@ -26,7 +26,7 @@ * @see OsmTagMapper * @see DefaultMapper */ -class NorwayMapper implements OsmTagMapper { +class NorwayMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -621,7 +621,7 @@ else if (speedLimit >= 11.1f) { props.defaultCarSpeed = 22.22f; // 80 km/h props.maxPossibleCarSpeed = 30.56f; // 110 km/h - new DefaultMapper().populateNotesAndNames(props); + super.populateNotesAndNames(props); props.setSlopeOverride(new BestMatchSpecifier("bridge=*"), true); props.setSlopeOverride(new BestMatchSpecifier("cutting=*"), true); diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java index 98379852689..7353c186564 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java @@ -9,7 +9,7 @@ import org.opentripplanner.osm.wayproperty.specifier.Condition.GreaterThan; import org.opentripplanner.osm.wayproperty.specifier.ExactMatchSpecifier; -class PortlandMapper implements OsmTagMapper { +class PortlandMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -57,7 +57,6 @@ public void populateProperties(WayPropertySet props) { // Max speed limit in Oregon is 70 mph ~= 113kmh ~= 31.3m/s props.maxPossibleCarSpeed = 31.4f; - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } } diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java index bef0be4101b..4f93425cc2b 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java @@ -21,7 +21,7 @@ * @see OsmTagMapper * @see DefaultMapper */ -class UKMapper implements OsmTagMapper { +class UKMapper extends DefaultMapper { @Override public void populateProperties(WayPropertySet props) { @@ -73,7 +73,6 @@ public void populateProperties(WayPropertySet props) { props.setCarSpeed("highway=secondary_link", 13.4f); // ~= 30mph props.setCarSpeed("highway=tertiary", 15.7f); // ~= 35mph - // Read the rest from the default set - new DefaultMapper().populateProperties(props); + super.populateProperties(props); } } From 7c452db2fd1708da941a60f3347a41504d6d9df2 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 15 Oct 2024 11:02:34 +0300 Subject: [PATCH 05/15] Remove unnecessary interface --- .../osm/tagmapping/AtlantaMapper.java | 3 +- .../osm/tagmapping/FinlandMapper.java | 3 +- .../osm/tagmapping/GermanyMapper.java | 3 +- .../osm/tagmapping/HamburgMapper.java | 1 - .../osm/tagmapping/HoustonMapper.java | 2 +- .../osm/tagmapping/NorwayMapper.java | 4 +- .../osm/tagmapping/OsmTagMapper.java | 736 +++++++++++++++++- .../osm/tagmapping/OsmTagMapperSource.java | 2 +- .../osm/tagmapping/PortlandMapper.java | 2 +- .../osm/tagmapping/UKMapper.java | 4 +- 10 files changed, 733 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java index 7ae6d985785..34ba62a1daa 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/AtlantaMapper.java @@ -13,10 +13,9 @@ * * @author demory * @see OsmTagMapper - * @see DefaultMapper */ -class AtlantaMapper extends DefaultMapper { +class AtlantaMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java index 1d9479e8fc3..e4267ce9454 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java @@ -23,9 +23,8 @@ * * @author juusokor * @see OsmTagMapper - * @see DefaultMapper */ -class FinlandMapper extends DefaultMapper { +class FinlandMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java index bad6f8f651e..af56b572bd8 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/GermanyMapper.java @@ -15,9 +15,8 @@ * networks. * * @see OsmTagMapper - * @see DefaultMapper */ -class GermanyMapper extends DefaultMapper { +class GermanyMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/HamburgMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/HamburgMapper.java index 47bd5164d1f..755f5864ba2 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/HamburgMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/HamburgMapper.java @@ -7,7 +7,6 @@ * * @see GermanyMapper * @see OsmTagMapper - * @see DefaultMapper * * @author Maintained by HBT (geofox-team@hbt.de) */ diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java index 6d03e7aea65..1d24dbafffb 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/HoustonMapper.java @@ -14,7 +14,7 @@ * 1. In Houston we want to disallow usage of downtown pedestrian tunnel system. */ -class HoustonMapper extends DefaultMapper { +class HoustonMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java index 21b2ecdab65..c37de8533c6 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/NorwayMapper.java @@ -24,9 +24,9 @@ * * @author seime * @see OsmTagMapper - * @see DefaultMapper + * @see OsmTagMapper */ -class NorwayMapper extends DefaultMapper { +class NorwayMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java index 9bf0ed2d20d..6bfb9367111 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java @@ -1,18 +1,728 @@ package org.opentripplanner.osm.tagmapping; +import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofBicycleSafety; +import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofWalkSafety; +import static org.opentripplanner.osm.wayproperty.WayPropertiesBuilder.withModes; +import static org.opentripplanner.street.model.StreetTraversalPermission.ALL; +import static org.opentripplanner.street.model.StreetTraversalPermission.BICYCLE_AND_CAR; +import static org.opentripplanner.street.model.StreetTraversalPermission.CAR; +import static org.opentripplanner.street.model.StreetTraversalPermission.NONE; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE; + import org.opentripplanner.osm.model.OsmWithTags; +import org.opentripplanner.osm.wayproperty.WayProperties; import org.opentripplanner.osm.wayproperty.WayPropertySet; +import org.opentripplanner.osm.wayproperty.specifier.BestMatchSpecifier; +import org.opentripplanner.osm.wayproperty.specifier.LogicalOrSpecifier; +import org.opentripplanner.routing.services.notes.StreetNotesService; /** - * Interface for populating a {@link WayPropertySet} that determine how OSM streets can be traversed - * in various modes and named. + * This factory class provides a default collection of {@link WayProperties} that determine how OSM + * streets can be traversed in various modes. + *

+ * Circa January 2011, Grant and Mele at TriMet undertook proper testing of bike (and transit) + * routing, and worked with David Turner on assigning proper weights to different facility types. + * The weights in this file grew organically from trial and error, and are the result of months of + * testing and tweaking the routes that OTP returned, as well as actually walking/biking these + * routes and making changes based on those experiences. This set of weights should be a great + * starting point for others to use, but they are to some extent tailored to the situation in + * Portland and people shouldn't hesitate to adjust them to for their own instance. + *

+ * The rules for assigning WayProperties to OSM ways are explained in. The final tie breaker if two + * Pickers both match is the sequence that the properties are added in this file: if all else is + * equal the 'props.setProperties' statement that is closer to the top of the page will prevail over + * those lower down the page. + *

+ * Foot and bicycle permissions are also addressed in OpenStreetMapGraphBuilderImpl.Handler#getPermissionsForEntity(). + * For instance, if a way that normally does not permit walking based on its tag matches (the + * prevailing 'props.setProperties' statement) has a 'foot=yes' tag the permissions are overridden + * and walking is allowed on that way. + *

+ * TODO clarify why this needs a separate factory interface. * - * @author bdferris, novalis, seime + * @author bdferris, novalis + * @see OsmTagMapper */ -public interface OsmTagMapper { - void populateProperties(WayPropertySet wayPropertySet); - default boolean doesTagValueDisallowThroughTraffic(String tagValue) { +public class OsmTagMapper { + + /* Populate properties on existing WayPropertySet */ + public void populateProperties(WayPropertySet props) { + WayProperties allWayProperties = withModes(ALL).build(); + WayProperties noneWayProperties = withModes(NONE).build(); + WayProperties pedestrianWayProperties = withModes(PEDESTRIAN).build(); + WayProperties pedestrianAndBicycleWayProperties = withModes(PEDESTRIAN_AND_BICYCLE).build(); + /* no bicycle tags */ + + /* NONE */ + props.setProperties("mtb:scale=3", noneWayProperties); + props.setProperties("mtb:scale=4", noneWayProperties); + props.setProperties("mtb:scale=5", noneWayProperties); + props.setProperties("mtb:scale=6", noneWayProperties); + + /* PEDESTRIAN */ + props.setProperties("highway=corridor", pedestrianWayProperties); + props.setProperties("highway=steps", pedestrianWayProperties); + props.setProperties("highway=crossing", pedestrianWayProperties); + props.setProperties("highway=platform", pedestrianWayProperties); + props.setProperties("public_transport=platform", pedestrianWayProperties); + props.setProperties("public_transport=platform;area=yes", pedestrianWayProperties); + props.setProperties("railway=platform", pedestrianWayProperties); + props.setProperties("footway=sidewalk;highway=footway", pedestrianWayProperties); + props.setProperties("mtb:scale=1", pedestrianWayProperties); + props.setProperties("mtb:scale=2", pedestrianWayProperties); + + /* PEDESTRIAN_AND_BICYCLE */ + props.setProperties("mtb:scale=0", pedestrianAndBicycleWayProperties); + props.setProperties("highway=cycleway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.6)); + props.setProperties("highway=path", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75)); + props.setProperties("highway=pedestrian", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9)); + props.setProperties("highway=footway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1)); + props.setProperties("highway=bridleway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.3)); + + /* ALL */ + props.setProperties("highway=living_street", withModes(ALL).bicycleSafety(0.9)); + props.setProperties("highway=unclassified", allWayProperties); + props.setProperties("highway=road", allWayProperties); + props.setProperties("highway=byway", withModes(ALL).bicycleSafety(1.3)); + props.setProperties("highway=track", withModes(ALL).bicycleSafety(1.3)); + props.setProperties("highway=service", withModes(ALL).bicycleSafety(1.1)); + props.setProperties("highway=residential", withModes(ALL).bicycleSafety(0.98)); + props.setProperties("highway=residential_link", withModes(ALL).bicycleSafety(0.98)); + props.setProperties("highway=tertiary", allWayProperties); + props.setProperties("highway=tertiary_link", allWayProperties); + props.setProperties("highway=secondary", withModes(ALL).bicycleSafety(1.5)); + props.setProperties("highway=secondary_link", withModes(ALL).bicycleSafety(1.5)); + props.setProperties("highway=primary", withModes(ALL).bicycleSafety(2.06)); + props.setProperties("highway=primary_link", withModes(ALL).bicycleSafety(2.06)); + + /* DRIVING ONLY */ + // trunk and motorway links are often short distances and necessary connections + props.setProperties("highway=trunk_link", withModes(CAR).bicycleSafety(2.06)); + props.setProperties("highway=motorway_link", withModes(CAR).bicycleSafety(2.06)); + + props.setProperties("highway=trunk", withModes(CAR).bicycleSafety(7.47)); + props.setProperties("highway=motorway", withModes(CAR).bicycleSafety(8)); + + /* cycleway=lane */ + props.setProperties( + "highway=*;cycleway=lane", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.87) + ); + props.setProperties("highway=service;cycleway=lane", withModes(ALL).bicycleSafety(0.77)); + props.setProperties("highway=residential;cycleway=lane", withModes(ALL).bicycleSafety(0.77)); + props.setProperties( + "highway=residential_link;cycleway=lane", + withModes(ALL).bicycleSafety(0.77) + ); + props.setProperties("highway=tertiary;cycleway=lane", withModes(ALL).bicycleSafety(0.87)); + props.setProperties("highway=tertiary_link;cycleway=lane", withModes(ALL).bicycleSafety(0.87)); + props.setProperties("highway=secondary;cycleway=lane", withModes(ALL).bicycleSafety(0.96)); + props.setProperties("highway=secondary_link;cycleway=lane", withModes(ALL).bicycleSafety(0.96)); + props.setProperties("highway=primary;cycleway=lane", withModes(ALL).bicycleSafety(1.15)); + props.setProperties("highway=primary_link;cycleway=lane", withModes(ALL).bicycleSafety(1.15)); + + /* BICYCLE_AND_CAR */ + props.setProperties( + "highway=trunk;cycleway=lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.5) + ); + props.setProperties( + "highway=trunk_link;cycleway=lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.15) + ); + props.setProperties( + "highway=motorway;cycleway=lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(2) + ); + props.setProperties( + "highway=motorway_link;cycleway=lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.15) + ); + + /* cycleway=share_busway */ + props.setProperties( + "highway=*;cycleway=share_busway", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.92) + ); + props.setProperties( + "highway=service;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.85) + ); + props.setProperties( + "highway=residential;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.85) + ); + props.setProperties( + "highway=residential_link;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.85) + ); + props.setProperties( + "highway=tertiary;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.92) + ); + props.setProperties( + "highway=tertiary_link;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.92) + ); + props.setProperties( + "highway=secondary;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.99) + ); + props.setProperties( + "highway=secondary_link;cycleway=share_busway", + withModes(ALL).bicycleSafety(0.99) + ); + props.setProperties( + "highway=primary;cycleway=share_busway", + withModes(ALL).bicycleSafety(1.25) + ); + props.setProperties( + "highway=primary_link;cycleway=share_busway", + withModes(ALL).bicycleSafety(1.25) + ); + props.setProperties( + "highway=trunk;cycleway=share_busway", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.75) + ); + props.setProperties( + "highway=trunk_link;cycleway=share_busway", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.25) + ); + props.setProperties( + "highway=motorway;cycleway=share_busway", + withModes(BICYCLE_AND_CAR).bicycleSafety(2.5) + ); + props.setProperties( + "highway=motorway_link;cycleway=share_busway", + withModes(BICYCLE_AND_CAR).bicycleSafety(1.25) + ); + + /* cycleway=opposite_lane */ + props.setProperties( + "highway=*;cycleway=opposite_lane", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1, 0.87) + ); + props.setProperties( + "highway=service;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(1.1, 0.77) + ); + props.setProperties( + "highway=residential;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(0.98, 0.77) + ); + props.setProperties( + "highway=residential_link;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(0.98, 0.77) + ); + props.setProperties( + "highway=tertiary;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(1, 0.87) + ); + props.setProperties( + "highway=tertiary_link;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(1, 0.87) + ); + props.setProperties( + "highway=secondary;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(1.5, 0.96) + ); + props.setProperties( + "highway=secondary_link;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(1.5, 0.96) + ); + props.setProperties( + "highway=primary;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(2.06, 1.15) + ); + props.setProperties( + "highway=primary_link;cycleway=opposite_lane", + withModes(ALL).bicycleSafety(2.06, 1.15) + ); + props.setProperties( + "highway=trunk;cycleway=opposite_lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(7.47, 1.5) + ); + props.setProperties( + "highway=trunk_link;cycleway=opposite_lane", + withModes(BICYCLE_AND_CAR).bicycleSafety(2.06, 1.15) + ); + + /* cycleway=track */ + props.setProperties( + "highway=*;cycleway=track", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) + ); + props.setProperties("highway=service;cycleway=track", withModes(ALL).bicycleSafety(0.65)); + props.setProperties("highway=residential;cycleway=track", withModes(ALL).bicycleSafety(0.65)); + props.setProperties( + "highway=residential_link;cycleway=track", + withModes(ALL).bicycleSafety(0.65) + ); + props.setProperties("highway=tertiary;cycleway=track", withModes(ALL).bicycleSafety(0.75)); + props.setProperties("highway=tertiary_link;cycleway=track", withModes(ALL).bicycleSafety(0.75)); + props.setProperties("highway=secondary;cycleway=track", withModes(ALL).bicycleSafety(0.8)); + props.setProperties("highway=secondary_link;cycleway=track", withModes(ALL).bicycleSafety(0.8)); + props.setProperties("highway=primary;cycleway=track", withModes(ALL).bicycleSafety(0.85)); + props.setProperties("highway=primary_link;cycleway=track", withModes(ALL).bicycleSafety(0.85)); + props.setProperties( + "highway=trunk;cycleway=track", + withModes(BICYCLE_AND_CAR).bicycleSafety(0.95) + ); + props.setProperties( + "highway=trunk_link;cycleway=track", + withModes(BICYCLE_AND_CAR).bicycleSafety(0.85) + ); + + /* cycleway=opposite_track */ + props.setProperties( + "highway=*;cycleway=opposite_track", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.0, 0.75) + ); + props.setProperties( + "highway=service;cycleway=opposite_track", + withModes(ALL).bicycleSafety(1.1, 0.65) + ); + props.setProperties( + "highway=residential;cycleway=opposite_track", + withModes(ALL).bicycleSafety(0.98, 0.65) + ); + props.setProperties( + "highway=residential_link;cycleway=opposite_track", + withModes(ALL).bicycleSafety(0.98, 0.65) + ); + props.setProperties( + "highway=tertiary;cycleway=opposite_track", + withModes(ALL).bicycleSafety(1, 0.75) + ); + props.setProperties( + "highway=tertiary_link;cycleway=opposite_track", + withModes(ALL).bicycleSafety(1, 0.75) + ); + props.setProperties( + "highway=secondary;cycleway=opposite_track", + withModes(ALL).bicycleSafety(1.5, 0.8) + ); + props.setProperties( + "highway=secondary_link;cycleway=opposite_track", + withModes(ALL).bicycleSafety(1.5, 0.8) + ); + props.setProperties( + "highway=primary;cycleway=opposite_track", + withModes(ALL).bicycleSafety(2.06, 0.85) + ); + props.setProperties( + "highway=primary_link;cycleway=opposite_track", + withModes(ALL).bicycleSafety(2.06, 0.85) + ); + props.setProperties( + "highway=trunk;cycleway=opposite_track", + withModes(BICYCLE_AND_CAR).bicycleSafety(7.47, 0.95) + ); + props.setProperties( + "highway=trunk_link;cycleway=opposite_track", + withModes(BICYCLE_AND_CAR).bicycleSafety(2.06, 0.85) + ); + + /* cycleway=shared_lane a.k.a. bike boulevards or neighborhood greenways */ + props.setProperties( + "highway=*;cycleway=shared_lane", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.77) + ); + props.setProperties("highway=service;cycleway=shared_lane", withModes(ALL).bicycleSafety(0.73)); + props.setProperties( + "highway=residential;cycleway=shared_lane", + withModes(ALL).bicycleSafety(0.77) + ); + props.setProperties( + "highway=residential_link;cycleway=shared_lane", + withModes(ALL).bicycleSafety(0.77) + ); + props.setProperties( + "highway=tertiary;cycleway=shared_lane", + withModes(ALL).bicycleSafety(0.83) + ); + props.setProperties( + "highway=tertiary_link;cycleway=shared_lane", + withModes(ALL).bicycleSafety(0.83) + ); + props.setProperties( + "highway=secondary;cycleway=shared_lane", + withModes(ALL).bicycleSafety(1.25) + ); + props.setProperties( + "highway=secondary_link;cycleway=shared_lane", + withModes(ALL).bicycleSafety(1.25) + ); + props.setProperties("highway=primary;cycleway=shared_lane", withModes(ALL).bicycleSafety(1.75)); + props.setProperties( + "highway=primary_link;cycleway=shared_lane", + withModes(ALL).bicycleSafety(1.75) + ); + + /* cycleway=opposite */ + props.setProperties( + "highway=*;cycleway=opposite", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1, 1.4) + ); + props.setProperties("highway=service;cycleway=opposite", withModes(ALL).bicycleSafety(1.1)); + props.setProperties( + "highway=residential;cycleway=opposite", + withModes(ALL).bicycleSafety(0.98) + ); + props.setProperties( + "highway=residential_link;cycleway=opposite", + withModes(ALL).bicycleSafety(0.98) + ); + props.setProperties("highway=tertiary;cycleway=opposite", allWayProperties); + props.setProperties("highway=tertiary_link;cycleway=opposite", allWayProperties); + props.setProperties( + "highway=secondary;cycleway=opposite", + withModes(ALL).bicycleSafety(1.5, 1.71) + ); + props.setProperties( + "highway=secondary_link;cycleway=opposite", + withModes(ALL).bicycleSafety(1.5, 1.71) + ); + props.setProperties( + "highway=primary;cycleway=opposite", + withModes(ALL).bicycleSafety(2.06, 2.99) + ); + props.setProperties( + "highway=primary_link;cycleway=opposite", + withModes(ALL).bicycleSafety(2.06, 2.99) + ); + + /* + * path designed for bicycles (should be treated exactly as a cycleway is), this is a multi-use path (MUP) + */ + props.setProperties( + "highway=path;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.60) + ); + + /* special cases for footway, pedestrian and bicycles */ + props.setProperties( + "highway=footway;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) + ); + props.setProperties( + "highway=footway;bicycle=yes;area=yes", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9) + ); + props.setProperties( + "highway=pedestrian;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) + ); + + /* sidewalk and crosswalk */ + props.setProperties( + "footway=sidewalk;highway=footway;bicycle=yes", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(2.5) + ); + props.setProperties( + "footway=sidewalk;highway=footway;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1) + ); + props.setProperties( + "highway=footway;footway=crossing", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(2.5) + ); + props.setProperties( + "highway=footway;footway=crossing;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1) + ); + + /* + * bicycles on tracks (tracks are defined in OSM as: Roads for agricultural use, gravel roads in the forest etc.; usually unpaved/unsealed but + * may occasionally apply to paved tracks as well.) + */ + props.setProperties( + "highway=track;bicycle=yes", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.18) + ); + props.setProperties( + "highway=track;bicycle=designated", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.99) + ); + props.setProperties( + "highway=track;bicycle=yes;surface=*", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.18) + ); + props.setProperties( + "highway=track;bicycle=designated;surface=*", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.99) + ); + /* this is to avoid double counting since tracks are almost of surface type that is penalized */ + props.setProperties( + "highway=track;surface=*", + withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.3) + ); + + /* bicycle=designated, but no bike infrastructure is present */ + props.setProperties("highway=*;bicycle=designated", withModes(ALL).bicycleSafety(0.97)); + props.setProperties("highway=service;bicycle=designated", withModes(ALL).bicycleSafety(0.84)); + props.setProperties( + "highway=residential;bicycle=designated", + withModes(ALL).bicycleSafety(0.95) + ); + props.setProperties( + "highway=unclassified;bicycle=designated", + withModes(ALL).bicycleSafety(0.95) + ); + props.setProperties( + "highway=residential_link;bicycle=designated", + withModes(ALL).bicycleSafety(0.95) + ); + props.setProperties("highway=tertiary;bicycle=designated", withModes(ALL).bicycleSafety(0.97)); + props.setProperties( + "highway=tertiary_link;bicycle=designated", + withModes(ALL).bicycleSafety(0.97) + ); + props.setProperties("highway=secondary;bicycle=designated", withModes(ALL).bicycleSafety(1.46)); + props.setProperties( + "highway=secondary_link;bicycle=designated", + withModes(ALL).bicycleSafety(1.46) + ); + props.setProperties("highway=primary;bicycle=designated", withModes(ALL).bicycleSafety(2)); + props.setProperties("highway=primary_link;bicycle=designated", withModes(ALL).bicycleSafety(2)); + props.setProperties( + "highway=trunk;bicycle=designated", + withModes(BICYCLE_AND_CAR).bicycleSafety(7.25) + ); + props.setProperties( + "highway=trunk_link;bicycle=designated", + withModes(BICYCLE_AND_CAR).bicycleSafety(2) + ); + props.setProperties( + "highway=motorway;bicycle=designated", + withModes(BICYCLE_AND_CAR).bicycleSafety(7.76) + ); + props.setProperties( + "highway=motorway_link;bicycle=designated", + withModes(BICYCLE_AND_CAR).bicycleSafety(2) + ); + + // We assume highway/cycleway of a cycle network to be safer (for bicycle network relations, their network is copied to way in postLoad) + // this uses a OR since you don't want to apply the safety multiplier more than once. + // Signed bicycle_roads and cyclestreets exist in traffic codes of some european countries. + // Tagging in OSM and on-the-ground use is varied, so just assume they are "somehow safer", too. + // In my test area ways often, but not always, have both tags. + // For simplicity these two concepts are handled together. + props.setMixinProperties( + new LogicalOrSpecifier( + "lcn=yes", + "rcn=yes", + "ncn=yes", + "bicycle_road=yes", + "cyclestreet=yes" + ), + ofBicycleSafety(0.7) + ); + + /* + * Automobile speeds in the United States: Based on my (mattwigway) personal experience, primarily in California + */ + props.setCarSpeed("highway=motorway", 29); // 29 m/s ~= 65 mph + props.setCarSpeed("highway=motorway_link", 15); // ~= 35 mph + props.setCarSpeed("highway=trunk", 24.6f); // ~= 55 mph + props.setCarSpeed("highway=trunk_link", 15); // ~= 35 mph + props.setCarSpeed("highway=primary", 20); // ~= 45 mph + props.setCarSpeed("highway=primary_link", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=secondary", 15); // ~= 35 mph + props.setCarSpeed("highway=secondary_link", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=tertiary", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=tertiary_link", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=living_street", 2.2f); // ~= 5 mph + + // generally, these will not allow cars at all, but the docs say + // "For roads used mainly/exclusively for pedestrians . . . which may allow access by + // motorised vehicles only for very limited periods of the day." + // http://wiki.openstreetmap.org/wiki/Key:highway + // This of course makes the street network time-dependent + props.setCarSpeed("highway=pedestrian", 2.2f); // ~= 5 mph + + props.setCarSpeed("highway=residential", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=unclassified", 11.2f); // ~= 25 mph + props.setCarSpeed("highway=service", 6.7f); // ~= 15 mph + props.setCarSpeed("highway=track", 4.5f); // ~= 10 mph + props.setCarSpeed("highway=road", 11.2f); // ~= 25 mph + + // default ~= 25 mph + props.defaultCarSpeed = 11.2f; + // 38 m/s ~= 85 mph ~= 137 kph + props.maxPossibleCarSpeed = 38f; + + /* special situations */ + + /* + * cycleway:left/right=lane/track/shared_lane permutations - no longer needed because left/right matching algorithm does this + */ + + /* cycleway:left=lane */ + /* cycleway:right=track */ + /* cycleway:left=track */ + /* cycleway:right=shared_lane */ + /* cycleway:left=shared_lane */ + /* cycleway:right=lane, cycleway:left=track */ + /* cycleway:right=lane, cycleway:left=shared_lane */ + /* cycleway:right=track, cycleway:left=lane */ + /* cycleway:right=track, cycleway:left=shared_lane */ + /* cycleway:right=shared_lane, cycleway:left=lane */ + /* cycleway:right=shared_lane, cycleway:left=track */ + + /* surface=* mixins */ + + /* + * The following tags have been removed from surface weights because they are no more of an impedence to bicycling than a paved surface + * surface=paving_stones surface=fine_gravel (sounds counter-intuitive but see the definition on the OSM Wiki) surface=tartan (this what + * running tracks are usually made of) + */ + + props.setMixinProperties("surface=unpaved", ofBicycleSafety(1.18)); + props.setMixinProperties("surface=compacted", ofBicycleSafety(1.18)); + props.setMixinProperties("surface=wood", ofBicycleSafety(1.18)); + + props.setMixinProperties("surface=cobblestone", ofBicycleSafety(1.3)); + props.setMixinProperties("surface=sett", ofBicycleSafety(1.3)); + props.setMixinProperties("surface=unhewn_cobblestone", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=grass_paver", ofBicycleSafety(1.3)); + props.setMixinProperties("surface=pebblestone", ofBicycleSafety(1.3)); + // Can be slick if wet, but otherwise not unfavorable to bikes + props.setMixinProperties("surface=metal", ofBicycleSafety(1.3)); + props.setMixinProperties("surface=ground", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=dirt", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=earth", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=grass", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=mud", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=woodchip", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=gravel", ofBicycleSafety(1.5)); + props.setMixinProperties("surface=artifical_turf", ofBicycleSafety(1.5)); + + /* sand is deadly for bikes */ + props.setMixinProperties("surface=sand", ofBicycleSafety(100)); + + /* Portland-local mixins */ + + props.setMixinProperties("foot=discouraged", ofWalkSafety(3)); + props.setMixinProperties("bicycle=discouraged", ofBicycleSafety(3)); + + props.setMixinProperties("foot=use_sidepath", ofWalkSafety(5)); + props.setMixinProperties("bicycle=use_sidepath", ofBicycleSafety(5)); + + populateNotesAndNames(props); + + // slope overrides + props.setSlopeOverride(new BestMatchSpecifier("bridge=*"), true); + props.setSlopeOverride(new BestMatchSpecifier("embankment=*"), true); + props.setSlopeOverride(new BestMatchSpecifier("cutting=*"), true); + props.setSlopeOverride(new BestMatchSpecifier("tunnel=*"), true); + props.setSlopeOverride(new BestMatchSpecifier("location=underground"), true); + props.setSlopeOverride(new BestMatchSpecifier("indoor=yes"), true); + } + + public void populateNotesAndNames(WayPropertySet props) { + /* and the notes */ + // TODO: The curly brackets in the string below mean that the CreativeNamer should substitute in OSM tag values. + // However they are not taken into account when passed to the translation function. + // props.createNotes("wheelchair:description=*", "{wheelchair:description}", StreetNotesService.WHEELCHAIR_MATCHER); + // TODO: The two entries below produce lots of spurious notes (because of OSM mapper comments) + // props.createNotes("note=*", "{note}", StreetNotesService.ALWAYS_MATCHER); + // props.createNotes("notes=*", "{notes}", StreetNotesService.ALWAYS_MATCHER); + props.createNotes( + "RLIS:bicycle=caution_area", + "note.caution", + StreetNotesService.BICYCLE_MATCHER + ); + props.createNotes( + "CCGIS:bicycle=caution_area", + "note.caution", + StreetNotesService.BICYCLE_MATCHER + ); + // TODO: Maybe we should apply the following notes only for car/bike + props.createNotes("surface=unpaved", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes( + "surface=compacted", + "note.unpaved_surface", + StreetNotesService.ALWAYS_MATCHER + ); + props.createNotes("surface=ground", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes("surface=dirt", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes("surface=earth", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes("surface=grass", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes("surface=mud", "note.muddy_surface", StreetNotesService.ALWAYS_MATCHER); + props.createNotes("toll=yes", "note.toll", StreetNotesService.DRIVING_MATCHER); + props.createNotes("toll:motorcar=yes", "note.toll", StreetNotesService.DRIVING_MATCHER); + + /* and some names */ + // Basics + props.createNames("highway=cycleway", "name.bike_path"); + props.createNames("cycleway=track", "name.bike_path"); + props.createNames("highway=pedestrian", "name.pedestrian_path"); + props.createNames("highway=pedestrian;area=yes", "name.pedestrian_area"); + props.createNames("highway=path", "name.path"); + props.createNames("highway=footway", "name.pedestrian_path"); + props.createNames("highway=bridleway", "name.bridleway"); + props.createNames("highway=footway;bicycle=no", "name.pedestrian_path"); + + // Platforms + props.createNames("otp:route_ref=*", "name.otp_route_ref"); + props.createNames("highway=platform;ref=*", "name.platform_ref"); + props.createNames("railway=platform;ref=*", "name.platform_ref"); + props.createNames("railway=platform;highway=footway;footway=sidewalk", "name.platform"); + props.createNames("railway=platform;highway=path;path=sidewalk", "name.platform"); + props.createNames("railway=platform;highway=pedestrian", "name.platform"); + props.createNames("railway=platform;highway=path", "name.platform"); + props.createNames("railway=platform;highway=footway", "name.platform"); + props.createNames("highway=platform", "name.platform"); + props.createNames("railway=platform", "name.platform"); + props.createNames("railway=platform;highway=footway;bicycle=no", "name.platform"); + + // Bridges/Tunnels + props.createNames("highway=pedestrian;bridge=*", "name.footbridge"); + props.createNames("highway=path;bridge=*", "name.footbridge"); + props.createNames("highway=footway;bridge=*", "name.footbridge"); + + props.createNames("highway=pedestrian;tunnel=*", "name.underpass"); + props.createNames("highway=path;tunnel=*", "name.underpass"); + props.createNames("highway=footway;tunnel=*", "name.underpass"); + + // Basic Mappings + props.createNames("highway=motorway", "name.road"); + props.createNames("highway=motorway_link", "name.ramp"); + props.createNames("highway=trunk", "name.road"); + props.createNames("highway=trunk_link", "name.ramp"); + + props.createNames("highway=primary", "name.road"); + props.createNames("highway=primary_link", "name.link"); + props.createNames("highway=secondary", "name.road"); + props.createNames("highway=secondary_link", "name.link"); + props.createNames("highway=tertiary", "name.road"); + props.createNames("highway=tertiary_link", "name.link"); + props.createNames("highway=unclassified", "name.road"); + props.createNames("highway=residential", "name.road"); + props.createNames("highway=living_street", "name.road"); + props.createNames("highway=road", "name.road"); + props.createNames("highway=service", "name.service_road"); + props.createNames("highway=service;service=alley", "name.alley"); + props.createNames("highway=service;service=parking_aisle", "name.parking_aisle"); + props.createNames("highway=byway", "name.byway"); + props.createNames("highway=track", "name.track"); + + props.createNames("highway=footway;footway=sidewalk", "name.sidewalk"); + props.createNames("highway=path;path=sidewalk", "name.sidewalk"); + + props.createNames("highway=steps", "name.steps"); + + props.createNames("amenity=bicycle_parking;name=*", "name.bicycle_parking_name"); + props.createNames("amenity=bicycle_parking", "name.bicycle_parking"); + + props.createNames("amenity=parking;name=*", "name.park_and_ride_name"); + props.createNames("amenity=parking", "name.park_and_ride_station"); + } + + public boolean doesTagValueDisallowThroughTraffic(String tagValue) { return ( "no".equals(tagValue) || "destination".equals(tagValue) || @@ -22,20 +732,20 @@ default boolean doesTagValueDisallowThroughTraffic(String tagValue) { ); } - default float getCarSpeedForWay(OsmWithTags way, boolean backward) { + public float getCarSpeedForWay(OsmWithTags way, boolean backward) { return way.getOsmProvider().getWayPropertySet().getCarSpeedForWay(way, backward); } - default Float getMaxUsedCarSpeed(WayPropertySet wayPropertySet) { + public Float getMaxUsedCarSpeed(WayPropertySet wayPropertySet) { return wayPropertySet.maxUsedCarSpeed; } - default boolean isGeneralNoThroughTraffic(OsmWithTags way) { + public boolean isGeneralNoThroughTraffic(OsmWithTags way) { String access = way.getTag("access"); return doesTagValueDisallowThroughTraffic(access); } - default boolean isVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way) { + public boolean isVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way) { String vehicle = way.getTag("vehicle"); if (vehicle != null) { return doesTagValueDisallowThroughTraffic(vehicle); @@ -47,7 +757,7 @@ default boolean isVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way) { /** * Returns true if through traffic for motor vehicles is not allowed. */ - default boolean isMotorVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way) { + public boolean isMotorVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way) { String motorVehicle = way.getTag("motor_vehicle"); if (motorVehicle != null) { return doesTagValueDisallowThroughTraffic(motorVehicle); @@ -59,7 +769,7 @@ default boolean isMotorVehicleThroughTrafficExplicitlyDisallowed(OsmWithTags way /** * Returns true if through traffic for bicycle is not allowed. */ - default boolean isBicycleNoThroughTrafficExplicitlyDisallowed(OsmWithTags way) { + public boolean isBicycleNoThroughTrafficExplicitlyDisallowed(OsmWithTags way) { String bicycle = way.getTag("bicycle"); if (bicycle != null) { return doesTagValueDisallowThroughTraffic(bicycle); @@ -71,7 +781,7 @@ default boolean isBicycleNoThroughTrafficExplicitlyDisallowed(OsmWithTags way) { /** * Returns true if through traffic for walk is not allowed. */ - default boolean isWalkNoThroughTrafficExplicitlyDisallowed(OsmWithTags way) { + public boolean isWalkNoThroughTrafficExplicitlyDisallowed(OsmWithTags way) { String foot = way.getTag("foot"); if (foot != null) { return doesTagValueDisallowThroughTraffic(foot); diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapperSource.java b/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapperSource.java index b40c2e7f75a..98593ef70d0 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapperSource.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapperSource.java @@ -18,7 +18,7 @@ public enum OsmTagMapperSource { public OsmTagMapper getInstance() { return switch (this) { - case DEFAULT -> new DefaultMapper(); + case DEFAULT -> new OsmTagMapper(); case NORWAY -> new NorwayMapper(); case UK -> new UKMapper(); case FINLAND -> new FinlandMapper(); diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java index 7353c186564..7da8f8ca886 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/PortlandMapper.java @@ -9,7 +9,7 @@ import org.opentripplanner.osm.wayproperty.specifier.Condition.GreaterThan; import org.opentripplanner.osm.wayproperty.specifier.ExactMatchSpecifier; -class PortlandMapper extends DefaultMapper { +class PortlandMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java index 4f93425cc2b..954fd84417a 100644 --- a/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java +++ b/src/main/java/org/opentripplanner/osm/tagmapping/UKMapper.java @@ -19,9 +19,9 @@ * * @author marcusyoung * @see OsmTagMapper - * @see DefaultMapper + * @see OsmTagMapper */ -class UKMapper extends DefaultMapper { +class UKMapper extends OsmTagMapper { @Override public void populateProperties(WayPropertySet props) { From 7ffca9b3a21fa0e4b0f459f7881f55dd353c9dc2 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 15 Oct 2024 11:08:57 +0300 Subject: [PATCH 06/15] Update OSM tag mapping related tests --- .../osm/tagmapping/OsmTagMapperTest.java | 48 +++++-------------- .../MapperTest.java} | 28 +++++++++-- 2 files changed, 35 insertions(+), 41 deletions(-) rename src/test/java/org/opentripplanner/osm/{tagmapping/DefaultMapperTest.java => wayproperty/MapperTest.java} (89%) diff --git a/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java b/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java index e0c70690e91..aaaf5178d5b 100644 --- a/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java +++ b/src/test/java/org/opentripplanner/osm/tagmapping/OsmTagMapperTest.java @@ -3,20 +3,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofBicycleSafety; -import static org.opentripplanner.osm.wayproperty.WayPropertiesBuilder.withModes; import static org.opentripplanner.street.model.StreetTraversalPermission.CAR; import org.junit.jupiter.api.Test; import org.opentripplanner.osm.model.OsmWithTags; -import org.opentripplanner.osm.wayproperty.WayPropertySet; public class OsmTagMapperTest { @Test public void isMotorThroughTrafficExplicitlyDisallowed() { OsmWithTags o = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); assertFalse(osmTagMapper.isMotorVehicleThroughTrafficExplicitlyDisallowed(o)); @@ -52,7 +49,7 @@ public void constantSpeedCarRouting() { @Test public void isBicycleNoThroughTrafficExplicitlyDisallowed() { - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); assertTrue( osmTagMapper.isBicycleNoThroughTrafficExplicitlyDisallowed(way("bicycle", "destination")) ); @@ -63,38 +60,17 @@ public void isBicycleNoThroughTrafficExplicitlyDisallowed() { @Test public void isWalkNoThroughTrafficExplicitlyDisallowed() { - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); assertTrue(osmTagMapper.isWalkNoThroughTrafficExplicitlyDisallowed(way("foot", "destination"))); assertTrue( osmTagMapper.isWalkNoThroughTrafficExplicitlyDisallowed(way("access", "destination")) ); } - @Test - public void mixin() { - var source = new DefaultMapper(); - var wps = new WayPropertySet(); - - wps.setProperties("tag=imaginary", withModes(CAR).bicycleSafety(2)); - - wps.setMixinProperties("foo=bar", ofBicycleSafety(0.5)); - source.populateProperties(wps); - - var withoutFoo = new OsmWithTags(); - withoutFoo.addTag("tag", "imaginary"); - assertEquals(2, wps.getDataForWay(withoutFoo).bicycleSafety().back()); - - // the mixin for foo=bar reduces the bike safety factor - var withFoo = new OsmWithTags(); - withFoo.addTag("tag", "imaginary"); - withFoo.addTag("foo", "bar"); - assertEquals(1, wps.getDataForWay(withFoo).bicycleSafety().back()); - } - @Test public void testAccessNo() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "no"); @@ -106,7 +82,7 @@ public void testAccessNo() { @Test public void testAccessPrivate() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "private"); @@ -118,7 +94,7 @@ public void testAccessPrivate() { @Test public void testFootModifier() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "private"); tags.addTag("foot", "yes"); @@ -131,7 +107,7 @@ public void testFootModifier() { @Test public void testVehicleDenied() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("vehicle", "destination"); @@ -143,7 +119,7 @@ public void testVehicleDenied() { @Test public void testVehicleDeniedMotorVehiclePermissive() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("vehicle", "destination"); tags.addTag("motor_vehicle", "designated"); @@ -156,7 +132,7 @@ public void testVehicleDeniedMotorVehiclePermissive() { @Test public void testVehicleDeniedBicyclePermissive() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("vehicle", "destination"); tags.addTag("bicycle", "designated"); @@ -169,7 +145,7 @@ public void testVehicleDeniedBicyclePermissive() { @Test public void testMotorcycleModifier() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "private"); tags.addTag("motor_vehicle", "yes"); @@ -182,7 +158,7 @@ public void testMotorcycleModifier() { @Test public void testBicycleModifier() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "private"); tags.addTag("bicycle", "yes"); @@ -195,7 +171,7 @@ public void testBicycleModifier() { @Test public void testBicyclePermissive() { OsmWithTags tags = new OsmWithTags(); - OsmTagMapper osmTagMapper = new DefaultMapper(); + OsmTagMapper osmTagMapper = new OsmTagMapper(); tags.addTag("access", "private"); tags.addTag("bicycle", "permissive"); diff --git a/src/test/java/org/opentripplanner/osm/tagmapping/DefaultMapperTest.java b/src/test/java/org/opentripplanner/osm/wayproperty/MapperTest.java similarity index 89% rename from src/test/java/org/opentripplanner/osm/tagmapping/DefaultMapperTest.java rename to src/test/java/org/opentripplanner/osm/wayproperty/MapperTest.java index 87e23acbf12..2cd9a74f06b 100644 --- a/src/test/java/org/opentripplanner/osm/tagmapping/DefaultMapperTest.java +++ b/src/test/java/org/opentripplanner/osm/wayproperty/MapperTest.java @@ -1,21 +1,23 @@ -package org.opentripplanner.osm.tagmapping; +package org.opentripplanner.osm.wayproperty; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofBicycleSafety; +import static org.opentripplanner.osm.wayproperty.WayPropertiesBuilder.withModes; import static org.opentripplanner.street.model.StreetTraversalPermission.ALL; +import static org.opentripplanner.street.model.StreetTraversalPermission.CAR; import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN; import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.opentripplanner.osm.model.OsmWithTags; -import org.opentripplanner.osm.wayproperty.SpeedPicker; -import org.opentripplanner.osm.wayproperty.WayPropertySet; +import org.opentripplanner.osm.tagmapping.OsmTagMapper; import org.opentripplanner.osm.wayproperty.specifier.BestMatchSpecifier; import org.opentripplanner.osm.wayproperty.specifier.WayTestData; -public class DefaultMapperTest { +public class MapperTest { private WayPropertySet wps; private OsmTagMapper mapper; @@ -24,7 +26,7 @@ public class DefaultMapperTest { @BeforeEach public void setup() { var wps = new WayPropertySet(); - DefaultMapper source = new DefaultMapper(); + var source = new OsmTagMapper(); source.populateProperties(wps); this.wps = wps; this.mapper = source; @@ -199,6 +201,22 @@ void slopeOverrides() { assertTrue(wps.getSlopeOverride(indoor)); } + @Test + public void mixin() { + wps.setProperties("tag=imaginary", withModes(CAR).bicycleSafety(2)); + wps.setMixinProperties("foo=bar", ofBicycleSafety(0.5)); + + var withoutFoo = new OsmWithTags(); + withoutFoo.addTag("tag", "imaginary"); + assertEquals(2, wps.getDataForWay(withoutFoo).bicycleSafety().back()); + + // the mixin for foo=bar reduces the bike safety factor + var withFoo = new OsmWithTags(); + withFoo.addTag("tag", "imaginary"); + withFoo.addTag("foo", "bar"); + assertEquals(1, wps.getDataForWay(withFoo).bicycleSafety().back()); + } + /** * Test that two values are within epsilon of each other. */ From 3417952b000cc58e6012eddc9812932178ed7881 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 15 Oct 2024 11:09:31 +0300 Subject: [PATCH 07/15] Update OSM tag mapping docs --- doc/user/osm/{Default.md => OsmTag.md} | 0 mkdocs.yml | 2 +- .../osm/tagmapping/DefaultMapper.java | 722 ------------------ 3 files changed, 1 insertion(+), 723 deletions(-) rename doc/user/osm/{Default.md => OsmTag.md} (100%) delete mode 100644 src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java diff --git a/doc/user/osm/Default.md b/doc/user/osm/OsmTag.md similarity index 100% rename from doc/user/osm/Default.md rename to doc/user/osm/OsmTag.md diff --git a/mkdocs.yml b/mkdocs.yml index 1364be7be1f..bce905f337a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,7 +74,7 @@ nav: - Introduction: 'Configuration.md' - Build: 'BuildConfiguration.md' - OSM Tag Mapping: - - Default: 'osm/Default.md' + - Default: 'osm/OsmTag.md' - Finland: 'osm/Finland.md' - Germany: 'osm/Germany.md' - Norway: 'osm/Norway.md' diff --git a/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java b/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java deleted file mode 100644 index c0b786d02e8..00000000000 --- a/src/main/java/org/opentripplanner/osm/tagmapping/DefaultMapper.java +++ /dev/null @@ -1,722 +0,0 @@ -package org.opentripplanner.osm.tagmapping; - -import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofBicycleSafety; -import static org.opentripplanner.osm.wayproperty.MixinPropertiesBuilder.ofWalkSafety; -import static org.opentripplanner.osm.wayproperty.WayPropertiesBuilder.withModes; -import static org.opentripplanner.street.model.StreetTraversalPermission.ALL; -import static org.opentripplanner.street.model.StreetTraversalPermission.BICYCLE_AND_CAR; -import static org.opentripplanner.street.model.StreetTraversalPermission.CAR; -import static org.opentripplanner.street.model.StreetTraversalPermission.NONE; -import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN; -import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE; - -import org.opentripplanner.osm.wayproperty.WayProperties; -import org.opentripplanner.osm.wayproperty.WayPropertySet; -import org.opentripplanner.osm.wayproperty.specifier.BestMatchSpecifier; -import org.opentripplanner.osm.wayproperty.specifier.LogicalOrSpecifier; -import org.opentripplanner.routing.services.notes.StreetNotesService; - -/** - * This factory class provides a default collection of {@link WayProperties} that determine how OSM - * streets can be traversed in various modes. - *

- * Circa January 2011, Grant and Mele at TriMet undertook proper testing of bike (and transit) - * routing, and worked with David Turner on assigning proper weights to different facility types. - * The weights in this file grew organically from trial and error, and are the result of months of - * testing and tweaking the routes that OTP returned, as well as actually walking/biking these - * routes and making changes based on those experiences. This set of weights should be a great - * starting point for others to use, but they are to some extent tailored to the situation in - * Portland and people shouldn't hesitate to adjust them to for their own instance. - *

- * The rules for assigning WayProperties to OSM ways are explained in. The final tie breaker if two - * Pickers both match is the sequence that the properties are added in this file: if all else is - * equal the 'props.setProperties' statement that is closer to the top of the page will prevail over - * those lower down the page. - *

- * Foot and bicycle permissions are also addressed in OpenStreetMapGraphBuilderImpl.Handler#getPermissionsForEntity(). - * For instance, if a way that normally does not permit walking based on its tag matches (the - * prevailing 'props.setProperties' statement) has a 'foot=yes' tag the permissions are overridden - * and walking is allowed on that way. - *

- * TODO clarify why this needs a separate factory interface. - * - * @author bdferris, novalis - * @see OsmTagMapper - */ -class DefaultMapper implements OsmTagMapper { - - /* Populate properties on existing WayPropertySet */ - public void populateProperties(WayPropertySet props) { - WayProperties allWayProperties = withModes(ALL).build(); - WayProperties noneWayProperties = withModes(NONE).build(); - WayProperties pedestrianWayProperties = withModes(PEDESTRIAN).build(); - WayProperties pedestrianAndBicycleWayProperties = withModes(PEDESTRIAN_AND_BICYCLE).build(); - /* no bicycle tags */ - - /* NONE */ - props.setProperties("mtb:scale=3", noneWayProperties); - props.setProperties("mtb:scale=4", noneWayProperties); - props.setProperties("mtb:scale=5", noneWayProperties); - props.setProperties("mtb:scale=6", noneWayProperties); - - /* PEDESTRIAN */ - props.setProperties("highway=corridor", pedestrianWayProperties); - props.setProperties("highway=steps", pedestrianWayProperties); - props.setProperties("highway=crossing", pedestrianWayProperties); - props.setProperties("highway=platform", pedestrianWayProperties); - props.setProperties("public_transport=platform", pedestrianWayProperties); - props.setProperties("public_transport=platform;area=yes", pedestrianWayProperties); - props.setProperties("railway=platform", pedestrianWayProperties); - props.setProperties("footway=sidewalk;highway=footway", pedestrianWayProperties); - props.setProperties("mtb:scale=1", pedestrianWayProperties); - props.setProperties("mtb:scale=2", pedestrianWayProperties); - - /* PEDESTRIAN_AND_BICYCLE */ - props.setProperties("mtb:scale=0", pedestrianAndBicycleWayProperties); - props.setProperties("highway=cycleway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.6)); - props.setProperties("highway=path", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75)); - props.setProperties("highway=pedestrian", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9)); - props.setProperties("highway=footway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1)); - props.setProperties("highway=bridleway", withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.3)); - - /* ALL */ - props.setProperties("highway=living_street", withModes(ALL).bicycleSafety(0.9)); - props.setProperties("highway=unclassified", allWayProperties); - props.setProperties("highway=road", allWayProperties); - props.setProperties("highway=byway", withModes(ALL).bicycleSafety(1.3)); - props.setProperties("highway=track", withModes(ALL).bicycleSafety(1.3)); - props.setProperties("highway=service", withModes(ALL).bicycleSafety(1.1)); - props.setProperties("highway=residential", withModes(ALL).bicycleSafety(0.98)); - props.setProperties("highway=residential_link", withModes(ALL).bicycleSafety(0.98)); - props.setProperties("highway=tertiary", allWayProperties); - props.setProperties("highway=tertiary_link", allWayProperties); - props.setProperties("highway=secondary", withModes(ALL).bicycleSafety(1.5)); - props.setProperties("highway=secondary_link", withModes(ALL).bicycleSafety(1.5)); - props.setProperties("highway=primary", withModes(ALL).bicycleSafety(2.06)); - props.setProperties("highway=primary_link", withModes(ALL).bicycleSafety(2.06)); - - /* DRIVING ONLY */ - // trunk and motorway links are often short distances and necessary connections - props.setProperties("highway=trunk_link", withModes(CAR).bicycleSafety(2.06)); - props.setProperties("highway=motorway_link", withModes(CAR).bicycleSafety(2.06)); - - props.setProperties("highway=trunk", withModes(CAR).bicycleSafety(7.47)); - props.setProperties("highway=motorway", withModes(CAR).bicycleSafety(8)); - - /* cycleway=lane */ - props.setProperties( - "highway=*;cycleway=lane", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.87) - ); - props.setProperties("highway=service;cycleway=lane", withModes(ALL).bicycleSafety(0.77)); - props.setProperties("highway=residential;cycleway=lane", withModes(ALL).bicycleSafety(0.77)); - props.setProperties( - "highway=residential_link;cycleway=lane", - withModes(ALL).bicycleSafety(0.77) - ); - props.setProperties("highway=tertiary;cycleway=lane", withModes(ALL).bicycleSafety(0.87)); - props.setProperties("highway=tertiary_link;cycleway=lane", withModes(ALL).bicycleSafety(0.87)); - props.setProperties("highway=secondary;cycleway=lane", withModes(ALL).bicycleSafety(0.96)); - props.setProperties("highway=secondary_link;cycleway=lane", withModes(ALL).bicycleSafety(0.96)); - props.setProperties("highway=primary;cycleway=lane", withModes(ALL).bicycleSafety(1.15)); - props.setProperties("highway=primary_link;cycleway=lane", withModes(ALL).bicycleSafety(1.15)); - - /* BICYCLE_AND_CAR */ - props.setProperties( - "highway=trunk;cycleway=lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.5) - ); - props.setProperties( - "highway=trunk_link;cycleway=lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.15) - ); - props.setProperties( - "highway=motorway;cycleway=lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(2) - ); - props.setProperties( - "highway=motorway_link;cycleway=lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.15) - ); - - /* cycleway=share_busway */ - props.setProperties( - "highway=*;cycleway=share_busway", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.92) - ); - props.setProperties( - "highway=service;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.85) - ); - props.setProperties( - "highway=residential;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.85) - ); - props.setProperties( - "highway=residential_link;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.85) - ); - props.setProperties( - "highway=tertiary;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.92) - ); - props.setProperties( - "highway=tertiary_link;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.92) - ); - props.setProperties( - "highway=secondary;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.99) - ); - props.setProperties( - "highway=secondary_link;cycleway=share_busway", - withModes(ALL).bicycleSafety(0.99) - ); - props.setProperties( - "highway=primary;cycleway=share_busway", - withModes(ALL).bicycleSafety(1.25) - ); - props.setProperties( - "highway=primary_link;cycleway=share_busway", - withModes(ALL).bicycleSafety(1.25) - ); - props.setProperties( - "highway=trunk;cycleway=share_busway", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.75) - ); - props.setProperties( - "highway=trunk_link;cycleway=share_busway", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.25) - ); - props.setProperties( - "highway=motorway;cycleway=share_busway", - withModes(BICYCLE_AND_CAR).bicycleSafety(2.5) - ); - props.setProperties( - "highway=motorway_link;cycleway=share_busway", - withModes(BICYCLE_AND_CAR).bicycleSafety(1.25) - ); - - /* cycleway=opposite_lane */ - props.setProperties( - "highway=*;cycleway=opposite_lane", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1, 0.87) - ); - props.setProperties( - "highway=service;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(1.1, 0.77) - ); - props.setProperties( - "highway=residential;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(0.98, 0.77) - ); - props.setProperties( - "highway=residential_link;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(0.98, 0.77) - ); - props.setProperties( - "highway=tertiary;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(1, 0.87) - ); - props.setProperties( - "highway=tertiary_link;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(1, 0.87) - ); - props.setProperties( - "highway=secondary;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(1.5, 0.96) - ); - props.setProperties( - "highway=secondary_link;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(1.5, 0.96) - ); - props.setProperties( - "highway=primary;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(2.06, 1.15) - ); - props.setProperties( - "highway=primary_link;cycleway=opposite_lane", - withModes(ALL).bicycleSafety(2.06, 1.15) - ); - props.setProperties( - "highway=trunk;cycleway=opposite_lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(7.47, 1.5) - ); - props.setProperties( - "highway=trunk_link;cycleway=opposite_lane", - withModes(BICYCLE_AND_CAR).bicycleSafety(2.06, 1.15) - ); - - /* cycleway=track */ - props.setProperties( - "highway=*;cycleway=track", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) - ); - props.setProperties("highway=service;cycleway=track", withModes(ALL).bicycleSafety(0.65)); - props.setProperties("highway=residential;cycleway=track", withModes(ALL).bicycleSafety(0.65)); - props.setProperties( - "highway=residential_link;cycleway=track", - withModes(ALL).bicycleSafety(0.65) - ); - props.setProperties("highway=tertiary;cycleway=track", withModes(ALL).bicycleSafety(0.75)); - props.setProperties("highway=tertiary_link;cycleway=track", withModes(ALL).bicycleSafety(0.75)); - props.setProperties("highway=secondary;cycleway=track", withModes(ALL).bicycleSafety(0.8)); - props.setProperties("highway=secondary_link;cycleway=track", withModes(ALL).bicycleSafety(0.8)); - props.setProperties("highway=primary;cycleway=track", withModes(ALL).bicycleSafety(0.85)); - props.setProperties("highway=primary_link;cycleway=track", withModes(ALL).bicycleSafety(0.85)); - props.setProperties( - "highway=trunk;cycleway=track", - withModes(BICYCLE_AND_CAR).bicycleSafety(0.95) - ); - props.setProperties( - "highway=trunk_link;cycleway=track", - withModes(BICYCLE_AND_CAR).bicycleSafety(0.85) - ); - - /* cycleway=opposite_track */ - props.setProperties( - "highway=*;cycleway=opposite_track", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.0, 0.75) - ); - props.setProperties( - "highway=service;cycleway=opposite_track", - withModes(ALL).bicycleSafety(1.1, 0.65) - ); - props.setProperties( - "highway=residential;cycleway=opposite_track", - withModes(ALL).bicycleSafety(0.98, 0.65) - ); - props.setProperties( - "highway=residential_link;cycleway=opposite_track", - withModes(ALL).bicycleSafety(0.98, 0.65) - ); - props.setProperties( - "highway=tertiary;cycleway=opposite_track", - withModes(ALL).bicycleSafety(1, 0.75) - ); - props.setProperties( - "highway=tertiary_link;cycleway=opposite_track", - withModes(ALL).bicycleSafety(1, 0.75) - ); - props.setProperties( - "highway=secondary;cycleway=opposite_track", - withModes(ALL).bicycleSafety(1.5, 0.8) - ); - props.setProperties( - "highway=secondary_link;cycleway=opposite_track", - withModes(ALL).bicycleSafety(1.5, 0.8) - ); - props.setProperties( - "highway=primary;cycleway=opposite_track", - withModes(ALL).bicycleSafety(2.06, 0.85) - ); - props.setProperties( - "highway=primary_link;cycleway=opposite_track", - withModes(ALL).bicycleSafety(2.06, 0.85) - ); - props.setProperties( - "highway=trunk;cycleway=opposite_track", - withModes(BICYCLE_AND_CAR).bicycleSafety(7.47, 0.95) - ); - props.setProperties( - "highway=trunk_link;cycleway=opposite_track", - withModes(BICYCLE_AND_CAR).bicycleSafety(2.06, 0.85) - ); - - /* cycleway=shared_lane a.k.a. bike boulevards or neighborhood greenways */ - props.setProperties( - "highway=*;cycleway=shared_lane", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.77) - ); - props.setProperties("highway=service;cycleway=shared_lane", withModes(ALL).bicycleSafety(0.73)); - props.setProperties( - "highway=residential;cycleway=shared_lane", - withModes(ALL).bicycleSafety(0.77) - ); - props.setProperties( - "highway=residential_link;cycleway=shared_lane", - withModes(ALL).bicycleSafety(0.77) - ); - props.setProperties( - "highway=tertiary;cycleway=shared_lane", - withModes(ALL).bicycleSafety(0.83) - ); - props.setProperties( - "highway=tertiary_link;cycleway=shared_lane", - withModes(ALL).bicycleSafety(0.83) - ); - props.setProperties( - "highway=secondary;cycleway=shared_lane", - withModes(ALL).bicycleSafety(1.25) - ); - props.setProperties( - "highway=secondary_link;cycleway=shared_lane", - withModes(ALL).bicycleSafety(1.25) - ); - props.setProperties("highway=primary;cycleway=shared_lane", withModes(ALL).bicycleSafety(1.75)); - props.setProperties( - "highway=primary_link;cycleway=shared_lane", - withModes(ALL).bicycleSafety(1.75) - ); - - /* cycleway=opposite */ - props.setProperties( - "highway=*;cycleway=opposite", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1, 1.4) - ); - props.setProperties("highway=service;cycleway=opposite", withModes(ALL).bicycleSafety(1.1)); - props.setProperties( - "highway=residential;cycleway=opposite", - withModes(ALL).bicycleSafety(0.98) - ); - props.setProperties( - "highway=residential_link;cycleway=opposite", - withModes(ALL).bicycleSafety(0.98) - ); - props.setProperties("highway=tertiary;cycleway=opposite", allWayProperties); - props.setProperties("highway=tertiary_link;cycleway=opposite", allWayProperties); - props.setProperties( - "highway=secondary;cycleway=opposite", - withModes(ALL).bicycleSafety(1.5, 1.71) - ); - props.setProperties( - "highway=secondary_link;cycleway=opposite", - withModes(ALL).bicycleSafety(1.5, 1.71) - ); - props.setProperties( - "highway=primary;cycleway=opposite", - withModes(ALL).bicycleSafety(2.06, 2.99) - ); - props.setProperties( - "highway=primary_link;cycleway=opposite", - withModes(ALL).bicycleSafety(2.06, 2.99) - ); - - /* - * path designed for bicycles (should be treated exactly as a cycleway is), this is a multi-use path (MUP) - */ - props.setProperties( - "highway=path;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.60) - ); - - /* special cases for footway, pedestrian and bicycles */ - props.setProperties( - "highway=footway;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) - ); - props.setProperties( - "highway=footway;bicycle=yes;area=yes", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9) - ); - props.setProperties( - "highway=pedestrian;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) - ); - - /* sidewalk and crosswalk */ - props.setProperties( - "footway=sidewalk;highway=footway;bicycle=yes", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(2.5) - ); - props.setProperties( - "footway=sidewalk;highway=footway;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1) - ); - props.setProperties( - "highway=footway;footway=crossing", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(2.5) - ); - props.setProperties( - "highway=footway;footway=crossing;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.1) - ); - - /* - * bicycles on tracks (tracks are defined in OSM as: Roads for agricultural use, gravel roads in the forest etc.; usually unpaved/unsealed but - * may occasionally apply to paved tracks as well.) - */ - props.setProperties( - "highway=track;bicycle=yes", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.18) - ); - props.setProperties( - "highway=track;bicycle=designated", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.99) - ); - props.setProperties( - "highway=track;bicycle=yes;surface=*", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.18) - ); - props.setProperties( - "highway=track;bicycle=designated;surface=*", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.99) - ); - /* this is to avoid double counting since tracks are almost of surface type that is penalized */ - props.setProperties( - "highway=track;surface=*", - withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(1.3) - ); - - /* bicycle=designated, but no bike infrastructure is present */ - props.setProperties("highway=*;bicycle=designated", withModes(ALL).bicycleSafety(0.97)); - props.setProperties("highway=service;bicycle=designated", withModes(ALL).bicycleSafety(0.84)); - props.setProperties( - "highway=residential;bicycle=designated", - withModes(ALL).bicycleSafety(0.95) - ); - props.setProperties( - "highway=unclassified;bicycle=designated", - withModes(ALL).bicycleSafety(0.95) - ); - props.setProperties( - "highway=residential_link;bicycle=designated", - withModes(ALL).bicycleSafety(0.95) - ); - props.setProperties("highway=tertiary;bicycle=designated", withModes(ALL).bicycleSafety(0.97)); - props.setProperties( - "highway=tertiary_link;bicycle=designated", - withModes(ALL).bicycleSafety(0.97) - ); - props.setProperties("highway=secondary;bicycle=designated", withModes(ALL).bicycleSafety(1.46)); - props.setProperties( - "highway=secondary_link;bicycle=designated", - withModes(ALL).bicycleSafety(1.46) - ); - props.setProperties("highway=primary;bicycle=designated", withModes(ALL).bicycleSafety(2)); - props.setProperties("highway=primary_link;bicycle=designated", withModes(ALL).bicycleSafety(2)); - props.setProperties( - "highway=trunk;bicycle=designated", - withModes(BICYCLE_AND_CAR).bicycleSafety(7.25) - ); - props.setProperties( - "highway=trunk_link;bicycle=designated", - withModes(BICYCLE_AND_CAR).bicycleSafety(2) - ); - props.setProperties( - "highway=motorway;bicycle=designated", - withModes(BICYCLE_AND_CAR).bicycleSafety(7.76) - ); - props.setProperties( - "highway=motorway_link;bicycle=designated", - withModes(BICYCLE_AND_CAR).bicycleSafety(2) - ); - - // We assume highway/cycleway of a cycle network to be safer (for bicycle network relations, their network is copied to way in postLoad) - // this uses a OR since you don't want to apply the safety multiplier more than once. - // Signed bicycle_roads and cyclestreets exist in traffic codes of some european countries. - // Tagging in OSM and on-the-ground use is varied, so just assume they are "somehow safer", too. - // In my test area ways often, but not always, have both tags. - // For simplicity these two concepts are handled together. - props.setMixinProperties( - new LogicalOrSpecifier( - "lcn=yes", - "rcn=yes", - "ncn=yes", - "bicycle_road=yes", - "cyclestreet=yes" - ), - ofBicycleSafety(0.7) - ); - - /* - * Automobile speeds in the United States: Based on my (mattwigway) personal experience, primarily in California - */ - props.setCarSpeed("highway=motorway", 29); // 29 m/s ~= 65 mph - props.setCarSpeed("highway=motorway_link", 15); // ~= 35 mph - props.setCarSpeed("highway=trunk", 24.6f); // ~= 55 mph - props.setCarSpeed("highway=trunk_link", 15); // ~= 35 mph - props.setCarSpeed("highway=primary", 20); // ~= 45 mph - props.setCarSpeed("highway=primary_link", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=secondary", 15); // ~= 35 mph - props.setCarSpeed("highway=secondary_link", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=tertiary", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=tertiary_link", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=living_street", 2.2f); // ~= 5 mph - - // generally, these will not allow cars at all, but the docs say - // "For roads used mainly/exclusively for pedestrians . . . which may allow access by - // motorised vehicles only for very limited periods of the day." - // http://wiki.openstreetmap.org/wiki/Key:highway - // This of course makes the street network time-dependent - props.setCarSpeed("highway=pedestrian", 2.2f); // ~= 5 mph - - props.setCarSpeed("highway=residential", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=unclassified", 11.2f); // ~= 25 mph - props.setCarSpeed("highway=service", 6.7f); // ~= 15 mph - props.setCarSpeed("highway=track", 4.5f); // ~= 10 mph - props.setCarSpeed("highway=road", 11.2f); // ~= 25 mph - - // default ~= 25 mph - props.defaultCarSpeed = 11.2f; - // 38 m/s ~= 85 mph ~= 137 kph - props.maxPossibleCarSpeed = 38f; - - /* special situations */ - - /* - * cycleway:left/right=lane/track/shared_lane permutations - no longer needed because left/right matching algorithm does this - */ - - /* cycleway:left=lane */ - /* cycleway:right=track */ - /* cycleway:left=track */ - /* cycleway:right=shared_lane */ - /* cycleway:left=shared_lane */ - /* cycleway:right=lane, cycleway:left=track */ - /* cycleway:right=lane, cycleway:left=shared_lane */ - /* cycleway:right=track, cycleway:left=lane */ - /* cycleway:right=track, cycleway:left=shared_lane */ - /* cycleway:right=shared_lane, cycleway:left=lane */ - /* cycleway:right=shared_lane, cycleway:left=track */ - - /* surface=* mixins */ - - /* - * The following tags have been removed from surface weights because they are no more of an impedence to bicycling than a paved surface - * surface=paving_stones surface=fine_gravel (sounds counter-intuitive but see the definition on the OSM Wiki) surface=tartan (this what - * running tracks are usually made of) - */ - - props.setMixinProperties("surface=unpaved", ofBicycleSafety(1.18)); - props.setMixinProperties("surface=compacted", ofBicycleSafety(1.18)); - props.setMixinProperties("surface=wood", ofBicycleSafety(1.18)); - - props.setMixinProperties("surface=cobblestone", ofBicycleSafety(1.3)); - props.setMixinProperties("surface=sett", ofBicycleSafety(1.3)); - props.setMixinProperties("surface=unhewn_cobblestone", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=grass_paver", ofBicycleSafety(1.3)); - props.setMixinProperties("surface=pebblestone", ofBicycleSafety(1.3)); - // Can be slick if wet, but otherwise not unfavorable to bikes - props.setMixinProperties("surface=metal", ofBicycleSafety(1.3)); - props.setMixinProperties("surface=ground", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=dirt", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=earth", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=grass", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=mud", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=woodchip", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=gravel", ofBicycleSafety(1.5)); - props.setMixinProperties("surface=artifical_turf", ofBicycleSafety(1.5)); - - /* sand is deadly for bikes */ - props.setMixinProperties("surface=sand", ofBicycleSafety(100)); - - /* Portland-local mixins */ - - props.setMixinProperties("foot=discouraged", ofWalkSafety(3)); - props.setMixinProperties("bicycle=discouraged", ofBicycleSafety(3)); - - props.setMixinProperties("foot=use_sidepath", ofWalkSafety(5)); - props.setMixinProperties("bicycle=use_sidepath", ofBicycleSafety(5)); - - populateNotesAndNames(props); - - // slope overrides - props.setSlopeOverride(new BestMatchSpecifier("bridge=*"), true); - props.setSlopeOverride(new BestMatchSpecifier("embankment=*"), true); - props.setSlopeOverride(new BestMatchSpecifier("cutting=*"), true); - props.setSlopeOverride(new BestMatchSpecifier("tunnel=*"), true); - props.setSlopeOverride(new BestMatchSpecifier("location=underground"), true); - props.setSlopeOverride(new BestMatchSpecifier("indoor=yes"), true); - } - - public void populateNotesAndNames(WayPropertySet props) { - /* and the notes */ - // TODO: The curly brackets in the string below mean that the CreativeNamer should substitute in OSM tag values. - // However they are not taken into account when passed to the translation function. - // props.createNotes("wheelchair:description=*", "{wheelchair:description}", StreetNotesService.WHEELCHAIR_MATCHER); - // TODO: The two entries below produce lots of spurious notes (because of OSM mapper comments) - // props.createNotes("note=*", "{note}", StreetNotesService.ALWAYS_MATCHER); - // props.createNotes("notes=*", "{notes}", StreetNotesService.ALWAYS_MATCHER); - props.createNotes( - "RLIS:bicycle=caution_area", - "note.caution", - StreetNotesService.BICYCLE_MATCHER - ); - props.createNotes( - "CCGIS:bicycle=caution_area", - "note.caution", - StreetNotesService.BICYCLE_MATCHER - ); - // TODO: Maybe we should apply the following notes only for car/bike - props.createNotes("surface=unpaved", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes( - "surface=compacted", - "note.unpaved_surface", - StreetNotesService.ALWAYS_MATCHER - ); - props.createNotes("surface=ground", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes("surface=dirt", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes("surface=earth", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes("surface=grass", "note.unpaved_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes("surface=mud", "note.muddy_surface", StreetNotesService.ALWAYS_MATCHER); - props.createNotes("toll=yes", "note.toll", StreetNotesService.DRIVING_MATCHER); - props.createNotes("toll:motorcar=yes", "note.toll", StreetNotesService.DRIVING_MATCHER); - - /* and some names */ - // Basics - props.createNames("highway=cycleway", "name.bike_path"); - props.createNames("cycleway=track", "name.bike_path"); - props.createNames("highway=pedestrian", "name.pedestrian_path"); - props.createNames("highway=pedestrian;area=yes", "name.pedestrian_area"); - props.createNames("highway=path", "name.path"); - props.createNames("highway=footway", "name.pedestrian_path"); - props.createNames("highway=bridleway", "name.bridleway"); - props.createNames("highway=footway;bicycle=no", "name.pedestrian_path"); - - // Platforms - props.createNames("otp:route_ref=*", "name.otp_route_ref"); - props.createNames("highway=platform;ref=*", "name.platform_ref"); - props.createNames("railway=platform;ref=*", "name.platform_ref"); - props.createNames("railway=platform;highway=footway;footway=sidewalk", "name.platform"); - props.createNames("railway=platform;highway=path;path=sidewalk", "name.platform"); - props.createNames("railway=platform;highway=pedestrian", "name.platform"); - props.createNames("railway=platform;highway=path", "name.platform"); - props.createNames("railway=platform;highway=footway", "name.platform"); - props.createNames("highway=platform", "name.platform"); - props.createNames("railway=platform", "name.platform"); - props.createNames("railway=platform;highway=footway;bicycle=no", "name.platform"); - - // Bridges/Tunnels - props.createNames("highway=pedestrian;bridge=*", "name.footbridge"); - props.createNames("highway=path;bridge=*", "name.footbridge"); - props.createNames("highway=footway;bridge=*", "name.footbridge"); - - props.createNames("highway=pedestrian;tunnel=*", "name.underpass"); - props.createNames("highway=path;tunnel=*", "name.underpass"); - props.createNames("highway=footway;tunnel=*", "name.underpass"); - - // Basic Mappings - props.createNames("highway=motorway", "name.road"); - props.createNames("highway=motorway_link", "name.ramp"); - props.createNames("highway=trunk", "name.road"); - props.createNames("highway=trunk_link", "name.ramp"); - - props.createNames("highway=primary", "name.road"); - props.createNames("highway=primary_link", "name.link"); - props.createNames("highway=secondary", "name.road"); - props.createNames("highway=secondary_link", "name.link"); - props.createNames("highway=tertiary", "name.road"); - props.createNames("highway=tertiary_link", "name.link"); - props.createNames("highway=unclassified", "name.road"); - props.createNames("highway=residential", "name.road"); - props.createNames("highway=living_street", "name.road"); - props.createNames("highway=road", "name.road"); - props.createNames("highway=service", "name.service_road"); - props.createNames("highway=service;service=alley", "name.alley"); - props.createNames("highway=service;service=parking_aisle", "name.parking_aisle"); - props.createNames("highway=byway", "name.byway"); - props.createNames("highway=track", "name.track"); - - props.createNames("highway=footway;footway=sidewalk", "name.sidewalk"); - props.createNames("highway=path;path=sidewalk", "name.sidewalk"); - - props.createNames("highway=steps", "name.steps"); - - props.createNames("amenity=bicycle_parking;name=*", "name.bicycle_parking_name"); - props.createNames("amenity=bicycle_parking", "name.bicycle_parking"); - - props.createNames("amenity=parking;name=*", "name.park_and_ride_name"); - props.createNames("amenity=parking", "name.park_and_ride_station"); - } -} From c6e74f3c007ea8eae39733cb6425eb411423c502 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 16 Oct 2024 09:08:14 +0300 Subject: [PATCH 08/15] Add unit tests for area permissions of Finland mapper --- .../osm/tagmapping/FinlandMapperTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/application/src/test/java/org/opentripplanner/osm/tagmapping/FinlandMapperTest.java b/application/src/test/java/org/opentripplanner/osm/tagmapping/FinlandMapperTest.java index e3f24f64c6c..8e931e1096a 100644 --- a/application/src/test/java/org/opentripplanner/osm/tagmapping/FinlandMapperTest.java +++ b/application/src/test/java/org/opentripplanner/osm/tagmapping/FinlandMapperTest.java @@ -2,6 +2,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.opentripplanner.street.model.StreetTraversalPermission.NONE; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE; import org.junit.jupiter.api.Test; import org.opentripplanner.osm.model.OsmWay; @@ -194,4 +196,28 @@ public void testTagMapping() { wayData = wps.getDataForWay(way); assertEquals(wayData.getPermission(), NONE); } + + /** + * Test that biking is not allowed in footway areas and transit platforms + */ + @Test + public void testArea() { + OsmWithTags way; + WayProperties wayData; + + way = new OsmWay(); + way.addTag("highway", "footway"); + way.addTag("area", "yes"); + wayData = wps.getDataForWay(way); + assertEquals(wayData.getPermission(), PEDESTRIAN); + + way = new OsmWay(); + way.addTag("public_transport", "platform"); + way.addTag("area", "yes"); + wayData = wps.getDataForWay(way); + assertEquals(wayData.getPermission(), PEDESTRIAN); + way.addTag("bicycle", "yes"); + wayData = wps.getDataForWay(way); + assertEquals(wayData.getPermission(), PEDESTRIAN_AND_BICYCLE); + } } From c5bb551ad8d3b4f348f44b9fe5b3edd07f5bd234 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 16 Oct 2024 09:36:55 +0300 Subject: [PATCH 09/15] Test biking on platforms in Germany --- .../osm/tagmapping/GermanyMapperTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/application/src/test/java/org/opentripplanner/osm/tagmapping/GermanyMapperTest.java b/application/src/test/java/org/opentripplanner/osm/tagmapping/GermanyMapperTest.java index 28f482a3388..c0901f4fcf5 100644 --- a/application/src/test/java/org/opentripplanner/osm/tagmapping/GermanyMapperTest.java +++ b/application/src/test/java/org/opentripplanner/osm/tagmapping/GermanyMapperTest.java @@ -1,6 +1,8 @@ package org.opentripplanner.osm.tagmapping; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN; +import static org.opentripplanner.street.model.StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -279,4 +281,19 @@ void testGermanAutobahnSpeed() { autobahn.addTag("maxspeed", "none"); assertEquals(33.33000183105469, wps.getCarSpeedForWay(autobahn, false), epsilon); } + + /** + * Test that biking is not allowed in transit platforms + */ + @Test + public void testArea() { + OsmWithTags way; + + way = new OsmWithTags(); + way.addTag("public_transport", "platform"); + way.addTag("area", "yes"); + assertEquals(wps.getDataForWay(way).getPermission(), PEDESTRIAN); + way.addTag("bicycle", "yes"); + assertEquals(wps.getDataForWay(way).getPermission(), PEDESTRIAN_AND_BICYCLE); + } } From a247756f7bd9793999e391a91d8a2283b0903055 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 16 Oct 2024 10:55:12 +0300 Subject: [PATCH 10/15] Remove unused logger --- .../graph_builder/module/osm/WalkableAreaBuilder.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java index 81f59287939..92c4cf3dad1 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java @@ -49,8 +49,6 @@ import org.opentripplanner.street.search.StreetSearchBuilder; import org.opentripplanner.street.search.state.State; import org.opentripplanner.street.search.strategy.DominanceFunctions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Theoretically, it is not correct to build the visibility graph on the joined polygon of areas @@ -71,9 +69,6 @@ * to an excessive number of edges, or to no edges at all if maxAreaNodes is surpassed. */ class WalkableAreaBuilder { - - private static final Logger LOG = LoggerFactory.getLogger(WalkableAreaBuilder.class); - private final DataImportIssueStore issueStore; private final int maxAreaNodes; From 03ef955b5d2149a4b4400eed84c687d31a9074b9 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 16 Oct 2024 11:43:44 +0300 Subject: [PATCH 11/15] Fix formatting --- .../graph_builder/module/osm/WalkableAreaBuilder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java index 92c4cf3dad1..2802ee70a89 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/WalkableAreaBuilder.java @@ -69,6 +69,7 @@ * to an excessive number of edges, or to no edges at all if maxAreaNodes is surpassed. */ class WalkableAreaBuilder { + private final DataImportIssueStore issueStore; private final int maxAreaNodes; From 0bde65520557b5e0917be7283ad758ef1a56e34d Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Oct 2024 13:31:54 +0300 Subject: [PATCH 12/15] Mark BestMatchSpecifier as deprecated --- .../osm/wayproperty/specifier/BestMatchSpecifier.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/src/main/java/org/opentripplanner/osm/wayproperty/specifier/BestMatchSpecifier.java b/application/src/main/java/org/opentripplanner/osm/wayproperty/specifier/BestMatchSpecifier.java index 1d03d74956e..5365937ad56 100644 --- a/application/src/main/java/org/opentripplanner/osm/wayproperty/specifier/BestMatchSpecifier.java +++ b/application/src/main/java/org/opentripplanner/osm/wayproperty/specifier/BestMatchSpecifier.java @@ -26,6 +26,10 @@ public class BestMatchSpecifier implements OsmSpecifier { public static final int NO_MATCH_SCORE = 0; private final Condition[] conditions; + /** + * @deprecated Logic is fuzzy and unpredictable, use ExactMatchSpecifier instead + */ + @Deprecated public BestMatchSpecifier(String spec) { conditions = OsmSpecifier.parseConditions(spec, ";"); } From 36c1006df4095d4a577873b6383ef792a69d7b79 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 23 Oct 2024 15:48:12 +0300 Subject: [PATCH 13/15] Use ExactMatchSpecifier for the problematic footway area biking rule Instead of adding competing best match rules, start using the well designed exact match specifier. This may cause some unexpected changes but as the change concerns only one specific rule, we should be able to deal with them, --- .../opentripplanner/osm/tagmapping/FinlandMapper.java | 2 -- .../opentripplanner/osm/tagmapping/OsmTagMapper.java | 11 +++++++---- doc/user/osm/Finland.md | 4 +--- doc/user/osm/Germany.md | 3 +-- doc/user/osm/OsmTag.md | 3 +-- doc/user/osm/UK.md | 3 +-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java b/application/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java index e4267ce9454..5e413af510a 100644 --- a/application/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java +++ b/application/src/main/java/org/opentripplanner/osm/tagmapping/FinlandMapper.java @@ -90,8 +90,6 @@ else if (speedLimit <= 16.65f) { // No biking on designated footways/sidewalks props.setProperties("highway=footway", withModes(PEDESTRIAN)); - props.setProperties("highway=footway;area=yes", withModes(PEDESTRIAN)); - //props.setProperties("public_transport=platform;area=yes", withModes(PEDESTRIAN)); props.setProperties("footway=sidewalk;highway=footway", withModes(PEDESTRIAN)); // Walking on segregated ways is safer than when cycling and walking happens on the same lane diff --git a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java index 6bfb9367111..6b8511cc4c8 100644 --- a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java +++ b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java @@ -14,6 +14,8 @@ import org.opentripplanner.osm.wayproperty.WayProperties; import org.opentripplanner.osm.wayproperty.WayPropertySet; import org.opentripplanner.osm.wayproperty.specifier.BestMatchSpecifier; +import org.opentripplanner.osm.wayproperty.specifier.Condition; +import org.opentripplanner.osm.wayproperty.specifier.ExactMatchSpecifier; import org.opentripplanner.osm.wayproperty.specifier.LogicalOrSpecifier; import org.opentripplanner.routing.services.notes.StreetNotesService; @@ -39,10 +41,8 @@ * prevailing 'props.setProperties' statement) has a 'foot=yes' tag the permissions are overridden * and walking is allowed on that way. *

- * TODO clarify why this needs a separate factory interface. * * @author bdferris, novalis - * @see OsmTagMapper */ public class OsmTagMapper { @@ -67,7 +67,6 @@ public void populateProperties(WayPropertySet props) { props.setProperties("highway=crossing", pedestrianWayProperties); props.setProperties("highway=platform", pedestrianWayProperties); props.setProperties("public_transport=platform", pedestrianWayProperties); - props.setProperties("public_transport=platform;area=yes", pedestrianWayProperties); props.setProperties("railway=platform", pedestrianWayProperties); props.setProperties("footway=sidewalk;highway=footway", pedestrianWayProperties); props.setProperties("mtb:scale=1", pedestrianWayProperties); @@ -408,7 +407,11 @@ public void populateProperties(WayPropertySet props) { withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) ); props.setProperties( - "highway=footway;bicycle=yes;area=yes", + new ExactMatchSpecifier( + new Condition.Equals("highway", "footway"), + new Condition.Equals("bicycle", "yes"), + new Condition.Equals("area", " yes") + ), withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9) ); props.setProperties( diff --git a/doc/user/osm/Finland.md b/doc/user/osm/Finland.md index cdf56dab057..df0d4856014 100644 --- a/doc/user/osm/Finland.md +++ b/doc/user/osm/Finland.md @@ -49,7 +49,6 @@ Lower safety values make an OSM way more desirable and higher values less desira | `present(highway); ice_road=yes` | `NONE` | | | | `present(highway); winter_road=yes` | `NONE` | | | | `highway=footway` | `PEDESTRIAN` | | | -| `highway=footway; area=yes` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `highway=cycleway; segregated=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | 1.1 | | `highway=footway; bridge=yes` | `PEDESTRIAN` | | | @@ -78,7 +77,6 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | -| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | @@ -193,7 +191,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/Germany.md b/doc/user/osm/Germany.md index fb6581a8d3b..527e5f5a3e7 100644 --- a/doc/user/osm/Germany.md +++ b/doc/user/osm/Germany.md @@ -42,7 +42,6 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | -| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | @@ -157,7 +156,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/OsmTag.md b/doc/user/osm/OsmTag.md index a77ebb41b82..e78467ce8bd 100644 --- a/doc/user/osm/OsmTag.md +++ b/doc/user/osm/OsmTag.md @@ -33,7 +33,6 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | -| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | @@ -148,7 +147,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/UK.md b/doc/user/osm/UK.md index 1eebd08c880..1dcae13e145 100644 --- a/doc/user/osm/UK.md +++ b/doc/user/osm/UK.md @@ -47,7 +47,6 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=crossing` | `PEDESTRIAN` | | | | `highway=platform` | `PEDESTRIAN` | | | | `public_transport=platform` | `PEDESTRIAN` | | | -| `public_transport=platform; area=yes` | `PEDESTRIAN` | | | | `railway=platform` | `PEDESTRIAN` | | | | `footway=sidewalk; highway=footway` | `PEDESTRIAN` | | | | `mtb:scale=1` | `PEDESTRIAN` | | | @@ -162,7 +161,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | From 3d754a59307a1c73441672b70a5ac5cb79d5a01d Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 4 Nov 2024 09:30:52 +0200 Subject: [PATCH 14/15] Use convenient notation for cycling area ExactMatchSpecifier --- .../org/opentripplanner/osm/tagmapping/OsmTagMapper.java | 6 +----- doc/user/osm/Finland.md | 2 +- doc/user/osm/Germany.md | 2 +- doc/user/osm/OsmTag.md | 2 +- doc/user/osm/UK.md | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java index 6b8511cc4c8..e4c258ccdc4 100644 --- a/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java +++ b/application/src/main/java/org/opentripplanner/osm/tagmapping/OsmTagMapper.java @@ -407,11 +407,7 @@ public void populateProperties(WayPropertySet props) { withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.75) ); props.setProperties( - new ExactMatchSpecifier( - new Condition.Equals("highway", "footway"), - new Condition.Equals("bicycle", "yes"), - new Condition.Equals("area", " yes") - ), + new ExactMatchSpecifier("highway=footway;bicycle=yes;area=yes"), withModes(PEDESTRIAN_AND_BICYCLE).bicycleSafety(0.9) ); props.setProperties( diff --git a/doc/user/osm/Finland.md b/doc/user/osm/Finland.md index df0d4856014..8a60b5f0b13 100644 --- a/doc/user/osm/Finland.md +++ b/doc/user/osm/Finland.md @@ -191,7 +191,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/Germany.md b/doc/user/osm/Germany.md index 527e5f5a3e7..922aa3af836 100644 --- a/doc/user/osm/Germany.md +++ b/doc/user/osm/Germany.md @@ -156,7 +156,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/OsmTag.md b/doc/user/osm/OsmTag.md index e78467ce8bd..814420b791f 100644 --- a/doc/user/osm/OsmTag.md +++ b/doc/user/osm/OsmTag.md @@ -147,7 +147,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | diff --git a/doc/user/osm/UK.md b/doc/user/osm/UK.md index 0fa908745d6..34c4d1c1778 100644 --- a/doc/user/osm/UK.md +++ b/doc/user/osm/UK.md @@ -163,7 +163,7 @@ Lower safety values make an OSM way more desirable and higher values less desira | `highway=primary_link; cycleway=opposite` | `ALL` | forward: 2.06
back: 2.99 | | | `highway=path; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.6 | | | `highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | -| `highway=footway; bicycle=yes; area= yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | +| `highway=footway; bicycle=yes; area=yes` | `PEDESTRIAN_AND_BICYCLE` | 0.9 | | | `highway=pedestrian; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 0.75 | | | `footway=sidewalk; highway=footway; bicycle=yes` | `PEDESTRIAN_AND_BICYCLE` | 2.5 | | | `footway=sidewalk; highway=footway; bicycle=designated` | `PEDESTRIAN_AND_BICYCLE` | 1.1 | | From e6d383b1e544ccf0f50c065e29e3d580f333c339 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Fri, 8 Nov 2024 13:21:09 +0200 Subject: [PATCH 15/15] Rename function newArea as addArea --- .../graph_builder/module/osm/OsmDatabase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java index 3079f41c4d4..8b88dea93b6 100644 --- a/application/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java +++ b/application/src/main/java/org/opentripplanner/graph_builder/module/osm/OsmDatabase.java @@ -688,7 +688,7 @@ private void processSingleWayAreas() { } } try { - newArea(new Area(way, List.of(way), Collections.emptyList(), nodesById)); + addArea(new Area(way, List.of(way), Collections.emptyList(), nodesById)); } catch (Area.AreaConstructionException | Ring.RingConstructionException e) { // this area cannot be constructed, but we already have all the // necessary nodes to construct it. So, something must be wrong with @@ -751,7 +751,7 @@ private void processMultipolygonRelations() { } processedAreas.add(relation); try { - newArea(new Area(relation, outerWays, innerWays, nodesById)); + addArea(new Area(relation, outerWays, innerWays, nodesById)); } catch (Area.AreaConstructionException | Ring.RingConstructionException e) { issueStore.add(new InvalidOsmGeometry(relation)); continue; @@ -786,7 +786,7 @@ private void processMultipolygonRelations() { /** * Handler for a new Area (single way area or multipolygon relations) */ - private void newArea(Area area) { + private void addArea(Area area) { StreetTraversalPermission permissions = area.parent .getOsmProvider() .getWayPropertySet()