How to lookup a zipcode from a GPS coordinate?

jpm picture jpm · May 28, 2009 · Viewed 14.5k times · Source

Say I have a web service API that accepts a zipcode as a parameter, but I only have access to a GPS coordinate (latitude, longitude). How can I dynamically lookup the zipcode that the coordinate belongs to?

I'm doing this work on the iPhone, so hopefully there's a simple way to do this within the CoreLocation APIs that I'm overlooking in the documentation.

Answer

nevan king picture nevan king · May 28, 2009

This page provides a database (in csv) of all the zip codes in the US, with their latitude and longitude. http://zips.sourceforge.net/

The file is 500k unpacked. Here's the first few lines of data:

"35004", "AL", " 33.606379", " -86.50249", "Moody", "Alabama"
"35005", "AL", " 33.592585", " -86.95969", "Adamsville", "Alabama"
"35006", "AL", " 33.451714", " -87.23957", "Adger", "Alabama"

Dump this data into a local database. Use the Haversine formula to compare your coordinates and the ones in the database to find the nearest point. CoreLocation has a function getDistanceFrom that you could use too.

- (CLLocationDistance)getDistanceFrom:(const CLLocation *)location

This page has a Haversine function in c and info about the zips database.

http://www.jaimerios.com/?p=39

Edit: Heres a great explanation from Google about calculating distances. It uses MySQL and PHP, but the SQL for finding nearest points is also useful here. It'd probably be faster to query using SQL, rather than the getDistanceFrom function.

http://code.google.com/support/bin/answer.py?answer=87134&topic=11364

Find the closest 20 locations that are within a radius of 25 miles to the 37, -122 coordinate:

SELECT id, ( 3959 * acos( cos( radians(37) ) 
 * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) 
 + sin( radians(37) ) * sin( radians( lat ) ) ) ) 
 AS distance FROM markers HAVING distance < 25 
 ORDER BY distance LIMIT 0 , 20; 

To search by kilometers instead of miles, replace 3959 with 6371.