Skip to content

Commit

Permalink
Remove TurnWeighting and handle turn weights within Weighting instead (
Browse files Browse the repository at this point in the history
…#1863)

* Calculate turn costs via TurnCostProvider within AbstractWeighting
* Move Weighting#calcWeight/Millis into static helper method in GHUtility
* Remove TurnWeighting and QueryGraphTurnCostStorage, add QueryGraphWeighting
* Move u_turn_costs parameter from CHProfile into (default) turn cost provider
  • Loading branch information
easbar committed Jan 28, 2020
1 parent 4811ff3 commit 4582ee0
Show file tree
Hide file tree
Showing 73 changed files with 810 additions and 686 deletions.
47 changes: 20 additions & 27 deletions core/src/main/java/com/graphhopper/GraphHopper.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.EDGE_OR_NODE;
import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.OFF;
import static com.graphhopper.routing.weighting.TurnCostProvider.NO_TURN_COST_PROVIDER;
import static com.graphhopper.routing.weighting.Weighting.INFINITE_U_TURN_COSTS;
import static com.graphhopper.util.Helper.*;
import static com.graphhopper.util.Parameters.Algorithms.*;
Expand Down Expand Up @@ -827,10 +828,10 @@ private void initCHAlgoFactoryDecorator() {

CHAlgoFactoryDecorator.EdgeBasedCHMode edgeBasedCHMode = chFactoryDecorator.getEdgeBasedCHMode();
if (!(edgeBasedCHMode == EDGE_OR_NODE && encoder.supportsTurnCosts())) {
chFactoryDecorator.addCHProfile(CHProfile.nodeBased(createWeighting(new HintsMap(chWeightingStr), encoder, null)));
chFactoryDecorator.addCHProfile(CHProfile.nodeBased(createWeighting(new HintsMap(chWeightingStr), encoder, null, NO_TURN_COST_PROVIDER)));
}
if (edgeBasedCHMode != OFF && encoder.supportsTurnCosts()) {
chFactoryDecorator.addCHProfile(CHProfile.edgeBased(createWeighting(new HintsMap(chWeightingStr), encoder, null), uTurnCosts));
chFactoryDecorator.addCHProfile(CHProfile.edgeBased(createWeighting(new HintsMap(chWeightingStr), encoder, null, new DefaultTurnCostProvider(encoder, ghStorage.getTurnCostStorage(), uTurnCosts))));
}
}
}
Expand All @@ -847,7 +848,8 @@ private void initLMAlgoFactoryDecorator() {

for (FlagEncoder encoder : encodingManager.fetchEdgeEncoders()) {
for (String lmWeightingStr : lmFactoryDecorator.getWeightingsAsStrings()) {
Weighting weighting = createWeighting(new HintsMap(lmWeightingStr), encoder, null);
// note that we do not consider turn costs during LM preparation?
Weighting weighting = createWeighting(new HintsMap(lmWeightingStr), encoder, null, NO_TURN_COST_PROVIDER);
lmFactoryDecorator.addWeighting(weighting);
}
}
Expand Down Expand Up @@ -936,23 +938,23 @@ void interpolateBridgesAndOrTunnels() {
* @return the weighting to be used for route calculation
* @see HintsMap
*/
public Weighting createWeighting(HintsMap hintsMap, FlagEncoder encoder, Graph graph) {
public Weighting createWeighting(HintsMap hintsMap, FlagEncoder encoder, Graph graph, TurnCostProvider turnCostProvider) {
String weightingStr = toLowerCase(hintsMap.getWeighting());
Weighting weighting = null;

if ("shortest".equalsIgnoreCase(weightingStr)) {
weighting = new ShortestWeighting(encoder);
weighting = new ShortestWeighting(encoder, turnCostProvider);
} else if ("fastest".equalsIgnoreCase(weightingStr) || weightingStr.isEmpty()) {
if (encoder.supports(PriorityWeighting.class))
weighting = new PriorityWeighting(encoder, hintsMap);
weighting = new PriorityWeighting(encoder, hintsMap, turnCostProvider);
else
weighting = new FastestWeighting(encoder, hintsMap);
weighting = new FastestWeighting(encoder, hintsMap, turnCostProvider);
} else if ("curvature".equalsIgnoreCase(weightingStr)) {
if (encoder.supports(CurvatureWeighting.class))
weighting = new CurvatureWeighting(encoder, hintsMap);
weighting = new CurvatureWeighting(encoder, hintsMap, turnCostProvider);

} else if ("short_fastest".equalsIgnoreCase(weightingStr)) {
weighting = new ShortFastestWeighting(encoder, hintsMap);
weighting = new ShortFastestWeighting(encoder, hintsMap, turnCostProvider);
}

if (weighting == null)
Expand All @@ -968,16 +970,6 @@ public Weighting createWeighting(HintsMap hintsMap, FlagEncoder encoder, Graph g
return weighting;
}

/**
* Potentially wraps the specified weighting into a TurnWeighting instance.
*/
public Weighting createTurnWeighting(Graph graph, Weighting weighting, TraversalMode tMode, double uTurnCosts) {
FlagEncoder encoder = weighting.getFlagEncoder();
if (encoder.supportsTurnCosts() && tMode.isEdgeBased())
return new TurnWeighting(weighting, graph.getTurnCostStorage(), uTurnCosts);
return weighting;
}

@Override
public GHResponse route(GHRequest request) {
GHResponse response = new GHResponse();
Expand Down Expand Up @@ -1056,6 +1048,14 @@ else if (ALT_ROUTE.equalsIgnoreCase(algoStr))
if (ghRsp.hasErrors())
return Collections.emptyList();

final int uTurnCostsInt = request.getHints().getInt(Routing.U_TURN_COSTS, INFINITE_U_TURN_COSTS);
if (uTurnCostsInt != INFINITE_U_TURN_COSTS && !tMode.isEdgeBased()) {
throw new IllegalArgumentException("Finite u-turn costs can only be used for edge-based routing, use `" + Routing.EDGE_BASED + "=true'");
}
TurnCostProvider turnCostProvider = (encoder.supportsTurnCosts() && tMode.isEdgeBased())
? new DefaultTurnCostProvider(encoder, ghStorage.getTurnCostStorage(), uTurnCostsInt)
: NO_TURN_COST_PROVIDER;

RoutingAlgorithmFactory tmpAlgoFactory = getAlgorithmFactory(hints);
Weighting weighting;
QueryGraph queryGraph;
Expand All @@ -1082,21 +1082,14 @@ else if (ALT_ROUTE.equalsIgnoreCase(algoStr))
} else {
checkNonChMaxWaypointDistance(points);
queryGraph = QueryGraph.lookup(ghStorage, qResults);
weighting = createWeighting(hints, encoder, queryGraph);
weighting = createWeighting(hints, encoder, queryGraph, turnCostProvider);
}
ghRsp.addDebugInfo("tmode:" + tMode.toString());

int maxVisitedNodesForRequest = hints.getInt(Routing.MAX_VISITED_NODES, maxVisitedNodes);
if (maxVisitedNodesForRequest > maxVisitedNodes)
throw new IllegalArgumentException("The max_visited_nodes parameter has to be below or equal to:" + maxVisitedNodes);

int uTurnCostInt = request.getHints().getInt(Routing.U_TURN_COSTS, INFINITE_U_TURN_COSTS);
if (uTurnCostInt != INFINITE_U_TURN_COSTS && !tMode.isEdgeBased()) {
throw new IllegalArgumentException("Finite u-turn costs can only be used for edge-based routing, use `" + Routing.EDGE_BASED + "=true'");
}
double uTurnCosts = uTurnCostInt == INFINITE_U_TURN_COSTS ? Double.POSITIVE_INFINITY : uTurnCostInt;
weighting = createTurnWeighting(queryGraph, weighting, tMode, uTurnCosts);

AlgorithmOptions algoOpts = AlgorithmOptions.start().
algorithm(algoStr).traversalMode(tMode).weighting(weighting).
maxVisitedNodes(maxVisitedNodesForRequest).
Expand Down
9 changes: 4 additions & 5 deletions core/src/main/java/com/graphhopper/routing/AStar.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.SPTEntry;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.Helper;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.*;

import java.util.PriorityQueue;

Expand Down Expand Up @@ -98,7 +95,9 @@ private void runAlgo() {
continue;

// todo: for #1776/#1835 move the access check into weighting
double tmpWeight = !outEdgeFilter.accept(iter) ? Double.POSITIVE_INFINITY : (weighting.calcWeight(iter, false, currEdge.edge) + currEdge.weightOfVisitedPath);
double tmpWeight = !outEdgeFilter.accept(iter)
? Double.POSITIVE_INFINITY
: (GHUtility.calcWeightWithTurnWeight(weighting, iter, false, currEdge.edge) + currEdge.weightOfVisitedPath);
if (Double.isInfinite(tmpWeight)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.graphhopper.util.EdgeExplorer;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;

import java.util.PriorityQueue;

Expand Down Expand Up @@ -218,7 +219,7 @@ protected double calcWeight(EdgeIteratorState iter, SPTEntry currEdge, boolean r
if (!access) {
return Double.POSITIVE_INFINITY;
}
return weighting.calcWeight(iter, reverse, getIncomingEdge(currEdge)) + currEdge.getWeightOfVisitedPath();
return GHUtility.calcWeightWithTurnWeight(weighting, iter, reverse, getIncomingEdge(currEdge)) + currEdge.getWeightOfVisitedPath();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

package com.graphhopper.routing;

import com.graphhopper.routing.weighting.TurnWeighting;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.SPTEntry;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.StopWatch;

/**
Expand Down Expand Up @@ -113,17 +113,15 @@ protected void onBwdTreeRoot(int node) {
protected void onEdge(int edge, int adjNode, boolean reverse, int prevOrNextEdge) {
EdgeIteratorState edgeState = graph.getEdgeIteratorState(edge, adjNode);
path.addDistance(edgeState.getDistance());
path.addTime(weighting.calcMillis(edgeState, reverse, prevOrNextEdge));
path.addTime(GHUtility.calcMillisWithTurnMillis(weighting, edgeState, reverse, prevOrNextEdge));
path.addEdge(edge);
}

protected void onMeetingPoint(int inEdge, int viaNode, int outEdge) {
if (!EdgeIterator.Edge.isValid(inEdge) || !EdgeIterator.Edge.isValid(outEdge)) {
return;
}
if (weighting instanceof TurnWeighting) {
path.addTime(((TurnWeighting) weighting).calcTurnMillis(inEdge, viaNode, outEdge));
}
path.addTime(weighting.calcTurnMillis(inEdge, viaNode, outEdge));
}

}
5 changes: 4 additions & 1 deletion core/src/main/java/com/graphhopper/routing/Dijkstra.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.graphhopper.storage.SPTEntry;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.Parameters;

import java.util.PriorityQueue;
Expand Down Expand Up @@ -79,7 +80,9 @@ protected void runAlgo() {
continue;

// todo: for #1776/#1835 move the access check into weighting
double tmpWeight = !outEdgeFilter.accept(iter) ? Double.POSITIVE_INFINITY : (weighting.calcWeight(iter, false, currEdge.edge) + currEdge.weight);
double tmpWeight = !outEdgeFilter.accept(iter)
? Double.POSITIVE_INFINITY
: (GHUtility.calcWeightWithTurnWeight(weighting, iter, false, currEdge.edge) + currEdge.weight);
if (Double.isInfinite(tmpWeight)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
import com.graphhopper.routing.util.TraversalMode;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.Helper;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.*;

import java.util.Arrays;

Expand Down Expand Up @@ -174,7 +171,9 @@ public int findEndNode(int from, int to) {
if (!accept(iter, prevEdgeId))
continue;

double tmpWeight = !outEdgeFilter.accept(iter) ? Double.POSITIVE_INFINITY : (weighting.calcWeight(iter, false, prevEdgeId) + weights[currNode]);
double tmpWeight = !outEdgeFilter.accept(iter)
? Double.POSITIVE_INFINITY
: (GHUtility.calcWeightWithTurnWeight(weighting, iter, false, prevEdgeId) + weights[currNode]);
if (Double.isInfinite(tmpWeight))
continue;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ private void updatePointsAndInstruction(EdgeIteratorState edge, PointList pl) {
}
double newDist = edge.getDistance();
prevInstruction.setDistance(newDist + prevInstruction.getDistance());
// todonow: why do we not account for turn times here ?
// todo: why do we not account for turn times here ?
prevInstruction.setTime(weighting.calcEdgeMillis(edge, false) + prevInstruction.getTime());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.graphhopper.storage.SPTEntry;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.StopWatch;

public class PathExtractor {
Expand Down Expand Up @@ -78,7 +79,7 @@ private void setExtractionTime(long nanos) {
protected void onEdge(int edge, int adjNode, int prevEdge) {
EdgeIteratorState edgeState = graph.getEdgeIteratorState(edge, adjNode);
path.addDistance(edgeState.getDistance());
path.addTime(weighting.calcMillis(edgeState, false, prevEdge));
path.addTime(GHUtility.calcMillisWithTurnMillis(weighting, edgeState, false, prevEdge));
path.addEdge(edge);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.graphhopper.routing.weighting.BeelineWeightApproximator;
import com.graphhopper.routing.weighting.WeightApproximator;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.NodeAccess;
import com.graphhopper.util.Helper;
Expand All @@ -37,27 +38,28 @@ public class RoutingAlgorithmFactorySimple implements RoutingAlgorithmFactory {
public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
RoutingAlgorithm ra;
String algoStr = opts.getAlgorithm();
Weighting weighting = g.wrapWeighting(opts.getWeighting());
if (DIJKSTRA_BI.equalsIgnoreCase(algoStr)) {
ra = new DijkstraBidirectionRef(g, opts.getWeighting(), opts.getTraversalMode());
ra = new DijkstraBidirectionRef(g, weighting, opts.getTraversalMode());
} else if (DIJKSTRA.equalsIgnoreCase(algoStr)) {
ra = new Dijkstra(g, opts.getWeighting(), opts.getTraversalMode());
ra = new Dijkstra(g, weighting, opts.getTraversalMode());

} else if (ASTAR_BI.equalsIgnoreCase(algoStr)) {
AStarBidirection aStarBi = new AStarBidirection(g, opts.getWeighting(),
AStarBidirection aStarBi = new AStarBidirection(g, weighting,
opts.getTraversalMode());
aStarBi.setApproximation(getApproximation(ASTAR_BI, opts, g.getNodeAccess()));
ra = aStarBi;

} else if (DIJKSTRA_ONE_TO_MANY.equalsIgnoreCase(algoStr)) {
ra = new DijkstraOneToMany(g, opts.getWeighting(), opts.getTraversalMode());
ra = new DijkstraOneToMany(g, weighting, opts.getTraversalMode());

} else if (ASTAR.equalsIgnoreCase(algoStr)) {
AStar aStar = new AStar(g, opts.getWeighting(), opts.getTraversalMode());
AStar aStar = new AStar(g, weighting, opts.getTraversalMode());
aStar.setApproximation(getApproximation(ASTAR, opts, g.getNodeAccess()));
ra = aStar;

} else if (ALT_ROUTE.equalsIgnoreCase(algoStr)) {
AlternativeRoute altRouteAlgo = new AlternativeRoute(g, opts.getWeighting(), opts.getTraversalMode());
AlternativeRoute altRouteAlgo = new AlternativeRoute(g, weighting, opts.getTraversalMode());
altRouteAlgo.setMaxPaths(opts.getHints().getInt(MAX_PATHS, 2));
altRouteAlgo.setMaxWeightFactor(opts.getHints().getDouble(MAX_WEIGHT, 1.4));
altRouteAlgo.setMaxShareFactor(opts.getHints().getDouble(MAX_SHARE, 0.6));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ private CHProfile select() {
if (edgeBased != null && p.isEdgeBased() != edgeBased) {
continue;
}
if (uTurnCosts != null && p.getUTurnCostsInt() != uTurnCosts) {
continue;
}
if (!p.getWeighting().matches(hintsMap)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
package com.graphhopper.routing.ch;

import com.graphhopper.routing.*;
import com.graphhopper.routing.weighting.TurnWeighting;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.*;

Expand Down Expand Up @@ -53,8 +52,7 @@ private RoutingAlgorithm doCreateAlgo(Graph graph, AlgorithmOptions opts) {
if (turnCostStorage == null) {
throw new IllegalArgumentException("For edge-based CH you need a turn cost extension");
}
TurnWeighting turnWeighting = new TurnWeighting(getWeighting(), turnCostStorage, chProfile.getUTurnCosts());
RoutingCHGraph g = new RoutingCHGraphImpl(graph, getWeighting(), turnWeighting);
RoutingCHGraph g = new RoutingCHGraphImpl(graph, graph.wrapWeighting(getWeighting()));
return createAlgoEdgeBased(g, opts);
} else {
RoutingCHGraph g = new RoutingCHGraphImpl(graph, chProfile.getWeighting());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
package com.graphhopper.routing.ch;

import com.graphhopper.routing.BidirPathExtractor;
import com.graphhopper.routing.weighting.TurnWeighting;
import com.graphhopper.storage.RoutingCHGraph;
import com.graphhopper.storage.SPTEntry;
import com.graphhopper.storage.ShortcutUnpacker;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;

/**
* @author easbar
Expand All @@ -36,9 +36,6 @@ public EdgeBasedCHBidirPathExtractor(RoutingCHGraph routingGraph) {
super(routingGraph.getGraph(), routingGraph.getWeighting());
this.routingGraph = routingGraph;
shortcutUnpacker = createShortcutUnpacker();
if (!(routingGraph.getWeighting() instanceof TurnWeighting)) {
throw new IllegalArgumentException("Need a TurnWeighting for edge-based CH");
}
}

@Override
Expand All @@ -55,7 +52,7 @@ private ShortcutUnpacker createShortcutUnpacker() {
@Override
public void visit(EdgeIteratorState edge, boolean reverse, int prevOrNextEdgeId) {
path.addDistance(edge.getDistance());
path.addTime(routingGraph.getWeighting().calcMillis(edge, reverse, prevOrNextEdgeId));
path.addTime(GHUtility.calcMillisWithTurnMillis(routingGraph.getWeighting(), edge, reverse, prevOrNextEdgeId));
path.addEdge(edge.getEdge());
}
}, true);
Expand Down

0 comments on commit 4582ee0

Please sign in to comment.