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

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
28天前
|
SQL Java 关系型数据库
Java连接MySQL数据库环境设置指南
请注意,在实际部署时应该避免将敏感信息(如用户名和密码)硬编码在源码文件里面;应该使用配置文件或者环境变量等更为安全可靠地方式管理这些信息。此外,在处理大量数据时考虑使用PreparedStatement而不是Statement可以提高性能并防止SQL注入攻击;同时也要注意正确处理异常情况,并且确保所有打开过得资源都被正确关闭释放掉以防止内存泄漏等问题发生。
72 13
|
2月前
|
机器学习/深度学习 Java 编译器
解锁硬件潜能:Java向量化计算,性能飙升W倍!
编译优化中的机器相关优化主要包括指令选择、寄存器分配、窥孔优化等,发生在编译后端,需考虑目标平台的指令集、寄存器、SIMD支持等硬件特性。向量化计算利用SIMD技术,实现数据级并行,大幅提升性能,尤其适用于图像处理、机器学习等领域。Java通过自动向量化和显式向量API(JDK 22标准)支持该技术。
80 4
|
3月前
|
人工智能 Java 关系型数据库
Java的时间处理与Mysql的时间查询
本文总结了Java中时间与日历的常用操作,包括时间的转换、格式化、日期加减及比较,并介绍了MySQL中按天、周、月、季度和年进行时间范围查询的方法,适用于日常开发中的时间处理需求。
|
3月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
237 14
|
5月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
8月前
|
存储 Java 关系型数据库
java调用mysql存储过程
在 Java 中调用 MySQL 存储过程主要借助 JDBC(Java Database Connectivity)。其核心原理是通过 JDBC 与 MySQL 建立连接,调用存储过程并处理结果。具体步骤包括:加载 JDBC 驱动、建立数据库连接、创建 CallableStatement 对象、设置存储过程参数并执行调用。此过程实现了 Java 程序与 MySQL 数据库的高效交互。
|
8月前
|
Java
Java计算时间差
这段代码提供了两个方法来计算时间差。`timeDistance` 方法接收两个 `Date` 对象,计算并返回两者之间的天数、小时数和分钟数差异,格式为“X天Y小时Z分钟”。`hourDistance` 方法则接收两个时间字符串,解析后计算并返回两者之间相差的小时数(向上取整)。
313 4
|
8月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
253 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
9月前
|
自然语言处理 Java 关系型数据库
Java mysql根据很长的富文本如何自动获取简介
通过使用Jsoup解析富文本并提取纯文本,然后根据需要生成简介,可以有效地处理和展示长文本内容。该方法简单高效,适用于各种应用场景。希望本文对您在Java中处理富文本并生成简介的需求提供实用的指导和帮助。
134 9
bzh
|
存储 算法 Dubbo
java计算圆的面积和java保留小数点后两位的方法
java计算圆的面积和java保留小数点后两位的方法
bzh
1026 0

推荐镜像

更多