There are several approaches to get zip codes within given radius from given zip:
- Round circle by square if zips given by points;
- Exact 3D geometry calculate if zips given by points;
- Exact GIS calculate if zips given by polygons.
Approximation by square
We approximate circle by square on surface, where:
- latitude +- radius/EARTH_RADUIS
- longitude +- radius/(EARTH_RADUIS*cos(latitude))
cos here is because longitudes distances differ depending on latitudes (say, in polar it is 0).
The databases for 1999 is an accessible open source, but up to date database costs money. Free database:
Open source database is about 42 000 records. Up to date is about 72 000. See, for instance:
Exact 3D calculations
- x= EARTH_RADIUS*sin(latitude)*cos(longitude)
- y= EARTH_RADIUS*sin(latitude)*sin(longitude)
- z= EARTH_RADIUS*cos(latitude)
Search points must be within sphere:
x*x + y*y + z*z <= radius*radius
It is non-efficient table full-scan implementation.
Exact zip polygon databases
Here you have to install open-source PostGIS (http://postgis.refractions.net/) system on your PostgreSQL and buy zip codes polygon database.
After installing PostGIS you can query zip codes within given radius the next way (http://postgis.refractions.net/pipermail/postgis-users/2007-February/014760.html):
SELECT z.zipcode FROM zipcode z, zipcode z2 WHERE z2.zipcode = '02109' AND expand(z2.the_geom, "whatever radius you want goes here but your spatial ref needs to be in that metric or you need to convert the radius") && z.the_geom AND distance(z.the_geom, z2.the_geom) <= "radius"
Zip codes polygon databases:
Or, if you use RoR, you can use the following plugins:
- YM4R/GM (http://agilewebdevelopment.com/plugins/ym4r_gm),
- GeoKit (http://geokit.rubyforge.org/).
As far as I understand they use Google API, so they have some restrictions.