有朋友遇到這樣一個問題,本身數據庫裏面有一些商家,須要根據用戶提交的地理位置找出必定範圍內的商家來返回個用戶。解決這個問題有兩種思路。php
第一種思路,從數據庫提取出商家的經緯度,而後計算和用戶經緯度間的距離,留下在距離範圍內地。git
這種方法貌似很科學,不過數據量稍微大一點就完蛋了。這裏涉及到的是計算兩個經緯度間的距離,方法的代碼以下:算法
/** * [getdistance3 description] * @param $lng1 [經度1] * @param $lat1 [緯度1] * @param $lng2 [經度2] * @param $lat2 [緯度2] * @return $distance [距離(米)] */ function getdistance3($lng1, $lat1, $lng2, $lat2){ $radLat1 = deg2rad($lat1); $radLat2 = deg2rad($lat2); $radLng1 = deg2rad($lng1); $radLng2 = deg2rad($lng2); $a = $radLat1 - $radLat2; $b = $radLng1 - $radLng2; $distance = 2*asin(sqrt(pow(sin($a/2),2)+cos($radLat1)*cos($radLat2)*pow(sin($b/2),2)))*6378137; return $distance; }
這個算法的公式是Google map用的,6378137(m)是地球半徑,若是以爲其餘值更合適能夠改。還有另一個公式,寫成代碼替換上面的$distance是這樣:數據庫
$distance = acos(sin($radLat1)*sin($radLat2)+cos($radLat1)*cos($radLat2)*cos($b))*637813;
經過三角恆等變換能夠知道兩者是恆等的。ide
這個方法用來算兩點距離是沒問題,不過要用來解決上面的給出特定範圍內商家的問題不現實。ip
第二種思路,經過給出的點A的經緯度座標和一個肯定的單位距離,先算出距A單位距離的經緯度範圍,再經過這個範圍爲條件從數據庫獲取知足條件的商家數據。get
程序代碼以下:it
/** * [getRange description] * @param $lng [經度] * @param $lat [緯度] * @param $raidus [半徑(米)] * @return [array] $range [經緯度範圍] */ function getRange($lng, $lat, $raidus){ $PI = 3.14159265; $latitude = $lat; $longitude = $lng; $degree = 40075016/360; $raidusMetre = $raidus; $radiusLat = $raidusMetre / $degree; $minLat = $latitude - $radiusLat; $maxLat = $latitude + $radiusLat; $mpdLng = $degree * cos($latitude * ($PI/180)); $radiusLng = $raidusMetre / $mpdLng; $minLng = $longitude - $radiusLng; $maxLng = $longitude + $radiusLng; $range = array('minLng' => $minLng, 'maxLng' => $maxLng, 'minLat' => $minLat, 'maxLat' => $maxLat); return $range; }
這裏40075016(m)是地球周長,若是以爲其餘值更合適也能夠改。經過這個方法,得出了距給出的點($lng, $lat)5000米之內的座標範圍:經度[$minLng, $maxLng],緯度[$minLat, $maxLat],原本想要的是一個半徑爲5000米的圓形範圍,如今得出的是一個正方形範圍,做爲近似使用應該能夠了。
接下來就只用到數據庫篩選出經緯度在這個範圍的商家出來,按照須要的數據格式返回給用戶了。若是給定的半徑範圍內沒有找到商家,能夠擴大半徑來搜出商家。
到此算是給出這個問題一個近似解決了,先暫時給他用着。io