Skip to content

Commit

Permalink
Some minor refactoring picked from turncost_ch branch. (#1336)
Browse files Browse the repository at this point in the history
* Some random fixes picked from turncosts_ch branch.

* Fixes some typos and whitespace
* Adds visited nodes sum to via routing template debug info.

* Adds doSpecificWork() to AbstractAlgoPreparation.

* Adds utility methods to print unit test graphs to the console.

* Does some minor reworks.

* Renames AllEdgesIterator for easier merging.

Signed-off-by: ammagamma <contactammagamma@gmail.com>

* Fixes usages of default locale.

Signed-off-by: ammagamma <contactammagamma@gmail.com>

* Makes CH levels start counting at 0.

Signed-off-by: ammagamma <contactammagamma@gmail.com>

* Fixes another default locale.

Signed-off-by: ammagamma <contactammagamma@gmail.com>
  • Loading branch information
easbar authored and karussell committed Apr 18, 2018
1 parent 2ce37a3 commit 51c8a58
Show file tree
Hide file tree
Showing 26 changed files with 161 additions and 119 deletions.
7 changes: 4 additions & 3 deletions core/src/main/java/com/graphhopper/GraphHopper.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1066,6 +1066,7 @@ else if (ALT_ROUTE.equalsIgnoreCase(algoStr))
hints(hints). hints(hints).
build(); build();


// do the actual route calculation !
altPaths = routingTemplate.calcPaths(queryGraph, tmpAlgoFactory, algoOpts); altPaths = routingTemplate.calcPaths(queryGraph, tmpAlgoFactory, algoOpts);


boolean tmpEnableInstructions = hints.getBool(Routing.INSTRUCTIONS, enableInstructions); boolean tmpEnableInstructions = hints.getBool(Routing.INSTRUCTIONS, enableInstructions);
Expand Down Expand Up @@ -1219,9 +1220,9 @@ protected void cleanUp() {
preparation.setMinOneWayNetworkSize(minOneWayNetworkSize); preparation.setMinOneWayNetworkSize(minOneWayNetworkSize);
preparation.doWork(); preparation.doWork();
int currNodeCount = ghStorage.getNodes(); int currNodeCount = ghStorage.getNodes();
logger.info("edges: " + ghStorage.getAllEdges().length() + ", nodes " + currNodeCount logger.info("edges: " + Helper.nf(ghStorage.getAllEdges().length()) + ", nodes " + Helper.nf(currNodeCount)
+ ", there were " + preparation.getMaxSubnetworks() + ", there were " + Helper.nf(preparation.getMaxSubnetworks())
+ " subnetworks. removed them => " + (prevNodeCount - currNodeCount) + " subnetworks. removed them => " + Helper.nf(prevNodeCount - currNodeCount)
+ " less nodes"); + " less nodes");
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public Builder weighting(Weighting weighting) {
} }


/** /**
* For possible values see Parameters.Algorithms * For possible values see {@link Parameters.Algorithms}
*/ */
public Builder algorithm(String algorithm) { public Builder algorithm(String algorithm) {
this.opts.algorithm = algorithm; this.opts.algorithm = algorithm;
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/graphhopper/routing/Dijkstra.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public Dijkstra(Graph graph, Weighting weighting, TraversalMode tMode) {
} }


protected void initCollections(int size) { protected void initCollections(int size) {
fromHeap = new PriorityQueue<SPTEntry>(size); fromHeap = new PriorityQueue<>(size);
fromMap = new GHIntObjectHashMap<SPTEntry>(size); fromMap = new GHIntObjectHashMap<>(size);
} }


@Override @Override
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public Path extract() {
return this; return this;


if (sptEntry.adjNode != edgeTo.adjNode) if (sptEntry.adjNode != edgeTo.adjNode)
throw new IllegalStateException("Locations of the 'to'- and 'from'-Edge has to be the same." + toString() + ", fromEntry:" + sptEntry + ", toEntry:" + edgeTo); throw new IllegalStateException("Locations of the 'to'- and 'from'-Edge have to be the same. " + toString() + ", fromEntry:" + sptEntry + ", toEntry:" + edgeTo);


extractSW.start(); extractSW.start();
if (switchFromAndToSPTEntry) { if (switchFromAndToSPTEntry) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/graphhopper/routing/QueryGraph.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
* @author Peter Karich * @author Peter Karich
*/ */
public class QueryGraph implements Graph { public class QueryGraph implements Graph {
final static int VE_BASE = 0, VE_BASE_REV = 1, VE_ADJ = 2, VE_ADJ_REV = 3; static final int VE_BASE = 0, VE_BASE_REV = 1, VE_ADJ = 2, VE_ADJ_REV = 3;
private static final AngleCalc AC = Helper.ANGLE_CALC; private static final AngleCalc AC = Helper.ANGLE_CALC;
private final Graph mainGraph; private final Graph mainGraph;
private final NodeAccess mainNodeAccess; private final NodeAccess mainNodeAccess;
Expand All @@ -61,7 +61,7 @@ public class QueryGraph implements Graph {
private final QueryGraph baseGraph; private final QueryGraph baseGraph;
private final GraphExtension wrappedExtension; private final GraphExtension wrappedExtension;
// TODO when spreading it on different threads we need multiple independent explorers // TODO when spreading it on different threads we need multiple independent explorers
private final Map<Integer, EdgeExplorer> cacheMap = new HashMap<Integer, EdgeExplorer>(4); private final Map<Integer, EdgeExplorer> cacheMap = new HashMap<>(4);


// For every virtual node there are 4 edges: base-snap, snap-base, snap-adj, adj-snap. // For every virtual node there are 4 edges: base-snap, snap-base, snap-adj, adj-snap.
List<VirtualEdgeIteratorState> virtualEdges; List<VirtualEdgeIteratorState> virtualEdges;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
import static com.graphhopper.util.Parameters.CH.DISABLE; import static com.graphhopper.util.Parameters.CH.DISABLE;


/** /**
* This class implements the CH decorator and provides several helper methods related to CH * This class implements the CH decorator for the routing algorithm factory and provides several
* preparation and its vehicle profiles. * helper methods related to CH preparation and its vehicle profiles.
* *
* @author Peter Karich * @author Peter Karich
*/ */
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class NodeContractor {
void initFromGraph() { void initFromGraph() {
// todo: do we really need this method ? the problem is that ghStorage/prepareGraph can potentially be modified // todo: do we really need this method ? the problem is that ghStorage/prepareGraph can potentially be modified
// between the constructor call and contractNode,calcShortcutCount etc. ... // between the constructor call and contractNode,calcShortcutCount etc. ...
maxLevel = prepareGraph.getNodes() + 1; maxLevel = prepareGraph.getNodes();
maxEdgesCount = ghStorage.getAllEdges().length(); maxEdgesCount = ghStorage.getAllEdges().length();
ignoreNodeFilter = new IgnoreNodeFilter(prepareGraph, maxLevel); ignoreNodeFilter = new IgnoreNodeFilter(prepareGraph, maxLevel);
FlagEncoder prepareFlagEncoder = prepareWeighting.getFlagEncoder(); FlagEncoder prepareFlagEncoder = prepareWeighting.getFlagEncoder();
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.EdgeIteratorState;


/** /**
* Used in CH preparation and therefor assumed that all edges are of type CHEdgeIteratorState * Used in CH preparation and therefore assumed that all edges are of type CHEdgeIteratorState
* <p> * <p>
* *
* @author Peter Karich * @author Peter Karich
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@


import java.util.*; import java.util.*;


import static com.graphhopper.util.Helper.nf;
import static com.graphhopper.util.Parameters.Algorithms.ASTAR_BI; import static com.graphhopper.util.Parameters.Algorithms.ASTAR_BI;
import static com.graphhopper.util.Parameters.Algorithms.DIJKSTRA_BI; import static com.graphhopper.util.Parameters.Algorithms.DIJKSTRA_BI;


Expand Down Expand Up @@ -59,7 +60,7 @@ public class PrepareContractionHierarchies extends AbstractAlgoPreparation imple
private CHEdgeExplorer vehicleAllTmpExplorer; private CHEdgeExplorer vehicleAllTmpExplorer;
private CHEdgeExplorer calcPrioAllExplorer; private CHEdgeExplorer calcPrioAllExplorer;
private int maxLevel; private int maxLevel;
// the most important nodes comes last // nodes with highest priority come last
private GHTreeMapComposed sortedNodes; private GHTreeMapComposed sortedNodes;
private int oldPriorities[]; private int oldPriorities[];
private double meanDegree; private double meanDegree;
Expand All @@ -72,6 +73,7 @@ public class PrepareContractionHierarchies extends AbstractAlgoPreparation imple
private double periodTime; private double periodTime;
private double lazyTime; private double lazyTime;
private double neighborTime; private double neighborTime;
private int initSize;


public PrepareContractionHierarchies(Directory dir, GraphHopperStorage ghStorage, CHGraph chGraph, public PrepareContractionHierarchies(Directory dir, GraphHopperStorage ghStorage, CHGraph chGraph,
Weighting weighting, TraversalMode traversalMode) { Weighting weighting, TraversalMode traversalMode) {
Expand Down Expand Up @@ -156,14 +158,31 @@ public PrepareContractionHierarchies setContractedNodes(double nodesContracted)
} }


@Override @Override
public void doWork() { public void doSpecificWork() {
allSW.start(); allSW.start();
super.doWork();

initFromGraph(); initFromGraph();
runGraphContraction();

logger.info("took:" + (int) allSW.stop().getSeconds() + "s "
+ ", new shortcuts: " + nf(nodeContractor.getAddedShortcutsCount())
+ ", " + prepareWeighting
+ ", dijkstras:" + nf(nodeContractor.getDijkstraCount())
+ ", " + getTimesAsString()
+ ", meanDegree:" + (long) meanDegree
+ ", initSize:" + nf(initSize)
+ ", periodic:" + periodicUpdatesPercentage
+ ", lazy:" + lastNodesLazyUpdatePercentage
+ ", neighbor:" + neighborUpdatePercentage
+ ", " + Helper.getMemInfo());

int edgeCount = ghStorage.getAllEdges().length();
logger.info("graph now - num edges: {}, num nodes: {}, num shortcuts: {}",
nf(edgeCount), nf(ghStorage.getNodes()), nf(prepareGraph.getAllEdges().length() - edgeCount));
}

protected void runGraphContraction() {
if (!prepareNodes()) if (!prepareNodes())
return; return;

contractNodes(); contractNodes();
} }


Expand Down Expand Up @@ -201,7 +220,7 @@ public final boolean accept(EdgeIteratorState edgeState) {
} }
}; };


maxLevel = prepareGraph.getNodes() + 1; maxLevel = prepareGraph.getNodes();
vehicleAllExplorer = prepareGraph.createEdgeExplorer(allFilter); vehicleAllExplorer = prepareGraph.createEdgeExplorer(allFilter);
vehicleAllTmpExplorer = prepareGraph.createEdgeExplorer(allFilter); vehicleAllTmpExplorer = prepareGraph.createEdgeExplorer(allFilter);
calcPrioAllExplorer = prepareGraph.createEdgeExplorer(accessWithLevelFilter); calcPrioAllExplorer = prepareGraph.createEdgeExplorer(accessWithLevelFilter);
Expand Down Expand Up @@ -239,10 +258,10 @@ private void contractNodes() {
// no witness path can be found. this is not really what we want, but changing it requires re-optimizing the // no witness path can be found. this is not really what we want, but changing it requires re-optimizing the
// graph contraction parameters, because it affects the node contraction order. // graph contraction parameters, because it affects the node contraction order.
meanDegree = prepareGraph.getAllEdges().length() / prepareGraph.getNodes(); meanDegree = prepareGraph.getAllEdges().length() / prepareGraph.getNodes();
int level = 1; initSize = sortedNodes.getSize();
int level = 0;
long counter = 0; long counter = 0;
int initSize = sortedNodes.getSize(); long logSize = Math.round(Math.max(10, initSize / 100d * logMessagesPercentage));
long logSize = Math.round(Math.max(10, sortedNodes.getSize() / 100 * logMessagesPercentage));
if (logMessagesPercentage == 0) if (logMessagesPercentage == 0)
logSize = Integer.MAX_VALUE; logSize = Integer.MAX_VALUE;


Expand All @@ -261,7 +280,7 @@ private void contractNodes() {


// according to paper "Polynomial-time Construction of Contraction Hierarchies for Multi-criteria Objectives" by Funke and Storandt // according to paper "Polynomial-time Construction of Contraction Hierarchies for Multi-criteria Objectives" by Funke and Storandt
// we don't need to wait for all nodes to be contracted // we don't need to wait for all nodes to be contracted
long nodesToAvoidContract = Math.round((100 - nodesContractedPercentage) / 100 * sortedNodes.getSize()); long nodesToAvoidContract = Math.round((100 - nodesContractedPercentage) / 100d * sortedNodes.getSize());
StopWatch lazySW = new StopWatch(); StopWatch lazySW = new StopWatch();


// Recompute priority of uncontracted neighbors. // Recompute priority of uncontracted neighbors.
Expand Down Expand Up @@ -297,14 +316,7 @@ private void contractNodes() {
lazyTime += lazySW.getSeconds(); lazyTime += lazySW.getSeconds();
neighborTime += neighborSW.getSeconds(); neighborTime += neighborSW.getSeconds();


logger.info(Helper.nf(counter) + ", updates:" + updateCounter logStats(counter, updateCounter);
+ ", nodes: " + Helper.nf(sortedNodes.getSize())
+ ", shortcuts:" + Helper.nf(nodeContractor.getAddedShortcutsCount())
+ ", dijkstras:" + Helper.nf(nodeContractor.getDijkstraCount())
+ ", " + getTimesAsString()
+ ", meanDegree:" + (long) meanDegree
+ ", algo:" + nodeContractor.getPrepareAlgoMemoryUsage()
+ ", " + Helper.getMemInfo());


nodeContractor.resetDijkstraTime(); nodeContractor.resetDijkstraTime();
periodSW = new StopWatch(); periodSW = new StopWatch();
Expand Down Expand Up @@ -364,28 +376,18 @@ private void contractNodes() {
} }
} }


// Preparation works only once so we can release temporary data.
// The preparation object itself has to be intact to create the algorithm.
close();

dijkstraTime += nodeContractor.getDijkstraSeconds(); dijkstraTime += nodeContractor.getDijkstraSeconds();
periodTime += periodSW.getSeconds(); periodTime += periodSW.getSeconds();
lazyTime += lazySW.getSeconds(); lazyTime += lazySW.getSeconds();
neighborTime += neighborSW.getSeconds(); neighborTime += neighborSW.getSeconds();
logger.info("took:" + (int) allSW.stop().getSeconds() logStats(counter, updateCounter);
+ ", new shortcuts: " + Helper.nf(nodeContractor.getAddedShortcutsCount())
+ ", " + prepareWeighting // Preparation works only once so we can release temporary data.
+ ", dijkstras:" + nodeContractor.getDijkstraCount() // The preparation object itself has to be intact to create the algorithm.
+ ", " + getTimesAsString() close();
+ ", meanDegree:" + (long) meanDegree
+ ", initSize:" + initSize
+ ", periodic:" + periodicUpdatesPercentage
+ ", lazy:" + lastNodesLazyUpdatePercentage
+ ", neighbor:" + neighborUpdatePercentage
+ ", " + Helper.getMemInfo());
} }


public void close() { private void close() {
nodeContractor.close(); nodeContractor.close();
sortedNodes = null; sortedNodes = null;
oldPriorities = null; oldPriorities = null;
Expand Down Expand Up @@ -420,10 +422,9 @@ public Weighting getWeighting() {
} }


private String getTimesAsString() { private String getTimesAsString() {
return "t(dijk):" + Helper.round2(dijkstraTime) return String.format(Locale.ROOT,
+ ", t(period):" + Helper.round2(periodTime) "t(dijk): %6.2f, t(period): %6.2f, t(lazy): %6.2f, t(neighbor): %6.2f",
+ ", t(lazy):" + Helper.round2(lazyTime) dijkstraTime, periodTime, lazyTime, neighborTime);
+ ", t(neighbor):" + Helper.round2(neighborTime);
} }


/** /**
Expand Down Expand Up @@ -481,4 +482,12 @@ public String toString() {
return "prepare|dijkstrabi|ch"; return "prepare|dijkstrabi|ch";
} }


private void logStats(long counter, int updateCounter) {
logger.info(String.format(Locale.ROOT,
"%10s, updates: %2d, nodes: %10s, shortcuts: %10s, dijkstras: %10s, %s, meanDegree: %2d, %s, %s",
nf(counter), updateCounter, nf(sortedNodes.getSize()),
nf(nodeContractor.getAddedShortcutsCount()), nf(nodeContractor.getDijkstraCount()),
getTimesAsString(), (long) meanDegree, nodeContractor.getPrepareAlgoMemoryUsage(),
Helper.getMemInfo()));
}
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -122,9 +122,7 @@ public boolean loadExisting() {
} }


@Override @Override
public void doWork() { public void doSpecificWork() {
super.doWork();

StopWatch sw = new StopWatch().start(); StopWatch sw = new StopWatch().start();
LOGGER.info("Start calculating " + lms.getLandmarkCount() + " landmarks, default active lms:" LOGGER.info("Start calculating " + lms.getLandmarkCount() + " landmarks, default active lms:"
+ defaultActiveLandmarks + ", weighting:" + lms.getLmSelectionWeighting() + ", " + Helper.getMemInfo()); + defaultActiveLandmarks + ", weighting:" + lms.getLmSelectionWeighting() + ", " + Helper.getMemInfo());
Expand All @@ -141,7 +139,7 @@ public RoutingAlgorithm getDecoratedAlgorithm(Graph qGraph, RoutingAlgorithm alg
int activeLM = Math.max(1, opts.getHints().getInt(Landmark.ACTIVE_COUNT, defaultActiveLandmarks)); int activeLM = Math.max(1, opts.getHints().getInt(Landmark.ACTIVE_COUNT, defaultActiveLandmarks));
if (algo instanceof AStar) { if (algo instanceof AStar) {
if (!lms.isInitialized()) if (!lms.isInitialized())
throw new IllegalStateException("Initalize landmark storage before creating algorithms"); throw new IllegalStateException("Initialize landmark storage before creating algorithms");


double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStar.EPSILON, 1); double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStar.EPSILON, 1);
AStar astar = (AStar) algo; AStar astar = (AStar) algo;
Expand All @@ -150,7 +148,7 @@ public RoutingAlgorithm getDecoratedAlgorithm(Graph qGraph, RoutingAlgorithm alg
return algo; return algo;
} else if (algo instanceof AStarBidirection) { } else if (algo instanceof AStarBidirection) {
if (!lms.isInitialized()) if (!lms.isInitialized())
throw new IllegalStateException("Initalize landmark storage before creating algorithms"); throw new IllegalStateException("Initialize landmark storage before creating algorithms");


double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1); double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
AStarBidirection astarbi = (AStarBidirection) algo; AStarBidirection astarbi = (AStarBidirection) algo;
Expand All @@ -159,7 +157,7 @@ public RoutingAlgorithm getDecoratedAlgorithm(Graph qGraph, RoutingAlgorithm alg
return algo; return algo;
} else if (algo instanceof AlternativeRoute) { } else if (algo instanceof AlternativeRoute) {
if (!lms.isInitialized()) if (!lms.isInitialized())
throw new IllegalStateException("Initalize landmark storage before creating algorithms"); throw new IllegalStateException("Initialize landmark storage before creating algorithms");


double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1); double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
AlternativeRoute altRoute = (AlternativeRoute) algo; AlternativeRoute altRoute = (AlternativeRoute) algo;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public List<Path> calcPaths(QueryGraph queryGraph, RoutingAlgorithmFactory algoF
String debug = ", algoInit:" + sw.stop().getSeconds() + "s"; String debug = ", algoInit:" + sw.stop().getSeconds() + "s";


sw = new StopWatch().start(); sw = new StopWatch().start();

// calculate paths
List<Path> tmpPathList = algo.calcPaths(fromQResult.getClosestNode(), toQResult.getClosestNode()); List<Path> tmpPathList = algo.calcPaths(fromQResult.getClosestNode(), toQResult.getClosestNode());
debug += ", " + algo.getName() + "-routing:" + sw.stop().getSeconds() + "s"; debug += ", " + algo.getName() + "-routing:" + sw.stop().getSeconds() + "s";
if (tmpPathList.isEmpty()) if (tmpPathList.isEmpty())
Expand All @@ -136,6 +138,7 @@ public List<Path> calcPaths(QueryGraph queryGraph, RoutingAlgorithmFactory algoF
throw new IllegalArgumentException("No path found due to maximum nodes exceeded " + algoOpts.getMaxVisitedNodes()); throw new IllegalArgumentException("No path found due to maximum nodes exceeded " + algoOpts.getMaxVisitedNodes());


visitedNodesSum += algo.getVisitedNodes(); visitedNodesSum += algo.getVisitedNodes();
altResponse.addDebugInfo("visited nodes sum: " + visitedNodesSum);
fromQResult = toQResult; fromQResult = toQResult;
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public abstract class AbstractAlgoPreparation {
public void doWork() { public void doWork() {
if (prepared) if (prepared)
throw new IllegalStateException("Call doWork only once!"); throw new IllegalStateException("Call doWork only once!");

prepared = true; prepared = true;
doSpecificWork();
} }


protected abstract void doSpecificWork();

public boolean isPrepared() { public boolean isPrepared() {
return prepared; return prepared;
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ else if (maxTurnCosts == 1) {
if (costs != 0 || Double.isInfinite(costs)) if (costs != 0 || Double.isInfinite(costs))
throw new IllegalArgumentException("Restricted turn can only have infinite costs (or use 0)"); throw new IllegalArgumentException("Restricted turn can only have infinite costs (or use 0)");
} else if (costs >= maxTurnCosts) } else if (costs >= maxTurnCosts)
throw new IllegalArgumentException("Cost is too high. Or specifiy restricted == true"); throw new IllegalArgumentException("Cost is too high. Or specify restricted == true");


if (costs < 0) if (costs < 0)
throw new IllegalArgumentException("Turn costs cannot be negative"); throw new IllegalArgumentException("Turn costs cannot be negative");
Expand Down Expand Up @@ -682,7 +682,7 @@ public double getDouble(long flags, int key) {
*/ */
protected double applyMaxSpeed(ReaderWay way, double speed) { protected double applyMaxSpeed(ReaderWay way, double speed) {
double maxSpeed = getMaxSpeed(way); double maxSpeed = getMaxSpeed(way);
// We obay speed limits // We obey speed limits
if (maxSpeed >= 0) { if (maxSpeed >= 0) {
// We assume that the average speed is 90% of the allowed maximum // We assume that the average speed is 90% of the allowed maximum
return maxSpeed * 0.9; return maxSpeed * 0.9;
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.EdgeIteratorState;


/** /**
* Only certain nodes are accepted and therefor the others are ignored. * Only accepts edges leading to equal and higher level nodes. Used in CH preparation.
* <p> * <p>
* *
* @author Peter Karich * @author Peter Karich
Expand Down
Loading

0 comments on commit 51c8a58

Please sign in to comment.