张世豪
2025-12-01 d23f280e37080cb9b5934350cc0fafb2c68421d5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
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<Coordinate> 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<Coordinate> filterByElevation(double minElevation, double maxElevation) {
        List<Coordinate> filtered = new ArrayList<>();
        for (Coordinate coord : coordinates) {
            double elev = coord.getElevation();
            if (elev >= minElevation && elev <= maxElevation) {
                filtered.add(coord);
            }
        }
        return filtered;
    }   
 
 
}