views:

4722

answers:

8

I grabbed a database of the zip codes and their langitudes/latitudes, etc from this This page. It has got the following fields:

ZIP, LATITUDE, LONGITUDE, CITY, STATE, COUNTY, ZIP_CLASS

The data was in a text file but I inserted it into a MySQL table. My question now is, how can i utilise the fields above to calculate the distance between two zip codes that a user can enter on the website? Working code in PHP will be appreciated

+5  A: 

It can be done with just maths...

function calc_distance($point1, $point2)
{
    $distance = (3958 * 3.1415926 * sqrt(
      ($point1['lat'] - $point2['lat'])
      * ($point1['lat'] - $point2['lat'])
      + cos($point1['lat'] / 57.29578)
      * cos($point2['lat'] / 57.29578)
      * ($point1['long'] - $point2['long'])
      * ($point1['long'] - $point2['long'])
     ) / 180);

    return $distance;
}
mike
Can you give a reference to where you took this calculation from?
Eran Galperin
Too many magic numbers, and far too much indentation to the right!
Jonathan Leffler
What unit is this returning the distance in? For a zip code which should give 10 miles, it gave something like 7892.xx (approx). How can this be converted to miles?
Click Upvote
functions from a util class had around for years. originally found the math online long ago, dont remember where.formating preference is subjective. i do agree with the magic numbers however its not to likely that the earth is going to change sizes and break the code.
mike
And shouldn't pi be 3.1415927 (with a 7 at the end, not a 6, since the next digit is 5? Or have I misremembered that...)
Ben
The magic numbers: 57.29578 degrees is one radian. And 3958 seems close to the Earth's radius, which is 3963 miles. [Why is the number different? And why only four significant digits when there are so many digits of π?]
ShreevatsaR
3958 is probably the mean radius: 3963 is the equatorial radius. Using a more accurate mean radius is probably meaningless given that the USA is not actually isometric to a subset of the surface of a sphere: what you'd want is a more accurate mean taken over the USA. Or use the GPS spheroid.
Steve Jessop
+1  A: 

See the SO question Geospatial Coordinates and Distance in Kilometres for insight and links. The conversion between miles and kilometres is discussed; you can omit it to get the answer in miles. The discussion also includes URLs to external sources of information.

Jonathan Leffler
+4  A: 

You can also try hitting a web service to calc the distance. Let someone else do the heavy lifting.

http://www.codebump.com/services/PlaceLookup.asmx

brendan
that would work for 2 zipcodes, but imagine trying to select the top 100 closest locations to a given zipcode, from thousands of records in the database :)
aryaxt
+1  A: 

Check out the Haversine formula for calculating great circle distances between two points. Some more samples can be found here

Haversine formula:

  • R = earth’s radius (mean radius = 6,371km)
  • Δlat = lat2− lat1
  • Δlong = long2− long1
  • a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
  • c = 2.atan2(√a, √(1−a))
  • d = R.c

(Note that angles need to be in radians to pass to trig functions).

Paul Dixon
A: 

Check out the Aviation Formulary (http://williams.best.vwh.net/avform.htm) for more formulas than you could ever need for calculating things like this.

dancavallaro
+5  A: 

This is mike's answer with some annotations for the magic numbers. It seemed to work fine for me for some test data:

function calc_distance($point1, $point2)
{
    $radius      = 3958;      // Earth's radius (miles)
    $pi          = 3.1415926;
    $deg_per_rad = 57.29578;  // Number of degrees/radian (for conversion)

    $distance = ($radius * $pi * sqrt(
                ($point1['lat'] - $point2['lat'])
                * ($point1['lat'] - $point2['lat'])
                + cos($point1['lat'] / $deg_per_rad)  // Convert these to
                * cos($point2['lat'] / $deg_per_rad)  // radians for cos()
                * ($point1['long'] - $point2['long'])
                * ($point1['long'] - $point2['long'])
        ) / 180);

    return $distance;  // Returned using the units used for $radius.
}
Adam Bellaire
+1  A: 

There is a great php class for handling this sort of thing, including distance between zip codes, written by micah carrick originally. I've put together a step by step for implementing it which might help. http://go.sparkfire.net/2009/09/search-by-location-miles-from-zipcode-in-php/

Dave
A: 

i have some problem on such topic.I got my answer. thanks everybody

NMRony