Skip to content

Instantly share code, notes, and snippets.

@ryanto
Created February 1, 2011 21:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanto/806683 to your computer and use it in GitHub Desktop.
Save ryanto/806683 to your computer and use it in GitHub Desktop.
<?php
/**
* Finds all of the X(table) within (radius) of (object).
*
* Uses Haversine formula
*
* @author ryan
*/
class Gps_Radius {
/**
* @var Doctrine_Connection
*/
private $doctrine;
private $table;
private $object;
private $radius;
private $limit = 10;
private $latitude;
private $longitude;
private $results = array();
public function setDoctrine($doctrine) {
$this->doctrine = $doctrine;
}
public function setTable($table) {
$this->table = $table;
}
public function setObject($object) {
$this->object = $object;
}
public function setRadius($radius) {
$this->radius = $radius;
}
public function setLimit($limit) {
$this->limit = $limit;
}
public function results() {
return $this->results;
}
public function count() {
return count($this->results);
}
/**
* @return array
*/
public function find() {
$this->tableData();
$this->randomize();
$this->limit();
$this->distance();
}
private function tableData() {
$longitude = $this->object->longitude;
$latitude = $this->object->latitude;
$radius = $this->radius;
$lng_min = $longitude - $radius / abs(cos(deg2rad($latitude)) * 69);
$lng_max = $longitude + $radius / abs(cos(deg2rad($latitude)) * 69);
$lat_min = $latitude - ($radius / 69);
$lat_max = $latitude + ($radius / 69);
$query = $this->doctrine->createQuery()
->from(addslashes($this->table) . ' t')
->where('latitude between ? and ?', array($lat_min, $lat_max))
->andWhere('longitude between ? and ?', array($lng_min, $lng_max));
$results = $query->execute();
$this->results = array();
foreach ($results as $row) {
if ($row->isViewable()) {
$this->results[] = array(
'object' => $row,
'distance' => $this->radius
);
}
}
}
private function distance() {
$newResults = array();
$latitude = $this->object->latitude;
$longitude = $this->object->longitude;
foreach ($this->results as $row) {
$object = $row['object'];
$distance = 3956 * 2 *
asin(sqrt(pow(sin(($latitude - abs($object->latitude)) * pi() / 180 / 2), 2) +
cos($latitude * pi() / 180) * cos(abs($object->latitude) * pi() / 180) *
pow(sin(($longitude - $object->longitude) * pi() / 180 / 2), 2)));
$row['distance'] = $distance;
$newResults[] = array('object' => $object, 'distance' => $distance);
}
$this->results = $newResults;
}
private function randomize() {
// kinda bad that this class is coupled with the search model. easy
// to refactor out if things look like they wil lget messy
usort($this->results, array('Search_Sort_Sort', 'sortByRandom'));
}
private function limit() {
$this->results = array_slice($this->results, 0, $this->limit);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment