From d709e6dad60398fd599900cf781d0dd1e8c37c1c Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期一, 01 十二月 2025 19:55:14 +0800
Subject: [PATCH] 20251201

---
 src/zhuye/MapRenderer.java |  289 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 284 insertions(+), 5 deletions(-)

diff --git a/src/zhuye/MapRenderer.java b/src/zhuye/MapRenderer.java
index 32049b4..aebc291 100644
--- a/src/zhuye/MapRenderer.java
+++ b/src/zhuye/MapRenderer.java
@@ -11,10 +11,13 @@
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Locale;
 import gecaoji.Device;
 import gecaoji.Gecaoji;
 import dikuai.Dikuaiguanli;
 import dikuai.Dikuai;
+import zhangaiwu.Obstacledraw;
+import zhangaiwu.Obstacledge;
 
 /**
  * 鍦板浘娓叉煋鍣� - 璐熻矗鍧愭爣绯荤粯鍒躲�佽鍥惧彉鎹㈢瓑鍔熻兘
@@ -43,6 +46,9 @@
     private Rectangle2D.Double boundaryBounds;
     private List<Point2D.Double> currentPlannedPath;
     private Rectangle2D.Double plannedPathBounds;
+    private List<Obstacledge.Obstacle> currentObstacles;
+    private Rectangle2D.Double obstacleBounds;
+    private String selectedObstacleName;
     private String boundaryName;
     private boolean boundaryPointsVisible;
     private String currentBoundaryLandNumber;
@@ -202,11 +208,16 @@
 
         boolean hasBoundary = currentBoundary != null && currentBoundary.size() >= 2;
         boolean hasPlannedPath = currentPlannedPath != null && currentPlannedPath.size() >= 2;
+        boolean hasObstacles = currentObstacles != null && !currentObstacles.isEmpty();
 
         if (hasBoundary) {
             drawCurrentBoundary(g2d);
         }
 
+        if (hasObstacles) {
+            Obstacledraw.drawObstacles(g2d, currentObstacles, scale, selectedObstacleName);
+        }
+
         if (hasPlannedPath) {
             drawCurrentPlannedPath(g2d);
         }
@@ -759,6 +770,264 @@
         currentBoundaryLandNumber = null;
     }
 
+    public void setCurrentObstacles(String obstaclesData, String landNumber) {
+        if (landNumber == null) {
+            clearObstacleData();
+            if (!hasRenderableBoundary() && !hasRenderablePlannedPath()) {
+                resetView();
+            } else {
+                visualizationPanel.repaint();
+            }
+            return;
+        }
+
+        List<Obstacledge.Obstacle> parsed = parseObstacles(obstaclesData, landNumber);
+        if (parsed.isEmpty()) {
+            clearObstacleData();
+            if (!hasRenderableBoundary() && !hasRenderablePlannedPath()) {
+                resetView();
+            } else {
+                visualizationPanel.repaint();
+            }
+            return;
+        }
+
+        currentObstacles = parsed;
+        obstacleBounds = convertObstacleBounds(Obstacledraw.getAllObstaclesBounds(parsed));
+        selectedObstacleName = null;
+
+        if (!hasRenderableBoundary() && !hasRenderablePlannedPath() && obstacleBounds != null) {
+            Rectangle2D.Double bounds = obstacleBounds;
+            SwingUtilities.invokeLater(() -> {
+                fitBoundsToView(bounds);
+                visualizationPanel.repaint();
+            });
+        } else {
+            visualizationPanel.repaint();
+        }
+    }
+
+    private void clearObstacleData() {
+        currentObstacles = null;
+        obstacleBounds = null;
+        selectedObstacleName = null;
+    }
+
+    private List<Obstacledge.Obstacle> parseObstacles(String obstaclesData, String landNumber) {
+        List<Obstacledge.Obstacle> obstacles = new ArrayList<>();
+        if (obstaclesData == null) {
+            return obstacles;
+        }
+
+        String normalized = stripInlineComment(obstaclesData.trim());
+        if (normalized.isEmpty() || "-1".equals(normalized)) {
+            return obstacles;
+        }
+
+        List<String> entries = splitObstacleEntries(normalized);
+        int defaultIndex = 1;
+
+        for (String entry : entries) {
+            String trimmedEntry = stripInlineComment(entry);
+            if (trimmedEntry.isEmpty()) {
+                continue;
+            }
+
+            String nameToken = null;
+            String shapeToken = null;
+            String coordsSection = trimmedEntry;
+
+            if (trimmedEntry.contains("::")) {
+                String[] parts = trimmedEntry.split("::", 3);
+                if (parts.length == 3) {
+                    nameToken = parts[0].trim();
+                    shapeToken = parts[1].trim();
+                    coordsSection = parts[2].trim();
+                }
+            } else if (trimmedEntry.contains("@")) {
+                String[] parts = trimmedEntry.split("@", 3);
+                if (parts.length == 3) {
+                    nameToken = parts[0].trim();
+                    shapeToken = parts[1].trim();
+                    coordsSection = parts[2].trim();
+                } else if (parts.length == 2) {
+                    shapeToken = parts[0].trim();
+                    coordsSection = parts[1].trim();
+                }
+            } else if (trimmedEntry.contains(":")) {
+                String[] parts = trimmedEntry.split(":", 3);
+                if (parts.length == 3) {
+                    nameToken = parts[0].trim();
+                    shapeToken = parts[1].trim();
+                    coordsSection = parts[2].trim();
+                } else if (parts.length == 2) {
+                    if (looksLikeShapeToken(parts[0])) {
+                        shapeToken = parts[0].trim();
+                        coordsSection = parts[1].trim();
+                    } else {
+                        nameToken = parts[0].trim();
+                        coordsSection = parts[1].trim();
+                    }
+                }
+            }
+
+            List<Obstacledge.XYCoordinate> xyCoordinates = parseObstacleCoordinates(coordsSection);
+            if (xyCoordinates.size() < 2) {
+                continue;
+            }
+
+            Obstacledge.ObstacleShape shape = resolveObstacleShape(shapeToken, xyCoordinates.size());
+            if (shape == null) {
+                continue;
+            }
+
+            String obstacleName = (nameToken != null && !nameToken.isEmpty())
+                    ? nameToken
+                    : "闅滅鐗�" + defaultIndex++;
+
+            Obstacledge.Obstacle obstacle = new Obstacledge.Obstacle(landNumber, obstacleName, shape);
+            obstacle.setXyCoordinates(new ArrayList<>(xyCoordinates));
+            populateDummyOriginalCoordinates(obstacle, xyCoordinates.size());
+
+            if (obstacle.isValid()) {
+                obstacles.add(obstacle);
+            }
+        }
+
+        return obstacles;
+    }
+
+    private boolean looksLikeShapeToken(String token) {
+        if (token == null) {
+            return false;
+        }
+        String normalized = token.trim().toLowerCase(Locale.ROOT);
+        return "circle".equals(normalized)
+                || "polygon".equals(normalized)
+                || "鍦嗗舰".equals(normalized)
+                || "澶氳竟褰�".equals(normalized)
+                || "0".equals(normalized)
+                || "1".equals(normalized);
+    }
+
+    private List<Obstacledge.XYCoordinate> parseObstacleCoordinates(String coordsSection) {
+        List<Obstacledge.XYCoordinate> coords = new ArrayList<>();
+        if (coordsSection == null) {
+            return coords;
+        }
+
+        String sanitized = stripInlineComment(coordsSection.trim());
+        if (sanitized.isEmpty() || "-1".equals(sanitized)) {
+            return coords;
+        }
+
+        String[] pairs = sanitized.split(";");
+        for (String pair : pairs) {
+            if (pair == null) {
+                continue;
+            }
+            String trimmed = stripInlineComment(pair.trim());
+            if (trimmed.isEmpty()) {
+                continue;
+            }
+            String[] parts = trimmed.split(",");
+            if (parts.length < 2) {
+                continue;
+            }
+            try {
+                double x = Double.parseDouble(parts[0].trim());
+                double y = Double.parseDouble(parts[1].trim());
+                coords.add(new Obstacledge.XYCoordinate(x, y));
+            } catch (NumberFormatException ignored) {
+                // Skip malformed coordinate pair
+            }
+        }
+
+        return coords;
+    }
+
+    private Obstacledge.ObstacleShape resolveObstacleShape(String shapeToken, int coordinateCount) {
+        if (shapeToken != null && !shapeToken.trim().isEmpty()) {
+            String normalized = shapeToken.trim().toLowerCase(Locale.ROOT);
+            if ("circle".equals(normalized) || "鍦嗗舰".equals(normalized) || "0".equals(normalized)) {
+                return Obstacledge.ObstacleShape.CIRCLE;
+            }
+            if ("polygon".equals(normalized) || "澶氳竟褰�".equals(normalized) || "1".equals(normalized)) {
+                return Obstacledge.ObstacleShape.POLYGON;
+            }
+        }
+
+        if (coordinateCount == 2) {
+            return Obstacledge.ObstacleShape.CIRCLE;
+        }
+        if (coordinateCount >= 3) {
+            return Obstacledge.ObstacleShape.POLYGON;
+        }
+        return null;
+    }
+
+    private void populateDummyOriginalCoordinates(Obstacledge.Obstacle obstacle, int xyCount) {
+        List<Obstacledge.DMCoordinate> dmCoordinates = new ArrayList<>();
+        int points = Math.max(1, xyCount);
+        for (int i = 0; i < points; i++) {
+            dmCoordinates.add(new Obstacledge.DMCoordinate(0.0, 'N'));
+            dmCoordinates.add(new Obstacledge.DMCoordinate(0.0, 'E'));
+        }
+        obstacle.setOriginalCoordinates(dmCoordinates);
+    }
+
+    private List<String> splitObstacleEntries(String data) {
+        List<String> entries = new ArrayList<>();
+        if (data.indexOf('|') >= 0) {
+            String[] parts = data.split("\\|");
+            for (String part : parts) {
+                if (part != null && !part.trim().isEmpty()) {
+                    entries.add(part.trim());
+                }
+            }
+        } else if (data.contains("\n")) {
+            String[] lines = data.split("\r?\n");
+            for (String line : lines) {
+                if (line != null && !line.trim().isEmpty()) {
+                    entries.add(line.trim());
+                }
+            }
+        } else {
+            entries.add(data);
+        }
+        return entries;
+    }
+
+    private String stripInlineComment(String text) {
+        if (text == null) {
+            return "";
+        }
+        int hashIndex = text.indexOf('#');
+        if (hashIndex >= 0) {
+            return text.substring(0, hashIndex).trim();
+        }
+        return text.trim();
+    }
+
+    private Rectangle2D.Double convertObstacleBounds(double[] bounds) {
+        if (bounds == null || bounds.length < 4) {
+            return null;
+        }
+        double minX = bounds[0];
+        double minY = bounds[1];
+        double maxX = bounds[2];
+        double maxY = bounds[3];
+        return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
+    }
+
+    private boolean hasRenderableBoundary() {
+        return currentBoundary != null && currentBoundary.size() >= 2;
+    }
+
+    private boolean hasRenderablePlannedPath() {
+        return currentPlannedPath != null && currentPlannedPath.size() >= 2;
+    }
+
     private void adjustViewAfterBoundaryReset() {
         if (plannedPathBounds != null) {
             Rectangle2D.Double bounds = plannedPathBounds;
@@ -766,16 +1035,26 @@
                 fitBoundsToView(bounds);
                 visualizationPanel.repaint();
             });
-        } else {
-            resetView();
+            return;
         }
+
+        if (obstacleBounds != null) {
+            Rectangle2D.Double bounds = obstacleBounds;
+            SwingUtilities.invokeLater(() -> {
+                fitBoundsToView(bounds);
+                visualizationPanel.repaint();
+            });
+            return;
+        }
+
+        resetView();
     }
 
     public void setCurrentPlannedPath(String plannedPath) {
         if (plannedPath == null) {
             currentPlannedPath = null;
             plannedPathBounds = null;
-            if (currentBoundary == null || currentBoundary.size() < 2) {
+            if (!hasRenderableBoundary()) {
                 resetView();
             } else {
                 visualizationPanel.repaint();
@@ -787,7 +1066,7 @@
         if (parsed.size() < 2) {
             currentPlannedPath = null;
             plannedPathBounds = null;
-            if (currentBoundary == null || currentBoundary.size() < 2) {
+            if (!hasRenderableBoundary()) {
                 resetView();
             } else {
                 visualizationPanel.repaint();
@@ -800,7 +1079,7 @@
 
         Rectangle2D.Double bounds = plannedPathBounds;
         SwingUtilities.invokeLater(() -> {
-            if (currentBoundary == null || currentBoundary.size() < 2) {
+            if (!hasRenderableBoundary()) {
                 fitBoundsToView(bounds);
             }
             visualizationPanel.repaint();

--
Gitblit v1.10.0