Calculating distance between two points, using latitude longitude?

JavaMathLatitude Longitude

Java Problem Overview


Here's my try, it's just a snippet of my code:

final double RADIUS = 6371.01;
double temp = Math.cos(Math.toRadians(latA))
            * Math.cos(Math.toRadians(latB))
            * Math.cos(Math.toRadians((latB) - (latA)))
            + Math.sin(Math.toRadians(latA))
            * Math.sin(Math.toRadians(latB));
    return temp * RADIUS * Math.PI / 180;

I am using this formulae to get the latitude and longitude:

x = Deg + (Min + Sec / 60) / 60)

Java Solutions


Solution 1 - Java

The Java code given by Dommer above gives slightly incorrect results but the small errors add up if you are processing say a GPS track. Here is an implementation of the Haversine method in Java which also takes into account height differences between two points.

/**
 * Calculate distance between two points in latitude and longitude taking
 * into account height difference. If you are not interested in height
 * difference pass 0.0. Uses Haversine method as its base.
 * 
 * lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
 * el2 End altitude in meters
 * @returns Distance in Meters
 */
public static double distance(double lat1, double lat2, double lon1,
		double lon2, double el1, double el2) {

	final int R = 6371; // Radius of the earth
	
	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));
	double distance = R * c * 1000; // convert to meters

	double height = el1 - el2;

	distance = Math.pow(distance, 2) + Math.pow(height, 2);

	return Math.sqrt(distance);
}

Solution 2 - Java

Here's a Java function that calculates the distance between two lat/long points, posted below, just in case it disappears again.

    private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
      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;
      if (unit == 'K') {
        dist = dist * 1.609344;
      } else if (unit == 'N') {
      	dist = dist * 0.8684;
        }
      return (dist);
    }
    
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  This function converts decimal degrees to radians             :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double deg2rad(double deg) {
      return (deg * Math.PI / 180.0);
    }
    
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  This function converts radians to decimal degrees             :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double rad2deg(double rad) {
      return (rad * 180.0 / Math.PI);
    }
    
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n");

Solution 3 - Java

Future readers who stumble upon this SOF article.

Obviously, the question was asked in 2010 and its now 2019. But it comes up early in an internet search. The original question does not discount use of third-party-library (when I wrote this answer).

public double calculateDistanceInMeters(double lat1, double long1, double lat2,
                                     double long2) {


    double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
    return dist;
}

and

<dependency>
  <groupId>org.apache.lucene</groupId>
  <artifactId>lucene-spatial</artifactId>
  <version>8.2.0</version>
</dependency>

https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0

Please read documentation about "SloppyMath" before diving in!

https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html

Solution 4 - Java

Note: this solution only works for short distances.

I tried to use dommer's posted formula for an application and found it did well for long distances but in my data I was using all very short distances, and dommer's post did very poorly. I needed speed, and the more complex geo calcs worked well but were too slow. So, in the case that you need speed and all the calculations you're making are short (maybe < 100m or so). I found this little approximation to work great. it assumes the world is flat mind you, so don't use it for long distances, it works by approximating the distance of a single Latitude and Longitude at the given Latitude and returning the Pythagorean distance in meters.

public class FlatEarthDist {
    //returns distance in meters
    public static double distance(double lat1, double lng1, 
                                      double lat2, double lng2){
	 double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1);
	 double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1);
	 return Math.sqrt(a*a+b*b);
    }

    private static double distPerLng(double lat){
	  return 0.0003121092*Math.pow(lat, 4)
			 +0.0101182384*Math.pow(lat, 3)
		         -17.2385140059*lat*lat
			 +5.5485277537*lat+111301.967182595;
    }

    private static double distPerLat(double lat){
            return -0.000000487305676*Math.pow(lat, 4)
				-0.0033668574*Math.pow(lat, 3)
				+0.4601181791*lat*lat
				-1.4558127346*lat+110579.25662316;
    }
}

Solution 5 - Java

Here is a page with javascript examples for various spherical calculations. The very first one on the page should give you what you need.

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

Here is the Javascript code

var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;

Where 'd' will hold the distance.

Solution 6 - Java

was a lot of great answers provided however I found some performance shortcomings, so let me offer a version with performance in mind. Every constant is precalculated and x,y variables are introduced to avoid calculating the same value twice. Hope it helps

    private static final double r2d = 180.0D / 3.141592653589793D;
    private static final double d2r = 3.141592653589793D / 180.0D;
    private static final double d2km = 111189.57696D * r2d;
    public static double meters(double lt1, double ln1, double lt2, double ln2) {
        double x = lt1 * d2r;
        double y = lt2 * d2r;
        return Math.acos( Math.sin(x) * Math.sin(y) + Math.cos(x) * Math.cos(y) * Math.cos(d2r * (ln1 - ln2))) * d2km;
    }

Solution 7 - Java

package distanceAlgorithm;

public class CalDistance {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
	CalDistance obj=new CalDistance();
	/*obj.distance(38.898556, -77.037852, 38.897147, -77.043934);*/
		System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "M") + " Miles\n");
		System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "K") + " Kilometers\n");
		System.out.println(obj.distance(32.9697, -96.80322, 29.46786, -98.53506, "N") + " Nautical Miles\n");		
	}	
	public double distance(double lat1, double lon1, double lat2, double lon2, String sr) {
		
		
	      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;
	      if (sr.equals("K")) {
	        dist = dist * 1.609344;
	      } else if (sr.equals("N")) {
	        dist = dist * 0.8684;
	        }
	      return (dist);
	    }
	public double deg2rad(double deg) {
	      return (deg * Math.PI / 180.0);
	    }
	public double rad2deg(double rad) {
	      return (rad * 180.0 / Math.PI);
	    }

	
	}

Solution 8 - Java

Slightly upgraded answer from @David George:

public static double distance(double lat1, double lat2, double lon1,
                              double lon2, double el1, double el2) {

    final int R = 6371; // Radius of the earth

    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));
    double distance = R * c * 1000; // convert to meters

    double height = el1 - el2;

    distance = Math.pow(distance, 2) + Math.pow(height, 2);

    return Math.sqrt(distance);
}

public static double distanceBetweenLocations(Location l1, Location l2) {
    if(l1.hasAltitude() && l2.hasAltitude()) {
        return distance(l1.getLatitude(), l2.getLatitude(), l1.getLongitude(), l2.getLongitude(), l1.getAltitude(), l2.getAltitude());
    }
    return l1.distanceTo(l2);
}

distance function is the same, but I've created I small wrapper function, which takes 2 Location objects. Thanks to this, I only use distance function if both of locations actually have altitude, because sometimes they don't. And it can lead to strange results (if location doesn't know its altitude 0 will be returned). In this case, I fall back to classic distanceTo function.

Solution 9 - Java

This wikipedia article provides the formulae and an example. The text is in german, but the calculations speak for themselves.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionm4designView Question on Stackoverflow
Solution 1 - JavaDavid GeorgeView Answer on Stackoverflow
Solution 2 - JavadommerView Answer on Stackoverflow
Solution 3 - JavagranadaCoderView Answer on Stackoverflow
Solution 4 - JavazahmdeView Answer on Stackoverflow
Solution 5 - JavaChris TaylorView Answer on Stackoverflow
Solution 6 - JavaStan SokolovView Answer on Stackoverflow
Solution 7 - JavaMAnoj SarnaikView Answer on Stackoverflow
Solution 8 - JavaMakaleleView Answer on Stackoverflow
Solution 9 - JavazellusView Answer on Stackoverflow