use of com.graphhopper.util.shapes.GHPoint in project graphhopper by graphhopper.
the class GraphHopper method calcPaths.
/**
* This method calculates the alternative path list using the low level Path objects.
*/
public List<Path> calcPaths(GHRequest request, GHResponse ghRsp) {
if (ghStorage == null || !fullyLoaded)
throw new IllegalStateException("Do a successful call to load or importOrLoad before routing");
if (ghStorage.isClosed())
throw new IllegalStateException("You need to create a new GraphHopper instance as it is already closed");
// default handling
String vehicle = request.getVehicle();
if (vehicle.isEmpty()) {
vehicle = getDefaultVehicle().toString();
request.setVehicle(vehicle);
}
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
if (!encodingManager.supports(vehicle))
throw new IllegalArgumentException("Vehicle " + vehicle + " unsupported. " + "Supported are: " + getEncodingManager());
HintsMap hints = request.getHints();
String tModeStr = hints.get("traversal_mode", traversalMode.toString());
TraversalMode tMode = TraversalMode.fromString(tModeStr);
if (hints.has(Routing.EDGE_BASED))
tMode = hints.getBool(Routing.EDGE_BASED, false) ? TraversalMode.EDGE_BASED_2DIR : TraversalMode.NODE_BASED;
FlagEncoder encoder = encodingManager.getEncoder(vehicle);
boolean disableCH = hints.getBool(CH.DISABLE, false);
if (!chFactoryDecorator.isDisablingAllowed() && disableCH)
throw new IllegalArgumentException("Disabling CH not allowed on the server-side");
boolean disableLM = hints.getBool(Landmark.DISABLE, false);
if (!lmFactoryDecorator.isDisablingAllowed() && disableLM)
throw new IllegalArgumentException("Disabling LM not allowed on the server-side");
String algoStr = request.getAlgorithm();
if (algoStr.isEmpty())
algoStr = chFactoryDecorator.isEnabled() && !disableCH ? DIJKSTRA_BI : ASTAR_BI;
List<GHPoint> points = request.getPoints();
// TODO Maybe we should think about a isRequestValid method that checks all that stuff that we could do to fail fast
// For example see #734
checkIfPointsAreInBounds(points);
RoutingTemplate routingTemplate;
if (ROUND_TRIP.equalsIgnoreCase(algoStr))
routingTemplate = new RoundTripRoutingTemplate(request, ghRsp, locationIndex, maxRoundTripRetries);
else if (ALT_ROUTE.equalsIgnoreCase(algoStr))
routingTemplate = new AlternativeRoutingTemplate(request, ghRsp, locationIndex);
else
routingTemplate = new ViaRoutingTemplate(request, ghRsp, locationIndex);
List<Path> altPaths = null;
int maxRetries = routingTemplate.getMaxRetries();
Locale locale = request.getLocale();
Translation tr = trMap.getWithFallBack(locale);
for (int i = 0; i < maxRetries; i++) {
StopWatch sw = new StopWatch().start();
List<QueryResult> qResults = routingTemplate.lookup(points, encoder);
ghRsp.addDebugInfo("idLookup:" + sw.stop().getSeconds() + "s");
if (ghRsp.hasErrors())
return Collections.emptyList();
RoutingAlgorithmFactory tmpAlgoFactory = getAlgorithmFactory(hints);
Weighting weighting;
QueryGraph queryGraph;
if (chFactoryDecorator.isEnabled() && !disableCH) {
boolean forceCHHeading = hints.getBool(CH.FORCE_HEADING, false);
if (!forceCHHeading && request.hasFavoredHeading(0))
throw new IllegalArgumentException("Heading is not (fully) supported for CHGraph. See issue #483");
// if LM is enabled we have the LMFactory with the CH algo!
RoutingAlgorithmFactory chAlgoFactory = tmpAlgoFactory;
if (tmpAlgoFactory instanceof LMAlgoFactoryDecorator.LMRAFactory)
chAlgoFactory = ((LMAlgoFactoryDecorator.LMRAFactory) tmpAlgoFactory).getDefaultAlgoFactory();
if (chAlgoFactory instanceof PrepareContractionHierarchies)
weighting = ((PrepareContractionHierarchies) chAlgoFactory).getWeighting();
else
throw new IllegalStateException("Although CH was enabled a non-CH algorithm factory was returned " + tmpAlgoFactory);
tMode = getCHFactoryDecorator().getNodeBase();
queryGraph = new QueryGraph(ghStorage.getGraph(CHGraph.class, weighting));
queryGraph.lookup(qResults);
} else {
checkNonChMaxWaypointDistance(points);
queryGraph = new QueryGraph(ghStorage);
queryGraph.lookup(qResults);
weighting = createWeighting(hints, encoder, queryGraph);
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);
weighting = createTurnWeighting(queryGraph, weighting, tMode);
AlgorithmOptions algoOpts = AlgorithmOptions.start().algorithm(algoStr).traversalMode(tMode).weighting(weighting).maxVisitedNodes(maxVisitedNodesForRequest).hints(hints).build();
altPaths = routingTemplate.calcPaths(queryGraph, tmpAlgoFactory, algoOpts);
boolean tmpEnableInstructions = hints.getBool(Routing.INSTRUCTIONS, enableInstructions);
boolean tmpCalcPoints = hints.getBool(Routing.CALC_POINTS, calcPoints);
double wayPointMaxDistance = hints.getDouble(Routing.WAY_POINT_MAX_DISTANCE, 1d);
DouglasPeucker peucker = new DouglasPeucker().setMaxDistance(wayPointMaxDistance);
PathMerger pathMerger = new PathMerger().setCalcPoints(tmpCalcPoints).setDouglasPeucker(peucker).setEnableInstructions(tmpEnableInstructions).setPathDetailsBuilders(pathBuilderFactory, request.getPathDetails()).setSimplifyResponse(simplifyResponse && wayPointMaxDistance > 0);
if (request.hasFavoredHeading(0))
pathMerger.setFavoredHeading(request.getFavoredHeading(0));
if (routingTemplate.isReady(pathMerger, tr))
break;
}
return altPaths;
} catch (IllegalArgumentException ex) {
ghRsp.addError(ex);
return Collections.emptyList();
} finally {
readLock.unlock();
}
}
use of com.graphhopper.util.shapes.GHPoint in project graphhopper by graphhopper.
the class InstructionsHelper method getPointForOrientationCalculation.
static GHPoint getPointForOrientationCalculation(EdgeIteratorState edgeIteratorState, NodeAccess nodeAccess) {
double tmpLat;
double tmpLon;
PointList tmpWayGeo = edgeIteratorState.fetchWayGeometry(3);
if (tmpWayGeo.getSize() <= 2) {
tmpLat = nodeAccess.getLatitude(edgeIteratorState.getAdjNode());
tmpLon = nodeAccess.getLongitude(edgeIteratorState.getAdjNode());
} else {
tmpLat = tmpWayGeo.getLatitude(1);
tmpLon = tmpWayGeo.getLongitude(1);
}
return new GHPoint(tmpLat, tmpLon);
}
use of com.graphhopper.util.shapes.GHPoint in project graphhopper by graphhopper.
the class QueryGraph method lookup.
/**
* For all specified query results calculate snapped point and if necessary set closest node
* to a virtual one and reverse closest edge. Additionally the wayIndex can change if an edge is
* swapped.
*
* @see QueryGraph
*/
public void lookup(List<QueryResult> resList) {
if (isInitialized())
throw new IllegalStateException("Call lookup only once. Otherwise you'll have problems for queries sharing the same edge.");
// initialize all none-final variables
virtualEdges = new ArrayList<VirtualEdgeIteratorState>(resList.size() * 2);
virtualNodes = new PointList(resList.size(), mainNodeAccess.is3D());
queryResults = new ArrayList<QueryResult>(resList.size());
baseGraph.virtualEdges = virtualEdges;
baseGraph.virtualNodes = virtualNodes;
baseGraph.queryResults = queryResults;
GHIntObjectHashMap<List<QueryResult>> edge2res = new GHIntObjectHashMap<List<QueryResult>>(resList.size());
// 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)
continue;
EdgeIteratorState closestEdge = res.getClosestEdge();
if (closestEdge == null)
throw new IllegalStateException("Do not call QueryGraph.lookup with invalid QueryResult " + res);
int base = closestEdge.getBaseNode();
// Force the identical direction for all closest edges.
// It is important to sort multiple results for the same edge by its wayIndex
boolean doReverse = base > closestEdge.getAdjNode();
if (base == closestEdge.getAdjNode()) {
// check for special case #162 where adj == base and force direction via latitude comparison
PointList pl = closestEdge.fetchWayGeometry(0);
if (pl.size() > 1)
doReverse = pl.getLatitude(0) > pl.getLatitude(pl.size() - 1);
}
if (doReverse) {
closestEdge = closestEdge.detach(true);
PointList fullPL = closestEdge.fetchWayGeometry(3);
res.setClosestEdge(closestEdge);
if (res.getSnappedPosition() == QueryResult.Position.PILLAR)
// ON pillar node
res.setWayIndex(fullPL.getSize() - res.getWayIndex() - 1);
else
// for case "OFF pillar node"
res.setWayIndex(fullPL.getSize() - res.getWayIndex() - 2);
if (res.getWayIndex() < 0)
throw new IllegalStateException("Problem with wayIndex while reversing closest edge:" + closestEdge + ", " + res);
}
// find multiple results on same edge
int edgeId = closestEdge.getEdge();
List<QueryResult> list = edge2res.get(edgeId);
if (list == null) {
list = new ArrayList<QueryResult>(5);
edge2res.put(edgeId, list);
}
list.add(res);
}
// Phase 2 - now it is clear which points cut one edge
// 1. create point lists
// 2. create virtual edges between virtual nodes and its neighbor (virtual or normal nodes)
edge2res.forEach(new IntObjectPredicate<List<QueryResult>>() {
@Override
public boolean apply(int edgeId, List<QueryResult> results) {
// we can expect at least one entry in the results
EdgeIteratorState closestEdge = results.get(0).getClosestEdge();
final PointList fullPL = closestEdge.fetchWayGeometry(3);
int baseNode = closestEdge.getBaseNode();
// sort results on the same edge by the wayIndex and if equal by distance to pillar node
Collections.sort(results, new Comparator<QueryResult>() {
@Override
public int compare(QueryResult o1, QueryResult o2) {
int diff = o1.getWayIndex() - o2.getWayIndex();
if (diff == 0) {
// sort by distance from snappedPoint to fullPL.get(wayIndex) if wayIndex is identical
GHPoint p1 = o1.getSnappedPoint();
GHPoint p2 = o2.getSnappedPoint();
if (p1.equals(p2))
return 0;
double fromLat = fullPL.getLatitude(o1.getWayIndex());
double fromLon = fullPL.getLongitude(o1.getWayIndex());
if (Helper.DIST_PLANE.calcNormalizedDist(fromLat, fromLon, p1.lat, p1.lon) > Helper.DIST_PLANE.calcNormalizedDist(fromLat, fromLon, p2.lat, p2.lon))
return 1;
return -1;
}
return diff;
}
});
GHPoint3D prevPoint = fullPL.toGHPoint(0);
int adjNode = closestEdge.getAdjNode();
int origTraversalKey = GHUtility.createEdgeKey(baseNode, adjNode, closestEdge.getEdge(), false);
int origRevTraversalKey = GHUtility.createEdgeKey(baseNode, adjNode, closestEdge.getEdge(), true);
long reverseFlags = closestEdge.detach(true).getFlags();
int prevWayIndex = 1;
int prevNodeId = baseNode;
int virtNodeId = virtualNodes.getSize() + mainNodes;
boolean addedEdges = false;
// fullPL into the right pieces.
for (int counter = 0; counter < results.size(); counter++) {
QueryResult res = results.get(counter);
if (res.getClosestEdge().getBaseNode() != baseNode)
throw new IllegalStateException("Base nodes have to be identical but were not: " + closestEdge + " vs " + res.getClosestEdge());
GHPoint3D currSnapped = res.getSnappedPoint();
// no new virtual nodes if exactly the same snapped point
if (prevPoint.equals(currSnapped)) {
res.setClosestNode(prevNodeId);
continue;
}
queryResults.add(res);
createEdges(origTraversalKey, origRevTraversalKey, prevPoint, prevWayIndex, res.getSnappedPoint(), res.getWayIndex(), fullPL, closestEdge, prevNodeId, virtNodeId, reverseFlags);
virtualNodes.add(currSnapped.lat, currSnapped.lon, currSnapped.ele);
// add edges again to set adjacent edges for newVirtNodeId
if (addedEdges) {
virtualEdges.add(virtualEdges.get(virtualEdges.size() - 2));
virtualEdges.add(virtualEdges.get(virtualEdges.size() - 2));
}
addedEdges = true;
res.setClosestNode(virtNodeId);
prevNodeId = virtNodeId;
prevWayIndex = res.getWayIndex() + 1;
prevPoint = currSnapped;
virtNodeId++;
}
// two edges between last result and adjacent node are still missing if not all points skipped
if (addedEdges)
createEdges(origTraversalKey, origRevTraversalKey, prevPoint, prevWayIndex, fullPL.toGHPoint(fullPL.getSize() - 1), fullPL.getSize() - 2, fullPL, closestEdge, virtNodeId - 1, adjNode, reverseFlags);
return true;
}
});
}
use of com.graphhopper.util.shapes.GHPoint in project graphhopper by graphhopper.
the class GraphHopperIT method testMonacoEnforcedDirection.
@Test
public void testMonacoEnforcedDirection() {
GHRequest req = new GHRequest().addPoint(new GHPoint(43.741069, 7.426854), 0.).addPoint(new GHPoint(43.744445, 7.429483), 190.).setVehicle(vehicle).setWeighting("fastest");
req.getHints().put(Routing.HEADING_PENALTY, "300");
GHResponse rsp = hopper.route(req);
PathWrapper arsp = rsp.getBest();
assertEquals(874., arsp.getDistance(), 10.);
assertEquals(31, arsp.getPoints().getSize());
}
use of com.graphhopper.util.shapes.GHPoint in project graphhopper by graphhopper.
the class GraphHopperIT method testPathDetailsSamePoint.
@Test
public void testPathDetailsSamePoint() {
GraphHopper tmpHopper = new GraphHopperOSM().setOSMFile(DIR + "/north-bayreuth.osm.gz").setCHEnabled(false).setGraphHopperLocation(tmpGraphFile).setEncodingManager(new EncodingManager("car"));
tmpHopper.importOrLoad();
GHRequest req = new GHRequest().addPoint(new GHPoint(49.984352, 11.498802)).addPoint(new GHPoint(49.984352, 11.498802)).setVehicle("car").setWeighting("fastest").setPathDetails(Arrays.asList(Parameters.DETAILS.AVERAGE_SPEED));
GHResponse rsp = tmpHopper.route(req);
assertFalse(rsp.hasErrors());
}
Aggregations