Tuesday, October 5, 2010

How to calculate the distance between 2 locations (latitude and longitude) in Java

In this post I wrote how the distance between 2 ips can be calculated using Maxmind. Calculating distance between 2 ips is not accurate, since Maxmind actually extracts for each ip an estimated latitude and longitude and then does distance calculation. The extracted values of latitude and longitude don’t stand for the real location of the user, but for the location of the ip, which is most likely, the location of the isp/organization that owns the ip.
Modern mobile devices are capable of knowing the exact location of the user in terms of latitude and longitude. This opens a whole new set of business opportunities for services and applications. One of many of the needs of these services and applications is calculating the distance between 2 locations. Of course, each location, is described using latitude and longitude.
In order to calculate the distance between 2 locations we will create a class named: Location. The class will mainly contain:
  • Inner enumeration named: Unit, which defines 3 possible units in which the distance can be calculated:
  • 2 members:
    • longitude
    • latitude
  • 2 static conversion methods:
    • deg2rad – Convert digress to radians.
    • rad2deg – Convert radians to degrees.
  • 2 overloaded methods name distance:
    • First method calculates the distance for a given latitude and longitude.
    • Second method uses the first method to calculated the distance for a given Location instance.
The actual calculation of the distance takes advantage of the trigonometry functions: sin and cos (we will not get to the mathematical explanation).
Let’s have a look at the Location class:
package com.bashan.blog.geo;
 
public class Location {
 
private double latitude;
private double longitude;
 
public Location() {
 
public Location(double latitude, double longitude) {
  this.latitude = latitude;
  this.longitude = longitude;
 
public double distance(double latitude, double longitude, Unit unit) {
  double theta = this.longitude - longitude;
  double dist = Math.sin(deg2rad(this.latitude)) * Math.sin(deg2rad(latitude)) +
  Math.cos(deg2rad(this.latitude)) * Math.cos(deg2rad(latitude)) *
  Math.cos(deg2rad(theta));
  dist = Math.acos(dist);
  dist = rad2deg(dist) * 60 * 1.1515;
  switch (unit) {
   case KM:
     dist = dist * 1.609344;
     break;
   case MILE:
    dist = dist * 0.8684;
    break;
   }
  return (dist);
 
public double distance(Location location, Unit unit) {
  return distance(location.getLatitude(), location.getLongitude(), unit);
 
public static double deg2rad(double deg) {
  return (deg * Math.PI / 180.0);
 
public static double rad2deg(double rad) {
  return (rad * 180.0 / Math.PI);
 
public double getLatitude() {
  return latitude;
 
public void setLatitude(double latitude) {
  this.latitude = latitude;
 
public double getLongitude() {
  return longitude;
 
public void setLongitude(double longitude) {
  this.longitude = longitude;
 
@Override
public String toString() {
  return "Location{" +
  "latitude=" + latitude +
  ", longitude=" + longitude +
  '}';
 
public static enum Unit {
  KM, MILE, NAUTICAL_MILE
}
}

The Location class can be downloaded from here.

Let’s have a look at a small test program showing how the Location class is used. We will create 2 Location instances, one of Israel and one of Unites States. The location is more or less at the center of each country.
public static void main(String[] args)
{
  Location locationIsrael = new Location(31.5, 34.75); // Latitude and longitude of Israel
  Location locationUS = new Location(38, -97); // Latitude and longitude of United States
  System.out.print("The distance between Israel and US is: " +
  locationIsrael.distance(locationUS, Unit.KM) + " Kilometers");
}

And the output of this program:
The distance between Israel and US is: 10810.089569538533 Kilometers

No comments:

Post a Comment