Skip to content

Instantly share code, notes, and snippets.

@scips
Last active February 28, 2018 20:28
Show Gist options
  • Save scips/e712696ed226d59d59c9f8c736edeb61 to your computer and use it in GitHub Desktop.
Save scips/e712696ed226d59d59c9f8c736edeb61 to your computer and use it in GitHub Desktop.
Geo Distance between 2 coord
<?php
function sphericalDistance($lat1,$lon1,$lat2,$lon2){
$R = 6371.0; // km
$d = acos(
sin(deg2rad($lat1))*sin(deg2rad($lat2))
+ cos(deg2rad($lat1))*cos(deg2rad($lat2))
* cos(deg2rad($lon2-$lon1))
)
* $R;
return $d;
}
function haversineDistance($lat1,$lon1,$lat2,$lon2){
$R = 6371.0; // km
$dLat = deg2rad($lat2-$lat1);
$dLon = deg2rad($lon2-$lon1);
$a = sin($dLat/2) * sin($dLat/2)
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2))
* sin($dLon/2) * sin($dLon/2);
$c = 2.0 * atan2(sqrt($a), sqrt(1-$a));
$d = $R * $c;
return $d;
}
function vincentyDistance($lat1,$lon1,$lat2,$lon2){
$a = 6378137.0; $b = 6356752.3142; $f = 1/298.257223563; // WGS-84 ellipsiod
//$a = 6378388; $b = 6356911.946; $f = 1/297; // WGS-84 ellipsiod
$L = deg2rad($lon2-$lon1);
$U1 = atan((1-$f) * tan(deg2rad($lat1)));
$U2 = atan((1-$f) * tan(deg2rad($lat2)));
$sinU1 = sin($U1);
$cosU1 = cos($U1);
$sinU2 = sin($U2);
$cosU2 = cos($U2);
$lambda = $L;
$lambdaP = $L;
$iterLimit = 100;
do{
$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;
$cosSigma = $sinU1 * $sinU2 + $cosU1*$cosU2*$cosLambda;
$sigma = atan2($sinSigma, $cosSigma);
$sinAlpha = $cosU1 * $cosU2 * $sinLambda / $sinSigma;
$cosSqAlpha = 1 - $sinAlpha*$sinAlpha;
if($cosSqAlpha!=0){
$cos2SigmaM = $cosSigma - 2*$sinU1*$sinU2/$cosSqAlpha;
}else{
$cos2SigmaM =0;
}
$C = $f/16*$cosSqAlpha*(4+$f*(4-3*$cosSqAlpha));
$lambdaP = $lambda;
$lambda = $L + (1-$C) * $f * $sinAlpha *
($sigma + $C*$sinSigma*($cos2SigmaM+$C*$cosSigma*(-1+2*$cos2SigmaM*$cos2SigmaM)));
}while(abs($lambda-$lambdaP) > 1e-12 && --$iterLimit>0);
if($iterLimit == 0) return false; // formula failed to converge
$uSq = $cosSqAlpha * ($a*$a - $b*$b) / ($b*$b);
$A = 1 + $uSq/16384.0*(4096+$uSq*(-768+$uSq*(320-175*$uSq)));
$B = $uSq/1024.0 * (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);
return $s/1000.0;
}
function DistanceBetweenTwoPoint($point1,$point2,$method=self::SPHERICAL_LAW){
switch($method){
case self::SPHERICAL_LAW:
$distance = $this->sphericalDistance($point1['latitude'],$point1['longitude'],$point2['latitude'],$point2['longitude']);
break;
case self::HAVERSINE:
$distance = $this->haversineDistance($point1['latitude'],$point1['longitude'],$point2['latitude'],$point2['longitude']);
break;
case self::VINCENTY:
$distance = $this->vincentyDistance($point1['latitude'],$point1['longitude'],$point2['latitude'],$point2['longitude']);
break;
}
return $distance;
}
// usage
$distance = DistanceBetweenTwoPoint(
array('longitude'=>50.8427501,'latitude'=>4.3515499)
,array('longitude'=>50.8427501,'latitude'=>4.3515499)
,RTBF_Utility_Regio::SPHERICAL_LAW
);
$distance = DistanceBetweenTwoPoint(
array('longitude'=>50.8427501,'latitude'=>4.3515499)
,array('longitude'=>50.8427501,'latitude'=>4.3515499)
,RTBF_Utility_Regio::HAVERSINE
);
$distance = DistanceBetweenTwoPoint(
array('longitude'=>50.8427501,'latitude'=>4.3515499)
,array('longitude'=>50.8427501,'latitude'=>4.3515499)
,RTBF_Utility_Regio::VINCENTY
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment