參考wiki百科上的一些球面計算公式:
Great-circle distanceHaversine formula假設已知點的經緯度分別為$lng, $lat先實現經度范圍的查詢,在haversin公式中令φ1 = φ2,可得:
用PHP進行計算,就是:
//$lat 已知點的緯度$dlng = 2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));$dlng = rad2deg($dlng);//轉換弧度然后是緯度范圍的查詢,在haversin公式中令 Δλ = 0,可得在PHP中進行計算,就是:
$dlat = $distance/EARTH_RADIUS;//EARTH_RADIUS地球半徑$dlat = rad2deg($dlat);//轉換弧度最后,就可以得出四個點的坐標:left-top : (lat + dlat, lng – dlng)right-top : (lat + dlat, lng + dlng)left-bottom : (lat – dlat, lng – dlng)right-bottom: (lat – dlat, lng + dlng)我把以上方法寫成了一個函數,綜合起來就是:define(EARTH_RADIUS, 6371);//地球半徑,平均半徑為6371km /** *計算某個經緯度的周圍某段距離的正方形的四個點 * *@param lng float 經度 *@param lat float 緯度 *@param distance float 該點所在圓的半徑,該圓與此正方形內切,默認值為0.5千米 *@return array 正方形的四個點的經緯度坐標 */ function returnSquarePoint($lng, $lat,$distance = 0.5){ $dlng = 2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat))); $dlng = rad2deg($dlng); $dlat = $distance/EARTH_RADIUS; $dlat = rad2deg($dlat); return array( 'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng), 'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng), 'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng), 'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng) ); }//使用此函數計算得到結果后,帶入sql查詢。$squares = returnSquarePoint($lng, $lat);$info_sql = "select id,locateinfo,lat,lng from `lbs_info` where lat<>0 and lat>{$squares['right-bottom']['lat']} and lat<{$squares['left-top']['lat']} and lng>{$squares['left-top']['lng']} and lng<{$squares['right-bottom']['lng']} "; 在lat和lng上建立一個聯合索引后,使用此項查詢,每條記錄的查詢消耗平均為0.8毫秒,相比以前的1700ms,真的是天壤之別啊。效率真真的是以前的2125倍~~總結:這應該也不是效率最好的辦法,但是效率比以前確實有明顯的提升。請記住,總有辦法更好的。
新聞熱點
疑難解答
圖片精選