| | |
| | | |
| | | import zhangaiwu.Obstacledge; |
| | | import zhuye.Shouye; |
| | | import zhuye.Coordinate; |
| | | import bianjie.bianjieguihua2; |
| | | |
| | | /** |
| | | * 障碍物管理页面 - UI优化版 |
| | |
| | | actionPanel.setLayout(new BoxLayout(actionPanel, BoxLayout.X_AXIS)); |
| | | actionPanel.setOpaque(false); |
| | | |
| | | JButton generateBtn = createStyledButton("重新生成坐标", PRIMARY_COLOR, true); |
| | | generateBtn.addActionListener(e -> generateObstacleCoordinates(obstacle, xyArea)); |
| | | // 对于圆形障碍物,不显示"重新生成坐标"按钮,只显示预览按钮 |
| | | Obstacledge.ObstacleShape shape = obstacle.getShape(); |
| | | boolean isCircle = (shape == Obstacledge.ObstacleShape.CIRCLE); |
| | | |
| | | if (!isCircle) { |
| | | // 只有非圆形障碍物才显示"重新生成坐标"按钮 |
| | | JButton generateBtn = createStyledButton("重新生成坐标", PRIMARY_COLOR, true); |
| | | generateBtn.addActionListener(e -> generateObstacleCoordinates(obstacle, xyArea)); |
| | | actionPanel.add(generateBtn); |
| | | actionPanel.add(Box.createHorizontalStrut(10)); |
| | | } |
| | | |
| | | JButton previewBtn = createStyledButton("预览", TEXT_SECONDARY, false); |
| | | previewBtn.setPreferredSize(new Dimension(70, 36)); // 稍微窄一点 |
| | | previewBtn.addActionListener(e -> previewObstacle(obstacle)); |
| | | |
| | | actionPanel.add(generateBtn); |
| | | actionPanel.add(Box.createHorizontalStrut(10)); |
| | | actionPanel.add(previewBtn); |
| | | |
| | | card.add(actionPanel); |
| | |
| | | return; |
| | | } |
| | | |
| | | double baseLat = parseDMToDecimal(baseParts[0].trim(), baseParts[1].trim()); |
| | | double baseLon = parseDMToDecimal(baseParts[2].trim(), baseParts[3].trim()); |
| | | Obstacledge.ObstacleShape shape = obstacle.getShape(); |
| | | List<Obstacledge.XYCoordinate> xyCoords; |
| | | |
| | | List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>(); |
| | | for (int i = 0; i < originalCoordsList.size(); i += 2) { |
| | | if (i + 1 >= originalCoordsList.size()) break; |
| | | double lat = originalCoordsList.get(i).toDecimalDegree(); |
| | | double lon = originalCoordsList.get(i + 1).toDecimalDegree(); |
| | | |
| | | if (Double.isFinite(lat) && Double.isFinite(lon)) { |
| | | double[] localXY = convertLatLonToLocal(lat, lon, baseLat, baseLon); |
| | | xyCoords.add(new Obstacledge.XYCoordinate(localXY[0], localXY[1])); |
| | | } |
| | | // 根据障碍物形状调用不同的算法 |
| | | if (shape == Obstacledge.ObstacleShape.POLYGON) { |
| | | // 多边形:使用 bianjieguihua2 算法 |
| | | xyCoords = generatePolygonCoordinates(originalCoordsList, baseStation); |
| | | } else if (shape == Obstacledge.ObstacleShape.CIRCLE) { |
| | | // 圆形:使用简单的坐标转换(保持原有逻辑) |
| | | xyCoords = generateCircleCoordinates(originalCoordsList, baseStation); |
| | | } else { |
| | | JOptionPane.showMessageDialog(this, "未知的障碍物形状", "错误", JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | if (xyCoords.isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, "坐标转换失败", "错误", JOptionPane.ERROR_MESSAGE); |
| | | if (xyCoords == null || xyCoords.isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, "坐标生成失败", "错误", JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 使用 bianjieguihua2 算法生成多边形坐标 |
| | | */ |
| | | private List<Obstacledge.XYCoordinate> generatePolygonCoordinates( |
| | | List<Obstacledge.DMCoordinate> originalCoordsList, String baseStation) { |
| | | |
| | | // 保存当前的 Coordinate.coordinates |
| | | List<Coordinate> savedCoordinates = new ArrayList<>(Coordinate.coordinates); |
| | | |
| | | try { |
| | | // 将障碍物的原始坐标转换为 Coordinate 对象列表 |
| | | List<Coordinate> coordinateList = new ArrayList<>(); |
| | | for (int i = 0; i < originalCoordsList.size(); i += 2) { |
| | | if (i + 1 >= originalCoordsList.size()) break; |
| | | |
| | | Obstacledge.DMCoordinate latCoord = originalCoordsList.get(i); |
| | | Obstacledge.DMCoordinate lonCoord = originalCoordsList.get(i + 1); |
| | | |
| | | // 转换为 Coordinate 对象 |
| | | // DMCoordinate 的 degreeMinute 是度分格式(如 2324.200273 表示 23度24.200273分) |
| | | // 需要格式化为字符串,保持度分格式 |
| | | double latDM = latCoord.getDegreeMinute(); |
| | | double lonDM = lonCoord.getDegreeMinute(); |
| | | |
| | | // 格式化度分格式:确保整数部分至少2位(度),小数部分是分 |
| | | String latStr = formatDegreeMinute(latDM); |
| | | String lonStr = formatDegreeMinute(lonDM); |
| | | char latDir = latCoord.getDirection(); |
| | | char lonDir = lonCoord.getDirection(); |
| | | |
| | | Coordinate coord = new Coordinate( |
| | | latStr, |
| | | String.valueOf(latDir), |
| | | lonStr, |
| | | String.valueOf(lonDir), |
| | | 0.0 // 高程数据,障碍物可能没有,设为0 |
| | | ); |
| | | coordinateList.add(coord); |
| | | } |
| | | |
| | | if (coordinateList.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // 设置到全局坐标列表 |
| | | Coordinate.coordinates.clear(); |
| | | Coordinate.coordinates.addAll(coordinateList); |
| | | |
| | | // 调用 bianjieguihua2 算法生成优化后的多边形坐标 |
| | | String optimizedCoordsStr = bianjieguihua2.processCoordinateListAuto(baseStation); |
| | | |
| | | if (optimizedCoordsStr == null || optimizedCoordsStr.trim().isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // 解析返回的坐标字符串,格式:"X0,Y0;X1,Y1;X2,Y2;..." |
| | | List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>(); |
| | | String[] pointStrings = optimizedCoordsStr.split(";"); |
| | | for (String pointStr : pointStrings) { |
| | | pointStr = pointStr.trim(); |
| | | if (pointStr.isEmpty()) continue; |
| | | |
| | | String[] parts = pointStr.split(","); |
| | | if (parts.length >= 2) { |
| | | try { |
| | | double x = Double.parseDouble(parts[0].trim()); |
| | | double y = Double.parseDouble(parts[1].trim()); |
| | | if (Double.isFinite(x) && Double.isFinite(y)) { |
| | | xyCoords.add(new Obstacledge.XYCoordinate(x, y)); |
| | | } |
| | | } catch (NumberFormatException e) { |
| | | // 跳过无效的坐标点 |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | return xyCoords; |
| | | |
| | | } finally { |
| | | // 恢复原来的坐标列表 |
| | | Coordinate.coordinates.clear(); |
| | | Coordinate.coordinates.addAll(savedCoordinates); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 格式化度分格式坐标 |
| | | * @param degreeMinute 度分值,如 2324.200273 表示 23度24.200273分 |
| | | * @return 格式化的字符串 |
| | | */ |
| | | private String formatDegreeMinute(double degreeMinute) { |
| | | // 度分格式:整数部分是度,小数部分是分 |
| | | // 例如 2324.200273 -> "2324.200273" |
| | | return String.format("%.6f", degreeMinute); |
| | | } |
| | | |
| | | /** |
| | | * 生成圆形坐标(保持原有简单转换逻辑) |
| | | */ |
| | | private List<Obstacledge.XYCoordinate> generateCircleCoordinates( |
| | | List<Obstacledge.DMCoordinate> originalCoordsList, String baseStation) { |
| | | |
| | | String[] baseParts = baseStation.split(","); |
| | | if (baseParts.length < 4) { |
| | | return null; |
| | | } |
| | | |
| | | double baseLat = parseDMToDecimal(baseParts[0].trim(), baseParts[1].trim()); |
| | | double baseLon = parseDMToDecimal(baseParts[2].trim(), baseParts[3].trim()); |
| | | |
| | | List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>(); |
| | | for (int i = 0; i < originalCoordsList.size(); i += 2) { |
| | | if (i + 1 >= originalCoordsList.size()) break; |
| | | double lat = originalCoordsList.get(i).toDecimalDegree(); |
| | | double lon = originalCoordsList.get(i + 1).toDecimalDegree(); |
| | | |
| | | if (Double.isFinite(lat) && Double.isFinite(lon)) { |
| | | double[] localXY = convertLatLonToLocal(lat, lon, baseLat, baseLon); |
| | | xyCoords.add(new Obstacledge.XYCoordinate(localXY[0], localXY[1])); |
| | | } |
| | | } |
| | | |
| | | return xyCoords; |
| | | } |
| | | |
| | | private void saveObstacleUpdate(Obstacledge.Obstacle obstacle, JTextArea coordArea) { |
| | | String landNumber = dikuai.getLandNumber(); |
| | | try { |