How can I measure distance and create a bounding box based on two latitude+longitude points in Java?

JavaGeocodingLatitude Longitude

Java Problem Overview


I am wanting to find the distance between two different points. This I know can be accomplished with the great circle distance. <http://www.meridianworlddata.com/Distance-calculation.asp>

Once done, with a point and distance I would like to find the point that distance north, and that distance east in order to create a box around the point.

Java Solutions


Solution 1 - Java

Here is a Java implementation of Haversine formula. I use this in a project to calculate distance in miles between lat/longs.

public static double distFrom(double lat1, double lng1, double lat2, double lng2) {
  	double earthRadius = 3958.75; // miles (or 6371.0 kilometers)
  	double dLat = Math.toRadians(lat2-lat1);
  	double dLng = Math.toRadians(lng2-lng1);
  	double sindLat = Math.sin(dLat / 2);
    double sindLng = Math.sin(dLng / 2);
    double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
            * Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
  	double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  	double dist = earthRadius * c;
  	
  	return dist;
	}

Solution 2 - Java

Or you could use SimpleLatLng. Apache 2.0 licensed and used in one production system that I know of: mine.

Short story:

I was searching for a simple geo library and couldn't find one to fit my needs. And who wants to write and test and debug these little geo tools over and over again in every application? There's got to be a better way!

So SimpleLatLng was born as a way to store latitude-longitude data, do distance calculations, and create shaped boundaries.

I know I'm two years too late to help the original poster, but my aim is to help the people like me who find this question in a search. I would love to have some people use it and contribute to the testing and vision of this little lightweight utility.

Solution 3 - Java

We've had some success using OpenMap to plot a lot of positional data. There's a LatLonPoint class that has some basic functionality, including distance.

Solution 4 - Java

For a more accurate distance (0.5mm) you can also use the Vincenty approximation:

/**
 * Calculates geodetic distance between two points specified by latitude/longitude using Vincenty inverse formula
 * for ellipsoids
 * 
 * @param lat1
 *            first point latitude in decimal degrees
 * @param lon1
 *            first point longitude in decimal degrees
 * @param lat2
 *            second point latitude in decimal degrees
 * @param lon2
 *            second point longitude in decimal degrees
 * @returns distance in meters between points with 5.10<sup>-4</sup> precision
 * @see <a href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html">Originally posted here</a>
 */
public static double distVincenty(double lat1, double lon1, double lat2, double lon2) {
    double a = 6378137, b = 6356752.314245, f = 1 / 298.257223563; // WGS-84 ellipsoid params
    double L = Math.toRadians(lon2 - lon1);
    double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
    double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
    double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
    double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);

    double sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
    double lambda = L, lambdaP, iterLimit = 100;
    do {
        sinLambda = Math.sin(lambda);
        cosLambda = Math.cos(lambda);
        sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)
                + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
        if (sinSigma == 0)
            return 0; // co-incident points
        cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
        sigma = Math.atan2(sinSigma, cosSigma);
        sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha = 1 - sinAlpha * sinAlpha;
        cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
        if (Double.isNaN(cos2SigmaM))
            cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)
        double C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
        lambdaP = lambda;
        lambda = L + (1 - C) * f * sinAlpha
                * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
    } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);

    if (iterLimit == 0)
        return Double.NaN; // formula failed to converge

    double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
    double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
    double deltaSigma = B
            * sinSigma
            * (cos2SigmaM + B
                    / 4
                    * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM
                            * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
    double dist = b * A * (sigma - deltaSigma);

    return dist;
}

This code was freely adapted from http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Solution 5 - Java

Corrected Haversine Distance formula....

public static double HaverSineDistance(double lat1, double lng1, double lat2, double lng2) 
{
	// mHager 08-12-2012
	// http://en.wikipedia.org/wiki/Haversine_formula
	// Implementation
	
	// convert to radians
	lat1 = Math.toRadians(lat1);
	lng1 = Math.toRadians(lng1);
	lat2 = Math.toRadians(lat2);
	lng2 = Math.toRadians(lng2);
	
	double dlon = lng2 - lng1;
	double dlat = lat2 - lat1;
	
	double a = Math.pow((Math.sin(dlat/2)),2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dlon/2),2);
	
	double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
	
	return EARTH_RADIUS * c;
}	

Solution 6 - Java

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

