實現思路:先定義PI和R地球半徑
准備階段:
public class CoordinateConversionUtils { private static final double PI = 3.14159265358979323; private static final double R = 6371229; /** * 計算兩點距離 * @param latLonReq1 * @param latLonReq2 * @return */ public static double getDistance(LatLonReq latLonReq1, LatLonReq latLonReq2) { GlobalCoordinates source = new GlobalCoordinates(latLonReq1.getLatitude(), latLonReq1.getLongitude()); GlobalCoordinates target = new GlobalCoordinates(latLonReq2.getLatitude(), latLonReq2.getLongitude()); return new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target).getEllipsoidalDistance(); } }
計算兩點的距離,這里使用了geodesy-1.1.3.jar這個jar庫,需要的話,可以直接前往maven官網搜索添加對應的pom依賴。此插件的誤差在0.1米內
我使用的百度坐標,百度坐標系 (BD-09) ,根據官網javascript的api進行測試,誤差在0.1米內
1.根據緯度,先算出1緯度的距離,不同經度下的1緯度的距離都是相等的
double oneLatitudeDistance = PI * R / 180;
2.根據經度,先算出1經度的距離,這里先把緯度固定,然后再加上1經度,算出不同緯度下的1經度距離是多少米
double latitude = latLon.getLatitude();//緯度 double longitude = latLon.getLongitude();//經度 double longitudeEnd = longitude + 1.0;//經度+1 double oneLongitudeDistance = getDistance(latLon, new LatLonReq(latitude, longitudeEnd));//經度加1后,計算當前緯度下的1經度的距離
3.根據1緯度和1經度的距離,反推距離內,經度和緯度的最大值和最小值
/** * latitude范圍 * @param latLon * @param range * @return */ public static double[] getLatitudeRange(LatLonReq latLon, double range){ double[] latitudeRange = {0.0,0.0}; double oneLatitudeDistance = PI * R / 180; double latitude = latLon.getLatitude(); double calculateLatitude = range / oneLatitudeDistance; latitudeRange[0] = latitude - calculateLatitude; latitudeRange[1] = latitude + calculateLatitude; return latitudeRange; } /** * longitude范圍 * @param latLon * @param range * @return */ public static double[] getLongitudeRange(LatLonReq latLon, double range){ double[] longitudeRange = {0.0,0.0}; double latitude = latLon.getLatitude(); double longitude = latLon.getLongitude(); double longitudeEnd = longitude + 1.0; double oneLongitudeDistance = getDistance(latLon, new LatLonReq(latitude, longitudeEnd)); double calculateLongitude = range / oneLongitudeDistance; longitudeRange[0] = longitude - calculateLongitude; longitudeRange[1] = longitude + calculateLongitude; return longitudeRange; }
4.根據上面的三個步驟,可推算出經緯度內的距離內的最大經度和緯度的范圍,然后根據經緯度的范圍可以形成一個類似正方形的經緯度范圍
數據庫存儲了多個點的坐標,我們需要查找某個點,范圍內的其他點,此處可以直接通過sql進行查詢
SELECT qlp.cgi,qlp.lonc,qlp.latc FROM qj_lte_param qlp WHERE cast(qlp.lonc as decimal(9,6) ) BETWEEN #{minLon} AND #{maxLon} AND cast(qlp.latc as decimal(9,6)) BETWEEN #{minLat} AND #{maxLat} AND qlp.project_id = #{projectId}
具體代碼步驟:先算出對應的經緯度范圍,然后使用sql查詢范圍內的其他點
double[] latitudeRange = CoordinateConversionUtils.getLatitudeRangeByLatLon(latc, lonc, lteRange); double[] longitudeRange = CoordinateConversionUtils.getLongitudeRangeByLatLon(latc, lonc, lteRange); List<QjLteParam> plots = qjLteParamMapper.searchPlot(longitudeRange[0], longitudeRange[1], latitudeRange[0], latitudeRange[1], projectId);
如果還需要計算距離的話,再使用getDistance方法,計算即可算出兩點的距離
double distance = CoordinateConversionUtils.getDistance(new LatLonReq(Double.parseDouble(plot.getLatc()), Double.parseDouble(plot.getLonc())), new LatLonReq(Double.parseDouble(latc), Double.parseDouble(lonc)));