Repository: graphhopper/graphhopper
Pull request #1693 (2019-08-23 10:18:52)

Remove shortcut(a, b) method from CHGraph
Just a minor cleanup: `CHGraph#shortcut(int a, int b)` was not used in production anymore. I replaced its usages with the methods used in production (namely `shortcut(int a, int b, ...)` and `shortcutEdgeBased`) and removed the method.


Patch:
diff --git a/core/files/changelog.txt b/core/files/changelog.txt
index 76eb529d2..e369529d0 100644
--- a/core/files/changelog.txt
+++ b/core/files/changelog.txt
@@ -14,6 +14,7 @@
     removed TraversalMode.EDGE_BASED_1DIR and TraversalMode.EDGE_BASED_2DIR_UTURN, renamed TraversalMode.EDGE_BASED_2DIR to TraversalMode.EDGE_BASED
     to prevent u-turns when using edge-based algorithms it is now required to use TurnWeighting, #1640
     GraphHopperStorage.getGraph(Class) was replaced by GraphHopperStorage.getBase/CHGraph(), #1669
+    CHGraph.shortcut(int, int) was removed (use .shortcut(int, int, ...) and/or .shortcutEdgeBased(int, int, ...) instead
 
 0.12
     renamed VirtualEdgeIteratorState.getOriginalEdgeKey to more precise getOriginalEdgeKey #1549
diff --git a/core/src/main/java/com/graphhopper/storage/CHGraph.java b/core/src/main/java/com/graphhopper/storage/CHGraph.java
index 6ef50906c..ca669fed8 100644
--- a/core/src/main/java/com/graphhopper/storage/CHGraph.java
+++ b/core/src/main/java/com/graphhopper/storage/CHGraph.java
@@ -51,10 +51,11 @@ public interface CHGraph extends Graph {
      * This method creates a shortcut between a to b which is nearly identical to creating an edge
      * except that it can be excluded or included for certain traversals or algorithms.
      */
-    CHEdgeIteratorState shortcut(int a, int b);
-
     int shortcut(int a, int b, int accessFlags, double weight, double distance, int skippedEdge1, int skippedEdge2);
 
+    /**
+     * like shortcut(), but for edge-based CH
+     */
     int shortcutEdgeBased(int a, int b, int accessFlags, double weight, double distance, int skippedEdge1, int skippedEdge2, int origFirst, int origLast);
 
     @Override
diff --git a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
index a8bbe1c3a..405973f90 100644
--- a/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
+++ b/core/src/main/java/com/graphhopper/storage/CHGraphImpl.java
@@ -105,22 +105,6 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
         assert nodeId < baseGraph.getNodes() : "node " + nodeId + " is invalid. Not in [0," + baseGraph.getNodes() + ")";
     }
 
-    @Override
-    public CHEdgeIteratorState shortcut(int a, int b) {
-        if (!baseGraph.isFrozen())
-            throw new IllegalStateException("Cannot create shortcut if graph is not yet frozen");
-
-        checkNodeId(a);
-        checkNodeId(b);
-
-        int scId = chEdgeAccess.internalEdgeAdd(nextShortcutId(), a, b);
-        CHEdgeIteratorImpl iter = new CHEdgeIteratorImpl(baseGraph, chEdgeAccess, EdgeFilter.ALL_EDGES);
-        boolean ret = iter.init(scId, b);
-        assert ret;
-        iter.setSkippedEdges(EdgeIterator.NO_EDGE, EdgeIterator.NO_EDGE);
-        return iter;
-    }
-
     @Override
     public int shortcut(int a, int b, int accessFlags, double weight, double distance, int skippedEdge1, int skippedEdge2) {
         if (!baseGraph.isFrozen())
@@ -140,7 +124,9 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
 
     @Override
     public int shortcutEdgeBased(int a, int b, int accessFlags, double weight, double distance, int skippedEdge1, int skippedEdge2, int origFirst, int origLast) {
-        assert edgeBased : "Edge-based shortcuts should only be added when CHGraph is edge-based";
+        if (!edgeBased) {
+            throw new IllegalStateException("Edge-based shortcuts should only be added when CHGraph is edge-based");
+        }
         int scId = shortcut(a, b, accessFlags, weight, distance, skippedEdge1, skippedEdge2);
         chEdgeAccess.setFirstAndLastOrigEdges(chEdgeAccess.toPointer(scId), origFirst, origLast);
         return scId;
@@ -882,6 +868,9 @@ public class CHGraphImpl implements CHGraph, Storable<CHGraph> {
         }
 
         public void setFirstAndLastOrigEdges(long edgePointer, int origFirst, int origLast) {
+            if (!edgeBased) {
+                throw new IllegalStateException("Edge-based shortcuts should only be added when CHGraph is edge-based");
+            }
             shortcuts.setInt(edgePointer + S_ORIG_FIRST, origFirst);
             shortcuts.setInt(edgePointer + S_ORIG_LAST, origLast);
         }


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java b/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
index af69fd51c..7b176da6e 100644
--- a/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
+++ b/core/src/test/java/com/graphhopper/routing/CHQueryWithTurnCostsTest.java
@@ -718,10 +718,9 @@ public class CHQueryWithTurnCostsTest {
     }
 
     private void addShortcut(int from, int to, int firstOrigEdge, int lastOrigEdge, int skipped1, int skipped2, double weight) {
-        CHEdgeIteratorState shortcut = chGraph.shortcut(from, to);
-        // we need to set flags first because they overwrite weight etc
-        shortcut.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), weight);
-        shortcut.setFirstAndLastOrigEdges(firstOrigEdge, lastOrigEdge).setSkippedEdges(skipped1, skipped2);
+        // todo: not using distance atm
+        double distance = 0;
+        chGraph.shortcutEdgeBased(from, to, PrepareEncoder.getScFwdDir(), weight, distance, skipped1, skipped2, firstOrigEdge, lastOrigEdge);
     }
 
     private void setLevelEqualToNodeIdForAllNodes() {
diff --git a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionCHTest.java b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionCHTest.java
index 51b639a74..7b6ac53a1 100644
--- a/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionCHTest.java
+++ b/core/src/test/java/com/graphhopper/routing/DijkstraBidirectionCHTest.java
@@ -91,14 +91,8 @@ public class DijkstraBidirectionCHTest extends AbstractRoutingAlgorithmTester {
 
         ghStorage.freeze();
         // simulate preparation
-        CHEdgeIteratorState iter2_1 = g2.shortcut(0, 5);
-        iter2_1.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 1);
-        iter2_1.setDistance(2.8);
-        iter2_1.setSkippedEdges(iter1_1.getEdge(), iter1_2.getEdge());
-        CHEdgeIteratorState tmp = g2.shortcut(0, 7);
-        tmp.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 1);
-        tmp.setDistance(4.2);
-        tmp.setSkippedEdges(iter2_1.getEdge(), iter2_2.getEdge());
+        int sc2_1 = g2.shortcut(0, 5, PrepareEncoder.getScFwdDir(), 1, 2.8, iter1_1.getEdge(), iter1_2.getEdge());
+        g2.shortcut(0, 7, PrepareEncoder.getScFwdDir(), 1, 4.2, sc2_1, iter2_2.getEdge());
         g2.setLevel(1, 0);
         g2.setLevel(3, 1);
         g2.setLevel(4, 2);
diff --git a/core/src/test/java/com/graphhopper/routing/ch/NodeBasedNodeContractorTest.java b/core/src/test/java/com/graphhopper/routing/ch/NodeBasedNodeContractorTest.java
index 18ae4a100..666e78358 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/NodeBasedNodeContractorTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/NodeBasedNodeContractorTest.java
@@ -184,20 +184,9 @@ public class NodeBasedNodeContractorTest {
         graph.edge(6, 7, 1, true);
         graph.freeze();
 
-        CHEdgeIteratorState sc1to4 = lg.shortcut(1, 4);
-        sc1to4.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 2);
-        sc1to4.setDistance(2);
-        sc1to4.setSkippedEdges(iter1to3.getEdge(), iter3to4.getEdge());
-
-        CHEdgeIteratorState sc4to6 = lg.shortcut(4, 6);
-        sc4to6.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 2);
-        sc4to6.setDistance(2);
-        sc4to6.setSkippedEdges(iter4to5.getEdge(), iter5to6.getEdge());
-
-        CHEdgeIteratorState sc6to4 = lg.shortcut(6, 4);
-        sc6to4.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 3);
-        sc6to4.setDistance(3);
-        sc6to4.setSkippedEdges(iter6to8.getEdge(), iter8to4.getEdge());
+        int sc1to4 = lg.shortcut(1, 4, PrepareEncoder.getScDirMask(), 2, 2, iter1to3.getEdge(), iter3to4.getEdge());
+        int sc4to6 = lg.shortcut(4, 6, PrepareEncoder.getScFwdDir(), 2, 2, iter4to5.getEdge(), iter5to6.getEdge());
+        int sc6to4 = lg.shortcut(6, 4, PrepareEncoder.getScFwdDir(), 3, 3, iter6to8.getEdge(), iter8to4.getEdge());
 
         setMaxLevelOnAllNodes();
 
