Repository: graphhopper/graphhopper
Pull request #1954 (2020-03-13 17:03:42)

use enum instead of int
@easbar as discussed in #1950 :)


Patch:
diff --git a/core/src/main/java/com/graphhopper/reader/dem/EdgeElevationInterpolator.java b/core/src/main/java/com/graphhopper/reader/dem/EdgeElevationInterpolator.java
index 3bcb5881f..161f0b327 100644
--- a/core/src/main/java/com/graphhopper/reader/dem/EdgeElevationInterpolator.java
+++ b/core/src/main/java/com/graphhopper/reader/dem/EdgeElevationInterpolator.java
@@ -146,7 +146,7 @@ public class EdgeElevationInterpolator {
                 double lon1 = nodeAccess.getLon(secondNodeId);
                 double ele1 = nodeAccess.getEle(secondNodeId);
 
-                final PointList pointList = edge.fetchWayGeometry(3);
+                final PointList pointList = edge.fetchWayGeometry(FetchMode.ALL);
                 final int count = pointList.size();
                 for (int index = 1; index < count - 1; index++) {
                     double lat = pointList.getLat(index);
diff --git a/core/src/main/java/com/graphhopper/routing/DirectionResolver.java b/core/src/main/java/com/graphhopper/routing/DirectionResolver.java
index 52d714aca..cfbef00ed 100644
--- a/core/src/main/java/com/graphhopper/routing/DirectionResolver.java
+++ b/core/src/main/java/com/graphhopper/routing/DirectionResolver.java
@@ -18,8 +18,6 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.routing.profiles.BooleanEncodedValue;
-import com.graphhopper.routing.util.FlagEncoder;
-import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.*;
@@ -192,7 +190,7 @@ public class DirectionResolver {
             }
             // we are interested in the coordinates of the next point on this edge, it could be the adj tower node
             // but also a pillar node
-            final PointList geometry = iter.fetchWayGeometry(3);
+            final PointList geometry = iter.fetchWayGeometry(FetchMode.ALL);
             double nextPointLat = geometry.getLat(1);
             double nextPointLon = geometry.getLon(1);
 
diff --git a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
index 1d7a128d8..56661a9f7 100644
--- a/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
+++ b/core/src/main/java/com/graphhopper/routing/InstructionsFromEdges.java
@@ -151,7 +151,7 @@ public class InstructionsFromEdges implements Path.EdgeVisitor {
         double adjLon = nodeAccess.getLongitude(adjNode);
         double latitude, longitude;
 
-        PointList wayGeo = edge.fetchWayGeometry(3);
+        PointList wayGeo = edge.fetchWayGeometry(FetchMode.ALL);
         boolean isRoundabout = edge.get(roundaboutEnc);
 
         if (wayGeo.getSize() <= 2) {
diff --git a/core/src/main/java/com/graphhopper/routing/InstructionsHelper.java b/core/src/main/java/com/graphhopper/routing/InstructionsHelper.java
index b395f6025..8c9062bbc 100644
--- a/core/src/main/java/com/graphhopper/routing/InstructionsHelper.java
+++ b/core/src/main/java/com/graphhopper/routing/InstructionsHelper.java
@@ -18,10 +18,7 @@
 package com.graphhopper.routing;
 
 import com.graphhopper.storage.NodeAccess;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.Helper;
-import com.graphhopper.util.Instruction;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 import com.graphhopper.util.shapes.GHPoint;
 
 /**
@@ -78,7 +75,7 @@ class InstructionsHelper {
     static GHPoint getPointForOrientationCalculation(EdgeIteratorState edgeIteratorState, NodeAccess nodeAccess) {
         double tmpLat;
         double tmpLon;
-        PointList tmpWayGeo = edgeIteratorState.fetchWayGeometry(3);
+        PointList tmpWayGeo = edgeIteratorState.fetchWayGeometry(FetchMode.ALL);
         if (tmpWayGeo.getSize() <= 2) {
             tmpLat = nodeAccess.getLatitude(edgeIteratorState.getAdjNode());
             tmpLon = nodeAccess.getLongitude(edgeIteratorState.getAdjNode());
diff --git a/core/src/main/java/com/graphhopper/routing/Path.java b/core/src/main/java/com/graphhopper/routing/Path.java
index 281d60ab0..49c73c4e4 100644
--- a/core/src/main/java/com/graphhopper/routing/Path.java
+++ b/core/src/main/java/com/graphhopper/routing/Path.java
@@ -24,6 +24,7 @@ import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.EdgeIterator;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.PointList;
 
 import java.util.ArrayList;
@@ -281,7 +282,7 @@ public class Path {
         forEveryEdge(new EdgeVisitor() {
             @Override
             public void next(EdgeIteratorState eb, int index, int prevEdgeId) {
-                PointList pl = eb.fetchWayGeometry(2);
+                PointList pl = eb.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ);
                 for (int j = 0; j < pl.getSize(); j++) {
                     points.add(pl, j);
                 }
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/GraphModificationBuilder.java b/core/src/main/java/com/graphhopper/routing/querygraph/GraphModificationBuilder.java
index 65ef0021e..3208e8eee 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/GraphModificationBuilder.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/GraphModificationBuilder.java
@@ -23,10 +23,7 @@ import com.graphhopper.coll.GHIntObjectHashMap;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.index.QueryResult;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.GHUtility;
-import com.graphhopper.util.Helper;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 import com.graphhopper.util.shapes.GHPoint;
 import com.graphhopper.util.shapes.GHPoint3D;
 
@@ -91,14 +88,14 @@ class GraphModificationBuilder {
             boolean doReverse = base > closestEdge.getAdjNode();
             if (base == closestEdge.getAdjNode()) {
                 // check for special case #162 where adj == base and force direction via latitude comparison
-                PointList pl = closestEdge.fetchWayGeometry(0);
+                PointList pl = closestEdge.fetchWayGeometry(FetchMode.PILLAR_ONLY);
                 if (pl.size() > 1)
                     doReverse = pl.getLatitude(0) > pl.getLatitude(pl.size() - 1);
             }
 
             if (doReverse) {
                 closestEdge = closestEdge.detach(true);
-                PointList fullPL = closestEdge.fetchWayGeometry(3);
+                PointList fullPL = closestEdge.fetchWayGeometry(FetchMode.ALL);
                 res.setClosestEdge(closestEdge);
                 if (res.getSnappedPosition() == QueryResult.Position.PILLAR)
                     // ON pillar node
@@ -129,7 +126,7 @@ class GraphModificationBuilder {
             public boolean apply(int edgeId, List<QueryResult> results) {
                 // we can expect at least one entry in the results
                 EdgeIteratorState closestEdge = results.get(0).getClosestEdge();
-                final PointList fullPL = closestEdge.fetchWayGeometry(3);
+                final PointList fullPL = closestEdge.fetchWayGeometry(FetchMode.ALL);
                 int baseNode = closestEdge.getBaseNode();
                 Collections.sort(results, new Comparator<QueryResult>() {
                     @Override
@@ -222,7 +219,7 @@ class GraphModificationBuilder {
         if (!isPillar) {
             basePoints.add(currSnapped.lat, currSnapped.lon, currSnapped.ele);
         }
-        // basePoints must have at least the size of 2 to make sure fetchWayGeometry(3) returns at least 2
+        // basePoints must have at least the size of 2 to make sure fetchWayGeometry(FetchMode.ALL) returns at least 2
         assert basePoints.size() >= 2 : "basePoints must have at least two points";
 
         PointList baseReversePoints = basePoints.clone(true);
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
index 5c4b915e3..5b12e2faf 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/QueryGraph.java
@@ -152,7 +152,7 @@ public class QueryGraph implements Graph {
         for (int edgePos : edgePositions) {
             VirtualEdgeIteratorState edge = getVirtualEdge(virtNodeIDintern * 4 + edgePos);
 
-            PointList wayGeo = edge.fetchWayGeometry(3);
+            PointList wayGeo = edge.fetchWayGeometry(FetchMode.ALL);
             double edgeOrientation;
             if (incoming) {
                 int numWayPoints = wayGeo.getSize();
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIterator.java b/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIterator.java
index 4f1d11665..371b8422a 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIterator.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIterator.java
@@ -23,10 +23,7 @@ import com.graphhopper.routing.profiles.EnumEncodedValue;
 import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.routing.util.EdgeFilter;
 import com.graphhopper.storage.IntsRef;
-import com.graphhopper.util.CHEdgeIteratorState;
-import com.graphhopper.util.EdgeIterator;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 
 import java.util.List;
 
@@ -82,7 +79,7 @@ class VirtualEdgeIterator implements EdgeIterator, CHEdgeIteratorState {
     }
 
     @Override
-    public PointList fetchWayGeometry(int mode) {
+    public PointList fetchWayGeometry(FetchMode mode) {
         return getCurrentEdge().fetchWayGeometry(mode);
     }
 
diff --git a/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIteratorState.java b/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIteratorState.java
index 376e11c97..dc23f4ef0 100644
--- a/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIteratorState.java
+++ b/core/src/main/java/com/graphhopper/routing/querygraph/VirtualEdgeIteratorState.java
@@ -22,10 +22,7 @@ import com.graphhopper.routing.profiles.DecimalEncodedValue;
 import com.graphhopper.routing.profiles.EnumEncodedValue;
 import com.graphhopper.routing.profiles.IntEncodedValue;
 import com.graphhopper.storage.IntsRef;
-import com.graphhopper.util.CHEdgeIteratorState;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.GHUtility;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 
 /**
  * Creates an edge state decoupled from a graph where nodes, pointList, etc are kept in memory.
@@ -86,24 +83,24 @@ public class VirtualEdgeIteratorState implements EdgeIteratorState, CHEdgeIterat
     }
 
     @Override
-    public PointList fetchWayGeometry(int mode) {
+    public PointList fetchWayGeometry(FetchMode mode) {
         if (pointList.getSize() == 0)
             return PointList.EMPTY;
         // due to API we need to create a new instance per call!
-        if (mode == 4) {
+        if (mode == FetchMode.TOWER_ONLY) {
             if (pointList.getSize() < 3)
                 return pointList.clone(false);
             PointList towerNodes = new PointList(2, pointList.is3D());
             towerNodes.add(pointList, 0);
             towerNodes.add(pointList, pointList.getSize() - 1);
             return towerNodes;
-        } else if (mode == 3)
+        } else if (mode == FetchMode.ALL)
             return pointList.clone(false);
-        else if (mode == 1)
+        else if (mode == FetchMode.BASE_AND_PILLAR)
             return pointList.copy(0, pointList.getSize() - 1);
-        else if (mode == 2)
+        else if (mode == FetchMode.PILLAR_AND_ADJ)
             return pointList.copy(1, pointList.getSize());
-        else if (mode == 0) {
+        else if (mode == FetchMode.PILLAR_ONLY) {
             if (pointList.getSize() == 1)
                 return PointList.EMPTY;
             return pointList.copy(1, pointList.getSize() - 1);
diff --git a/core/src/main/java/com/graphhopper/routing/util/Bike2WeightFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/Bike2WeightFlagEncoder.java
index d05521619..97674fb23 100644
--- a/core/src/main/java/com/graphhopper/routing/util/Bike2WeightFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/Bike2WeightFlagEncoder.java
@@ -20,6 +20,7 @@ package com.graphhopper.routing.util;
 import com.graphhopper.reader.ReaderWay;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.PMap;
 import com.graphhopper.util.PointList;
 
@@ -53,7 +54,7 @@ public class Bike2WeightFlagEncoder extends BikeFlagEncoder {
 
     @Override
     public void applyWayTags(ReaderWay way, EdgeIteratorState edge) {
-        PointList pl = edge.fetchWayGeometry(3);
+        PointList pl = edge.fetchWayGeometry(FetchMode.ALL);
         if (!pl.is3D())
             throw new IllegalStateException(toString() + " requires elevation data to improve speed calculation based on it. Please enable it in config via e.g. graph.elevation.provider: srtm");
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/HikeFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/HikeFlagEncoder.java
index bb49faf35..7d8107c03 100644
--- a/core/src/main/java/com/graphhopper/routing/util/HikeFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/HikeFlagEncoder.java
@@ -20,10 +20,7 @@ package com.graphhopper.routing.util;
 import com.graphhopper.reader.ReaderWay;
 import com.graphhopper.routing.weighting.PriorityWeighting;
 import com.graphhopper.storage.IntsRef;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.Helper;
-import com.graphhopper.util.PMap;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 
 import java.util.TreeMap;
 
@@ -98,7 +95,7 @@ public class HikeFlagEncoder extends FootFlagEncoder {
 
     @Override
     public void applyWayTags(ReaderWay way, EdgeIteratorState edge) {
-        PointList pl = edge.fetchWayGeometry(3);
+        PointList pl = edge.fetchWayGeometry(FetchMode.ALL);
         if (!pl.is3D())
             return;
 
diff --git a/core/src/main/java/com/graphhopper/routing/util/WheelchairFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/WheelchairFlagEncoder.java
index 6ba53f312..190bcb103 100644
--- a/core/src/main/java/com/graphhopper/routing/util/WheelchairFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/WheelchairFlagEncoder.java
@@ -20,6 +20,7 @@ package com.graphhopper.routing.util;
 import com.graphhopper.reader.ReaderWay;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.PMap;
 import com.graphhopper.util.PointList;
 
@@ -216,7 +217,7 @@ public class WheelchairFlagEncoder extends FootFlagEncoder {
      */
     @Override
     public void applyWayTags(ReaderWay way, EdgeIteratorState edge) {
-        PointList pl = edge.fetchWayGeometry(3);
+        PointList pl = edge.fetchWayGeometry(FetchMode.ALL);
 
         double prevEle = pl.getElevation(0);
         double fullDist2D = edge.getDistance();
diff --git a/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java b/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
index 363b40f26..167e97d62 100644
--- a/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
+++ b/core/src/main/java/com/graphhopper/routing/weighting/AbstractWeighting.java
@@ -21,6 +21,7 @@ import com.graphhopper.routing.profiles.BooleanEncodedValue;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
 import com.graphhopper.routing.util.FlagEncoder;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 
 import static com.graphhopper.routing.weighting.TurnCostProvider.NO_TURN_COST_PROVIDER;
 import static com.graphhopper.util.Helper.isEmpty;
@@ -68,7 +69,7 @@ public abstract class AbstractWeighting implements Weighting {
         if (reverse && !edgeState.getReverse(accessEnc) || !reverse && !edgeState.get(accessEnc))
             throw new IllegalStateException("Calculating time should not require to read speed from edge in wrong direction. " +
                     "(" + edgeState.getBaseNode() + " - " + edgeState.getAdjNode() + ") "
-                    + edgeState.fetchWayGeometry(3) + ", dist: " + edgeState.getDistance() + " "
+                    + edgeState.fetchWayGeometry(FetchMode.ALL) + ", dist: " + edgeState.getDistance() + " "
                     + "Reverse:" + reverse + ", fwd:" + edgeState.get(accessEnc) + ", bwd:" + edgeState.getReverse(accessEnc) + ", fwd-speed: " + edgeState.get(avSpeedEnc) + ", bwd-speed: " + edgeState.getReverse(avSpeedEnc));
 
         double speed = reverse ? edgeState.getReverse(avSpeedEnc) : edgeState.get(avSpeedEnc);
diff --git a/core/src/main/java/com/graphhopper/storage/BaseGraph.java b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
index 3b0e2865f..e9c146dbc 100644
--- a/core/src/main/java/com/graphhopper/storage/BaseGraph.java
+++ b/core/src/main/java/com/graphhopper/storage/BaseGraph.java
@@ -540,7 +540,7 @@ class BaseGraph implements Graph {
         // copy the rest with higher level API
         to.setDistance(from.getDistance()).
                 setName(from.getName()).
-                setWayGeometry(from.fetchWayGeometry(0));
+                setWayGeometry(from.fetchWayGeometry(FetchMode.PILLAR_ONLY));
 
         return to;
     }
@@ -950,8 +950,8 @@ class BaseGraph implements Graph {
         return bytes;
     }
 
-    private PointList fetchWayGeometry_(long edgePointer, boolean reverse, int mode, int baseNode, int adjNode) {
-        if (mode == 4) {
+    private PointList fetchWayGeometry_(long edgePointer, boolean reverse, FetchMode mode, int baseNode, int adjNode) {
+        if (mode == FetchMode.TOWER_ONLY) {
             // no reverse handling required as adjNode and baseNode is already properly switched
             PointList pillarNodes = new PointList(2, nodeAccess.is3D());
             pillarNodes.add(nodeAccess, baseNode);
@@ -968,14 +968,14 @@ class BaseGraph implements Graph {
             geoRef += 4L;
             bytes = new byte[count * nodeAccess.getDimension() * 4];
             wayGeometry.getBytes(geoRef, bytes, bytes.length);
-        } else if (mode == 0)
+        } else if (mode == FetchMode.PILLAR_ONLY)
             return PointList.EMPTY;
 
-        PointList pillarNodes = new PointList(count + mode, nodeAccess.is3D());
+        PointList pillarNodes = new PointList(getPointListLength(count, mode), nodeAccess.is3D());
         if (reverse) {
-            if ((mode & 2) != 0)
+            if (mode == FetchMode.ALL || mode == FetchMode.PILLAR_AND_ADJ)
                 pillarNodes.add(nodeAccess, adjNode);
-        } else if ((mode & 1) != 0)
+        } else if (mode == FetchMode.ALL || mode == FetchMode.BASE_AND_PILLAR)
             pillarNodes.add(nodeAccess, baseNode);
 
         int index = 0;
@@ -993,16 +993,31 @@ class BaseGraph implements Graph {
         }
 
         if (reverse) {
-            if ((mode & 1) != 0)
+            if (mode == FetchMode.ALL || mode == FetchMode.BASE_AND_PILLAR)
                 pillarNodes.add(nodeAccess, baseNode);
 
             pillarNodes.reverse();
-        } else if ((mode & 2) != 0)
+        } else if (mode == FetchMode.ALL || mode == FetchMode.PILLAR_AND_ADJ)
             pillarNodes.add(nodeAccess, adjNode);
 
         return pillarNodes;
     }
 
+    static int getPointListLength(int pillarNodes, FetchMode mode) {
+        switch (mode) {
+            case TOWER_ONLY:
+                return 2;
+            case PILLAR_ONLY:
+                return pillarNodes;
+            case BASE_AND_PILLAR:
+            case PILLAR_AND_ADJ:
+                return pillarNodes + 1;
+            case ALL:
+                return pillarNodes + 2;
+        }
+        throw new IllegalArgumentException("Mode isn't handled " + mode);
+    }
+
     private void setName(long edgePointer, String name) {
         int stringIndexRef = (int) stringIndex.add(Collections.singletonMap(STRING_IDX_NAME_KEY, name));
         if (stringIndexRef < 0)
@@ -1358,7 +1373,7 @@ class BaseGraph implements Graph {
         }
 
         @Override
-        public PointList fetchWayGeometry(int mode) {
+        public PointList fetchWayGeometry(FetchMode mode) {
             return baseGraph.fetchWayGeometry_(edgePointer, reverse, mode, getBaseNode(), getAdjNode());
         }
 
diff --git a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
index 1ecc12287..65d6d4956 100644
--- a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
+++ b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
@@ -843,13 +843,6 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
                 throw new IllegalStateException("Method " + methodName + " only for shortcuts " + getEdge());
         }
 
-        private void checkShortcutAndEdgeBased(String method) {
-            checkShortcut(true, method);
-            if (!chProfile.isEdgeBased()) {
-                throw new IllegalStateException("Method " + method + " only allowed when CH graph is configured for edge based traversal");
-            }
-        }
-
         @Override
         public final String getName() {
             checkShortcut(false, "getName");
@@ -863,7 +856,7 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
         }
 
         @Override
-        public final PointList fetchWayGeometry(int mode) {
+        public final PointList fetchWayGeometry(FetchMode mode) {
             checkShortcut(false, "fetchWayGeometry");
             return edgeIterable.fetchWayGeometry(mode);
         }
diff --git a/core/src/main/java/com/graphhopper/storage/GraphEdgeIdFinder.java b/core/src/main/java/com/graphhopper/storage/GraphEdgeIdFinder.java
index c6a4094b8..7e95a38ed 100644
--- a/core/src/main/java/com/graphhopper/storage/GraphEdgeIdFinder.java
+++ b/core/src/main/java/com/graphhopper/storage/GraphEdgeIdFinder.java
@@ -22,10 +22,7 @@ import com.graphhopper.coll.GHIntHashSet;
 import com.graphhopper.routing.util.EdgeFilter;
 import com.graphhopper.routing.util.HintsMap;
 import com.graphhopper.storage.index.LocationIndex;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.GHUtility;
-import com.graphhopper.util.Parameters;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 import com.graphhopper.util.shapes.Polygon;
 import com.graphhopper.util.shapes.*;
 import org.locationtech.jts.algorithm.RectangleLineIntersector;
@@ -60,7 +57,7 @@ public class GraphEdgeIdFinder {
         locationIndex.query(shape.getBounds(), new LocationIndex.EdgeVisitor(graph.createEdgeExplorer(filter)) {
             @Override
             public void onEdge(EdgeIteratorState edge, int nodeA, int nodeB) {
-                if (shape.intersects(edge.fetchWayGeometry(3).makeImmutable()))
+                if (shape.intersects(edge.fetchWayGeometry(FetchMode.ALL).makeImmutable()))
                     edgeIds.add(edge.getEdge());
             }
         });
@@ -77,7 +74,7 @@ public class GraphEdgeIdFinder {
             locationIndex.query(BBox.fromEnvelope(geometry.getEnvelopeInternal()), new LocationIndex.EdgeVisitor(graph.createEdgeExplorer(filter)) {
                 @Override
                 public void onEdge(EdgeIteratorState edge, int nodeA, int nodeB) {
-                    if (geometry.intersects(edge.fetchWayGeometry(3).toLineString(false)))
+                    if (geometry.intersects(edge.fetchWayGeometry(FetchMode.ALL).toLineString(false)))
                         edgeIds.add(edge.getEdge());
                 }
             });
@@ -221,7 +218,7 @@ public class GraphEdgeIdFinder {
                 Shape shape = blockedShapes.get(shapeIdx);
                 if (shape.getBounds().intersects(bbox)) {
                     if (pointList == null)
-                        pointList = edgeState.fetchWayGeometry(3).makeImmutable();
+                        pointList = edgeState.fetchWayGeometry(FetchMode.ALL).makeImmutable();
                     if (shape.intersects(pointList))
                         return true;
                 }
diff --git a/core/src/main/java/com/graphhopper/storage/index/LocationIndexTree.java b/core/src/main/java/com/graphhopper/storage/index/LocationIndexTree.java
index 9b98cad30..fd0a60ba3 100644
--- a/core/src/main/java/com/graphhopper/storage/index/LocationIndexTree.java
+++ b/core/src/main/java/com/graphhopper/storage/index/LocationIndexTree.java
@@ -860,7 +860,7 @@ public class LocationIndexTree implements LocationIndex {
                     double lon1 = nodeAccess.getLongitude(nodeA);
                     double lat2;
                     double lon2;
-                    PointList points = allIter.fetchWayGeometry(0);
+                    PointList points = allIter.fetchWayGeometry(FetchMode.PILLAR_ONLY);
                     int len = points.getSize();
                     for (int i = 0; i < len; i++) {
                         lat2 = points.getLatitude(i);
@@ -1074,7 +1074,7 @@ public class LocationIndexTree implements LocationIndex {
             double tmpLat = currLat;
             double tmpLon = currLon;
             double tmpNormedDist;
-            PointList pointList = currEdge.fetchWayGeometry(2);
+            PointList pointList = currEdge.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ);
             int len = pointList.getSize();
             for (int pointIndex = 0; pointIndex < len; pointIndex++) {
                 double wayLat = pointList.getLatitude(pointIndex);
diff --git a/core/src/main/java/com/graphhopper/storage/index/QueryResult.java b/core/src/main/java/com/graphhopper/storage/index/QueryResult.java
index df930677d..73a9afbce 100644
--- a/core/src/main/java/com/graphhopper/storage/index/QueryResult.java
+++ b/core/src/main/java/com/graphhopper/storage/index/QueryResult.java
@@ -21,6 +21,7 @@ import com.graphhopper.routing.querygraph.QueryGraph;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.util.DistanceCalc;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.PointList;
 import com.graphhopper.util.shapes.GHPoint;
 import com.graphhopper.util.shapes.GHPoint3D;
@@ -144,7 +145,7 @@ public class QueryResult {
         if (snappedPoint != null)
             throw new IllegalStateException("Calculate snapped point only once");
 
-        PointList fullPL = getClosestEdge().fetchWayGeometry(3);
+        PointList fullPL = getClosestEdge().fetchWayGeometry(FetchMode.ALL);
         double tmpLat = fullPL.getLatitude(wayIndex);
         double tmpLon = fullPL.getLongitude(wayIndex);
         double tmpEle = fullPL.getElevation(wayIndex);
diff --git a/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java b/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
index c0ba8f97e..27cbd0804 100644
--- a/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
+++ b/core/src/main/java/com/graphhopper/util/EdgeIteratorState.java
@@ -106,16 +106,10 @@ public interface EdgeIteratorState {
      * (docs/core/low-level-api.md#what-are-pillar-and-tower-nodes). Updates to the returned list
      * are not reflected in the graph, for that you've to use setWayGeometry.
      *
-     * @param mode can be <ul>
-     *             <li>0 = only pillar nodes, no tower nodes</li>
-     *             <li>1 = inclusive the base tower node only</li>
-     *             <li>2 = inclusive the adjacent tower node only</li>
-     *             <li>3 = inclusive the base and adjacent tower node</li>
-     *             <li>4 = only tower nodes, no pillar nodes</li>
-     *             </ul>
-     * @return pillar nodes
+     * @param mode {@link FetchMode}
+     * @return the pillar and/or tower nodes depending on the mode.
      */
-    PointList fetchWayGeometry(int mode);
+    PointList fetchWayGeometry(FetchMode mode);
 
     /**
      * @param list is a sorted collection of coordinates between the base node and the current adjacent node. Specify
diff --git a/core/src/main/java/com/graphhopper/util/FetchMode.java b/core/src/main/java/com/graphhopper/util/FetchMode.java
new file mode 100644
index 000000000..a1d6a945e
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/util/FetchMode.java
@@ -0,0 +1,9 @@
+package com.graphhopper.util;
+
+/**
+ * This enum is used to specify which nodes should be included in the PointList when calling
+ * {@link EdgeIteratorState#fetchWayGeometry(FetchMode)}. See also docs/core/low-level-api.md
+ */
+public enum FetchMode {
+    TOWER_ONLY, PILLAR_ONLY, BASE_AND_PILLAR, PILLAR_AND_ADJ, ALL;
+}
diff --git a/core/src/main/java/com/graphhopper/util/GHUtility.java b/core/src/main/java/com/graphhopper/util/GHUtility.java
index e189ae6e3..6848b4550 100644
--- a/core/src/main/java/com/graphhopper/util/GHUtility.java
+++ b/core/src/main/java/com/graphhopper/util/GHUtility.java
@@ -289,7 +289,7 @@ public class GHUtility {
         String str = nodeId + ":" + na.getLatitude(nodeId) + "," + na.getLongitude(nodeId) + "\n";
         while (iter.next()) {
             str += "  ->" + iter.getAdjNode() + " (" + iter.getDistance() + ") pillars:"
-                    + iter.fetchWayGeometry(0).getSize() + ", edgeId:" + iter.getEdge()
+                    + iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).getSize() + ", edgeId:" + iter.getEdge()
                     + "\t" + BitUtil.BIG.toBitString(iter.getFlags().ints[0], 8) + "\n";
         }
         return str;
@@ -526,7 +526,7 @@ public class GHUtility {
             }
 
             @Override
-            public PointList fetchWayGeometry(int type) {
+            public PointList fetchWayGeometry(FetchMode type) {
                 return Helper.createPointList(0, 2, 6, 4);
             }
 
@@ -639,7 +639,7 @@ public class GHUtility {
         na.setNode(node, lat, lon);
         EdgeIterator iter = g.createEdgeExplorer().setBaseNode(node);
         while (iter.next()) {
-            iter.setDistance(iter.fetchWayGeometry(3).calcDistance(DIST_EARTH));
+            iter.setDistance(iter.fetchWayGeometry(FetchMode.ALL).calcDistance(DIST_EARTH));
             // System.out.println(node + "->" + adj + ": " + iter.getDistance());
         }
     }
@@ -731,7 +731,7 @@ public class GHUtility {
         }
 
         @Override
-        public PointList fetchWayGeometry(int type) {
+        public PointList fetchWayGeometry(FetchMode type) {
             throw new UnsupportedOperationException("Not supported. Edge is empty.");
         }
 
@@ -969,7 +969,7 @@ public class GHUtility {
     }
 
     public static BBox createBBox(EdgeIteratorState edgeState) {
-        PointList towerNodes = edgeState.fetchWayGeometry(4);
+        PointList towerNodes = edgeState.fetchWayGeometry(FetchMode.TOWER_ONLY);
         int secondIndex = towerNodes.getSize() == 1 ? 0 : 1;
         return BBox.fromPoints(towerNodes.getLatitude(0), towerNodes.getLongitude(0),
                 towerNodes.getLatitude(secondIndex), towerNodes.getLongitude(secondIndex));
diff --git a/core/src/main/java/com/graphhopper/util/details/PathDetailsFromEdges.java b/core/src/main/java/com/graphhopper/util/details/PathDetailsFromEdges.java
index 0cf9a9b41..0af7a56f5 100644
--- a/core/src/main/java/com/graphhopper/util/details/PathDetailsFromEdges.java
+++ b/core/src/main/java/com/graphhopper/util/details/PathDetailsFromEdges.java
@@ -21,6 +21,7 @@ import com.graphhopper.routing.Path;
 import com.graphhopper.routing.profiles.EncodedValueLookup;
 import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -84,7 +85,7 @@ public class PathDetailsFromEdges implements Path.EdgeVisitor {
                 calc.startInterval(lastIndex);
             }
         }
-        lastIndex += edge.fetchWayGeometry(2).size();
+        lastIndex += edge.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ).size();
     }
 
     @Override
diff --git a/docs/core/create-new-flagencoder.md b/docs/core/create-new-flagencoder.md
index 3193d39b6..e4b9193b0 100644
--- a/docs/core/create-new-flagencoder.md
+++ b/docs/core/create-new-flagencoder.md
@@ -29,7 +29,7 @@ See Bike2WeightFlagEncoder for an example that uses different weights: slower sp
 ## Elevation
 
 To incorporate or precalculate values based on the elevation data you can hook into applyWayTags
-and call edge.fetchWayGeometry(3) or again, see Bike2WeightFlagEncoder.
+and call edge.fetchWayGeometry(FetchMode.ALL) or again, see Bike2WeightFlagEncoder.
 
 ## Add to the core
 
diff --git a/docs/core/low-level-api.md b/docs/core/low-level-api.md
index 4cada3cae..4b4ac4b21 100644
--- a/docs/core/low-level-api.md
+++ b/docs/core/low-level-api.md
@@ -12,7 +12,7 @@ only a sub-set of them are actual junctions, which are the ones we are intereste
 Those junction nodes (and end-standing nodes of dead alleys) we call *tower nodes* which also 
 have a graphhopper node ID associated, going from 0 to graph.getNodes(). 
 The helper nodes between the junctions we call 'pillar nodes' which can be fetched via
-`edgeIteratorState.fetchWayGeometry(0)`. Avoiding the traversal of pillar nodes while routing makes 
+`edgeIteratorState.fetchWayGeometry(FetchMode.PILLAR_ONLY)`. Avoiding the traversal of pillar nodes while routing makes 
 routing a lot faster (~8 times).
 
 That splitting into pillar and tower nodes is also the reason why there can't be a unique mapping from 
diff --git a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/TripFromLabel.java b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/TripFromLabel.java
index 6d33ac6e4..1702e700b 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/TripFromLabel.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/TripFromLabel.java
@@ -387,8 +387,8 @@ class TripFromLabel {
         List<Coordinate> coordinates = new ArrayList<>();
         final Iterator<Label.Transition> iterator = transitions.iterator();
         iterator.next();
-        coordinates.addAll(toCoordinateArray(iterator.next().edge.edgeIteratorState.fetchWayGeometry(3)));
-        iterator.forEachRemaining(transition -> coordinates.addAll(toCoordinateArray(transition.edge.edgeIteratorState.fetchWayGeometry(2))));
+        coordinates.addAll(toCoordinateArray(iterator.next().edge.edgeIteratorState.fetchWayGeometry(FetchMode.ALL)));
+        iterator.forEachRemaining(transition -> coordinates.addAll(toCoordinateArray(transition.edge.edgeIteratorState.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ))));
         return geometryFactory.createLineString(coordinates.toArray(new Coordinate[coordinates.size()]));
     }
 
diff --git a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
index 8435e16e2..367e57487 100644
--- a/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
+++ b/reader-gtfs/src/main/java/com/graphhopper/reader/gtfs/WrapperGraph.java
@@ -33,10 +33,7 @@ import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.storage.TurnCostStorage;
-import com.graphhopper.util.EdgeExplorer;
-import com.graphhopper.util.EdgeIterator;
-import com.graphhopper.util.EdgeIteratorState;
-import com.graphhopper.util.PointList;
+import com.graphhopper.util.*;
 import com.graphhopper.util.shapes.BBox;
 
 import java.util.ArrayList;
@@ -62,7 +59,7 @@ public class WrapperGraph implements Graph {
             }
             extraEdgesBySource.put(extraEdge.getBaseNode(), extraEdge);
             extraEdgesByDestination.put(extraEdge.getAdjNode(), new VirtualEdgeIteratorState(extraEdge.getOriginalEdgeKey(), extraEdge.getEdge(), extraEdge.getAdjNode(),
-                    extraEdge.getBaseNode(), extraEdge.getDistance(), extraEdge.getFlags(), extraEdge.getName(), extraEdge.fetchWayGeometry(3), true));
+                    extraEdge.getBaseNode(), extraEdge.getDistance(), extraEdge.getFlags(), extraEdge.getName(), extraEdge.fetchWayGeometry(FetchMode.ALL), true));
         }
     }
 
@@ -157,7 +154,7 @@ public class WrapperGraph implements Graph {
             }
 
             @Override
-            public PointList fetchWayGeometry(int mode) {
+            public PointList fetchWayGeometry(FetchMode mode) {
                 throw new UnsupportedOperationException();
             }
 
@@ -355,7 +352,7 @@ public class WrapperGraph implements Graph {
                     }
 
                     @Override
-                    public PointList fetchWayGeometry(int mode) {
+                    public PointList fetchWayGeometry(FetchMode mode) {
                         return current.fetchWayGeometry(mode);
                     }
 
diff --git a/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java b/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
index d3bc6e076..6276150b0 100644
--- a/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
+++ b/tools/src/main/java/com/graphhopper/ui/MiniGraphUI.java
@@ -38,6 +38,7 @@ import com.graphhopper.routing.weighting.Weighting;
 import com.graphhopper.storage.*;
 import com.graphhopper.storage.index.LocationIndexTree;
 import com.graphhopper.storage.index.QueryResult;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.PMap;
 import com.graphhopper.util.Parameters.Algorithms;
 import com.graphhopper.util.PointList;
@@ -280,7 +281,7 @@ public class MiniGraphUI {
                     boolean fwd = edge.get(accessEnc);
                     boolean bwd = edge.getReverse(accessEnc);
                     float width = speed > 90 ? 1f : 0.8f;
-                    PointList pl = edge.fetchWayGeometry(3);
+                    PointList pl = edge.fetchWayGeometry(FetchMode.ALL);
                     for (int i = 1; i < pl.size(); i++) {
                         if (fwd && !bwd) {
                             mg.plotDirectedEdge(g2, pl.getLatitude(i - 1), pl.getLongitude(i - 1), pl.getLatitude(i), pl.getLongitude(i), width);
diff --git a/web-bundle/src/main/java/com/graphhopper/resources/MVTResource.java b/web-bundle/src/main/java/com/graphhopper/resources/MVTResource.java
index a060ef5b5..24364dd61 100644
--- a/web-bundle/src/main/java/com/graphhopper/resources/MVTResource.java
+++ b/web-bundle/src/main/java/com/graphhopper/resources/MVTResource.java
@@ -99,7 +99,7 @@ public class MVTResource {
                 LineString lineString;
                 RoadClass rc = edge.get(roadClassEnc);
                 if (zInfo >= 14) {
-                    PointList pl = edge.fetchWayGeometry(3);
+                    PointList pl = edge.fetchWayGeometry(FetchMode.ALL);
                     lineString = pl.toLineString(false);
                 } else if (rc == RoadClass.MOTORWAY
                         || zInfo > 10 && (rc == RoadClass.PRIMARY || rc == RoadClass.TRUNK)


Test patch:
diff --git a/core/src/test/java/com/graphhopper/reader/dem/BridgeElevationInterpolatorTest.java b/core/src/test/java/com/graphhopper/reader/dem/BridgeElevationInterpolatorTest.java
index 0871a4199..41332be02 100644
--- a/core/src/test/java/com/graphhopper/reader/dem/BridgeElevationInterpolatorTest.java
+++ b/core/src/test/java/com/graphhopper/reader/dem/BridgeElevationInterpolatorTest.java
@@ -23,6 +23,7 @@ import com.graphhopper.routing.profiles.RoadEnvironment;
 import com.graphhopper.storage.IntsRef;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.Helper;
 import com.graphhopper.util.PointList;
 import org.junit.Test;
@@ -121,7 +122,7 @@ public class BridgeElevationInterpolatorTest extends EdgeElevationInterpolatorTe
         assertEquals(10, na.getElevation(8), PRECISION);
         assertEquals(0, na.getElevation(9), PRECISION);
 
-        final PointList edge17PointList = edge17.fetchWayGeometry(3);
+        final PointList edge17PointList = edge17.fetchWayGeometry(FetchMode.ALL);
         assertEquals(6, edge17PointList.size());
         assertEquals(10, edge17PointList.getEle(0), PRECISION);
         assertEquals(12, edge17PointList.getEle(1), PRECISION);
diff --git a/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java b/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
index d1ffee626..529f558c7 100644
--- a/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
+++ b/core/src/test/java/com/graphhopper/routing/querygraph/QueryGraphTest.java
@@ -176,11 +176,11 @@ public class QueryGraphTest {
 
         QueryGraph queryGraph = QueryGraph.lookup(g, qr);
         EdgeIteratorState state = GHUtility.getEdge(queryGraph, 0, 1);
-        assertEquals(4, state.fetchWayGeometry(3).size());
+        assertEquals(4, state.fetchWayGeometry(FetchMode.ALL).size());
 
         //  fetch virtual edge and check way geometry
         state = GHUtility.getEdge(queryGraph, 4, 3);
-        assertEquals(2, state.fetchWayGeometry(3).size());
+        assertEquals(2, state.fetchWayGeometry(FetchMode.ALL).size());
 
         // now we actually test the edges at the real tower nodes (virtual ones should be added and some real ones removed)
         assertEquals("[1->4, 1 1-0]", ((VirtualEdgeIterator) queryGraph.createEdgeExplorer().setBaseNode(1)).getEdges().toString());
@@ -415,7 +415,7 @@ public class QueryGraphTest {
         EdgeIteratorState edge = GHUtility.getEdge(g, base, adj);
         if (edge == null)
             throw new IllegalStateException("edge " + base + "-" + adj + " not found");
-        return edge.fetchWayGeometry(3);
+        return edge.fetchWayGeometry(FetchMode.ALL);
     }
 
     public QueryResult createLocationResult(double lat, double lon,
@@ -677,19 +677,19 @@ public class QueryGraphTest {
 
         assertTrue(iter.next());
         assertEquals(0, iter.getAdjNode());
-        assertEquals(1, iter.fetchWayGeometry(0).size());
-        assertEquals(2, iter.fetchWayGeometry(1).size());
-        assertEquals(2, iter.fetchWayGeometry(2).size());
-        assertEquals(3, iter.fetchWayGeometry(3).size());
-        assertEquals(Helper.createPointList(0.15, 0.15, 0.1, 0.1, 0.0, 0.0), iter.fetchWayGeometry(3));
+        assertEquals(1, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ).size());
+        assertEquals(3, iter.fetchWayGeometry(FetchMode.ALL).size());
+        assertEquals(Helper.createPointList(0.15, 0.15, 0.1, 0.1, 0.0, 0.0), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertTrue(iter.next());
         assertEquals(1, iter.getAdjNode());
-        assertEquals(1, iter.fetchWayGeometry(0).size());
-        assertEquals(2, iter.fetchWayGeometry(1).size());
-        assertEquals(2, iter.fetchWayGeometry(2).size());
-        assertEquals(3, iter.fetchWayGeometry(3).size());
-        assertEquals(Helper.createPointList(0.15, 0.15, 0.2, 0.2, 0.3, 0.3), iter.fetchWayGeometry(3));
+        assertEquals(1, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ).size());
+        assertEquals(3, iter.fetchWayGeometry(FetchMode.ALL).size());
+        assertEquals(Helper.createPointList(0.15, 0.15, 0.2, 0.2, 0.3, 0.3), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertFalse(iter.next());
     }
@@ -718,19 +718,19 @@ public class QueryGraphTest {
 
         assertTrue(iter.next());
         assertEquals(0, iter.getAdjNode());
-        assertEquals(1, iter.fetchWayGeometry(0).size());
-        assertEquals(2, iter.fetchWayGeometry(1).size());
-        assertEquals(2, iter.fetchWayGeometry(2).size());
-        assertEquals(3, iter.fetchWayGeometry(3).size());
-        assertEquals(Helper.createPointList(0.2, 0.2, 0.1, 0.1, 0.0, 0.0), iter.fetchWayGeometry(3));
+        assertEquals(1, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ).size());
+        assertEquals(3, iter.fetchWayGeometry(FetchMode.ALL).size());
+        assertEquals(Helper.createPointList(0.2, 0.2, 0.1, 0.1, 0.0, 0.0), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertTrue(iter.next());
         assertEquals(1, iter.getAdjNode());
-        assertEquals(0, iter.fetchWayGeometry(0).size());
-        assertEquals(1, iter.fetchWayGeometry(1).size());
-        assertEquals(1, iter.fetchWayGeometry(2).size());
-        assertEquals(2, iter.fetchWayGeometry(3).size());
-        assertEquals(Helper.createPointList(0.2, 0.2, 0.5, 0.1), iter.fetchWayGeometry(3));
+        assertEquals(0, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).size());
+        assertEquals(1, iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR).size());
+        assertEquals(1, iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ).size());
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.ALL).size());
+        assertEquals(Helper.createPointList(0.2, 0.2, 0.5, 0.1), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertFalse(iter.next());
     }
diff --git a/core/src/test/java/com/graphhopper/routing/util/NameSimilarityEdgeFilterTest.java b/core/src/test/java/com/graphhopper/routing/util/NameSimilarityEdgeFilterTest.java
index 6adc8f079..f12f10c99 100644
--- a/core/src/test/java/com/graphhopper/routing/util/NameSimilarityEdgeFilterTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/NameSimilarityEdgeFilterTest.java
@@ -21,6 +21,7 @@ import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphBuilder;
 import com.graphhopper.storage.NodeAccess;
 import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.FetchMode;
 import com.graphhopper.util.GHUtility;
 import com.graphhopper.util.PointList;
 import com.graphhopper.util.shapes.GHPoint;
@@ -257,7 +258,7 @@ public class NameSimilarityEdgeFilterTest {
             }
 
             @Override
-            public PointList fetchWayGeometry(int type) {
+            public PointList fetchWayGeometry(FetchMode type) {
                 PointList list = new PointList();
                 list.add(basePoint);
                 return list;
diff --git a/core/src/test/java/com/graphhopper/storage/AbstractGraphStorageTester.java b/core/src/test/java/com/graphhopper/storage/AbstractGraphStorageTester.java
index ef84dd562..5d6e50f7c 100644
--- a/core/src/test/java/com/graphhopper/storage/AbstractGraphStorageTester.java
+++ b/core/src/test/java/com/graphhopper/storage/AbstractGraphStorageTester.java
@@ -288,7 +288,7 @@ public abstract class AbstractGraphStorageTester {
         assertEquals(edge.getName(), newEdge.getName());
         assertEquals(edge.getDistance(), newEdge.getDistance(), 1e-7);
         assertEquals(edge.getFlags(), newEdge.getFlags());
-        assertEquals(edge.fetchWayGeometry(0), newEdge.fetchWayGeometry(0));
+        assertEquals(edge.fetchWayGeometry(FetchMode.PILLAR_ONLY), newEdge.fetchWayGeometry(FetchMode.PILLAR_ONLY));
     }
 
     @Test
@@ -620,11 +620,11 @@ public abstract class AbstractGraphStorageTester {
         EdgeIterator iter = carAllExplorer.setBaseNode(id9);
         assertTrue(iter.next());
         assertEquals(id12, iter.getAdjNode());
-        assertEquals(2, iter.fetchWayGeometry(0).getLongitude(0), 1e-7);
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLongitude(0), 1e-7);
 
         assertTrue(iter.next());
         assertEquals(id11, iter.getAdjNode());
-        assertEquals(2, iter.fetchWayGeometry(0).getLongitude(0), 1e-7);
+        assertEquals(2, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLongitude(0), 1e-7);
     }
 
     @Test
@@ -843,33 +843,33 @@ public abstract class AbstractGraphStorageTester {
         EdgeIterator iter = carAllExplorer.setBaseNode(0);
         assertTrue(iter.next());
         assertEquals(14, iter.getAdjNode());
-        assertPList(Helper.createPointList(1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(0));
-        assertPList(Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(1));
-        assertPList(Helper.createPointList(1, 11, 1, 12, 1, 13.0, 0.14, 0.14), iter.fetchWayGeometry(2));
-        assertPList(Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0, 0.14, 0.14), iter.fetchWayGeometry(3));
+        assertPList(Helper.createPointList(1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
+        assertPList(Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0), iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR));
+        assertPList(Helper.createPointList(1, 11, 1, 12, 1, 13.0, 0.14, 0.14), iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ));
+        assertPList(Helper.createPointList(0.01, 0.01, 1, 11, 1, 12, 1, 13.0, 0.14, 0.14), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertTrue(iter.next());
         assertEquals(4, iter.getAdjNode());
-        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(0));
-        assertPList(Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(1));
-        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(2));
-        assertPList(Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(3));
+        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
+        assertPList(Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR));
+        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ));
+        assertPList(Helper.createPointList(0.01, 0.01, 1, 1, 1, 2, 1, 3, 0.4, 0.4), iter.fetchWayGeometry(FetchMode.ALL));
 
         assertFalse(iter.next());
 
         iter = carOutExplorer.setBaseNode(0);
         assertTrue(iter.next());
         assertEquals(4, iter.getAdjNode());
-        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(0));
+        assertPList(Helper.createPointList(1, 1, 1, 2, 1, 3), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
         assertFalse(iter.next());
 
         iter = carInExplorer.setBaseNode(10);
         assertTrue(iter.next());
         assertEquals(4, iter.getAdjNode());
-        assertPList(Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(0));
-        assertPList(Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(1));
-        assertPList(Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4), iter.fetchWayGeometry(2));
-        assertPList(Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4), iter.fetchWayGeometry(3));
+        assertPList(Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
+        assertPList(Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5), iter.fetchWayGeometry(FetchMode.BASE_AND_PILLAR));
+        assertPList(Helper.createPointList(1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4), iter.fetchWayGeometry(FetchMode.PILLAR_AND_ADJ));
+        assertPList(Helper.createPointList(0.99, 0.99, 1, 9, 1, 8, 1, 7, 1, 6, 1, 5, 0.4, 0.4), iter.fetchWayGeometry(FetchMode.ALL));
         assertFalse(iter.next());
     }
 
@@ -1040,9 +1040,9 @@ public abstract class AbstractGraphStorageTester {
         assertEquals(100, na.getEle(1), 1e-1);
 
         graph.edge(0, 1).setWayGeometry(Helper.createPointList3D(10, 27, 72, 11, 20, 1));
-        assertEquals(Helper.createPointList3D(10, 27, 72, 11, 20, 1), GHUtility.getEdge(graph, 0, 1).fetchWayGeometry(0));
-        assertEquals(Helper.createPointList3D(10, 20, -10, 10, 27, 72, 11, 20, 1, 11, 2, 100), GHUtility.getEdge(graph, 0, 1).fetchWayGeometry(3));
-        assertEquals(Helper.createPointList3D(11, 2, 100, 11, 20, 1, 10, 27, 72, 10, 20, -10), GHUtility.getEdge(graph, 1, 0).fetchWayGeometry(3));
+        assertEquals(Helper.createPointList3D(10, 27, 72, 11, 20, 1), GHUtility.getEdge(graph, 0, 1).fetchWayGeometry(FetchMode.PILLAR_ONLY));
+        assertEquals(Helper.createPointList3D(10, 20, -10, 10, 27, 72, 11, 20, 1, 11, 2, 100), GHUtility.getEdge(graph, 0, 1).fetchWayGeometry(FetchMode.ALL));
+        assertEquals(Helper.createPointList3D(11, 2, 100, 11, 20, 1, 10, 27, 72, 10, 20, -10), GHUtility.getEdge(graph, 1, 0).fetchWayGeometry(FetchMode.ALL));
     }
 
     @Test
@@ -1091,14 +1091,14 @@ public abstract class AbstractGraphStorageTester {
         iter.next();
         EdgeIteratorState edgeState02 = iter.detach(false);
         assertEquals(2, iter.getAdjNode());
-        assertEquals(1, edgeState02.fetchWayGeometry(0).getLatitude(0), 1e-1);
+        assertEquals(1, edgeState02.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLatitude(0), 1e-1);
         assertEquals(2, edgeState02.getAdjNode());
         assertTrue(edgeState02.get(carAccessEnc));
 
         EdgeIteratorState edgeState20 = iter.detach(true);
         assertEquals(0, edgeState20.getAdjNode());
         assertEquals(2, edgeState20.getBaseNode());
-        assertEquals(3, edgeState20.fetchWayGeometry(0).getLatitude(0), 1e-1);
+        assertEquals(3, edgeState20.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLatitude(0), 1e-1);
         assertFalse(edgeState20.get(carAccessEnc));
         assertEquals(GHUtility.getEdge(graph, 0, 2).getFlags(), edgeState02.getFlags());
         assertEquals(GHUtility.getEdge(graph, 2, 0).getFlags(), edgeState20.getFlags());
@@ -1108,9 +1108,9 @@ public abstract class AbstractGraphStorageTester {
         assertEquals(2, edgeState02.getAdjNode());
         assertEquals(2, edgeState20.getBaseNode());
 
-        assertEquals(0, iter.fetchWayGeometry(0).size());
-        assertEquals(1, edgeState02.fetchWayGeometry(0).getLatitude(0), 1e-1);
-        assertEquals(3, edgeState20.fetchWayGeometry(0).getLatitude(0), 1e-1);
+        assertEquals(0, iter.fetchWayGeometry(FetchMode.PILLAR_ONLY).size());
+        assertEquals(1, edgeState02.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLatitude(0), 1e-1);
+        assertEquals(3, edgeState20.fetchWayGeometry(FetchMode.PILLAR_ONLY).getLatitude(0), 1e-1);
 
         // #162 a directed self referencing edge should be able to reverse its state too
         GHUtility.setProperties(graph.edge(3, 3, 2, true), carEncoder, 10, true, false);
diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
index 7b9d7c7bc..d6639ea46 100644
--- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
+++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageTest.java
@@ -31,6 +31,7 @@ import java.io.IOException;
 import java.util.Collections;
 
 import static com.graphhopper.util.EdgeIteratorState.REVERSE_STATE;
+import static com.graphhopper.util.FetchMode.*;
 import static org.junit.Assert.*;
 
 /**
@@ -130,14 +131,14 @@ public class GraphHopperStorageTest extends AbstractGraphStorageTester {
 
         EdgeIterator iter = explorer.setBaseNode(0);
         assertTrue(iter.next());
-        assertEquals(Helper.createPointList3D(3.5, 4.5, 0, 5, 6, 0), iter.fetchWayGeometry(0));
+        assertEquals(Helper.createPointList3D(3.5, 4.5, 0, 5, 6, 0), iter.fetchWayGeometry(PILLAR_ONLY));
 
         assertTrue(iter.next());
-        assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(0));
-        assertEquals(Helper.createPointList3D(10, 10, 0, 1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(1));
-        assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0, 11, 20, 1), iter.fetchWayGeometry(2));
-        assertEquals(Helper.createPointList3D(10, 10, 0, 11, 20, 1), iter.fetchWayGeometry(4));
-        assertEquals(Helper.createPointList3D(11, 20, 1, 10, 10, 0), iter.detach(true).fetchWayGeometry(4));
+        assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(PILLAR_ONLY));
+        assertEquals(Helper.createPointList3D(10, 10, 0, 1.5, 1, 0, 2, 3, 0), iter.fetchWayGeometry(BASE_AND_PILLAR));
+        assertEquals(Helper.createPointList3D(1.5, 1, 0, 2, 3, 0, 11, 20, 1), iter.fetchWayGeometry(PILLAR_AND_ADJ));
+        assertEquals(Helper.createPointList3D(10, 10, 0, 11, 20, 1), iter.fetchWayGeometry(TOWER_ONLY));
+        assertEquals(Helper.createPointList3D(11, 20, 1, 10, 10, 0), iter.detach(true).fetchWayGeometry(TOWER_ONLY));
 
         assertEquals(11, na.getLatitude(1), 1e-2);
         assertEquals(20, na.getLongitude(1), 1e-2);
@@ -151,9 +152,9 @@ public class GraphHopperStorageTest extends AbstractGraphStorageTester {
         assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));
 
         EdgeIteratorState eib = GHUtility.getEdge(g, 1, 2);
-        assertEquals(Helper.createPointList3D(), eib.fetchWayGeometry(0));
-        assertEquals(Helper.createPointList3D(11, 20, 1), eib.fetchWayGeometry(1));
-        assertEquals(Helper.createPointList3D(12, 12, 0.4), eib.fetchWayGeometry(2));
+        assertEquals(Helper.createPointList3D(), eib.fetchWayGeometry(PILLAR_ONLY));
+        assertEquals(Helper.createPointList3D(11, 20, 1), eib.fetchWayGeometry(BASE_AND_PILLAR));
+        assertEquals(Helper.createPointList3D(12, 12, 0.4), eib.fetchWayGeometry(PILLAR_AND_ADJ));
         assertEquals(GHUtility.asSet(0), GHUtility.getNeighbors(explorer.setBaseNode(2)));
     }
 
diff --git a/core/src/test/java/com/graphhopper/util/GHUtilityTest.java b/core/src/test/java/com/graphhopper/util/GHUtilityTest.java
index 971658c03..78ed38f01 100644
--- a/core/src/test/java/com/graphhopper/util/GHUtilityTest.java
+++ b/core/src/test/java/com/graphhopper/util/GHUtilityTest.java
@@ -76,7 +76,7 @@ public class GHUtilityTest {
             // This is meant to verify that all of the same edges (including tower nodes)
             // are included in the copied graph. Can not use iter.getDistance() since it
             // does not verify new geometry. See #1732
-            distance += iter.fetchWayGeometry(3).calcDistance(calc);
+            distance += iter.fetchWayGeometry(FetchMode.ALL).calcDistance(calc);
         }
         return distance;
     }
@@ -145,7 +145,7 @@ public class GHUtilityTest {
         newStore.freeze();
 
         edgeState = GHUtility.getEdge(lg, 5, 6);
-        assertEquals(Helper.createPointList(-1, 3, 12, 10), edgeState.fetchWayGeometry(0));
+        assertEquals(Helper.createPointList(-1, 3, 12, 10), edgeState.fetchWayGeometry(FetchMode.PILLAR_ONLY));
 
         NodeAccess na = lg.getNodeAccess();
         assertEquals(0, na.getLatitude(0), 1e-6);
diff --git a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
index 8770a0d4d..9f554397b 100644
--- a/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
+++ b/reader-osm/src/test/java/com/graphhopper/reader/osm/OSMReaderTest.java
@@ -109,7 +109,7 @@ public class OSMReaderTest {
         assertTrue(iter.next());
         assertEquals("street 123, B 122", iter.getName());
         assertEquals(n50, iter.getAdjNode());
-        AbstractGraphStorageTester.assertPList(Helper.createPointList(51.25, 9.43), iter.fetchWayGeometry(0));
+        AbstractGraphStorageTester.assertPList(Helper.createPointList(51.25, 9.43), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
         assertTrue(iter.get(carAccessEnc));
         assertTrue(iter.getReverse(carAccessEnc));
 
@@ -185,12 +185,12 @@ public class OSMReaderTest {
         EdgeIterator iter = carOutExplorer.setBaseNode(n20);
         assertTrue(iter.next());
         assertEquals(n40, iter.getAdjNode());
-        AbstractGraphStorageTester.assertPList(Helper.createPointList(), iter.fetchWayGeometry(0));
+        AbstractGraphStorageTester.assertPList(Helper.createPointList(), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
         assertTrue(iter.next());
         assertEquals(n30, iter.getAdjNode());
         assertEquals(93146.888, iter.getDistance(), 1);
         assertTrue(iter.next());
-        AbstractGraphStorageTester.assertPList(Helper.createPointList(), iter.fetchWayGeometry(0));
+        AbstractGraphStorageTester.assertPList(Helper.createPointList(), iter.fetchWayGeometry(FetchMode.PILLAR_ONLY));
         assertEquals(n10, iter.getAdjNode());
         assertEquals(88643, iter.getDistance(), 1);
 
@@ -669,7 +669,7 @@ public class OSMReaderTest {
         int n50 = AbstractGraphStorageTester.getIdOf(graph, 49);
 
         EdgeIteratorState edge = GHUtility.getEdge(graph, n20, n50);
-        assertEquals(Helper.createPointList3D(52, 9, -10, 51.25, 9.43, 100, 49, 10, -30), edge.fetchWayGeometry(3));
+        assertEquals(Helper.createPointList3D(52, 9, -10, 51.25, 9.43, 100, 49, 10, -30), edge.fetchWayGeometry(FetchMode.ALL));
     }
 
     @Test
@@ -687,11 +687,11 @@ public class OSMReaderTest {
 
         EdgeIteratorState edge = GHUtility.getEdge(graph, n50, n30);
         assertEquals(Helper.createPointList3D(49.5001, 11.501, 426, 49.5002, 11.5015, 441, 49.5011, 11.502, 410.0),
-                edge.fetchWayGeometry(3));
+                edge.fetchWayGeometry(FetchMode.ALL));
 
         edge = GHUtility.getEdge(graph, n10, n50);
         assertEquals(Helper.createPointList3D(49.501, 11.5001, 383.0, 49.5001, 11.501, 426.0),
-                edge.fetchWayGeometry(3));
+                edge.fetchWayGeometry(FetchMode.ALL));
     }
 
     /**