问题修改
This commit is contained in:
parent
26eb4c75d7
commit
85b8427fb6
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue