Skip to content

Commit

Permalink
Make sidewalk PermissionLabeler more restrictive
Browse files Browse the repository at this point in the history
Disallow walking anywhere driving is allowed
  • Loading branch information
ansoncfit committed Aug 9, 2024
1 parent 68e4e87 commit e272229
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package com.conveyal.r5.labeling;


import com.conveyal.osmlib.Way;
import com.conveyal.r5.streets.EdgeStore;

import java.util.EnumMap;
import java.util.EnumSet;

/**
* Traversal permission labeler that restricts walking on most driving ways (useful for networks with complete
* sidewalks). Also includes permissions for the United States (see USTraversalPermissionLabeler).
Expand All @@ -12,7 +18,80 @@ public class SidewalkTraversalPermissionLabeler extends TraversalPermissionLabel
addPermissions("cycleway", "bicycle=yes;foot=yes");
addPermissions("trunk|primary|secondary|tertiary|unclassified|residential|living_street|road|service|track",
"access=yes;foot=no"); // Note foot=no
}

@Override
public RoadPermission getPermissions(Way way) {
EnumMap<Node, Label> tree = getTreeForWay(way);

applySpecificPermissions(tree, way);

applyWheelchairPermissions(tree, way);

EnumSet<EdgeStore.EdgeFlag> ret = EnumSet.noneOf(EdgeStore.EdgeFlag.class);

Label walk = walk(tree, Node.FOOT);
Label bicycle = walk(tree, Node.BICYCLE);
Label car = walk(tree, Node.CAR);
Label wheelchair = walk(tree, Node.WHEELCHAIR);
if (walk == Label.YES && car == Label.NO) {
ret.add(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);
} else if (walk == Label.NO_THRU_TRAFFIC) {
ret.add(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_PEDESTRIAN);
}
if (wheelchair == Label.YES && car == Label.NO) {
ret.add(EdgeStore.EdgeFlag.ALLOWS_WHEELCHAIR);
}

if (wheelchair == Label.LIMITED) {
ret.add(EdgeStore.EdgeFlag.LIMITED_WHEELCHAIR);
}
if (bicycle == Label.YES) {
ret.add(EdgeStore.EdgeFlag.ALLOWS_BIKE);
} else if (bicycle == Label.NO_THRU_TRAFFIC) {
ret.add(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_BIKE);
}
if (car == Label.YES) {
ret.add(EdgeStore.EdgeFlag.ALLOWS_CAR);
} else if (car == Label.NO_THRU_TRAFFIC) {
ret.add(EdgeStore.EdgeFlag.NO_THRU_TRAFFIC_CAR);
}


EnumSet<EdgeStore.EdgeFlag> forward = EnumSet.copyOf(ret);
EnumSet<EdgeStore.EdgeFlag> backward = EnumSet.copyOf(ret);

applyDirectionalPermissions(way, forward, backward);

// check for one-way streets. Note that leaf nodes will always be labeled and there is no unknown,
// so we need not traverse the tree
EnumMap<Node, OneWay> dir = getDirectionalTree(way);

//Backward edge
// you can traverse back if this is not one way or it is one way reverse
if (dir.get(Node.CAR) == OneWay.YES) backward.remove(EdgeStore.EdgeFlag.ALLOWS_CAR);
if (dir.get(Node.BICYCLE) == OneWay.YES) backward.remove(EdgeStore.EdgeFlag.ALLOWS_BIKE);
if (dir.get(Node.FOOT) == OneWay.YES) backward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);

//Forward edge
// you can always forward traverse unless this is a rare reversed one-way street
if (dir.get(Node.CAR) == OneWay.REVERSE) forward.remove(EdgeStore.EdgeFlag.ALLOWS_CAR);
if (dir.get(Node.BICYCLE) == OneWay.REVERSE) forward.remove(EdgeStore.EdgeFlag.ALLOWS_BIKE);
if (dir.get(Node.FOOT) == OneWay.REVERSE) forward.remove(EdgeStore.EdgeFlag.ALLOWS_PEDESTRIAN);

//This needs to be called after permissions were removed in directionalTree
//it is moved from directional tree since we can only remove permissions there
//but they need to be added also for example highway=residential;bicycle=no;oneway=yes;bicycle:left=opposite_lane

//If oneway is reversed (oneway=-1) opposite bicycle permission also need to be since they are opposite rest of traffic
if (dir.get(Node.CAR) == OneWay.REVERSE){
applyOppositeBicyclePermissions(way, forward);
} else {
applyOppositeBicyclePermissions(way, backward);
}


return new RoadPermission(forward, backward);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public RoadPermission getPermissions(Way way) {
* @param tree
* @param way
*/
private void applyWheelchairPermissions(EnumMap<Node, Label> tree, Way way) {
void applyWheelchairPermissions (EnumMap<Node, Label> tree, Way way) {
if (way.hasTag("highway", "steps")) {
applyLabel(Node.WHEELCHAIR, Label.NO, tree);
}
Expand All @@ -167,7 +167,7 @@ private void applyWheelchairPermissions(EnumMap<Node, Label> tree, Way way) {
* @param way
* @param backward
*/
private void applyOppositeBicyclePermissions(Way way, EnumSet<EdgeStore.EdgeFlag> backward) {
void applyOppositeBicyclePermissions (Way way, EnumSet<EdgeStore.EdgeFlag> backward) {
String cyclewayLeftTagValue = way.getTag("cycleway:left");
String cyclewayRightTagValue = way.getTag("cycleway:right");
String cyclewayTagValue = way.getTag("cycleway");
Expand Down Expand Up @@ -197,8 +197,8 @@ private void applyOppositeBicyclePermissions(Way way, EnumSet<EdgeStore.EdgeFlag
* @param forward
* @param backward
*/
private void applyDirectionalPermissions(Way way, EnumSet<EdgeStore.EdgeFlag> forward,
EnumSet<EdgeStore.EdgeFlag> backward) {
void applyDirectionalPermissions (Way way, EnumSet<EdgeStore.EdgeFlag> forward,
EnumSet<EdgeStore.EdgeFlag> backward) {
String cyclewayLeftTagValue = way.getTag("cycleway:left");
String cyclewayRightTagValue = way.getTag("cycleway:right");

Expand Down Expand Up @@ -228,7 +228,7 @@ public EnumSet<EdgeStore.EdgeFlag> getPermissions(Way way, boolean back) {
}

/** returns whether this node is permitted traversal anywhere in the hierarchy */
private Label walk (EnumMap<Node, Label> tree, Node node) {
Label walk (EnumMap<Node, Label> tree, Node node) {
do {
//We need to return first labeled node not first yes node
//Otherwise access=yes bicycle=no returns true for bicycle
Expand All @@ -242,7 +242,7 @@ private Label walk (EnumMap<Node, Label> tree, Node node) {
}

/** apply any specific permissions that may exist */
private void applySpecificPermissions (EnumMap<Node, Label> tree, Way way) {
void applySpecificPermissions (EnumMap<Node, Label> tree, Way way) {
// start from the root of the tree
if (way.hasTag("access")) applyLabel(Node.ACCESS, Label.fromTag(way.getTag("access")), tree);
if (way.hasTag("foot")) applyLabel(Node.FOOT, Label.fromTag(way.getTag("foot")), tree);
Expand Down Expand Up @@ -398,7 +398,7 @@ protected EnumMap<Node, Label> getDefaultTree () {
}

/** Get a directional tree (for use when labeling one-way streets) where every node is labeled bidirectional */
private EnumMap<Node, OneWay> getDirectionalTree (Way way) {
EnumMap<Node, OneWay> getDirectionalTree (Way way) {
EnumMap<Node, OneWay> tree = new EnumMap<>(Node.class);

// label all nodes as unknown
Expand Down

0 comments on commit e272229

Please sign in to comment.