Get the distance between two geo points
Asked Answered
P

9

110

I want to make an app which checks the nearest place where a user is. I can easily get the location of the user and I have already a list of places with latitude and longitude.

What would be the best way to know the nearest place of the list against the current user location.

I could not find anything in the google APIs.

Population answered 29/4, 2010 at 23:30 Comment(0)
C
173
Location loc1 = new Location("");
loc1.setLatitude(lat1);
loc1.setLongitude(lon1);

Location loc2 = new Location("");
loc2.setLatitude(lat2);
loc2.setLongitude(lon2);

float distanceInMeters = loc1.distanceTo(loc2);

Reference: http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)

Chrysarobin answered 15/12, 2013 at 22:12 Comment(4)
Probably slower than using Location.DistanceBetween() since it is using Location objects but works for my purposes very well.Maneater
Which class i have to import for the Location import android.location.Location; or whichGone
@PranavMS yes android.location.Location;Huh
I think that distanceTo returns the distance between the first and last point but in a rectal line , so if you take any other directions from point a to b its gonna never be accuarated since the path is different, thats when distanceBetween joins in, you can save each distance between the points beign created and then with the final parameter results[] get the correct distance.Om
D
122

http://developer.android.com/reference/android/location/Location.html

Look into distanceTo or distanceBetween. You can create a Location object from a latitude and longitude:

Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);
Delly answered 29/4, 2010 at 23:34 Comment(3)
distanceBetween is a static method that takes 2 sets of lat long points, so you don't even need to instantiate a Location object =)Phenomenon
I'm sure he meant that for distanceTo method.Garbers
This is great and super helpful, but what is the String provider for in the constrructor?Staunch
C
35

An approximated solution (based on an equirectangular projection), much faster (it requires only 1 trig and 1 square root).

This approximation is relevant if your points are not too far apart. It will always over-estimate compared to the real haversine distance. For example it will add no more than 0.05382 % to the real distance if the delta latitude or longitude between your two points does not exceed 4 decimal degrees.

The standard formula (Haversine) is the exact one (that is, it works for any couple of longitude/latitude on earth) but is much slower as it needs 7 trigonometric and 2 square roots. If your couple of points are not too far apart, and absolute precision is not paramount, you can use this approximate version (Equirectangular), which is much faster as it uses only one trigonometric and one square root.

// Approximate Equirectangular -- works if (lat1,lon1) ~ (lat2,lon2)
int R = 6371; // km
double x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
double y = (lat2 - lat1);
double distance = Math.sqrt(x * x + y * y) * R;

You can optimize this further by either:

  1. Removing the square root if you simply compare the distance to another (in that case compare both squared distance);
  2. Factoring-out the cosine if you compute the distance from one master point to many others (in that case you do the equirectangular projection centered on the master point, so you can compute the cosine once for all comparisons).

For more info see: http://www.movable-type.co.uk/scripts/latlong.html

There is a nice reference implementation of the Haversine formula in several languages at: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

Czarevna answered 2/12, 2010 at 20:39 Comment(5)
great man thanx. But if I need to get a set of locations around one location in a perimeter, should I use a while loop to check each location against the searched one and keep only the ones that are in the perimeter?Referendum
You can, but that's a brute-force approach in O(n). For a O(1) solution, use a 2D spatial index to trim the potential matches before computing the exact solution. We're leaving the scope of this question :)Hedda
this is a very nice wrapup of nice possible optimizations.. thx! Excactly what I was looking forDecommission
I just wanted to know if this formula works for large distancesRufe
See the answer, but in short: no, it does not work for large distances. The larger the distance between the two points, the larger the error compared to the exact Haversine formulæ.Hedda
G
12

There are a couple of methods you could use, but to determine which one is best we first need to know if you are aware of the user's altitude, as well as the altitude of the other points?

Depending on the level of accuracy you are after, you could look into either the Haversine or Vincenty formulae...

These pages detail the formulae, and, for the less mathematically inclined also provide an explanation of how to implement them in script!

Haversine Formula: http://www.movable-type.co.uk/scripts/latlong.html

Vincenty Formula: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

If you have any problems with any of the meanings in the formulae, just comment and I'll do my best to answer them :)

Gauntlett answered 30/4, 2010 at 0:41 Comment(0)
A
4

There are two ways to get distance between LatLng.

public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)

See this

and second

public float distanceTo (Location dest) as answered by praveen.

Asuncionasunder answered 1/8, 2015 at 17:27 Comment(0)
J
3
private float getDistance(double lat1, double lon1, double lat2, double lon2) {
        float[] distance = new float[2];
        Location.distanceBetween(lat1, lon1, lat2, lon2, distance);
        return distance[0];
    }
Janijania answered 25/2, 2018 at 19:30 Comment(0)
C
2

Just use the following method, pass it lat and long and get distance in meter:

private static double distance_in_meter(final double lat1, final double lon1, final double lat2, final double lon2) {
    double R = 6371000f; // Radius of the earth in m
    double dLat = (lat1 - lat2) * Math.PI / 180f;
    double dLon = (lon1 - lon2) * Math.PI / 180f;
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(latlong1.latitude * Math.PI / 180f) * Math.cos(latlong2.latitude * Math.PI / 180f) *
                    Math.sin(dLon/2) * Math.sin(dLon/2);
    double c = 2f * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double d = R * c;
    return d;
}
Caslon answered 9/9, 2016 at 18:27 Comment(2)
latlong1 and latlong2 are not definedCompotation
what is latlong1 & latlong2 ?Stockwell
H
1

a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)

c = 2 ⋅ atan2( √a, √(1−a) )

distance = R ⋅ c

where φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);

note that angles need to be in radians to pass to trig functions!

fun distanceInMeter(firstLocation: Location, secondLocation: Location): Double {
    val earthRadius = 6371000.0
    val deltaLatitudeDegree = (firstLocation.latitude - secondLocation.latitude) * Math.PI / 180f
    val deltaLongitudeDegree = (firstLocation.longitude - secondLocation.longitude) * Math.PI / 180f
    val a = sin(deltaLatitudeDegree / 2).pow(2) +
            cos(firstLocation.latitude * Math.PI / 180f) * cos(secondLocation.latitude * Math.PI / 180f) *
            sin(deltaLongitudeDegree / 2).pow(2)
    val c = 2f * atan2(sqrt(a), sqrt(1 - a))
    return earthRadius * c
}


data class Location(val latitude: Double, val longitude: Double)
Hereld answered 3/8, 2020 at 10:56 Comment(0)
C
0

you can get distance and time using google Map API Google Map API

just pass downloaded JSON to this method you will get real time Distance and Time between two latlong's

void parseJSONForDurationAndKMS(String json) throws JSONException {

    Log.d(TAG, "called parseJSONForDurationAndKMS");
    JSONObject jsonObject = new JSONObject(json);
    String distance;
    String duration;
    distance = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
    duration = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");

    Log.d(TAG, "distance : " + distance);
    Log.d(TAG, "duration : " + duration);

    distanceBWLats.setText("Distance : " + distance + "\n" + "Duration : " + duration);


}
Chrisse answered 2/8, 2018 at 12:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.