Java计算经纬度距离的示例代码

2025-05-18 14:50

本文主要是介绍Java计算经纬度距离的示例代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下...

Java 中计算两个经纬度之间的距离,可以使用以下多种方法(代码示例均返回米为单位):

1. Haversine公式(中等精度,推荐通用场景)

public class GeoDistanceCalculator {
 
    public static double haversineDistance(double lat1, double lon1, double lat2, double lon2) {
        final int EARTH_RADIUS_METERS = 6371000;
 
        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_METERS * c;
    }
 
    public static void main(String[] args) {
        double distance = haversineDistance(40.7128, -74.0060, 34.0522, -118.2437);
        System.out.println("距离:" + distance + " 米"); // 输出约 3933476 米
    }
}

2. 球面余弦定理(简单但精度较低)

public static double sphericalCosineLaw(double lat1, double lon1, double lat2, double lon2) {
    final int EARTH_RADIUS_METERS = 6371000;
 
    double lat1Rad = Math.toRadians(lat1);
    double lat2Rad = Math.toRadians(lat2);
    double dLon = Math.toRadians(lon2 - lon1);
 
    double distance = Math.acos(
        Math.sin(lat1Rad) * Math.sin(lat2Rad) +
        Math.cos(lat1Rad) * Math.cos(lat2Rad) * Math.cos(dLon)
    ) * EARTH_RADIUS_METERS;
 
    return distance;
}

3. Vincenty公式(高精度,适用于复杂模型)

public static double vincentyDistance(double lat1, double lon1, double lat2, double lon2) {
    final double a = 6378137.0; // 赤道半径(米)
    final double b = 6356752.314245; // 极半径(米)
    final double f = 1 / 298.257223563; // 扁率
 
    double L = Math.toRadians(lon2 - lon1);
    double U1 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat1)));
    double U2 = Math.atan((1 - f) * Math.tan(Math.toRadians(lat2)));
 
    double sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
    double sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
 
    double lambda = L, lambdaPrev;
    double sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, C;
    int maxIterations = 200;
 
    do {
        double sinLambda = Math.sin(lambda), 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; // 重合点
 
        cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
        sigma = Math.atan2(sinSigma, cosSwww.chinasem.cnigma);
   javascript     sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
        cosSqAlpha = 1 - sinAlpha * sinAlpha;
        C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
        lambdaPrev = lambda;
        lambda = L + (1 - C) * f * sinAlpha * 
            (sigma + C * sinSigma * (cosSigma + C * cosSigma * (-1 + 2 * C * cosSigma * cosSigma)));
    } while (Math.abs(lambda - lambdaPrev) > 1e-12 && --maxIterations > 0);
 
    double uSq = cosSqAlpha * (a * a - b * b) / (b * b);
    double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
    double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
    double deltaSigma = B * sinSigma * (cosSigma + B / 4 * 
        (cosSigma * (-1 + 2 * B * cosSigma * cosSigma) - 
         B / 6 * cosSigma * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cosSigma * cosSigma)));
 
    return b * A * (sigma - deltaSigma);
}

4. Android内置方法(仅限Android开发)

import android.location.Location;
 
public static float androidLocationDistance(double lat1, double lon1, double lat2, double lon2) {
    Location location1 = new Location("point1");
    location1.setLatitude(lat1);
    location1.setLongitude(lon1);
 
    Location location2 = new Location("point2");
    location2.setLatitude(lat2);
    location2.setLongitude(lon2);
 
    return location1.distanceTo(location2); // 返回米
}

5. 极地坐标系近似法(快速但低精度)

public static double polarApproximation(double lat1, double lon1, double lat2, double lon2) {
    final int EARTH_RADIUS_METERS = 6371000;
 
    double dLat = Math.toRadians(lat2 - lat1);
    double dLon = Math.toRadians(lon2 - lon1);
    double avgLat = Math.toRadians((lat1 + lat2) / 2);
 
    double x = dLon * Math.cos(avgLat);
    double y = dLat;
    return Math.sqrt(x * x + y * y) * EARTH_RADIUS_METERS;
}

6.方法对比

