use of com.graphhopper.routing.ev.TurnCost in project graphhopper by graphhopper.
the class CHPreparationGraph method buildTurnCostFunctionFromTurnCostStorage.
/**
* Builds a turn cost function for a given graph('s turn cost storage) and a weighting.
* The trivial implementation would be simply returning {@link Weighting#calcTurnWeight}. However, it turned out
* that reading all turn costs for the current encoder and then storing them in separate arrays upfront speeds up
* edge-based CH preparation by about 25%. See #2084
*/
public static TurnCostFunction buildTurnCostFunctionFromTurnCostStorage(Graph graph, Weighting weighting) {
FlagEncoder encoder = weighting.getFlagEncoder();
String key = TurnCost.key(encoder.toString());
if (!encoder.hasEncodedValue(key))
return (inEdge, viaNode, outEdge) -> 0;
DecimalEncodedValue turnCostEnc = encoder.getDecimalEncodedValue(key);
TurnCostStorage turnCostStorage = graph.getTurnCostStorage();
// we maintain a list of inEdge/outEdge/turn-cost triples (we use two arrays for this) that is sorted by nodes
LongArrayList turnCostEdgePairs = new LongArrayList();
DoubleArrayList turnCosts = new DoubleArrayList();
// for each node we store the index of the first turn cost entry/triple in the list
final int[] turnCostNodes = new int[graph.getNodes() + 1];
TurnCostStorage.TurnRelationIterator tcIter = turnCostStorage.getAllTurnRelations();
int lastNode = -1;
while (tcIter.next()) {
int viaNode = tcIter.getViaNode();
if (viaNode < lastNode)
throw new IllegalStateException();
long edgePair = BitUtil.LITTLE.combineIntsToLong(tcIter.getFromEdge(), tcIter.getToEdge());
// note that as long as we only use OSM turn restrictions all the turn costs are infinite anyway
double turnCost = tcIter.getCost(turnCostEnc);
int index = turnCostEdgePairs.size();
turnCostEdgePairs.add(edgePair);
turnCosts.add(turnCost);
if (viaNode != lastNode) {
for (int i = lastNode + 1; i <= viaNode; i++) {
turnCostNodes[i] = index;
}
}
lastNode = viaNode;
}
for (int i = lastNode + 1; i <= turnCostNodes.length - 1; i++) {
turnCostNodes[i] = turnCostEdgePairs.size();
}
turnCostNodes[turnCostNodes.length - 1] = turnCostEdgePairs.size();
// currently the u-turn costs are the same for all junctions, so for now we just get them for one of them
double uTurnCosts = weighting.calcTurnWeight(1, 0, 1);
return (inEdge, viaNode, outEdge) -> {
if (!EdgeIterator.Edge.isValid(inEdge) || !EdgeIterator.Edge.isValid(outEdge))
return 0;
else if (inEdge == outEdge)
return uTurnCosts;
// traverse all turn cost entries we have for this viaNode and return the turn costs if we find a match
for (int i = turnCostNodes[viaNode]; i < turnCostNodes[viaNode + 1]; i++) {
long l = turnCostEdgePairs.get(i);
if (inEdge == BitUtil.LITTLE.getIntLow(l) && outEdge == BitUtil.LITTLE.getIntHigh(l))
return turnCosts.get(i);
}
return 0;
};
}
Aggregations