Commit 3aa8ba97 authored by DaGal's avatar DaGal
Browse files

Optimizations for OneToMany routes

parent d762cdd2
......@@ -17,11 +17,11 @@
*/
package com.graphhopper;
import com.graphhopper.util.PMap;
import java.util.ArrayList;
import java.util.List;
import com.graphhopper.util.PMap;
/**
* Wrapper containing path and error output of GraphHopper.
* <p>
......@@ -77,12 +77,12 @@ public class GHResponse {
public String getDebugInfo() {
String str = debugInfo;
for (PathWrapper ar : pathWrappers) {
if (!str.isEmpty())
str += "; ";
str += ar.getDebugInfo();
}
// for (PathWrapper ar : pathWrappers) {
// if (!str.isEmpty())
// str += "; ";
//
// str += ar.getDebugInfo();
// }
return str;
}
......
......@@ -1080,6 +1080,7 @@ public class GraphHopper implements GraphHopperAPI {
Weighting weighting;
QueryGraph queryGraph;
sw = new StopWatch().start();
if (chFactoryDecorator.isEnabled() && !disableCH) {
boolean forceCHHeading = hints.getBool(CH.FORCE_HEADING, false);
if (!forceCHHeading && request.hasFavoredHeading(0))
......@@ -1105,6 +1106,7 @@ public class GraphHopper implements GraphHopperAPI {
weighting = createWeighting(hints, encoder, queryGraph);
ghRsp.addDebugInfo("tmode:" + tMode.toString());
}
ghRsp.addDebugInfo("graphLookup:" + sw.stop().getSeconds() + "s");
int maxVisitedNodesForRequest = hints.getInt(Routing.MAX_VISITED_NODES, maxVisitedNodes);
if (maxVisitedNodesForRequest > maxVisitedNodes)
......
......@@ -17,6 +17,16 @@
*/
package com.graphhopper.routing;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.carrotsearch.hppc.IntArrayList;
import com.carrotsearch.hppc.IntObjectMap;
import com.carrotsearch.hppc.predicates.IntObjectPredicate;
......@@ -31,13 +41,17 @@ import com.graphhopper.storage.GraphExtension;
import com.graphhopper.storage.NodeAccess;
import com.graphhopper.storage.TurnCostExtension;
import com.graphhopper.storage.index.QueryResult;
import com.graphhopper.util.*;
import com.graphhopper.util.AngleCalc;
import com.graphhopper.util.EdgeExplorer;
import com.graphhopper.util.EdgeIterator;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.Helper;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.BBox;
import com.graphhopper.util.shapes.GHPoint;
import com.graphhopper.util.shapes.GHPoint3D;
import java.util.*;
/**
* A class which is used to query the underlying graph with real GPS points. It does so by
* introducing virtual nodes and edges. It is lightweight in order to be created every time a new
......@@ -222,7 +236,7 @@ public class QueryGraph implements Graph {
// calculate snapped point and swap direction of closest edge if necessary
for (QueryResult res : resList) {
// Do not create virtual node for a query result if it is directly on a tower node or not found
if (res.getSnappedPosition() == QueryResult.Position.TOWER)
if (res.getSnappedPosition() == QueryResult.Position.TOWER || !res.isValid())
continue;
EdgeIteratorState closestEdge = res.getClosestEdge();
......
......@@ -19,7 +19,9 @@ package com.graphhopper.routing.template;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse;
......@@ -29,12 +31,12 @@ import com.graphhopper.routing.Path;
import com.graphhopper.routing.QueryGraph;
import com.graphhopper.routing.RoutingAlgorithm;
import com.graphhopper.routing.RoutingAlgorithmFactory;
import com.graphhopper.routing.util.DefaultEdgeFilter;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.storage.index.LocationIndex;
import com.graphhopper.storage.index.QueryResult;
import com.graphhopper.util.Parameters.Routing;
import com.graphhopper.util.PathMerger;
import com.graphhopper.util.PointList;
import com.graphhopper.util.Translation;
import com.graphhopper.util.shapes.GHPoint;
......@@ -43,20 +45,46 @@ import com.graphhopper.util.shapes.GHPoint;
*
* @author Peter Karich
*/
public class OneToManyRoutingTemplate extends ViaRoutingTemplate {
public class OneToManyRoutingTemplate extends AbstractRoutingTemplate implements RoutingTemplate {
protected final GHRequest ghRequest;
protected final GHResponse ghResponse;
protected final PathWrapper altResponse = new PathWrapper();
private final LocationIndex locationIndex;
// result from route
protected List<Path> pathList;
protected static Map<GHPoint, QueryResult> cache = new HashMap<>();
public OneToManyRoutingTemplate(GHRequest ghRequest, GHResponse ghRsp, LocationIndex locationIndex) {
super(ghRequest, ghRsp, locationIndex);
this.locationIndex = locationIndex;
this.ghRequest = ghRequest;
this.ghResponse = ghRsp;
}
@Override
public List<QueryResult> lookup(List<GHPoint> points, FlagEncoder encoder) {
return super.lookup(points, encoder);
if (points.size() < 2)
throw new IllegalArgumentException("At least 2 points have to be specified, but was:" + points.size());
EdgeFilter edgeFilter = new DefaultEdgeFilter(encoder);
queryResults = new ArrayList<>(points.size());
for (int placeIndex = 0; placeIndex < points.size(); placeIndex++) {
GHPoint point = points.get(placeIndex);
QueryResult res = cache.get(point);
if (res == null) {
res = locationIndex.findClosest(point.lat, point.lon, edgeFilter);
cache.put(point, res);
}
queryResults.add(res);
}
return queryResults;
}
@Override
public List<Path> calcPaths(QueryGraph queryGraph, RoutingAlgorithmFactory algoFactory, AlgorithmOptions algoOpts) {
long visitedNodesSum = 0L;
boolean viaTurnPenalty = ghRequest.getHints().getBool(Routing.PASS_THROUGH, false);
int pointCounts = ghRequest.getPoints().size();
pathList = new ArrayList<>(pointCounts - 1);
QueryResult fromQResult = queryResults.get(0);
......@@ -65,6 +93,9 @@ public class OneToManyRoutingTemplate extends ViaRoutingTemplate {
for (int placeIndex = 1; placeIndex < pointCounts; placeIndex++) {
QueryResult toQResult = queryResults.get(placeIndex);
if (!toQResult.isValid())
continue;
List<Path> tmpPathList = algo.calcPaths(fromQResult.getClosestNode(), toQResult.getClosestNode());
if (tmpPathList.isEmpty())
throw new IllegalStateException("At least one path has to be returned for " + fromQResult + " -> " + toQResult);
......@@ -100,16 +131,18 @@ public class OneToManyRoutingTemplate extends ViaRoutingTemplate {
throw new RuntimeException("Empty paths for alternative route calculation not expected");
// if alternative route calculation was done then create the responses from single paths
PointList wpList = getWaypoints();
altResponse.setWaypoints(wpList);
ghResponse.add(altResponse);
pathMerger.doWork(altResponse, Collections.singletonList(pathList.get(0)), tr);
for (int index = 1; index < pathList.size(); index++) {
PathWrapper tmpAltRsp = new PathWrapper();
tmpAltRsp.setWaypoints(wpList);
ghResponse.add(tmpAltRsp);
pathMerger.doWork(tmpAltRsp, Collections.singletonList(pathList.get(index)), tr);
}
return true;
}
@Override
public int getMaxRetries() {
return 1;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment