use of com.graphhopper.isochrone.algorithm.ShortestPathTree in project graphhopper by graphhopper.
the class IsochroneResource method doGet.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response doGet(@Context UriInfo uriInfo, @QueryParam("profile") String profileName, @QueryParam("buckets") @Range(min = 1, max = 20) @DefaultValue("1") IntParam nBuckets, @QueryParam("reverse_flow") @DefaultValue("false") boolean reverseFlow, @QueryParam("point") @NotNull GHPointParam point, @QueryParam("time_limit") @DefaultValue("600") LongParam timeLimitInSeconds, @QueryParam("distance_limit") @DefaultValue("-1") LongParam distanceLimitInMeter, @QueryParam("weight_limit") @DefaultValue("-1") LongParam weightLimit, @QueryParam("type") @DefaultValue("json") ResponseType respType, @QueryParam("tolerance") @DefaultValue("0") double toleranceInMeter, @QueryParam("full_geometry") @DefaultValue("false") boolean fullGeometry) {
StopWatch sw = new StopWatch().start();
PMap hintsMap = new PMap();
RouteResource.initHints(hintsMap, uriInfo.getQueryParameters());
hintsMap.putObject(Parameters.CH.DISABLE, true);
hintsMap.putObject(Parameters.Landmark.DISABLE, true);
if (Helper.isEmpty(profileName)) {
profileName = profileResolver.resolveProfile(hintsMap).getName();
removeLegacyParameters(hintsMap);
}
errorIfLegacyParameters(hintsMap);
Profile profile = graphHopper.getProfile(profileName);
if (profile == null)
throw new IllegalArgumentException("The requested profile '" + profileName + "' does not exist");
LocationIndex locationIndex = graphHopper.getLocationIndex();
Graph graph = graphHopper.getGraphHopperStorage();
Weighting weighting = graphHopper.createWeighting(profile, hintsMap);
BooleanEncodedValue inSubnetworkEnc = graphHopper.getEncodingManager().getBooleanEncodedValue(Subnetwork.key(profileName));
if (hintsMap.has(Parameters.Routing.BLOCK_AREA)) {
GraphEdgeIdFinder.BlockArea blockArea = GraphEdgeIdFinder.createBlockArea(graph, locationIndex, Collections.singletonList(point.get()), hintsMap, new FiniteWeightFilter(weighting));
weighting = new BlockAreaWeighting(weighting, blockArea);
}
Snap snap = locationIndex.findClosest(point.get().lat, point.get().lon, new DefaultSnapFilter(weighting, inSubnetworkEnc));
if (!snap.isValid())
throw new IllegalArgumentException("Point not found:" + point);
QueryGraph queryGraph = QueryGraph.create(graph, snap);
TraversalMode traversalMode = profile.isTurnCosts() ? EDGE_BASED : NODE_BASED;
ShortestPathTree shortestPathTree = new ShortestPathTree(queryGraph, queryGraph.wrapWeighting(weighting), reverseFlow, traversalMode);
double limit;
if (weightLimit.get() > 0) {
limit = weightLimit.get();
shortestPathTree.setWeightLimit(limit + Math.max(limit * 0.14, 2_000));
} else if (distanceLimitInMeter.get() > 0) {
limit = distanceLimitInMeter.get();
shortestPathTree.setDistanceLimit(limit + Math.max(limit * 0.14, 2_000));
} else {
limit = timeLimitInSeconds.get() * 1000;
shortestPathTree.setTimeLimit(limit + Math.max(limit * 0.14, 200_000));
}
ArrayList<Double> zs = new ArrayList<>();
double delta = limit / nBuckets.get();
for (int i = 0; i < nBuckets.get(); i++) {
zs.add((i + 1) * delta);
}
ToDoubleFunction<ShortestPathTree.IsoLabel> fz;
if (weightLimit.get() > 0) {
fz = l -> l.weight;
} else if (distanceLimitInMeter.get() > 0) {
fz = l -> l.distance;
} else {
fz = l -> l.time;
}
Triangulator.Result result = triangulator.triangulate(snap, queryGraph, shortestPathTree, fz, degreesFromMeters(toleranceInMeter));
ContourBuilder contourBuilder = new ContourBuilder(result.triangulation);
ArrayList<Geometry> isochrones = new ArrayList<>();
for (Double z : zs) {
logger.info("Building contour z={}", z);
MultiPolygon isochrone = contourBuilder.computeIsoline(z, result.seedEdges);
if (fullGeometry) {
isochrones.add(isochrone);
} else {
Polygon maxPolygon = heuristicallyFindMainConnectedComponent(isochrone, isochrone.getFactory().createPoint(new Coordinate(point.get().lon, point.get().lat)));
isochrones.add(isochrone.getFactory().createPolygon(((LinearRing) maxPolygon.getExteriorRing())));
}
}
ArrayList<JsonFeature> features = new ArrayList<>();
for (Geometry isochrone : isochrones) {
JsonFeature feature = new JsonFeature();
HashMap<String, Object> properties = new HashMap<>();
properties.put("bucket", features.size());
if (respType == geojson) {
properties.put("copyrights", ResponsePathSerializer.COPYRIGHTS);
}
feature.setProperties(properties);
feature.setGeometry(isochrone);
features.add(feature);
}
ObjectNode json = JsonNodeFactory.instance.objectNode();
sw.stop();
ObjectNode finalJson = null;
if (respType == geojson) {
json.put("type", "FeatureCollection");
json.putPOJO("features", features);
finalJson = json;
} else {
json.putPOJO("polygons", features);
final ObjectNode info = json.putObject("info");
info.putPOJO("copyrights", ResponsePathSerializer.COPYRIGHTS);
info.put("took", Math.round((float) sw.getMillis()));
finalJson = json;
}
logger.info("took: " + sw.getSeconds() + ", visited nodes:" + shortestPathTree.getVisitedNodes());
return Response.ok(finalJson).header("X-GH-Took", "" + sw.getSeconds() * 1000).build();
}
use of com.graphhopper.isochrone.algorithm.ShortestPathTree in project graphhopper by graphhopper.
the class IsochroneExample method main.
public static void main(String[] args) {
String relDir = args.length == 1 ? args[0] : "";
GraphHopper hopper = createGraphHopperInstance(relDir + "core/files/andorra.osm.pbf");
// get encoder from GraphHopper instance
EncodingManager encodingManager = hopper.getEncodingManager();
FlagEncoder encoder = encodingManager.getEncoder("car");
// snap some GPS coordinates to the routing graph and build a query graph
FastestWeighting weighting = new FastestWeighting(encoder);
Snap snap = hopper.getLocationIndex().findClosest(42.508679, 1.532078, new DefaultSnapFilter(weighting, encodingManager.getBooleanEncodedValue(Subnetwork.key("car"))));
QueryGraph queryGraph = QueryGraph.create(hopper.getGraphHopperStorage(), snap);
// run the isochrone calculation
ShortestPathTree tree = new ShortestPathTree(queryGraph, weighting, false, TraversalMode.NODE_BASED);
// find all nodes that are within a radius of 120s
tree.setTimeLimit(120_000);
AtomicInteger counter = new AtomicInteger(0);
// you need to specify a callback to define what should be done
tree.search(snap.getClosestNode(), label -> {
// see IsoLabel.java for more properties
// System.out.println("node: " + label.node + ", time: " + label.time + ", distance: " + label.distance);
counter.incrementAndGet();
});
assert counter.get() > 200;
}
use of com.graphhopper.isochrone.algorithm.ShortestPathTree in project graphhopper by graphhopper.
the class SPTResource method doGet.
// Annotating this as application/json because errors come out as json, and
// IllegalArgumentExceptions are not mapped to a fixed mediatype, because in RouteResource, it could be GPX.
@GET
@Produces({ "text/csv", "application/json" })
public Response doGet(@Context UriInfo uriInfo, @QueryParam("profile") String profileName, @QueryParam("reverse_flow") @DefaultValue("false") boolean reverseFlow, @QueryParam("point") @NotNull GHPointParam point, @QueryParam("columns") String columnsParam, @QueryParam("time_limit") @DefaultValue("600") LongParam timeLimitInSeconds, @QueryParam("distance_limit") @DefaultValue("-1") LongParam distanceInMeter) {
StopWatch sw = new StopWatch().start();
PMap hintsMap = new PMap();
RouteResource.initHints(hintsMap, uriInfo.getQueryParameters());
hintsMap.putObject(Parameters.CH.DISABLE, true);
hintsMap.putObject(Parameters.Landmark.DISABLE, true);
if (Helper.isEmpty(profileName)) {
profileName = profileResolver.resolveProfile(hintsMap).getName();
removeLegacyParameters(hintsMap);
}
errorIfLegacyParameters(hintsMap);
Profile profile = graphHopper.getProfile(profileName);
if (profile == null)
throw new IllegalArgumentException("The requested profile '" + profileName + "' does not exist");
LocationIndex locationIndex = graphHopper.getLocationIndex();
Graph graph = graphHopper.getGraphHopperStorage();
Weighting weighting = graphHopper.createWeighting(profile, hintsMap);
BooleanEncodedValue inSubnetworkEnc = graphHopper.getEncodingManager().getBooleanEncodedValue(Subnetwork.key(profileName));
if (hintsMap.has(Parameters.Routing.BLOCK_AREA)) {
GraphEdgeIdFinder.BlockArea blockArea = GraphEdgeIdFinder.createBlockArea(graph, locationIndex, Collections.singletonList(point.get()), hintsMap, new FiniteWeightFilter(weighting));
weighting = new BlockAreaWeighting(weighting, blockArea);
}
Snap snap = locationIndex.findClosest(point.get().lat, point.get().lon, new DefaultSnapFilter(weighting, inSubnetworkEnc));
if (!snap.isValid())
throw new IllegalArgumentException("Point not found:" + point);
QueryGraph queryGraph = QueryGraph.create(graph, snap);
NodeAccess nodeAccess = queryGraph.getNodeAccess();
TraversalMode traversalMode = profile.isTurnCosts() ? EDGE_BASED : NODE_BASED;
ShortestPathTree shortestPathTree = new ShortestPathTree(queryGraph, queryGraph.wrapWeighting(weighting), reverseFlow, traversalMode);
if (distanceInMeter.get() > 0) {
shortestPathTree.setDistanceLimit(distanceInMeter.get());
} else {
double limit = timeLimitInSeconds.get() * 1000;
shortestPathTree.setTimeLimit(limit);
}
final String COL_SEP = ",", LINE_SEP = "\n";
List<String> columns;
if (!Helper.isEmpty(columnsParam))
columns = Arrays.asList(columnsParam.split(","));
else
columns = Arrays.asList("longitude", "latitude", "time", "distance");
if (columns.isEmpty())
throw new IllegalArgumentException("Either omit the columns parameter or specify the columns via comma separated values");
Map<String, EncodedValue> pathDetails = new HashMap<>();
for (String col : columns) {
if (encodingManager.hasEncodedValue(col))
pathDetails.put(col, encodingManager.getEncodedValue(col, EncodedValue.class));
}
StreamingOutput out = output -> {
try (Writer writer = new BufferedWriter(new OutputStreamWriter(output, Helper.UTF_CS))) {
StringBuilder sb = new StringBuilder();
for (String col : columns) {
if (sb.length() > 0)
sb.append(COL_SEP);
sb.append(col);
}
sb.append(LINE_SEP);
writer.write(sb.toString());
shortestPathTree.search(snap.getClosestNode(), l -> {
IsoLabelWithCoordinates label = isoLabelWithCoordinates(nodeAccess, l);
sb.setLength(0);
for (int colIndex = 0; colIndex < columns.size(); colIndex++) {
String col = columns.get(colIndex);
if (colIndex > 0)
sb.append(COL_SEP);
switch(col) {
case "node_id":
sb.append(label.nodeId);
continue;
case "prev_node_id":
sb.append(label.prevNodeId);
continue;
case "edge_id":
sb.append(label.edgeId);
continue;
case "prev_edge_id":
sb.append(label.prevEdgeId);
continue;
case "distance":
sb.append(label.distance);
continue;
case "prev_distance":
sb.append(label.prevCoordinate == null ? 0 : label.prevDistance);
continue;
case "time":
sb.append(label.timeMillis);
continue;
case "prev_time":
sb.append(label.prevCoordinate == null ? 0 : label.prevTimeMillis);
continue;
case "longitude":
sb.append(Helper.round6(label.coordinate.lon));
continue;
case "prev_longitude":
sb.append(label.prevCoordinate == null ? null : Helper.round6(label.prevCoordinate.lon));
continue;
case "latitude":
sb.append(Helper.round6(label.coordinate.lat));
continue;
case "prev_latitude":
sb.append(label.prevCoordinate == null ? null : Helper.round6(label.prevCoordinate.lat));
continue;
}
if (!EdgeIterator.Edge.isValid(label.edgeId))
continue;
EdgeIteratorState edge = queryGraph.getEdgeIteratorState(label.edgeId, label.nodeId);
if (edge == null)
continue;
if (col.equals(Parameters.Details.STREET_NAME)) {
sb.append(edge.getName().replaceAll(",", ""));
continue;
}
EncodedValue ev = pathDetails.get(col);
if (ev instanceof DecimalEncodedValue) {
DecimalEncodedValue dev = (DecimalEncodedValue) ev;
sb.append(reverseFlow ? edge.getReverse(dev) : edge.get(dev));
} else if (ev instanceof EnumEncodedValue) {
EnumEncodedValue eev = (EnumEncodedValue) ev;
sb.append(reverseFlow ? edge.getReverse(eev) : edge.get(eev));
} else if (ev instanceof BooleanEncodedValue) {
BooleanEncodedValue eev = (BooleanEncodedValue) ev;
sb.append(reverseFlow ? edge.getReverse(eev) : edge.get(eev));
} else if (ev instanceof IntEncodedValue) {
IntEncodedValue eev = (IntEncodedValue) ev;
sb.append(reverseFlow ? edge.getReverse(eev) : edge.get(eev));
} else {
throw new IllegalArgumentException("Unknown property " + col);
}
}
sb.append(LINE_SEP);
try {
writer.write(sb.toString());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
logger.info("took: " + sw.stop().getSeconds() + ", visited nodes:" + shortestPathTree.getVisitedNodes() + ", " + uriInfo.getQueryParameters());
} catch (IOException e) {
throw new RuntimeException(e);
}
};
// Give media type explicitly since we are annotating CSV and JSON, because error messages are JSON.
return Response.ok(out).type("text/csv").build();
}
Aggregations