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

---
 src/zhangaiwu/AddDikuai.java |  393 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 389 insertions(+), 4 deletions(-)

diff --git a/src/dikuai/AddDikuai.java b/src/zhangaiwu/AddDikuai.java
similarity index 78%
rename from src/dikuai/AddDikuai.java
rename to src/zhangaiwu/AddDikuai.java
index 8c59d2a..017bc55 100644
--- a/src/dikuai/AddDikuai.java
+++ b/src/zhangaiwu/AddDikuai.java
@@ -1,4 +1,4 @@
-package dikuai;
+package zhangaiwu;
 
 import javax.swing.*;
 
@@ -14,11 +14,15 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import bianjie.jisuanmianjie;
+import dikuai.Dikuai;
+import dikuai.Dikuaiguanli;
 import gecaoji.Device;
 import bianjie.bianjieguihua2;
+import lujing.Lunjingguihua;
 import ui.UIConfig;
 import zhuye.MowerLocationData;
 import zhuye.Shouye;
@@ -62,6 +66,7 @@
     private JButton nextButton;
     private JButton createButton;
     private JLabel boundaryCountLabel;
+    private JPanel obstacleListContainer;
     
     // 鍦板潡鏁版嵁
     private Map<String, String> dikuaiData = new HashMap<>();
@@ -218,6 +223,10 @@
         formGroup.add(areaNameField);
         formGroup.add(Box.createRigidArea(new Dimension(0, 8)));
         formGroup.add(hintLabel);
+
+    formGroup.add(Box.createRigidArea(new Dimension(0, 20)));
+    JPanel obstacleSection = createObstacleSummarySection();
+    formGroup.add(obstacleSection);
         
         stepPanel.add(formGroup);
         stepPanel.add(Box.createVerticalGlue());
@@ -226,6 +235,256 @@
         
         return stepPanel;
     }