@@ -221,8 +210,8 @@ public class NodeBasedNodeContractorTest {
         nodeContractor.contractNode(4);
         checkShortcuts(manualSc1, manualSc2, manualSc3,
                 // there should be two different shortcuts for both directions!
-                expectedShortcut(1, 6, sc1to4, sc4to6, true, false),
-                expectedShortcut(6, 1, sc6to4, sc1to4, true, false)
+                expectedShortcut(1, 6, lg.getEdgeIteratorState(sc1to4, 4), lg.getEdgeIteratorState(sc4to6, 6), true, false),
+                expectedShortcut(6, 1, lg.getEdgeIteratorState(sc6to4, 4), lg.getEdgeIteratorState(sc1to4, 1), true, false)
         );
     }
 
diff --git a/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java b/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
index 8b73762ab..06832d0c6 100644
--- a/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
+++ b/core/src/test/java/com/graphhopper/routing/ch/PrepareContractionHierarchiesTest.java
@@ -309,34 +309,30 @@ public class PrepareContractionHierarchiesTest {
         EdgeIteratorState edgeState34 = g.edge(3, 4).setDistance(dist).setFlags(edgeFlags);
         EdgeIteratorState edgeState45 = g.edge(4, 5).setDistance(dist).setFlags(edgeFlags);
         EdgeIteratorState edgeState56 = g.edge(5, 6).setDistance(dist).setFlags(edgeFlags);
+        int oneDirFlags = PrepareEncoder.getScFwdDir();
 
         int tmpEdgeId = edgeState01.getEdge();
         ghStorage.freeze();
-        CHEdgeIteratorState sc0_2 = g.shortcut(0, 2);
         int x = EdgeIterator.NO_EDGE;
-        sc0_2.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), w.calcWeight(edgeState01, false, x) + w.calcWeight(edgeState12, false, x));
-        sc0_2.setDistance(2 * dist);
-        sc0_2.setSkippedEdges(tmpEdgeId, edgeState12.getEdge());
-        tmpEdgeId = sc0_2.getEdge();
-        CHEdgeIteratorState sc0_3 = g.shortcut(0, 3);
-        sc0_3.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), sc0_2.getWeight() + w.calcWeight(edgeState23, false, x));
-        sc0_3.setDistance(3 * dist);
-        sc0_3.setSkippedEdges(tmpEdgeId, edgeState23.getEdge());
-        tmpEdgeId = sc0_3.getEdge();
-        CHEdgeIteratorState sc0_4 = g.shortcut(0, 4);
-        sc0_4.setDistance(4);
-        sc0_4.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), sc0_3.getWeight() + w.calcWeight(edgeState34, false, x));
-        sc0_4.setSkippedEdges(tmpEdgeId, edgeState34.getEdge());
-        tmpEdgeId = sc0_4.getEdge();
-        CHEdgeIteratorState sc0_5 = g.shortcut(0, 5);
-        sc0_5.setDistance(5);
-        sc0_5.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), sc0_4.getWeight() + w.calcWeight(edgeState45, false, x));
-        sc0_5.setSkippedEdges(tmpEdgeId, edgeState45.getEdge());
-        tmpEdgeId = sc0_5.getEdge();
-        CHEdgeIteratorState sc0_6 = g.shortcut(0, 6);
-        sc0_6.setDistance(6);
-        sc0_6.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), sc0_5.getWeight() + w.calcWeight(edgeState56, false, x));
-        sc0_6.setSkippedEdges(tmpEdgeId, edgeState56.getEdge());
+        double weight = w.calcWeight(edgeState01, false, x) + w.calcWeight(edgeState12, false, x);
+        int sc0_2 = g.shortcut(0, 2, oneDirFlags, w.calcWeight(edgeState01, false, x) + w.calcWeight(edgeState12, false, x), 2 * dist, tmpEdgeId, edgeState12.getEdge());
+
+        tmpEdgeId = sc0_2;
+        weight += w.calcWeight(edgeState23, false, x);
+        int sc0_3 = g.shortcut(0, 3, oneDirFlags, weight, 3 * dist, tmpEdgeId, edgeState23.getEdge());
+
+        tmpEdgeId = sc0_3;
+        weight += w.calcWeight(edgeState34, false, x);
+        int sc0_4 = g.shortcut(0, 4, oneDirFlags, weight, 4, tmpEdgeId, edgeState34.getEdge());
+
+        tmpEdgeId = sc0_4;
+        weight += w.calcWeight(edgeState45, false, x);
+        int sc0_5 = g.shortcut(0, 5, oneDirFlags, weight, 5, tmpEdgeId, edgeState45.getEdge());
+
+        tmpEdgeId = sc0_5;
+        weight += w.calcWeight(edgeState56, false, x);
+        int sc0_6 = g.shortcut(0, 6, oneDirFlags, weight, 6, tmpEdgeId, edgeState56.getEdge());
+
         g.setLevel(0, 10);
         g.setLevel(6, 9);
         g.setLevel(5, 8);
