Egor Sharapkov
Egor Sharapkov

Reputation: 5

Problem with the calculating distance between locations using Haversine formula

I am calculating the distance between two points recorded in the history of Yandex.Maps in the Android 11 app. Everything works well in the getPoints method. We write all the coordinates they were in our database to a list of arrays. I even implemented overflow, exit, and array checks. Again, up to this point, everything worked well and as expected.

public ArrayList<Double> getPoints () {
    ArrayList<Double> location = new ArrayList<>();
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.rawQuery("select latitude,longitude from "+Table_Name_Location,null);
    if(cursor.getCount() > 0) {
        while (cursor.moveToNext()) {
            Double latitude = cursor.getDouble(cursor.getColumnIndex("Lat"));
            Double longitude = cursor.getDouble(cursor.getColumnIndex("Longi"));
            location.add(latitude);
            location.add(longitude);
        }
    }
    cursor.close();
    return location;
}

However, when I try to calculate the length in the distance method, several latitudes and longitudes stored in the SQLite database incorrectly calculate the total distance, for example, 450 kilometres, and according to our data, we should get 230 km. A calculation error occurs.

private double distance(double lat1, double lon1, double lat2, double lon2) {
    double theta = lon1 - lon2;
    double dist = Math.sin(deg2rad(lat1))
        * Math.sin(deg2rad(lat2))
        + Math.cos(deg2rad(lat1))
        * Math.cos(deg2rad(lat2))
        * Math.cos(deg2rad(theta));
    dist = Math.acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    return (dist);
}

private double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

private double rad2deg(double rad) {
    return (rad * 180.0 / Math.PI);
}

I tried to calculate the distance using the haversine formula. I also wrote functions to convert radians to degrees and vice versa. In the distance method, I calculate the distance using the haversine formula. I suspect that the error is in calculating the distance, namely in the implementation of the haversine formula.

Upvotes: 0

Views: 2220

Answers (2)

Wnjklm
Wnjklm

Reputation: 67

     /**
     * Calculate the distance between two points in meters using the Haversine formula
     *
     * @param lat latitude of the first point
     * @param lon longitude of the first point
     * @param lat2 latitude of the second point
     * @param lon2 longitude of the second point
     * @return the distance between the two points in meters            
     **/
    public static double distance(double lat, double lon, double lat2, double lon2) {
        final double R = 6371e3;
        final double la = lat * java.lang.Math.PI / 180;
        final double laa = lat2 * java.lang.Math.PI / 180;
        final double lo = (lat2 - lat) * java.lang.Math.PI / 180;
        final double loo = (lon2 - lon) * java.lang.Math.PI / 180;
        final double a = java.lang.Math.sin(lo / 2) * java.lang.Math.sin(lo / 2) + java.lang.Math.cos(la) * java.lang.Math.cos(laa) * java.lang.Math.sin(loo / 2) * java.lang.Math.sin(loo / 2);
        final double c = 2 * java.lang.Math.atan2(java.lang.Math.sqrt(a), java.lang.Math.sqrt(1 - a));
        return R * c;
    }

Upvotes: 0

Ervin Szilagyi
Ervin Szilagyi

Reputation: 16805

For distance you need the reverse Haversine formula:

dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2(sqrt(a), sqrt(1-a)) 
d = R * c

R = 6371 # mean radius of the Earth in km

(source of formula: link)

The implementation of this in Java would look like the following:

private double distance(double lat1, double lon1, double lat2, double lon2) {
    final int R = 6371;
    double latDistance = Math.toRadians(lat2 - lat1);
    double lonDistance = Math.toRadians(lon2 - lon1);
    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
            Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                    Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

Upvotes: 1

Related Questions