1
votes

I am using GraphHopper for finding a route between points. I want to predict the location of the vehicle at the given time t if it is moving at an average speed of x. GraphHopper has a module for finding isochrone but I can't figure out how I can run it on a single route. Below is the code which I am currently using

    List<GHPoint> points = new ArrayList<>();

    points.add(origin);

    for (GHPoint pnt : waypoints) {
        points.add(pnt);
    }

    points.add(destination);

    GHRequest req = new GHRequest(points).
            setWeighting("shortest").
            setVehicle("car").              
            setLocale(Locale.US);

    GHResponse rsp = graphHopper.route(req);

    // first check for errors
    if(rsp.hasErrors()) {
        // handle them!
        // rsp.getErrors()
        List<Throwable> errors = rsp.getErrors();
        return null;
    }

    PathWrapper bestPath = rsp.getBest();
2
That's great, you have used graphHopper.route (whatever that is) to get a PathWrapper object (whatever that is). I am going to assume that the PathWrapper contains a list of points to follow or a list of edges to follow. Therefore, I would assume that you would iterate through the edges, calculate the distance of each edge, and subtract that from the total distance of t * x until you get to around zero, and then figure out where t is on that edge. What have you tried so far? - Jamie
@Jamie thanks for the feedback it did resolved the issue - Haider

2 Answers

2
votes

To solve your problem, you could use the Isochrone Request API which is located here.

To predict Point B where your vehicle could be, we need to provide the next params:

  1. point - specify the start coordinate, required param;
  2. time_limit - specify which time the vehicle should travel. In seconds. Here is magic, provide here your t param;
  3. vehicle - the vehicle profile for which the route should be calculated. Default is car;
  4. distance_limit - specify which distance the vehicle should travel. In meters. You could calculate it, using (t x v) formula, because you specified that your vehicle moves at the average speed.

That is it. The GraphHopper API returns to you the list of polygons in GeoJson format.

Example:

int t = 600; // in seconds
int v = 10;  // in meters per second
int s = t * v; // in meters
IsochroneApi isochrone = new IsochroneApi();
isochrone.setApiClient(GHApiUtil.createClient());
try {
    // Please note: the request string for the point has the order "lat,lon" but the response contains
    // an array with the order [lon,lat]
    IsochroneResponse rsp = isochrone.getIsochrone("51.183728,14.42801", t, s, VehicleProfileId.CAR,
            3, false, "fastest");
    final IsochroneResponsePolygon isochrone0 = rsp.getPolygons().get(0);
    List<List<BigDecimal>> exteriorRing = isochrone0.getGeometry().getCoordinates().get(0);
    System.out.println(exteriorRing);
    double lon0 = ((Number) exteriorRing.get(0).get(0)).doubleValue();
    double lat0 = ((Number) exteriorRing.get(0).get(1)).doubleValue();
    System.out.println("first coord " + lat0 + ", " + lon0);
} catch (Exception ex) {
    throw new RuntimeException(ex);
}
1
votes

Thanks to @Jamie i got the interpolated point by lopping the coordinate list in LineString. You can get the LineString by using getPoints().toLineString method i.e. bestPath.getPoints().toLineString(false).

The distance was calculated like this by

   distance = (avgSpeedKMPerHr/ 3.6 ) * timeSec;

Below is the function which is used

  //distacne in meters which was calucletd 
public Point interpolatePointAlogLine(LineString line,double distance) throws 
   NoSuchAuthorityCodeException, FactoryException
{       
    GeodeticCalculator calculator = new GeodeticCalculator(CRS.decode("EPSG:4326")); 
    GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING), 4326);

    List<Coordinate> coordinates = new ArrayList<Coordinate>();
    Collections.addAll(coordinates, line.getCoordinates());
    double accumulatedLength = 0;

    if(distance >= line.getLength())
        return geometryFactory.createPoint(line.getEndPoint());

    for (int i = 0; i < coordinates.size(); i++)
    {

        Coordinate c1 = coordinates.get(i);
        Coordinate c2 = coordinates.get(i + 1);

        calculator.setStartingGeographicPoint(c1.x, c1.y);
        calculator.setDestinationGeographicPoint(c2.x, c2.y);

        double length = calculator.getOrthodromicDistance();

        if (length + accumulatedLength >= distance) 
        {
            double offsetLength = distance - accumulatedLength;
            double ratio = offsetLength / length;
            double dx = c2.x - c1.x;
            double dy = c2.y - c1.y;

            Coordinate iPoint = new Coordinate(c1.x + (dx * ratio), 
                    c1.y + (dy * ratio));

            return geometryFactory.createPoint(iPoint));
        }
        else {
            accumulatedLength += length;
        }
    }
    return null;
}