Skip to content

Commit

Permalink
make pointlist more usable on client side
Browse files Browse the repository at this point in the history
  • Loading branch information
karussell committed Mar 25, 2019
1 parent 4edf5ec commit d29c7ca
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,49 @@ public void setDistanceLimit(double limit) {
this.finishLimit = limit + Math.max(limit * 0.14, 2_000);
}

public static class IsoLabelWithCoordinates {
public Coordinate baseCoordinate;
public Coordinate adjCoordinate;
public long time;
public double distance;
// debug info
public int edgeId, baseNodeId;
public final int adjNodeId;

public IsoLabelWithCoordinates(int adjNodeId) {
this.adjNodeId = adjNodeId;
}
}

public List<IsoLabelWithCoordinates> search(int from) {
searchInternal(from);

final List<IsoLabelWithCoordinates> shortestPathEntries = new ArrayList<>(fromMap.size());
final NodeAccess na = graph.getNodeAccess();
fromMap.forEach(new IntObjectProcedure<IsoLabel>() {

@Override
public void apply(int nodeId, IsoLabel label) {
double lat = na.getLatitude(nodeId);
double lon = na.getLongitude(nodeId);
IsoLabelWithCoordinates sptInfo = new IsoLabelWithCoordinates(nodeId);
sptInfo.adjCoordinate = new Coordinate(lon, lat);
sptInfo.time = label.time;
sptInfo.distance = label.distance;
sptInfo.edgeId = label.edge;
shortestPathEntries.add(sptInfo);
if (label.parent != null) {
nodeId = label.parent.adjNode;
double lat2 = na.getLatitude(nodeId);
double lon2 = na.getLongitude(nodeId);
sptInfo.baseNodeId = nodeId;
sptInfo.baseCoordinate = new Coordinate(lon2, lat2);
}
}
});
return shortestPathEntries;
}

