Jump to content

Archived

This topic is now archived and is closed to further replies.

kewl132

Zip Code Locator Hack Question

Recommended Posts

I am in the process of hacking a dealer/zipcode locator script and have ran into a roadblock. I need the script to display the returned results sorted by the distance.

you can view the demo I have up at www.jonstober.com/demo.php

I think I just need to sort the array returned by get_zips_in_range function before I display it but I am not sure how to do this?

Here is the code that I am using

[code]<?

class zipcode_class {

   var $last_error = "";            // last error message set by this class
   var $last_time = 0;              // last function execution time (debug info)
   var $units = "m";                // m = miles, k = kilometers
   var $decimals = 2;               // decimal places for returned distance


   function get_zip_details($zip) {
      
      // This function pulls the details from the database for a
      // given zip code.

      $sql = "SELECT lattitude, longitude, city, state.state_prefix, state_name,
              zip_class, station from zip_code, state
              WHERE zip_code=$zip
              AND zip_code.state_prefix=state.state_prefix";
              
      $r = mysql_query($sql);
      if (!$r) {
         $this->last_error = mysql_error();
         return;
      } else {
         $row = mysql_fetch_array($r, MYSQL_ASSOC);
         mysql_free_result($r);
         return $row;      
      }
   }

   function get_zip_point($zip) {
  
      // This function pulls just the lattitude and longitude from the
      // database for a given zip code.
      
      $sql = "SELECT lattitude, longitude from zip_code WHERE zip_code=$zip";
      $r = mysql_query($sql);
      if (!$r) {
         $this->last_error = mysql_error();
         return;
      } else {
         $row = mysql_fetch_array($r);
         mysql_free_result($r);
         return $row;      
      }      
   }
  
   function calculate_mileageA($lat1, $lat2, $lon1, $lon2) {
      
      // This function is not used right now.  This is based on code found
      // all over the internet such as 4guysfromrolla.com.  It's not clear
      // who the original author was.
      
      $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2));
      $dist = $dist+cos(deg2rad($lat1))*cos(deg2rad($lat2))*cos(deg2rad($lon1 - $lon2));
      $dist = acos($dist);
      $dist = rad2deg($dist);
      return $dist * 60 * 1.1515;
   }

   function calculate_mileage($lat1, $lat2, $lon1, $lon2) {

      // used internally, this function actually performs that calculation to
      // determine the mileage between 2 points defined by lattitude and
      // longitude coordinates.  This calculation is based on the code found
      // at http://www.cryptnet.net/fsp/zipdy/
      
      // Convert lattitude/longitude (degrees) to radians for calculations
      $lat1 = deg2rad($lat1);
      $lon1 = deg2rad($lon1);
      $lat2 = deg2rad($lat2);
      $lon2 = deg2rad($lon2);
      
      // Find the deltas
      $delta_lat = $lat2 - $lat1;
      $delta_lon = $lon2 - $lon1;
    
      // Find the Great Circle distance
      $temp = pow(sin($delta_lat/2.0),2) + cos($lat1) * cos($lat2) * pow(sin($delta_lon/2.0),2);
      $distance = 3956 * 2 * atan2(sqrt($temp),sqrt(1-$temp));

      return $distance;
   }
  
   function get_zips_in_range($zip, $range) {
      
      // returns an array of the zip codes within $range of $zip. Returns
      // an array with keys as zip codes and values as the distance from
      // the zipcode defined in $zip.
      
      
      $details = $this->get_zip_point($zip);  // base zip details
      if (empty($details)) return;
      
      // This portion of the routine  calculates the minimum and maximum lat and
      // long within a given range.  This portion of the code was written
      // by Jeff Bearer (http://www.jeffbearer.com). This significanly decreases
      // the time it takes to execute a query.  My demo took 3.2 seconds in
      // v1.0.0 and now executes in 0.4 seconds!  Greate job Jeff!
      
      // Find Max - Min Lat / Long for Radius and zero point and query
      // only zips in that range.
      $lat_range = $range/69.172;
      $lon_range = abs($range/(cos($details[0]) * 69.172));
      $min_lat = number_format($details[0] - $lat_range, "4", ".", "");
      $max_lat = number_format($details[0] + $lat_range, "4", ".", "");
      $min_lon = number_format($details[1] - $lon_range, "4", ".", "");
      $max_lon = number_format($details[1] + $lon_range, "4", ".", "");
      

      $return = array();    // declared here for scope


      $sql = "SELECT * FROM zip_code
              WHERE szip = zip_code AND lattitude BETWEEN '$min_lat' AND
             '$max_lat' AND longitude BETWEEN '$min_lon' AND '$max_lon' LIMIT 3";
            
      $r = mysql_query($sql);
      
      if (!$r) {    // sql error
      
         $this->last_error = mysql_error();
         return;
        
      } else {
          
         while ($row = mysql_fetch_row($r)) {
  
            // loop through all 40 some thousand zip codes and determine whether
            // or not it's within the specified range.
            
            $dist = $this->calculate_mileage($details[0],$row[1],$details[1],$row[2]);
            if ($this->units == 'k') $dist = $dist * 1.609344;
            if ($dist <= $range) {
               $return[str_pad($row[0], 5, "0", STR_PAD_LEFT)] = round($dist, $this->decimals);
            }
         }
         mysql_free_result($r);
      }
      
          
      return $return;
   }

   function chronometer()  {

   // chronometer function taken from the php manual.  This is used primarily
   // for debugging and anlyzing the functions while developing this class.  
  
   $now = microtime(TRUE);  // float, in _seconds_
   $now = $now + time();
   $malt = 1;
   $round = 7;
  
   if ($this->last_time > 0) {
       /* Stop the chronometer : return the amount of time since it was started,
       in ms with a precision of 3 decimal places, and reset the start time.
       We could factor the multiplication by 1000 (which converts seconds
       into milliseconds) to save memory, but considering that floats can
       reach e+308 but only carry 14 decimals, this is certainly more precise */
      
       $retElapsed = round($now * $malt - $this->last_time * $malt, $round);
      
       $this->last_time = $now;
      
       return $retElapsed;
   } else {
       // Start the chronometer : save the starting time
    
       $this->last_time = $now;
      
       return 0;
   }
}

} [/code]

Share this post


Link to post
Share on other sites
It may be as simple as using an ORDER BY clause to your SQL statement.

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.