根据给定点的经纬度和特定距离取范围类的数

一、计算两个经纬度的距离

 
根据经纬度计算距离
  • R为地球半径,可取平均值 6371km;
  • φ1, φ2 表示两点的纬度;
  • Δλ 表示两点经度的差值。
        /**   
         * Created by yuliang on 2015/3/20.   
         */    
        public class LocationUtils {    
            private static double EARTH_RADIUS = 6378.137;    
            
            private static double rad(double d) {    
                return d * Math.PI / 180.0;    
            }    
            
            /**   
             * 通过经纬度获取距离(单位:米)   
             * @param lat1   
             * @param lng1   
             * @param lat2   
             * @param lng2   
             * @return   
             */    
            public static double getDistance(double lat1, double lng1, double lat2,    
                                             double lng2) {    
                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 * EARTH_RADIUS;    
                s = Math.round(s * 10000d) / 10000d;    
                s = s*1000;    
                return s;    
            }    
        }    

    二、根据某一经纬度和距离计算附近的经纬度

    • R为地球半径,可取平均值 6371km;
    • φ1, φ2 表示两点的纬度;
    • Δλ 表示两点经度的差值。

    1、计算步骤:

    • 先来求东西两侧的的范围边界。在haversin公式中令φ1 = φ2,可得:
     
    计算公式

    double dlng = 2 * Math.asin(Math.sin(gpsAround.getDistance() / (2 * EARTH_RADIUS)) / Math.cos(gpsAround.getLatitude().doubleValue()));
    // 弧度转换成角度
    dlng = Math.toRadians(dlng);

    • 然后求南北两侧的范围边界,在haversin公式中令 Δλ = 0,可得:
     
    公式
        // 然后求南北两侧的范围边界,在haversin公式中令 Δλ = 0
        double dlat = gpsAround.getDistance() / EARTH_RADIUS;
        // 弧度转换成角度
        dlng = Math.toDegrees(dlat);
    • 确定四个点坐标(即两个经度和两个纬度)
          // 坐标 10
          GPS left_bottom = new ShopAddress().new GPS();
          left_bottom.setLatitude(gpsAround.getLatitude().subtract(new BigDecimal(dlat)));
          left_bottom.setLongitude(gpsAround.getLongitude().subtract(new BigDecimal(dlng)));
      
          // 坐标 01
          GPS right_top = new ShopAddress().new GPS();
          right_top.setLatitude(gpsAround.getLatitude().add(new BigDecimal(dlat)));
          right_top.setLongitude(gpsAround.getLongitude().add(new BigDecimal(dlng)));

      2、用例

      private final static double EARTH_RADIUS = 6371.393;// 地球半径
      
        private static Map<String, GPS> getNearbyGCJ(GPSAround gpsAround) {
          if (null == gpsAround) {
            return null;
          }
      
          // 求东西两侧的的范围边界。在haversin公式中令φ1 = φ2(维度相同),传入的距离为 米,转换为千米
          double dlng = 2 * Math.asin(Math.sin((gpsAround.getDistance() / 1000) / (2 * EARTH_RADIUS))
              / Math.cos(gpsAround.getLatitude().doubleValue() * Math.PI / 180));
          // 弧度转换成角度
          // dlng = Math.toRadians(dlng);
          dlng = Math.toDegrees(dlng);
      
          // 然后求南北两侧的范围边界,在haversin公式中令 Δλ = 0
          double dlat = (gpsAround.getDistance() / 1000) / EARTH_RADIUS;
          // 弧度转换成角度
          dlat = Math.toDegrees(dlat);
      
          // 通过计算可以得到上下左右四个点的经纬度,即,两个经度,两个纬度
          // 坐标 10
          GPS left_bottom = new GPS(
              gpsAround.getLongitude().subtract(new BigDecimal(dlng)).setScale(8,
                  BigDecimal.ROUND_HALF_UP),
              gpsAround.getLatitude().subtract(new BigDecimal(dlat)).setScale(8,
                  BigDecimal.ROUND_HALF_UP));
      
          // 坐标 01
          GPS right_top = new GPS(
              gpsAround.getLongitude().add(new BigDecimal(dlng)).setScale(8, BigDecimal.ROUND_HALF_UP),
              gpsAround.getLatitude().add(new BigDecimal(dlat)).setScale(8, BigDecimal.ROUND_HALF_UP));
      
          Map<String, GPS> gpsMap = new HashMap<>();
          gpsMap.put("top", right_top);
          gpsMap.put("bottom", left_bottom);
      
          return gpsMap;
        }

      三、mysql计算逻辑(性能较差)

      SELECT
          shop_id ,
          shop_name ,
          lng ,
          lat ,
          POWER(lat - 40.05748 , 2) + POWER(lng - 116.30759 , 2) * POWER(COS((lat + 40.05748) / 2) , 2) AS distance
      FROM
          shop_list
      HAVING
          distance < 1000
      ORDER BY
          distance
      LIMIT 100;

      效果展示

       
      效果展示

    作者:慕凌峰
    链接:https://www.jianshu.com/p/ed6ea376911e
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

posted on 2020-12-03 11:10  意扬  阅读(723)  评论(0编辑  收藏  举报

导航