Thursday, December 12, 2024

Calculate the Distance between Two Points in your Web Apps

Calculate the Distance between Two Points in your Web Apps

As more and more Web apps are run on mobile devices, the more demand for geolocation capabilities increase. As the name suggests, Geolocation is about the reporting of your location to other users, as well as associating real-world locations (such as landmarks) to your location. Today’s article reveals the main obstacle to accurately calculating the distance between two locations and presents a practical solution.

The Haversine Formula

One of the main challenges to calculating distances – especially large ones – is accounting for the curvature of the Earth. If only the Earth were flat, calculating the distance between two points would be as simple as for that of a straight line! The Haversine formula includes a constant (it’s the R variable below) that represents the radius of the Earth. Depending on whether you are measuring in miles or kilometers, it would equal 3956 mi or 6367 km respectively.

The basic formula is:

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) )
distance = R * c (where R is the radius of the Earth)

R = 6367 km OR 3956 mi

Keep in mind that the Haversine formula is not 100% accurate because the Earth is not a perfect sphere – it bulges at the equator. Hence, distances near the equator would be underestimated while those near the polar regions would be overestimated. Nonetheless, the Haversine gives a good enough approximation for most applications.

The distance() Function Implementations

The GeoDataSource.com site has implementations of the Haversine formula for a variety of languages, including Java, JavaScript, PHP, Perl, SQL, and others.

I included the JavaScript and Java versions here because those are the two primary mobile app development languages. In both cases, the distance function accepts five parameters:

  • lat1, lon1: The Latitude and Longitude of point 1 (in decimal degrees)
  • lat2, lon2: The Latitude and Longitude of point 2 (in decimal degrees)
  • unit: The unit of measurement in which to calculate the results where:
    • ‘M’ is statute miles (default)
    • ‘K’ is kilometers
    • ‘N’ is nautical miles

The JavaScript Code

The JavaScript version of the Haversine formula as implemented by the GeoDataSource.com site is perfectly usable, but don’t compress it without adding the semi-colon line terminators first!

function distance(lat1, lon1, lat2, lon2, unit) {
        var radlat1 = Math.PI * lat1/180
        var radlat2 = Math.PI * lat2/180
        var radlon1 = Math.PI * lon1/180
        var radlon2 = Math.PI * lon2/180
        var theta = lon1-lon2
        var radtheta = Math.PI * theta/180
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        dist = Math.acos(dist)
        dist = dist * 180/Math.PI
        dist = dist * 60 * 1.1515
        if (unit=="K") { dist = dist * 1.609344 }
        if (unit=="N") { dist = dist * 0.8684 }
        return dist
}

Using the JavaScript distance() Function

Here is an example that calls the distance() function to calculate the number of kilometers between centretown London and Paris. Notice that I am rounding the results to three decimal places. You can omit that step if you don’t mind a lot of decimal places.

var distance = distance(51.5112139, -0.119824, 48.8567, 2.3508, 'K');
//round to 3 decimal places
console.log(Math.round(distance*1000)/1000);  //displays 343.548

That matches the number from distancefromto.net of 344 km.

The Haversine Formula in Java

I took the liberty of plugging the java code on the GeoDataSource.com site into a some static functions within a class named Geolocation. That would allow for testing of the distance() function and calling it without having to instantiate a class.

package com.robertgravelle.geolocation;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;

public class Geolocation {

        public static 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 static double deg2rad(double deg) {
          return (deg * Math.PI / 180.0);
        }

        // This function converts radians to decimal degrees
        private static double rad2deg(double rad) {
          return (rad * 180 / Math.PI);
        }

        public static void main(String[] args) {
                //place test code here
        }
}

Using the Geolocation distance() Method

Here is an example that calls the distance() function to calculate the number of miles between centretown London and Paris. Notice the use of single quotes around the unit character (and not double quotes).

double distance = Geolocation.distance(51.5112139, -0.119824, 48.8567, 2.3508, 'M');

NumberFormat df = DecimalFormat.getInstance();
df.setMaximumFractionDigits(3);
df.setRoundingMode(RoundingMode.CEILING);
System.out.println(df.format(distance) + " Milesn"); //displays 213.471 Miles

Once again, the answer matches up with that of the distancefromto.net site.

Conclusion

The Haversine formula is certainly not the only way to calculate distances, but it is easy enough to use and accurate enough to satisfy most requirements.

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured