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; } }