package bianjie; import java.util.ArrayList; import java.util.List; import zhuye.Coordinate; public class bianjieguihua2 { /** * 优化边界XY坐标字符串 * * @param boundaryXYString 边界XY坐标字符串,格式:"X0,Y0;X1,Y1;X2,Y2;..." * @return 优化后的边界坐标字符串,格式:"X0,Y0;X1,Y1;X2,Y2;..." */ public static String optimizeBoundaryXYString(String boundaryXYString) { try { // 检查输入数据 if (boundaryXYString == null || boundaryXYString.trim().isEmpty()) { throw new IllegalArgumentException("边界坐标字符串不能为空"); } // 解析XY坐标字符串 List localCoordinates = parseXYString(boundaryXYString); if (localCoordinates == null || localCoordinates.isEmpty()) { throw new IllegalArgumentException("无法解析边界坐标字符串"); } // 三角形小区域特殊处理,避免过度插值导致点数扩增 if (localCoordinates.size() == 3) { double triangleArea = calculatePolygonArea(localCoordinates); double trianglePerimeter = calculatePerimeter(localCoordinates); System.out.println("检测到三角形边界,面积=" + String.format("%.2f", triangleArea) + "m², 周长=" + String.format("%.2f", trianglePerimeter) + "m"); if (triangleArea < 100.0 || trianglePerimeter < 30.0) { System.out.println("小三角形,跳过插值优化"); BoundaryAlgorithm.Coordinate firstPoint = localCoordinates.get(0); List trianglePoints = new ArrayList<>(localCoordinates); trianglePoints.add(new BoundaryAlgorithm.Coordinate( firstPoint.x, firstPoint.y, firstPoint.lat, firstPoint.lon)); return convertBoundaryPointsToString(trianglePoints); } } // 创建算法实例 BoundaryAlgorithm algorithm = new BoundaryAlgorithm(); // 自动场景分析(基于XY坐标,无高程数据) BoundaryAlgorithm.SceneAnalysis sceneAnalysis = analyzeSceneFromXYCoordinates(localCoordinates); System.out.println("自动场景分析结果:"); System.out.println(sceneAnalysis.toString()); // 根据场景分析结果获取参数 BoundaryAlgorithm.BoundaryParameters params = algorithm.getParametersForPreset(sceneAnalysis.suggestedPreset); System.out.println("自动选择的参数: 间隔=" + params.interval + "米, 角度阈值=" + params.angleThreshold + "度"); // 使用优化算法处理边界 List optimizedPoints = algorithm.optimizeBoundaryPointsAdvanced(localCoordinates, params); // 质量评估 BoundaryAlgorithm.BoundaryQuality boundaryQuality = algorithm.evaluateBoundaryQuality(optimizedPoints); System.out.println("边界质量评估结果:"); System.out.println(boundaryQuality.toString()); // 转换为输出字符串格式 return convertBoundaryPointsToString(optimizedPoints); } catch (Exception e) { throw new RuntimeException("优化边界坐标字符串时发生错误: " + e.getMessage(), e); } } /** * 解析XY坐标字符串为Coordinate列表 * * @param xyString XY坐标字符串,格式:"X0,Y0;X1,Y1;X2,Y2;..." * @return Coordinate列表 */ private static List parseXYString(String xyString) { List coordinates = new ArrayList<>(); if (xyString == null || xyString.trim().isEmpty()) { return coordinates; } String[] points = xyString.split(";"); for (String point : points) { point = point.trim(); if (point.isEmpty()) { continue; } String[] parts = point.split(","); if (parts.length >= 2) { try { double x = Double.parseDouble(parts[0].trim()); double y = Double.parseDouble(parts[1].trim()); // lat和lon设为0,因为我们只需要XY坐标 coordinates.add(new BoundaryAlgorithm.Coordinate(x, y, 0.0, 0.0)); } catch (NumberFormatException e) { System.err.println("解析坐标失败: " + point + ", 错误: " + e.getMessage()); } } } return coordinates; } /** * 基于XY坐标进行场景分析(无高程数据) */ private static BoundaryAlgorithm.SceneAnalysis analyzeSceneFromXYCoordinates( List localCoords) { BoundaryAlgorithm.SceneAnalysis analysis = new BoundaryAlgorithm.SceneAnalysis(); if (localCoords.size() < 3) { analysis.suggestedPreset = "复杂小区域"; return analysis; } // 计算基本统计信息 calculateBasicStatisticsFromCoordinates(localCoords, analysis); // 计算边界复杂度 calculateBoundaryComplexityFromCoordinates(localCoords, analysis); // 无高程数据,设置为0 analysis.elevationRange = 0; // 自动选择预设场景(不考虑高程因素) selectPresetAutomaticallyFromXYCoordinates(analysis); return analysis; } /** * 从XY坐标自动选择预设场景(不考虑高程因素) */ private static void selectPresetAutomaticallyFromXYCoordinates(BoundaryAlgorithm.SceneAnalysis analysis) { // 决策逻辑基于面积和复杂度 double areaWeight = 0.6; double complexityWeight = 0.4; // 计算综合得分 double score = 0; // 面积因素:面积越大,越适合大间隔 double areaScore = Math.min(1.0, analysis.area / 1000.0); // 1000平方米为基准 score += areaScore * areaWeight; // 复杂度因素:复杂度越高,越需要小间隔 double complexityScore = analysis.complexity; score += complexityScore * complexityWeight; // 根据得分选择预设 if (score < 0.3) { analysis.suggestedPreset = "平坦大区域"; } else if (score < 0.6) { analysis.suggestedPreset = "常规区域"; } else { analysis.suggestedPreset = "复杂小区域"; } System.out.println("自动场景选择得分: " + String.format("%.2f", score) + " -> " + analysis.suggestedPreset); } /** * 自动处理Coordinate列表并生成优化后的边界坐标(无需传入间隔和角度阈值) * * @param coordinates Coordinate对象列表 * @param baseStation 基准站坐标,格式:"纬度,N/S,经度,E/W" 例如:"2324.194945,N,11330.938547,E" * @return 优化后的边界坐标字符串,格式:"X0,Y0;X1,Y1;X2,Y2;..." */ public static String processCoordinateListAuto(String baseStation) { List coordinates =Coordinate.coordinates; try { // 检查输入数据 if (coordinates == null || coordinates.isEmpty()) { throw new IllegalArgumentException("坐标列表不能为空"); } if (baseStation == null || baseStation.trim().isEmpty()) { throw new IllegalArgumentException("基站坐标不能为空"); } // 解析基准站坐标 String[] baseParts = baseStation.split(","); if (baseParts.length != 4) { throw new IllegalArgumentException("基准站坐标格式错误,应为: 纬度,N/S,经度,E/W"); } double baseLat = parseDMToDecimal(baseParts[0], baseParts[1]); double baseLon = parseDMToDecimal(baseParts[2], baseParts[3]); // 将Coordinate列表转换为局部坐标系坐标 List localCoordinates = convertToLocalCoordinates(coordinates, baseLat, baseLon); // 三角形小区域特殊处理,避免过度插值导致点数扩增 if (localCoordinates.size() == 3) { double triangleArea = calculatePolygonArea(localCoordinates); double trianglePerimeter = calculatePerimeter(localCoordinates); System.out.println("检测到三角形边界,面积=" + String.format("%.2f", triangleArea) + "m², 周长=" + String.format("%.2f", trianglePerimeter) + "m"); if (triangleArea < 100.0 || trianglePerimeter < 30.0) { System.out.println("小三角形,跳过插值优化"); BoundaryAlgorithm.Coordinate firstPoint = localCoordinates.get(0); List trianglePoints = new ArrayList<>(localCoordinates); trianglePoints.add(new BoundaryAlgorithm.Coordinate( firstPoint.x, firstPoint.y, firstPoint.lat, firstPoint.lon)); return convertBoundaryPointsToString(trianglePoints); } } // 创建算法实例 BoundaryAlgorithm algorithm = new BoundaryAlgorithm(); // 自动场景分析(增强版,使用高程数据) BoundaryAlgorithm.SceneAnalysis sceneAnalysis = analyzeSceneFromCoordinates(localCoordinates, coordinates); System.out.println("自动场景分析结果:"); System.out.println(sceneAnalysis.toString()); // 根据场景分析结果获取参数 BoundaryAlgorithm.BoundaryParameters params = algorithm.getParametersForPreset(sceneAnalysis.suggestedPreset); System.out.println("自动选择的参数: 间隔=" + params.interval + "米, 角度阈值=" + params.angleThreshold + "度"); // 使用优化算法处理边界 List optimizedPoints = algorithm.optimizeBoundaryPointsAdvanced(localCoordinates, params); // 质量评估 BoundaryAlgorithm.BoundaryQuality boundaryQuality = algorithm.evaluateBoundaryQuality(optimizedPoints); System.out.println("边界质量评估结果:"); System.out.println(boundaryQuality.toString()); // 转换为输出字符串格式 return convertBoundaryPointsToString(optimizedPoints); } catch (Exception e) { throw new RuntimeException("自动处理坐标列表时发生错误: " + e.getMessage(), e); } } /** * 基于坐标列表进行场景分析(增强版,使用高程数据) */ private static BoundaryAlgorithm.SceneAnalysis analyzeSceneFromCoordinates( List localCoords, List originalCoords) { BoundaryAlgorithm.SceneAnalysis analysis = new BoundaryAlgorithm.SceneAnalysis(); if (localCoords.size() < 3) { analysis.suggestedPreset = "复杂小区域"; return analysis; } // 计算基本统计信息 calculateBasicStatisticsFromCoordinates(localCoords, analysis); // 计算边界复杂度 calculateBoundaryComplexityFromCoordinates(localCoords, analysis); // 计算高程变化(使用原始坐标的高程数据) calculateElevationStatistics(originalCoords, analysis); // 自动选择预设场景(增强版,考虑高程因素) selectPresetAutomaticallyFromCoordinates(analysis); return analysis; } /** * 从坐标计算基本统计信息 */ private static void calculateBasicStatisticsFromCoordinates( List points, BoundaryAlgorithm.SceneAnalysis analysis) { // 计算总距离 analysis.totalDistance = 0; for (int i = 1; i < points.size(); i++) { analysis.totalDistance += calculateDistance(points.get(i-1), points.get(i)); } // 计算面积 analysis.area = calculatePolygonArea(points); // 计算平均速度 (假设时间间隔为1秒) if (points.size() > 1) { analysis.avgSpeed = analysis.totalDistance / (points.size() - 1); } else { analysis.avgSpeed = 0; } } /** * 计算高程统计信息 */ private static void calculateElevationStatistics(List coordinates, BoundaryAlgorithm.SceneAnalysis analysis) { if (coordinates == null || coordinates.isEmpty()) { analysis.elevationRange = 0; return; } double minElevation = Double.MAX_VALUE; double maxElevation = Double.MIN_VALUE; for (Coordinate coord : coordinates) { double elevation = coord.getElevation(); if (elevation < minElevation) minElevation = elevation; if (elevation > maxElevation) maxElevation = elevation; } analysis.elevationRange = maxElevation - minElevation; // 计算平均高程 double sumElevation = 0; for (Coordinate coord : coordinates) { sumElevation += coord.getElevation(); } double avgElevation = sumElevation / coordinates.size(); System.out.println("高程统计: 范围=" + String.format("%.2f", analysis.elevationRange) + "米, 平均=" + String.format("%.2f", avgElevation) + "米"); } /** * 从坐标计算边界复杂度 */ private static void calculateBoundaryComplexityFromCoordinates( List points, BoundaryAlgorithm.SceneAnalysis analysis) { if (points.size() < 3) { analysis.complexity = 0; return; } double totalAngleChange = 0; int angleCount = 0; for (int i = 1; i < points.size() - 1; i++) { double angleChange = Math.abs(calculateAngleChange( points.get(i-1), points.get(i), points.get(i+1) )); totalAngleChange += angleChange; angleCount++; } // 复杂度基于角度变化和边界长度 double avgAngleChange = angleCount > 0 ? totalAngleChange / angleCount : 0; // 标准化复杂度 (0-1范围) analysis.complexity = Math.min(1.0, avgAngleChange / 45.0); // 45度作为高复杂度阈值 } /** * 从坐标自动选择预设场景(增强版,考虑高程因素) */ private static void selectPresetAutomaticallyFromCoordinates(BoundaryAlgorithm.SceneAnalysis analysis) { // 决策逻辑基于多个因素 double areaWeight = 0.4; double complexityWeight = 0.3; double elevationWeight = 0.3; // 增加高程权重 // 计算综合得分 double score = 0; // 面积因素:面积越大,越适合大间隔 double areaScore = Math.min(1.0, analysis.area / 1000.0); // 1000平方米为基准 score += areaScore * areaWeight; // 复杂度因素:复杂度越高,越需要小间隔 double complexityScore = analysis.complexity; score += complexityScore * complexityWeight; // 高程因素:高程变化越大,越需要精细处理 double elevationScore = Math.min(1.0, analysis.elevationRange / 20.0); // 20米变化为基准 score += elevationScore * elevationWeight; // 根据得分选择预设 if (score < 0.3) { analysis.suggestedPreset = "平坦大区域"; } else if (score < 0.6) { analysis.suggestedPreset = "常规区域"; } else { analysis.suggestedPreset = "复杂小区域"; } System.out.println("自动场景选择得分: " + String.format("%.2f", score) + " -> " + analysis.suggestedPreset); } /** * 计算两点间距离 */ private static double calculateDistance(BoundaryAlgorithm.Coordinate p1, BoundaryAlgorithm.Coordinate p2) { double dx = p2.x - p1.x; double dy = p2.y - p1.y; return Math.sqrt(dx * dx + dy * dy); } /** * 计算角度变化 */ private static double calculateAngleChange(BoundaryAlgorithm.Coordinate prev, BoundaryAlgorithm.Coordinate current, BoundaryAlgorithm.Coordinate next) { double angle1 = Math.atan2(current.y - prev.y, current.x - prev.x); double angle2 = Math.atan2(next.y - current.y, next.x - current.x); double angleChange = Math.toDegrees(angle2 - angle1); // 规范化角度到 [-180, 180] while (angleChange > 180) angleChange -= 360; while (angleChange < -180) angleChange += 360; return angleChange; } /** * 计算多边形面积 */ private static double calculatePolygonArea(List points) { if (points.size() < 3) return 0.0; double area = 0.0; int n = points.size(); for (int i = 0; i < n; i++) { BoundaryAlgorithm.Coordinate current = points.get(i); BoundaryAlgorithm.Coordinate next = points.get((i + 1) % n); area += (current.x * next.y - next.x * current.y); } return Math.abs(area) / 2.0; } private static double calculatePerimeter(List points) { if (points == null || points.size() != 3) { return 0.0; } double d1 = calculateDistance(points.get(0), points.get(1)); double d2 = calculateDistance(points.get(1), points.get(2)); double d3 = calculateDistance(points.get(2), points.get(0)); return d1 + d2 + d3; } // ============ 其他方法保持不变 ============ /** * 将度分格式坐标转换为十进制度格式 */ private static double parseDMToDecimal(String dmCoord, String direction) { try { if (dmCoord == null || dmCoord.isEmpty()) { return 0; } int dotIndex = dmCoord.indexOf('.'); if (dotIndex < 2) { return 0; } // 提取度部分和分部分 int degrees = Integer.parseInt(dmCoord.substring(0, dotIndex - 2)); double minutes = Double.parseDouble(dmCoord.substring(dotIndex - 2)); // 转换为十进制度 double decimal = degrees + minutes / 60.0; // 根据方向调整正负 if ("S".equals(direction) || "W".equals(direction)) { decimal = -decimal; } return decimal; } catch (Exception e) { throw new IllegalArgumentException("度分坐标解析错误: " + dmCoord, e); } } /** * 将Coordinate列表转换为局部坐标系坐标 */ private static List convertToLocalCoordinates( List coordinates, double baseLat, double baseLon) { List localCoords = new ArrayList<>(); for (Coordinate coord : coordinates) { try { // 解析度分格式坐标为十进制度 double lat = parseDMToDecimal(coord.getLatitude(), coord.getLatDirection()); double lon = parseDMToDecimal(coord.getLongitude(), coord.getLonDirection()); // 转换为局部坐标系 BoundaryAlgorithm.Coordinate localCoord = convertToLocalCoordinate(lat, lon, baseLat, baseLon); localCoords.add(localCoord); } catch (Exception e) { System.err.println("坐标转换失败: " + coord + ", 错误: " + e.getMessage()); } } return localCoords; } /** * 将经纬度坐标转换为局部坐标系 */ private static BoundaryAlgorithm.Coordinate convertToLocalCoordinate( double lat, double lon, double baseLat, double baseLon) { double earthRadius = 6371000; // 地球半径(米) // 计算北方向距离 double deltaLat = lat - baseLat; double northDistance = deltaLat * Math.PI / 180.0 * earthRadius; // 计算东方向距离(考虑纬度对经度距离的影响) double deltaLon = lon - baseLon; double eastDistance = deltaLon * Math.PI / 180.0 * earthRadius * Math.cos(baseLat * Math.PI / 180.0); return new BoundaryAlgorithm.Coordinate(eastDistance, northDistance, lat, lon); } /** * 将边界点列表转换为字符串格式 */ private static String convertBoundaryPointsToString(List points) { if (points == null || points.isEmpty()) { return ""; } StringBuilder coordinatesBuilder = new StringBuilder(); for (int i = 0; i < points.size(); i++) { BoundaryAlgorithm.Coordinate point = points.get(i); coordinatesBuilder.append(String.format("%.2f,%.2f", point.x, point.y)); if (i < points.size() - 1) { coordinatesBuilder.append(";"); } } return coordinatesBuilder.toString(); } // // ============ 测试方法 ============ // // /** // * 测试方法 // */ // public static void main(String[] args) { // try { // // 创建测试Coordinate列表(包含高程数据) // int count = Coordinate.loadFromGNGGAFile(); // List coordinateList=Coordinate.coordinates; // // // 设置基准站坐标 // String baseStation = "3949.91202005,N,11616.85440851,E"; // // // 调用自动处理方法 // String result = bianjieguihua2.processCoordinateListAuto(coordinateList, baseStation); // // System.out.println("自动处理的边界点坐标结果: " + result); // // } catch (Exception e) { // System.err.println("处理失败: " + e.getMessage()); // e.printStackTrace(); // } // } }