Repository: graphhopper/graphhopper
Pull request #2167 (2020-10-27 10:52:20)

Remove InstructionAnnotation
HGV toll is the default for motorways and trunks in a lot of countries. Displaying a toll warning for `Toll.HGV` isn't that helpful for truck drivers and will confuse owners of non-HGV vehicles.

boldtrn: Have a look at https://discuss.graphhopper.com/t/using-instruction-annotations/6005

I think we should get rid of annotations in general :).
otbutz: Agreed but that would require changes on the client side if i'm not mistaken?
boldtrn: If you want to show the same information on the client as it was before, yes. But I think for the change on the GraphHopper side it should be enough to just remove the annotation handling in the Instruction generation.
otbutz: @boldtrn i've completely removed the InstructionAnnotation
karussell: Thanks, good idea to remove that (have changed the title of this issue accordingly). Can you also have a look into the gh maps JS code? (we can later add support for toll, ferry, ... via path details)
otbutz: @karussell i've removed the annotation handling from instructions.js and updated the API documentation
boldtrn: Since this is a breaking change, should we mention it in the changelog?

Patch:
diff --git a/api/src/main/java/com/graphhopper/util/FinishInstruction.java b/api/src/main/java/com/graphhopper/util/FinishInstruction.java
index fde1825b1..3d0781029 100644
--- a/api/src/main/java/com/graphhopper/util/FinishInstruction.java
+++ b/api/src/main/java/com/graphhopper/util/FinishInstruction.java
@@ -22,7 +22,7 @@ package com.graphhopper.util;
  */
 public class FinishInstruction extends Instruction {
     public FinishInstruction(String name, final double lat, final double lon, final double ele) {
-        super(FINISH, name, InstructionAnnotation.EMPTY, new PointList(2, !Double.isNaN(ele)) {
+        super(FINISH, name, new PointList(2, !Double.isNaN(ele)) {
             {
                 add(lat, lon, ele);
             }
@@ -30,7 +30,7 @@ public class FinishInstruction extends Instruction {
     }
 
     public FinishInstruction(final double lat, final double lon, final double ele) {
-        super(FINISH, "", InstructionAnnotation.EMPTY, new PointList(2, !Double.isNaN(ele)) {
+        super(FINISH, "", new PointList(2, !Double.isNaN(ele)) {
             {
                 add(lat, lon, ele);
             }
diff --git a/api/src/main/java/com/graphhopper/util/Instruction.java b/api/src/main/java/com/graphhopper/util/Instruction.java
index 0119c993b..0cfe4c9f3 100644
--- a/api/src/main/java/com/graphhopper/util/Instruction.java
+++ b/api/src/main/java/com/graphhopper/util/Instruction.java
@@ -43,7 +43,6 @@ public class Instruction {
     public static final int PT_TRANSFER = 102;
     public static final int PT_END_TRIP = 103;
     protected PointList points;
-    protected final InstructionAnnotation annotation;
     protected boolean rawName;
     protected int sign;
     protected String name;
@@ -55,11 +54,10 @@ public class Instruction {
      * The points, distances and times have exactly the same count. The last point of this
      * instruction is not duplicated here and should be in the next one.
      */
-    public Instruction(int sign, String name, InstructionAnnotation ia, PointList pl) {
+    public Instruction(int sign, String name, PointList pl) {
         this.sign = sign;
         this.name = name;
         this.points = pl;
-        this.annotation = ia;
     }
 
     /**
@@ -70,10 +68,6 @@ public class Instruction {
         rawName = true;
     }
 
-    public InstructionAnnotation getAnnotation() {
-        return annotation;
-    }
-
     /**
      * The instruction for the person/driver to execute.
      */
diff --git a/api/src/main/java/com/graphhopper/util/InstructionAnnotation.java b/api/src/main/java/com/graphhopper/util/InstructionAnnotation.java
deleted file mode 100644
index 606976c0d..000000000
--- a/api/src/main/java/com/graphhopper/util/InstructionAnnotation.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *  Licensed to GraphHopper GmbH under one or more contributor
- *  license agreements. See the NOTICE file distributed with this work for
- *  additional information regarding copyright ownership.
- *
- *  GraphHopper GmbH licenses this file to you under the Apache License,
- *  Version 2.0 (the "License"); you may not use this file except in
- *  compliance with the License. You may obtain a copy of the License at
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package com.graphhopper.util;
-
-/**
- * @author Peter Karich
- */
-public class InstructionAnnotation {
-    public final static InstructionAnnotation EMPTY = new InstructionAnnotation();
-    private boolean empty;
-    private int importance;
-    private String message;
-
-    private InstructionAnnotation() {
-        setEmpty();
-    }
-
-    public InstructionAnnotation(int importance, String message) {
-        if (message.isEmpty() && importance == 0) {
-            setEmpty();
-        } else {
-            this.empty = false;
-            this.importance = importance;
-            this.message = message;
-        }
-    }
-
-    private void setEmpty() {
-        this.empty = true;
-        this.importance = 0;
-        this.message = "";
-    }
-
-    public boolean isEmpty() {
-        return empty;
-    }
-
-    public int getImportance() {
-        return importance;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    @Override
-    public String toString() {
-        return importance + ": " + getMessage();
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 3;
-        hash = 83 * hash + this.importance;
-        hash = 83 * hash + (this.message != null ? this.message.hashCode() : 0);
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        final InstructionAnnotation other = (InstructionAnnotation) obj;
-        if (this.importance != other.importance)
-            return false;
-        if ((this.message == null) ? (other.message != null) : !this.message.equals(other.message))
-            return false;
-        return true;
-    }
-}
diff --git a/api/src/main/java/com/graphhopper/util/RoundaboutInstruction.java b/api/src/main/java/com/graphhopper/util/RoundaboutInstruction.java
index fb8326bab..493836d7b 100644
--- a/api/src/main/java/com/graphhopper/util/RoundaboutInstruction.java
+++ b/api/src/main/java/com/graphhopper/util/RoundaboutInstruction.java
@@ -30,8 +30,8 @@ public class RoundaboutInstruction extends Instruction {
     private boolean exited = false;
     private double radian = Double.NaN;
 
-    public RoundaboutInstruction(int sign, String name, InstructionAnnotation ia, PointList pl) {
-        super(sign, name, ia, pl);
+    public RoundaboutInstruction(int sign, String name, PointList pl) {
+        super(sign, name, pl);
     }
 
     public RoundaboutInstruction increaseExitNumber() {
diff --git a/api/src/main/java/com/graphhopper/util/ViaInstruction.java b/api/src/main/java/com/graphhopper/util/ViaInstruction.java
index e496b9f09..d52187670 100644
--- a/api/src/main/java/com/graphhopper/util/ViaInstruction.java
+++ b/api/src/main/java/com/graphhopper/util/ViaInstruction.java
@@ -23,12 +23,12 @@ package com.graphhopper.util;
 public class ViaInstruction extends Instruction {
     private int viaPosition = -1;
 
-    public ViaInstruction(String name, InstructionAnnotation ia, PointList pl) {
-        super(REACHED_VIA, name, ia, pl);
+    public ViaInstruction(String name, PointList pl) {
+        super(REACHED_VIA, name, pl);
     }
 
     public ViaInstruction(Instruction instr) {
-        this(instr.getName(), instr.getAnnotation(), instr.getPoints());
+        this(instr.getName(), instr.getPoints());
         setDistance(instr.getDistance());
         setTime(instr.getTime());
         this.extraInfo = instr.extraInfo;
diff --git a/config-example.yml b/config-example.yml
index 22663b6eb..d400bfd6d 100644
--- a/config-example.yml
+++ b/config-example.yml
@@ -17,7 +17,8 @@ graphhopper:
 
   # Add additional information to every edge. Used for path details (#1548), better instructions (#1844) and tunnel/bridge interpolation (#798).
   # Default values are: road_class,road_class_link,road_environment,max_speed,road_access (since #1805)
-  # More are: surface,max_width,max_height,max_weight,max_axle_load,max_length,hazmat,hazmat_tunnel,hazmat_water,toll,track_type
+  # More are: surface,max_width,max_height,max_weight,max_axle_load,max_length,hazmat,hazmat_tunnel,hazmat_water,toll,track_type,
+  #           mtb_rating, hiking_rating, horse_rating
   # graph.encoded_values: surface,toll,track_type
 
   ##### Routing Profiles ####
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index eb692e84f..495a49547 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -3,6 +3,7 @@
     CustomWeighting requires LinkedHashMap throw exception if this is not provided
     removed Dockerfile
     the second argument of the VirtualEdgeIteratorState constructor is now an edge key (was an edge id before)
+    removed instruction annotations(cycleway, off_bike, ford, ferry, private, toll)
 
 2.0
     AbstractFlagEncoder#getMaxSpeed returns now Double#NaN instead of -1 if no maxspeed was found
diff --git a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
index c466b07f1..fa507ed12 100644
--- a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
+++ b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
@@ -20,7 +20,6 @@ package com.graphhopper.routing;
 import com.graphhopper.routing.ev.*;
 import com.graphhopper.routing.util.DefaultEdgeFilter;
 import com.graphhopper.routing.util.FlagEncoder;
-import com.graphhopper.routing.util.TransportationMode;
 import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.NodeAccess;
@@ -42,19 +41,13 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
     private final FlagEncoder encoder;
     private final NodeAccess nodeAccess;
 
-    private final Translation tr;
     private final InstructionList ways;
     private final EdgeExplorer outEdgeExplorer;
     private final EdgeExplorer crossingExplorer;
     private final BooleanEncodedValue roundaboutEnc;
     private final BooleanEncodedValue accessEnc;
-    private final BooleanEncodedValue getOffBikeEnc;
     private final BooleanEncodedValue roadClassLinkEnc;
-    private final EnumEncodedValue<RouteNetwork> bikeRouteEnc;
     private final EnumEncodedValue<RoadClass> roadClassEnc;
-    private final EnumEncodedValue<RoadEnvironment> roadEnvEnc;
-    private final EnumEncodedValue<RoadAccess> roadAccessEnc;
-    private final EnumEncodedValue<Toll> tollEnc;
     private final DecimalEncodedValue maxSpeedEnc;
 
     /*
@@ -88,31 +81,19 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
     private boolean prevInRoundabout;
     private String prevName;
     private String prevInstructionName;
-    private InstructionAnnotation prevAnnotation;
 
-    private final int MAX_U_TURN_DISTANCE = 35;
+    private static final int MAX_U_TURN_DISTANCE = 35;
 
     public InstructionsFromEdges(Graph graph, Weighting weighting, EncodedValueLookup evLookup,
-                                 Translation tr, InstructionList ways) {
+                                 InstructionList ways) {
         this.encoder = weighting.getFlagEncoder();
         this.weighting = weighting;
         this.accessEnc = evLookup.getBooleanEncodedValue(getKey(encoder.toString(), "access"));
         this.roundaboutEnc = evLookup.getBooleanEncodedValue(Roundabout.KEY);
-
-        // both EncodedValues are optional; And return annotation only when instructions for bike encoder is requested
-        String key = RouteNetwork.key("bike");
-        this.bikeRouteEnc = evLookup.hasEncodedValue(key) ? evLookup.getEnumEncodedValue(key, RouteNetwork.class) : null;
-        this.getOffBikeEnc = encoder.getTransportationMode() == TransportationMode.BIKE && evLookup.hasEncodedValue(GetOffBike.KEY)
-                ? evLookup.getBooleanEncodedValue(GetOffBike.KEY) : null;
-        this.tollEnc = evLookup.hasEncodedValue(Toll.KEY) ? evLookup.getEnumEncodedValue(Toll.KEY, Toll.class) : null;
-
         this.roadClassEnc = evLookup.getEnumEncodedValue(RoadClass.KEY, RoadClass.class);
         this.roadClassLinkEnc = evLookup.getBooleanEncodedValue(RoadClassLink.KEY);
         this.maxSpeedEnc = evLookup.getDecimalEncodedValue(MaxSpeed.KEY);
-        this.roadEnvEnc = evLookup.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
-        this.roadAccessEnc = evLookup.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
         this.nodeAccess = graph.getNodeAccess();
-        this.tr = tr;
         this.ways = ways;
         prevNode = -1;
         prevInRoundabout = false;
@@ -130,7 +111,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
             if (path.getEdgeCount() == 0) {
                 ways.add(new FinishInstruction(graph.getNodeAccess(), path.getEndNode()));
             } else {
-                path.forEveryEdge(new InstructionsFromEdges(graph, weighting, evLookup, tr, ways));
+                path.forEveryEdge(new InstructionsFromEdges(graph, weighting, evLookup, ways));
             }
         }
         return ways;
@@ -165,50 +146,17 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         }
 
         String name = edge.getName();
-        String info = "";
-        int importance = 1;
-        if (getOffBikeEnc != null) {
-            if (edge.get(roadClassEnc) == RoadClass.CYCLEWAY
-                    || bikeRouteEnc != null && edge.get(bikeRouteEnc) != RouteNetwork.MISSING) {
-                // for backward compatibility
-                importance = 0;
-                info = tr.tr("cycleway");
-            } else if (edge.get(getOffBikeEnc)) {
-                info = tr.tr("off_bike");
-            }
-        }
-
-        RoadEnvironment re = edge.get(roadEnvEnc);
-        if (re == RoadEnvironment.FORD) {
-            importance = 2; // could be dangerous
-            info = tr.tr("way_contains_ford");
-        } else if (re == RoadEnvironment.FERRY) {
-            info = tr.tr("way_contains_ferry");
-        }
-
-        // if private access is allowed we need a warning
-        RoadAccess ra = edge.get(roadAccessEnc);
-        if (ra == RoadAccess.PRIVATE)
-            info = info.isEmpty() ? tr.tr("way_contains_private") : info + ", " + tr.tr("way_contains_private");
-
-        if (tollEnc != null && edge.get(tollEnc) != Toll.NO)
-            info = info.isEmpty() ? tr.tr("way_contains_toll") : info + ", " + tr.tr("way_contains_toll");
-
-        InstructionAnnotation annotation = info.isEmpty()
-                ? InstructionAnnotation.EMPTY
-                : new InstructionAnnotation(importance, info);
 
         if ((prevName == null) && (!isRoundabout)) // very first instruction (if not in Roundabout)
         {
             int sign = Instruction.CONTINUE_ON_STREET;
-            prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
+            prevInstruction = new Instruction(sign, name, new PointList(10, nodeAccess.is3D()));
             double startLat = nodeAccess.getLat(baseNode);
             double startLon = nodeAccess.getLon(baseNode);
             double heading = AngleCalc.ANGLE_CALC.calcAzimuth(startLat, startLon, latitude, longitude);
             prevInstruction.setExtraInfo("heading", Helper.round(heading, 2));
             ways.add(prevInstruction);
             prevName = name;
-            prevAnnotation = annotation;
 
         } else if (isRoundabout) {
             // remark: names and annotations within roundabout are ignored
@@ -216,7 +164,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
             {
                 int sign = Instruction.USE_ROUNDABOUT;
                 RoundaboutInstruction roundaboutInstruction = new RoundaboutInstruction(sign, name,
-                        annotation, new PointList(10, nodeAccess.is3D()));
+                        new PointList(10, nodeAccess.is3D()));
                 prevInstructionPrevOrientation = prevOrientation;
                 if (prevName != null) {
                     // check if there is an exit at the same node the roundabout was entered
@@ -242,7 +190,6 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
                 {
                     prevOrientation = AngleCalc.ANGLE_CALC.calcOrientation(prevLat, prevLon, latitude, longitude);
                     prevName = name;
-                    prevAnnotation = annotation;
                 }
                 prevInstruction = roundaboutInstruction;
                 ways.add(prevInstruction);
@@ -281,10 +228,9 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
 
             prevInstructionName = prevName;
             prevName = name;
-            prevAnnotation = annotation;
 
         } else {
-            int sign = getTurn(edge, baseNode, prevNode, adjNode, annotation, name);
+            int sign = getTurn(edge, baseNode, prevNode, adjNode, name);
 
             if (sign != Instruction.IGNORE) {
                 /*
@@ -330,12 +276,11 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
                     prevInstruction.setSign(uTurnType);
                     prevInstruction.setName(name);
                 } else {
-                    prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
+                    prevInstruction = new Instruction(sign, name, new PointList(10, nodeAccess.is3D()));
                     // Remember the Orientation and name of the road, before doing this maneuver
                     prevInstructionPrevOrientation = prevOrientation;
                     prevInstructionName = prevName;
                     ways.add(prevInstruction);
-                    prevAnnotation = annotation;
                 }
             }
             // Update the prevName, since we don't always create an instruction on name changes the previous
@@ -378,19 +323,13 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         ways.add(finishInstruction);
     }
 
-    private int getTurn(EdgeIteratorState edge, int baseNode, int prevNode, int adjNode, InstructionAnnotation annotation, String name) {
+    private int getTurn(EdgeIteratorState edge, int baseNode, int prevNode, int adjNode, String name) {
         GHPoint point = InstructionsHelper.getPointForOrientationCalculation(edge, nodeAccess);
         double lat = point.getLat();
         double lon = point.getLon();
         prevOrientation = AngleCalc.ANGLE_CALC.calcOrientation(doublePrevLat, doublePrevLon, prevLat, prevLon);
         int sign = InstructionsHelper.calculateSign(prevLat, prevLon, lat, lon, prevOrientation);
 
-        boolean forceInstruction = false;
-
-        if (!annotation.equals(prevAnnotation) && !annotation.isEmpty()) {
-            forceInstruction = true;
-        }
-
         InstructionsOutgoingEdges outgoingEdges = new InstructionsOutgoingEdges(prevEdge, edge, encoder, maxSpeedEnc, roadClassEnc, roadClassLinkEnc, crossingExplorer, nodeAccess, prevNode, baseNode, adjNode);
         int nrOfPossibleTurns = outgoingEdges.getAllowedTurns();
 
@@ -403,7 +342,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
                 // TODO if we see issue with this approach we could consider checking if the edge is a oneway
                 return sign;
             }
-            return returnForcedInstructionOrIgnore(forceInstruction, sign);
+            return Instruction.IGNORE;
         }
 
         // Very certain, this is a turn
@@ -413,7 +352,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
              * bending. We should only do this, if following the street is the obvious choice.
              */
             if (InstructionsHelper.isNameSimilar(name, prevName) && outgoingEdges.outgoingEdgesAreSlowerByFactor(2)) {
-                return returnForcedInstructionOrIgnore(forceInstruction, sign);
+                return Instruction.IGNORE;
             }
 
             return sign;
@@ -459,7 +398,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
                 // this approach only works for major roads, for minor roads it can be hard to differentiate easily in real life
                 if (roadClass == RoadClass.MOTORWAY || roadClass == RoadClass.TRUNK || roadClass == RoadClass.PRIMARY || roadClass == RoadClass.SECONDARY || roadClass == RoadClass.TERTIARY) {
                     if ((roadClass == prevRoadClass && link == prevLink) && (otherRoadClass != prevRoadClass || otherLink != prevLink)) {
-                        return returnForcedInstructionOrIgnore(forceInstruction, sign);
+                        return Instruction.IGNORE;
                     }
                 }
 
@@ -491,12 +430,6 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
             }
         }
 
-        return returnForcedInstructionOrIgnore(forceInstruction, sign);
-    }
-
-    private int returnForcedInstructionOrIgnore(boolean forceInstruction, int sign) {
-        if (forceInstruction)
-            return sign;
         return Instruction.IGNORE;
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/ev/HikeRating.java b/core/src/main/java/com/graphhopper/routing/ev/HikeRating.java
new file mode 100644
index 000000000..b8348ede2
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/ev/HikeRating.java
@@ -0,0 +1,9 @@
+package com.graphhopper.routing.ev;
+
+public class HikeRating {
+    public static final String KEY = "hike_rating";
+
+    public static IntEncodedValue create() {
+        return new UnsignedIntEncodedValue(KEY, 3, false);
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/ev/HorseRating.java b/core/src/main/java/com/graphhopper/routing/ev/HorseRating.java
new file mode 100644
index 000000000..5fcbed99f
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/ev/HorseRating.java
@@ -0,0 +1,9 @@
+package com.graphhopper.routing.ev;
+
+public class HorseRating {
+    public static final String KEY = "horse_rating";
+
+    public static IntEncodedValue create() {
+        return new UnsignedIntEncodedValue(KEY, 3, false);
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/ev/MtbRating.java b/core/src/main/java/com/graphhopper/routing/ev/MtbRating.java
new file mode 100644
index 000000000..71d98b53f
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/ev/MtbRating.java
@@ -0,0 +1,9 @@
+package com.graphhopper.routing.ev;
+
+public class MtbRating {
+    public static final String KEY = "mtb_rating";
+
+    public static IntEncodedValue create() {
+        return new UnsignedIntEncodedValue(KEY, 3, false);
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
index c32f8dffb..1980def84 100644
--- a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
@@ -75,6 +75,7 @@ public class CarFlagEncoder extends AbstractFlagEncoder {
         setSpeedTwoDirections(properties.getBool("speed_two_directions", false));
 
         intendedValues.add("yes");
+        intendedValues.add("designated");
         intendedValues.add("permissive");
 
         potentialBarriers.add("gate");
@@ -146,6 +147,7 @@ public class CarFlagEncoder extends AbstractFlagEncoder {
         return this;
     }
 
+    @Override
     public TransportationMode getTransportationMode() {
         return TransportationMode.CAR;
     }
diff --git a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
index 14af94c1e..24a37c849 100644
--- a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
@@ -138,6 +138,7 @@ public class FootFlagEncoder extends AbstractFlagEncoder {
         speedDefault = MEAN_SPEED;
     }
 
+    @Override
     public TransportationMode getTransportationMode() {
         return TransportationMode.FOOT;
     }
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java b/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
index ade86b7b2..0a5f53645 100644
--- a/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/DefaultTagParserFactory.java
@@ -64,6 +64,12 @@ public class DefaultTagParserFactory implements TagParserFactory {
             return new OSMHazmatTunnelParser();
         else if (name.equals(HazmatWater.KEY))
             return new OSMHazmatWaterParser();
+        else if (name.equals(MtbRating.KEY))
+            return new OSMMtbRatingParser();
+        else if (name.equals(HikeRating.KEY))
+            return new OSMHikeRatingParser();
+        else if (name.equals(HorseRating.KEY))
+            return new OSMHorseRatingParser();
         else if (name.equals(Country.KEY))
             throw new IllegalArgumentException("The property spatial_rules.borders_directory is required in the configuration " +
                     "when using 'country' in encoded_values");
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHikeRatingParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHikeRatingParser.java
new file mode 100644
index 000000000..cf4191296
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHikeRatingParser.java
@@ -0,0 +1,64 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package com.graphhopper.routing.util.parsers;
+
+import com.graphhopper.reader.ReaderWay;
+import com.graphhopper.routing.ev.EncodedValue;
+import com.graphhopper.routing.ev.EncodedValueLookup;
+import com.graphhopper.routing.ev.HikeRating;
+import com.graphhopper.routing.ev.IntEncodedValue;
+import com.graphhopper.storage.IntsRef;
+
+import java.util.List;
+
+/**
+ * Parses the hiking difficulty. Where hiking corresponds to 1, mountain_hiking to 2 until 6.
+ *
+ * @see <a href="https://wiki.openstreetmap.org/wiki/Key:sac_scale">Key:sac_scale</a> for details on OSM hiking difficulties.
+ */
+public class OSMHikeRatingParser implements TagParser {
+
+    private final IntEncodedValue sacScaleEnc;
+
+    public OSMHikeRatingParser() {
+        this.sacScaleEnc = HikeRating.create();
+    }
+
+    @Override
+    public void createEncodedValues(EncodedValueLookup lookup, List<EncodedValue> link) {
+        link.add(sacScaleEnc);
+    }
+
+    @Override
+    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, boolean ferry, IntsRef relationFlags) {
+        String scale = readerWay.getTag("sac_scale");
+        int rating = 0;
+        if (scale != null) {
+            if (scale.equals("hiking")) rating = 1;
+            else if (scale.equals("mountain_hiking")) rating = 2;
+            else if (scale.equals("demanding_mountain_hiking")) rating = 3;
+            else if (scale.equals("alpine_hiking")) rating = 4;
+            else if (scale.equals("demanding_alpine_hiking")) rating = 5;
+            else if (scale.equals("difficult_alpine_hiking")) rating = 6;
+        }
+        if (rating != 0)
+            sacScaleEnc.setInt(false, edgeFlags, rating);
+
+        return edgeFlags;
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHorseRatingParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHorseRatingParser.java
new file mode 100644
index 000000000..f05599bf5
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMHorseRatingParser.java
@@ -0,0 +1,63 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package com.graphhopper.routing.util.parsers;
+
+import com.graphhopper.reader.ReaderWay;
+import com.graphhopper.routing.ev.EncodedValue;
+import com.graphhopper.routing.ev.EncodedValueLookup;
+import com.graphhopper.routing.ev.HorseRating;
+import com.graphhopper.routing.ev.IntEncodedValue;
+import com.graphhopper.storage.IntsRef;
+
+import java.util.List;
+
+/**
+ * Parses the horseback riding difficulty. Where common is mapped to 1, demanding to 2 until 6
+ *
+ * @see <a href="https://wiki.openstreetmap.org/wiki/Key:horse_scale">Key:horse_scale</a> for details on horseback riding difficulties.
+ */
+public class OSMHorseRatingParser implements TagParser {
+
+    private final IntEncodedValue horseScale;
+
+    public OSMHorseRatingParser() {
+        this.horseScale = HorseRating.create();
+    }
+
+    @Override
+    public void createEncodedValues(EncodedValueLookup lookup, List<EncodedValue> link) {
+        link.add(horseScale);
+    }
+
+    @Override
+    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, boolean ferry, IntsRef relationFlags) {
+        String scale = readerWay.getTag("horse_scale");
+        int rating = 0;
+        if (scale != null) {
+            if (scale.equals("common")) rating = 1;
+            else if (scale.equals("demanding")) rating = 2;
+            else if (scale.equals("difficult")) rating = 3;
+            else if (scale.equals("critical")) rating = 4;
+            else if (scale.equals("dangerous")) rating = 5;
+            else if (scale.equals("impossible")) rating = 6;
+        }
+        if (rating != 0)
+            horseScale.setInt(false, edgeFlags, rating);
+        return edgeFlags;
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/util/parsers/OSMMtbRatingParser.java b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMMtbRatingParser.java
new file mode 100644
index 000000000..ab484a787
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/util/parsers/OSMMtbRatingParser.java
@@ -0,0 +1,68 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package com.graphhopper.routing.util.parsers;
+
+import com.graphhopper.reader.ReaderWay;
+import com.graphhopper.routing.ev.EncodedValue;
+import com.graphhopper.routing.ev.EncodedValueLookup;
+import com.graphhopper.routing.ev.IntEncodedValue;
+import com.graphhopper.routing.ev.MtbRating;
+import com.graphhopper.storage.IntsRef;
+
+import java.util.List;
+
+/**
+ * Parses the mountain biking difficulty.
+ * A mapping mtb:scale=0 corresponds to 1 and mtb:scale=1 to 2 until 7.
+ *
+ * @see <a href="https://wiki.openstreetmap.org/wiki/Key:mtb:scale">Key:mtb:scale</a> for details on OSM mountain biking difficulties.
+ * @see <a href=""http://www.singletrail-skala.de/>Single Trail Scale</a>
+ */
+public class OSMMtbRatingParser implements TagParser {
+
+    private final IntEncodedValue mtbRatingEnc;
+
+    public OSMMtbRatingParser() {
+        this.mtbRatingEnc = MtbRating.create();
+    }
+
+    @Override
+    public void createEncodedValues(EncodedValueLookup lookup, List<EncodedValue> link) {
+        link.add(mtbRatingEnc);
+    }
+
+    @Override
+    public IntsRef handleWayTags(IntsRef edgeFlags, ReaderWay readerWay, boolean ferry, IntsRef relationFlags) {
+        String scale = readerWay.getTag("mtb:scale");
+        int rating = 0;
+        if (scale != null) {
+            if (scale.length() == 2 && (scale.charAt(1) == '+' || scale.charAt(1) == '-'))
+                scale = scale.substring(0, 1);
+            try {
+                int scaleAsInt = Integer.parseInt(scale);
+                rating = scaleAsInt + 1;
+            } catch (Exception ex) {
+            }
+        }
+
+        if (rating != 0)
+            mtbRatingEnc.setInt(false, edgeFlags, rating);
+
+        return edgeFlags;
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/storage/BaseGraph.java b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
index 1366c4aff..290054acf 100644
--- a/core/src/main/java/com/graphhopper/storage/BaseGraph.java
+++ b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
@@ -116,11 +116,6 @@ class BaseGraph implements Graph {
                 nodes.setInt((long) nodeId * nodeEntryBytes + N_EDGE_REF, edgeId);
             }
 
-            @Override
-            final int getEntryBytes() {
-                return edgeEntryBytes;
-            }
-
             @Override
             final long toPointer(int edgeId) {
                 assert isInBounds(edgeId) : "edgeId " + edgeId + " not in bounds [0," + edgeCount + ")";
@@ -930,19 +925,15 @@ class BaseGraph implements Graph {
 
         @Override
         public boolean next() {
-            while (true) {
-                edgeId++;
-                if (edgeId >= baseGraph.edgeCount)
-                    return false;
-
-                edgePointer = edgeAccess.toPointer(edgeId);
-                adjNode = edgeAccess.getNodeB(edgePointer);
-
-                baseNode = edgeAccess.getNodeA(edgePointer);
-                freshFlags = false;
-                reverse = false;
-                return true;
-            }
+            edgeId++;
+            if (edgeId >= baseGraph.edgeCount)
+                return false;
+            edgePointer = edgeAccess.toPointer(edgeId);
+            baseNode = edgeAccess.getNodeA(edgePointer);
+            adjNode = edgeAccess.getNodeB(edgePointer);
+            freshFlags = false;
+            reverse = false;
+            return true;
         }
 
         @Override
diff --git a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
index b6d45bbeb..089d6c03a 100644
--- a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
+++ b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
@@ -73,7 +73,7 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
         final String name = chConfig.getName();
         this.nodesCH = dir.find("nodes_ch_" + name, DAType.getPreferredInt(dir.getDefaultType()));
         this.shortcuts = dir.find("shortcuts_" + name, DAType.getPreferredInt(dir.getDefaultType()));
-        this.chEdgeAccess = new CHEdgeAccess(name);
+        this.chEdgeAccess = new CHEdgeAccess();
         if (segmentSize >= 0) {
             nodesCH.setSegmentSize(segmentSize);
             shortcuts.setSegmentSize(segmentSize);
@@ -446,18 +446,16 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
         @Override
         public boolean next() {
-            while (true) {
-                allEdgeIterator.edgeId++;
-                allEdgeIterator.edgePointer = (long) allEdgeIterator.edgeId * allEdgeIterator.edgeAccess.getEntryBytes();
-                if (!checkRange())
-                    return false;
-
-                allEdgeIterator.adjNode = allEdgeIterator.edgeAccess.getNodeB(allEdgeIterator.edgePointer);
-                allEdgeIterator.baseNode = allEdgeIterator.edgeAccess.getNodeA(allEdgeIterator.edgePointer);
-                allEdgeIterator.freshFlags = false;
-                allEdgeIterator.reverse = false;
-                return true;
-            }
+            allEdgeIterator.edgeId++;
+            if (allEdgeIterator.edgeId >= baseGraph.edgeCount + shortcutCount)
+                return false;
+            selectEdgeAccess(allEdgeIterator.edgeId);
+            allEdgeIterator.edgePointer = allEdgeIterator.edgeAccess.toPointer(allEdgeIterator.edgeId);
+            allEdgeIterator.baseNode = allEdgeIterator.edgeAccess.getNodeA(allEdgeIterator.edgePointer);
+            allEdgeIterator.adjNode = allEdgeIterator.edgeAccess.getNodeB(allEdgeIterator.edgePointer);
+            allEdgeIterator.freshFlags = false;
+            allEdgeIterator.reverse = false;
+            return true;
         }
 
         @Override
@@ -465,25 +463,9 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
             return allEdgeIterator.detach(reverseArg);
         }
 
-        private boolean checkRange() {
-            if (isShortcut())
-                return allEdgeIterator.edgeId < shortcutCount;
-
-            if (allEdgeIterator.edgeId < baseGraph.edgeCount)
-                return true;
-
-            // iterate over shortcuts
-            allEdgeIterator.edgeAccess = chEdgeAccess;
-            allEdgeIterator.edgeId = 0;
-            allEdgeIterator.edgePointer = (long) allEdgeIterator.edgeId * shortcutEntryBytes;
-            return allEdgeIterator.edgeId < shortcutCount;
-        }
-
         @Override
         public int getEdge() {
-            if (isShortcut())
-                return baseGraph.edgeCount + allEdgeIterator.edgeId;
-            return super.getEdge();
+            return allEdgeIterator.edgeId;
         }
 
         @Override
@@ -499,11 +481,9 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
     }
 
     private class CHEdgeAccess extends EdgeAccess {
-        private final String name;
 
-        public CHEdgeAccess(String name) {
+        public CHEdgeAccess() {
             super(shortcuts);
-            this.name = name;
         }
 
         @Override
@@ -516,11 +496,6 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
             nodesCH.setInt((long) nodeId * nodeCHEntryBytes + N_CH_REF, edgeId);
         }
 
-        @Override
-        final int getEntryBytes() {
-            return shortcutEntryBytes;
-        }
-
         void setShortcutFlags(long edgePointer, int flags) {
             edges.setInt(edgePointer + E_FLAGS, flags);
         }
@@ -601,10 +576,6 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
             return tmp < shortcutCount && tmp >= 0;
         }
 
-        @Override
-        public String toString() {
-            return "ch edge access " + name;
-        }
     }
 
     private class CHEdgeIteratorStateImpl implements CHEdgeIteratorState {
@@ -648,6 +619,7 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
         @Override
         public EdgeIteratorState setFlags(IntsRef edgeFlags) {
+            checkShortcut(false, "getFlags");
             return edgeIterable.setFlags(edgeFlags);
         }
 
@@ -659,6 +631,7 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
         @Override
         public EdgeIteratorState copyPropertiesFrom(EdgeIteratorState e) {
+            checkShortcut(false, "copyPropertiesFrom");
             return edgeIterable.copyPropertiesFrom(e);
         }
 
@@ -717,11 +690,13 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
         @Override
         public boolean getFwdAccess() {
+            checkShortcut(true, "getFwdAccess");
             return (getShortcutFlags() & (edgeIterable.reverse ? PrepareEncoder.getScBwdDir() : PrepareEncoder.getScFwdDir())) != 0;
         }
 
         @Override
         public boolean getBwdAccess() {
+            checkShortcut(true, "getBwdAccess");
             return (getShortcutFlags() & (edgeIterable.reverse ? PrepareEncoder.getScFwdDir() : PrepareEncoder.getScBwdDir())) != 0;
         }
 
@@ -797,76 +772,91 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
         @Override
         public EdgeIteratorState set(BooleanEncodedValue property, boolean value) {
+            checkShortcut(false, "set(BooleanEncodedValue, boolean)");
             return edgeIterable.set(property, value);
         }
 
         @Override
         public EdgeIteratorState setReverse(BooleanEncodedValue property, boolean value) {
+            checkShortcut(false, "setReverse(BooleanEncodedValue, boolean)");
             return edgeIterable.setReverse(property, value);
         }
 
         @Override
         public int get(IntEncodedValue property) {
+            checkShortcut(false, "get(IntEncodedValue)");
             return edgeIterable.get(property);
         }
 
         @Override
         public EdgeIteratorState set(IntEncodedValue property, int value) {
+            checkShortcut(false, "set(IntEncodedValue, int)");
             return edgeIterable.set(property, value);
         }
 
         @Override
         public int getReverse(IntEncodedValue property) {
+            checkShortcut(false, "getReverse(IntEncodedValue)");
             return edgeIterable.getReverse(property);
         }
 
         @Override
         public EdgeIteratorState setReverse(IntEncodedValue property, int value) {
+            checkShortcut(false, "setReverse(IntEncodedValue, int)");
             return edgeIterable.setReverse(property, value);
         }
 
         @Override
         public double get(DecimalEncodedValue property) {
+            checkShortcut(false, "get(DecimalEncodedValue)");
             return edgeIterable.get(property);
         }
 
         @Override
         public EdgeIteratorState set(DecimalEncodedValue property, double value) {
+            checkShortcut(false, "set(DecimalEncodedValue, double)");
             return edgeIterable.set(property, value);
         }
 
         @Override
         public double getReverse(DecimalEncodedValue property) {
+            checkShortcut(false, "getReverse(DecimalEncodedValue)");
             return edgeIterable.getReverse(property);
         }
 
         @Override
         public EdgeIteratorState setReverse(DecimalEncodedValue property, double value) {
+            checkShortcut(false, "setReverse(DecimalEncodedValue, double)");
             return edgeIterable.setReverse(property, value);
         }
 
         @Override
         public <T extends Enum> T get(EnumEncodedValue<T> property) {
+            checkShortcut(false, "get(EnumEncodedValue<T>)");
             return edgeIterable.get(property);
         }
 
         @Override
         public <T extends Enum> EdgeIteratorState set(EnumEncodedValue<T> property, T value) {
+            checkShortcut(false, "set(EnumEncodedValue<T>, T)");
             return edgeIterable.set(property, value);
         }
 
         @Override
         public <T extends Enum> T getReverse(EnumEncodedValue<T> property) {
+            checkShortcut(false, "getReverse(EnumEncodedValue<T>)");
             return edgeIterable.getReverse(property);
         }
 
         @Override
         public <T extends Enum> EdgeIteratorState setReverse(EnumEncodedValue<T> property, T value) {
+            checkShortcut(false, "setReverse(EnumEncodedValue<T>, T)");
             return edgeIterable.setReverse(property, value);
         }
 
         @Override
         public EdgeIteratorState detach(boolean reverseArg) {
+            checkShortcut(false, "detach(boolean)");
             return edgeIterable.detach(reverseArg);
         }
 
diff --git a/core/src/main/java/com/graphhopper/storage/EdgeAccess.java b/core/src/main/java/com/graphhopper/storage/EdgeAccess.java
index 5cada72d5..650460018 100644
--- a/core/src/main/java/com/graphhopper/storage/EdgeAccess.java
+++ b/core/src/main/java/com/graphhopper/storage/EdgeAccess.java
@@ -46,8 +46,6 @@ abstract class EdgeAccess {
 
     abstract void setEdgeRef(int nodeId, int edgeId);
 
-    abstract int getEntryBytes();
-
     final void readFlags(long edgePointer, IntsRef edgeFlags) {
         int size = edgeFlags.ints.length;
         for (int i = 0; i < size; i++) {
diff --git a/core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java b/core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java
index b12ab51d1..97fdba964 100644
--- a/core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java
+++ b/core/src/main/java/com/graphhopper/util/details/PathDetailsBuilderFactory.java
@@ -17,14 +17,12 @@
  */
 package com.graphhopper.util.details;
 
-import com.graphhopper.coll.MapEntry;
 import com.graphhopper.routing.ev.*;
 import com.graphhopper.routing.weighting.Weighting;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Map;
 
 import static com.graphhopper.routing.util.EncodingManager.getKey;
 import static com.graphhopper.util.Parameters.Details.*;
@@ -76,15 +74,15 @@ public class PathDetailsBuilderFactory {
                 builders.add(new BooleanDetails(key, evl.getBooleanEncodedValue(key)));
         }
 
-        for (Map.Entry entry : Arrays.asList(new MapEntry<>(RoadClass.KEY, RoadClass.class),
-                new MapEntry<>(RoadEnvironment.KEY, RoadEnvironment.class), new MapEntry<>(Surface.KEY, Surface.class),
-                new MapEntry<>(RoadAccess.KEY, RoadAccess.class), new MapEntry<>(Toll.KEY, Toll.class),
-                new MapEntry<>(TrackType.KEY, TrackType.class), new MapEntry<>(Hazmat.KEY, Hazmat.class),
-                new MapEntry<>(HazmatTunnel.KEY, HazmatTunnel.class), new MapEntry<>(HazmatWater.KEY, HazmatWater.class),
-                new MapEntry<>(Country.KEY, Country.class))) {
-            String key = (String) entry.getKey();
+        for (String key : Arrays.asList(RoadClass.KEY, RoadEnvironment.KEY, Surface.KEY, RoadAccess.KEY,
+                Toll.KEY, TrackType.KEY, Hazmat.KEY, HazmatTunnel.KEY, HazmatWater.KEY, Country.KEY)) {
             if (requestedPathDetails.contains(key) && evl.hasEncodedValue(key))
-                builders.add(new EnumDetails(key, evl.getEnumEncodedValue(key, (Class<Enum>) entry.getValue())));
+                builders.add(new EnumDetails<>(key, evl.getEnumEncodedValue(key, Enum.class)));
+        }
+
+        for (String key : Arrays.asList(MtbRating.KEY, HikeRating.KEY, HorseRating.KEY)) {
+            if (requestedPathDetails.contains(key) && evl.hasEncodedValue(key))
+                builders.add(new IntDetails(key, evl.getIntEncodedValue(key)));
         }
 
         if (requestedPathDetails.size() != builders.size()) {
diff --git a/docs/web/api-doc.md b/docs/web/api-doc.md
index 3fa6d586f..ada77e4a9 100644
--- a/docs/web/api-doc.md
+++ b/docs/web/api-doc.md
@@ -93,8 +93,6 @@ paths[0].instructions[0].distance             | The distance for this instructio
 paths[0].instructions[0].time                 | The duration for this instruction, in ms
 paths[0].instructions[0].interval             | An array containing the first and the last index (relative to paths[0].points) of the points for this instruction. This is useful to know for which part of the route the instructions are valid.
 paths[0].instructions[0].sign                 | A number which specifies the sign to show e.g. 2 for a right turn.<br>KEEP_LEFT=-7<br>TURN_SHARP_LEFT = -3<br>TURN_LEFT = -2<br>TURN_SLIGHT_LEFT = -1<br>CONTINUE_ON_STREET = 0<br>TURN_SLIGHT_RIGHT = 1<br>TURN_RIGHT = 2<br>TURN_SHARP_RIGHT = 3<br>FINISH = 4<br>REACHED_VIA = 5<br>USE_ROUNDABOUT = 6<br>KEEP_RIGHT=7<br>implement some default for all other
-paths[0].instructions[0].annotation_text      | [optional] A text describing the instruction in more detail, e.g. like surface of the way, warnings or involved costs
-paths[0].instructions[0].annotation_importance| [optional] 0 stands for INFO, 1 for warning, 2 for costs, 3 for costs and warning
 paths[0].instructions[0].exit_number          | [optional] Only available for USE_ROUNDABOUT instructions. The count of exits at which the route leaves the roundabout.
 paths[0].instructions[0].exited               | [optional] Only available for USE_ROUNDABOUT instructions. True if the roundabout should be exited. False if a via point or end is placed in the roundabout, thus, the roundabout should not be exited due to this instruction.
 paths[0].instructions[0].turn_angle           | [optional] Only available for USE_ROUNDABOUT instructions. The radian of the route within the roundabout: `0 < r < 2*PI` for clockwise and `-2PI < r < 0` for counterclockwise transit. `NaN` if the direction of rotation is undefined.
diff --git a/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/ContourBuilder.java b/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/ContourBuilder.java
index b9ba043e4..8badafb03 100644
--- a/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/ContourBuilder.java
+++ b/isochrone/src/main/java/com/graphhopper/isochrone/algorithm/ContourBuilder.java
@@ -68,12 +68,7 @@ public class ContourBuilder {
                     cC = e.orig().midPoint(e.dest()).getCoordinate();
                 }
                 // Strip z coordinate
-                Coordinate c = new Coordinate(cC.x, cC.y);
-                // Truncate coordinates at defined number of decimal places.
-                // Shouldn't be necessary because Geometries carry the precision model with them, but the
-                // JSON writer ignores it, so there's that.
-                geometryFactory.getPrecisionModel().makePrecise(c);
-                polyPoints.add(c);
+                polyPoints.add(new Coordinate(cC.x, cC.y));
                 processed.add(e);
                 ReadableQuadEdge E1 = ccw ? e.oNext().getPrimary() : e.oPrev().getPrimary();
                 ReadableQuadEdge E2 = ccw ? e.dPrev().getPrimary() : e.dNext().getPrimary();
diff --git a/reader-gtfs/src/main/java/com/graphhopper/gtfs/TripFromLabel.java b/reader-gtfs/src/main/java/com/graphhopper/gtfs/TripFromLabel.java
index 0c08c6074..09fabe927 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/gtfs/TripFromLabel.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/gtfs/TripFromLabel.java
@@ -106,7 +106,7 @@ class TripFromLabel {
                 final PointList pl;
                 if (!ptLeg.isInSameVehicleAsPrevious) {
                     pl = new PointList();
-                    final Instruction departureInstruction = new Instruction(Instruction.PT_START_TRIP, ptLeg.trip_headsign, InstructionAnnotation.EMPTY, pl);
+                    final Instruction departureInstruction = new Instruction(Instruction.PT_START_TRIP, ptLeg.trip_headsign, pl);
                     departureInstruction.setDistance(leg.getDistance());
                     departureInstruction.setTime(ptLeg.travelTime);
                     instructions.add(departureInstruction);
@@ -123,7 +123,7 @@ class TripFromLabel {
                 final Trip.Stop arrivalStop = ptLeg.stops.get(ptLeg.stops.size() - 1);
                 arrivalPointList.add(arrivalStop.geometry.getY(), arrivalStop.geometry.getX());
                 pointsList.add(arrivalStop.geometry.getY(), arrivalStop.geometry.getX());
-                Instruction arrivalInstruction = new Instruction(Instruction.PT_END_TRIP, arrivalStop.stop_name, InstructionAnnotation.EMPTY, arrivalPointList);
+                Instruction arrivalInstruction = new Instruction(Instruction.PT_END_TRIP, arrivalStop.stop_name, arrivalPointList);
                 if (ptLeg.isInSameVehicleAsPrevious) {
                     instructions.set(instructions.size() - 1, arrivalInstruction);
                 } else {
@@ -373,7 +373,7 @@ class TripFromLabel {
         } else {
             InstructionList instructions = new InstructionList(tr);
             InstructionsFromEdges instructionsFromEdges = new InstructionsFromEdges(graph,
-                    weighting, weighting.getFlagEncoder(), tr, instructions);
+                    weighting, weighting.getFlagEncoder(), instructions);
             int prevEdgeId = -1;
             for (int i = 1; i < path.size(); i++) {
                 if (path.get(i).edge.edgeType != GtfsStorage.EdgeType.HIGHWAY) {
diff --git a/web-api/src/main/java/com/graphhopper/jackson/InstructionListSerializer.java b/web-api/src/main/java/com/graphhopper/jackson/InstructionListSerializer.java
index ee518ed68..4ae3353e8 100644
--- a/web-api/src/main/java/com/graphhopper/jackson/InstructionListSerializer.java
+++ b/web-api/src/main/java/com/graphhopper/jackson/InstructionListSerializer.java
@@ -17,17 +17,20 @@
  */
 package com.graphhopper.jackson;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.graphhopper.util.Helper;
 import com.graphhopper.util.Instruction;
-import com.graphhopper.util.InstructionAnnotation;
 import com.graphhopper.util.InstructionList;
 
-import java.io.IOException;
-import java.util.*;
-
 public class InstructionListSerializer extends JsonSerializer<InstructionList> {
     @Override
     public void serialize(InstructionList instructions, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
@@ -37,15 +40,7 @@ public class InstructionListSerializer extends JsonSerializer<InstructionList> {
             Map<String, Object> instrJson = new HashMap<>();
             instrList.add(instrJson);
 
-            InstructionAnnotation ia = instruction.getAnnotation();
-            String text = instruction.getTurnDescription(instructions.getTr());
-            if (Helper.isEmpty(text))
-                text = ia.getMessage();
-            instrJson.put("text", Helper.firstBig(text));
-            if (!ia.isEmpty()) {
-                instrJson.put("annotation_text", ia.getMessage());
-                instrJson.put("annotation_importance", ia.getImportance());
-            }
+            instrJson.put("text", Helper.firstBig(instruction.getTurnDescription(instructions.getTr())));
 
             instrJson.put("street_name", instruction.getName());
             instrJson.put("time", instruction.getTime());
diff --git a/web-api/src/main/java/com/graphhopper/jackson/ResponsePathDeserializer.java b/web-api/src/main/java/com/graphhopper/jackson/ResponsePathDeserializer.java
index 8be68ee24..1d03d642e 100644
--- a/web-api/src/main/java/com/graphhopper/jackson/ResponsePathDeserializer.java
+++ b/web-api/src/main/java/com/graphhopper/jackson/ResponsePathDeserializer.java
@@ -95,14 +95,9 @@ public class ResponsePathDeserializer extends JsonDeserializer<ResponsePath> {
                         instPL.add(pointList, j);
                     }
 
-                    InstructionAnnotation ia = InstructionAnnotation.EMPTY;
-                    if (jsonObj.has("annotation_importance") && jsonObj.has("annotation_text")) {
-                        ia = new InstructionAnnotation(jsonObj.get("annotation_importance").asInt(), jsonObj.get("annotation_text").asText());
-                    }
-
                     Instruction instr;
                     if (sign == Instruction.USE_ROUNDABOUT || sign == Instruction.LEAVE_ROUNDABOUT) {
-                        RoundaboutInstruction ri = new RoundaboutInstruction(sign, text, ia, instPL);
+                        RoundaboutInstruction ri = new RoundaboutInstruction(sign, text, instPL);
 
                         if (jsonObj.has("exit_number")) {
                             ri.setExitNumber(jsonObj.get("exit_number").asInt());
@@ -122,14 +117,14 @@ public class ResponsePathDeserializer extends JsonDeserializer<ResponsePath> {
 
                         instr = ri;
                     } else if (sign == Instruction.REACHED_VIA) {
-                        ViaInstruction tmpInstr = new ViaInstruction(text, ia, instPL);
+                        ViaInstruction tmpInstr = new ViaInstruction(text, instPL);
                         tmpInstr.setViaCount(viaCount);
                         viaCount++;
                         instr = tmpInstr;
                     } else if (sign == Instruction.FINISH) {
                         instr = new FinishInstruction(text, instPL, 0);
                     } else {
-                        instr = new Instruction(sign, text, ia, instPL);
+                        instr = new Instruction(sign, text, instPL);
                         if (sign == Instruction.CONTINUE_ON_STREET) {
                             if (jsonObj.has("heading")) {
                                 instr.setExtraInfo("heading", jsonObj.get("heading").asDouble());
diff --git a/web/src/main/resources/assets/js/instructions.js b/web/src/main/resources/assets/js/instructions.js
index bcebfb523..a222be658 100644
--- a/web/src/main/resources/assets/js/instructions.js
+++ b/web/src/main/resources/assets/js/instructions.js
@@ -10,12 +10,6 @@ function addInstruction(mapLayer, main, instr, instrIndex, lngLat, useMiles, deb
     else
         sign = messages.getSignName(sign);
     var title = instr.text;
-    if (instr.annotation_text) {
-        if (!title)
-            title = instr.annotation_text;
-        else
-            title = title + ", " + instr.annotation_text;
-    }
 
     var pathname = window.location.pathname;
     var dirname = pathname.substring(0, pathname.lastIndexOf('/'));


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
index 08a199f93..dc809ebe0 100644
--- a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
@@ -90,24 +90,6 @@ public class CarFlagEncoderTest {
         way.setTag("motorcar", "yes");
         assertTrue(encoder.getAccess(way).isWay());
 
-        way.clearTags();
-        way.setTag("route", "ferry");
-        assertTrue(encoder.getAccess(way).isFerry());
-        way.setTag("motorcar", "no");
-        assertTrue(encoder.getAccess(way).canSkip());
-
-        way.clearTags();
-        way.setTag("route", "ferry");
-        way.setTag("foot", "yes");
-        assertTrue(encoder.getAccess(way).canSkip());
-
-        way.clearTags();
-        way.setTag("route", "ferry");
-        way.setTag("access", "no");
-        assertTrue(encoder.getAccess(way).canSkip());
-        way.setTag("vehicle", "yes");
-        assertTrue(encoder.getAccess(way).isFerry());
-
         way.clearTags();
         way.setTag("access", "yes");
         way.setTag("motor_vehicle", "no");
@@ -487,8 +469,11 @@ public class CarFlagEncoderTest {
         way.setTag("railway", "tram");
         // but allow tram to be on the same way
         assertTrue(encoder.getAccess(way).isWay());
+    }
 
-        way = new ReaderWay(1);
+    @Test
+    public void testFerry() {
+        ReaderWay way = new ReaderWay(1);
         way.setTag("route", "shuttle_train");
         way.setTag("motorcar", "yes");
         way.setTag("bicycle", "no");
@@ -527,6 +512,30 @@ public class CarFlagEncoderTest {
         assertTrue(encoder.getAccess(way).isFerry());
         // We have ignored the unrealisitc long duration and take the unknown speed
         assertEquals(2.5, encoder.getFerrySpeed(way), 1e-1);
+
+        way.clearTags();
+        way.setTag("route", "ferry");
+        assertTrue(encoder.getAccess(way).isFerry());
+        way.setTag("motorcar", "no");
+        assertTrue(encoder.getAccess(way).canSkip());
+
+        way.clearTags();
+        way.setTag("route", "ferry");
+        way.setTag("foot", "yes");
+        assertTrue(encoder.getAccess(way).canSkip());
+
+        way.clearTags();
+        way.setTag("route", "ferry");
+        way.setTag("foot", "designated");
+        way.setTag("motor_vehicle", "designated");
+        assertTrue(encoder.getAccess(way).isFerry());
+
+        way.clearTags();
+        way.setTag("route", "ferry");
+        way.setTag("access", "no");
+        assertTrue(encoder.getAccess(way).canSkip());
+        way.setTag("vehicle", "yes");
+        assertTrue(encoder.getAccess(way).isFerry());
     }
 
     @Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/EncodingManagerTest.java b/core/src/test/java/com/graphhopper/routing/util/EncodingManagerTest.java
index 242318449..0b86c69fe 100644
--- a/core/src/test/java/com/graphhopper/routing/util/EncodingManagerTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/EncodingManagerTest.java
@@ -83,6 +83,7 @@ public class EncodingManagerTest {
     @Test
     public void testToDetailsStringIncludesEncoderVersionNumber() {
         FlagEncoder encoder = new AbstractFlagEncoder(1, 2.0, 0) {
+            @Override
             public TransportationMode getTransportationMode() {
                 return TransportationMode.BIKE;
             }
diff --git a/core/src/test/java/com/graphhopper/util/InstructionListTest.java b/core/src/test/java/com/graphhopper/util/InstructionListTest.java
index fac96988a..61b92f256 100644
--- a/core/src/test/java/com/graphhopper/util/InstructionListTest.java
+++ b/core/src/test/java/com/graphhopper/util/InstructionListTest.java
@@ -347,29 +347,6 @@ public class InstructionListTest {
         assertEquals("3-4", Instructions.find(wayList, 15.099, 9.9, 1000).getName());
     }
 
-    @Test
-    public void simpleAnnotations() {
-        Graph graph = createTestGraph();
-
-        EnumEncodedValue<RoadEnvironment> roadEnvEnc = carManager.getEnumEncodedValue(RoadEnvironment.KEY, RoadEnvironment.class);
-        EnumEncodedValue<RoadAccess> roadAccessEnc = carManager.getEnumEncodedValue(RoadAccess.KEY, RoadAccess.class);
-        EdgeIteratorState edge1 = GHUtility.getEdge(graph, 7, 8);
-        edge1.set(roadEnvEnc, RoadEnvironment.FERRY);
-
-        EdgeIteratorState edge2 = GHUtility.getEdge(graph, 8, 9);
-        edge2.set(roadAccessEnc, RoadAccess.PRIVATE);
-
-        Weighting weighting = new FastestWeighting(carEncoder);
-        final InstructionList ways = new InstructionList(usTR);
-        InstructionsFromEdges instrFromEdges = new InstructionsFromEdges(graph, weighting, carManager, usTR, ways);
-        instrFromEdges.next(edge1, 0, EdgeIterator.NO_EDGE);
-        instrFromEdges.next(edge2, 1, edge1.getEdge());
-        instrFromEdges.finish();
-
-        assertEquals("take the ferry", ways.get(0).getAnnotation().getMessage());
-        assertEquals("private road", ways.get(1).getAnnotation().getMessage());
-    }
-
     private void compare(List<List<Double>> expected, List<List<Double>> actual) {
         for (int i = 0; i < expected.size(); i++) {
             List<Double> e = expected.get(i);
diff --git a/reader-osm/src/test/java/com/graphhopper/GraphHopperTest.java b/reader-osm/src/test/java/com/graphhopper/GraphHopperTest.java
index ebfd94faf..81689176c 100644
--- a/reader-osm/src/test/java/com/graphhopper/GraphHopperTest.java
+++ b/reader-osm/src/test/java/com/graphhopper/GraphHopperTest.java
@@ -1087,16 +1087,14 @@ public class GraphHopperTest {
         assertFalse(rsp.hasErrors());
         ResponsePath res = rsp.getBest();
         assertEquals(6932.2, res.getDistance(), .1);
-        assertEquals(104, res.getPoints().getSize());
+        assertEquals(103, res.getPoints().getSize());
 
         InstructionList il = res.getInstructions();
-        assertEquals(21, il.size());
+        assertEquals(19, il.size());
 
         assertEquals("continue onto Obere Landstraße", il.get(0).getTurnDescription(tr));
-        assertEquals("get off the bike", il.get(0).getAnnotation().getMessage());
         assertEquals(69.28, (Double) il.get(0).getExtraInfoJSON().get("heading"), .01);
         assertEquals("turn left onto Kirchengasse", il.get(1).getTurnDescription(tr));
-        assertEquals("get off the bike", il.get(1).getAnnotation().getMessage());
 
         assertEquals("turn right onto Pfarrplatz", il.get(2).getTurnDescription(tr));
         assertEquals("turn right onto Margarethenstraße", il.get(3).getTurnDescription(tr));
@@ -1107,8 +1105,7 @@ public class GraphHopperTest {
         assertEquals("keep left onto Austraße", il.get(10).getTurnDescription(tr));
         assertEquals("keep left onto Rechte Kremszeile", il.get(11).getTurnDescription(tr));
         //..
-        assertEquals("turn right onto Treppelweg", il.get(17).getTurnDescription(tr));
-        assertEquals("cycleway", il.get(17).getAnnotation().getMessage());
+        assertEquals("turn right onto Treppelweg", il.get(15).getTurnDescription(tr));
 
         // do not return 'get off bike' for foot
         rsp = hopper.route(new GHRequest(48.410987, 15.599492, 48.411172, 15.600371).
@@ -1116,7 +1113,6 @@ public class GraphHopperTest {
         assertFalse(rsp.hasErrors());
         il = rsp.getBest().getInstructions();
         assertEquals("continue onto Obere Landstraße", il.get(0).getTurnDescription(tr));
-        assertEquals("", il.get(0).getAnnotation().getMessage());
     }
 
     @Test
diff --git a/web-api/src/test/java/com/graphhopper/util/InstructionListRepresentationTest.java b/web-api/src/test/java/com/graphhopper/util/InstructionListRepresentationTest.java
index 73f50ef9f..7636c3730 100644
--- a/web-api/src/test/java/com/graphhopper/util/InstructionListRepresentationTest.java
+++ b/web-api/src/test/java/com/graphhopper/util/InstructionListRepresentationTest.java
@@ -23,8 +23,7 @@ public class InstructionListRepresentationTest {
         pl.add(52.514, 13.349);
         pl.add(52.5135, 13.35);
         pl.add(52.514, 13.351);
-        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname",
-                new InstructionAnnotation(0, ""), pl)
+        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname", pl)
                 .setDirOfRotation(-0.1)
                 .setRadian(-Math.PI + 1)
                 .setExitNumber(2)
@@ -44,8 +43,7 @@ public class InstructionListRepresentationTest {
         pl.add(52.514, 13.349);
         pl.add(52.5135, 13.35);
         pl.add(52.514, 13.351);
-        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname",
-                new InstructionAnnotation(0, ""), pl)
+        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname", pl)
                 .setRadian(-Math.PI + 1)
                 .setExitNumber(2)
                 .setExited();
diff --git a/web-bundle/src/test/java/com/graphhopper/util/gpx/GpxFromInstructionsTest.java b/web-bundle/src/test/java/com/graphhopper/util/gpx/GpxFromInstructionsTest.java
index f5c1315cc..560758270 100644
--- a/web-bundle/src/test/java/com/graphhopper/util/gpx/GpxFromInstructionsTest.java
+++ b/web-bundle/src/test/java/com/graphhopper/util/gpx/GpxFromInstructionsTest.java
@@ -128,20 +128,19 @@ public class GpxFromInstructionsTest {
 
     @Test
     public void testCreateGPX() {
-        InstructionAnnotation ea = InstructionAnnotation.EMPTY;
         InstructionList instructions = new InstructionList(trMap.getWithFallBack(Locale.US));
         PointList pl = new PointList();
         pl.add(49.942576, 11.580384);
         pl.add(49.941858, 11.582422);
-        instructions.add(new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, pl).setDistance(240).setTime(15000));
+        instructions.add(new Instruction(Instruction.CONTINUE_ON_STREET, "temp", pl).setDistance(240).setTime(15000));
 
         pl = new PointList();
         pl.add(49.941575, 11.583501);
-        instructions.add(new Instruction(Instruction.TURN_LEFT, "temp2", ea, pl).setDistance(25).setTime(4000));
+        instructions.add(new Instruction(Instruction.TURN_LEFT, "temp2", pl).setDistance(25).setTime(4000));
 
         pl = new PointList();
         pl.add(49.941389, 11.584311);
-        instructions.add(new Instruction(Instruction.TURN_LEFT, "temp2", ea, pl).setDistance(25).setTime(3000));
+        instructions.add(new Instruction(Instruction.TURN_LEFT, "temp2", pl).setDistance(25).setTime(3000));
         instructions.add(new FinishInstruction(49.941029, 11.584514, 0));
 
         List<GPXEntry> result = GpxFromInstructions.createGPXList(instructions);
@@ -164,8 +163,7 @@ public class GpxFromInstructionsTest {
         pl.add(52.555423473315, 13.43890086052345);
         pl.add(52.555550691982, 13.43946393816465);
         pl.add(52.555619423589, 13.43886994061328);
-        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname",
-                InstructionAnnotation.EMPTY, pl)
+        RoundaboutInstruction instr = new RoundaboutInstruction(Instruction.USE_ROUNDABOUT, "streetname", pl)
                 .setRadian(2.058006514284998d)
                 .setExitNumber(3)
                 .setExited();
@@ -185,7 +183,7 @@ public class GpxFromInstructionsTest {
         PointList pl = new PointList();
         pl.add(0.000001, 0.000001);
         pl.add(-0.000123, -0.000125);
-        Instruction instruction = new Instruction(0, "do it", null, pl);
+        Instruction instruction = new Instruction(0, "do it", pl);
         instructions.add(instruction);
         instructions.add(new FinishInstruction(0.000852, 0.000852, 0));
 
@@ -242,14 +240,13 @@ public class GpxFromInstructionsTest {
 
     @Test
     public void testCalcAzimuthAndGetDirection() {
-        InstructionAnnotation ea = InstructionAnnotation.EMPTY;
         PointList pl = new PointList();
         pl.add(49.942, 11.584);
 
         PointList nextPl = new PointList();
         nextPl.add(49.942, 11.582);
-        Instruction currI = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, pl);
-        Instruction nextI = new Instruction(Instruction.CONTINUE_ON_STREET, "next", ea, nextPl);
+        Instruction currI = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", pl);
+        Instruction nextI = new Instruction(Instruction.CONTINUE_ON_STREET, "next", nextPl);
 
         assertEquals(270, GpxFromInstructions.calcAzimuth(currI, nextI), .1);
         assertEquals("W", GpxFromInstructions.calcDirection(currI, nextI));
@@ -257,7 +254,7 @@ public class GpxFromInstructionsTest {
         PointList p2 = new PointList();
         p2.add(49.942, 11.580);
         p2.add(49.944, 11.582);
-        Instruction i2 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, p2);
+        Instruction i2 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", p2);
 
         assertEquals(32.76, GpxFromInstructions.calcAzimuth(i2, null), .1);
         assertEquals("NE", GpxFromInstructions.calcDirection(i2, null));
@@ -265,7 +262,7 @@ public class GpxFromInstructionsTest {
         PointList p3 = new PointList();
         p3.add(49.942, 11.580);
         p3.add(49.944, 11.580);
-        Instruction i3 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, p3);
+        Instruction i3 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", p3);
 
         assertEquals(0, GpxFromInstructions.calcAzimuth(i3, null), .1);
         assertEquals("N", GpxFromInstructions.calcDirection(i3, null));
@@ -273,13 +270,13 @@ public class GpxFromInstructionsTest {
         PointList p4 = new PointList();
         p4.add(49.940, 11.580);
         p4.add(49.920, 11.586);
-        Instruction i4 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, p4);
+        Instruction i4 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", p4);
 
         assertEquals("S", GpxFromInstructions.calcDirection(i4, null));
 
         PointList p5 = new PointList();
         p5.add(49.940, 11.580);
-        Instruction i5 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", ea, p5);
+        Instruction i5 = new Instruction(Instruction.CONTINUE_ON_STREET, "temp", p5);
 
         assertTrue(Double.isNaN(GpxFromInstructions.calcAzimuth(i5, null)));
         assertEquals("", GpxFromInstructions.calcDirection(i5, null));