问题修改

This commit is contained in:
jiang 2025-10-11 10:00:18 +08:00
parent 26eb4c75d7
commit 85b8427fb6
2 changed files with 254 additions and 15 deletions

View File

@ -0,0 +1,225 @@
package com.bonus.material.iot.controller;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class GNSSCoordinateTool {
// 坐标系转换所需常量
private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
private static double pi = 3.1415926535897932384626;
private static double a = 6378245.0;
private static double ee = 0.00669342162296594323;
/**
* 将GNSS输出的纬度格式(DDMM.MMMMMM)转换为十进制度(DD.DDDDDD)
* @param latStr GNSS纬度字符串格式为DDMM.MMMMMM
* @return 十进制纬度值
*/
public static double gnssLatToDecimal(String latStr) {
if (latStr == null || latStr.trim().isEmpty()) {
throw new IllegalArgumentException("纬度数据不能为空");
}
try {
// 提取度前两位
int degrees = Integer.parseInt(latStr.substring(0, 2));
// 提取分及小数部分
BigDecimal minutes = new BigDecimal(latStr.substring(2));
// 计算十进制纬度
return new BigDecimal(degrees)
.add(minutes.divide(new BigDecimal(60), 8, RoundingMode.HALF_UP))
.doubleValue();
} catch (Exception e) {
throw new IllegalArgumentException("无效的纬度格式: " + latStr + "正确格式应为DDMM.MMMMMM", e);
}
}
/**
* 将GNSS输出的经度格式(DDDMM.MMMMMM)转换为十进制度(DDD.DDDDDD)
* @param lonStr GNSS经度字符串格式为DDDMM.MMMMMM
* @return 十进制经度值
*/
public static double gnssLonToDecimal(String lonStr) {
if (lonStr == null || lonStr.trim().isEmpty()) {
throw new IllegalArgumentException("经度数据不能为空");
}
try {
// 提取度前三位
int degrees = Integer.parseInt(lonStr.substring(0, 3));
// 提取分及小数部分
BigDecimal minutes = new BigDecimal(lonStr.substring(3));
// 计算十进制经度
return new BigDecimal(degrees)
.add(minutes.divide(new BigDecimal(60), 8, RoundingMode.HALF_UP))
.doubleValue();
} catch (Exception e) {
throw new IllegalArgumentException("无效的经度格式: " + lonStr + "正确格式应为DDDMM.MMMMMM", e);
}
}
/**
* 检查坐标是否在中国境外
*/
private static boolean outOfChina(double lon, double lat) {
if (lon < 72.004 || lon > 137.8347) {
return true;
} else if (lat < 0.8293 || lat > 55.8271) {
return true;
}
return false;
}
/**
* 纬度转换
*/
private static double transformLat(double lon, double lat) {
double ret = -100.0 + 2.0 * lon + 3.0 * lat + 0.2 * lat * lat + 0.1 * lon * lat +
0.2 * Math.sqrt(Math.abs(lon));
ret += (20.0 * Math.sin(6.0 * lon * pi) + 20.0 * Math.sin(2.0 * lon * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * pi) + 320 * Math.sin(lat * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 经度转换
*/
private static double transformLng(double lon, double lat) {
double ret = 300.0 + lon + 2.0 * lat + 0.1 * lon * lon + 0.1 * lon * lat +
0.1 * Math.sqrt(Math.abs(lon));
ret += (20.0 * Math.sin(6.0 * lon * pi) + 20.0 * Math.sin(2.0 * lon * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lon * pi) + 40.0 * Math.sin(lon / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lon / 12.0 * pi) + 300.0 * Math.sin(lon / 30.0 * pi)) * 2.0 / 3.0;
return ret;
}
/**
* WGS84转GCJ02(火星坐标系)
*/
public static double[] wgs84ToGcj02(double wgsLon, double wgsLat) {
if (outOfChina(wgsLon, wgsLat)) {
return new double[] { wgsLon, wgsLat };
}
double dLat = transformLat(wgsLon - 105.0, wgsLat - 35.0);
double dLng = transformLng(wgsLon - 105.0, wgsLat - 35.0);
double radLat = wgsLat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
return new double[] { wgsLon + dLng, wgsLat + dLat };
}
/**
* GCJ02(火星坐标系)转WGS84
*/
public static double[] gcj02ToWgs84(double gcjLon, double gcjLat) {
if (outOfChina(gcjLon, gcjLat)) {
return new double[] { gcjLon, gcjLat };
}
double dLat = transformLat(gcjLon - 105.0, gcjLat - 35.0);
double dLng = transformLng(gcjLon - 105.0, gcjLat - 35.0);
double radLat = gcjLat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mglat = gcjLat + dLat;
double mglng = gcjLon + dLng;
return new double[] { gcjLon * 2 - mglng, gcjLat * 2 - mglat };
}
/**
* 火星坐标系(GCJ-02)转百度坐标系(BD-09)
*/
public static double[] gcj02ToBd09(double gcjLon, double gcjLat) {
double z = Math.sqrt(gcjLon * gcjLon + gcjLat * gcjLat) + 0.00002 * Math.sin(gcjLat * x_pi);
double theta = Math.atan2(gcjLat, gcjLon) + 0.000003 * Math.cos(gcjLon * x_pi);
return new double[] {
z * Math.cos(theta) + 0.0065,
z * Math.sin(theta) + 0.006
};
}
/**
* 百度坐标系(BD-09)转火星坐标系(GCJ-02)
*/
public static double[] bd09ToGcj02(double bdLon, double bdLat) {
double x = bdLon - 0.0065;
double y = bdLat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
return new double[] { z * Math.cos(theta), z * Math.sin(theta) };
}
/**
* WGS84转百度坐标系(BD-09)
*/
public static double[] wgs84ToBd09(double wgsLon, double wgsLat) {
double[] gcj = wgs84ToGcj02(wgsLon, wgsLat);
return gcj02ToBd09(gcj[0], gcj[1]);
}
/**
* 百度坐标系(BD-09)转WGS84
*/
public static double[] bd09ToWgs84(double bdLon, double bdLat) {
double[] gcj = bd09ToGcj02(bdLon, bdLat);
return gcj02ToWgs84(gcj[0], gcj[1]);
}
/**
* 格式化坐标为指定小数位数的字符串
*/
public static String formatCoordinate(double coordinate, int decimalPlaces) {
return new BigDecimal(coordinate)
.setScale(decimalPlaces, RoundingMode.HALF_UP)
.toString();
}
// 测试方法
public static void main(String[] args) {
try {
// 示例GNSS输出的坐标
String gnssLat = "3149.332558"; // 纬度 DDMM.MMMMMM格式
String gnssLon = "11706.912570"; // 经度 DDDMM.MMMMMM格式
// 转换为十进制WGS84坐标
double wgsLat = gnssLatToDecimal(gnssLat);
double wgsLon = gnssLonToDecimal(gnssLon);
System.out.println("GNSS原始坐标:");
System.out.println("纬度: " + gnssLat + " (DDMM.MMMMMM)");
System.out.println("经度: " + gnssLon + " (DDDMM.MMMMMM)");
System.out.println("\n转换为WGS84十进制坐标:");
System.out.println("纬度: " + formatCoordinate(wgsLat, 6));
System.out.println("经度: " + formatCoordinate(wgsLon, 6));
// 转换为其他地图坐标系
double[] gcj02 = wgs84ToGcj02(wgsLon, wgsLat);
double[] bd09 = wgs84ToBd09(wgsLon, wgsLat);
System.out.println("\n各地图坐标系坐标:");
System.out.println("谷歌/高德地图 (GCJ-02): " +
formatCoordinate(gcj02[1], 6) + ", " + formatCoordinate(gcj02[0], 6));
System.out.println("百度地图 (BD-09): " +
bd09[1] + ", " + formatCoordinate(bd09[0], 6));
} catch (Exception e) {
System.err.println("转换出错: " + e.getMessage());
}
}
}

View File

@ -1,7 +1,6 @@
package com.bonus.material.iot.controller;
import com.alibaba.fastjson.JSON;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.material.iot.dto.GpsData;
import com.bonus.material.iot.dto.PhaseData;
import com.fasterxml.jackson.databind.JsonNode;
@ -12,6 +11,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -213,17 +215,18 @@ public class IotDataController {
String gnssStr = rootNode.get("position").get("gnss").asText();
parseGnssData(gnssStr, data);
}
if ((data.getLatitude() == null || data.getLatitude().isEmpty()) && rootNode.has("wifi")) {
String wifiStr = rootNode.get("wifi").asText();
parseLbsWifiData(wifiStr, data, "wifi");
}
// 如果没有有效的 GNSS 数据尝试解析 LBS WiFi
if ((data.getLatitude() == null || data.getLatitude().isEmpty()) && rootNode.has("lbs")) {
String lbsStr = rootNode.get("lbs").asText();
parseLbsWifiData(lbsStr, data, "lbs");
}
if ((data.getLatitude() == null || data.getLatitude().isEmpty()) && rootNode.has("wifi")) {
String wifiStr = rootNode.get("wifi").asText();
parseLbsWifiData(wifiStr, data, "wifi");
}
}
/**
@ -268,9 +271,14 @@ public class IotDataController {
// 安全设置字段
if (gnrmcParts.length > 0) data.setUtcTime(gnrmcParts[0]);
if (gnrmcParts.length > 1) data.setStatus(gnrmcParts[1]);
if (gnrmcParts.length > 2) data.setLatitude(gnrmcParts[2]);
double latitude = GNSSCoordinateTool.gnssLatToDecimal(gnrmcParts[2]);
double longitude = GNSSCoordinateTool.gnssLonToDecimal(gnrmcParts[4]);
double[] bd09 = GNSSCoordinateTool.wgs84ToBd09(longitude, latitude);
if (gnrmcParts.length > 2) data.setLatitude(String.valueOf(bd09[0]));
if (gnrmcParts.length > 3) data.setLatDirection(gnrmcParts[3]);
if (gnrmcParts.length > 4) data.setLongitude(gnrmcParts[4]);
if (gnrmcParts.length > 4) data.setLongitude(String.valueOf(bd09[1]));
if (gnrmcParts.length > 5) data.setLonDirection(gnrmcParts[5]);
if (gnrmcParts.length > 6) data.setSpeedOverGround(gnrmcParts[6]);
if (gnrmcParts.length > 7) data.setCourseOverGround(gnrmcParts[7]);
@ -293,9 +301,14 @@ public class IotDataController {
String[] gnggaParts = gngga.split(":", -1);
if (gnggaParts.length > 0) data.setUtcTime(gnggaParts[0]);
if (gnggaParts.length > 1) data.setLatitude(gnggaParts[1]);
double latitude = GNSSCoordinateTool.gnssLatToDecimal(gnggaParts[1]);
double longitude = GNSSCoordinateTool.gnssLonToDecimal(gnggaParts[3]);
double[] bd09 = GNSSCoordinateTool.wgs84ToBd09(longitude, latitude);
if (gnggaParts.length > 1) data.setLatitude(String.valueOf(bd09[0]));
if (gnggaParts.length > 2) data.setLatDirection(gnggaParts[2]);
if (gnggaParts.length > 3) data.setLongitude(gnggaParts[3]);
if (gnggaParts.length > 3) data.setLongitude(String.valueOf(bd09[1]));
if (gnggaParts.length > 4) data.setLonDirection(gnggaParts[4]);
if (gnggaParts.length > 5) data.setQuality(gnggaParts[5]);
if (gnggaParts.length > 6) data.setNumSatellitesUsed(gnggaParts[6]);
@ -303,7 +316,6 @@ public class IotDataController {
if (gnggaParts.length > 8) data.setAltitude(gnggaParts[8]);
if (gnggaParts.length > 10) data.setGeoidSeparation(gnggaParts[10]);
}
/**
* 解析LBS或WiFi位置数据
*/
@ -311,13 +323,15 @@ public class IotDataController {
try {
String[] parts = dataStr.split(",");
if (parts.length == 3) {
data.setLatitude(parts[0]);
data.setLongitude(parts[1]);
double[] bd09 = GNSSCoordinateTool.wgs84ToBd09(Double.parseDouble(parts[1]), Double.parseDouble(parts[0]));
data.setLatitude(String.valueOf(bd09[1]));
data.setLongitude(String.valueOf(bd09[0]));
data.setAccuracy(parts[2]);
data.setPositionSource(source);
} else if (parts.length == 2) {
data.setLatitude(parts[0]);
data.setLongitude(parts[1]);
double[] bd09 = GNSSCoordinateTool.wgs84ToBd09(Double.parseDouble(parts[1]), Double.parseDouble(parts[0]));
data.setLatitude(String.valueOf(bd09[1]));
data.setLongitude(String.valueOf(bd09[0]));
data.setPositionSource(source);
} else {
logger.warn("{}数据格式不正确,部分不足: {}", source, dataStr);