@Override
    public GHPoint intermediatePoint(double f, double lat1, double lon1, double lat2, double lon2) {
        double lat1radians = Math.toRadians(lat1);
        double lon1radians = Math.toRadians(lon1);
        double lat2radians = Math.toRadians(lat2);
        double lon2radians = Math.toRadians(lon2);

        // This formula is taken from: (http://www.movable-type.co.uk/scripts/latlong.html -> https://github.com/chrisveness/geodesy MIT)

        double deltaLat = lat2radians - lat1radians;
        double deltaLon = lon2radians - lon1radians;
        double cosLat1 = cos(lat1radians);
        double cosLat2 = cos(lat2radians);
        double sinHalfDeltaLat = sin(deltaLat / 2);
        double sinHalfDeltaLon = sin(deltaLon / 2);

        double a = sinHalfDeltaLat * sinHalfDeltaLat + cosLat1 * cosLat2 * sinHalfDeltaLon * sinHalfDeltaLon;
        double angularDistance = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double sinDistance = sin(angularDistance);

        if (angularDistance == 0) return new GHPoint(lat1, lon1);

        double A = Math.sin((1 - f) * angularDistance) / sinDistance;
        double B = Math.sin(f * angularDistance) / sinDistance;

        double x = A * cosLat1 * cos(lon1radians) + B * cosLat2 * cos(lon2radians);
        double y = A * cosLat1 * sin(lon1radians) + B * cosLat2 * sin(lon2radians);
        double z = A * sin(lat1radians) + B * sin(lat2radians);

        double midLat = Math.toDegrees(Math.atan2(z, Math.sqrt(x * x + y * y)));
        double midLon = Math.toDegrees(Math.atan2(y, x));

        return new GHPoint(midLat, midLon);
    }
@Test
    public void testIntermediatePoint() {
        DistanceCalc distCalc = new DistanceCalcEarth();
        GHPoint point = distCalc.intermediatePoint(0, 0, 0, 0, 0);
        assertEquals(0, point.getLat(), 1e-5);
        assertEquals(0, point.getLon(), 1e-5);

        point = distCalc.intermediatePoint(0.5, 0, 0, 10, 0);
        assertEquals(5, point.getLat(), 1e-5);
        assertEquals(0, point.getLon(), 1e-5);

        point = distCalc.intermediatePoint(0.5, 0, 0, 0, 10);
        assertEquals(0, point.getLat(), 1e-5);
        assertEquals(5, point.getLon(), 1e-5);

        // cross international date line going west
        point = distCalc.intermediatePoint(0.5, 45, -179, 45, 177);
        assertEquals(45, point.getLat(), 1);
        assertEquals(179, point.getLon(), 1e-5);

        // cross international date line going east
        point = distCalc.intermediatePoint(0.5, 45, 179, 45, -177);
        assertEquals(45, point.getLat(), 1);
        assertEquals(-179, point.getLon(), 1e-5);

        // cross north pole
        point = distCalc.intermediatePoint(0.25, 45, -90, 45, 90);
        assertEquals(67.5, point.getLat(), 1e-1);
        assertEquals(-90, point.getLon(), 1e-5);
        point = distCalc.intermediatePoint(0.75, 45, -90, 45, 90);
        assertEquals(67.5, point.getLat(), 1e-1);
        assertEquals(90, point.getLon(), 1e-5);
    }