Archive for the 'Applications' Category

Radius-based Zip Code Finder

A year or so ago, I had the task to build a “zip code finder”; a tool that allows a user to enter a zip code and a radius, and return all zip codes in that radius.  All of the references I found online were pretty much the exact application I was trying to build, so they didn’t help me that much. I did eventually run across the math that allows you to build the application. Unfortunately, I didn’t save the link to the page. If I ever find it, I’ll be sure to post it. While I initially built this application for US zip codes, I’m sure it’ll work for zip codes outside of the US, since we are mostly concerned with the longitude and latitudes of the zip codes. This is how to build a radius-based zip code finder:

First, you need a zip code database. The database should contain the following fields at minimum: zip code, longitude, and latitude. Let me say that this task alone can be difficult, if you are searching for a free database. Most of the databases available will cost money, mainly because the database data changes every-so often (since US zip codes change every so often). Free databases (mostly in the form of a .CSV file) are out there, but if you want a highly accurate database, it might be worth to pay the money for one.

Update – After looking around for a little bit, I found this file that will work as a nice zip code database. The file comes directly from the US Census, so it should be pretty accurate. You can also check this SourceForge project for a nice zip code database.

Now comes the math and the process of determining the longitudes and latitudes in the radius. Since I’m not a math expert, I’ll do my best to explain what each number or formula is. For the formulas, I’ll show the PHP code (I actually created the PHP code by converting the original .NET code I wrote.)

Step 1
Find the longitude and latitude for the zip code using the database. This is your center point for your radius. If you can’t find the zip code in the database, then the zip code is incorrect or you have an outdated database.

Step 2
Convert the longitude, latitude, and radius distance (in miles) to radians using these formulas:

1
2
3
4
// Convert the coordinates and distance to radians
$dLatInRads = $latitude * (M_PI / 180);
$dLongInRads = $longitude * (M_PI / 180);
$dDistInRad = $distanceRadius / EARTH_RADIUS_IN_MILES;

EARTH_RADIUS_IN_MILES is a constant set to 3956. M_PI is a PHP constant.

Step 3
Honestly, I don’t remember what this number is for. In my code, it’s called “lat”. It uses this formula:

1
$lat = asin(sin($dLatInRads) * cos($dDistInRad));

Step 4
Find the top and bottom lines of the bounding box using this formula:

1
2
3
4
5
6
7
// Find the top line
$topLine = $dLatInRads + $dDistInRad;
$topLine *= (180 / M_PI);
 
// Find the bottom line
$bottomLine = $dLatInRads - $dDistInRad;
$bottomLine *= (180 / M_PI);

Step 5
Find the right and left lines of the bounding box. For each line, you need to calculate a number called “dlon”. Once again, I don’t remember what this is. Here is the formula:

1
2
3
4
5
6
7
8
9
// Find the right line
$dlon = atan2(sin(M_PI / 2) * sin($dDistInRad) * cos($dLatInRads), cos($dDistInRad) - sin($dLatInRads) * sin($lat));
$rightLine = (fmod(($dLongInRads + $dlon + M_PI), (2 * M_PI))) - M_PI;
$rightLine *= (180 / M_PI);
 
// Find the left line
$dlon = atan2(sin(3 * M_PI / 2) * sin($dDistInRad) * cos($dLatInRads), cos($dDistInRad) - sin($dLatInRads) * sin($lat));
$leftLine = (fmod(($dLongInRads + $dlon + M_PI), (2 * M_PI))) - M_PI;
$leftLine *= (180 / M_PI);

You now have the full bounding box of the zip code radius.

Step 6
Using the database, find all longitudes and latitudes in the bounding box. I use this SQL statement:

1
2
3
4
5
6
SELECT ZipCode, Latitude, Longitude
FROM ZipCodes
WHERE Latitude <= '$bottomLine'
AND Latitude >= '$topLine'
AND Longitude <= '$leftLine'
AND Longitude >= '$rightLine'";

This will return all the zip codes in the bounding box. Note that the bounding box is exactly that… a box. Some of the zip codes you return will be outside of the initial radius. If you want, you can filter out those zip codes in Step 7.

Step 7 (optional)
Filter out the zip codes outside of the radius by simply checking the distance between the center longitude/latitude and the returned zip code longitude/latitude. Use this formula:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Convert all the coordinates to radians
$dStartLatInRad = $startLatitude * (M_PI / 180);
$dStartLongInRad = $startLongitude * (M_PI / 180);
$dEndLatInRad = $endLatitude * (M_PI / 180);
$dEndLongInRad = $endLongitude * (M_PI / 180);
 
// Find the distance between the starting and ending coordinates
$dLatitude = $dEndLatInRad - $dStartLatInRad;
$dLongitude = $dEndLongInRad - $dStartLongInRad;
 
// Intermediate result a
$a = pow(sin($dLatitude / 2) , 2) + cos($dStartLatInRad) * cos($dEndLatInRad) * pow(sin($dLongitude / 2), 2);
 
// Intermediate result c (great circle distance in radians)
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
 
// Distance
$dDistance = EARTH_RADIUS_IN_MILES * $c;

After you filter out the zip codes, you can return your result set. That’s it!

Switching del.icio.us Account Names

A couple of days ago I realized that I have inconsistency between all my social networking website account names (the OCD kicked in). I decided to switch all my ‘cjsharp1′ accounts over to a ‘cjsharp’ account name (pitiful, huh). Funny thing is that between all the social networks sites I am involved in, the only one I wanted to switch was my del.icio.us account, which is also the most complicated to switch.

Here is what you have to do to switch del.icio.us accounts. Unfortunately, this will not transfer your network along with it, so if you have a large network, be prepared to handle that accordingly. This also will not transfer your profile settings or your tag bundles.

  1. Create your new account through del.icio.us.
  2. Log into your old account. Export your old account’s bookmarks (Settings > Bookmarks > Export/Backup). Be sure to include the tags and notes. It will export it to an HTML file.
  3. Log out of your old account, then log into your new account.
  4. Import the HTML file into your new account (Settings > Bookmarks > Import/Upload). By default, the ‘imported’ tag will be appended to each bookmark. If you don’t want this tag appended, just remove it. (Or you can leave this as it is and delete the tag later). It may take some time for the bookmarks to import. It took about 5-10 minutes for my bookmarks to import. It all depends on the incoming traffic to del.icio.us and the number of bookmarks you are importing.
  5. When the import is complete, view your new account’s bookmarks. You will see that all of the imported bookmarks are not shared by default. To make things more complicated, del.icio.us does not offer a ‘share all’ function, due to a couple reason listed in their FAQ. To work around this, I found this option which involves pasting some JavaScript in the address bar of your browser. The quickest way to do this is to view your del.icio.us page showing as many bookmarks at one time (100), paste the JavaScript in the address bar, confirm how many bookmarks will be shared (via a JavaScript pop-up), sit back and relax. A delay is set between the requests in order to prevent del.icio.us from blocking your requests. I set my delay to 4 seconds (delay=4000) with no problems.
  6. Finally, once all of your bookmarks are imported and shared, you’ll want to delete your old account. Log out of your new account and log back into your old account, and delete your account (Settings > Account > Delete Account).