Last active
August 29, 2015 14:02
-
-
Save zetas/f08f9f89a579c6bcef31 to your computer and use it in GitHub Desktop.
Crazy geospatial radius calculation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$db = new PDO('mysql:host=localhost;port=3306;dbname=homestead', 'homestead', 'secret'); | |
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); | |
#4980,Long Prairie,MN,verified,45.971955,-94.866789 | |
$lat = 45.971955; | |
$lon = -94.866789; | |
$rad = 30; #KM | |
$R = 6371; // earth's mean radius, km | |
$maxLat = $lat + rad2deg($rad/$R); | |
$minLat = $lat - rad2deg($rad/$R); | |
// compensate for degrees longitude getting smaller with increasing latitude | |
$maxLon = $lon + rad2deg($rad/$R/cos(deg2rad($lat))); | |
$minLon = $lon - rad2deg($rad/$R/cos(deg2rad($lat))); | |
$sql = " | |
Select id, name, state, latitude, longitude, | |
acos(sin(:lat)*sin(radians(latitude)) + cos(:lat)*cos(radians(latitude))*cos(radians(longitude)-:lon)) * :R As D | |
From ( | |
Select id, name, state, latitude, longitude | |
From cities | |
Where latitude Between :minLat And :maxLat | |
And longitude Between :minLon And :maxLon | |
) As FirstCut | |
Where acos(sin(:lat)*sin(radians(latitude)) + cos(:lat)*cos(radians(latitude))*cos(radians(longitude)-:lon)) * :R < :rad | |
Order by D"; | |
$params = array( | |
'lat' => deg2rad($lat), | |
'lon' => deg2rad($lon), | |
'minLat' => $minLat, | |
'minLon' => $minLon, | |
'maxLat' => $maxLat, | |
'maxLon' => $maxLon, | |
'rad' => $rad, | |
'R' => $R, | |
); | |
$points = $db->prepare($sql); | |
$points->execute($params); | |
foreach ($points as $point) { | |
echo "$point->id|$point->name|$point->state\n\n"; | |
} | |
/* | |
Response with a radius of 30km: | |
vagrant@homestead:~$ php test.php | |
4980|Long Prairie|MN | |
4901|Eagle Bend|MN | |
5054|Sauk Centre|MN | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment