Skip to content

Commit 2445e81

Browse files
authored
Improve ferry instructions (graphhopper#3179)
* announce ferry in instructions * extra instruction sign needed * Update maps to 34acd30e * fix * ensure never NPE * use mode==ferry for mapbox response
1 parent 9b2c2c9 commit 2445e81

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+214
-26
lines changed

core/src/main/java/com/graphhopper/GraphHopper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -866,10 +866,10 @@ protected void prepareImport() {
866866
"graph.encoded_values: " + encodedValuesString);
867867
}
868868

869-
// these are used in the snap prevention filter (avoid motorway, tunnel, etc.) so they have to be there
869+
// following encoded values are used by instructions and in the snap prevention filter (avoid motorway, tunnel, etc.)
870870
encodedValuesWithProps.putIfAbsent(RoadClass.KEY, new PMap());
871871
encodedValuesWithProps.putIfAbsent(RoadEnvironment.KEY, new PMap());
872-
// used by instructions...
872+
// now only used by instructions:
873873
encodedValuesWithProps.putIfAbsent(Roundabout.KEY, new PMap());
874874
encodedValuesWithProps.putIfAbsent(VehicleAccess.key("car"), new PMap());
875875
encodedValuesWithProps.putIfAbsent(RoadClassLink.KEY, new PMap());

core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
4444
private final BooleanEncodedValue roundaboutEnc;
4545
private final BooleanEncodedValue roadClassLinkEnc;
4646
private final EnumEncodedValue<RoadClass> roadClassEnc;
47+
private final EnumEncodedValue<RoadEnvironment> roadEnvEnc;
4748
private final IntEncodedValue lanesEnc;
4849
private final DecimalEncodedValue maxSpeedEnc;
4950

@@ -78,6 +79,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
7879
private boolean prevInRoundabout;
7980
private String prevDestinationAndRef;
8081
private String prevName;
82+
private RoadEnvironment prevRoadEnv;
8183
private String prevInstructionName;
8284