方法精度速度适用场景
Haversine公式中等(~0.5%)通用场景(导航、LBhttp://www.chinasem.cnS服务)
Vincenty公式高(~0.5mm)高精度需求(测绘、科学研究)
球面余弦定理快速估算(非关键场景)
Android Location中等中等Android应用开发
极地近似法极快快速筛选大量坐标点

7.选择建议

推荐使用 Haversine 公式:适用于大多数应用(如计算两个城市间的距离)。

需要高精度时选择 Vincenty 公式:例如地质勘测或导航系统

Android 开发直接使用 Location.distanceTo():无需手动实现算法。

快速筛选坐标点用极地近似法:例如在数据库中筛选附近地点。

8.知识延展

python计算经纬度两点之间距离方法

在Python中计算两个经纬度之间的距离有多种方法,常用的包括Haversine公式和Vincenty公式。下面是这两种方法的实现示例。

1. Haversine公式

Haversine公式是一种简单且常用的计算地球表面两点之间最短距离(大圆距离)的方法。

import math
 
def haversine_distance(lat1, lon1, lat2, lon2):
    # 地球半径,单位:公里
    R = 6371.0
    
    # 将经纬度转换为弧度
    lat1_rad = math.radians(lat1)
    lon1_rad = math.radians(lon1)
    lat2_rad = math.radians(lat2)
    lon2_rad = math.radians(lon2)
    
    # 计算差值
    dlat = lat2_rad - lat1_rad
    dlon = lon2_rad - lon1_rad
    
    # Haversine公式
    a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rChina编程ad) * math.sin(dlon / 2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    
    distance = R * c
    return distance
 
# 示例使用
lat1, lon1 = 34.052235, -118.243683  # 洛杉矶的经纬度
lat2, lon2 = 40.712776, -74.005974   # 纽约的经纬度
 
distance = haversine_distance(lat1, lon1, lat2, lon2)
print(f"Distance using Haversine formula: {distance} km")

2. Vincenty公式

Vincenty公式提供了更高的精度,适用于需要精确测量的情况。

第一种使用geographiclib库

pip install geographiclib
from geographiclib.geodesic import Geodesic
 
def vincenty_distance(lat1, lon1, lat2, lon2):
    geod = Geodesic.WGS84  # 使用WGS84椭球体模型
    result = geod.Inverse(lat1, lon1, lat2, lon2)
    distance = result['s12'] / 1000.0  # 距离单位:公里
    return distance
 
# 示例使用
lat1, lon1 = 34.052235, -118.243683  # 洛杉矶的经纬度
lat2, lon2 = 40.712776, -74.005974   # 纽约的经纬度
 
distance = vincenty_distance(lat1, lon1, lat2, lon2)
print(f"Distance using Vincenty formula: {distance} km")

第二种使用geopy库

pip install geopy
from geopy.distance import geodesic
 
def calculate_distance_with_geopy(lat1, lon1, lat2, lon2):
    # 定义两个点
    point1 = (lat1, lon1)
    point2 = (lahttp://www.chinasem.cnt2, lon2)
    
    # 计算两点之间的距离
    distance = geodesic(point1, point2).kilometers
    return distance
 
# 示例使用
lat1, lon1 = 34.052235, -118.243683  # 洛杉矶的经纬度
lat2, lon2 = 40.712776, -74.005974   # 纽约的经纬度
 
distance = calculate_distance_with_geopy(lat1, lon1, lat2, lon2)
print(f"Distance using Vincenty formula: {distance} km")

Haversine公式:简单易用,适合大多数情况。

Vincenty公式:更高精度,适用于需要精确测量的情况。

到此这篇关于Java计算经纬度距离的示例代码的文章就介绍到这了,更多相关Java计算经纬度距离内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于Java计算经纬度距离的示例代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154656

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

Python函数作用域示例详解

《Python函数作用域示例详解》本文介绍了Python中的LEGB作用域规则,详细解析了变量查找的四个层级,通过具体代码示例,展示了各层级的变量访问规则和特性,对python函数作用域相关知识感兴趣... 目录一、LEGB 规则二、作用域实例2.1 局部作用域(Local)2.2 闭包作用域(Enclos

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语