Skip to content

Commit 1951462

Browse files
committed
Fix distance, time and weight for edge-based CH alternatives, fix graphhopper#2936
1 parent 34749f8 commit 1951462

File tree

3 files changed

+55
-16
lines changed

3 files changed

+55
-16
lines changed

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.carrotsearch.hppc.IntIndexedContainer;
2222
import com.carrotsearch.hppc.cursors.IntCursor;
2323
import com.carrotsearch.hppc.predicates.IntObjectPredicate;
24+
import com.graphhopper.routing.weighting.Weighting;
2425
import com.graphhopper.storage.Graph;
2526
import com.graphhopper.storage.RoutingCHGraph;
2627
import com.graphhopper.util.EdgeIteratorState;
@@ -136,7 +137,7 @@ List<AlternativeInfo> calcAlternatives(final int s, final int t) {
136137
// at u->v->x in which case uvtPath is not found. If we do not stop here we might return
137138
// an alternative that does not even reach t, and has a lower weight than the best path.
138139
continue;
139-
Path path = concat(graph.getBaseGraph(), suvPath, uvtPath);
140+
Path path = concat(graph.getBaseGraph(), graph.getBaseGraph().wrapWeighting(graph.getWeighting()), suvPath, uvtPath);
140141
extraVisitedNodes += vtRouter.getVisitedNodes();
141142

142143
double sharedDistanceWithShortest = sharedDistanceWithShortest(path);
@@ -242,22 +243,22 @@ private EdgeIteratorState getNextNodeTMetersAway(Path path, int vIndex, double T
242243
return edges.get(i - 1);
243244
}
244245

245-
private static Path concat(Graph graph, Path suvPath, Path uvtPath) {
246+
private static Path concat(Graph graph, Weighting weighting, Path suvPath, Path uvtPath) {
246247
assert suvPath.isFound();
247248
assert uvtPath.isFound();
248249
Path path = new Path(graph);
249-
path.setFromNode(suvPath.calcNodes().get(0));
250+
path.setFromNode(suvPath.getFromNode());
250251
path.getEdges().addAll(suvPath.getEdges());
252+
if (uvtPath.getEdges().isEmpty())
253+
throw new IllegalStateException("uvtPath.getEdges() should not be empty");
251254
Iterator<IntCursor> uvtPathI = uvtPath.getEdges().iterator();
252-
if (!uvtPathI.hasNext()) { // presumably v == t, has been known to happen, no test yet
253-
return suvPath;
254-
}
255-
uvtPathI.next(); // skip u-v edge
255+
int uvEdge = uvtPathI.next().value;// skip u-v edge
256256
uvtPathI.forEachRemaining(edge -> path.addEdge(edge.value));
257+
EdgeIteratorState vuEdgeState = graph.getEdgeIteratorState(uvEdge, uvtPath.getFromNode());
257258
path.setEndNode(uvtPath.getEndNode());
258-
path.setWeight(suvPath.getWeight() + uvtPath.getWeight());
259-
path.setDistance(suvPath.getDistance() + uvtPath.getDistance());
260-
path.addTime(suvPath.getTime() + uvtPath.getTime());
259+
path.setWeight(suvPath.getWeight() + uvtPath.getWeight() - weighting.calcEdgeWeight(vuEdgeState, true));
260+
path.setDistance(suvPath.getDistance() + uvtPath.getDistance() - vuEdgeState.getDistance());
261+
path.addTime(suvPath.getTime() + uvtPath.getTime() - weighting.calcEdgeMillis(vuEdgeState, true));
261262
path.setFound(true);
262263
return path;
263264
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ public Path setEndNode(int end) {
101101
return this;
102102
}
103103

104-
/**
105-
* @return the first node of this Path.
106-
*/
107-
private int getFromNode() {
104+
public int getFromNode() {
108105
if (fromNode < 0)
109106
throw new IllegalStateException("fromNode < 0 should not happen");
110107

core/src/test/java/com/graphhopper/routing/AlternativeRouteEdgeCHTest.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@
3232
import java.util.List;
3333

3434
import static com.graphhopper.util.EdgeIterator.ANY_EDGE;
35-
import static org.junit.jupiter.api.Assertions.assertEquals;
36-
import static org.junit.jupiter.api.Assertions.assertTrue;
35+
import static org.junit.jupiter.api.Assertions.*;
3736

3837
public class AlternativeRouteEdgeCHTest {
3938
private final DecimalEncodedValue speedEnc = new DecimalEncodedValueImpl("speed", 5, 5, false);
@@ -183,4 +182,46 @@ void turnRestrictionAtConnectingNode() {
183182
assertEquals(IntArrayList.from(s, t), pathInfos.get(j).path.calcNodes(), "alternatives must start/end at start/end node");
184183
}
185184
}
185+
186+
@Test
187+
void distanceTimeAndWeight() {
188+
final BaseGraph graph = new BaseGraph.Builder(em).withTurnCosts(true).create();
189+
// 0-1-2-3---|
190+
// \ |
191+
// 5-6-7-8
192+
graph.edge(0, 1).setDistance(500).set(speedEnc, 60);
193+
graph.edge(1, 2).setDistance(500).set(speedEnc, 60);
194+
graph.edge(2, 3).setDistance(500).set(speedEnc, 60);
195+
graph.edge(2, 5).setDistance(1000).set(speedEnc, 60);
196+
graph.edge(3, 7).setDistance(1500).set(speedEnc, 60);
197+
graph.edge(5, 6).setDistance(500).set(speedEnc, 60);
198+
graph.edge(6, 7).setDistance(500).set(speedEnc, 60);
199+
graph.edge(7, 8).setDistance(500).set(speedEnc, 60);
200+
graph.freeze();
201+
CHConfig chConfig = CHConfig.edgeBased("profile", new SpeedWeighting(speedEnc, turnCostEnc, graph.getTurnCostStorage(), Double.POSITIVE_INFINITY));
202+
PrepareContractionHierarchies contractionHierarchies = PrepareContractionHierarchies.fromGraph(graph, chConfig);
203+
contractionHierarchies.useFixedNodeOrdering(NodeOrderingProvider.fromArray(7, 6, 0, 2, 4, 5, 1, 3, 8));
204+
PrepareContractionHierarchies.Result res = contractionHierarchies.doWork();
205+
RoutingCHGraph routingCHGraph = RoutingCHGraphImpl.fromGraph(graph, res.getCHStorage(), res.getCHConfig());
206+
final int s = 0;
207+
final int t = 8;
208+
PMap hints = new PMap();
209+
AlternativeRouteEdgeCH altDijkstra = new AlternativeRouteEdgeCH(routingCHGraph, hints);
210+
List<AlternativeRouteEdgeCH.AlternativeInfo> pathInfos = altDijkstra.calcAlternatives(s, t);
211+
assertTrue(pathInfos.size() > 1, "the graph, contraction order and alternative route algorith must be such that " +
212+
"there is at least one alternative path, otherwise this test makes no sense");
213+
AlternativeRouteEdgeCH.AlternativeInfo best = pathInfos.get(0);
214+
assertEquals(3500, best.path.getDistance());
215+
assertEquals(58.3333, best.path.getWeight(), 1.e-3);
216+
assertEquals(58333, best.path.getTime(), 10);
217+
assertEquals(IntArrayList.from(0, 1, 2, 5, 6, 7, 8), best.path.calcNodes());
218+
for (int j = 1; j < pathInfos.size(); j++) {
219+
Path alternative = pathInfos.get(j).path;
220+
assertEquals(3500, alternative.getDistance());
221+
assertEquals(58.3333, alternative.getWeight(), 1.e-3);
222+
assertEquals(58333, alternative.getTime(), 1);
223+
assertEquals(IntArrayList.from(0, 1, 2, 3, 7, 8), alternative.calcNodes());
224+
}
225+
}
226+
186227
}

0 commit comments

Comments
 (0)