给定经纬度,计算附近多少公里范围内的地点

场景:当时我们项目用的是spring-data-jpa, 用hql实现的话,实在是不知道怎么搞,所以想出这么个方法。这样做的就是避免直接在数据查询语句中去计算该点附近多少公里范围内的点,将sql语句的实现转成了代码实现。

第一步:根据给定某点经纬度,给定距离数,计算出该点附近相应距离范围的所有的点

   /**
     * 查找附近的门店
     * @param    longitude 经度
     * @param    latitude 纬度
     * @param    distince 距离 (千米)
     * @return   List 符合距离范围的所有的点
     * @Data     2018.10.26
     */
    public List<PickStoreOfflineModel> findNearbyStore(BigDecimal longitude, BigDecimal latitude, Integer distince) {
        String[] split = getNearbyByLongitudeAndLatitudeAndDistince(longitude, latitude, distince).split("-");
        BigDecimal minlng = new BigDecimal(split[0]);
        BigDecimal maxlng = new BigDecimal(split[1]);
        BigDecimal minlat = new BigDecimal(split[2]);
        BigDecimal maxlat = new BigDecimal(split[3]);
        return pickStoreOfflineDao.findNearbyStore(minlng, maxlng, minlat, maxlat);
    }


   /**
     *
     * @Description   计算给定经纬度附近相应公里数的经纬度范围
     * @param         longitude 经度
     * @param         latitude 纬度
     * @param         distince 距离(千米)
     * @return        String 格式:经度最小值-经度最大值-纬度最小值-纬度最大值
     * @Data          2018.10.26
     **/
    public static String getNearbyByLongitudeAndLatitudeAndDistince(BigDecimal longitude, BigDecimal latitude, Integer distince) {
        double r = 6371.393;    // 地球半径千米
        double lng = longitude.longValue();
        double lat = latitude.longValue();
        double dlng = 2 * Math.asin(Math.sin(distince / (2 * r)) / Math.cos(lat * Math.PI / 180));
        dlng = dlng * 180 / Math.PI;// 角度转为弧度
        double dlat = distince / r;
        dlat = dlat * 180 / Math.PI;
        double minlat = lat - dlat;
        double maxlat = lat + dlat;
        double minlng = lng - dlng;
        double maxlng = lng + dlng;

        return minlng + "-" + maxlng + "-" + minlat + "-" + maxlat;
    }

第二步:根据第一步查出来的所有点,依次取出其经纬度和给定地点的经纬度计算距离,并存储到实体类(该距离字段表中不存),只是起一个中间计算的作用。

最后利用Collectionss.sort()方法排序,根据距离排。

   /**
     * @Description  计算距离远近并按照距离排序
     * @param        longitude 经度
     * @param        latitude 纬度
     * @param        nearbyStoreList  附近门店
     * @return       按照距离由近到远排序之后List
     */
    public List<PickStoreOfflineDto> getNearbyStoreByDistinceAsc(BigDecimal longitude, BigDecimal latitude, List<PickStoreOfflineModel> nearbyStoreList) {
        List<PickStoreOfflineDto> list = new ArrayList<>();
        nearbyStoreList.forEach(pickStoreOfflineModel -> {
            PickStoreOfflineDto pickStoreOfflineDto = new PickStoreOfflineDto();
            BeanUtils.copyProperties(pickStoreOfflineModel, pickStoreOfflineDto);
            Double distince = getDistince(longitude, latitude,
                    pickStoreOfflineModel.getLongitude(), pickStoreOfflineModel.getLatitude());
            pickStoreOfflineDto.setDistince(distince.longValue());
            list.add(pickStoreOfflineDto);
        });
        Collections.sort(list, Comparator.comparing(PickStoreOfflineDto::getDistince));
        return list;
    }



     /**
     * @Description     根据经纬度获取两点之间的距离
     * @param           longitude1   地点1经度
     * @param           latitude1    地点1纬度
     * @param           longitude2   地点2经度
     * @param           latitude2    地点2纬度
     * @return          距离:单位 米
     */
    public static Double getDistince(BigDecimal longitude1, BigDecimal latitude1, BigDecimal longitude2, BigDecimal latitude2) {
        double r = 6371.393;         // 地球半径千米
        double lat1 = latitude1.doubleValue();
        double lng1 = longitude1.doubleValue();
        double lat2 = latitude2.doubleValue();
        double lng2 = longitude2.doubleValue();
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
                Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
        s = s * r;
        s = Math.round(s * 1000);
        return s;
    }

    private static Double rad(double d) {
        return d * Math.PI / 180.0;
    }

好了   就是这样子,反正我是实现了,老大也认可了。o(╥﹏╥)o

有用的到的小伙伴可以参考下,也可以留言交流下。

猜你喜欢

转载自blog.csdn.net/pavel101/article/details/83585431