暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

经纬度科普!MySQL和编程语言是如何计算两个坐标之间的距离的?

小雨青年 2022-09-06
1267

一、经纬度的科普

什么是经纬度呢?其实各位上学的时候地理课上都学过,作为本文中基础中的基础,有必要普及一下。

地理坐标系一般是指由经度、纬度和相对高度组成的坐标系,能够标示地球上的任何一个位置。经度和纬度常合称为经纬度,把球面上的经纬度显示在平面地图上需要采用某种地图投影。


经度、纬度能够标记地球上的位置。


经纬度以度数表示,一般可直接以小数点表示,但亦可把度数的小数点分为角分(1角分等于六十分之一度),和秒(一秒等于六十分之一分)。


1.度分秒表示(度:分:秒)-49°30'00"-49d30m00s

2.度分表示(度:分)-49°30.0'-49d30.0m

3.度数表示-49.5000°-49.5000d(一般会有四位小数)。


经度范围是0-180°,纬度范围是0-90°。




二、目前各大地图平台的经纬度标注方式

1. 百度地图

百度地图的页面不支持查看经纬度坐标,你需要到百度地图开放平台找打拾取坐标工具,地址是 https://api.map.baidu.com/lbsapi/getpoint/index.html ,可以在地图选点,找到经纬度。

下图所示,我在地图上找到的点的作为116.415979,39.888558



百度地图的坐标是经度在前纬度在后的方式。


2. 高德地图

高德地图同样也需要在开放平台找到坐标拾取器,可以查看具体位置的坐标,地址是https://lbs.amap.com/tools/picker , 比如我还是在天坛公园内随便找了一个点,坐标为116.410829,39.881913


百度地图和高德地图都是保留了小数点后6位



3. 谷歌地图

谷歌地图在位置上点击,就能显示位置的坐标,下图的坐标为39.883966, 116.414634.


和上面两个不同的是,谷歌地图的坐标为纬度在前经度在后,需要你在实际项目开发中注意。





三、坐标体系

1. 目前的坐标体系有哪些


WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系。

GCJ02:又称火星坐标系,是由中国国家测绘局制定的地理坐标系统,是由WGS84加密后得到的坐标系。

BD09:为百度坐标系,在GCJ02坐标系基础上再次加密。其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标。


2. 各大地图平台使用的是哪种坐标体系

百度地图——BD09

高德地图——GCJ02

谷歌地图——GCJ02


目前百度地图提供了非百度坐标系转换为百度坐标系的API,文档地址是 https://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition


注意的是,根据相关法律规定,不支持将任何一种坐标系坐标转换为GPS标准坐标。


我们从接下来要讲的的距离测算方法来看,不同的坐标体系内测量距离的方式是一样的,坐标体系更多的意义是在于对于真实坐标系的隐藏而不影响日常大众对于位置服务的使用。


三、两个坐标之间的距离计算

目前市面上计算两点之间距离的基本都是基于余弦球面定律,该定律使用三角函数来测量地球的曲率,以准确测量地球上的距离。

1. geodatasource

这个网站提供了全世界各个城市的经纬度信息,他自带了距离计算器,地址是 https://www.geodatasource.com/demo ,并且提供各种语言的距离计算函数。你在网上搜索到的各种文章,也基本都是这个源码。


function distance($lat1, $lon1, $lat2, $lon2, $unit) {
  if (($lat1 == $lat2) && ($lon1 == $lon2)) {
    return 0;
  }
  else {
    $theta = $lon1 - $lon2;
    $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
    $dist = acos($dist);
    $dist = rad2deg($dist);
    $miles = $dist * 60 * 1.1515;
    $unit = strtoupper($unit);

    if ($unit == "K") {
      return ($miles * 1.609344);
    } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
      return $miles;
    }
  }
}

echo distance(32.9697, -96.80322, 29.46786, -98.53506, "M") . " Miles
"
;
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "K") . " Kilometers
"
;
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "N") . " Nautical Miles
"
;

其他语言参考 https://www.geodatasource.com/resources/categories/technical/

2. MYSQL

MySQL的5.7版本内建了函数,可以计算距离。文档地址是 https://dev.mysql.com/doc/refman/5.7/en/spatial-convenience-functions.html#function_st-distance-sphere

SELECT ST_Distance_Sphere(ST_GeomFromText('POINT(116.41294 39.883374)'), ST_GeomFromText('POINT(116.413085 39.882777)')) as d_distance;

如下图所示,返回的距离单位是米。



四、总结

在实际项目中,要统一使用的地图API,尽量不要多种地图一起使用,不同的坐标体系在地图上标记位置会不准确。




文章转载自小雨青年,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论