Spring Boot集成geodesy实现距离计算

1.什么是geodesy?

浩瀚的宇宙中,地球是我们赖以生存的家园。自古以来,人类一直对星球上的位置和彼此的距离着迷。无论是航海探险、贸易往来还是科学研究,精确计算两个地点之间的距离都是至关重要的。 Geodesy:大地测量学的神奇力量 Geodesy,又称大地测量学,是一门研究地球形状、大小及其重力场的学科。在地球距离计算中,它扮演着至关重要的角色。Geodesy 的原理基于球面几何。 首先,Geodesy 将地球近似为一个光滑的球体。然后,根据经纬度坐标,将两个地点视为球面上的两点。最后,使用球面距离公式:

d = R * arccos(sin(φ1) * sin(φ2) + cos(φ1) * cos(φ2) * cos(λ1 - λ2))

其中,R 是地球半径,φ1 和 φ2 分别是两个地点的纬度,λ1 和 λ2 是两个地点的经度,d 是两点之间的距离。 通过这个公式,Geodesy 能够快速准确地计算出地球上两个经纬度坐标之间的距离。

2.代码工程

实验目标

  • 1.利用数学公式计算
  • 2.利用Java库包Geodesy

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>geodesy</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.gavaghan</groupId>
            <artifactId>geodesy</artifactId>
            <version>1.1.3</version>
        </dependency>

    </dependencies>
</project>

数学公式计算类

package com.et.geodesy.util;

import lombok.experimental.UtilityClass;

import java.math.BigDecimal;

/**
 *
 *
 * <p>formula:S=R·arccos[cosβ1·cosβ·2cos(α1-α2)+sinβ1·sinβ2]
 */
@UtilityClass
public class MathDistanceUtil {

  private static final double EARTH_RADIUS = 6371393;

  private static final double DEGREES_TO_RADIANS = 0.017453292519943295;

  /**
   * Calculate according to formula
   *
   * @param longitude1
   * @param latitude1
   * @param longitude2
   * @param latitude2
   * @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();
  }

  /**
   * refer:{@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();
  }


}

库包调用

底层原理也是基于公式计算,方便大家使用才封装成包

package com.et.geodesy.util;

import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.math.BigDecimal;
import java.math.RoundingMode;


public class GeodsyDistanceUtils {

    /**
     *
     *
     * @param lonA A longitude
     * @param latA A latitude
     * @param lonB B longitude
     * @param latB B latitude
     * @param newScale The result is kept to decimal places
     * @return distant (m)
     */
    public static double getDistance(Double lonA, Double latA, Double lonB, Double latB,int newScale) {
        GlobalCoordinates source = new GlobalCoordinates(latA, lonA);
        GlobalCoordinates target = new GlobalCoordinates(latB, lonB);
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target);
        double distance = geoCurve.getEllipsoidalDistance();
        BigDecimal distanceBig = new BigDecimal(distance).setScale(newScale, RoundingMode.UP);
        return distanceBig.doubleValue();
    }

}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

3.测试

编写测试类

@Test
public void getDistance() {
    // source (113.324553,23.106414)
    // target (121.499718, 31.239703)
    double distance1 = GeodsyDistanceUtils.getDistance(113.324553,23.106414,
            121.499718, 31.239703,2);
    System.out.println("distant1(m):" + distance1);
    double distance2 = MathDistanceUtil.getDistance(113.324553, 23.106414, 121.499718, 31.239703);
    System.out.println("distant2(m):" + distance2);
}

运行单元测试,发现2种计算方式误差不大

distant1(m):1212316.48
distant2(m):1212391.2574948743

4.引用

相关推荐

  1. Spring Boot集成geodesy实现距离计算

    2024-06-08 07:20:06       22 阅读
  2. SpringBoot集成Elasticsearch实例

    2024-06-08 07:20:06       24 阅读
  3. SpringBoot集成Redisson实现限流(二)

    2024-06-08 07:20:06       61 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-08 07:20:06       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-08 07:20:06       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-08 07:20:06       87 阅读
  4. Python语言-面向对象

    2024-06-08 07:20:06       96 阅读

热门阅读

  1. SQL查询的优化方案

    2024-06-08 07:20:06       37 阅读
  2. npm常用命令,包含移除,安装等

    2024-06-08 07:20:06       31 阅读
  3. Zookeeper 和 Eureka 的区别

    2024-06-08 07:20:06       25 阅读
  4. Apache Kylin:大数据分析从入门到精通

    2024-06-08 07:20:06       32 阅读
  5. UE5-AI

    UE5-AI

    2024-06-08 07:20:06      30 阅读
  6. vb.net学习总结

    2024-06-08 07:20:06       26 阅读
  7. Android 14.0 修改wifi信号强度和信号等级

    2024-06-08 07:20:06       26 阅读
  8. 深度学习中2D检测

    2024-06-08 07:20:06       28 阅读
  9. kafka消息积压处理方案

    2024-06-08 07:20:06       28 阅读
  10. opencv灰度变换

    2024-06-08 07:20:06       29 阅读
  11. Apache Spark MLlib详解

    2024-06-08 07:20:06       29 阅读
  12. cpp--lua--cpp执行lua

    2024-06-08 07:20:06       27 阅读
  13. c++替换字符或字符串函数

    2024-06-08 07:20:06       29 阅读
  14. 抽象类和抽象方法(abstract)

    2024-06-08 07:20:06       31 阅读