Skip to content

Instantly share code, notes, and snippets.

@jakebathman
Last active July 15, 2020 15:10
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 jakebathman/883a447f9eca970b0bc1 to your computer and use it in GitHub Desktop.
Save jakebathman/883a447f9eca970b0bc1 to your computer and use it in GitHub Desktop.
Lat/Lon Distance Calculator
<?php
/**
* Calculate the distance between two points on a sphere
*
* Implements the Haversine formula: http://en.wikipedia.org/wiki/Haversine_formula
*
* More advanced calculation (good for antipodal points) can be used by using
* FALSE for $boolUseHaversine. This will use another solution to the Great-circle
* ditance problem (http://en.wikipedia.org/wiki/Great-circle_distance), implementing
* the Vincenty formula (http://en.wikipedia.org/wiki/Vincenty%27s_formulae#Nearly_antipodal_points).
* This matches the calculation from Google's Geometry Library's computeDistanceBetween() function,
* assuming the Mercator projection value of Earth's radius of 6378137.0 meters
*
* $lat1 (string) decimal latitude for point 1
* $lng1 (string) decimal longitude for point 1
* $lat2 (string) decimal latitude for point 2
* $lng2 (string) decimal longitude for point 2
* $unit (string) OPTIONAL unit of measure, either M (miles, the default), K (kilometers), or N (nautical miles)
* $boolUseHaversine (boolean) OPTIONAL formula to use for the calculation. Haversine is good for shorter distances (<10,000 km),
* see above for more information on Haversine
*
* @return Returns a decimal distance in the $unit of choice
*
*/
function geoDistance($lat1, $lng1, $lat2, $lng2, $unit = "M", $boolUseHaversine = true)
{
if ($boolUseHaversine === true) {
$theta = $lng1 - $lng2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$totalDist = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($totalDist * 1.609344);
} elseif ($unit == "N") {
return ($totalDist * 0.8684);
} else {
return $totalDist;
}
} else {
// Vincenty formula implementation from martinstoeckli on Stack Overflow: http://stackoverflow.com/a/10054282/1026279
$earthRadius = 6378137.0; // in meters
// convert from degrees to radians
$latFrom = deg2rad($lat1);
$lonFrom = deg2rad($lng1);
$latTo = deg2rad($lat2);
$lonTo = deg2rad($lng2);
$lonDelta = $lonTo - $lonFrom;
$a = pow(cos($latTo) * sin($lonDelta), 2) +
pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
$angle = atan2(sqrt($a), $b);
$totalDist = $angle * $earthRadius;
return $totalDist / 1000;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment