获取距离某坐标附近一定范围内的点的两种方式

   日期:2020-08-07     浏览:235    评论:0    
核心提示:获取距离某坐标附近一定范围内的点的两种方式场景:数据库中有一些点坐标,需要查找出距离当前位置2千米范围内的坐标方式1:根据两个经纬度计算距离,Oracle/MySql计算地表两点之间的距离:Oracle:创建获取弧度的函数:CREATE OR REPLACE FUNCTION RAD(d number) RETURN NUMBERisPI number :=3.141592625;beginreturn d* PI/180.0;end ;创建根据两个坐标计算距离的函数CR_获取当前坐标某一范围

获取距离某坐标附近一定范围内的点的两种方式

场景:数据库中有一些点坐标,需要查找出距离当前位置2千米范围内的坐标

方式1:根据两个经纬度计算距离,Oracle/MySql计算地表两点之间的距离:

Oracle:

  • 创建获取弧度的函数:
CREATE OR REPLACe FUNCTION RAD(d number) RETURN NUMBER
is
PI number :=3.141592625;
begin
return  d* PI/180.0;
end ;
  • 创建根据两个坐标计算距离的函数
CREATE OR REPLACE FUNCTION GetDistance(LngBegin number,
                                        LatBegin number,
                                        LngEnd number,
                                        LatEnd number) RETURN NUMBER is
  earth_padius number := 6378.137;
  radLat1      number := rad(LngBegin);
  radLat2      number := rad(LngEnd);
  a            number := radLat1 - radLat2;
  b            number := rad(LatBegin) - rad(LatEnd);
  s            number := 0;
begin
  s := 2 *
       Asin(Sqrt(power(sin(a / 2), 2) +
                 cos(radLat1) * cos(radLat2) * power(sin(b / 2), 2)));
  s := s * earth_padius;
  s := Round(s * 10000)/10;
  return s;
end;
  • 查询距离
SELECT
   GetDistance(#{lon},#{lat},SHOP_LON,SHOP_LAT) AS Mdistance 
FROM Shop

MySql:
查询距离sql:

SELECt
	ROUND( 6378.138 * 2 * ASIN( SQRT( POW( SIN(( #{lat} * PI() / 180 - SHOP_LAT * PI() / 180) / 2 ),
         2 ) + COS(#{lat} * PI() / 180) * COS(SHOP_LAT * PI() / 180) * POW( SIN( ( #{lon} * PI() / 180 - SHOP_LON * PI() / 180 ) / 2 ),
         2 ) ) ) * 1000 ) AS Mdistance
FROM Shop

当然,也可将计算方法封装为函数

拿到距离后根据条件取值,因为是sql查询,若数据量大时,效率是一个问题

方式2:根据经纬度和距离计算出矩形范围,取范围内的值:

  • 提供工具类如下:
public class GeoUtil
{
    
    private static double EARTH_RADIUS = 6378.137;
    
    
    public static double[] getRectangle(double lng, double lat, long distance)
    {
        float delta = 111000;
        if (lng != 0 && lat != 0)
        {
            double lng1 = lng - distance / Math.abs(Math.cos(Math.toRadians(lat)) * delta);
            double lng2 = lng + distance / Math.abs(Math.cos(Math.toRadians(lat)) * delta);
            double lat1 = lat - (distance / delta);
            double lat2 = lat + (distance / delta);
            return new double[] {lng1, lat1, lng2, lat2};
        }
        else
        {
            double lng1 = lng - distance / delta;
            double lng2 = lng + distance / delta;
            double lat1 = lat - (distance / delta);
            double lat2 = lat + (distance / delta);
            return new double[] {lng1, lat1, lng2, lat2};
        }
    }
    
    
    public static double getDistanceOfMeter(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 * 10000) / 10;
        return s;
    }
    
    private static double rad(double d)
    {
        return d * Math.PI / 180.0;
    }
}

这种方式得到的是一个范围,查询时无需计算根据大小即可取出范围内的点,但是就没有具体的距离值了。在数据量大时效率较高。同时比较符合app的某些业务场景,例如每次展示手机屏幕范围内的点(手机是方的)

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服