diff --git a/core/src/test/java/com/graphhopper/routing/util/DefaultEdgeFilterTest.java b/core/src/test/java/com/graphhopper/routing/util/DefaultEdgeFilterTest.java
index cc9645584..2f1f78e85 100644
--- a/core/src/test/java/com/graphhopper/routing/util/DefaultEdgeFilterTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/DefaultEdgeFilterTest.java
@@ -27,7 +27,6 @@ import com.graphhopper.storage.GraphBuilder;
 import com.graphhopper.storage.GraphHopperStorage;
 import com.graphhopper.util.CHEdgeExplorer;
 import com.graphhopper.util.CHEdgeIterator;
-import com.graphhopper.util.CHEdgeIteratorState;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -68,10 +67,9 @@ public class DefaultEdgeFilterTest {
         assertEquals("Wrong incoming edges", IntHashSet.from(2, 3), inEdges);
     }
 
-    private void addShortcut(CHGraph chGraph, int from, int to, boolean fwd, int firstOrigEdge, int lastOrigEdge) {
-        CHEdgeIteratorState shortcut = chGraph.shortcut(from, to);
-        shortcut.setFlagsAndWeight(fwd ? PrepareEncoder.getScFwdDir() : PrepareEncoder.getScBwdDir(), 0);
-        shortcut.setFirstAndLastOrigEdges(firstOrigEdge, lastOrigEdge);
+    private void addShortcut(CHGraph chGraph, int from, int to, boolean fwd, int skip1, int skip2) {
+        int accessFlags = fwd ? PrepareEncoder.getScFwdDir() : PrepareEncoder.getScBwdDir();
+        chGraph.shortcut(from, to, accessFlags, 5, 5, skip1, skip2);
     }
 
 }
