package publicway; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class Gpstoxuzuobiao { private static final double METERS_PER_DEGREE_LAT = 111320.0d; // 缓存基准站坐标 private static double cachedBaseLat = 0.0; private static double cachedBaseLon = 0.0; private static boolean baseStationLoaded = false; /** * 解析GNGGA数据并转换为XY坐标 * @param gnggaData $GNGGA数据 * @return double[]{x, y} 相对坐标,如果解析失败或无基站数据返回null */ public static double[] processGNGGAToXY(String gnggaData) { ensureBaseStationLoaded(); if (!baseStationLoaded) { return null; } return processGNGGAToXY(gnggaData, cachedBaseLat, cachedBaseLon); } /** * 解析GNGGA数据并转换为XY坐标 * @param gnggaData $GNGGA数据 * @param baseLat 基准站纬度 * @param baseLon 基准站经度 * @return double[]{x, y} 相对坐标 */ public static double[] processGNGGAToXY(String gnggaData, double baseLat, double baseLon) { if (gnggaData == null || !gnggaData.contains("$GNGGA")) { return null; } // 简单的解析逻辑,提取经纬度 // 格式: $GNGGA,hhmmss.ss,lat,latDir,lon,lonDir,quality,sats,hdop,alt,units,sep,units,age,refID*cs String[] parts = gnggaData.split(","); // 找到$GNGGA的位置 int index = -1; for(int i=0; i= parts.length) { return null; } String latStr = parts[index + 2]; String latDir = parts[index + 3]; String lonStr = parts[index + 4]; String lonDir = parts[index + 5]; if (latStr.isEmpty() || lonStr.isEmpty()) { return null; } double lat = parseDMToDecimal(latStr, latDir); double lon = parseDMToDecimal(lonStr, lonDir); return convertLatLonToLocal(lat, lon, baseLat, baseLon); } /** * 将度分格式(DMM)转换为十进制格式(DD) * @param dmm 度分格式字符串 (e.g. "3015.1234") * @param direction 方向 (N/S/E/W) * @return 十进制经纬度 */ public static double parseDMToDecimal(String dmm, String direction) { if (dmm == null || dmm.isEmpty()) { return 0.0; } try { double val = Double.parseDouble(dmm); int degrees = (int) (val / 100); double minutes = val - degrees * 100; double decimal = degrees + minutes / 60.0; if (direction != null && (direction.equalsIgnoreCase("S") || direction.equalsIgnoreCase("W"))) { decimal = -decimal; } return decimal; } catch (NumberFormatException e) { return 0.0; } } /** * 将经纬度转换为相对坐标(XY) * @param lat 目标纬度 * @param lon 目标经度 * @param baseLat 基准站纬度 * @param baseLon 基准站经度 * @return double[]{x, y} (单位: 米) */ public static double[] convertLatLonToLocal(double lat, double lon, double baseLat, double baseLon) { double deltaLat = lat - baseLat; double deltaLon = lon - baseLon; double meanLatRad = Math.toRadians((baseLat + lat) / 2.0); double eastMeters = deltaLon * METERS_PER_DEGREE_LAT * Math.cos(meanLatRad); double northMeters = deltaLat * METERS_PER_DEGREE_LAT; return new double[]{eastMeters, northMeters}; } private static void ensureBaseStationLoaded() { if (baseStationLoaded) return; Properties props = new Properties(); try (FileInputStream input = new FileInputStream("basestation.properties")) { props.load(input); String coords = props.getProperty("installationCoordinates"); if (coords != null && !coords.isEmpty() && !"-1".equals(coords)) { String[] parts = coords.split(","); if (parts.length >= 4) { cachedBaseLat = parseDMToDecimal(parts[0], parts[1]); cachedBaseLon = parseDMToDecimal(parts[2], parts[3]); baseStationLoaded = true; } } } catch (IOException e) { // ignore } } /** * 重新加载基准站信息 */ public static void reloadBaseStation() { baseStationLoaded = false; ensureBaseStationLoaded(); } }