8385
private static final int MAX_U_TURN_DISTANCE = 35;
@@ -86,6 +88,7 @@ public InstructionsFromEdges(Graph graph, Weighting weighting, EncodedValueLooku
8688
InstructionList ways) {
8789
this.weighting = weighting;
8890
this.roundaboutEnc = evLookup.getBooleanEncodedValue(Roundabout.KEY);
91+
this.roadEnvEnc = evLookup.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
8992
this.roadClassEnc = evLookup.getEnumEncodedValue(RoadClass.KEY, RoadClass.class);
9093
this.roadClassLinkEnc = evLookup.getBooleanEncodedValue(RoadClassLink.KEY);
9194
this.maxSpeedEnc = evLookup.getDecimalEncodedValue(MaxSpeed.KEY);
@@ -95,6 +98,7 @@ public InstructionsFromEdges(Graph graph, Weighting weighting, EncodedValueLooku
9598
prevNode = -1;
9699
prevInRoundabout = false;
97100
prevName = null;
101+
prevRoadEnv = null;
98102

99103
BooleanEncodedValue carAccessEnc = evLookup.getBooleanEncodedValue(VehicleAccess.key("car"));
100104
outEdgeExplorer = graph.createEdgeExplorer(edge -> edge.get(carAccessEnc));
@@ -149,6 +153,8 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
149153
final String destination = (String) edge.getValue(STREET_DESTINATION); // getValue is fast if it does not exist in edge
150154
final String destinationRef = (String) edge.getValue(STREET_DESTINATION_REF);
151155
final String motorwayJunction = (String) edge.getValue(MOTORWAY_JUNCTION);
156+
final RoadEnvironment roadEnv = edge.get(roadEnvEnc);
157+
152158
if ((prevInstruction == null) && (!isRoundabout)) // very first instruction (if not in Roundabout)
153159
{
154160
int sign = Instruction.CONTINUE_ON_STREET;
@@ -157,12 +163,15 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
157163
prevInstruction.setExtraInfo(STREET_DESTINATION, destination);
158164
prevInstruction.setExtraInfo(STREET_DESTINATION_REF, destinationRef);
159165
prevInstruction.setExtraInfo(MOTORWAY_JUNCTION, motorwayJunction);
166+
prevInstruction.setExtraInfo("ferry", InstructionsHelper.createFerryInfo(roadEnv, prevRoadEnv));
167+
160168
double startLat = nodeAccess.getLat(baseNode);
161169
double startLon = nodeAccess.getLon(baseNode);
162170
double heading = AngleCalc.ANGLE_CALC.calcAzimuth(startLat, startLon, latitude, longitude);
163171
prevInstruction.setExtraInfo("heading", Helper.round(heading, 2));
164172
ways.add(prevInstruction);
165173
prevName = name;
174+
prevRoadEnv = roadEnv;
166175
prevDestinationAndRef = destination + destinationRef;
167176

168177
} else if (isRoundabout) {
@@ -197,6 +206,7 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
197206
{
198207
prevOrientation = AngleCalc.ANGLE_CALC.calcOrientation(prevLat, prevLon, latitude, longitude);
199208
prevName = name;
209+
prevRoadEnv = roadEnv;
200210
prevDestinationAndRef = destination + destinationRef;
201211
}
202212
prevInstruction = roundaboutInstruction;
@@ -220,6 +230,7 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
220230
prevInstruction.setExtraInfo(STREET_DESTINATION, destination);
221231
prevInstruction.setExtraInfo(STREET_DESTINATION_REF, destinationRef);
222232
prevInstruction.setExtraInfo(MOTORWAY_JUNCTION, motorwayJunction);
233+
prevInstruction.setExtraInfo("ferry", InstructionsHelper.createFerryInfo(roadEnv, prevRoadEnv));
223234

224235
// calc angle between roundabout entrance and exit
225236
double orientation = AngleCalc.ANGLE_CALC.calcOrientation(prevLat, prevLon, latitude, longitude);
@@ -239,6 +250,7 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
239250

240251
prevInstructionName = prevName;
241252
prevName = name;
253+
prevRoadEnv = roadEnv;
242254
prevDestinationAndRef = destination + destinationRef;
243255

244256
} else {
@@ -296,10 +308,12 @@ public void next(EdgeIteratorState edge, int index, int prevEdgeId) {
296308
prevInstruction.setExtraInfo(STREET_DESTINATION, destination);
297309
prevInstruction.setExtraInfo(STREET_DESTINATION_REF, destinationRef);
298310
prevInstruction.setExtraInfo(MOTORWAY_JUNCTION, motorwayJunction);
311+
prevInstruction.setExtraInfo("ferry", InstructionsHelper.createFerryInfo(roadEnv, prevRoadEnv));
299312
}
300313
// Update the prevName, since we don't always create an instruction on name changes the previous
301314
// name can be an old name. This leads to incorrect turn instructions due to name changes
302315
prevName = name;
316+
prevRoadEnv = roadEnv;
303317
prevDestinationAndRef = destination + destinationRef;
304318
}
305319

@@ -351,10 +365,13 @@ private int getTurn(EdgeIteratorState edge, int baseNode, int prevNode, int adjN
351365
InstructionsOutgoingEdges outgoingEdges = new InstructionsOutgoingEdges(prevEdge, edge, weighting, maxSpeedEnc,
352366
roadClassEnc, roadClassLinkEnc, lanesEnc, allExplorer, nodeAccess, prevNode, baseNode, adjNode);
353367
int nrOfPossibleTurns = outgoingEdges.getAllowedTurns();
368+
RoadEnvironment roadEnv = edge.get(roadEnvEnc);
354369

355370
// there is no other turn possible
356371
if (nrOfPossibleTurns <= 1) {
357-
if (Math.abs(sign) > 1 && outgoingEdges.getVisibleTurns() > 1 && !outgoingEdges.mergedOrSplitWay()) {
372+
if (InstructionsHelper.isToFerry(roadEnv, prevRoadEnv)) return Instruction.FERRY;
373+
if (Math.abs(sign) > 1 && outgoingEdges.getVisibleTurns() > 1 && !outgoingEdges.mergedOrSplitWay()
374+
|| InstructionsHelper.isFromFerry(roadEnv, prevRoadEnv)) {
358375
// This is an actual turn because |sign| > 1
359376
// There could be some confusion, if we would not create a turn instruction, even though it is the only
360377
// possible turn, also see #1048
@@ -366,9 +383,11 @@ private int getTurn(EdgeIteratorState edge, int baseNode, int prevNode, int adjN
366383

367384
// Very certain, this is a turn
368385
if (Math.abs(sign) > 1) {
386+
if (InstructionsHelper.isToFerry(roadEnv, prevRoadEnv)) return Instruction.FERRY;
369387
// Don't show an instruction if the user is following a street, even though the street is
370388
// bending. We should only do this, if following the street is the obvious choice.
371389
if (InstructionsHelper.isSameName(name, prevName) && outgoingEdges.outgoingEdgesAreSlowerByFactor(2)
390+
|| InstructionsHelper.isFromFerry(roadEnv, prevRoadEnv)
372391
|| outgoingEdges.mergedOrSplitWay()) {
373392
return Instruction.IGNORE;
374393
}
@@ -397,6 +416,11 @@ private int getTurn(EdgeIteratorState edge, int baseNode, int prevNode, int adjN
397416
// Signs provide too less detail, so we use the delta for a precise comparison
398417
double delta = InstructionsHelper.calculateOrientationDelta(prevLat, prevLon, lat, lon, prevOrientation);
399418

419+
if (InstructionsHelper.isToFerry(roadEnv, prevRoadEnv))
420+
return Instruction.FERRY;
421+
else if (InstructionsHelper.isFromFerry(roadEnv, prevRoadEnv))
422+
return Instruction.CONTINUE_ON_STREET;
423+
400424
// This state is bad! Two streets are going more or less straight
401425
// Happens a lot for trunk_links
402426
// For _links, comparing flags works quite good, as links usually have different speeds => different flags

core/src/main/java/com/graphhopper/routing/InstructionsHelper.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package com.graphhopper.routing;
1919

20+
import com.graphhopper.routing.ev.RoadEnvironment;
2021
import com.graphhopper.storage.NodeAccess;
2122
import com.graphhopper.util.*;
2223
import com.graphhopper.util.shapes.GHPoint;
@@ -80,4 +81,19 @@ static GHPoint getPointForOrientationCalculation(EdgeIteratorState edgeIteratorS
8081
}
8182
return new GHPoint(tmpLat, tmpLon);
8283
}
84+
85+
static boolean isToFerry(RoadEnvironment re, RoadEnvironment prev) {
86+
return (re == RoadEnvironment.FERRY) && re != prev;
87+
}
88+
89+
static boolean isFromFerry(RoadEnvironment re, RoadEnvironment prev) {
90+
return (prev == RoadEnvironment.FERRY) && re != prev;
91+
}
92+
93+
static String createFerryInfo(RoadEnvironment re, RoadEnvironment prev) {
94+
if (re == prev) return null;
95+
if (re == RoadEnvironment.FERRY) return "board_ferry";
96+
if (prev == RoadEnvironment.FERRY) return "leave_ferry";
97+
return null;
98+
}
8399
}

core/src/main/resources/com/graphhopper/util/ar.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=توقف %1$s
3636
roundabout_enter=أدخل الدوران
3737
roundabout_exit=في الدوران ، أتخذ مخرج %1$s
3838
roundabout_exit_onto=في الدوران ، أتخذ مخرج %1$s من خلال %2$s
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=%1$s اجمالى صعود
4042
web.total_descend=%1$s اجمالى نزول
4143
web.way_contains_ford=انتبه ، هناك مخاضة على الطريق

core/src/main/resources/com/graphhopper/util/ast.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=pasando per %1$s
3636
roundabout_enter=Entra na rotonda
3737
roundabout_exit=Na rotonda, toma la salida %1$s
3838
roundabout_exit_onto=Na rotonda, toma la salida %1$s haza %2$s
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=%1$s d'ascensu total
4042
web.total_descend=%1$s de descensu total
4143
web.way_contains_ford=hai un vau nel camín

core/src/main/resources/com/graphhopper/util/az.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=dayanacaq %1$s
3636
roundabout_enter=dairəvi yola dönün
3737
roundabout_exit=%1$s çıxışdan çıxın
3838
roundabout_exit_onto=%1$s çıxışdan %2$s çıxın
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=%1$s yüksəliş
4042
web.total_descend=%1$s eniş
4143
web.way_contains_ford=Yolda keçid var

core/src/main/resources/com/graphhopper/util/bg.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=отправна точка %1$s
3636
roundabout_enter=Влезте в кръговото кръстовище
3737
roundabout_exit=На кръговото кръстовище вземете изход %1$s
3838
roundabout_exit_onto=На кръговото кръстовище вземете изход %1$s по %2$s
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=%1$s общо изкачване
4042
web.total_descend=%1$s общо слизане
4143
web.way_contains_ford=Внимание, на пътя има брод

core/src/main/resources/com/graphhopper/util/bn_BN.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=
3636
roundabout_enter=গোলচক্কর
3737
roundabout_exit=গোলচক্কর হতে %1$s এর দিকে যান
3838
roundabout_exit_onto=গোলচক্কর হতে %2$s এ যেতে %1$s এর দিকে যান
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=
4042
web.total_descend=
4143
web.way_contains_ford=

core/src/main/resources/com/graphhopper/util/ca.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=passant per %1$s
3636
roundabout_enter=Entra a la rotonda
3737
roundabout_exit=A la rotonda, agafa la %1$sa sortida
3838
roundabout_exit_onto=A la rotonda, agafa la %1$sa sortida cap a %2$s
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=%1$s de pujada total
4042
web.total_descend=%1$s de baixada total
4143
web.way_contains_ford=hi ha un gual en el camí
@@ -100,7 +102,7 @@ web.via_hint=Passant per
100102
web.from_hint=Des de
101103
web.gpx_export_button=Exporta a GPX
102104
web.gpx_button=GPX
103-
web.settings_gpx_export=Exportació GPX
105+
web.settings_gpx_export=Exportació GPX
104106
web.settings_gpx_export_trk=Amb pista
105107
web.settings_gpx_export_rte=Amb ruta
106108
web.settings_gpx_export_wpt=Amb waypoints

core/src/main/resources/com/graphhopper/util/cs_CZ.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ stopover=průjezdní bod %1$s
3636
roundabout_enter=Vjeďte na kruhový objezd
3737
roundabout_exit=Na kruhovém objezdu použijte %1$s. výjezd
3838
roundabout_exit_onto=Na kruhovém objezdu použijte %1$s. výjezd, směrem na %2$s
39+
leave_ferry=
40+
board_ferry=
3941
web.total_ascend=celkové stoupání %1$s
4042
web.total_descend=celkové klesání %1$s
4143
web.way_contains_ford=Trasa obsahuje brody

0 commit comments

Comments
 (0)