\ No newline at end of file
diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageCHTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageCHTest.java
index f4b4443ce..5222015eb 100644
--- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageCHTest.java
+++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageCHTest.java
@@ -36,6 +36,7 @@ import java.util.Collections;
 import java.util.List;
 
 import static com.graphhopper.routing.ch.NodeBasedNodeContractorTest.SC_ACCESS;
+import static com.graphhopper.util.EdgeIterator.NO_EDGE;
 import static org.junit.Assert.*;
 
 /**
@@ -108,15 +109,8 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         g.edge(10, 11, 1, true);
 
         graph.freeze();
-        CHEdgeIteratorState tmpIter = g.shortcut(3, 4);
-        tmpIter.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 0);
-        tmpIter.setDistance(40);
-        assertEquals(EdgeIterator.NO_EDGE, tmpIter.getSkippedEdge1());
-        assertEquals(EdgeIterator.NO_EDGE, tmpIter.getSkippedEdge2());
-
-        tmpIter = g.shortcut(0, 4);
-        tmpIter.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 0);
-        tmpIter.setDistance(40);
+        g.shortcut(3, 4, PrepareEncoder.getScDirMask(), 0, 40, NO_EDGE, NO_EDGE);
+        g.shortcut(0, 4, PrepareEncoder.getScDirMask(), 0, 40, NO_EDGE, NO_EDGE);
         g.setLevel(0, 1);
         g.setLevel(4, 1);
 
@@ -125,8 +119,8 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         iter = g.createEdgeExplorer().setBaseNode(2);
         assertEquals(2, GHUtility.count(iter));
 
-        tmpIter = g.shortcut(5, 6);
-        tmpIter.setSkippedEdges(1, 2);
+        int sc = g.shortcut(5, 6, PrepareEncoder.getScDirMask(), 0, 40, 1, 2);
+        CHEdgeIteratorState tmpIter = g.getEdgeIteratorState(sc, 6);
         assertEquals(1, tmpIter.getSkippedEdge1());
         assertEquals(2, tmpIter.getSkippedEdge2());
     }
@@ -144,18 +138,9 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         // only remove edges
         lg.edge(4, 1, 30, true);
         graph.freeze();
-        CHEdgeIteratorState tmp = lg.shortcut(1, 2);
-        tmp.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 0);
-        tmp.setDistance(10);
-        tmp.setSkippedEdges(10, 11);
-        tmp = lg.shortcut(1, 0);
-        tmp.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 0);
-        tmp.setDistance(20);
-        tmp.setSkippedEdges(12, 13);
-        tmp = lg.shortcut(3, 1);
-        tmp.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 0);
-        tmp.setDistance(30);
-        tmp.setSkippedEdges(14, 15);
+        lg.shortcut(1, 2, PrepareEncoder.getScDirMask(), 0, 10, 10, 11);
+        lg.shortcut(1, 0, PrepareEncoder.getScFwdDir(), 0, 20, 12, 13);
+        lg.shortcut(3, 1, PrepareEncoder.getScFwdDir(), 0, 30, 14, 15);
         // create everytime a new independent iterator for disconnect method
         EdgeIterator iter = lg.createEdgeExplorer().setBaseNode(1);
         iter.next();
@@ -194,7 +179,8 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
 
         // only remove edges
         int flags = PrepareEncoder.getScDirMask();
-        CHEdgeIteratorState sc1 = g.shortcut(0, 1);
+        int sc = g.shortcut(0, 1, flags, 5, 5, NO_EDGE, NO_EDGE);
+        CHEdgeIteratorState sc1 = g.getEdgeIteratorState(sc, 1);
         assertTrue(sc1.isShortcut());
         sc1.setWeight(2.001);
         assertEquals(2.001, sc1.getWeight(), 1e-3);
@@ -229,18 +215,16 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         ghStorage.freeze();
 
         CHGraph lg = ghStorage.getCHGraph(weighting);
-        CHEdgeIteratorState sc1 = lg.shortcut(0, 1);
-        sc1.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 100.123);
+        int sc1 = lg.shortcut(0, 1, PrepareEncoder.getScFwdDir(), 100.123, 0, NO_EDGE, NO_EDGE);
 
-        assertEquals(100.123, lg.getEdgeIteratorState(sc1.getEdge(), sc1.getAdjNode()).getWeight(), 1e-3);
-        assertEquals(100.123, lg.getEdgeIteratorState(sc1.getEdge(), sc1.getBaseNode()).getWeight(), 1e-3);
-        assertEquals(100.123, ((CHEdgeIteratorState) GHUtility.getEdge(lg, sc1.getBaseNode(), sc1.getAdjNode())).getWeight(), 1e-3);
-        assertEquals(100.123, ((CHEdgeIteratorState) GHUtility.getEdge(lg, sc1.getAdjNode(), sc1.getBaseNode())).getWeight(), 1e-3);
+        assertEquals(100.123, lg.getEdgeIteratorState(sc1, 1).getWeight(), 1e-3);
+        assertEquals(100.123, lg.getEdgeIteratorState(sc1, 0).getWeight(), 1e-3);
+        assertEquals(100.123, ((CHEdgeIteratorState) GHUtility.getEdge(lg, 0, 1)).getWeight(), 1e-3);
+        assertEquals(100.123, ((CHEdgeIteratorState) GHUtility.getEdge(lg, 1, 0)).getWeight(), 1e-3);
 
-        sc1 = lg.shortcut(1, 0);
-        assertTrue(sc1.isShortcut());
-        sc1.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 1.011011);
-        assertEquals(1.011011, sc1.getWeight(), 1e-3);
+        int sc2 = lg.shortcut(1, 0, PrepareEncoder.getScDirMask(), 1.011011, 0, NO_EDGE, NO_EDGE);
+        assertEquals(1.011011, lg.getEdgeIteratorState(sc2, 0).getWeight(), 1e-3);
+        assertEquals(1.011011, lg.getEdgeIteratorState(sc2, 1).getWeight(), 1e-3);
     }
 
     @Test
@@ -273,7 +257,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         EdgeIteratorState edge1 = chGraph.edge(0, 1);
         chGraph.edge(1, 2);
         graph.freeze();
-        chGraph.shortcut(0, 1);
+        chGraph.shortcut(0, 1, PrepareEncoder.getScDirMask(), 10, 10, NO_EDGE, NO_EDGE);
 
         QueryGraph qGraph = new QueryGraph(chGraph);
         QueryResult fromRes = createQR(1.004, 1.01, 0, edge1);
@@ -321,7 +305,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         assertEquals(1, GHUtility.count(graph.createEdgeExplorer().setBaseNode(1)));
         assertEquals(1, GHUtility.count(chGraph.createEdgeExplorer().setBaseNode(1)));
 
-        chGraph.shortcut(2, 3);
+        chGraph.shortcut(2, 3, PrepareEncoder.getScDirMask(), 10, 10, NO_EDGE, NO_EDGE);
 
         // should be identical to access without shortcut
         assertEquals(1, GHUtility.count(graph.createEdgeExplorer().setBaseNode(1)));
@@ -367,7 +351,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         graph.freeze();
 
         CHGraph lg = graph.getCHGraph();
-        lg.shortcut(1, 4).setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 3);
+        lg.shortcut(1, 4, PrepareEncoder.getScFwdDir(), 3, 3, NO_EDGE, NO_EDGE);
 
         EdgeExplorer vehicleOutExplorer = lg.createEdgeExplorer(DefaultEdgeFilter.outEdges(carEncoder));
         // iteration should result in same nodes even if reusing the iterator
@@ -383,7 +367,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         graph.freeze();
 
         CHGraph lg = graph.getCHGraph();
-        lg.shortcut(1, 4);
+        lg.shortcut(1, 4, PrepareEncoder.getScDirMask(), 10, 10, NO_EDGE, NO_EDGE);
 
         AllCHEdgesIterator iter = lg.getAllEdges();
         iter.next();
@@ -403,8 +387,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
         graph.freeze();
 
         CHGraph lg = graph.getCHGraph();
-        CHEdgeIteratorState shortcut = lg.shortcut(1, 4);
-        shortcut.setSkippedEdges(edge1.getEdge(), edge2.getEdge());
+        lg.shortcut(1, 4, PrepareEncoder.getScDirMask(), 10, 10, edge1.getEdge(), edge2.getEdge());
 
         AllCHEdgesIterator iter = lg.getAllEdges();
         iter.next();
@@ -475,9 +458,7 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
 
     private void addShortcut(CHGraph chGraph, int from, int to, boolean fwd, int firstOrigEdge, int lastOrigEdge,
                              int skipEdge1, int skipEdge2, int distance) {
-        CHEdgeIteratorState shortcut = chGraph.shortcut(from, to);
-        shortcut.setFlagsAndWeight(fwd ? PrepareEncoder.getScFwdDir() : PrepareEncoder.getScBwdDir(), 0);
-        shortcut.setFirstAndLastOrigEdges(firstOrigEdge, lastOrigEdge).setSkippedEdges(skipEdge1, skipEdge2).setDistance(distance);
+        chGraph.shortcutEdgeBased(from, to, fwd ? PrepareEncoder.getScFwdDir() : PrepareEncoder.getScBwdDir(), 0, distance, skipEdge1, skipEdge2, firstOrigEdge, lastOrigEdge);
     }
 
     @Test
@@ -499,36 +480,32 @@ public class GraphHopperStorageCHTest extends GraphHopperStorageTest {
 
         CHGraph carCHGraph = graph.getCHGraph(chWeightings.get(0));
         // enable forward directions for car
-        CHEdgeIteratorState carSC02 = carCHGraph.shortcut(0, 2);
-        carSC02.setFlagsAndWeight(PrepareEncoder.getScFwdDir(), 10);
-        carSC02.setDistance(20);
+        int carSC02 = carCHGraph.shortcut(0, 2, PrepareEncoder.getScFwdDir(), 10, 20, NO_EDGE, NO_EDGE);
 
         CHGraph bikeCHGraph = graph.getCHGraph(chWeightings.get(1));
-        CHEdgeIteratorState bikeSC02 = bikeCHGraph.shortcut(0, 2);
         // enable both directions for bike
-        bikeSC02.setFlagsAndWeight(PrepareEncoder.getScDirMask(), 10);
-        bikeSC02.setDistance(20);
+        int bikeSC02 = bikeCHGraph.shortcut(0, 2, PrepareEncoder.getScDirMask(), 10, 20, NO_EDGE, NO_EDGE);
 
         // assert car CH graph
-        assertTrue(carCHGraph.getEdgeIteratorState(carSC02.getEdge(), 2).get(tmpCarAccessEnc));
-        assertFalse(carCHGraph.getEdgeIteratorState(carSC02.getEdge(), 2).getReverse(tmpCarAccessEnc));
+        assertTrue(carCHGraph.getEdgeIteratorState(carSC02, 2).get(tmpCarAccessEnc));
+        assertFalse(carCHGraph.getEdgeIteratorState(carSC02, 2).getReverse(tmpCarAccessEnc));
 
         BooleanEncodedValue tmpBikeAccessEnc = tmpBike.getAccessEnc();
 
         // throw exception for wrong encoder
         try {
-            assertFalse(carCHGraph.getEdgeIteratorState(carSC02.getEdge(), 2).get(tmpBikeAccessEnc));
+            assertFalse(carCHGraph.getEdgeIteratorState(carSC02, 2).get(tmpBikeAccessEnc));
             fail();
         } catch (AssertionError ex) {
         }
 
         // assert bike CH graph
-        assertTrue(bikeCHGraph.getEdgeIteratorState(bikeSC02.getEdge(), 2).get(tmpBikeAccessEnc));
-        assertTrue(bikeCHGraph.getEdgeIteratorState(bikeSC02.getEdge(), 2).getReverse(tmpBikeAccessEnc));
+        assertTrue(bikeCHGraph.getEdgeIteratorState(bikeSC02, 2).get(tmpBikeAccessEnc));
+        assertTrue(bikeCHGraph.getEdgeIteratorState(bikeSC02, 2).getReverse(tmpBikeAccessEnc));
 
         // throw exception for wrong encoder
         try {
-            assertFalse(bikeCHGraph.getEdgeIteratorState(bikeSC02.getEdge(), 2).getReverse(tmpCarAccessEnc));
+            assertFalse(bikeCHGraph.getEdgeIteratorState(bikeSC02, 2).getReverse(tmpCarAccessEnc));
             fail();
         } catch (AssertionError ex) {
         }
diff --git a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java b/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java
index 63a83f116..e777fe5b8 100644
--- a/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java
+++ b/core/src/test/java/com/graphhopper/storage/index/LocationIndexTreeCHTest.java
@@ -83,23 +83,18 @@ public class LocationIndexTreeCHTest extends LocationIndexTreeTest {
         // create shortcuts
         ghStorage.freeze();
         int flags = PrepareEncoder.getScDirMask();
-        CHEdgeIteratorState iter5 = lg.shortcut(0, 2);
-        iter5.setFlagsAndWeight(flags, 0);
-        iter5.setDistance(20);
-        iter5.setSkippedEdges(iter1.getEdge(), iter2.getEdge());
-        CHEdgeIteratorState iter6 = lg.shortcut(2, 4);
-        iter6.setFlagsAndWeight(flags, 0);
-        iter6.setDistance(28);
-        iter6.setSkippedEdges(iter3.getEdge(), iter4.getEdge());
-        CHEdgeIteratorState tmp = lg.shortcut(0, 4);
-        tmp.setFlagsAndWeight(flags, 0);
-        tmp.setDistance(40);
-        tmp.setSkippedEdges(iter5.getEdge(), iter6.getEdge());
+        int sc1 = addShortcut(lg, 0, 2, 0, 20, iter1.getEdge(), iter2.getEdge(), flags);
+        int sc2 = addShortcut(lg, 2, 4, 0, 28, iter3.getEdge(), iter4.getEdge(), flags);
+        addShortcut(lg, 0, 4, 0, 40, sc1, sc2, flags);
 
         LocationIndex index = createIndex(ghStorage, -1);
         assertEquals(2, findID(index, 0, 0.5));
     }
 
+    private int addShortcut(CHGraph lg, int from, int to, double weight, double distance, int skip1, int skip2, int direction) {
+        return lg.shortcut(from, to, direction, weight, distance, skip1, skip2);
+    }
+
     @Test
     public void testSortHighLevelFirst() {
         GraphHopperStorage g = createGHStorage(new RAMDirectory(), encodingManager, false);