package zhuye; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; /** * 自定义坐标点类(包含高程数据) */ public class Coordinate { public static boolean isStartSaveGngga=false; public static boolean isStartSaveGngga() { return isStartSaveGngga; } public static void setStartSaveGngga(boolean isStartSaveGngga) { Coordinate.isStartSaveGngga = isStartSaveGngga; } private String latitude; // 纬度(度分格式) private String latDirection; // 纬度方向 private String longitude; // 经度(度分格式) private String lonDirection; // 经度方向 private double elevation; // 海拔高度(米)- 新增属性 public static List coordinates = new ArrayList<>(); // 推荐使用ArrayList // 原有构造函数(保持向后兼容) public Coordinate(String latitude, String latDirection, String longitude, String lonDirection) { this.latitude = latitude; this.latDirection = latDirection; this.longitude = longitude; this.lonDirection = lonDirection; this.elevation = 0.0; // 默认海拔为0 } // 新增构造函数(包含海拔高度) public Coordinate(String latitude, String latDirection, String longitude, String lonDirection, double elevation) { this.latitude = latitude; this.latDirection = latDirection; this.longitude = longitude; this.lonDirection = lonDirection; this.elevation = elevation; } // Getter方法 public String getLatitude() { return latitude; } public String getLatDirection() { return latDirection; } public String getLongitude() { return longitude; } public String getLonDirection() { return lonDirection; } public double getElevation() { return elevation; } // 新增getter @Override public String toString() { return latitude + "," + latDirection + "," + longitude + "," + lonDirection + "," + String.format("%.2f", elevation); } // 如果需要去重,重写equals和hashCode @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Coordinate that = (Coordinate) obj; return Objects.equals(latitude, that.latitude) && Objects.equals(latDirection, that.latDirection) && Objects.equals(longitude, that.longitude) && Objects.equals(lonDirection, that.lonDirection) && Math.abs(this.elevation - that.elevation) < 0.01; // 考虑浮点数精度 } @Override public int hashCode() { return Objects.hash(latitude, latDirection, longitude, lonDirection, elevation); } /** * 解析GNGGA数据返回Coordinate对象列表(增强版,包含高程数据) */ public static void parseGNGGAToCoordinateList(String gnggaData) { if(isStartSaveGngga) { String[] records = gnggaData.split("\\$GNGGA"); for (String record : records) { try { String trimmedRecord = record.trim(); if (trimmedRecord.isEmpty()) continue; if (!trimmedRecord.startsWith(",")) { trimmedRecord = "," + trimmedRecord; } String[] fields = trimmedRecord.split(","); if (fields.length < 10) { // 检查字段数量,需要包含高程字段 continue; } // 检查定位质量 String fixQualityStr = fields[6]; if (fixQualityStr.isEmpty()) continue; int fixQuality; try { fixQuality = Integer.parseInt(fixQualityStr); } catch (NumberFormatException e) { continue; } if (fixQuality != 4) continue; // 提取坐标数据 String latitudeStr = fields[2]; String latDirection = fields[3]; String longitudeStr = fields[4]; String lonDirection = fields[5]; // 提取海拔高度(第10个字段,索引9) double elevation = 0.0; try { String elevationStr = fields[9]; if (elevationStr != null && !elevationStr.isEmpty()) { elevation = Double.parseDouble(elevationStr); } } catch (NumberFormatException e) { // 高程解析失败,使用默认值0 System.err.println("高程解析失败,使用默认值0: " + fields[9]); } if (latitudeStr.isEmpty() || longitudeStr.isEmpty() || latDirection.isEmpty() || lonDirection.isEmpty()) { continue; } // 创建Coordinate对象并添加到列表(包含高程数据) Coordinate coord = new Coordinate(latitudeStr, latDirection, longitudeStr, lonDirection, elevation); coordinates.add(coord); } catch (Exception e) { System.err.println("解析GNGGA记录失败: " + record); } } } } /** * 从根目录的GNGGA.txt文件加载数据并解析保存到coordinates集合中 * * @return 成功加载的坐标点数量 */ public static int loadFromGNGGAFile() { return loadFromGNGGAFile("GNGGA.txt"); } /** * 从指定文件路径加载GNGGA数据并解析保存到coordinates集合中 * * @param filePath 文件路径 * @return 成功加载的坐标点数量 */ public static int loadFromGNGGAFile(String filePath) { int loadedCount = 0; coordinates.clear(); // 清空现有数据 try { File file = new File(filePath); // 如果文件不存在,尝试在用户当前目录下查找 if (!file.exists()) { file = new File(System.getProperty("user.dir") + File.separator + filePath); } // 如果还是不存在,尝试在类路径中查找 if (!file.exists()) { System.err.println("文件未找到: " + filePath); return 0; } BufferedReader reader = new BufferedReader(new FileReader(file)); String line; StringBuilder gnggaData = new StringBuilder(); System.out.println("开始读取GNGGA文件: " + file.getAbsolutePath()); while ((line = reader.readLine()) != null) { // 清理数据:移除多余的空格和换行 line = line.trim(); if (line.isEmpty()) continue; // 如果行包含$GNGGA,则添加到数据中 if (line.contains("$GNGGA")) { gnggaData.append(line); } } reader.close(); // 解析GNGGA数据 if (gnggaData.length() > 0) { parseGNGGAToCoordinateList(gnggaData.toString()); loadedCount = coordinates.size(); System.out.println("成功加载 " + loadedCount + " 个坐标点"); // 输出统计信息 if (loadedCount > 0) { double[] elevationRange = getElevationRange(); double avgElevation = getAverageElevation(); System.out.println("海拔统计: 范围=" + String.format("%.2f", elevationRange[0]) + " - " + String.format("%.2f", elevationRange[1]) + "米, 平均=" + String.format("%.2f", avgElevation) + "米"); } } else { System.out.println("文件中未找到有效的GNGGA数据"); } } catch (IOException e) { System.err.println("读取GNGGA文件时发生错误: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { System.err.println("处理GNGGA数据时发生错误: " + e.getMessage()); e.printStackTrace(); } return loadedCount; } /** * 获取所有坐标点的平均海拔高度 */ public static double getAverageElevation() { if (coordinates.isEmpty()) { return 0.0; } double sum = 0.0; for (Coordinate coord : coordinates) { sum += coord.getElevation(); } return sum / coordinates.size(); } /** * 获取海拔高度范围 */ public static double[] getElevationRange() { if (coordinates.isEmpty()) { return new double[]{0.0, 0.0}; } double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; for (Coordinate coord : coordinates) { double elev = coord.getElevation(); if (elev < min) min = elev; if (elev > max) max = elev; } return new double[]{min, max}; } /** * 根据海拔高度过滤坐标点 */ public static List filterByElevation(double minElevation, double maxElevation) { List filtered = new ArrayList<>(); for (Coordinate coord : coordinates) { double elev = coord.getElevation(); if (elev >= minElevation && elev <= maxElevation) { filtered.add(coord); } } return filtered; } }