Show:

File: platform/plugins/Places/classes/Places/Zipcode.php

<?php
/**
 * @module Places
 */
/**
 * Class representing 'Zipcode' rows in the 'Places' database
 * You can create an object of this class either to
 * access its non-static methods, or to actually
 * represent a zipcode row in the Places database.
 *
 * @class Places_Zipcode
 * @extends Base_Places_Zipcode
 */
class Places_Zipcode extends Base_Places_Zipcode
{
	/**
	 * The setUp() method is called the first time
	 * an object of this class is constructed.
	 * @method setUp
	 */
	function setUp()
	{
		parent::setUp();
	}

	/**
	 * Implements the __set_state method, so it can work with
	 * with var_export and be re-imported successfully.
	 * @method __set_state
	 * @param {array} $array
	 * @return {Places_Zipcode} Class instance
	 */
	static function __set_state(array $array)
	{
		$result = new Places_Zipcode();
		foreach($array as $k => $v)
			$result->$k = $v;
		return $result;
	}
	
	
	/**
	 * Call this function to find zipcodes near a certain location
	 * @param {double} $latitude The latitude of the coordinates to search around
	 * @param {double} $longitude The longitude of the coordinates to search around
	 * @param {double} $meters The radius, in meters, around the central point of the zipcode
	 * @param {double} $limit Limit on how many to return. Defaults to 100.
	 * @return {array} Returns an array of Places_Zipcode objects, if any are found.
	 */
	public static function nearby($latitude, $longitude, $meters, $limit = 100)
	{
		// First, get a bounding box that's big enough to avoid false negatives
		$latGrid = $meters / (1609.34 * 69.1703234283616);
		$longGrid = abs($latGrid / cos(deg2rad($latitude)));
		
		// Now, select zipcodes in a bounding box using one of the indexes
		$q = Places_Zipcode::select()
		->where(array('latitude' => new Db_Range(
			$latitude - $latGrid, false, true, $latitude + $latGrid
		)));
		$condition1 = array('longitude' => new Db_Range(
			max($longitude - $longGrid, -180), false,
			false, min($longitude + $longGrid, 180)
		));
		if ($longitude + $longGrid > 180) {
			$q = $q->andWhere($condition1, array('longitude' => new Db_Range(
				-180, true, false, $longitude + $longGrid - 180 * 2
			)));
		} else if ($longitude - $longGrid < -180) {
			$q = $q->andWhere($condition1, array('longitude' => new Db_Range(
				$longitude - $longGrid + 180 * 2, false, true, 180
			)));
		} else {
			$q = $q->andWhere($condition1);
		}
		$latitude = substr($latitude, 0, 10);
		$longitude = substr($longitude, 0, 10);
		$q = $q->orderBy(
			"POW(latitude - ($latitude), 2) + POW(longitude - ($longitude), 2)"
		);
		if ($limit) {
			$q = $q->limit($limit);
		}
		return $q->fetchDbRows();
	}
	
	/**
	 * Use this to calculate the distance of a zipcode's central point to some
	 * pair of geographic coordinates.
	 * @param {double} $latitude
	 * @param {double} $longitude
	 */
	function distanceTo($latitude, $longitude)
	{
		return Places::distance($this->latitude, $this->longitude, $latitude, $longitude);
	}
	
	/**
	 * Use this to calculate the distance of a zipcode's central point to some lat/long pair
	 * @param {double} $lat
	 * @param {double} $long
	 */
	function distanceToZipcode($zipcode)
	{
		return Places::distance($this->latitude, $this->longitude, $zipcode->latitude, $zipcode->longitude);
	}
};