Calculate geodesic distance between two points
May.13, 2007 in
Code Snippets, PHP
/**
* Calculate geodesic distance (in meters) between two points specified by
* latitude/longitude using Vincenty inverse formula for ellipsoids
*
* from: Vincenty inverse formula - T Vincenty, "Direct and Inverse
* Solutions of Geodesics on the Ellipsoid with application of nested
* equations", Survey Review, vol XXII no 176, 1975
* http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
*
* Ported from JavaScript to PHP Martin Milesich - http://milesich.com
*
* Original JavaScript version
* http://www.movable-type.co.uk/scripts/latlong-vincenty.html
*
* @param float $lat1 in form 52.2166667
* @param float $lat2 in form 52.35
* @param float $lon1 in form 5.9666667
* @param float $lon2 in form 4.9166667
* @return float in form 73.174873 (meters)
*/
function distVincenty($lat1, $lon1, $lat2, $lon2)
{
$lat1 = deg2rad($lat1);
$lat2 = deg2rad($lat2);
$lon1 = deg2rad($lon1);
$lon2 = deg2rad($lon2);
$a = 6378137; $b = 6356752.3142; $f = 1/298.257223563; // WGS-84 ellipsoid
$L = $lon2 - $lon1;
$U1 = atan((1-$f) * tan($lat1));
$U2 = atan((1-$f) * tan($lat2));
$sinU1 = sin($U1); $cosU1 = cos($U1);
$sinU2 = sin($U2); $cosU2 = cos($U2);
$lambda = $L; $lambdaP = 2 * M_PI;
$iterLimit = 20;
while (abs($lambda - $lambdaP) > 1e-12 && --$iterLimit > 0)
{
$sinLambda = sin($lambda);
$cosLambda = cos($lambda);
$sinSigma = sqrt(($cosU2 * $sinLambda) * ($cosU2 * $sinLambda) +
($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda) *
($cosU1 * $sinU2 - $sinU1 * $cosU2 * $cosLambda));
if ($sinSigma == 0) return 0; // co-incident points
$cosSigma = $sinU1 * $sinU2 + $cosU1 * $cosU2 * $cosLambda;
$sigma = atan2($sinSigma, $cosSigma); // was atan2
$alpha = asin($cosU1 * $cosU2 * $sinLambda / $sinSigma);
$cosSqAlpha = cos($alpha) * cos($alpha);
$cos2SigmaM = $cosSigma - 2 * $sinU1 * $sinU2 / $cosSqAlpha;
$C = $f / 16 * $cosSqAlpha * (4 + $f * (4 - 3 * $cosSqAlpha));
$lambdaP = $lambda;
$lambda = $L + (1 - $C) * $f * sin($alpha) *
($sigma + $C * $sinSigma * ($cos2SigmaM + $C * $cosSigma *
(-1 + 2 * $cos2SigmaM * $cos2SigmaM)));
}
if ($iterLimit == 0) return false; // formula failed to converge
$uSq = $cosSqAlpha * ($a * $a - $b * $b) / ($b * $b);
$A = 1 + $uSq / 16384 * (4096 + $uSq * (-768 + $uSq * (320 - 175 * $uSq)));
$B = $uSq / 1024 * (256 + $uSq * (-128 + $uSq * (74 - 47 * $uSq)));
$deltaSigma = $B * $sinSigma * ($cos2SigmaM + $B / 4 * ($cosSigma * (-1 + 2 * $cos2SigmaM * $cos2SigmaM) -
$B / 6 * $cos2SigmaM * (-3 + 4 * $sinSigma * $sinSigma) * (-3 + 4 * $cos2SigmaM * $cos2SigmaM)));
$s = $b * $A * ($sigma - $deltaSigma);
$s = round($s, 3); // round to 1mm precision
return $s;
}


One thing though, Why do you use it that way?
Well, I have ported this function to PHP but you should ask your math questions to the original autor :-)
http://www.movable-type.co.uk/scripts/latlong-vincenty.html
Thanks a lot!
I've changed the highlighting script so everything should be ok now.
There is something wrong with the highlighting script. It keeps changing --$iterLimit to -$iterLimit.
Hi Mike,
you are right. This function doesn't work as it is now. There is an typo in the script. It should be --$iterLimit and not -$iterLimit. It is fixed now. Thank you for your comment.
I don't know how Google calculate the distance therefore I can't tell your who is wrong with their calculations.
Martin
I have a question.
If I literally copy the function and run it it gives me an error on the while() loop. This is because of the && -$iterLimit.
If I changed the code as follows
$iterLimit = 20;
$iterLimit_min = 20*-1;
while (abs($lambda - $lambdaP) > 1e-12 && $iterLimit_min > 0) {
It validates, but I aint getting results.
If I do abs($lambda - $lambdaP) > 1e-12 && $iterLimit > 0 ) { it works (without the -)
If I do while (abs($lambda - $lambdaP) > 1e-12) { it works (without && -$iterLimit >0 )
What can I do?
BTW: Google Maps is giving me 164km for a distance between point, the scripts tells me 161km. How is this possible? Is Google wrong?
Hi Dev,
this is not java nor program. It is only a PHP function. You can not run it interactively on your PC.
Martin
Came across your java pgm for gedesic distance between to points on the earth's surface. Very interesting. What do I have to do to compile these codes and run it interactively on my PC ?
- Regards
Dev
San Diego, California,USA
[...] Vincenty formula jest lekko zmodyfikowana wersja pochodzaca z tej strony http://milesich.com/2007/05/13/calculate-geodesic-distance-between-two-points/ [...]