use of com.graphhopper.util.EdgeIteratorState in project graphhopper by graphhopper.
the class DijkstraBidirectionCHTest method runTestWithDirectionDependentEdgeSpeed.
private void runTestWithDirectionDependentEdgeSpeed(int speed, int revSpeed, int from, int to, IntArrayList expectedPath, FlagEncoder encoder) {
EncodingManager encodingManager = new EncodingManager(encoder);
FastestWeighting weighting = new FastestWeighting(encoder);
AlgorithmOptions algoOpts = AlgorithmOptions.start().weighting(weighting).build();
GraphHopperStorage graph = createGHStorage(encodingManager, Arrays.asList(weighting), false);
EdgeIteratorState edge = graph.edge(0, 1, 2, true);
long flags = edge.getFlags();
flags = encoder.setSpeed(flags, speed);
flags = encoder.setReverseSpeed(flags, revSpeed);
edge.setFlags(flags);
graph.edge(1, 2, 1, true);
CHGraph chGraph = graph.getGraph(CHGraph.class);
for (int i = 0; i < 3; ++i) {
chGraph.setLevel(i, i);
}
graph.freeze();
RoutingAlgorithm algo = createCHAlgo(graph, chGraph, true, algoOpts);
Path p = algo.calcPath(from, to);
assertEquals(3, p.getDistance(), 1.e-3);
assertEquals(p.toString(), expectedPath, p.calcNodes());
}
use of com.graphhopper.util.EdgeIteratorState in project graphhopper by graphhopper.
the class JTSTriangulator method triangulate.
public Result triangulate(Snap snap, QueryGraph queryGraph, ShortestPathTree shortestPathTree, ToDoubleFunction<ShortestPathTree.IsoLabel> fz, double tolerance) {
final NodeAccess na = queryGraph.getNodeAccess();
Collection<Coordinate> sites = new ArrayList<>();
shortestPathTree.search(snap.getClosestNode(), label -> {
double exploreValue = fz.applyAsDouble(label);
double lat = na.getLat(label.node);
double lon = na.getLon(label.node);
Coordinate site = new Coordinate(lon, lat);
site.z = exploreValue;
sites.add(site);
// add a pillar node to increase precision a bit for longer roads
if (label.parent != null) {
EdgeIteratorState edge = queryGraph.getEdgeIteratorState(label.edge, label.node);
PointList innerPoints = edge.fetchWayGeometry(FetchMode.PILLAR_ONLY);
if (innerPoints.size() > 0) {
int midIndex = innerPoints.size() / 2;
double lat2 = innerPoints.getLat(midIndex);
double lon2 = innerPoints.getLon(midIndex);
Coordinate site2 = new Coordinate(lon2, lat2);
site2.z = exploreValue;
sites.add(site2);
}
}
});
if (sites.size() > routerConfig.getMaxVisitedNodes() / 3)
throw new IllegalArgumentException("Too many nodes would be included in post processing (" + sites.size() + "). Let us know if you need this increased.");
// Sites may contain repeated coordinates. Especially for edge-based traversal, that's expected -- we visit
// each node multiple times.
// But that's okay, the triangulator de-dupes by itself, and it keeps the first z-value it sees, which is
// what we want.
Collection<ConstraintVertex> constraintVertices = sites.stream().map(ConstraintVertex::new).collect(Collectors.toList());
ConformingDelaunayTriangulator conformingDelaunayTriangulator = new ConformingDelaunayTriangulator(constraintVertices, tolerance);
conformingDelaunayTriangulator.setConstraints(new ArrayList<>(), new ArrayList<>());
conformingDelaunayTriangulator.formInitialDelaunay();
conformingDelaunayTriangulator.enforceConstraints();
Geometry convexHull = conformingDelaunayTriangulator.getConvexHull();
if (!(convexHull instanceof Polygon)) {
throw new IllegalArgumentException("Too few points found. " + "Please try a different 'point' or a larger 'time_limit'.");
}
QuadEdgeSubdivision tin = conformingDelaunayTriangulator.getSubdivision();
for (Vertex vertex : (Collection<Vertex>) tin.getVertices(true)) {
if (tin.isFrameVertex(vertex)) {
vertex.setZ(Double.MAX_VALUE);
}
}
ReadableTriangulation triangulation = ReadableTriangulation.wrap(tin);
return new Result(triangulation, triangulation.getEdges());
}
use of com.graphhopper.util.EdgeIteratorState in project graphhopper by graphhopper.
the class PtIsochroneResource method doGet.
@GET
@Produces({ MediaType.APPLICATION_JSON })
public Response doGet(@QueryParam("point") GHLocationParam sourceParam, @QueryParam("time_limit") @DefaultValue("600") long seconds, @QueryParam("reverse_flow") @DefaultValue("false") boolean reverseFlow, @QueryParam("pt.earliest_departure_time") @NotNull OffsetDateTimeParam departureTimeParam, @QueryParam("pt.blocked_route_types") @DefaultValue("0") int blockedRouteTypes, @QueryParam("result") @DefaultValue("multipolygon") String format) {
Instant initialTime = departureTimeParam.get().toInstant();
GHLocation location = sourceParam.get();
double targetZ = seconds * 1000;
GeometryFactory geometryFactory = new GeometryFactory();
final FlagEncoder footEncoder = encodingManager.getEncoder("foot");
final Weighting weighting = new FastestWeighting(footEncoder);
DefaultSnapFilter snapFilter = new DefaultSnapFilter(weighting, graphHopperStorage.getEncodingManager().getBooleanEncodedValue(Subnetwork.key("foot")));
PtLocationSnapper.Result snapResult = new PtLocationSnapper(graphHopperStorage, locationIndex, gtfsStorage).snapAll(Arrays.asList(location), Arrays.asList(snapFilter));
GraphExplorer graphExplorer = new GraphExplorer(snapResult.queryGraph, gtfsStorage.getPtGraph(), weighting, gtfsStorage, RealtimeFeed.empty(), reverseFlow, false, false, 5.0, reverseFlow, blockedRouteTypes);
MultiCriteriaLabelSetting router = new MultiCriteriaLabelSetting(graphExplorer, reverseFlow, false, false, 0, Collections.emptyList());
Map<Coordinate, Double> z1 = new HashMap<>();
NodeAccess nodeAccess = snapResult.queryGraph.getNodeAccess();
for (Label label : router.calcLabels(snapResult.nodes.get(0), initialTime)) {
if (!((label.currentTime - initialTime.toEpochMilli()) * (reverseFlow ? -1 : 1) <= targetZ)) {
break;
}
if (label.node.streetNode != -1) {
Coordinate nodeCoordinate = new Coordinate(nodeAccess.getLon(label.node.streetNode), nodeAccess.getLat(label.node.streetNode));
z1.merge(nodeCoordinate, (double) (label.currentTime - initialTime.toEpochMilli()) * (reverseFlow ? -1 : 1), Math::min);
} else if (label.edge != null && (label.edge.getType() == GtfsStorage.EdgeType.EXIT_PT || label.edge.getType() == GtfsStorage.EdgeType.ENTER_PT)) {
GtfsStorage.PlatformDescriptor platformDescriptor = label.edge.getPlatformDescriptor();
Stop stop = gtfsStorage.getGtfsFeeds().get(platformDescriptor.feed_id).stops.get(platformDescriptor.stop_id);
Coordinate nodeCoordinate = new Coordinate(stop.stop_lon, stop.stop_lat);
z1.merge(nodeCoordinate, (double) (label.currentTime - initialTime.toEpochMilli()) * (reverseFlow ? -1 : 1), Math::min);
}
}
if (format.equals("multipoint")) {
MultiPoint exploredPoints = geometryFactory.createMultiPointFromCoords(z1.keySet().toArray(new Coordinate[0]));
return wrap(exploredPoints);
} else {
MultiPoint exploredPoints = geometryFactory.createMultiPointFromCoords(z1.keySet().toArray(new Coordinate[0]));
// Get at least all nodes within our bounding box (I think convex hull would be enough.)
// I think then we should have all possible encroaching points. (Proof needed.)
locationIndex.query(BBox.fromEnvelope(exploredPoints.getEnvelopeInternal()), edgeId -> {
EdgeIteratorState edge = snapResult.queryGraph.getEdgeIteratorStateForKey(edgeId * 2);
z1.merge(new Coordinate(nodeAccess.getLon(edge.getBaseNode()), nodeAccess.getLat(edge.getBaseNode())), Double.MAX_VALUE, Math::min);
z1.merge(new Coordinate(nodeAccess.getLon(edge.getAdjNode()), nodeAccess.getLat(edge.getAdjNode())), Double.MAX_VALUE, Math::min);
});
exploredPoints = geometryFactory.createMultiPointFromCoords(z1.keySet().toArray(new Coordinate[0]));
CoordinateList siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(exploredPoints);
List<ConstraintVertex> constraintVertices = new ArrayList<>();
for (Object siteCoord : siteCoords) {
Coordinate coord = (Coordinate) siteCoord;
constraintVertices.add(new ConstraintVertex(coord));
}
ConformingDelaunayTriangulator cdt = new ConformingDelaunayTriangulator(constraintVertices, JTS_TOLERANCE);
cdt.setConstraints(new ArrayList(), new ArrayList());
cdt.formInitialDelaunay();
QuadEdgeSubdivision tin = cdt.getSubdivision();
for (Vertex vertex : (Collection<Vertex>) tin.getVertices(true)) {
if (tin.isFrameVertex(vertex)) {
vertex.setZ(Double.MAX_VALUE);
} else {
Double aDouble = z1.get(vertex.getCoordinate());
if (aDouble != null) {
vertex.setZ(aDouble);
} else {
vertex.setZ(Double.MAX_VALUE);
}
}
}
ReadableTriangulation triangulation = ReadableTriangulation.wrap(tin);
ContourBuilder contourBuilder = new ContourBuilder(triangulation);
MultiPolygon isoline = contourBuilder.computeIsoline(targetZ, triangulation.getEdges());
// debugging tool
if (format.equals("triangulation")) {
Response response = new Response();
for (Vertex vertex : (Collection<Vertex>) tin.getVertices(true)) {
JsonFeature feature = new JsonFeature();
feature.setGeometry(geometryFactory.createPoint(vertex.getCoordinate()));
HashMap<String, Object> properties = new HashMap<>();
properties.put("z", vertex.getZ());
feature.setProperties(properties);
response.polygons.add(feature);
}
for (QuadEdge edge : (Collection<QuadEdge>) tin.getPrimaryEdges(false)) {
JsonFeature feature = new JsonFeature();
feature.setGeometry(edge.toLineSegment().toGeometry(geometryFactory));
HashMap<String, Object> properties = new HashMap<>();
feature.setProperties(properties);
response.polygons.add(feature);
}
JsonFeature feature = new JsonFeature();
feature.setGeometry(isoline);
HashMap<String, Object> properties = new HashMap<>();
properties.put("z", targetZ);
feature.setProperties(properties);
response.polygons.add(feature);
response.info.copyrights.addAll(ResponsePathSerializer.COPYRIGHTS);
return response;
} else {
return wrap(isoline);
}
}
}
use of com.graphhopper.util.EdgeIteratorState in project graphhopper by graphhopper.
the class HeadingRoutingTest method calcNodes.
private int[] calcNodes(Graph graph, ResponsePath responsePath) {
List<PathDetail> edgeKeys = responsePath.getPathDetails().get("edge_key");
int[] result = new int[edgeKeys.size() + 1];
for (int i = 0; i < edgeKeys.size(); i++) {
int edgeKey = (int) edgeKeys.get(i).getValue();
int edgeId = edgeKey / 2;
EdgeIteratorState edgeIteratorState = graph.getEdgeIteratorState(edgeId, Integer.MIN_VALUE);
result[i] = edgeKey % 2 == 0 ? edgeIteratorState.getBaseNode() : edgeIteratorState.getAdjNode();
if (i == edgeKeys.size() - 1)
result[edgeKeys.size()] = edgeKey % 2 == 0 ? edgeIteratorState.getAdjNode() : edgeIteratorState.getBaseNode();
}
return result;
}
use of com.graphhopper.util.EdgeIteratorState in project graphhopper by graphhopper.
the class CHQueryWithTurnCostsTest method testFindPath_shortcutLoopIsRecognizedAsIncomingEdge.
@ParameterizedTest
@ArgumentsSource(FixtureProvider.class)
public void testFindPath_shortcutLoopIsRecognizedAsIncomingEdge(Fixture f) {
// -0-
// \ /
// 3 -- 4 -- 2 -- 1
EdgeIteratorState edge0 = GHUtility.setSpeed(60, true, true, f.encoder, f.graph.edge(3, 4).setDistance(1));
EdgeIteratorState edge1 = GHUtility.setSpeed(60, true, true, f.encoder, f.graph.edge(4, 2).setDistance(1));
EdgeIteratorState edge2 = GHUtility.setSpeed(60, true, false, f.encoder, f.graph.edge(2, 0).setDistance(1));
EdgeIteratorState edge3 = GHUtility.setSpeed(60, true, false, f.encoder, f.graph.edge(0, 2).setDistance(1));
EdgeIteratorState edge4 = GHUtility.setSpeed(60, true, false, f.encoder, f.graph.edge(2, 1).setDistance(1));
f.setRestriction(edge1, edge4, 2);
f.freeze();
f.setIdentityLevels();
// contracting node 0 yields (the only) shortcut - and its a loop
f.addShortcut(2, 2, edge2.getEdge(), edge3.getEdge(), edge2.getEdge(), edge3.getEdge(), 2, false);
// node 2 is the bridge node where the forward and backward searches meet (highest level). since there is a turn restriction
// at node 2 we cannot go from 4 to 1 directly, but we need to take the loop at 2 first. when the backward
// search arrives at 2 it is crucial that the ('forward') loop-shortcut at 2 is recognized as an incoming edge
// at node 2, otherwise the backward search ends at node 2. the forward search can never reach node 2 at all,
// because it never goes to a lower level. so when the backward search does not see the 'forward' loop shortcut
// no path between 3 and 1 will be found even though there is one.
f.testPathCalculation(3, 1, 5, IntArrayList.from(3, 4, 2, 0, 2, 1));
}
Aggregations