MySQL以及Java根据经纬度计算距离

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL以及Java根据经纬度计算距离

球面距离公式

球面距离计算公式.jpeg

球面距离公式是计算球面上两点间距离的公式。

举个例子:已知,设R为球体半径,点A ,纬度角β1 ,经度角α1 ;点B ,纬度角β2 ,经度角α2。求点A和点B两点间的距离?

公式:S=R·arccos[cosβ1·cosβ·2cos(α1-α2)+sinβ1·sinβ2]

公式参考:球面距离公式

地球半径

地球半径:6371.393千米。

计算坐标点

广州塔,经纬度:113.324553,23.106414

东方明珠电视塔,经纬度:121.499718,31.239703

关于在线经纬度获取的话,可以看看高德地图的:https://lbs.amap.com/tools/picker

Java版本

/**
 * 根据球面距离公式计算两个地点之间的距离
 *
 * <p>公式:S=R·arccos[cosβ1·cosβ·2cos(α1-α2)+sinβ1·sinβ2]
 */
@UtilityClass
public class DistanceUtil {

  /** 地球半径(单位:米) */
  private static final double EARTH_RADIUS = 6371393;

  /** 以度为单位的角度值乘以该常数以获得以弧度为单位的角度值。 */
  private static final double DEGREES_TO_RADIANS = 0.017453292519943295;

  /**
   * 根据公式进行计算
   *
   * @param longitude1 位置1经度
   * @param latitude1 位置1纬度
   * @param longitude2 位置2经度
   * @param latitude2 位置2纬度
   * @return 返回计算的距离,单位:米
   */
  public static double getDistance(
      Double longitude1, Double latitude1, Double longitude2, Double latitude2) {
    double radiansLongitude1 = toRadians(longitude1);
    double radiansLatitude1 = toRadians(latitude1);
    double radiansLongitude2 = toRadians(longitude2);
    double radiansLatitude2 = Math.toRadians(latitude2);

    final double cos =
        BigDecimal.valueOf(Math.cos(radiansLatitude1))
            .multiply(BigDecimal.valueOf(Math.cos(radiansLatitude2)))
            .multiply(
                BigDecimal.valueOf(
                    Math.cos(
                        BigDecimal.valueOf(radiansLongitude1)
                            .subtract(BigDecimal.valueOf(radiansLongitude2))
                            .doubleValue())))
            .add(
                BigDecimal.valueOf(Math.sin(radiansLatitude1))
                    .multiply(BigDecimal.valueOf(Math.sin(radiansLatitude2))))
            .doubleValue();

    double acos = Math.acos(cos);
    return BigDecimal.valueOf(EARTH_RADIUS).multiply(BigDecimal.valueOf(acos)).doubleValue();
  }

  /**
   * 参考:{@link Math#toRadians(double)}
   *
   * @param value value
   * @return {double}
   */
  private static double toRadians(double value) {
    return BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(DEGREES_TO_RADIANS)).doubleValue();
  }

  /**
   * 测试
   *
   * <pre>
   * 广州塔,经纬度:113.324553,23.106414
   * 东方明珠电视塔,经纬度:121.499718,31.239703
   * </pre>
   *
   * @param args args
   */
  public static void main(String[] args) {
    double distance = getDistance(113.324553, 23.106414, 121.499718, 31.239703);
    System.out.println(distance);
  }
}

计算结果(单位:米):

1212391.2574948743

MySQL版本

开始写计算函数

有了前面球面距离计算公式基础之后,我们就可以一葫芦画瓢写出mysql版的函数了。

创建calculate_distance函数

这里我将计算距离结果单位设置为米。

CREATE FUNCTION calculate_distance ( longitude1 DOUBLE, latitude1 DOUBLE, longitude2 DOUBLE, latitude2 DOUBLE ) RETURNS DOUBLE 
BEGIN
    RETURN 6371393 * ACOS( 
        COS( RADIANS( latitude1 ))  
        * COS( RADIANS( latitude2 )) 
        * COS( RADIANS( longitude2 - longitude1 )) 
        + SIN( RADIANS( latitude1 )) 
        * SIN( RADIANS( latitude2 )) 
    );
END;

说明: MySQL中的RADIANS函数

将度数值转换为弧度值。

