2012-03-06 73 views
8

我有一個像下面在數組中找到最接近的經度和緯度?

49.648881 
-103.575312 

一個經度和緯度作爲PHP一個字符串,我想採取並查看值的數組找到最接近的一個。該陣列看起來像

array(
'0'=>array('item1','otheritem1details....','55.645645','-42.5323'), 
'1'=>array('item1','otheritem1details....','100.645645','-402.5323') 
); 

我想要返回具有最長和最近的數組。在這種情況下,它將是第一個(是的,我知道-400不是一個可能的值)。

有沒有什麼快速簡單的方法來做到這一點?我嘗試了數組搜索,但沒有奏效。

差異代碼

function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

    $theta = $lon1 - $lon2; 
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
    $dist = acos($dist); 
    $dist = rad2deg($dist); 
    $miles = $dist * 60 * 1.1515; 
    $unit = strtoupper($unit); 

    if ($unit == "K") { 
    return ($miles * 1.609344); 
    } else if ($unit == "N") { 
     return ($miles * 0.8684); 
    } else { 
     return $miles; 
     } 
} 
+0

能否請您提供您的代碼,你得到兩個經/緯對像'作用距離($ LAT1之間的距離,$ long1,$ lat2,$ long2){...'? – hakre 2012-03-06 17:52:45

+0

這沒有意義,它是簡單的數學? 55 - 49 = 6,55-100 = 45 6小於45. – Steven 2012-03-06 17:54:58

+0

您是否確實知道如何計算地球上兩點之間的距離? – hakre 2012-03-06 17:56:19

回答

20

接近你需要映射首先每個項目與參考點的距離。

然後你排序的地圖,然後你可以告訴它具有最低(或最高如果反向搜索)距離:

$ref = array(49.648881, -103.575312); 

$items = array(
    '0' => array('item1','otheritem1details....','55.645645','-42.5323'), 
    '1' => array('item1','otheritem1details....','100.645645','-402.5323') 
); 

$distances = array_map(function($item) use($ref) { 
    $a = array_slice($item, -2); 
    return distance($a, $ref); 
}, $items); 

asort($distances); 

echo 'Closest item is: ', var_dump($items[key($distances)]); 

輸出:

Closest item is: array(4) { 
    [0]=> 
    string(5) "item1" 
    [1]=> 
    string(21) "otheritem1details...." 
    [2]=> 
    string(9) "55.645645" 
    [3]=> 
    string(8) "-42.5323" 
} 

照顧你有緯度和長度的正確順序。

距離函數(僅頭部略有變化和單位已撤銷):

function distance($a, $b) 
{ 
    list($lat1, $lon1) = $a; 
    list($lat2, $lon2) = $b; 

    $theta = $lon1 - $lon2; 
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
    $dist = acos($dist); 
    $dist = rad2deg($dist); 
    $miles = $dist * 60 * 1.1515; 
    return $miles; 
} 
+0

輝煌!很好的答案! – nickspiel 2014-05-08 02:30:22

1

有沒有快速簡便的方法來做到這一點。您必須迭代所有元素並計算它們之間的距離和起始點,保存結果並重復,僅在結果低於前一個時才保存結果。

0

遍歷數組,將值與您的值進行比較。如果該值小於當前存儲的值(或者如果您沒有當前存儲的值),請改爲存儲該值,否則將其丟棄。

$closest = null; 
foreach($array as $key => $value){ 
    $distance = //compare distance here; 
    if ($closest === null || $closest > $distance) { 
     $closest = $distance; 
    }; 
}; 

當然,這將是由一個事實,即緯度和經度上的球體變得更加困難,東經179和-179比90和179

+0

我已經明確地更新了你的答案,增加了'null'作爲默認值而不是空字符串,顯式嚴格檢查'null',明確指出'179'和'-179'是關於經度的。 – Tadeck 2012-03-06 18:07:24

+0

這就是爲什麼我是前端開發人員,而不是PHP大師。謝謝。 :) – 2012-03-06 18:14:48

4

而是用餘弦的距離定律,你可以使用平面地球近似。平面地球方程減少了計算中的三角函數的數量。 Δlat,Δlon是您的參考點和測試點之間的差異。

這個公式對於長距離導航(千里)不準確,但對於這個特殊的問題,你並不是真正對準確的距離感興趣,但是誰是最接近我的。這是一個更簡單的公式,應該給你。

x = Δlon * cos(lat) // lat/lon are in radians! 
y = Δlat 
distance = R * sqrt(x² + y²) // R is radius of the earth; 
           // typical value is 6371 km 

參考:http://www.movable-type.co.uk/scripts/latlong.html

遠程代碼

function distanceMeters($lat1, $lon1, $lat2, $lon2) { 
    $x = deg2rad($lon1 - $lon2) * cos(deg2rad($lat1)); 
    $y = deg2rad($lat1 - $lat2); 
    $dist = 6371000.0 * sqrt($x*$x + $y*$y); 

    return $dist; 
} 
+0

LOL nvm,我剛剛讀取你的功能名稱是distanceMeters ...忽略我。 – Steven 2012-03-07 22:46:02

+0

如果你不關心實際距離(即只是排序),你還可以從最後一步中刪除R *,因爲它是所有條目的常數乘法 – MatsLindh 2017-06-21 11:28:09