Java下怎么获取经纬度坐标间的距离

Java下怎么获取经纬度坐标间的距离

Haversine公式

该公式通过考虑地球的曲率,能够较为准确地估算两点间的大圆距离。以下是Java实现代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class DistanceCalculator {

    public static void main(String[] args) {
        // 示例:计算北京和上海之间的距离
        double lat1 = 39.9042; // 北京纬度
        double lon1 = 116.4074; // 北京经度
        double lat2 = 31.2304; // 上海纬度
        double lon2 = 121.4737; // 上海经度
        
        double distance = calculateDistance(lat1, lon1, lat2, lon2);
        System.out.println("距离: " + distance + " 公里");
    }

    /**
     * 使用Haversine公式计算两个经纬度点之间的距离
     * @param lat1 第一个点的纬度(十进制度数)
     * @param lon1 第一个点的经度(十进制度数)
     * @param lat2 第二个点的纬度(十进制度数)
     * @param lon2 第二个点的经度(十进制度数)
     * @return 两点之间的距离,单位为公里
     */
    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int EARTH_RADIUS = 6371000; // 地球平均半径,单位:公里

        // 将十进制度数转换为弧度
        double lat1Rad = Math.toRadians(lat1);
        double lon1Rad = Math.toRadians(lon1);
        double lat2Rad = Math.toRadians(lat2);
        double lon2Rad = Math.toRadians(lon2);

        // 计算纬度和经度的差值
        double deltaLat = lat2Rad - lat1Rad;
        double deltaLon = lon2Rad - lon1Rad;

        // Haversine公式计算
        double a = Math.pow(Math.sin(deltaLat / 2), 2)
                + Math.cos(lat1Rad) * Math.cos(lat2Rad)
                * Math.pow(Math.sin(deltaLon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return EARTH_RADIUS * c;
    }
}

代码说明:

单位处理: 输入参数为十进制度数(例如:39.9042°N),计算结果以米为单位。

Haversine公式步骤:

将经纬度转换为弧度。

计算纬度和经度的差值(Δφ和Δλ)。

应用公式计算角距离(a和c)。

最终距离由地球半径乘以角距离得出。

精度说明: 公式假设地球为完美球体,实际地球为椭球,因此存在微小误差(通常小于0.5%)。

此方法适用于大多数需要快速估算地理距离的场景,如地理位置服务、导航应用等。


使用 Geodesy 库(基于 Vincenty 公式)

Geodesy 库支持更复杂的椭球模型(如 WGS84),适合高精度场景。需要先添加依赖:

Maven 依赖:

1
2
3
4
5
<dependency>
    <groupId>org.gavaghan</groupId>
    <artifactId>geodesy</artifactId>
    <version>1.1.3</version>
</dependency>

运行 HTML

Java 代码示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import org.gavaghan.geodesy.*;

public class GeodesyDistance {

    public static void main(String[] args) {
        // 初始化坐标点(纬度, 经度)
        GlobalPosition beijing = new GlobalPosition(39.9042, 116.4074, 0);
        GlobalPosition shanghai = new GlobalPosition(31.2304, 121.4737, 0);

        // 使用 Vincenty 公式计算距离(单位:米)
        GeodeticCalculator geoCalc = new GeodeticCalculator();
        Ellipsoid reference = Ellipsoid.WGS84; // 使用 WGS84 椭球模型
        double distance = geoCalc.calculateGeodeticCurve(reference, shanghai, beijing).getEllipsoidalDistance();

        System.out.println("距离: " + distance / 1000 + " 公里");
    }
}

关键点:

精度更高:Vincenty 公式在椭球模型下的误差通常小于 1毫米。

椭球模型选择:支持多种标准(如 Ellipsoid.WGS84、Ellipsoid.GRS80)。

异常处理:当两点几乎是“对跖点”(antipodal)时可能不收敛,需捕获 ArithmeticException。


使用 GeoTools 库

GeoTools 是一个功能强大的 GIS 工具库,支持复杂的地理空间操作。需要添加依赖:

Maven 依赖:

1
2
3
4
5
<dependency>
    <groupId>org.geotools</groupId>
    <artifactId>gt-main</artifactId>
    <version>25.0</version>
</dependency>

运行 HTML Java 代码示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;

public class GeoToolsDistance {

    public static void main(String[] args) throws Exception {
        // 初始化 GeodeticCalculator(默认使用 WGS84 坐标系)
        GeodeticCalculator geoCalc = new GeodeticCalculator(DefaultGeographicCRS.WGS84);

        // 设置起点(北京)
        geoCalc.setStartingGeographicPoint(116.4074, 39.9042);

        // 设置终点(上海)
        geoCalc.setDestinationGeographicPoint(121.4737, 31.2304);

        // 获取距离(单位:米)
        double distance = geoCalc.getOrthodromicDistance();

        System.out.println("距离: " + distance / 1000 + " 公里");
    }
}

关键点:

默认坐标系:DefaultGeographicCRS.WGS84 是标准经纬度坐标系。

更多功能:支持方位角计算、坐标投影转换等高级操作。

性能优化:适合处理大规模地理数据。

方法对比

方法 精度 效率 复杂度 适用场景
Haversine 0.5% 误差 极高 简单 快速估算,小范围距离计算
Geodesy (Vincenty) 毫米级 中等 高精度测量(如测绘、导航)
GeoTools 复杂 GIS 系统、复杂地理分析
Licensed under CC BY-NC-SA 4.0
Gear(夕照)的博客。记录开发、生活,以及一些不足为道的思考……