实现思路:先定义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)));