-
Notifications
You must be signed in to change notification settings - Fork 376
/
TargetGraphBuilder.java
120 lines (104 loc) 路 4.73 KB
/
TargetGraphBuilder.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package org.heigit.ors.matrix;
import com.carrotsearch.hppc.IntHashSet;
import com.graphhopper.routing.querygraph.QueryRoutingCHGraph;
import com.graphhopper.storage.RoutingCHEdgeExplorer;
import com.graphhopper.storage.RoutingCHEdgeIterator;
import com.graphhopper.storage.RoutingCHGraph;
import org.heigit.ors.routing.algorithms.SubGraph;
import org.heigit.ors.routing.graphhopper.extensions.edgefilters.core.ExclusiveDownwardSearchEdgeFilter;
import java.util.PriorityQueue;
import static org.heigit.ors.matrix.util.GraphUtils.isCoreNode;
public class TargetGraphBuilder {
RoutingCHGraph chGraph;
private int coreNodeLevel;
private int nodeCount;
/**
* Phase I: build shortest path tree from all target nodes to the core, only upwards in level.
* The EdgeFilter in use is a downward search edge filter with reverse access acceptance so that in the last phase of the algorithm, the targetGraph can be explored downwards
*
* @param targets the targets that form the seed for target graph building
*/
public TargetGraphResults prepareTargetGraph(int[] targets, RoutingCHGraph chGraph, boolean swap, int coreNodeLevel) {
PriorityQueue<Integer> localPrioQueue = new PriorityQueue<>(100);
ExclusiveDownwardSearchEdgeFilter downwardEdgeFilter = new ExclusiveDownwardSearchEdgeFilter(chGraph, swap);
RoutingCHEdgeExplorer edgeExplorer = swap ? chGraph.createOutEdgeExplorer()
: chGraph.createInEdgeExplorer();
SubGraph targetGraph = new SubGraph(chGraph);
IntHashSet coreExitPoints = new IntHashSet();
this.coreNodeLevel = coreNodeLevel;
this.chGraph = chGraph;
//Get node count from base graph, as chGraph should be a query graph with additional virtual nodes that are counted in chGraph.getNodes()
//TODO Refactoring : implement isVirtualNode in QueryRoutingCHGraph from underlying query graph for better style
if (chGraph instanceof QueryRoutingCHGraph)
this.nodeCount = chGraph.getBaseGraph().getBaseGraph().getNodes();
else
this.nodeCount = chGraph.getNodes();
addNodes(targetGraph, localPrioQueue, targets, coreExitPoints);
while (!localPrioQueue.isEmpty()) {
int node = localPrioQueue.poll();
RoutingCHEdgeIterator iter = edgeExplorer.setBaseNode(node);
downwardEdgeFilter.setBaseNode(node);
exploreEntry(targetGraph, localPrioQueue, downwardEdgeFilter, node, iter, coreExitPoints);
}
TargetGraphResults targetGraphResults = new TargetGraphResults();
targetGraphResults.setTargetGraph(targetGraph);
targetGraphResults.setCoreExitPoints(coreExitPoints);
return targetGraphResults;
}
/**
* Explore the target graph and build coreExitPoints
*
* @param localPrioQueue
* @param downwardEdgeFilter
* @param baseNode
* @param iter
*/
private void exploreEntry(SubGraph targetGraph, PriorityQueue<Integer> localPrioQueue, ExclusiveDownwardSearchEdgeFilter downwardEdgeFilter, int baseNode, RoutingCHEdgeIterator iter, IntHashSet coreExitPoints) {
while (iter.next()) {
if (!downwardEdgeFilter.accept(iter))
continue;
boolean isNewNode = targetGraph.addEdge(baseNode, iter, true);
int adjNode = iter.getAdjNode();
if (isCoreNode(chGraph, adjNode, nodeCount, coreNodeLevel))
coreExitPoints.add(adjNode);
else if (isNewNode)
localPrioQueue.add(adjNode);
}
}
/**
* Add nodes to target graph and prioQueue for target graph
*
* @param graph
* @param prioQueue
* @param nodes
*/
private void addNodes(SubGraph graph, PriorityQueue<Integer> prioQueue, int[] nodes, IntHashSet coreExitPoints) {
for (int i = 0; i < nodes.length; i++) {
int nodeId = nodes[i];
if (nodeId >= 0) {
if (graph != null)
graph.addEdge(nodeId, null, true);
if (isCoreNode(chGraph, nodeId, nodeCount, coreNodeLevel))
coreExitPoints.add(nodeId);
else
prioQueue.add(nodeId);
}
}
}
public static class TargetGraphResults {
SubGraph targetGraph;
IntHashSet coreExitPoints;
public SubGraph getTargetGraph() {
return targetGraph;
}
public void setTargetGraph(SubGraph targetGraph) {
this.targetGraph = targetGraph;
}
public IntHashSet getCoreExitPoints() {
return coreExitPoints;
}
public void setCoreExitPoints(IntHashSet coreExitPoints) {
this.coreExitPoints = coreExitPoints;
}
}
}