public static Double distanceBetweenTwoLocationsInKm(Double latitudeOne, Double longitudeOne, Double latitudeTwo, Double longitudeTwo) {
		if (latitudeOne == null || latitudeTwo == null || longitudeOne == null || longitudeTwo == null) {
			return null;
		}

		Double earthRadius = 6371.0;
		Double diffBetweenLatitudeRadians = Math.toRadians(latitudeTwo - latitudeOne);
		Double diffBetweenLongitudeRadians = Math.toRadians(longitudeTwo - longitudeOne);
		Double latitudeOneInRadians = Math.toRadians(latitudeOne);
		Double latitudeTwoInRadians = Math.toRadians(latitudeTwo);
		Double a = Math.sin(diffBetweenLatitudeRadians / 2) * Math.sin(diffBetweenLatitudeRadians / 2) + Math.cos(latitudeOneInRadians) * Math.cos(latitudeTwoInRadians) * Math.sin(diffBetweenLongitudeRadians / 2)
				* Math.sin(diffBetweenLongitudeRadians / 2);
		Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
		return (earthRadius * c);
	}

Solution 7 - Java

You can use the Java Geodesy Library for GPS, it uses the Vincenty's formulae which takes account of the earths surface curvature.

Implementation goes like this:

import org.gavaghan.geodesy.*;
...
GeodeticCalculator geoCalc = new GeodeticCalculator();
Ellipsoid reference = Ellipsoid.WGS84;
GlobalPosition pointA = new GlobalPosition(latitude, longitude, 0.0);
GlobalPosition userPos = new GlobalPosition(userLat, userLon, 0.0);
double distance = geoCalc.calculateGeodeticCurve(reference, userPos, pointA).getEllipsoidalDistance();

The resulting distance is in meters.

Solution 8 - Java

I know that there are many answers, but in doing some research on this topic, I found that most answers here use the Haversine formula, but the Vincenty formula is actually more accurate. There was one post that adapted the calculation from a Javascript version, but it's very unwieldy. I found a version that is superior because:

  1. It also has an open license.
  2. It uses OOP principles.
  3. It has greater flexibility to choose the ellipsoid you want to use.
  4. It has more methods to allow for different calculations in the future.
  5. It is well documented.

VincentyDistanceCalculator

Solution 9 - Java

This method would help you find the distance between to geographic location in km.

private double getDist(double lat1, double lon1, double lat2, double lon2)
{
	int R = 6373; // radius of the earth in kilometres
	double lat1rad = Math.toRadians(lat1);
	double lat2rad = Math.toRadians(lat2);
	double deltaLat = Math.toRadians(lat2-lat1);
	double deltaLon = Math.toRadians(lon2-lon1);

	double a = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
	        Math.cos(lat1rad) * Math.cos(lat2rad) *
	        Math.sin(deltaLon/2) * Math.sin(deltaLon/2);
	double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

	double d = R * c;
	return d;
}

Solution 10 - Java

Kotlin version of Haversine formula. Returned result in meters. Tested on https://www.vcalc.com/wiki/vCalc/Haversine+-+Distance

const val EARTH_RADIUS_IN_METERS = 6371007.177356707

fun distance(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Double {
    val latDiff = Math.toRadians(abs(lat2 - lat1))
    val lngDiff = Math.toRadians(abs(lng2 - lng1))
    val a = sin(latDiff / 2) * sin(latDiff / 2) +
        cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
        sin(lngDiff / 2) * sin(lngDiff / 2)
    val c = 2 * atan2(sqrt(a), sqrt(1 - a))
    return EARTH_RADIUS_IN_METERS * c
}

Solution 11 - Java

I typically use MATLAB with the Mapping Toolbox, and then use the code in my Java using MATLAB Builder JA. It makes my life a lot simpler. Given most schools have it for free student access, you can try it out (or get the trial version to get over your work).

Solution 12 - Java

For Android, there is a simple approach.

 public static float getDistanceInMeter(LatLng start, LatLng end) { 
    float[] results = new float[1];
    Location.distanceBetween(start.latitude, start.longitude, end.latitude, end.longitude, results);
    return results[0];

}

;

https://developer.android.com/reference/android/location/Location#distanceBetween(lat1,lng1,lat2,lng2,output[])

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
QuestionwillView Question on Stackoverflow
Solution 1 - JavaSeanView Answer on Stackoverflow
Solution 2 - JavaJavadocMDView Answer on Stackoverflow
Solution 3 - JavaBrendan CashmanView Answer on Stackoverflow
Solution 4 - JavaVictor P.View Answer on Stackoverflow
Solution 5 - JavaMatthew HagerView Answer on Stackoverflow
Solution 6 - JavaRija RamampiandraView Answer on Stackoverflow
Solution 7 - JavaOscar SalgueroView Answer on Stackoverflow
Solution 8 - JavamikehoView Answer on Stackoverflow
Solution 9 - JavaAd InfinitumView Answer on Stackoverflow
Solution 10 - JavaBinakotView Answer on Stackoverflow
Solution 11 - JavaChetan RawalView Answer on Stackoverflow
Solution 12 - JavamakataView Answer on Stackoverflow