2011-02-17 28 views
62

鑑於與緯度經度+位置的地方數據庫在一定距離內的所有緯度經度位置,如40.8120390,-73.4889650,我如何才能找到的指定距離內的所有位置具體位置?算法找到一個給定的緯度位置LNG

它似乎並不非常有效的選擇從數據庫中的所有位置,然後通過他們去一個接一個,讓從起始位置的距離,看他們是否在規定範圍內。有沒有一種很好的方法來縮小數據庫中最初選擇的位置?一旦我有(或沒有?)一個縮小的位置集合,我是否仍然一個接一個地檢查距離,還是有更好的方法?

我這樣做的語言並不重要。謝謝!

+4

這可能是你所需要的:http://en.wikipedia.org/wiki/K-d_tree – biziclop

+1

無法通過一個SQL查詢來解決它嗎? SELECT * FROM WHERE(Lat - :Lat)^ 2 +(Long - :Long)^ 2 <=:Distance^2(ofc,其他一些數學參與球體和球體等等,這只是一個例子) – Dialecticus

+0

你有沒有在瓦萊拉找到任何答案? –

回答

1

你需要的是空間搜索。您可以使用Solr Spatial search。它也有內置的經緯度數據類型,check here

+0

雖然這可能在理論上回答這個問題,但[這將是更可取的](// meta.stackoverflow.com/q/8259)在這裏包含答案的基本部分,並提供供參考的鏈接。 –

34

從比較緯度之間的距離開始。每個緯度的距離大約爲69英里(111公里)。該範圍從赤道68.703英里(110.567公里)到極點69.407(111.699公里)不等(由於地球的略橢球體形狀)。兩個地點之間的距離將等於或大於緯度之間的距離。

請注意,這不是真正的經度 - 經度的每度的長度取決於緯度。但是,如果您的數據受限於某個區域(例如,單個國家/地區),則還可以計算經度的最小和最大範圍。


繼續將它假定球形地球低精度,快速距離計算:

具有座標{LAT1,lon1}和{LAT2,lon2}兩點之間的大圓距離d由下式給出:

d = acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2)) 

甲數學上等效式,這是一種用於短距離舍入誤差較少主題是:

d = 2*asin(sqrt((sin((lat1-lat2)/2))^2 + 
    cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)) 

d的單位爲弧度

distance_km ≈ radius_km * distance_radians ≈ 6371 * d 

(6371公里是average radius of the earth

的距離此方法的計算需求是mimimal。但是,對於小距離,結果非常準確。


然後,如果它在一個給定的距離,或多或少,使用更準確的方法。

GeographicLib是我所知道的最準確的實現,儘管Vincenty inverse formula也可以使用。


如果您使用的是RDBMS,請將緯度設置爲主鍵,將經度設置爲輔助鍵。如上所述查詢緯度範圍或緯度/經度範圍,然後計算結果集的精確距離。

請注意,所有主要RDBMS的現代版本本地支持地理數據類型和查詢。

+0

只是擡起頭來,第一個鏈接被打破。 – kunruh

+0

@ kunruh:謝謝。該鏈接指向Ed Williams的航空公式,現在似乎已經離線了。我用公式替換了鏈接。 –

2

正如biziclop提到的,某種度量空間樹可能是您最好的選擇。我有使用kd-trees和四叉樹來做這些類型的範圍查詢的經驗,它們非常快;他們也不那麼難寫。我建議看看這些結構之一,因爲它們還可以讓你回答其他有趣的問題,例如「我的數據集中最接近這點的最近點是什麼?」

+0

雖然這可能是解決問題的有價值的提示,但答案確實需要證明解決方案。請[編輯]提供示例代碼來展示你的意思。或者,可以考慮將其寫爲註釋。 –

+1

我實際上認爲這裏的代碼會讓人分心 - 對於包含樹結構和選擇的特定語言的庫而言,這太具體了(注意,這個問題沒有用語言標記)。 – templatetypedef

4

嘗試此很好的解決方案:Geolocation Search

+1

雖然這在理論上可以回答這個問題,[最好](// meta.stackoverflow.com/q/8259)在這裏包含答案的基本部分,並提供供參考的鏈接。 –

0

您可以經緯度轉換爲UTM格式,它是可以幫助你計算距離度量標準格式。然後,您可以輕鬆決定點是否落入特定位置。

+0

雖然這可能是解決問題的有價值的提示,但答案確實需要證明解決方案。請[編輯]提供示例代碼來展示你的意思。或者,可以考慮將其寫爲註釋。 –

8

根據當前用戶的緯度,經度和距離你想找到,SQL查詢如下。

SELECT * FROM(
    SELECT *,(((acos(sin((@latitude*pi()/180)) * sin((Latitude*pi()/180))+cos((@latitude*pi()/180)) * cos((Latitude*pi()/180)) * cos(((@longitude - Longitude)*pi()/180))))*180/pi())*60*1.1515*1.609344) as distance FROM Distances) t 
WHERE distance <= @distance 

@latitude和@longitude是該點的緯度和經度。 緯度和經度是距離表的列。 pi的值是22/7

+0

yogihosting,你是一個傳奇! – Illuminati

3

Tank's Yogihosting

我在我的數據庫表中的一個goups從打開斯特里普地圖和我測試成功。

距離工作罰款米。

SET @orig_lat=-8.116137; 
SET @orig_lon=-34.897488; 
SET @dist=1000; 

SELECT *,(((acos(sin((@orig_lat*pi()/180)) * sin((dest.latitude*pi()/180))+cos((@orig_lat*pi()/180))*cos((dest.latitude*pi()/180))*cos(((@orig_lon-dest.longitude)*pi()/180))))*180/pi())*60*1.1515*1609.344) as distance FROM nodes AS dest HAVING distance < @dist ORDER BY distance ASC LIMIT 100; 
+0

世界不是一個球體! –

+0

你的建議是什麼? –

-2

你可以檢查這個方程 我認爲這將有助於

SELECT id, (3959 * acos(cos(radians(37)) * cos(radians(lat)) * cos(radians(lng) - radians(-122)) + sin(radians(37)) * sin(radians(lat)))) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20; 
+0

雖然這段代碼可能有助於解決問題,但它並沒有解釋_why_和/或_how_它是如何回答問題的。提供這種附加背景將顯着提高其長期教育價值。請[編輯]您的答案以添加解釋,包括適用的限制和假設。特別是,3959和37的魔法值從哪裏來? –

0

既然你說任何語言是可以接受的,自然選擇是PostGIS的:

SELECT * FROM places 
WHERE ST_DistanceSpheroid(geom, $location, $spheroid) < $max_metres; 

如果您想要使用WGS數據,您應該設置$spheroid'SPHEROID["WGS 84",6378137,298.257223563]'

假設您已將places索引爲geom列,這應該是合理有效的。

相關問題