您的位置:首页 > 数据库

SQL计算GIS两点的距离

2014-06-03 13:01 465 查看

最近创业的一个产品要用到计算两个GIS点的距离,搜了下网上,关于这个的还真少。高中时读的X科是地理,结合了一下解释几何,收集了如下解决方案。

 一、代码实现(oracle)

Create Or Replace Function get_earth_distance(lon1 Number,
                                              lat1 Number,
                                              lon2 Number,
                                              lat2 Number) Return Number As
  rad_lon1     Number(12, 8);
  rad_lat1     Number(12, 8);
  rad_lon2     Number(12, 8);
  rad_lat2     Number(12, 8);
  a            Number(12, 8);
  b            Number(12, 8);
  pi           Number := 3.14159265;
  s            Number(20, 8);
  EARTH_RADIUS Number := 6378.137;
Begin
  rad_lat1 := lat1 * pi / 180.0;
  rad_lat2 := lat2 * pi / 180.0;
  rad_lon1 := lon1 * pi / 180.0;
  rad_lon2 := lon2 * pi / 180.0;
  a        := rad_lat1 - rad_lat2;
  b        := rad_lon1 - rad_lon2;
  s        := 2 * asin(sqrt(power(sin(a / 2), 2)
                            cos(rad_lat1) * cos(rad_lat2) *
                            power(sin(b / 2), 2)));
  s        := s * EARTH_RADIUS;
  s        := round(s * 100000) / 100000;
  s        := s * 1000;
  Return s;
End get_earth_distance;

计算精度与谷歌地图的距离精度差不多,相差范围在0.2米以下。

二、关于经纬度十进制表示法

对于两个点,在纬度相等的情况下:

经度每隔0.00001度,距离相差约1米;每隔0.0001度,距离相差约10米;每隔0.001度,距离相差约100米;每隔0.01度,距离相差约1000米;每隔0.1度,距离相差约10000米。

对于两个点,在经度相等的情况下:

纬度每隔0.00001度,距离相差约1.1米;每隔0.0001度,距离相差约11米;每隔0.001度,距离相差约111米;每隔0.01度,距离相差约1113米;每隔0.1度,距离相差约11132米

方便的改成sql语句

假设计算118.041 36.793与数据库内坐标点的距离

mysql> select 6378137*2*asin(Sqrt(power(sin((36.793-domlat)*pi()/360),2)  + Cos(36.793*pi()/180)*Cos(domlat*pi()/180)*power(sin((118.041-domlon)*pi()/360),2))) as distance,domip from dominfo order by distance;

精简一下啊

select 12756274*asin(Sqrt(power(sin((36.793-domlat)*0.008726646),2) + Cos(36.793*0.0174533)*Cos(domlat*0.0174533)*power(sin((118.041-domlon)*0.008726646),2)))
4000
as distance,domip from dominfo order by distance;

三、Java算法

  public static double geographicDistance(double lng1, double lat1, double lng2, double lat2) {
        double dLat = Math.toRadians(lat2 - lat1); 
        double dLng = Math.toRadians(lng2 - lng1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                            Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                            Math.sin(dLng / 2) * Math.sin(dLng / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = EARTH_RADIUS * c;
        return new BigDecimal(distance).intValue();
    } 
 

地理知识我就不再说了,可以翻高中的课本,呵呵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息