PHP – Calculate distance between two postcodes

A while ago I was tasked with designing a small application that calculates the distance between two postcodes. The overall purpose of the application was to fetch the three retail store chains that were nearest to the consumer’s postcode. I naturally assumed the easiest way to do this was to compare the longitude and latitude of both the stores and the consumer’s location. To add a little context, I live in Australia, and I was unable to find a database of all Australian postcodes with their respective longitude and latitude.

Having said that, Australia Post provide a great database with all postcodes within Australia. Once I had a list of these postcodes, I had to then go on to determine their location. To do so, I took advantage of Google Map’s API and wrote a small function to return the longitude and latitude of a given postcode:

// Fetch the coordinates
function getPostcodeLongitudeLatitude($postcode, $country = 'AUS')
{
    // Form the API url
    $url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .
        intval($postcode) . '+' . $country . '&sensor=false';

    // Make the API call
    $result = @file_get_contents($url);
    $geoDetails = json_decode($result);

    // If a successful call, fetch the long/lat
    if ($geoDetails->status === 'OK' &&
        isset($geoDetails->results[0]->geometry->location))
    {
        return $geoDetails->results[0]->geometry->location;
    }
}

A call to the function with postcode 2000 (Sydney) will return the following result:

object(stdClass)#11 (2) {
  ["lat"]=>
  float(-33.8657305)
  ["lng"]=>
  float(151.20733)
}

The above snippet sends a request to the Google Map API which in turn returns the latitude and longitude. I wrote a small script which looped through my database of postcodes and then retrieved and stored their longitude/latitude location (if you’re using a database and they already have each postcode longitude/latitude, this step is not required).

Determining the distance between two longitude/latitudes

Once I had the locations of each postcode, it was relatively easy to code a function that determines the distance between two locations. I say it was easy to code, but that’s only because I used Vincenty’s formula as the basis of my calculations. Even though it may look quite difficult, it is actually very simple math (to learn of the theory behind the math, I strongly urge you to read the Wikipedia article and its sources). My simple PHP implementation of the Vincenty formula is represented in the following function:

function vincentyDistance($latFrom, $longForm, $latTo, $longTo, $earthRadius = 6371000)
{
  // Convert the longitude and latitude from degrees to radians
  $latFrom = deg2rad($latFrom);
  $lonFrom = deg2rad($longForm);
  $latTo = deg2rad($latTo);
  $lonTo = deg2rad($longTo);

  // Mathematics calculations
  $lonDelta = $lonTo - $lonFrom;
  $angle = atan2(
    sqrt(pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2) + pow(cos($latTo) * sin($lonDelta), 2)),
    sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta)
  );

  return $angle * $earthRadius;
}

Therefore, tying the two functions together and calculating the distance between the two postcodes can be done via:

$source = getPostcodeLongitudeLatitude(2000);
$dest = getPostcodeLongitudeLatitude(2050);
$distance = vincentyDistance($source->lat, $source->lng, $dest->lat, $dest->lng);

This in turn returns float(3439.5729259515), which is the distance in meters between the two postcodes.

Comments are closed.