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;
|
}
|
|
|
}
|