Skip to content

Commit b6d09e8

Browse files
authored
Merge branch 'dev' into abyrd/cost-field-cleanup
2 parents 4c289ca + 0435eaa commit b6d09e8

File tree

9 files changed

+131
-11
lines changed

9 files changed

+131
-11
lines changed

src/main/java/com/conveyal/r5/analyst/cluster/TransportNetworkConfig.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,18 @@ public class TransportNetworkConfig {
6262
*/
6363
public boolean saveShapes;
6464

65+
/**
66+
* Steepest allowable slope for traversal. If a way has an "incline" tag (e.g., from OSW or GATIS rather than
67+
* a typical OSM source) with an absolute value that exceeds this limit, custom TraversalPermissionLabelers can
68+
* remove permissions. Currently implemented only for pedestrians.
69+
*/
70+
public Double maxIncline;
71+
72+
/**
73+
* Whether to exclude pedestrian traversal of ways with highway=stairs tags and nodes with kerb=raised tags. This
74+
* option should generally be used with detailed sidewalk networks and a TraversalPermissionLabeler that forces
75+
* use of sidewalks (i.e., disallows walking on roadways).
76+
*/
77+
public boolean stepFree;
78+
6579
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.conveyal.r5.labeling;
2+
3+
import com.conveyal.osmlib.Way;
4+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
5+
import com.conveyal.r5.streets.EdgeStore;
6+
7+
/**
8+
* USTraversalPermissionLabeler, except biking is disallowed on ways with footway=sidewalk tag
9+
*/
10+
public class NoSidewalkCyclingTraversalPermissionLabeler extends USTraversalPermissionLabeler {
11+
public NoSidewalkCyclingTraversalPermissionLabeler (TransportNetworkConfig config) {
12+
super(config);
13+
}
14+
15+
@Override
16+
public RoadPermission getPermissions(Way way) {
17+
RoadPermission rp = super.getPermissions(way);
18+
if (way.hasTag("footway", "sidewalk")) {
19+
rp.forward.remove(EdgeStore.EdgeFlag.ALLOWS_BIKE);
20+
rp.backward.remove(EdgeStore.EdgeFlag.ALLOWS_BIKE);
21+
}
22+
return rp;
23+
}
24+
25+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.conveyal.r5.labeling;
2+
3+
import com.conveyal.osmlib.Way;
4+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
5+
import com.conveyal.r5.streets.EdgeStore;
6+
7+
/**
8+
* USTraversalPermissionLabeler, except walking is disallowed on ways that allow cars and ways with inclines
9+
* steeper than a specified limit.
10+
*/
11+
public class NoSteepInclinesTraversalPermissionLabeler extends SidewalkTraversalPermissionLabeler {
12+
13+
Double maxIncline;
14+
public NoSteepInclinesTraversalPermissionLabeler (TransportNetworkConfig config) {
15+
super(config);
16+
if (config != null) {
17+
if (config.maxIncline != null) this.maxIncline = config.maxIncline;
18+
}
19+
}
20+
@Override
21+
public RoadPermission getPermissions(Way way) {
22+
// Base class (SidewalkTraversalPermissionLabeler) disallows walking on ways that allow cars
23+
RoadPermission rp = super.getPermissions(way);
24+
25+
// Disallow walking on ways with slopes steeper than specified maxIncline
26+
if (maxIncline != null) {
27+
if (way.hasTag("incline") && Math.abs(Double.parseDouble(way.getTag("incline"))) > maxIncline) {
28+
rp.disallowPedestrians();
29+
}
30+
}
31+
32+
return rp;
33+
}
34+
35+
}

src/main/java/com/conveyal/r5/labeling/RoadPermission.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,10 @@ public RoadPermission(EnumSet<EdgeStore.EdgeFlag> forward,
1818
this.backward = backward;
1919

2020
}
21+
22+
public void disallowPedestrians() {
23+
this.forward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
24+
this.backward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
25+
}
26+
2127
}

src/main/java/com/conveyal/r5/labeling/SidewalkTraversalPermissionLabeler.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.conveyal.r5.labeling;
22

33
import com.conveyal.osmlib.Way;
4+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
45
import com.conveyal.r5.streets.EdgeStore;
56

67
/**
@@ -16,6 +17,10 @@ public class SidewalkTraversalPermissionLabeler extends TraversalPermissionLabel
1617
"access=yes");
1718
}
1819

20+
public SidewalkTraversalPermissionLabeler (TransportNetworkConfig config) {
21+
super(config);
22+
}
23+
1924
@Override
2025
public RoadPermission getPermissions(Way way) {
2126
RoadPermission rp = super.getPermissions(way);
@@ -24,10 +29,7 @@ public RoadPermission getPermissions(Way way) {
2429
rp.backward.contains(EdgeStore.EdgeFlag.ALLOWS_CAR) ||
2530
rp.backward.contains(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_CAR)
2631
) {
27-
rp.forward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
28-
rp.forward.remove(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_PEDESTRIAN);
29-
rp.backward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
30-
rp.backward.remove(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_PEDESTRIAN);
32+
rp.disallowPedestrians();
3133
}
3234
return rp;
3335
}

src/main/java/com/conveyal/r5/labeling/TraversalPermissionLabeler.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.conveyal.r5.labeling;
22

33
import com.conveyal.osmlib.Way;
4+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
45
import com.conveyal.r5.streets.EdgeStore;
56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
@@ -29,6 +30,8 @@ public abstract class TraversalPermissionLabeler {
2930
//This is immutable map of highway tag and boolean which is true if this tag has same road with _link
3031
static final Map<String, Boolean> validHighwayTags;
3132

33+
boolean stepFree;
34+
3235
static {
3336

3437
Map<String, Boolean> validHighwayTagsConst;
@@ -63,6 +66,12 @@ public abstract class TraversalPermissionLabeler {
6366
addPermissions("footway|steps|platform|public_transport=platform|railway=platform|corridor", "access=no;foot=yes");
6467
}
6568

69+
public TraversalPermissionLabeler (TransportNetworkConfig config) {
70+
if (config != null) {
71+
this.stepFree = config.stepFree;
72+
}
73+
}
74+
6675
public RoadPermission getPermissions(Way way) {
6776
EnumMap<Node, Label> tree = getTreeForWay(way);
6877

@@ -132,6 +141,10 @@ public RoadPermission getPermissions(Way way) {
132141
applyOppositeBicyclePermissions(way, backward);
133142
}
134143

144+
if (stepFree && way.hasTag("highway", "steps")) {
145+
forward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
146+
backward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
147+
}
135148

136149
return new RoadPermission(forward, backward);
137150
}

src/main/java/com/conveyal/r5/labeling/USTraversalPermissionLabeler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.conveyal.r5.labeling;
22

33

4+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
5+
46
/**
57
* Traversal permission labeler for the United States, adding things that differ from the base TraversalPermissionLabeler.
68
* https://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions#United_States_of_America
@@ -12,4 +14,8 @@ public class USTraversalPermissionLabeler extends TraversalPermissionLabeler {
1214
addPermissions("cycleway", "bicycle=yes;foot=yes");
1315
}
1416

17+
public USTraversalPermissionLabeler (TransportNetworkConfig config) {
18+
super(config);
19+
}
20+
1521
}

src/main/java/com/conveyal/r5/streets/StreetLayer.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import com.conveyal.r5.api.util.ParkRideParking;
1313
import com.conveyal.r5.common.GeometryUtils;
1414
import com.conveyal.r5.labeling.LevelOfTrafficStressLabeler;
15+
import com.conveyal.r5.labeling.NoSidewalkCyclingTraversalPermissionLabeler;
16+
import com.conveyal.r5.labeling.NoSteepInclinesTraversalPermissionLabeler;
1517
import com.conveyal.r5.labeling.RoadPermission;
1618
import com.conveyal.r5.labeling.SidewalkTraversalPermissionLabeler;
1719
import com.conveyal.r5.labeling.SpeedLabeler;
@@ -133,6 +135,7 @@ public class StreetLayer implements Serializable, Cloneable {
133135
public TIntObjectMap<BikeRentalStation> bikeRentalStationMap;
134136
public TIntObjectMap<ParkRideParking> parkRideLocationsMap;
135137

138+
private boolean stepFree = false;
136139
// TODO these are only needed when building the network, should we really be keeping them here in the layer?
137140
// We should instead have a network builder that holds references to this transient state. Note initial
138141
// approach of specifying a TraversalPermissionLabeler in TransportNetworkConfig.
@@ -209,21 +212,26 @@ public class StreetLayer implements Serializable, Cloneable {
209212

210213
public StreetLayer() {
211214
speedLabeler = new SpeedLabeler(SpeedConfig.defaultConfig());
212-
permissionLabeler = new USTraversalPermissionLabeler();
215+
permissionLabeler = new USTraversalPermissionLabeler(null);
213216
}
214217

215218
public StreetLayer(TransportNetworkConfig config) {
216219
this();
217220
if (config != null) {
218221
permissionLabeler = switch (config.traversalPermissionLabeler) {
219-
case "sidewalk" -> new SidewalkTraversalPermissionLabeler();
220-
case null -> new USTraversalPermissionLabeler();
222+
case "sidewalk" -> new SidewalkTraversalPermissionLabeler(config);
223+
case "noSidewalkCycling" -> new NoSidewalkCyclingTraversalPermissionLabeler(config);
224+
case "noSteepWays" -> new NoSteepInclinesTraversalPermissionLabeler(config);
225+
case null -> new USTraversalPermissionLabeler(config);
221226
default -> throw new IllegalArgumentException(
222227
"Unknown traversal permission labeler: " + config.traversalPermissionLabeler
223228
);
224229
};
230+
231+
stepFree = config.stepFree;
232+
225233
} else {
226-
permissionLabeler = new USTraversalPermissionLabeler();
234+
permissionLabeler = new USTraversalPermissionLabeler(null);
227235
}
228236
}
229237

@@ -334,7 +342,7 @@ void loadFromOsm (OSM osm, boolean removeIslands, boolean saveVertexIndex) {
334342
}
335343
final boolean intersection = osm.intersectionNodes.contains(way.nodes[n]);
336344
final boolean lastNode = (n == (way.nodes.length - 1));
337-
if (intersection || lastNode || isImpassable(node)) {
345+
if (intersection || lastNode || isImpassable(node, stepFree)) {
338346
makeEdgePair(way, beginIdx, n, entry.getKey());
339347
beginIdx = n;
340348
}
@@ -1059,7 +1067,7 @@ private int getVertexIndexForOsmNode(long osmNodeId) {
10591067
if (node.hasTag("highway", "traffic_signals")) {
10601068
vertexStore.setFlag(vertexIndex, TRAFFIC_SIGNAL);
10611069
}
1062-
if (isImpassable(node)) {
1070+
if (isImpassable(node, stepFree)) {
10631071
vertexStore.setFlag(vertexIndex, IMPASSABLE);
10641072
}
10651073
vertexIndexForOsmNode.put(osmNodeId, vertexIndex);
@@ -1113,7 +1121,7 @@ private static short speedToShort(Float speed) {
11131121
*
11141122
* Ideally such areas would be treated as no-through-traffic but that would involve more tricky heuristics.
11151123
*/
1116-
private static boolean isImpassable (Node node) {
1124+
private static boolean isImpassable (Node node, boolean requireStepFree) {
11171125
// This code is hit millions of times so we want to bypass it as much as possible.
11181126
if (node.hasNoTags()) {
11191127
return false;
@@ -1128,6 +1136,11 @@ private static boolean isImpassable (Node node) {
11281136
// Consider the node impassable only when all mode-specific exception tags are missing or clearly negative.
11291137
return isNullOrNo(node.getTag("foot")) && isNullOrNo(node.getTag("bicycle"));
11301138
}
1139+
1140+
if (requireStepFree && node.hasTag("kerb", "raised")) {
1141+
return true;
1142+
}
1143+
11311144
// As a default, err on the side of returning false, which will maintain the preexisting code path.
11321145
return false;
11331146
}

src/test/java/com/conveyal/r5/labeling/TestPermissionsLabeler.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.conveyal.r5.labeling;
22

3+
import com.conveyal.r5.analyst.cluster.TransportNetworkConfig;
4+
35
/**
46
* This is used for tests. It adds new highway tag highway=nobikenoped which forbids cycling and walking. But allows other things.
57
* Created by mabu on 27.11.2015.
@@ -8,4 +10,8 @@ public class TestPermissionsLabeler extends USTraversalPermissionLabeler {
810
static {
911
addPermissions("highway=nobikenoped", "access=yes;bicycle=no;foot=no");
1012
}
13+
14+
public TestPermissionsLabeler () {
15+
super(null);
16+
}
1117
}

0 commit comments

Comments
 (0)