1

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();
BSeitkazin
  • 2,889
  • 25
  • 40
Haider
  • 615
  • 1
  • 16
  • 38
  • 1
    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 Nov 20 '19 at 21:02
  • @Jamie thanks for the feedback it did resolved the issue – Haider Nov 23 '19 at 08:59

2 Answers2

2

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);
}
BSeitkazin
  • 2,889
  • 25
  • 40
  • Thanks for the response , i used the example given in https://github.com/graphhopper/graphhopper/blob/0.13/docs/isochrone/java.md to find the points but it gives me multiple points and i want to just find the point on selected route – Haider Nov 21 '19 at 09:08
  • @Haider updated answer with example. For more information use this part of documentation - https://github.com/graphhopper/directions-api-clients – BSeitkazin Nov 21 '19 at 09:31
  • is lon0 and lat0 will always be on the best route selected from route? – Haider Nov 21 '19 at 12:29
  • 1
    @Haider it is assuming that, because you selected `fastest` param `IsochroneResponse`. – BSeitkazin Nov 21 '19 at 15:36
  • but in above code you did not provided any destination how it now if its the same route – Haider Nov 21 '19 at 15:45
  • @Haider this is how their `GraphHopper` API work. They provide you some routes, how they think is efficient. After that, you could iterate it, and provide own algorithm of the definition "the best route". And it doesn't belong to question, but it is another question. If you have some issue about the "best route", could ask new question, with better tags with better spcialists. – BSeitkazin Nov 21 '19 at 15:58
  • @Haider if the answer was useful, and solves initial question, pls, mark it as right question. Thank you. – BSeitkazin Nov 22 '19 at 09:01
  • As mentioned by Jamie i solved this by by iterating on point list – Haider Nov 23 '19 at 08:58
1

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;
}
Haider
  • 615
  • 1
  • 16
  • 38