2012-09-15 36 views
12

我已經看過如此多的函數,但它恰好只適用於MySQL或Postgresql。我想要PHP的等價邏輯。我正在進行一些比較, 就像我有創建時所產生的這些數據。如何使用PHP檢查某個座標是否落入另一個座標半徑

Lat: 56.130366 
Long: -106.34677099999 

後來,我想檢查這個座標是否落在另一個座標的半徑內,然後返回true,否則爲false。

Lat: 57.223366 
Long: -106.34675644699 
radius: 100000 (meters) 

在此先感謝!

+1

谷歌「haversine公式」或「Vincenty公式」工作了兩次緯度/多頭 –

回答

28

感謝您的幫助。下面是一個示例函數,它使用兩組經度和緯度座標並返回兩者之間的距離。

function getDistance($latitude1, $longitude1, $latitude2, $longitude2) { 
    $earth_radius = 6371; 

    $dLat = deg2rad($latitude2 - $latitude1); 
    $dLon = deg2rad($longitude2 - $longitude1); 

    $a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * sin($dLon/2) * sin($dLon/2); 
    $c = 2 * asin(sqrt($a)); 
    $d = $earth_radius * $c; 

    return $d; 
} 

$distance = getDistance(56.130366, -106.34677099999, 57.223366, -106.34675644699); 
if($distance < 100) { 
    echo "Within 100 kilometer radius"; 
} else { 
    echo "Outside 100 kilometer radius"; 
} 
+2

[相當於,但在Javascript](https://gist.github.com/moshmage/2ae02baa14d10bd6092424dcef5a1186),因爲我花了太長時間尋找這個。 – MoshMage

6

您應該使用Haversine formula計算兩點之間的距離。你有一個PHP version here

然後檢查是否distance < 100000

+0

你到了那裏良好的代碼之間的距離。但距離真的是米或公里? –

+0

這取決於地球半徑。如果你使用6371就像我已經鏈接的代碼,它是公里:) –

+0

我看到一些算法使用6367作爲地球半徑,但其中大部分是6371真的很重要嗎?無論如何感謝:) –

1

這應有助於,

$lat_origin = 56.130366; 
$long_origin = -106.34677099999; 

$lat_dest = 57.223366; 
$long_dest = -106.34675644699; 

$radius  = 3958;  # Earth's radius (miles, convert to meters) 
$deg_per_rad = 57.29578; # Number of degrees/radian (for conversion) 

$distance = ($radius * pi() * sqrt(
      ($lat_origin - $lat_dest) 
      * ($lat_origin - $lat_dest) 
      + cos($lat_origin/$deg_per_rad) # Convert these to 
      * cos($lat_dest/$deg_per_rad) # radians for cos() 
      * ($long_origin - $long_dest) 
      * ($long_origin - $long_dest) 
    )/180); 
1
// Vincenty formula to calculate great circle distance between 2 locations 
//  expressed as Lat/Long in KM 

function VincentyDistance($lat1,$lat2,$lon1,$lon2){ 
    $a = 6378137 - 21 * sin(lat); 
    $b = 6356752.3142; 
    $f = 1/298.257223563; 

    $p1_lat = $lat1/57.29577951; 
    $p2_lat = $lat2/57.29577951; 
    $p1_lon = $lon1/57.29577951; 
    $p2_lon = $lon2/57.29577951; 

    $L = $p2_lon - $p1_lon; 

    $U1 = atan((1-$f) * tan($p1_lat)); 
    $U2 = atan((1-$f) * tan($p2_lat)); 

    $sinU1 = sin($U1); 
    $cosU1 = cos($U1); 
    $sinU2 = sin($U2); 
    $cosU2 = cos($U2); 

    $lambda = $L; 
    $lambdaP = 2*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); 
     $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))); 
    } 

    $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); 
    return $s/1000; 
} 


echo VincentyDistance($lat1,$lat2,$lon1,$lon2); 
相關問題