Java实现通过经纬度求两个任意地点在球面上的距离

news2024/11/26 4:51:18

我们在实际开发中会获取对应的经纬度,可以使用ES大数据搜索引擎进行计算对应区域的数据,那我们在如何根据两个经纬度获取对应的球面距离,就是在地球上从一个地点到另一个地点的直线距离

工具类如下:

public class GeoUtils {
    // 地球半径(单位:米)
    private static final double EARTH_RADIUS = 6371000.0;

    /**
     * 使用Haversine公式计算两点之间的球面距离
     *
     * @param lat1 latitude 纬度
     * @param lon1 longitude 经度
     * @param lat2 纬度
     * @param lon2 经度
     * @return 球面距离
     */
    public static double haversineDistance(double lat1, double lon1, double lat2, double lon2) {
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return EARTH_RADIUS * c;
    }

    /**
     * 使用Vincenty公式计算两点之间的球面距离
     *
     * @param lat1 latitude 纬度
     * @param lon1 longitude 经度
     * @param lat2 纬度
     * @param lon2 经度
     * @return 球面距离
     */
    public static double vincentyDistance(double lat1, double lon1, double lat2, double lon2) {
        double a = EARTH_RADIUS;
        double f = 1.0 / 298.257223563; // WGS-84 ellipsoid parameters
        double b = a * (1.0 - f);
        double lat1Rad = Math.toRadians(lat1);
        double lon1Rad = Math.toRadians(lon1);
        double lat2Rad = Math.toRadians(lat2);
        double lon2Rad = Math.toRadians(lon2);

        double L = lon2Rad - lon1Rad;
        double U1 = Math.atan((1.0 - f) * Math.tan(lat1Rad));
        double U2 = Math.atan((1.0 - f) * Math.tan(lat2Rad));
        double sinU1 = Math.sin(U1);
        double cosU1 = Math.cos(U1);
        double sinU2 = Math.sin(U2);
        double cosU2 = Math.cos(U2);

        double lambda = L;
        double lambdaP;
        int iterLimit = 100;
        double cosSigma, sinSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM;
        do {
            double sinLambda = Math.sin(lambda);
            double cosLambda = Math.cos(lambda);
            sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) +
                    (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) *
                            (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
            if (sinSigma == 0) {
                return 0.0;
            }
            cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
            sigma = Math.atan2(sinSigma, cosSigma);
            sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
            cos2SigmaM = cosSigma - 2.0 * sinU1 * sinU2 / cosSqAlpha;
            if (Double.isNaN(cos2SigmaM)) {
                cos2SigmaM = 0.0;
            }
            double C = f / 16.0 * cosSqAlpha * (4.0 + f * (4.0 - 3.0 * cosSqAlpha));
            lambdaP = lambda;
            lambda = L + (1.0 - C) * f * sinAlpha *
                    (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM)));
        } while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);

        if (iterLimit == 0) {
            return Double.NaN; // Formula failed to converge
        }

        double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
        double A = 1 + uSq / 16384.0 * (4096.0 + uSq * (-768 + uSq * (320 - 175 * uSq)));
        double B = uSq / 1024.0 * (256.0 + uSq * (-128.0 + uSq * (74.0 - 47 * uSq)));
        double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4.0 * (cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM) -
                B / 6.0 * cos2SigmaM * (-3.0 + 4.0 * sinSigma * sinSigma) *
                        (-3.0 + 4.0 * cos2SigmaM * cos2SigmaM)));
        return b * A * (sigma - deltaSigma);
    }

    /**
     * 使用球面三角法计算两点之间的球面距离
     *
     * @param lat1 latitude 纬度
     * @param lon1 longitude 经度
     * @param lat2 纬度
     * @param lon2 经度
     * @return 球面距离
     */
    public static double sphericalLawOfCosinesDistance(double lat1, double lon1, double lat2, double lon2) {
        double dLon = Math.toRadians(lon2 - lon1);
        lat1 = Math.toRadians(lat1);
        lat2 = Math.toRadians(lat2);
        return Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(dLon)) * EARTH_RADIUS;
    }

    /**
     * 将米转换成公里
     *
     * @param meters
     * @return
     */
    public static double metersToKilometers(double meters) {
        return meters / 1000.0;
    }

}

