wlzboy
2025-09-25 4648a3bee638e9a99d2d80b66f8833b261a2db91
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package com.ruoyi.common.utils;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
 
/**
 * GPS坐标距离计算工具类
 * 使用Haversine公式计算两点间的球面距离
 * 
 * @author ruoyi
 * @date 2024-01-15
 */
public class GpsDistanceUtils {
    
    /** 地球半径(公里) */
    private static final double EARTH_RADIUS = 6371.0;
    
    /**
     * 计算两个GPS坐标点之间的距离(公里)
     * 
     * @param lat1 起点纬度
     * @param lon1 起点经度
     * @param lat2 终点纬度
     * @param lon2 终点经度
     * @return 距离(公里),保留2位小数
     */
    public static BigDecimal calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        // 将角度转换为弧度
        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.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
                   Math.cos(lat1Rad) * Math.cos(lat2Rad) *
                   Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
        
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        
        // 计算距离
        double distance = EARTH_RADIUS * c;
        
        // 返回BigDecimal,保留2位小数
        return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP);
    }
    
    /**
     * 计算两个GPS坐标点之间的距离(公里)
     * 
     * @param lat1 起点纬度
     * @param lon1 起点经度
     * @param lat2 终点纬度
     * @param lon2 终点经度
     * @return 距离(公里),保留2位小数
     */
    public static BigDecimal calculateDistance(BigDecimal lat1, BigDecimal lon1, BigDecimal lat2, BigDecimal lon2) {
        if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) {
            return BigDecimal.ZERO;
        }
        
        return calculateDistance(lat1.doubleValue(), lon1.doubleValue(), 
                               lat2.doubleValue(), lon2.doubleValue());
    }
    
    /**
     * 验证GPS坐标是否有效
     * 
     * @param latitude 纬度
     * @param longitude 经度
     * @return 是否有效
     */
    public static boolean isValidCoordinate(double latitude, double longitude) {
        return latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
    }
    
    /**
     * 验证GPS坐标是否有效
     * 
     * @param latitude 纬度
     * @param longitude 经度
     * @return 是否有效
     */
    public static boolean isValidCoordinate(BigDecimal latitude, BigDecimal longitude) {
        if (latitude == null || longitude == null) {
            return false;
        }
        
        return isValidCoordinate(latitude.doubleValue(), longitude.doubleValue());
    }
    
    /**
     * 格式化GPS坐标显示
     * 
     * @param coordinate 坐标值
     * @return 格式化后的坐标字符串
     */
    public static String formatCoordinate(BigDecimal coordinate) {
        if (coordinate == null) {
            return "";
        }
        return coordinate.setScale(6, RoundingMode.HALF_UP).toString();
    }
    
    /**
     * 获取坐标的度分秒格式
     * 
     * @param coordinate 坐标值(度)
     * @return 度分秒格式字符串
     */
    public static String toDegreesMinutesSeconds(BigDecimal coordinate) {
        if (coordinate == null) {
            return "";
        }
        
        double coord = coordinate.doubleValue();
        boolean isNegative = coord < 0;
        coord = Math.abs(coord);
        
        int degrees = (int) coord;
        double minutesFloat = (coord - degrees) * 60;
        int minutes = (int) minutesFloat;
        double seconds = (minutesFloat - minutes) * 60;
        
        String result = String.format("%d°%d'%.2f\"", degrees, minutes, seconds);
        return isNegative ? "-" + result : result;
    }
}