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