测试从纽约到伦敦的距离

  public static void main(String[] args) {
        double newYorkLat = 40.7128; // 纽约的纬度
        double newYorkLon = -74.0060; // 纽约的经度
        double londonLat = 51.5074; // 伦敦的纬度
        double londonLon = -0.1278; // 伦敦的经度
        double distance1 = GeoUtils.haversineDistance(newYorkLat, newYorkLon, londonLat, londonLon);
        System.out.println("从纽约到伦敦的球面距离:" + distance1 + " 米 ," + metersToKilometers(distance1) + " 公里");
        double distance2 = GeoUtils.vincentyDistance(newYorkLat, newYorkLon, londonLat, londonLon);
        System.out.println("从纽约到伦敦的球面距离:" + distance2 + " 米 ," + metersToKilometers(distance2) + " 公里");
        double distance3 = GeoUtils.sphericalLawOfCosinesDistance(newYorkLat, newYorkLon, londonLat, londonLon);
        System.out.println("从纽约到伦敦的球面距离:" + distance3 + " 米 ," + metersToKilometers(distance3) + " 公里");
    }

这样子就可以求出地球上两点之间的距离了 

8f249501609b491f9a24e4de5c1524e7.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1264996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手教你如何实现List——ArrayList

目录 前言: 线性表 顺序表 接口的实现 一. 打印顺序表 二.新增元素,默认在数组最后新增 三.在 pos 位置新增元素 四.判定是否包含某个元素 五. 查找某个元素对应的位置 六.获取 pos 位置的元素 七.给 pos 位置的元素设为 value 八.删除第一次出现的关键字k…

移动应用开发介绍及iOS方向学习路线(HUT移动组版)

移动应用开发介绍及iOS方向学习路线(HUT移动组版) 前言 ​ 作为一个HUT移动组待了一坤年(两年半)多的老人,在这里为还在考虑进哪个组的萌新们以及将来进组的新朋友提供一份关于移动应用开发介绍以及学习路线的白话文…

华为云(HECS)docker环境下安装jenkins

Jenkins是一个开源的自动化工具,可以自动化地完成构建、测试、交付或部署等任务。总之重点就是三个字:自动化,至于如何实现这些功能,Jenkins基于插件化的机制,提供了众多的插件来完成持续集成CI与持续部署CD。 【持续…

直播场景视频和特效解决方案

直播已经成为企业与消费者互动的重要方式,如何提供优质的直播内容,提升直播效果,以及实现直播内容的商业化转化,一直是企业面临的重要挑战。为此,美摄科技提供了一套全面的直播场景解决方案,帮助企业解决这…

内网渗透(哈希传递)

概念 早期SMB协议明文在网络上传输数据,后来诞生了LM验证机制,LM机制由于过于简单,微软提出了WindowsNT挑战/响应机制,这就是NTLM。 哈希传递前提 同密码(攻击主机与实现主机两台要密码一致)。 NTLM协议 加密ntlm哈希 转换成…

力扣hot100 最大子数组和 动态规划 分治 无后效性 子问题划分

👨‍🏫 题目地址 无后效性 为了保证计算子问题能够按照顺序、不重复地进行,动态规划要求已经求解的子问题不受后续阶段的影响。这个条件也被叫做「无后效性」。换言之,动态规划对状态空间的遍历构成一张有向无环图,遍…

UE4 UE5 使用SVN控制

关键概念:虚幻引擎中使用SVN,帮助团队成员共享资源。 1. UE4/UE5项目文件 如果不需要编译的中间缓存,则删除: DerivedDataCache、Intermediate、Saved 三个文件夹 2.更新、上传

梦极光(ez_re???)