mysql> SELECT RADIANS(180);
+-------------------+
| RADIANS(180)      |
+-------------------+
| 3.141592653589793 |
+-------------------+
1 row in set (0.03 sec)

MySQL计算示例

示例sql查询两点的距离,实际情况你可以根据自己数据库中的字段去调整sql,在此我仅仅是演示:

mysql> SELECT calculate_distance(113.324553, 23.106414, 121.499718, 31.239703);
+------------------------------------------------------------------+
| calculate_distance(113.324553, 23.106414, 121.499718, 31.239703) |
+------------------------------------------------------------------+
|                                               1212391.2574948743 |
+------------------------------------------------------------------+
1 row in set (0.06 sec)

计算结果跟前面Java版本的一样。

结果大概都是1212391米。

对比验证计算结果

注意,以下结果仅供参考!

高德地图验证结果

高德地图经纬度计算在线地址

广州塔到东方明珠电视塔的距离:1213675 米。跟我们公式计算(Java版本&MySQL版本)的误差大概是:1284 米。

高德地图在线计算距离-广州塔-东方明珠电视塔.png

百度地图计算结果

百度地图经纬度计算在线地址

广州塔到东方明珠电视塔的距离:1212315.87 米。跟我们公式计算(Java版本&MySQL版本)的误差大概是:75.13 米。

百度地图在线计算距离-广州塔-东方明珠电视塔.png

结尾

毕竟这是计算的直线距离,不同的计算方法、坐标系(Sphere坐标系、WGS84坐标系)、精度等等因素都会影响计算的结果。

如果要计算驾车、步行这种分类计算距离的,建议可以去看看使用高德地图、百度地图、腾讯地图的API。

关于博主

欢迎关注博主个人博客:www.lzhpo.com

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
关系型数据库 MySQL Java
【MySQL+java+jpa】MySQL数据返回项目的感悟
【MySQL+java+jpa】MySQL数据返回项目的感悟
44 1
|
2月前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
73 0
|
2月前
|
分布式计算 关系型数据库 MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
50 3
|
21天前
|
存储 分布式计算 Java
存算分离与计算向数据移动:深度解析与Java实现
【11月更文挑战第10天】随着大数据时代的到来,数据量的激增给传统的数据处理架构带来了巨大的挑战。传统的“存算一体”架构,即计算资源与存储资源紧密耦合,在处理海量数据时逐渐显露出其局限性。为了应对这些挑战,存算分离(Disaggregated Storage and Compute Architecture)和计算向数据移动(Compute Moves to Data)两种架构应运而生,成为大数据处理领域的热门技术。
40 2
|
25天前
|
分布式计算 Java MaxCompute
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置
|
2月前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
2月前
|
关系型数据库 MySQL Java
java协程操作mysql数据库
本文介绍了如何在Java项目中使用虚拟线程和协程操作MySQL数据库,并通过代码示例展示了如何利用CompletableFuture实现非阻塞数据库连接和操作。
29 2
java协程操作mysql数据库
|
2月前
|
机器学习/深度学习 算法 搜索推荐
让星星⭐月亮告诉你,Java冒泡排序及其时间复杂度计算
冒泡排序是一种简单的排序算法,通过多次遍历数组,每次比较相邻元素并交换位置,将较小的元素逐步移至数组前端。第一轮结束后,最小值会位于首位;第二轮则将次小值置于第二位,依此类推。经过 (n-1) 轮遍历后,数组完成排序。冒泡排序的时间复杂度为 O(n²),在最优情况下(已排序数组)时间复杂度为 O(n)。示例代码展示了如何实现冒泡排序。
52 1
|
2月前
|
分布式计算 资源调度 Hadoop
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
98 3
|
25天前
|
Java API Apache
java集合的组内平均值怎么计算
通过本文的介绍,我们了解了在Java中计算集合的组内平均值的几种方法。每种方法都有其优缺点,具体选择哪种方法应根据实际需求和场景决定。无论是使用传统的循环方法,还是利用Java 8的Stream API,亦或是使用第三方库(如Apache Commons Collections和Guava),都可以有效地计算集合的组内平均值。希望本文对您理解和实现Java中的集合平均值计算有所帮助。
26 0
下一篇
无影云桌面