+
+    private JPanel createObstacleSummarySection() {
+        JPanel section = new JPanel();
+        section.setLayout(new BoxLayout(section, BoxLayout.Y_AXIS));
+        section.setOpaque(false);
+        section.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+        JLabel title = new JLabel("宸叉湁闅滅鐗�");
+        title.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 16));
+        title.setForeground(TEXT_COLOR);
+        title.setAlignmentX(Component.LEFT_ALIGNMENT);
+        section.add(title);
+        section.add(Box.createRigidArea(new Dimension(0, 8)));
+
+        obstacleListContainer = new JPanel();
+        obstacleListContainer.setLayout(new BoxLayout(obstacleListContainer, BoxLayout.Y_AXIS));
+        obstacleListContainer.setOpaque(false);
+        obstacleListContainer.setAlignmentX(Component.LEFT_ALIGNMENT);
+        section.add(obstacleListContainer);
+
+        updateObstacleSummary();
+
+        return section;
+    }
+
+    private void updateObstacleSummary() {
+        if (obstacleListContainer == null) {
+            return;
+        }
+
+        obstacleListContainer.removeAll();
+        List<ObstacleSummary> summaries = loadExistingObstacles();
+
+        if (summaries.isEmpty()) {
+            JLabel emptyLabel = new JLabel("鏆傛棤闅滅鐗�");
+            emptyLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 13));
+            emptyLabel.setForeground(LIGHT_TEXT);
+            emptyLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+            obstacleListContainer.add(emptyLabel);
+        } else {
+            int index = 1;
+            for (ObstacleSummary summary : summaries) {
+                JPanel row = new JPanel(new BorderLayout());
+                row.setOpaque(false);
+                row.setAlignmentX(Component.LEFT_ALIGNMENT);
+                row.setBorder(BorderFactory.createEmptyBorder(6, 0, 6, 0));
+
+                String labelText = String.format(Locale.CHINA, "%02d. %s", index++, summary.getName());
+                JLabel nameLabel = new JLabel(labelText);
+                nameLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+                nameLabel.setForeground(TEXT_COLOR);
+
+                JLabel coordLabel = new JLabel(summary.getDisplayCoords());
+                coordLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 13));
+                coordLabel.setForeground(LIGHT_TEXT);
+                coordLabel.setToolTipText(summary.getFullCoords());
+
+                row.add(nameLabel, BorderLayout.WEST);
+                row.add(coordLabel, BorderLayout.CENTER);
+                obstacleListContainer.add(row);
+            }
+        }
+
+        obstacleListContainer.revalidate();
+        obstacleListContainer.repaint();
+    }
+
+    private List<ObstacleSummary> loadExistingObstacles() {
+        List<ObstacleSummary> summaries = new ArrayList<>();
+
+        String landNumber = getPendingLandNumber();
+        String raw = null;
+        if (landNumber != null) {
+            Dikuai dikuai = Dikuai.getDikuai(landNumber);
+            if (dikuai != null) {
+                raw = normalizeCoordinateValue(dikuai.getObstacleCoordinates());
+            }
+        }
+        if (raw == null) {
+            raw = normalizeCoordinateValue(dikuaiData.get("obstacleCoordinates"));
+        }
+        if (!isMeaningfulValue(raw)) {
+            return summaries;
+        }
+
+        String normalized = stripInlineComment(raw);
+        if (normalized.isEmpty()) {
+            return summaries;
+        }
+
+        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();
+                    }
+                }
+            }
+
+            String sanitizedCoords = sanitizeCoordinateString(coordsSection);
+            if (!isMeaningfulValue(sanitizedCoords)) {
+                continue;
+            }
+
+            String resolvedName;
+            if (nameToken != null && !nameToken.isEmpty()) {
+                resolvedName = nameToken;
+            } else {
+                resolvedName = "闅滅鐗�" + defaultIndex++;
+            }
+
+            String displayCoords = truncateCoordinateForDisplay(sanitizedCoords, 12);
+            summaries.add(new ObstacleSummary(resolvedName, sanitizedCoords, displayCoords));
+        }
+
+        return summaries;
+    }
+
+    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 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 String sanitizeCoordinateString(String value) {
+        if (value == null) {
+            return "";
+        }
+        String stripped = stripInlineComment(value);
+        if (stripped.isEmpty()) {
+            return "";
+        }
+        return stripped.replace("\r", "").replace("\n", "").replace("\t", "").replace(" ", "");
+    }
+
+    private String truncateCoordinateForDisplay(String coords, int maxLength) {
+        if (coords == null) {
+            return "";
+        }
+        String trimmed = coords.trim();
+        if (trimmed.length() <= maxLength) {
+            return trimmed;
+        }
+        if (maxLength <= 3) {
+            return trimmed.substring(0, maxLength);
+        }
+        return trimmed.substring(0, maxLength - 3) + "...";
+    }
+
+    private static final class ObstacleSummary {
+        private final String name;
+        private final String fullCoords;
+        private final String displayCoords;
+
+        ObstacleSummary(String name, String fullCoords, String displayCoords) {
+            this.name = name;
+            this.fullCoords = fullCoords;
+            this.displayCoords = displayCoords;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getFullCoords() {
+            return fullCoords;
+        }
+
+        public String getDisplayCoords() {
+            return displayCoords;
+        }
+    }
     
     private JPanel createStep2Panel() {
         JPanel stepPanel = new JPanel();
@@ -675,9 +934,89 @@
             showStep(2);
             return;
         }
-        dikuaiData.put("mowingPattern", (String) mowingPatternCombo.getSelectedItem());
-        dikuaiData.put("mowingWidth", mowingWidthSpinner.getValue().toString());
-        JOptionPane.showMessageDialog(this, "宸叉牴鎹綋鍓嶈缃敓鎴愬壊鑽夎矾寰�", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+        Dikuai dikuai = getOrCreatePendingDikuai();
+        String boundaryCoords = null;
+        if (dikuai != null) {
+            boundaryCoords = normalizeCoordinateValue(dikuai.getBoundaryCoordinates());
+        }
+        if (boundaryCoords == null) {
+            boundaryCoords = normalizeCoordinateValue(dikuaiData.get("boundaryCoordinates"));
+        }
+        if (boundaryCoords == null) {
+            JOptionPane.showMessageDialog(this, "鏈壘鍒版湁鏁堢殑鍦板潡杈圭晫鍧愭爣锛屾棤娉曠敓鎴愯矾寰�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            if (createButton != null) {
+                createButton.setEnabled(false);
+            }
+            return;
+        }
+
+        String obstacleCoords = null;
+        if (dikuai != null) {
+            obstacleCoords = normalizeCoordinateValue(dikuai.getObstacleCoordinates());
+        }
+        if (obstacleCoords == null) {
+            obstacleCoords = normalizeCoordinateValue(dikuaiData.get("obstacleCoordinates"));
+        }
+
+        String patternDisplay = (String) mowingPatternCombo.getSelectedItem();
+        dikuaiData.put("mowingPattern", patternDisplay);
+
+        Object widthObj = mowingWidthSpinner.getValue();
+        if (!(widthObj instanceof Number)) {
+            JOptionPane.showMessageDialog(this, "鍓茶崏瀹藉害杈撳叆鏃犳晥", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            if (createButton != null) {
+                createButton.setEnabled(false);
+            }
+            return;
+        }
+        double widthCm = ((Number) widthObj).doubleValue();
+        if (widthCm <= 0) {
+            JOptionPane.showMessageDialog(this, "鍓茶崏瀹藉害蹇呴』澶т簬0", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            if (createButton != null) {
+                createButton.setEnabled(false);
+            }
+            return;
+        }
+        dikuaiData.put("mowingWidth", widthObj.toString());
+
+        String widthMeters = String.format(Locale.US, "%.2f", widthCm / 100.0);
+        String plannerMode = resolvePlannerMode(patternDisplay);
+
+        try {
+            List<Lunjingguihua.PathSegment> segments = Lunjingguihua.generatePathSegments(
+                boundaryCoords,
+                obstacleCoords,
+                widthMeters,
+                plannerMode
+            );
+            String plannedPath = Lunjingguihua.formatPathSegments(segments);
+            if (!isMeaningfulValue(plannedPath)) {
+                JOptionPane.showMessageDialog(this, "鐢熸垚鍓茶崏璺緞澶辫触: 鐢熸垚缁撴灉涓虹┖", "閿欒", JOptionPane.ERROR_MESSAGE);
+                if (createButton != null) {
+                    createButton.setEnabled(false);
+                }
+                return;
+            }
+            dikuaiData.put("plannedPath", plannedPath);
+            if (createButton != null) {
+                createButton.setEnabled(true);
+            }
+            JOptionPane.showMessageDialog(this,
+                "宸叉牴鎹綋鍓嶈缃敓鎴愬壊鑽夎矾寰勶紝鍏辩敓鎴� " + segments.size() + " 娈点��",
+                "鎴愬姛",
+                JOptionPane.INFORMATION_MESSAGE);
+        } catch (IllegalArgumentException ex) {
+            JOptionPane.showMessageDialog(this, "鐢熸垚鍓茶崏璺緞澶辫触: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
+            if (createButton != null) {
+                createButton.setEnabled(false);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            JOptionPane.showMessageDialog(this, "鐢熸垚鍓茶崏璺緞鏃跺彂鐢熷紓甯�: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
+            if (createButton != null) {
+                createButton.setEnabled(false);
+            }
+        }
     }
     
     private JButton createPrimaryButton(String text, int fontSize) {
@@ -732,6 +1071,7 @@
         nextButton = createPrimaryButton("涓嬩竴姝�", 16);
         createButton = createPrimaryButton("淇濆瓨", 16);
         createButton.setVisible(false);
+    createButton.setEnabled(false);
 
         buttonPanel.add(prevButton);
         buttonPanel.add(Box.createHorizontalGlue());
@@ -880,6 +1220,36 @@
             boundaryCountLabel.setVisible(false);
         }
     }
+
+    private boolean hasGeneratedPath() {
+        return isMeaningfulValue(dikuaiData.get("plannedPath"));
+    }
+
+    private String normalizeCoordinateValue(String value) {
+        return isMeaningfulValue(value) ? value.trim() : null;
+    }
+
+    private boolean isMeaningfulValue(String value) {
+        if (value == null) {
+            return false;
+        }
+        String trimmed = value.trim();
+        return !trimmed.isEmpty() && !"-1".equals(trimmed);
+    }
+
+    private String resolvePlannerMode(String patternDisplay) {
+        if (patternDisplay == null) {
+            return "parallel";
+        }
+        String trimmed = patternDisplay.trim();
+        if (trimmed.isEmpty()) {
+            return "parallel";
+        }
+        if ("铻烘棆寮�".equals(trimmed) || "spiral".equalsIgnoreCase(trimmed) || "1".equals(trimmed)) {
+            return "spiral";
+        }
+        return "parallel";
+    }
     
     private void setupEventHandlers() {
         // 涓婁竴姝ユ寜閽�
@@ -922,6 +1292,10 @@
         currentStep = step;
         cardLayout.show(stepsPanel, "step" + step);
         
+        if (step == 1) {
+            updateObstacleSummary();
+        }
+
         // 鏇存柊鎸夐挳鐘舵��
         updateButtonState(step);
     }
@@ -932,9 +1306,11 @@
         if (step < 3) {
             nextButton.setVisible(true);
             createButton.setVisible(false);
+            createButton.setEnabled(false);
         } else {
             nextButton.setVisible(false);
             createButton.setVisible(true);
+            createButton.setEnabled(hasGeneratedPath());
         }
 
         Container parent = prevButton.getParent();
@@ -977,6 +1353,10 @@
             case 3:
                 dikuaiData.put("mowingPattern", (String) mowingPatternCombo.getSelectedItem());
                 dikuaiData.put("mowingWidth", mowingWidthSpinner.getValue().toString());
+                if (!hasGeneratedPath()) {
+                    JOptionPane.showMessageDialog(this, "璇峰厛鐢熸垚鍓茶崏璺緞", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                    return false;
+                }
                 break;
         }
         return true;
@@ -1271,6 +1651,11 @@
             dikuai.setMowingWidth(dikuaiData.get("mowingWidth"));
         }
 
+        String plannedPath = dikuaiData.get("plannedPath");
+        if (isMeaningfulValue(plannedPath)) {
+            dikuai.setPlannedPath(plannedPath);
+        }
+
         Dikuai.putDikuai(landNumber, dikuai);
         Dikuai.saveToProperties();
         

--
Gitblit v1.10.0