ez_re 先查壳看看,没有壳 32位 我先说说这道题 打开分析找到主函数 在这里就是flag了,用十六进制转ascll码 我们先运行这个程序看看 我想说说我的想法 首先没看出来这里是十六进制转ascll码其次41D538数组用来干啥来的?题目里面给出的请…

JVM GC算法

一, 垃圾回收分类: 按线程数分,可以分为串行垃圾回收器和并行垃圾回收器。 按工作模式分,可以分为并发垃圾回收器和独占式垃圾回收器 按碎片处理方式分,可以分为压缩式垃圾回收器和非压缩式垃圾回收器按工作的内存区间分,又可分为…

Linux常用命令----shutdown命令

文章目录 命令概述参数解释使用示例及解释 命令概述 shutdown 命令用于安全地关闭或重启 Linux 系统。它允许管理员指定一个时间点执行操作,并可发送警告信息给所有登录的用户。 参数解释 时间参数 ([时间]): now: 立即执行关闭或重启操作。m: 在 m 分钟后执行操作…

redis基本数据结构

Redis入门:五大数据类型 文章目录 Redis入门:五大数据类型一.概述二.Redis的基本了解三.Redis五大数据类型1.String (字符串)2.List(列表)3.Set集合(元素唯一不重复)4.Hash集合5.zSet(有序集合) 一.概述 什么是Redis Redis(Remote Dictiona…

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具 一、Simple mind map介绍1.1 Simple mind map简介1.2 Simple mind map特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker co…

基于STM32 + TIM _定时器的基本机构和工作原理详解

前言 本篇博客主要学习了解定时器的基本结构和工作原理,掌握定时器的驱动程序和设计。本篇博客大部分是自己收集和整理,如有侵权请联系我删除。 本次博客板子使用的是正点原子精英版,芯片是STM32F103ZET6,需要资料可以我拿取。 本博客内容原…

线性系统理论 -- 降阶观测器的设计

定理: 若系统能观测,且rankCm,则系统的状态观测器的最小维数是(n-m)。 线性定常时不变系统方程如下(以三阶(n3)单入单出系统为例,有mrankC1): 取变换阵P,有: 对上述系统…

AT89S52单片机的定时器

目录 定时器/计数器的结构 工作方式控制寄存器TMOD和TCON 定时器/计数器T1、T0的4种工作方式 1.方式0 2.方式1 3.方式2 4.方式3 定时器/计数器T2的结构与工作方式 1.T2的特殊功能寄存器T2MOD和T2CON 2.特殊功能寄存器T2CON 3.T2的三种工作模式 1. 捕捉方式 2.重新…

LangChain 14 SequencialChain链接不同的组件

LangChain系列文章 LangChain 实现给动物取名字,LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索I…

基于Eclipse+Mysql+Tomcat开发的挖掘机配件营销系统

基于EclipseMysqlTomcat开发的挖掘机配件营销系统 项目介绍💁🏻 大家都有目共睹,现在的科学技术发展很迅速。而如今,计算机应用已经完全融入到人们的生产和生活当中,特别是企业,现在的企业几乎都是离不开计…

论如何让Spring Boot在高压力环境下依然与众不同

文章目录 🔊博主介绍🥤本文内容调优线程池优化线程池配置多样化设备支持分布式控制同步编程 📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客…

网络和信息系统指令 ( NIS2 ) 及其全球影响

网络和信息系统指令 ( NIS2 ) 将于 2024 年 10 月生效,旨在提高欧盟 (EU) 的网络弹性。 不过,其影响可能会更广泛,带来更严格的流程和控制,并重新定义我们向被视为国家关键的组织提供服务的方式。 该强制性指令将具有效力&#x…

centos7.9 + gitlab12.3.0安装

本文在centos7.9操作系统上安装gitlab 12.3.0,gitlab官方最新的版本已经是16.6.0了,这里仍然安装12.3.0版本的原因是汉化包的最新版本是12.3.0,如果汉化包的版本和gitlab的版本不对应,会出现汉化他无法启动的现象。 1、安装依赖 …