例如,我在我的數據庫中有汽車事件。這些事件有經緯度。在使用GPS的手機上,我用他的座標獲取用戶的位置。用戶可以選擇他想知道他周圍是否有事故的半徑。所以,假設他想知道在他身邊2英里的事件。PHP MySQL通過GPS獲取半徑用戶位置的位置
因此,我從電話發送到Web服務用戶的經度,經度和他選擇的半徑。我需要做一個SQL查詢來獲取用戶周圍2英里的事件。
你有什麼想法該怎麼做?
例如,我在我的數據庫中有汽車事件。這些事件有經緯度。在使用GPS的手機上,我用他的座標獲取用戶的位置。用戶可以選擇他想知道他周圍是否有事故的半徑。所以,假設他想知道在他身邊2英里的事件。PHP MySQL通過GPS獲取半徑用戶位置的位置
因此,我從電話發送到Web服務用戶的經度,經度和他選擇的半徑。我需要做一個SQL查詢來獲取用戶周圍2英里的事件。
你有什麼想法該怎麼做?
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;
}
} // end function
$x_lat=center_of_serach;
$x_lon=center_of_serach;
$_distance=some_distance_in_miles;
$query1 = "SELECT * FROM `location_table` WHERE somefield=somefilter";
$result=mysql_db_query($db_conn, $query1);
$max_rows=mysql_num_rows($result);
if ($max_rows>0)
{
while ($data1=mysql_fetch_assoc($result))
{
if (distance($x_lat,$x_lon,$data1['lat'],$data1['lng'],'m')<$_distance)
{
//do stuff
}
}
它更快地獲取所有數據並通過函數運行它,而不是在數據庫不太大的情況下使用查詢。
它也適用於Kilos和Nautical英里。 ;)
有一個公式可以計算兩個緯度/經度座標之間的距離。但要小心 - 它在計算上相當昂貴,所以如果你有很多事件發生,你會想要做到這一點。首先,read about the maths involved。
至於PHP的代碼,一個快速谷歌翻了起來this link,看起來可能工作。
現在,你可能想使用一些更有效的方法來你的事件點分爲兩類:一類是點可能是範圍內(希望一個很小的一套),以及那些你完全可以打折。檢查超過幾十個事件座標可能是一個性能問題。
我對此沒有任何特別的瞭解,但如果沒有人有聰明的事情發生,我會在稍後允許的情況下嘗試自己提出一些事情。
我也推薦這個。我會考慮在數據集上做兩次傳球。第一遍將檢查事件經度是否在位置經度的X英里內,以及事件緯度是否在位置緯度的X英里內。這是一個非常簡單的查詢,它將返回一個較小的數據集來處理。使用這個較小的數據集,開始做一些觸發以確定事件與用戶位置的線性距離,這需要更復雜的數學運算,但您至少現在正在使用較小的數據集。 – 2010-07-28 04:11:01
@Jakobud你可以在相同的查詢中運行該過濾器:'WHERE lat <='「。$ _ distance。」'AND lng <='「。$ _ distance。」'「;' – 2010-07-28 04:15:44
是的,類似的東西。 Jackobud的方法是,首先檢查是否有候選點在用戶座標爲中心的4英里(16平方英里)的區域內,如果是,則進行更昂貴的計算以確定它是否與在那個廣場內的圓圈[http://en.wikipedia.org/wiki/Inscribed_circle] – timdev 2010-07-28 04:19:25
SELECT 3963 * ACOS(
SIN(RADIANS($pointAlat)) * SIN(RADIANS($pointAlat)) + COS(RADIANS($pointAlat)) * COS(RADIANS($pointBlat)) * COS(RADIANS($pointAlong) - RADIANS($pointBlong)))
AS
distance;
另外,如果您正在尋找在這個良好的讀/教程。檢查這裏 http://www.phpfreaks.com/forums/index.php/topic,208965.0.html
沒用,因爲你不能在WHERE子句中使用別名 - 這將迫使他計算一堆超驗函數兩次。 Ouch。在一個潛在的巨大數據集上。Double Ouch。 – NullUserException 2010-07-28 04:17:44
計算的距離是相當昂貴的計算,如其他人所說。返回大量數據集也不是一個好主意 - 特別考慮到PHP在性能方面並不是那麼好。
我會使用一種啓發式算法,如使用簡單加法和減法來近似距離。
1分鐘=1.86公里= 1.15 英里
只要搜索與事故分貝該範圍(實際上是方形的,而不是一個圓圈)之內,那麼你可以在這些工作與PHP。
編輯:這是一種替代;這個近似的方法計算較不昂貴的:
近似距離以英里爲:以英里
改進的大致距離:
sqrt(x * x + y * y)
where x = 69.1 * (lat2 - lat1)
and y = 53.0 * (lon2 - lon1)
您可以通過添加餘弦運算功能改善這種近似距離計算的準確性:
sqrt(x * x + y * y)
where x = 69.1 * (lat2 - lat1)
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3)
來源:http://www.meridianworlddata.com/Distance-Calculation.asp
編輯2:我跑了一堆隨機生成的數據集的測試。
絕對不值得。只需要近似。
代碼是在這裏:http://pastebin.org/424186
另一個很好的啓發式。使用一分鐘(或其相關細分)可能的最小可能距離,並使用該距離排除明顯超過兩英里遠的任何候選點。當然,你可以變得更聰明,並根據用戶的位置使用各種近似值。 – timdev 2010-07-28 04:23:47
我做了快速搜索,轉向了this blog post它提供了一個很好的解釋和SQL選擇在給定半徑的記錄。
在評論中,他建議「爲了在大型數據集上加快速度,您可能首先需要在原點附近抓住一個方形塊,然後在原點和緯度/經度上加上一英里左右,然後使用上述從中間開始工作的子選擇「對我來說聽起來像是要走的路。
LOL我只是注意到你有的鏈接..是的,這是有效的。 ;) – 2010-07-28 04:09:40