Building remarkable businesses

Geographic Distance and Azimuth Calculations

GeoCalc is a PHP and (MySQL) API that is useful in performing distance calculations between two distinct points on the earth's surface. Used in most GIS (Geographic Information Systems), these are standard algorithms with various levels of accuracy. Simple example of uses for this software would be to find the nearest store location to you, or finding the straight-line distance between two points on a map.

This code was "ported" to PHP from Visual C++ by Steven Brendtro of www.imaginerc.com. The original article and source code, written by andyf4i can be found here on CodeGuru.com.

The GeoCalc library is available for download at the bottom of this page.

Methods

The following methods are available in the API. All code samples below are written in PHP.

Basic Methods

// The default constructor
GeoCalc()

// Using the Great Circle formula, calculate the distance in 
// kilometers between Latitude/Longitude 1 and Latitude/Longitude 2
GCDistance($lat1, $lon1, $lat2, $lon2)

// Using the Great Circle formula, calculate the azimuth between 
// Latitude/Longitude 1 and Latitude/Longitude 2
GCAzimuth($lat1, $lon1, $lat2, $lon2)

// Using the Ellipsoidal Approximation formula, calculate the distance 
// in kilometers between Latitude/Longitude 1 and Latitude/Longitude 2
ApproxDistance($lat1, $lon1, $lat2, $lon2)

// Using the Ellipsoidal Distance formula, calculate the distance in 
// kilometers between Latitude/Longitude 1 and Latitude/Longitude 2. 
// This formula is the most accurate, as it accounts for the "egg-like"
// shape of the earth
EllipsoidDistance($lat1, $lon1, $lat2, $lon2) 	

Basic Methods

// Get the number of Kilometers per degree longitude at the given latitude.
getKmPerLonAtLat($dLatitude)  

// Get the number of degrees longitude per kilometer at the given latitude.
getLonPerKmAtLat($dLatitude) 

// Get the number of kilometers per degree latitude (average of 111.0 
// kilometers per degree of latitude)
getKmPerLat() 

// Get the number of degrees latitude per kilometer (average of 
// 1/111 degrees per kilometer)
getLatPerKm()

Helper Function

ConvKilometersToMiles($dValue) //  	Convert a distance from kilometers to miles (km / 1.609344 = miles).

Examples

Here are some example uses for this class:

      include_once("GeoCalc.class.php");
      $oGC = new GeoCalc();

      // Great Circle Distance
      $dDist = $oGC->GCDistance(38.9333,-94.3253,38.9314,-94.4876);

      // Great Circle Azimuth
      $dDist =  $oGC->GCAzimuth(38.9333,-94.3253,38.9314,-94.4876);

      // Approximate Ellipsoid Distance
      $dDist = $oGC->ApproxDistance(38.9333,-94.3253,38.9314,-94.4876);

      // Accurate Ellipsoid Distance
      $dDist = $oGC->EllipsoidDistance(38.9333,-94.3253,38.9314,-94.4876);

      // Convert distance from kilometers to miles
      $dDistMiles = ConvKilometersToMiles($dDist);

      // Advanced Calculation:
        // The following will search for ZIP codes
        // within a radius (roughly calculated)

        // Define the center of the search bounds...
        $dLongitude = -94.44590241;
        $dLatitude = 38.7996;

        // Define the maximum search distance
        $dRadius = 100.00;  // in kilometers

        // Calculate the boundary distance in degrees longitude / latitude
        $dAddLat = $oGC->getLatPerKm() * $dRadius;
        $dAddLon = $oGC->getLonPerKmAtLat($dLatitude) * $dRadius;

        // Calculate the boundaries
        $dNorthBounds = $dLatitude + $dAddLat;
        $dSouthBounds = $dLatitude - $dAddLat;
        $dWestBounds = $dLongitude - $dAddLon;
        $dEastBounds = $dLongitude + $dAddLon;

        print "Center Longitude: $dLongitude\n";
        print "Center Latitude: $dLatitude\n";
        print "Radius: $dRadius kilometers\n";

        print "North Bounds: $dNorthBounds\n";
        print "South Bounds: $dSouthBounds\n";
        print "East Bounds: $dEastBounds\n";
        print "West Bounds: $dWestBounds\n";

        // Sample SQL query statement based on above boundaries:
        $strQuery = "SELECT * FROM PostalCodes " .
                    "WHERE Latitude > $dSouthBounds " .
                    "AND Latitude < $dNorthBounds " .
                    "AND Longitude > $dWestBounds " .
                    "AND Longitude < $dEastBounds";

For Additional Performance

Using MySQL User Defined Functions (UDF), it is possible to speed up the execution of your distance calculation queries. The performance increase is achieved by relying on a pre-compiled, native library being linked into a running MySQL server.

You can download the FREE GeoCalc MySQL UDF here:

  • GeoCalc UDF 1.0.0 (MySQL <= 4.2)
  • GeoCalc UDF 1.1.1 (MySQL > 4.2)
  • Alternatively, these are both available through the UDF Registry.

    Instructions

    Instructions for compilation and use are included in the downloads.

    Downloads

    Below are all the files available for GeoCalc PHP, the MySQL UDF, and even a free postal code database to get you started in your development. Happy programming!

    AttachmentSize
    GeoCalc PHP 1.23.51 KB
    Free Postal Code to Lon/Lat Database1.17 MB
    MySQL GeoCalc UDF 1.0.0 (MySQL <= 4.2)6.38 KB
    MySQL GeoCalc UDF 1.1.1 (MySQL > 4.2)13.63 KB