public List<List<Coordinate>> searchGPS(int from, final int bucketCount) {
searchInternal(from);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.graphhopper.GraphHopper;
import com.graphhopper.isochrone.algorithm.Isochrone;
import com.graphhopper.isochrone.algorithm.DelaunayTriangulationIsolineBuilder;
import com.graphhopper.isochrone.algorithm.Isochrone;
import com.graphhopper.json.geo.JsonFeature;
import com.graphhopper.routing.QueryGraph;
import com.graphhopper.routing.util.*;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.index.LocationIndex;
import com.graphhopper.storage.index.QueryResult;
import com.graphhopper.util.Helper;
import com.graphhopper.util.StopWatch;
import com.graphhopper.util.shapes.GHPoint;
import org.locationtech.jts.geom.Coordinate;
Expand Down Expand Up @@ -55,6 +56,7 @@ public Response doGet(
@QueryParam("reverse_flow") @DefaultValue("false") boolean reverseFlow,
@QueryParam("point") GHPoint point,
@QueryParam("result") @DefaultValue("polygon") String resultStr,
@QueryParam("pointlist_ext_header") String extendedHeader,
@QueryParam("time_limit") @DefaultValue("600") long timeLimitInSeconds,
@QueryParam("distance_limit") @DefaultValue("-1") double distanceInMeter) {

Expand Down Expand Up @@ -92,28 +94,21 @@ public Response doGet(
isochrone.setTimeLimit(timeLimitInSeconds);
}

List<List<Coordinate>> buckets = isochrone.searchGPS(qr.getClosestNode(), nBuckets);
if (isochrone.getVisitedNodes() > graphHopper.getMaxVisitedNodes() / 5) {
throw new IllegalArgumentException("Server side reset: too many junction nodes would have to explored (" + isochrone.getVisitedNodes() + "). Let us know if you need this increased.");
}

int counter = 0;
for (List<Coordinate> bucket : buckets) {
if (bucket.size() < 2) {
throw new IllegalArgumentException("Too few points found for bucket " + counter + ". "
+ "Please try a different 'point', a smaller 'buckets' count or a larger 'time_limit'. "
+ "And let us know if you think this is a bug!");
if ("polygon".equalsIgnoreCase(resultStr)) {
List<List<Coordinate>> buckets = isochrone.searchGPS(qr.getClosestNode(), nBuckets);
if (isochrone.getVisitedNodes() > graphHopper.getMaxVisitedNodes() / 5) {
throw new IllegalArgumentException("Server side reset: too many junction nodes would have to explored (" + isochrone.getVisitedNodes() + "). Let us know if you need this increased.");
}
counter++;
}

if ("pointlist".equalsIgnoreCase(resultStr)) {
sw.stop();
logger.info("took: " + sw.getSeconds() + ", visited nodes:" + isochrone.getVisitedNodes() + ", " + uriInfo.getQueryParameters());
return Response.fromResponse(jsonSuccessResponse(buckets, sw.getSeconds()))
.header("X-GH-Took", "" + sw.getSeconds() * 1000)
.build();
} else if ("polygon".equalsIgnoreCase(resultStr)) {
int counter = 0;
for (List<Coordinate> bucket : buckets) {
if (bucket.size() < 2) {
throw new IllegalArgumentException("Too few points found for bucket " + counter + ". "
+ "Please try a different 'point', a smaller 'buckets' count or a larger 'time_limit'. "
+ "And let us know if you think this is a bug!");
}
counter++;
}
ArrayList<JsonFeature> features = new ArrayList<>();
List<Coordinate[]> polygonShells = delaunayTriangulationIsolineBuilder.calcList(buckets, buckets.size() - 1);
for (Coordinate[] polygonShell : polygonShells) {
Expand All @@ -126,17 +121,70 @@ public Response doGet(
}
sw.stop();
logger.info("took: " + sw.getSeconds() + ", visited nodes:" + isochrone.getVisitedNodes() + ", " + uriInfo.getQueryParameters());
return Response.fromResponse(jsonSuccessResponse(features, sw.getSeconds()))
return Response.fromResponse(jsonSuccessResponse("polygons", features, sw.getSeconds()))
.header("X-GH-Took", "" + sw.getSeconds() * 1000)
.build();
} else if ("pointlist".equalsIgnoreCase(resultStr)) {
Collection<String> header = new LinkedHashSet<>(Arrays.asList("longitude", "latitude", "time", "distance"));
if (!Helper.isEmpty(extendedHeader))
header.addAll(Arrays.asList(extendedHeader.split(",")));
List<Isochrone.IsoLabelWithCoordinates> resultList = isochrone.search(qr.getClosestNode());
List<List> items = new ArrayList(resultList.size());
for (Isochrone.IsoLabelWithCoordinates label : resultList) {
List list = new ArrayList(header.size());
for (String h : header) {
switch (h) {
case "distance":
list.add(label.distance);
break;
case "time":
list.add(label.distance);
break;
case "node_id":
list.add(label.adjNodeId);
break;
case "edge_id":
list.add(label.edgeId);
break;
case "longitude":
list.add(label.adjCoordinate.x);
break;
case "latitude":
list.add(label.adjCoordinate.y);
break;
case "prev_longitude":
list.add(label.baseCoordinate == null ? null : label.baseCoordinate.x);
break;
case "prev_latitude":
list.add(label.baseCoordinate == null ? null : label.baseCoordinate.y);
break;
case "prev_node_id":
list.add(label.baseNodeId);
break;
default:
throw new IllegalArgumentException("Unknown property " + h);
}
}
items.add(list);
}
sw.stop();
Map map = new HashMap();
map.put("header", header);
map.put("items", items);

logger.info("took: " + sw.getSeconds() + ", visited nodes:" + isochrone.getVisitedNodes() + ", " + uriInfo.getQueryParameters());
return Response.fromResponse(jsonSuccessResponse("result", map, sw.getSeconds()))
.header("X-GH-Took", "" + sw.getSeconds() * 1000)
.build();

} else {
throw new IllegalArgumentException("type not supported:" + resultStr);
}
}

private Response jsonSuccessResponse(Object result, float took) {
private Response jsonSuccessResponse(String keyName, Object result, float took) {
ObjectNode json = JsonNodeFactory.instance.objectNode();
json.putPOJO("polygons", result);
json.putPOJO(keyName, result);
// If you replace GraphHopper with your own brand name, this is fine.
// Still it would be highly appreciated if you mention us in your about page!
final ObjectNode info = json.putObject("info");
Expand Down

1 comment on commit d29c7ca

@crazycapivara
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It returns distance for time as well:

switch (h) {
                        case "distance":
                            list.add(label.distance);
                            break;
                        case "time":
                            list.add(label.distance);
                            break;

Please sign in to comment.