LBS 球面距離公式
http://wiki.myoa.info/zh-blog:20
Java,Mysql-根據一個給定經緯度的點,進行附近500米地點查詢–合理利用算法
最近做一個項目:需要查詢一個站點(已知該站點經緯度)500米范圍內的其它站點。所以,我首先想到的是,對每條記錄,去進行遍歷,跟數據庫中的每一個點進行距離計算,當距離小於500米時,認為匹配。這樣做確實能夠得到結果,但是效率極其低下,因為每條記錄都要去循環匹配n條數據,其消耗的時間可想而知。
於是我就想到一個先過濾出大概的經緯度范圍再進行計算。比方說正方形的四個點,於是我在網上搜索,意外的,查詢到了一個關於這個計算附近地點搜索初探,里面使用python實現了這個想法。所以參考了一下原文中的算法,使用JAVA進行了實現。
實現原理也是很相似的,先算出該點周圍的矩形的四個點,然后使用經緯度去直接匹配數據庫中的記錄。
思路:首先算出“給定坐標附近500米”這個范圍的坐標范圍。 雖然它是個圓,但我們可以先求出該圓的外接正方形,然后拿正方形的經緯度范圍去搜索數據庫。
先來求東西兩側的的范圍邊界。在haversin公式中令φ1 = φ2,可得
然后求南北兩側的范圍邊界,在haversin公式中令 Δλ = 0,可得
⊿φ = d/R
用Java代碼寫就是
/先計算查詢點的經緯度范圍<span style="font-family: 微軟雅黑, Helvetica, Times, Arial, serif;">lat已知緯度,lng已知經度</span>
double R = 6371.137;//R為地球半徑,可取平均值 6371.137km
double dis = 0.5;//距離 0.5千米
double dlng = 2*Math.asin(Math.sin(dis/(2*R))/Math.cos(lat*Math.PI/180)); //⊿λ東西兩側的的范圍邊界
dlng = dlng*180/Math.PI;//角度轉為弧度
double dlat = dis/R; //⊿φ南北兩側的范圍邊界
dlat = dlat*180/Math.PI;
最后,就可以得出四個點的坐標:
left-top : (lat + dlat, lng – dlng)
right-top : (lat + dlat, lng + dlng)
left-bottom : (lat – dlat, lng – dlng)
right-bottom: (lat – dlat, lng + dlng)
綜合也就是這樣進行篩選查詢
public List<Property> findNeighPosition(double longitude,double latitude){
//先計算查詢點的經緯度范圍
double r = 6371;//地球半徑千米
double dis = 0.5;//0.5千米距離
double dlng = 2*Math.asin(Math.sin(dis/(2*r))/Math.cos(latitude*Math.PI/180));
dlng = dlng*180/Math.PI;//角度轉為弧度
double dlat = dis/r;
dlat = dlat*180/Math.PI;
double minlat =latitude-dlat;
double maxlat = latitude+dlat;
double minlng = longitude -dlng;
double maxlng = longitude + dlng;
String hql = "from Property where longitude>=? and longitude =<? and latitude>=? latitude=<? and state=0";
Object[] values = {minlng,maxlng,minlat,maxlat};
List<Property> list = find(hql, values);
return list;
}