1. 前言

在我们平时使用美团,饿了么等app进行订餐,或者使用猫眼进行订电影票的时候,都有一个距离的排序,表明该家店距离我们当前的位置,这种基于地理位置的服务,统一被称为LBS(Location Based Service),而LBS的实现则是借助于GIS,WC(无线通信)等信息技术来实现。而今天我们所要讨论的就是这个距离的实现。

GIS,Geographic information system,地理信息系统。

  1. 计算方式

由于地球是一个椭圆形,我们在计算的时候有点麻烦,所以我们更常用的方式是将地球作为一个球形来计算,而计算球面上任意两点之间的距离的公式通常有两种:Great-circle distance和Haversine formula,而目前大多数公司都是用的是Haversine公式,原因可以参考:

Great-circle distance公式用到了大量余弦函数, 而两点间距离很短时(比如地球表面上相距几百米的两点),余弦函数会得出0.999…的结果, 会导致较大的舍入误差。而Haversine公式采用了正弦函数,即使距离很小,也能保持足够的有效数字。

而有关这两者的介绍可以参考维基百科:Haversine formula 维基百科,Great-circle distance 维基百科。而最终该公式的形式为:

至于为什么是这种形式,其实目前网上有许多推导公式,感兴趣的可以看一下推导过程,顺便回忆一下自己当年学过的数学知识:
1. 关于已知两点经纬度求球面最短距离的公式推导
2. 根据经纬度计算两点之间的距离的公式推导过程以及google.maps的测距函数

而如果要考虑到高度的影响的话,可以参考:https://stackoverflow.com/questions/3694380/calculating-distance-between-two-points-using-latitude-longitude

另外,还有一种方式是 Vincenty’s formulae,该方式也是用于计算球体表面两点之间距离的方式,而它所基于的就是地球是扁球体的形状,因此这种方式比假设地球是球体的方式应该更加准确,但实现起来比较麻烦。感兴趣的可以查看下维基百科:Vincenty’s formulae 维基百科

接下来说几点概念:

3.1 地球半径

由于地球不是一个完美的球体,所以并不能用一个特别准确的值来表示地球的实际半径,不过由于地球的形状很接近球体,用[6357km] 到 [6378km]的范围值可以涵盖需要的所有半径。并且通常情况下,地球半径有几个常用值:

极半径,从地球中心至南极或北极的距离, 相当于6356.7523km;
赤道半径,从地球中心到赤道的距离,大约6378.137km;
平均半径,6371.393km,表示地球中心到地球表面所有各点距离的平均值;
RE,地球半径,有时被使用作为距离单位, 特别是在天文学和地质学中常用,大概距离是6370.856km;

所以我们通过地球半径进行计算的时候,通常情况下,我们可以使用上面的每一个值都可以进行计算,不过或多或少都会有误差的,但这样的误差是也是允许存在的。这里参考自维基百科:维基百科-地球半径

  1. MySQL实现

同样,在MySQL中实现该功能,计算公式还是通过Haversine公式。不过在Google Map中,已经提供了相应的实现方式,我们先来看一下。

