坐标系计算工具类
This commit is contained in:
parent
1c5a0bc5c0
commit
3e90541057
@ -4,8 +4,7 @@ package com.cdzy.common.utils;
|
||||
* 坐标转换工具类。
|
||||
*
|
||||
* @author dingchao
|
||||
* @date 2025/4/2
|
||||
* @modified by:
|
||||
* @since 2025/4/2
|
||||
*/
|
||||
public class CoordinateUtil {
|
||||
// 克拉索夫斯基椭球参数
|
||||
@ -13,6 +12,11 @@ public class CoordinateUtil {
|
||||
private static final double A = 6378245.0; // 长半轴
|
||||
private static final double EE = 0.00669342162296594323; // 第一偏心率平方
|
||||
|
||||
// 坐标系常量
|
||||
public static final String EPSG_4326 = "EPSG:4326"; // WGS84
|
||||
public static final String GCJ02 = "GCJ02"; // 火星坐标系
|
||||
public static final String BD09 = "BD09"; // 百度坐标系
|
||||
|
||||
/**
|
||||
* WGS84 --> GCJ02
|
||||
* @param wgsLon 经度
|
||||
@ -39,6 +43,131 @@ public class CoordinateUtil {
|
||||
return new double[]{gcjLon, gcjLat};
|
||||
}
|
||||
|
||||
/**
|
||||
* GCJ02 --> WGS84
|
||||
* @param gcjLon 经度
|
||||
* @param gcjLat 纬度
|
||||
* @return WGS84坐标数组 [经度, 纬度]
|
||||
*/
|
||||
public static double[] GCJ02ToWGS84(double gcjLon, double gcjLat) {
|
||||
if (outOfChina(gcjLon, gcjLat)) {
|
||||
return new double[]{gcjLon, gcjLat};
|
||||
}
|
||||
// 使用迭代法进行逆向转换
|
||||
double[] wgs84 = WGS84ToGCJ02(gcjLon, gcjLat);
|
||||
double deltaLon = wgs84[0] - gcjLon;
|
||||
double deltaLat = wgs84[1] - gcjLat;
|
||||
return new double[]{gcjLon - deltaLon, gcjLat - deltaLat};
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用坐标转换方法
|
||||
* @param lon 经度
|
||||
* @param lat 纬度
|
||||
* @param from 源坐标系
|
||||
* @param to 目标坐标系
|
||||
* @return 转换后的坐标数组 [经度, 纬度]
|
||||
* @throws IllegalArgumentException 当不支持的坐标系转换时抛出异常
|
||||
*/
|
||||
public static double[] convert(double lon, double lat, String from, String to) {
|
||||
if (from == null || to == null) {
|
||||
throw new IllegalArgumentException("源坐标系和目标坐标系不能为null");
|
||||
}
|
||||
|
||||
// 相同坐标系直接返回
|
||||
if (from.equals(to)) {
|
||||
return new double[]{lon, lat};
|
||||
}
|
||||
|
||||
// WGS84转GCJ02
|
||||
if (EPSG_4326.equals(from) && GCJ02.equals(to)) {
|
||||
return WGS84ToGCJ02(lon, lat);
|
||||
}
|
||||
|
||||
// GCJ02转WGS84
|
||||
if (GCJ02.equals(from) && EPSG_4326.equals(to)) {
|
||||
return GCJ02ToWGS84(lon, lat);
|
||||
}
|
||||
|
||||
// WGS84转BD09
|
||||
if (EPSG_4326.equals(from) && BD09.equals(to)) {
|
||||
return WGS84ToDB09(lon, lat);
|
||||
}
|
||||
|
||||
// GCJ02转BD09
|
||||
if (GCJ02.equals(from) && BD09.equals(to)) {
|
||||
return GCJ02ToBD(new double[]{lon, lat});
|
||||
}
|
||||
|
||||
// BD09转GCJ02
|
||||
if (BD09.equals(from) && GCJ02.equals(to)) {
|
||||
return BD09ToGCJ02(new double[]{lon, lat});
|
||||
}
|
||||
|
||||
// 其他转换组合可以通过已有方法组合实现
|
||||
if (BD09.equals(from) && EPSG_4326.equals(to)) {
|
||||
// BD09 -> GCJ02 -> WGS84
|
||||
double[] gcj02 = BD09ToGCJ02(new double[]{lon, lat});
|
||||
return GCJ02ToWGS84(gcj02[0], gcj02[1]);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("不支持的坐标系转换: " + from + " -> " + to);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断坐标是否为WGS84坐标系(通过检查是否在国内且未加密)
|
||||
* @param lon 经度
|
||||
* @param lat 纬度
|
||||
* @return true-可能是WGS84坐标, false-可能是GCJ02坐标
|
||||
*/
|
||||
public static boolean isWGS84Coordinate(double lon, double lat) {
|
||||
if (outOfChina(lon, lat)) {
|
||||
return true; // 国外坐标WGS84和GCJ02相同
|
||||
}
|
||||
|
||||
// 计算该坐标如果从WGS84转GCJ02的偏移量
|
||||
double[] gcj02 = WGS84ToGCJ02(lon, lat);
|
||||
double deltaLon = Math.abs(gcj02[0] - lon);
|
||||
double deltaLat = Math.abs(gcj02[1] - lat);
|
||||
|
||||
// 如果偏移量很小,说明可能是GCJ02坐标
|
||||
// 如果偏移量较大,说明可能是WGS84坐标
|
||||
return deltaLon > 0.0001 || deltaLat > 0.0001;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个坐标系之间的偏移距离(米)
|
||||
* @param lon 经度
|
||||
* @param lat 纬度
|
||||
* @param from 源坐标系
|
||||
* @param to 目标坐标系
|
||||
* @return 偏移距离(米)
|
||||
*/
|
||||
public static double calculateOffsetDistance(double lon, double lat, String from, String to) {
|
||||
double[] converted = convert(lon, lat, from, to);
|
||||
return calculateDistance(lon, lat, converted[0], converted[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个坐标点之间的距离(米)
|
||||
* @param lon1 点1经度
|
||||
* @param lat1 点1纬度
|
||||
* @param lon2 点2经度
|
||||
* @param lat2 点2纬度
|
||||
* @return 距离(米)
|
||||
*/
|
||||
public static double calculateDistance(double lon1, double lat1, double lon2, double lat2) {
|
||||
double radLat1 = Math.toRadians(lat1);
|
||||
double radLat2 = Math.toRadians(lat2);
|
||||
double a = radLat1 - radLat2;
|
||||
double b = Math.toRadians(lon1) - Math.toRadians(lon2);
|
||||
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
|
||||
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
|
||||
s = s * A; // 使用椭球长半轴
|
||||
s = Math.round(s * 10000) / 10000.0;
|
||||
return s;
|
||||
}
|
||||
|
||||
// 纬度偏移计算
|
||||
private static double transformLat(double x, double y) {
|
||||
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y;
|
||||
@ -92,8 +221,8 @@ public class CoordinateUtil {
|
||||
return new double[]{tempLon, tempLat};
|
||||
}
|
||||
|
||||
/*
|
||||
* wgs84 --> baidu
|
||||
/**
|
||||
* WGS84 --> BD09
|
||||
*
|
||||
* @param lng 经度
|
||||
* @param lat 纬度
|
||||
@ -103,5 +232,4 @@ public class CoordinateUtil {
|
||||
double[] gcj02 = WGS84ToGCJ02(lng,lat);
|
||||
return GCJ02ToBD(gcj02);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user