Skip to content

Commit

Permalink
Remove FlagEncoder.getAnnotation (#1811)
Browse files Browse the repository at this point in the history
* initial version of required encoded values

* remove FlagEncoder.getAnnotation and create GetOffBike EncodedValue for replacement

* fix tests

* clean up
  • Loading branch information
karussell committed Dec 4, 2019
1 parent 0a967b3 commit daa5b9c
Show file tree
Hide file tree
Showing 27 changed files with 270 additions and 507 deletions.
4 changes: 2 additions & 2 deletions core/src/main/java/com/graphhopper/reader/ReaderElement.java
Expand Up @@ -136,15 +136,15 @@ public boolean hasTag(String key, String... values) {
/**
* Check that a given tag has one of the specified values.
*/
public final boolean hasTag(String key, Set<String> values) {
public final boolean hasTag(String key, Collection<String> values) {
return values.contains(getTag(key, ""));
}

/**
* Check a number of tags in the given order for the any of the given values. Used to parse
* hierarchical access restrictions
*/
public boolean hasTag(List<String> keyList, Set<String> values) {
public boolean hasTag(List<String> keyList, Collection<String> values) {
for (String key : keyList) {
if (values.contains(getTag(key, "")))
return true;
Expand Down
Expand Up @@ -17,7 +17,7 @@
*/
package com.graphhopper.routing;

import com.graphhopper.routing.profiles.BooleanEncodedValue;
import com.graphhopper.routing.profiles.*;
import com.graphhopper.routing.util.DefaultEdgeFilter;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.weighting.Weighting;
Expand All @@ -27,6 +27,8 @@
import com.graphhopper.util.*;
import com.graphhopper.util.shapes.GHPoint;

import static com.graphhopper.routing.util.EncodingManager.getKey;

/**
* This class calculates instructions from the edges in a Path.
*
Expand All @@ -46,6 +48,11 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
private final EdgeExplorer crossingExplorer;
private final BooleanEncodedValue roundaboutEnc;
private final BooleanEncodedValue accessEnc;
private final BooleanEncodedValue getOffBikeEnc;
private final EnumEncodedValue<RouteNetwork> bikeRouteEnc;
private final EnumEncodedValue<RoadClass> roadClassEnc;
private final EnumEncodedValue<RoadEnvironment> roadEnvEnc;

/*
* We need three points to make directions
*
Expand Down Expand Up @@ -81,33 +88,40 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {

private final int MAX_U_TURN_DISTANCE = 35;

public InstructionsFromEdges(Graph graph, Weighting weighting,
BooleanEncodedValue roundaboutEnc,
public InstructionsFromEdges(Graph graph, Weighting weighting, EncodedValueLookup evLookup,
Translation tr, InstructionList ways) {
this.weighting = weighting;
this.encoder = weighting.getFlagEncoder();
this.accessEnc = this.encoder.getAccessEnc();
this.roundaboutEnc = roundaboutEnc;
this.weighting = weighting;
this.accessEnc = evLookup.getBooleanEncodedValue(getKey(encoder.toString(), "access"));
this.roundaboutEnc = evLookup.getBooleanEncodedValue(Roundabout.KEY);

// both EncodedValues are optional and only used when bike encoders are added
String key = getKey("bike", RouteNetwork.EV_SUFFIX);
this.bikeRouteEnc = evLookup.hasEncodedValue(key) ? evLookup.getEnumEncodedValue(key, RouteNetwork.class) : null;
this.getOffBikeEnc = evLookup.hasEncodedValue(GetOffBike.KEY) ? evLookup.getBooleanEncodedValue(GetOffBike.KEY) : null;

this.roadClassEnc = evLookup.getEnumEncodedValue(RoadClass.KEY, RoadClass.class);
this.roadEnvEnc = evLookup.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
this.nodeAccess = graph.getNodeAccess();
this.tr = tr;
this.ways = ways;
prevNode = -1;
prevInRoundabout = false;
prevName = null;
outEdgeExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.outEdges(this.encoder));
crossingExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.allEdges(this.encoder));
outEdgeExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.outEdges(encoder));
crossingExplorer = graph.createEdgeExplorer(DefaultEdgeFilter.allEdges(encoder));
}

/**
* @return the list of instructions for this path.
*/
public static InstructionList calcInstructions(Path path, Graph graph, Weighting weighting, BooleanEncodedValue roundaboutEnc, final Translation tr) {
public static InstructionList calcInstructions(Path path, Graph graph, Weighting weighting, EncodedValueLookup evLookup, final Translation tr) {
final InstructionList ways = new InstructionList(tr);
if (path.isFound()) {
if (path.getSize() == 0) {
ways.add(new FinishInstruction(graph.getNodeAccess(), path.getEndNode()));
} else {
path.forEveryEdge(new InstructionsFromEdges(graph, weighting, roundaboutEnc, tr, ways));
path.forEveryEdge(new InstructionsFromEdges(graph, weighting, evLookup, tr, ways));
}
}
return ways;
Expand Down Expand Up @@ -143,7 +157,19 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
}

String name = edge.getName();
InstructionAnnotation annotation = encoder.getAnnotation(flags, tr);
InstructionAnnotation annotation = InstructionAnnotation.EMPTY;
if (getOffBikeEnc != null) {
// only for bikes do
if (edge.get(roadClassEnc) == RoadClass.CYCLEWAY
|| bikeRouteEnc != null && edge.get(bikeRouteEnc) != RouteNetwork.OTHER) {
// for backward compatibility
annotation = new InstructionAnnotation(0, tr.tr("cycleway"));
} else if (edge.get(getOffBikeEnc)) {
annotation = new InstructionAnnotation(1, tr.tr("off_bike"));
}
} else if (edge.get(roadEnvEnc) == RoadEnvironment.FORD) {
annotation = new InstructionAnnotation(1, tr.tr("way_contains_ford"));
}

if ((prevName == null) && (!isRoundabout)) // very first instruction (if not in Roundabout)
{
Expand Down
Expand Up @@ -18,8 +18,8 @@
package com.graphhopper.routing;

import com.graphhopper.routing.profiles.BooleanEncodedValue;
import com.graphhopper.routing.profiles.MaxSpeed;
import com.graphhopper.routing.profiles.DecimalEncodedValue;
import com.graphhopper.routing.profiles.MaxSpeed;
import com.graphhopper.routing.util.DataFlagEncoder;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.storage.IntsRef;
Expand Down Expand Up @@ -57,19 +57,14 @@
*/
class InstructionsOutgoingEdges {

final EdgeIteratorState prevEdge;
final EdgeIteratorState currentEdge;

private final EdgeIteratorState prevEdge;
private final EdgeIteratorState currentEdge;
// Outgoing edges that we would be allowed to turn on
final List<EdgeIteratorState> allowedOutgoingEdges;

private final List<EdgeIteratorState> allowedOutgoingEdges;
// All outgoing edges, including oneways in the wrong direction
final List<EdgeIteratorState> allOutgoingEdges;

final FlagEncoder encoder;
final BooleanEncodedValue accessEnc;
final DecimalEncodedValue speedEnc;
final NodeAccess nodeAccess;
private final List<EdgeIteratorState> allOutgoingEdges;
private final DecimalEncodedValue speedEnc;
private final NodeAccess nodeAccess;

public InstructionsOutgoingEdges(EdgeIteratorState prevEdge,
EdgeIteratorState currentEdge,
Expand All @@ -81,8 +76,7 @@ public InstructionsOutgoingEdges(EdgeIteratorState prevEdge,
int adjNode) {
this.prevEdge = prevEdge;
this.currentEdge = currentEdge;
this.encoder = encoder;
this.accessEnc = encoder.getAccessEnc();
BooleanEncodedValue accessEnc = encoder.getAccessEnc();
this.speedEnc = (encoder instanceof DataFlagEncoder) ? encoder.getDecimalEncodedValue(MaxSpeed.KEY) : encoder.getAverageSpeedEnc();
this.nodeAccess = nodeAccess;

Expand Down
Expand Up @@ -34,6 +34,8 @@ public EncodedValue create(String string) {
// creating the Country EV is done while SpatialRuleIndex is created and not here
if (Roundabout.KEY.equals(name)) {
enc = Roundabout.create();
} else if (GetOffBike.KEY.equals(name)) {
enc = GetOffBike.create();
} else if (RoadClass.KEY.equals(name)) {
enc = new EnumEncodedValue<>(RoadClass.KEY, RoadClass.class);
} else if (RoadClassLink.KEY.equals(name)) {
Expand Down
@@ -0,0 +1,9 @@
package com.graphhopper.routing.profiles;

public class GetOffBike {
public static final String KEY = "get_off_bike";

public static BooleanEncodedValue create() {
return new SimpleBooleanEncodedValue(KEY, false);
}
}
Expand Up @@ -228,11 +228,6 @@ public long handleNodeTags(ReaderNode node) {
return 0;
}

@Override
public InstructionAnnotation getAnnotation(IntsRef edgeFlags, Translation tr) {
return InstructionAnnotation.EMPTY;
}

/**
* Sets default flags with specified access.
*/
Expand Down
Expand Up @@ -40,10 +40,7 @@
* @author ratrun
*/
abstract public class BikeCommonFlagEncoder extends AbstractFlagEncoder {
/**
* Reports whether this edge is unpaved.
*/
public static final int K_UNPAVED = 100;

protected static final int PUSHING_SECTION_SPEED = 4;
// Pushing section highways are parts where you need to get off your bike and push it (German: Schiebestrecke)
protected final HashSet<String> pushingSectionsHighways = new HashSet<>();
Expand All @@ -57,8 +54,6 @@ abstract public class BikeCommonFlagEncoder extends AbstractFlagEncoder {
private final Map<String, Integer> highwaySpeeds = new HashMap<>();
protected boolean speedTwoDirections;
DecimalEncodedValue priorityEnc;
private BooleanEncodedValue unpavedEnc;
private IntEncodedValue wayTypeEnc;
// Car speed limit which switches the preference from UNCHANGED to AVOID_IF_POSSIBLE
private int avoidSpeedLimit;
EnumEncodedValue<RouteNetwork> bikeRouteEnc;
Expand Down Expand Up @@ -212,8 +207,6 @@ public void createEncodedValues(List<EncodedValue> registerNewEncodedValue, Stri
// first two bits are reserved for route handling in superclass
super.createEncodedValues(registerNewEncodedValue, prefix, index);
registerNewEncodedValue.add(avgSpeedEnc = new UnsignedDecimalEncodedValue(getKey(prefix, "average_speed"), speedBits, speedFactor, speedTwoDirections));
registerNewEncodedValue.add(unpavedEnc = new SimpleBooleanEncodedValue(getKey(prefix, "paved"), false));
registerNewEncodedValue.add(wayTypeEnc = new UnsignedIntEncodedValue(getKey(prefix, "waytype"), 2, false));
registerNewEncodedValue.add(priorityEnc = new UnsignedDecimalEncodedValue(getKey(prefix, "priority"), 3, PriorityCode.getFactor(1), false));

bikeRouteEnc = getEnumEncodedValue(getKey("bike", EV_SUFFIX), RouteNetwork.class);
Expand Down Expand Up @@ -324,7 +317,6 @@ public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay way, EncodingManager.A
if (!access.isFerry()) {
wayTypeSpeed = applyMaxSpeed(way, wayTypeSpeed);
handleSpeed(edgeFlags, way, wayTypeSpeed);
handleBikeRelated(edgeFlags, way, priorityFromRelation != null && priorityFromRelation > UNCHANGED.getValue());
} else {
double ferrySpeed = getFerrySpeed(way);
handleSpeed(edgeFlags, way, ferrySpeed);
Expand Down Expand Up @@ -398,48 +390,6 @@ int getSpeed(ReaderWay way) {
return speed;
}

@Override
public InstructionAnnotation getAnnotation(IntsRef edgeFlags, Translation tr) {
int paveType = 0; // paved
if (unpavedEnc.getBool(false, edgeFlags))
paveType = 1; // unpaved

int wayType = wayTypeEnc.getInt(false, edgeFlags);
String wayName = getWayName(paveType, wayType, tr);
return new InstructionAnnotation(0, wayName);
}

String getWayName(int pavementType, int wayType, Translation tr) {
String pavementName = "";
if (pavementType == 1)
pavementName = tr.tr("unpaved");

String wayTypeName = "";
switch (wayType) {
case 0:
wayTypeName = "";
break;
case 1:
wayTypeName = tr.tr("off_bike");
break;
case 2:
wayTypeName = tr.tr("cycleway");
break;
case 3:
wayTypeName = tr.tr("small_way");
break;
}

if (pavementName.isEmpty()) {
if (wayType == 0 || wayType == 3)
return "";
return wayTypeName;
} else if (wayTypeName.isEmpty())
return pavementName;
else
return wayTypeName + ", " + pavementName;
}

/**
* In this method we prefer cycleways or roads with designated bike access and avoid big roads
* or roads with trams or pedestrian.
Expand Down Expand Up @@ -562,46 +512,6 @@ void collect(ReaderWay way, double wayTypeSpeed, TreeMap<Double, Integer> weight
}
}

/**
* Handle surface and wayType encoding
*/
void handleBikeRelated(IntsRef edgeFlags, ReaderWay way, boolean partOfCycleRelation) {
String surfaceTag = way.getTag("surface");
String highway = way.getTag("highway");
String trackType = way.getTag("tracktype");

// Populate unpavedBit
if ("track".equals(highway) && !"grade1".equals(trackType)
|| "path".equals(highway) && surfaceTag == null
|| unpavedSurfaceTags.contains(surfaceTag)) {
unpavedEnc.setBool(false, edgeFlags, true);
}

WayType wayType;
if (roadValues.contains(highway))
wayType = WayType.ROAD;
else
wayType = WayType.OTHER_SMALL_WAY;

boolean isPushingSection = isPushingSection(way);
if (isPushingSection && !partOfCycleRelation || "steps".equals(highway))
wayType = WayType.PUSHING_SECTION;

if (way.hasTag("bicycle", intendedValues)) {
if (isPushingSection && !way.hasTag("bicycle", "designated"))
wayType = WayType.OTHER_SMALL_WAY;
else if (wayType == WayType.OTHER_SMALL_WAY || wayType == WayType.PUSHING_SECTION)
wayType = WayType.CYCLEWAY;
} else if ("cycleway".equals(highway))
wayType = WayType.CYCLEWAY;

wayTypeEnc.setInt(false, edgeFlags, wayType.getValue());
}

boolean isPushingSection(ReaderWay way) {
return way.hasTag("highway", pushingSectionsHighways) || way.hasTag("railway", "platform") || way.hasTag("bicycle", "dismount");
}

protected void handleSpeed(IntsRef edgeFlags, ReaderWay way, double speed) {
avgSpeedEnc.setDecimal(false, edgeFlags, speed);

Expand Down Expand Up @@ -633,11 +543,11 @@ protected void handleSpeed(IntsRef edgeFlags, ReaderWay way, double speed) {
}
}

protected void setHighwaySpeed(String highway, int speed) {
void setHighwaySpeed(String highway, int speed) {
highwaySpeeds.put(highway, speed);
}

protected int getHighwaySpeed(String key) {
int getHighwaySpeed(String key) {
return highwaySpeeds.get(key);
}

Expand All @@ -661,28 +571,11 @@ public boolean supports(Class<?> feature) {
return PriorityWeighting.class.isAssignableFrom(feature);
}

public void setAvoidSpeedLimit(int limit) {
void setAvoidSpeedLimit(int limit) {
avoidSpeedLimit = limit;
}

protected void setSpecificClassBicycle(String subkey) {
void setSpecificClassBicycle(String subkey) {
classBicycleKey = "class:bicycle:" + subkey;
}

private enum WayType {
ROAD(0),
PUSHING_SECTION(1),
CYCLEWAY(2),
OTHER_SMALL_WAY(3);

private final int value;

private WayType(int value) {
this.value = value;
}

public int getValue() {
return value;
}
}
}
Expand Up @@ -75,13 +75,6 @@ public int getVersion() {
return 2;
}

@Override
boolean isPushingSection(ReaderWay way) {
String highway = way.getTag("highway");
String trackType = way.getTag("tracktype");
return super.isPushingSection(way) || "track".equals(highway) && trackType != null && !"grade1".equals(trackType);
}

@Override
public String toString() {
return "bike";
Expand Down

0 comments on commit daa5b9c

Please sign in to comment.