SELECTid,(3959 * acos(cos( radians( 37 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(- 122 ) ) + sin( radians( 37 ) ) * sin( radians( lat ) ) ) ) AS distance
FROMmarkers
HAVINGdistance < 25
ORDER BYdistance LIMIT 0,20;

而如果我们要查询公里,将3959英里也就是地球半径,修改为6371即可。

Google Maps地址:Creating a Store Locator on Google Maps php&MySQL

4.2 st_distance函数

MySQL其实在很早就提供了这种存储经纬度及相关运算的功能,这种数据类型叫做空间数据类型,而对应的索引被称为空间索引,但由于MySQL之前的版本对InnoDB支持的并不是太好,所以使用的并不多。不过MySQL5.6和MySQL5.7对此进行了优化,添加了st_distance等相关函数来支持经纬度相关的计算。

SELECTs.*,( st_distance ( point ( lng, lat ), point (- 122.083235, 37.38714 ) ) * 111195 ) AS distance
FROMmarkers s
ORDER BYdistance

其中,point是MySQL的空间数据类型,先不多说这块。就这样,我们只需要通过st_distance函数就计算出了我们所需要查询的结果,不过这里需要说一下:

st_distance 函数返回的单位是degrees,也就是空间单位的度数,我们如果要将degrees转换为米或者千米的话,需要乘以 EARTH_RADIUS * PI/180, EARTH_RADIUS 也就是地球半径,至于是米还是千米,就看该变量的单位。
该运算其实就相当于对地球半径进行弧度与角度的转换,也就是Math.toRadians,而上面我们写的111195其实是一个有误差的值,该值就是通过该计算得出的结果。

其实,MySQL有提供直接查询结果是米的函数:st_distance_sphere,并且该函数的计算结果要比st_distance转换为米的结果更精确。不过该函数是MySQL5.7之后才引入的,5.7之前还是需要通过计算转换成米。更多可参考官方文档地址:MySQL 5.7 ST_Distance_Sphere(g1, g2 [, radius])

5 Geohash算法

Geohash是目前比较主流的范围搜索的算法,比如说搜索附近500米内的地点这种问题。Geohash算法将二维的经纬度编码为一个字符串,每个字符串代表了某一矩形区域,也就是说,这个矩形区域内所有的点(经纬度坐标)都共享相同的GeoHash字符串,这样在查询的时候就可以对该字符串做索引,然后根据该字符串进行过滤。

Geohash算法的最大用途其实就是附近地址搜索了,不过,从geohash的编码算法中可以看出它的一个缺点,也就是边界问题:虽然两个地点距离很近,但恰好位于分界点的两侧,这样geohash字符串就会不相同,然后匹配的时候就会有问题。不过要解决这个问题也很简单,就是计算的时候,计算出8个分别分布在周围8个区域的地点。

原文

根据经纬度计算两点之间的距离相关推荐

  1. php 如何根据经纬度计算距离,小程序实例:如何根据经纬度计算两点之间的距离(代码)...

    本篇文章给大家带来的内容是关于小程序实例:如何根据经纬度计算两点之间的距离(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助.//计算两点位置距离 getDistance: fun ...

  2. Java根据经纬度计算两点之间的距离

    1. 前言   在我们平时使用美团,饿了么等app进行订餐,或者使用猫眼进行订电影票的时候,都有一个距离的排序,表明该家店距离我们当前的位置,这种基于地理位置的服务,统一被称为LBS(Location ...

  3. 根据经纬度计算两点之间的距离(单位米)

    package com.xiao.map;// 算法工程师!! public class MapUtils {private static double rad(double d) {return d ...

  4. 地理大圆距离 C语言,通过经纬度计算两点之间的距离

    2019独角兽企业重金招聘Python工程师标准>>> 项目里有一个需求是计算两台机器之间的距离,有了这两台机器的经纬度,距离就很好计算了. 有一个 球面余弦定律 可以用来可以计算球 ...

  5. 通过经纬度计算两点之间的距离的公式

    通过经纬度计算两点之间距离的常用公式如下: 设点 A 的纬度为 $lat_A$,经度为 $lon_A$,点 B 的纬度为 $lat_B$,经度为 $lon_B$,则两点之间的距离 $d$ 为: $d ...

  6. php根据经纬度计算两点之间的距离

    之前我们已经说过了如何根据IP获取当前用户的经纬度,不会获取的小童鞋可以去看一下之前的文章. 这回我们将功能再延伸一下,根据将纬度计算两点之间的距离. 废话不多说,直接上码: function get ...

  7. 根据经纬度计算两点之间的距离、点到直线的距离

    以下内容适合初学者,我用来评估跑路径跟踪结果的代码. 简单的看了其他人的博客,基本都是用半正矢公式(Haversine formula)计算距离的. 其中,a=lat1-lat2(经度差);b=lon ...

  8. 根据经纬度计算两点之间的距离的公式

    //距离单位 米 public static double algorithm(double longitude1, double latitude1, double longitude2, doub ...

  9. MySQL中利用经纬度计算两点之间的距离

    MySQL中利用st_distance 函数计算经纬度距离 方法一: 精确到0.000000米 例: 经度:lon1,lon2 纬度:lat1 , lat2 SELECT st_distance(PO ...

  10. 根据经纬度计算两点之间的距离---google计算公式推导

    经纬度常用词   经度 longitude, 维度 latitude 图和解读来源网上资料,自我也进行一遍推导,有些地方会加入自己的一些理解,重新温故了之前学的三角函数,度,弧度,弧长的概念,记忆模糊 ...

最新文章

  1. python批量改名_Python写个批量改名工具
  2. 当对象与原型有相同的属性,调用时的上下文指向问题
  3. DirectX 向量点乘和叉乘
  4. 冒泡排序和其两种优化
  5. 成员函数和友元函数实现一元运算符重载
  6. 1040 Longest Symmetric String (25 分)_15行代码AC
  7. Linux平台 Oracle 18c RAC安装Part3:DB配置
  8. redis的使用场景和基本数据类型
  9. linux系统软件包依赖关系,Ubuntu解决包依赖关系
  10. 致远OA ajaxAction formulaManager 文件上传漏洞
  11. java学生奖学金管理系统_java毕业设计_springboot框架的高校学生奖学金评定系统...
  12. N-Queen(java实现)
  13. Idea搭建web服务器
  14. nyoj-506-洗澡
  15. 牛客网赛码网 输入输出格式 pythonC++
  16. linux 进程hang,GoldenGate Extract进程hang问题解决一例
  17. 肾功能及早期肾损伤的检查题库【1】
  18. 2019中科院力学所研究生学术论坛随笔
  19. waymo数据集总结
  20. 从三星 Note 7 电池事故引发的锂电池安全问题探讨 | 硬创公开课

热门文章

  1. [转载]关于CIPS不得不知道的14个要点
  2. libmodbus在ARM linux开发板上使用
  3. 中华人民共和国网络安全法
  4. 记账APP华而不实?Excel门槛太高?不如用它在线记账!
  5. 『2022/2/5』Android Studio下载安装详细步骤(Android Studio BumbleBee/2021.1.1.21 Patch 1 )
  6. (最新)Win7安装配置IIS7.5详细图文教程 (一)
  7. 逻辑门图解(NOT门 AND门 OR门 XOR门)
  8. python---字符串的拼接、去重、反转、字母花样排序、单词出现判断、统计文件特定单词频率lambda、硬盘容量、列表转字符串
  9. 《职场动物进化手册》笔记整理
  10. LINUX下载安装CUDA