Hey guys, this is Karl, one of the developers are RA. We’ve been messing with a few GIS functions lately, and I wanted to make a post for the developers out there.
It turned out the vast amount of PHP code out there that works with Latitude and Longitude doesn’t really lend itself well to GPS coordinates, so I adapted some existing code, and rewrote some code over here to do what we needed. So here are some of the functions.
This function takes two points, and determines the distance between them using the cosine law. This method is reasonably accurate up to around 200km.
function latLongToDistance($lata, $lnga, $latb, $lngb, $km = false) { $theta = $lnga - $lngb; $dist = sin(deg2rad($lata)) * sin(deg2rad($latb)) + cos(deg2rad($lata)) * cos(deg2rad($latb)) * cos(deg2rad($theta)); $dist = rad2deg(acos($dist)); $miles = $dist * 60 * 1.1515; if ($km) return $miles * 1.609344; return $miles; }
Next we wanted to find a square radius, or bounding box given a distance. Give the function a point, and a distance, and it’ll give you a min and max of latitude and longitude for that area. You can use this in SQL to limit the results and later do a check for direct distance from a point, for say, traditional circular radius.
function latLongSquareRadius($lat, $lng, $distance, $km = false) { if (!$km) $distance = $distance * 1.609344; $radius = 6371.009; $lat2 = $lat + rad2deg($distance / $radius); $lat1 = $lat - rad2deg($distance / $radius); //longitude requires compensation $lng2 = $lng + rad2deg($distance / $radius / cos(deg2rad($lat))); $lng1 = $lng - rad2deg($distance / $radius / cos(deg2rad($lat))); return array($lat2, $lng1, $lat1, $lng2); }
Or perhaps you have a world map image, and you’d like to convert lat/long to X/Y coordinates to print a location on the map
function latLongToXY($lat, $long, $width, $height) { $x = ($long + 180) * ($width / 360); $y = (($lat * -1) + 90) * ($height / 180); return array($x, $y); }
How about if we want to take a point, and given a bearing and distance, find where we would end up?
function latLongBearingDistance($lata, $lnga, $range, $bearing, $km = false) { if (!$km) $range = $range * 1.609344; $range /= 6371.009; $bearing = deg2rad($bearing); $lata = deg2rad($lata); $lnga = deg2rad($lnga); $lat = asin(sin($lata) * cos($range) + cos($lata) * sin($range) * cos($bearing)); $lng = $lnga + atan2(sin($bearing) * sin($range) * cos($lata), cos($range) - sin($lata) * sin($lat)); return array(rad2deg($lat), rad2deg($lng)); }
Hope that helps!