Skip to content

Commit d831dbf

Browse files
authored
Remove routing templates, remove RoutingAlgorithmFactory interface for CH (graphhopper#2057)
1 parent d6112c0 commit d831dbf

29 files changed

+1072
-855
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected SPTEntry followParentsUntilRoot(SPTEntry sptEntry, boolean reverse) {
9494
}
9595

9696
protected void setExtractionTime(long nanos) {
97-
path.setDebugInfo("path extraction: " + nanos / 1000 + " micros");
97+
path.setDebugInfo("path extraction: " + nanos / 1000 + " μs");
9898
}
9999

100100
protected int getIncEdge(SPTEntry entry) {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.graphhopper.routing;
20+
21+
import com.graphhopper.routing.ch.CHRoutingAlgorithmFactory;
22+
import com.graphhopper.routing.querygraph.QueryGraph;
23+
import com.graphhopper.util.PMap;
24+
import com.graphhopper.util.Parameters;
25+
import com.graphhopper.util.StopWatch;
26+
27+
import java.util.Collections;
28+
import java.util.List;
29+
30+
import static com.graphhopper.util.EdgeIterator.ANY_EDGE;
31+
import static com.graphhopper.util.Parameters.Routing.MAX_VISITED_NODES;
32+
33+
public class CHPathCalculator implements PathCalculator {
34+
private final QueryGraph queryGraph;
35+
private final CHRoutingAlgorithmFactory algoFactory;
36+
private final PMap algoOpts;
37+
private String debug;
38+
private int visitedNodes;
39+
40+
public CHPathCalculator(QueryGraph queryGraph, CHRoutingAlgorithmFactory algoFactory, PMap algoOpts) {
41+
this.queryGraph = queryGraph;
42+
this.algoFactory = algoFactory;
43+
this.algoOpts = algoOpts;
44+
}
45+
46+
@Override
47+
public List<Path> calcPaths(int from, int to, EdgeRestrictions edgeRestrictions) {
48+
if (!edgeRestrictions.getUnfavoredEdges().isEmpty())
49+
throw new IllegalArgumentException("Using unfavored edges is currently not supported for CH");
50+
RoutingAlgorithm algo = createAlgo();
51+
return calcPaths(from, to, edgeRestrictions, algo);
52+
}
53+
54+
private RoutingAlgorithm createAlgo() {
55+
StopWatch sw = new StopWatch().start();
56+
RoutingAlgorithm algo = algoFactory.createAlgo(queryGraph, algoOpts);
57+
debug = ", algoInit:" + (sw.stop().getNanos() / 1000) + " μs";
58+
return algo;
59+
}
60+
61+
private List<Path> calcPaths(int from, int to, EdgeRestrictions edgeRestrictions, RoutingAlgorithm algo) {
62+
StopWatch sw = new StopWatch().start();
63+
List<Path> paths;
64+
if (edgeRestrictions.getSourceOutEdge() != ANY_EDGE || edgeRestrictions.getTargetInEdge() != ANY_EDGE) {
65+
if (!(algo instanceof BidirRoutingAlgorithm))
66+
throw new IllegalArgumentException("To make use of the " + Parameters.Routing.CURBSIDE + " parameter you need a bidirectional algorithm, got: " + algo.getName());
67+
paths = Collections.singletonList(((BidirRoutingAlgorithm) algo).calcPath(from, to, queryGraph.shiftEdgeId(edgeRestrictions.getSourceOutEdge()), queryGraph.shiftEdgeId(edgeRestrictions.getTargetInEdge())));
68+
} else {
69+
paths = algo.calcPaths(from, to);
70+
}
71+
if (paths.isEmpty())
72+
throw new IllegalStateException("Path list was empty for " + from + " -> " + to);
73+
int maxVisitedNodes = algoOpts.getInt(MAX_VISITED_NODES, Integer.MAX_VALUE);
74+
if (algo.getVisitedNodes() >= maxVisitedNodes)
75+
throw new IllegalArgumentException("No path found due to maximum nodes exceeded " + maxVisitedNodes);
76+
visitedNodes = algo.getVisitedNodes();
77+
debug += ", " + algo.getName() + "-routing:" + sw.stop().getMillis() + " ms";
78+
return paths;
79+
}
80+
81+
@Override
82+
public String getDebugString() {
83+
return debug;
84+
}
85+
86+
@Override
87+
public int getVisitedNodes() {
88+
return visitedNodes;
89+
}
90+
91+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.graphhopper.routing;
20+
21+
import com.carrotsearch.hppc.IntArrayList;
22+
23+
import static com.graphhopper.util.EdgeIterator.ANY_EDGE;
24+
25+
public class EdgeRestrictions {
26+
private int sourceOutEdge = ANY_EDGE;
27+
private int targetInEdge = ANY_EDGE;
28+
private final IntArrayList unfavoredEdges = IntArrayList.from();
29+
30+
public int getSourceOutEdge() {
31+
return sourceOutEdge;
32+
}
33+
34+
public void setSourceOutEdge(int sourceOutEdge) {
35+
this.sourceOutEdge = sourceOutEdge;
36+
}
37+
38+
public int getTargetInEdge() {
39+
return targetInEdge;
40+
}
41+
42+
public void setTargetInEdge(int targetInEdge) {
43+
this.targetInEdge = targetInEdge;
44+
}
45+
46+
public IntArrayList getUnfavoredEdges() {
47+
return unfavoredEdges;
48+
}
49+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.graphhopper.routing;
20+
21+
import com.carrotsearch.hppc.cursors.IntCursor;
22+
import com.graphhopper.routing.querygraph.QueryGraph;
23+
import com.graphhopper.util.Parameters;
24+
import com.graphhopper.util.StopWatch;
25+
26+
import java.util.Collections;
27+
import java.util.List;
28+
29+
import static com.graphhopper.util.EdgeIterator.ANY_EDGE;
30+
31+
public class FlexiblePathCalculator implements PathCalculator {
32+
private final QueryGraph queryGraph;
33+
private final RoutingAlgorithmFactory algoFactory;
34+
private AlgorithmOptions algoOpts;
35+
private String debug;
36+
private int visitedNodes;
37+
38+
public FlexiblePathCalculator(QueryGraph queryGraph, RoutingAlgorithmFactory algoFactory, AlgorithmOptions algoOpts) {
39+
this.queryGraph = queryGraph;
40+
this.algoFactory = algoFactory;
41+
this.algoOpts = algoOpts;
42+
}
43+
44+
@Override
45+
public List<Path> calcPaths(int from, int to, EdgeRestrictions edgeRestrictions) {
46+
RoutingAlgorithm algo = createAlgo();
47+
return calcPaths(from, to, edgeRestrictions, algo);
48+
}
49+
50+
private RoutingAlgorithm createAlgo() {
51+
StopWatch sw = new StopWatch().start();
52+
RoutingAlgorithm algo = algoFactory.createAlgo(queryGraph, algoOpts);
53+
debug = ", algoInit:" + (sw.stop().getNanos() / 1000) + " μs";
54+
return algo;
55+
}
56+
57+
private List<Path> calcPaths(int from, int to, EdgeRestrictions edgeRestrictions, RoutingAlgorithm algo) {
58+
StopWatch sw = new StopWatch().start();
59+
// todo: so far 'heading' is implemented like this: we mark the unfavored edges on the query graph and then
60+
// our weighting applies a penalty to these edges. however, this only works for virtual edges and to make
61+
// this compatible with edge-based routing we would have to use edge keys instead of edge ids. either way a
62+
// better approach seems to be making the weighting (or the algorithm for that matter) aware of the unfavored
63+
// edges directly without changing the graph
64+
for (IntCursor c : edgeRestrictions.getUnfavoredEdges())
65+
queryGraph.unfavorVirtualEdge(c.value);
66+
67+
List<Path> paths;
68+
if (edgeRestrictions.getSourceOutEdge() != ANY_EDGE || edgeRestrictions.getTargetInEdge() != ANY_EDGE) {
69+
if (!(algo instanceof BidirRoutingAlgorithm))
70+
throw new IllegalArgumentException("To make use of the " + Parameters.Routing.CURBSIDE + " parameter you need a bidirectional algorithm, got: " + algo.getName());
71+
paths = Collections.singletonList(((BidirRoutingAlgorithm) algo).calcPath(from, to, edgeRestrictions.getSourceOutEdge(), edgeRestrictions.getTargetInEdge()));
72+
} else {
73+
paths = algo.calcPaths(from, to);
74+
}
75+
76+
// reset all direction enforcements in queryGraph to avoid influencing next path
77+
// todo: is this correct? aren't we taking a second look at these edges later when we calc times or
78+
// instructions etc.?
79+
queryGraph.clearUnfavoredStatus();
80+
81+
if (paths.isEmpty())
82+
throw new IllegalStateException("Path list was empty for " + from + " -> " + to);
83+
if (algo.getVisitedNodes() >= algoOpts.getMaxVisitedNodes())
84+
throw new IllegalArgumentException("No path found due to maximum nodes exceeded " + algoOpts.getMaxVisitedNodes());
85+
visitedNodes = algo.getVisitedNodes();
86+
debug += ", " + algo.getName() + "-routing:" + sw.stop().getMillis() + " ms";
87+
return paths;
88+
}
89+
90+
@Override
91+
public String getDebugString() {
92+
return debug;
93+
}
94+
95+
@Override
96+
public int getVisitedNodes() {
97+
return visitedNodes;
98+
}
99+
100+
public AlgorithmOptions getAlgoOpts() {
101+
return algoOpts;
102+
}
103+
104+
public void setAlgoOpts(AlgorithmOptions algoOpts) {
105+
this.algoOpts = algoOpts;
106+
}
107+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.graphhopper.routing;
20+
21+
import com.carrotsearch.hppc.IntArrayList;
22+
23+
class MultiplePointsNotFoundException extends RuntimeException {
24+
25+
private final IntArrayList pointsNotFound;
26+
27+
MultiplePointsNotFoundException(IntArrayList pointsNotFound) {
28+
this.pointsNotFound = pointsNotFound;
29+
}
30+
31+
IntArrayList getPointsNotFound() {
32+
return pointsNotFound;
33+
}
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package com.graphhopper.routing;
20+
21+
import java.util.List;
22+
23+
/**
24+
* Implementations of this class allow repeatedly calculating paths for different start/target nodes and edge restrictions
25+
*/
26+
public interface PathCalculator {
27+
List<Path> calcPaths(int from, int to, EdgeRestrictions edgeRestrictions);
28+
29+
String getDebugString();
30+
31+
int getVisitedNodes();
32+
33+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private SPTEntry followParentsUntilRoot(SPTEntry sptEntry) {
7272
}
7373

7474
private void setExtractionTime(long nanos) {
75-
path.setDebugInfo("path extraction: " + nanos / 1000 + " micros");
75+
path.setDebugInfo("path extraction: " + nanos / 1000 + " μs");
7676
}
7777

7878
protected void onEdge(int edge, int adjNode, int prevEdge) {

0 commit comments

Comments
 (0)