From b518f895dec5264fd25e22a68300c40ceba6f43d Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期六, 20 十二月 2025 15:30:20 +0800
Subject: [PATCH] 新增了按钮功能

---
 src/dikuai/addzhangaiwu.java |  656 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 631 insertions(+), 25 deletions(-)

diff --git a/src/dikuai/addzhangaiwu.java b/src/dikuai/addzhangaiwu.java
index f14b481..662c5c1 100644
--- a/src/dikuai/addzhangaiwu.java
+++ b/src/dikuai/addzhangaiwu.java
@@ -10,8 +10,11 @@
 import java.awt.Font;
 import java.awt.Image;
 import java.awt.Window;
+import java.awt.Container;
+import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.io.File;
@@ -51,6 +54,9 @@
 import zhangaiwu.AddDikuai;
 import zhangaiwu.Obstacledge;
 import zhangaiwu.yulanzhangaiwu;
+import zhuye.buttonset;
+import bianjie.bianjieguihua2;
+import bianjie.ThreePointCircle;
 
 /**
  * 闅滅鐗╂柊澧�/缂栬緫瀵硅瘽妗嗐�傝璁¤瑷�鍙傝�� {@link AddDikuai}锛屾敮鎸侀�氳繃瀹炲湴缁樺埗閲囬泦闅滅鐗╁潗鏍囥��
@@ -87,7 +93,10 @@
     private JPanel selectedMethodPanel;
     private JPanel selectedShapePanel;
     private JButton drawButton;
+    private JButton generateBoundaryButton;  // 鐢熸垚闅滅鐗╄竟鐣屾寜閽�
+    private JButton previewButton;  // 棰勮鎸夐挳
     private JLabel drawingStatusLabel;
+    private JLabel boundaryStatusLabel;  // 鐢熸垚闅滅鐗╄竟鐣岀姸鎬佹爣绛�
     private JTextField obstacleNameField;
     private JPanel existingObstacleListPanel;
     private JPanel step1NextButtonRow;
@@ -287,13 +296,10 @@
     }
 
     private JButton createInlineButton(String text) {
-        JButton button = new JButton(text);
+        JButton button = buttonset.createStyledButton(text, PRIMARY_COLOR);
         button.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 12));
-        button.setForeground(WHITE);
-        button.setBackground(PRIMARY_COLOR);
         button.setBorder(BorderFactory.createEmptyBorder(6, 16, 6, 16));
         button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-        button.setFocusPainted(false);
         Dimension size = new Dimension(72, 28);
         button.setPreferredSize(size);
         button.setMinimumSize(size);
@@ -492,6 +498,7 @@
             formData.remove("editingObstacleName");
             formData.remove("obstacleCoordinates");
             formData.remove("obstacleOriginalCoordinates");
+            formData.remove("generatedBoundaryCoordinates");  // 娓呴櫎鐢熸垚鐨勮竟鐣屽潗鏍�
             if (obstacleNameField != null) {
                 obstacleNameField.setText("");
             } else {
@@ -499,6 +506,7 @@
             }
             updateDrawingStatus();
             updateSaveButtonState();
+            updatePreviewButtonState();
         }
     }
 
@@ -541,10 +549,24 @@
 
         stepPanel.add(Box.createRigidArea(new Dimension(0, 24)));
 
+        // 鎸夐挳瀹瑰櫒锛氶噸鏂扮粯鍒� + 鐢熸垚闅滅鐗╄竟鐣�
+        JPanel buttonRow = new JPanel();
+        buttonRow.setLayout(new BoxLayout(buttonRow, BoxLayout.X_AXIS));
+        buttonRow.setOpaque(false);
+        buttonRow.setAlignmentX(Component.LEFT_ALIGNMENT);
+        
         drawButton = createPrimaryButton("寮�濮嬬粯鍒�", 16);
-        drawButton.setAlignmentX(Component.LEFT_ALIGNMENT);
         drawButton.addActionListener(e -> startDrawingWorkflow());
-        stepPanel.add(drawButton);
+        buttonRow.add(drawButton);
+        
+        buttonRow.add(Box.createRigidArea(new Dimension(10, 0)));
+        
+        generateBoundaryButton = createPrimaryButton("鐢熸垚闅滅鐗╄竟鐣�", 16);
+        generateBoundaryButton.setVisible(false);  // 鍒濆闅愯棌锛岀粯鍒跺畬鎴愬悗鏄剧ず
+        generateBoundaryButton.addActionListener(e -> generateObstacleBoundary());
+        buttonRow.add(generateBoundaryButton);
+        
+        stepPanel.add(buttonRow);
 
         stepPanel.add(Box.createRigidArea(new Dimension(0, 12)));
 
@@ -553,6 +575,15 @@
         drawingStatusLabel.setForeground(LIGHT_TEXT);
         drawingStatusLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
         stepPanel.add(drawingStatusLabel);
+        
+        // 娣诲姞鐢熸垚闅滅鐗╄竟鐣岀姸鎬佹爣绛�
+        stepPanel.add(Box.createRigidArea(new Dimension(0, 8)));
+        boundaryStatusLabel = new JLabel("");
+        boundaryStatusLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 13));
+        boundaryStatusLabel.setForeground(LIGHT_TEXT);
+        boundaryStatusLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        boundaryStatusLabel.setVisible(false);  // 鍒濆闅愯棌
+        stepPanel.add(boundaryStatusLabel);
 
         stepPanel.add(Box.createVerticalGlue());
         return stepPanel;
@@ -566,12 +597,24 @@
 
         prevButton = createSecondaryButton("涓婁竴姝�");
         nextButton = createPrimaryButton("涓嬩竴姝�", 16);
+        // 璁剧疆涓嬩竴姝ユ寜閽搴︿负300鍍忕礌
+        nextButton.setPreferredSize(new Dimension(300, nextButton.getPreferredSize().height));
+        nextButton.setMaximumSize(new Dimension(300, nextButton.getPreferredSize().height));
+        
+        previewButton = createSecondaryButton("棰勮");
+        previewButton.setVisible(false);  // 鍒濆闅愯棌锛岀敓鎴愯竟鐣屽悗鏄剧ず
+        previewButton.setOpaque(true);
+        previewButton.setContentAreaFilled(true);
+        previewButton.addActionListener(e -> previewObstacleBoundary());
+        
         saveButton = createPrimaryButton("淇濆瓨", 16);
         saveButton.setVisible(false);
 
         buttonPanel.add(prevButton);
         buttonPanel.add(Box.createHorizontalGlue());
         buttonPanel.add(Box.createRigidArea(new Dimension(12, 0)));
+        buttonPanel.add(previewButton);
+        buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
         buttonPanel.add(saveButton);
 
         attachNextButtonToStep1Row();
@@ -753,6 +796,10 @@
         if (option == null) {
             return;
         }
+        if (userTriggered && "handheld".equalsIgnoreCase(type) && !hasConfiguredHandheldMarker()) {
+            JOptionPane.showMessageDialog(this, "璇峰厛鍘荤郴缁熻缃坊鍔犱究鎼烘墦鐐瑰櫒缂栧彿", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
         if (selectedMethodPanel != null && selectedMethodPanel != option) {
             resetOptionAppearance(selectedMethodPanel);
         }
@@ -764,6 +811,11 @@
         }
     }
 
+    private boolean hasConfiguredHandheldMarker() {
+        String handheldId = Setsys.getPropertyValue("handheldMarkerId");
+        return handheldId != null && !handheldId.trim().isEmpty();
+    }
+
     private void selectShapeOption(JPanel option, String type, boolean userTriggered) {
         if (option == null) {
             return;
@@ -859,6 +911,23 @@
         }
 
         activeDrawingShape = null;
+        
+        // 閲嶆柊缁樺埗鏃舵竻闄や箣鍓嶇敓鎴愮殑杈圭晫鍧愭爣
+        formData.remove("generatedBoundaryCoordinates");
+        if (previewButton != null) {
+            previewButton.setVisible(false);
+        }
+        // 娓呴櫎杈圭晫鐘舵�佹爣绛�
+        if (boundaryStatusLabel != null) {
+            boundaryStatusLabel.setVisible(false);
+            boundaryStatusLabel.setText("");
+        }
+        // 瀵逛簬鍦嗗舰闅滅鐗╋紝闅愯棌鐢熸垚杈圭晫鎸夐挳
+        String shapeKey = formData.get("obstacleShape");
+        boolean isCircle = "circle".equals(shapeKey);
+        if (isCircle && generateBoundaryButton != null) {
+            generateBoundaryButton.setVisible(false);
+        }
 
         String method = formData.get("drawingMethod");
         if (!isMeaningfulValue(method)) {
@@ -1033,14 +1102,11 @@
                 session.captureMessage = "鏃犳硶鏍规嵁閲囬泦鐨勭偣鐢熸垚鍦嗭紝璇风‘淇濋�夋嫨浜嗕笁涓潪鍏辩嚎鐨勫渾鍛ㄧ偣";
                 return;
             }
-            double[] radiusPoint = pickRadiusPoint(xyPoints, circle);
-            if (radiusPoint == null) {
-                session.captureSuccessful = false;
-                session.captureMessage = "閲囬泦鐨勫渾鍛ㄧ偣寮傚父锛屾棤娉曠敓鎴愬渾";
-                return;
-            }
+            // 浣跨敤璁$畻鍑虹殑鍗婂緞鐢熸垚涓�涓湡姝g殑鍦嗕笂鐐癸紙鍦嗗績鍙充晶鐨勭偣锛夛紝纭繚棰勮鏃惰绠楃殑鍗婂緞鍜岀粨鏉熺粯鍒舵椂鐨勫崐寰勪竴鑷�
+            double radiusX = circle.centerX + circle.radius;
+            double radiusY = circle.centerY;
             String result = String.format(Locale.US, "%.2f,%.2f;%.2f,%.2f",
-                    circle.centerX, circle.centerY, radiusPoint[0], radiusPoint[1]);
+                    circle.centerX, circle.centerY, radiusX, radiusY);
             session.data.put("obstacleCoordinates", result);
             session.captureSuccessful = true;
             session.captureMessage = "宸查噰闆嗗渾褰㈤殰纰嶇墿锛屽叡 " + xyPoints.size() + " 涓偣";
@@ -1293,7 +1359,7 @@
         }
         if (!configMap.isEmpty()) {
             List<ExistingObstacle> remaining = new ArrayList<>(configMap.values());
-            remaining.sort(Comparator.comparing(ExistingObstacle::getName, String.CASE_INSENSITIVE_ORDER));
+            remaining.sort((a, b) -> String.CASE_INSENSITIVE_ORDER.compare(a.getName(), b.getName()));
             result.addAll(remaining);
         }
         if (result.isEmpty()) {
@@ -1358,8 +1424,15 @@
     private void preloadData() {
         formData.remove("obstacleCoordinates");
         formData.remove("obstacleOriginalCoordinates");
+        formData.remove("generatedBoundaryCoordinates");  // 娓呴櫎鐢熸垚鐨勮竟鐣屽潗鏍�
         formData.remove("editingObstacleName");
         updateDrawingStatus();
+        updatePreviewButtonState();
+        // 娓呴櫎杈圭晫鐘舵�佹爣绛�
+        if (boundaryStatusLabel != null) {
+            boundaryStatusLabel.setVisible(false);
+            boundaryStatusLabel.setText("");
+        }
     }
 
     private void updateDrawingStatus() {
@@ -1367,21 +1440,140 @@
             return;
         }
         String coords = formData.get("obstacleCoordinates");
+        String shapeKey = formData.get("obstacleShape");
+        boolean isCircle = "circle".equals(shapeKey);
+        
         if (isMeaningfulValue(coords)) {
-            int count = countCoordinatePairs(coords);
-            drawingStatusLabel.setText("宸查噰闆嗛殰纰嶇墿鏁版嵁锛岀偣鏁帮細" + count);
+            if (isCircle) {
+                // 瀵逛簬鍦嗗舰闅滅鐗╋紝鏄剧ず鍦嗗績鍧愭爣鍜屽崐寰�
+                String statusText = parseCircleStatusText(coords);
+                drawingStatusLabel.setText(statusText);
+            } else {
+                // 瀵逛簬澶氳竟褰㈤殰纰嶇墿锛屾樉绀虹偣鏁�
+                int count = countCoordinatePairs(coords);
+                drawingStatusLabel.setText("宸查噰闆嗛殰纰嶇墿鏁版嵁锛岀偣鏁帮細" + count);
+            }
             if (!drawingInProgress && drawButton != null) {
                 drawButton.setText("閲嶆柊缁樺埗");
                 drawButton.setEnabled(true);
             }
+            // 瀵逛簬鍦嗗舰闅滅鐗╋紝涓嶆樉绀�"鐢熸垚闅滅鐗╄竟鐣�"鎸夐挳
+            if (generateBoundaryButton != null) {
+                generateBoundaryButton.setVisible(!isCircle);
+            }
         } else {
             drawingStatusLabel.setText("灏氭湭閲囬泦闅滅鐗╁潗鏍�");
             if (!drawingInProgress && drawButton != null) {
                 drawButton.setText("寮�濮嬬粯鍒�");
                 drawButton.setEnabled(true);
             }
+            // 鏈粯鍒舵椂闅愯棌"鐢熸垚闅滅鐗╄竟鐣�"鎸夐挳
+            if (generateBoundaryButton != null) {
+                generateBoundaryButton.setVisible(false);
+            }
+            // 鏈敓鎴愯竟鐣屾椂闅愯棌棰勮鎸夐挳
+            if (previewButton != null) {
+                previewButton.setVisible(false);
+            }
+            // 闅愯棌杈圭晫鐘舵�佹爣绛�
+            if (boundaryStatusLabel != null) {
+                boundaryStatusLabel.setVisible(false);
+            }
         }
         updateSaveButtonState();
+        updatePreviewButtonState();
+    }
+    
+    /**
+     * 鏇存柊杈圭晫鐘舵�佹爣绛�
+     */
+    private void updateBoundaryStatusLabel(int pointCount) {
+        if (boundaryStatusLabel == null) {
+            return;
+        }
+        if (pointCount > 0) {
+            boundaryStatusLabel.setText("鐢熸垚闅滅鐗╄竟鐣岀偣鏁帮細" + pointCount);
+            boundaryStatusLabel.setVisible(true);
+        } else {
+            boundaryStatusLabel.setText("");
+            boundaryStatusLabel.setVisible(false);
+        }
+    }
+    
+    /**
+     * 鏇存柊棰勮鎸夐挳鐨勬樉绀虹姸鎬�
+     */
+    private void updatePreviewButtonState() {
+        if (previewButton == null) {
+            return;
+        }
+        
+        // 瀵逛簬鍦嗗舰闅滅鐗╋紝涓嶆樉绀洪瑙堟寜閽�
+        String shapeKey = formData.get("obstacleShape");
+        boolean isCircle = "circle".equals(shapeKey);
+        if (isCircle) {
+            previewButton.setVisible(false);
+            previewButton.setEnabled(false);
+            return;
+        }
+        
+        // 鍙湁鍦ㄧ敓鎴愯竟鐣屽悗鎵嶆樉绀洪瑙堟寜閽�
+        String generatedBoundary = formData.get("generatedBoundaryCoordinates");
+        boolean hasGeneratedBoundary = isMeaningfulValue(generatedBoundary);
+
+        if (hasGeneratedBoundary) {
+            // 鐢熸垚杈圭晫鍚庯紝閲嶆柊鍒涘缓缁胯壊鐨勯瑙堟寜閽�
+            // 鑾峰彇鎸夐挳鐨勭埗瀹瑰櫒鍜屼綅缃�
+            Container parent = previewButton.getParent();
+            if (parent != null) {
+                // 淇濆瓨鍘熸湁鐨凙ctionListener
+                ActionListener[] listeners = previewButton.getActionListeners();
+                
+                // 绉婚櫎鏃ф寜閽�
+                parent.remove(previewButton);
+                
+                // 鍒涘缓鏂扮殑缁胯壊棰勮鎸夐挳锛堜娇鐢ㄤ富鎸夐挳鏍峰紡锛�
+                previewButton = createPrimaryButton("棰勮", 16);
+                previewButton.setVisible(true);
+                previewButton.setEnabled(true);
+                
+                // 鎭㈠ActionListener
+                for (ActionListener listener : listeners) {
+                    previewButton.addActionListener(listener);
+                }
+                
+                // 娣诲姞鍒扮埗瀹瑰櫒锛堝湪淇濆瓨鎸夐挳涔嬪墠锛�
+                int previewIndex = -1;
+                Component[] components = parent.getComponents();
+                for (int i = 0; i < components.length; i++) {
+                    if (components[i] instanceof JButton) {
+                        JButton btn = (JButton) components[i];
+                        if ("淇濆瓨".equals(btn.getText())) {
+                            previewIndex = i;
+                            break;
+                        }
+                    }
+                }
+                
+                if (previewIndex >= 0) {
+                    parent.add(previewButton, previewIndex);
+                    parent.add(Box.createRigidArea(new Dimension(10, 0)), previewIndex + 1);
+                } else {
+                    // 濡傛灉鎵句笉鍒颁繚瀛樻寜閽紝娣诲姞鍒版湯灏�
+                    parent.add(Box.createRigidArea(new Dimension(12, 0)));
+                    parent.add(previewButton);
+                    parent.add(Box.createRigidArea(new Dimension(10, 0)));
+                }
+                
+                // 鍒锋柊甯冨眬
+                parent.revalidate();
+                parent.repaint();
+            }
+        } else {
+            // 鏈敓鎴愯竟鐣屾椂锛岄殣钘忔寜閽�
+            previewButton.setVisible(false);
+            previewButton.setEnabled(false);
+        }
     }
 
     private int countCoordinatePairs(String coords) {
@@ -1404,21 +1596,80 @@
         }
         return count;
     }
+    
+    /**
+     * 瑙f瀽鍦嗗舰闅滅鐗╁潗鏍囷紝鐢熸垚鐘舵�佹枃鏈�
+     * 鏍煎紡锛歝enterX,centerY;radiusX,radiusY
+     * 杩斿洖锛氬綋鍓嶉噰闆嗗渾褰㈠渾蹇冨潗鏍噚,y,鍗婂緞n绫�
+     */
+    private String parseCircleStatusText(String coords) {
+        if (!isMeaningfulValue(coords)) {
+            return "灏氭湭閲囬泦鍦嗗舰闅滅鐗╁潗鏍�";
+        }
+        
+        try {
+            String[] pairs = coords.split(";");
+            if (pairs.length < 2) {
+                return "鍦嗗舰闅滅鐗╁潗鏍囨牸寮忛敊璇�";
+            }
+            
+            // 瑙f瀽鍦嗗績鍧愭爣
+            String[] centerParts = pairs[0].trim().split(",");
+            if (centerParts.length < 2) {
+                return "鍦嗗舰闅滅鐗╁潗鏍囨牸寮忛敊璇�";
+            }
+            double centerX = Double.parseDouble(centerParts[0].trim());
+            double centerY = Double.parseDouble(centerParts[1].trim());
+            
+            // 瑙f瀽鍦嗕笂涓�鐐瑰潗鏍�
+            String[] radiusParts = pairs[1].trim().split(",");
+            if (radiusParts.length < 2) {
+                return "鍦嗗舰闅滅鐗╁潗鏍囨牸寮忛敊璇�";
+            }
+            double radiusX = Double.parseDouble(radiusParts[0].trim());
+            double radiusY = Double.parseDouble(radiusParts[1].trim());
+            
+            // 璁$畻鍗婂緞锛堢背锛�
+            double radius = Math.sqrt(Math.pow(radiusX - centerX, 2) + Math.pow(radiusY - centerY, 2));
+            
+            // 鏍煎紡鍖栨樉绀猴細褰撳墠閲囬泦鍦嗗舰鍦嗗績鍧愭爣x,y,鍗婂緞n绫�
+            return String.format(Locale.US, "褰撳墠閲囬泦鍦嗗舰鍦嗗績鍧愭爣%.2f,%.2f,鍗婂緞%.2f绫�", 
+                    centerX, centerY, radius);
+        } catch (Exception e) {
+            return "鍦嗗舰闅滅鐗╁潗鏍囪В鏋愬け璐�";
+        }
+    }
 
     private void updateSaveButtonState() {
         if (saveButton != null) {
             boolean hasCoords = isMeaningfulValue(formData.get("obstacleCoordinates"));
             boolean hasName = isMeaningfulValue(formData.get("obstacleName"));
-            boolean enabled = hasCoords && hasName;
+            
+            // 妫�鏌ユ槸鍚︾敓鎴愪簡闅滅鐗╄竟鐣屽潗鏍�
+            String shapeKey = formData.get("obstacleShape");
+            boolean hasGeneratedBoundary = isMeaningfulValue(formData.get("generatedBoundaryCoordinates"));
+            
+            // 濡傛灉鏄杈瑰舰闅滅鐗╋紝蹇呴』鐢熸垚杈圭晫鍧愭爣鎵嶈兘淇濆瓨
+            // 濡傛灉鏄渾褰㈤殰纰嶇墿鎴栧叾浠栧舰鐘讹紝涓嶉渶瑕佺敓鎴愯竟鐣屽氨鑳戒繚瀛�
+            boolean boundaryRequirementMet = true;
+            if ("polygon".equals(shapeKey)) {
+                boundaryRequirementMet = hasGeneratedBoundary;
+            }
+            
+            boolean enabled = hasCoords && hasName && boundaryRequirementMet;
             saveButton.setEnabled(enabled);
             if (enabled) {
                 saveButton.setBackground(PRIMARY_COLOR);
                 saveButton.setForeground(WHITE);
                 saveButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+                saveButton.setOpaque(true);
+                saveButton.setContentAreaFilled(true);
             } else {
                 saveButton.setBackground(MEDIUM_GRAY);
                 saveButton.setForeground(TEXT_COLOR);
                 saveButton.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+                saveButton.setOpaque(true);
+                saveButton.setContentAreaFilled(true);
             }
         }
     }
@@ -1456,6 +1707,7 @@
         String obstacleName = formData.get("obstacleName");
         String coordsValue = formData.get("obstacleCoordinates");
         String originalValue = formData.get("obstacleOriginalCoordinates");
+        String generatedBoundaryValue = formData.get("generatedBoundaryCoordinates");  // 鐢熸垚鐨勮竟鐣屽潗鏍�
         String shapeKey = formData.get("obstacleShape");
         String previousName = formData.get("editingObstacleName");
 
@@ -1466,6 +1718,16 @@
 
         String coords = coordsValue.trim();
         String originalCoords = isMeaningfulValue(originalValue) ? originalValue.trim() : null;
+        // 瀵逛簬鍦嗗舰闅滅鐗╋紝鐩存帴浣跨敤obstacleCoordinates锛堝湪绗�3涓偣纭鏃跺凡鐢熸垚锛�
+        // 瀵逛簬澶氳竟褰㈤殰纰嶇墿锛屽鏋滄湁鐢熸垚鐨勮竟鐣屽潗鏍囷紝浣跨敤鐢熸垚鐨勮竟鐣屽潗鏍囷紱鍚﹀垯浣跨敤鍘熷鍧愭爣
+        String finalCoords;
+        if ("circle".equals(shapeKey)) {
+            // 鍦嗗舰闅滅鐗╃洿鎺ヤ娇鐢ㄥ凡鐢熸垚鐨勫潗鏍�
+            finalCoords = coords;
+        } else {
+            // 澶氳竟褰㈤殰纰嶇墿浼樺厛浣跨敤鐢熸垚鐨勮竟鐣屽潗鏍�
+            finalCoords = isMeaningfulValue(generatedBoundaryValue) ? generatedBoundaryValue.trim() : coords;
+        }
         String trimmedName = isMeaningfulValue(obstacleName) ? obstacleName.trim() : null;
         if (!isMeaningfulValue(trimmedName)) {
             JOptionPane.showMessageDialog(this, "闅滅鐗╁悕绉版棤鏁�", "閿欒", JOptionPane.ERROR_MESSAGE);
@@ -1477,7 +1739,7 @@
             formData.put("editingObstacleName", trimmedName);
         }
 
-        if (!persistObstacleToConfig(landNumber, previousName, trimmedName, shapeKey, coords, originalCoords)) {
+        if (!persistObstacleToConfig(landNumber, previousName, trimmedName, shapeKey, finalCoords, originalCoords)) {
             JOptionPane.showMessageDialog(this, "鍐欏叆闅滅鐗╅厤缃け璐ワ紝璇烽噸璇�", "閿欒", JOptionPane.ERROR_MESSAGE);
             return;
         }
@@ -1489,6 +1751,315 @@
         activeSession = null;
         dispose();
     }
+    
+    /**
+     * 鐢熸垚闅滅鐗╄竟鐣屽潗鏍�
+     */
+    private void generateObstacleBoundary() {
+        String originalCoords = formData.get("obstacleOriginalCoordinates");
+        if (!isMeaningfulValue(originalCoords)) {
+            JOptionPane.showMessageDialog(this, "鏃犲師濮嬪潗鏍囨暟鎹紝鏃犳硶鐢熸垚杈圭晫", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+        
+        String baseStation = targetDikuai.getBaseStationCoordinates();
+        if (!isMeaningfulValue(baseStation)) {
+            JOptionPane.showMessageDialog(this, "鍦板潡鏈缃熀绔欏潗鏍�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+        
+        String shapeKey = formData.get("obstacleShape");
+        
+        try {
+            String method = formData.get("drawingMethod");
+            
+            // 澶勭悊鍦嗗舰闅滅鐗�
+            if ("circle".equals(shapeKey)) {
+                if (!"mower".equals(method)) {
+                    JOptionPane.showMessageDialog(this, "鍙湁鍓茶崏鏈虹粯鍒剁殑鍦嗗舰闅滅鐗╂墠鏀寔鐢熸垚杈圭晫鍧愭爣", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+                    return;
+                }
+                
+                // 灏嗗師濮嬪潗鏍囪浆鎹负Coordinate瀵硅薄鍒楄〃
+                List<Coordinate> coordinateList = parseOriginalCoordinatesToCoordinateList(originalCoords);
+                if (coordinateList.size() < 3) {
+                    JOptionPane.showMessageDialog(this, "鍦嗗舰闅滅鐗╄嚦灏戦渶瑕佷笁涓噰闆嗙偣", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                // 瑙f瀽鍩虹珯鍧愭爣
+                String[] baseParts = baseStation.split(",");
+                if (baseParts.length < 4) {
+                    JOptionPane.showMessageDialog(this, "鍩虹珯鍧愭爣鏍煎紡鏃犳晥", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                double baseLat = parseDMToDecimal(baseParts[0].trim(), baseParts[1].trim());
+                double baseLon = parseDMToDecimal(baseParts[2].trim(), baseParts[3].trim());
+                
+                // 灏嗗師濮嬪潗鏍囪浆鎹负XY鍧愭爣锛堟湰鍦板潗鏍囩郴锛�
+                List<double[]> xyPoints = new ArrayList<>();
+                for (Coordinate coord : coordinateList) {
+                    double lat = parseDMToDecimal(coord.getLatitude(), coord.getLatDirection());
+                    double lon = parseDMToDecimal(coord.getLongitude(), coord.getLonDirection());
+                    xyPoints.add(convertLatLonToLocal(lat, lon, baseLat, baseLon));
+                }
+                
+                // 浣跨敤ThreePointCircle绠楁硶璁$畻鍦嗗績鍜屽崐寰�
+                if (xyPoints.size() < 3) {
+                    JOptionPane.showMessageDialog(this, "鑷冲皯闇�瑕佷笁涓偣鎵嶈兘鐢熸垚鍦嗗舰杈圭晫", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                // 鍙栧墠涓変釜鐐硅绠楀渾
+                double[] p1 = xyPoints.get(0);
+                double[] p2 = xyPoints.get(1);
+                double[] p3 = xyPoints.get(2);
+                
+                String point1 = String.format(Locale.US, "%.2f,%.2f", p1[0], p1[1]);
+                String point2 = String.format(Locale.US, "%.2f,%.2f", p2[0], p2[1]);
+                String point3 = String.format(Locale.US, "%.2f,%.2f", p3[0], p3[1]);
+                
+                String circleResult = bianjie.ThreePointCircle.getCircleFromPoints(point1, point2, point3);
+                
+                // 瑙f瀽缁撴灉锛氭牸寮忎负 "鍦嗗績: x,y; 鍗婂緞: r"
+                if (circleResult == null || circleResult.startsWith("閿欒")) {
+                    JOptionPane.showMessageDialog(this, "鐢熸垚鍦嗗舰杈圭晫澶辫触: " + circleResult, "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                // 瑙f瀽鍦嗗績鍜屽崐寰�
+                String[] parts = circleResult.split(";");
+                if (parts.length < 2) {
+                    JOptionPane.showMessageDialog(this, "瑙f瀽鍦嗗舰杈圭晫缁撴灉澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                // 鎻愬彇鍦嗗績鍧愭爣
+                String centerPart = parts[0].trim(); // "鍦嗗績: x,y"
+                String radiusPart = parts[1].trim(); // "鍗婂緞: r"
+                
+                String centerCoords = centerPart.substring(centerPart.indexOf(":") + 1).trim();
+                String radiusStr = radiusPart.substring(radiusPart.indexOf(":") + 1).trim();
+                
+                String[] centerXY = centerCoords.split(",");
+                if (centerXY.length < 2) {
+                    JOptionPane.showMessageDialog(this, "瑙f瀽鍦嗗績鍧愭爣澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                double centerX = Double.parseDouble(centerXY[0].trim());
+                double centerY = Double.parseDouble(centerXY[1].trim());
+                double radius = Double.parseDouble(radiusStr.trim());
+                
+                // 璁$畻鍦嗕笂涓�鐐癸紙鍦嗗績鍙充晶鐨勭偣锛�
+                double radiusX = centerX + radius;
+                double radiusY = centerY;
+                
+                // 鐢熸垚杈圭晫鍧愭爣鏍煎紡锛氬渾蹇僗,鍦嗗績Y;鍦嗕笂鐐筙,鍦嗕笂鐐筜
+                String boundaryCoords = String.format(Locale.US, "%.2f,%.2f;%.2f,%.2f", 
+                    centerX, centerY, radiusX, radiusY);
+                
+                // 淇濆瓨鐢熸垚鐨勮竟鐣屽潗鏍�
+                formData.put("generatedBoundaryCoordinates", boundaryCoords);
+                
+                // 鏇存柊杈圭晫鐘舵�佹爣绛炬樉绀猴紙鍦嗗舰鍙湁2涓偣锛氬渾蹇冨拰鍦嗕笂涓�鐐癸級
+                updateBoundaryStatusLabel(2);
+                
+                // 鏇存柊棰勮鎸夐挳鏄剧ず锛堝彉鎴愮豢鑹插彲鐐瑰嚮锛�
+                updatePreviewButtonState();
+                
+                // 鏇存柊淇濆瓨鎸夐挳鐘舵�侊紙鍙樻垚鍙偣鍑伙級
+                updateSaveButtonState();
+                
+                // 寮哄埗鍒锋柊UI
+                SwingUtilities.invokeLater(() -> {
+                    if (previewButton != null) {
+                        previewButton.revalidate();
+                        previewButton.repaint();
+                    }
+                });
+                
+                JOptionPane.showMessageDialog(this, "鍦嗗舰闅滅鐗╄竟鐣屽潗鏍囧凡鐢熸垚", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+            
+            // 澶勭悊澶氳竟褰㈤殰纰嶇墿
+            if (!"polygon".equals(shapeKey)) {
+                JOptionPane.showMessageDialog(this, "鍙湁澶氳竟褰㈡垨鍦嗗舰闅滅鐗╂墠闇�瑕佺敓鎴愯竟鐣屽潗鏍�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+            
+            // 妫�鏌ョ粯鍒舵柟寮忥紝鍙湁鍓茶崏鏈虹粯鍒剁殑澶氳竟褰㈡墠璋冪敤bianjieguihua2
+            if (!"mower".equals(method)) {
+                JOptionPane.showMessageDialog(this, "鍙湁鍓茶崏鏈虹粯鍒剁殑澶氳竟褰㈡墠鏀寔鐢熸垚杈圭晫鍧愭爣", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+            
+            // 灏嗗師濮嬪潗鏍囪浆鎹负Coordinate瀵硅薄鍒楄〃
+            List<Coordinate> coordinateList = parseOriginalCoordinatesToCoordinateList(originalCoords);
+            if (coordinateList.isEmpty()) {
+                JOptionPane.showMessageDialog(this, "鍘熷鍧愭爣鏁版嵁鏃犳晥", "閿欒", JOptionPane.ERROR_MESSAGE);
+                return;
+            }
+            
+            // 淇濆瓨褰撳墠鐨凜oordinate.coordinates
+            List<Coordinate> savedCoordinates = new ArrayList<>(Coordinate.coordinates);
+            
+            try {
+                // 璁剧疆鍒板叏灞�鍧愭爣鍒楄〃
+                Coordinate.coordinates.clear();
+                Coordinate.coordinates.addAll(coordinateList);
+                
+                // 璋冪敤bianjieguihua2绠楁硶鐢熸垚浼樺寲鍚庣殑澶氳竟褰㈣竟鐣屽潗鏍�
+                String optimizedCoordsStr = bianjieguihua2.processCoordinateListAuto(baseStation);
+                
+                if (optimizedCoordsStr == null || optimizedCoordsStr.trim().isEmpty()) {
+                    JOptionPane.showMessageDialog(this, "鐢熸垚杈圭晫鍧愭爣澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
+                    return;
+                }
+                
+                // 淇濆瓨鐢熸垚鐨勮竟鐣屽潗鏍�
+                formData.put("generatedBoundaryCoordinates", optimizedCoordsStr.trim());
+                
+                // 璁$畻鐢熸垚鐨勮竟鐣岀偣鏁�
+                int boundaryPointCount = countCoordinatePairs(optimizedCoordsStr.trim());
+                
+                // 鏇存柊杈圭晫鐘舵�佹爣绛炬樉绀�
+                updateBoundaryStatusLabel(boundaryPointCount);
+                
+                // 鏇存柊棰勮鎸夐挳鏄剧ず锛堝彉鎴愮豢鑹插彲鐐瑰嚮锛�
+                updatePreviewButtonState();
+                
+                // 鏇存柊淇濆瓨鎸夐挳鐘舵�侊紙鍙樻垚鍙偣鍑伙級
+                updateSaveButtonState();
+                
+                // 寮哄埗鍒锋柊UI
+                SwingUtilities.invokeLater(() -> {
+                    if (previewButton != null) {
+                        previewButton.revalidate();
+                        previewButton.repaint();
+                    }
+                });
+                
+                JOptionPane.showMessageDialog(this, "闅滅鐗╄竟鐣屽潗鏍囧凡鐢熸垚", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+                
+            } finally {
+                // 鎭㈠鍘熸潵鐨勫潗鏍囧垪琛�
+                Coordinate.coordinates.clear();
+                Coordinate.coordinates.addAll(savedCoordinates);
+            }
+            
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            JOptionPane.showMessageDialog(this, "鐢熸垚杈圭晫鍧愭爣鏃跺彂鐢熼敊璇�: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+    
+    /**
+     * 灏嗗師濮嬪潗鏍囧瓧绗︿覆瑙f瀽涓篊oordinate瀵硅薄鍒楄〃
+     */
+    private List<Coordinate> parseOriginalCoordinatesToCoordinateList(String originalCoords) {
+        List<Coordinate> coordinateList = new ArrayList<>();
+        if (!isMeaningfulValue(originalCoords)) {
+            return coordinateList;
+        }
+        
+        // 鍘熷鍧愭爣鏍煎紡锛氱含搴�1,鏂瑰悜1,缁忓害1,鏂瑰悜1;绾害2,鏂瑰悜2,缁忓害2,鏂瑰悜2;...
+        String[] pointStrings = originalCoords.split(";");
+        for (String pointStr : pointStrings) {
+            pointStr = pointStr.trim();
+            if (pointStr.isEmpty()) continue;
+            
+            String[] parts = pointStr.split(",");
+            if (parts.length >= 4) {
+                try {
+                    String lat = parts[0].trim();
+                    String latDir = parts[1].trim();
+                    String lon = parts[2].trim();
+                    String lonDir = parts[3].trim();
+                    
+                    Coordinate coord = new Coordinate(lat, latDir, lon, lonDir, 0.0);
+                    coordinateList.add(coord);
+                } catch (Exception e) {
+                    // 璺宠繃鏃犳晥鐨勫潗鏍囩偣
+                    continue;
+                }
+            }
+        }
+        
+        return coordinateList;
+    }
+    
+    /**
+     * 棰勮闅滅鐗╄竟鐣�
+     */
+    private void previewObstacleBoundary() {
+        String generatedBoundary = formData.get("generatedBoundaryCoordinates");
+        if (!isMeaningfulValue(generatedBoundary)) {
+            JOptionPane.showMessageDialog(this, "璇峰厛鐢熸垚闅滅鐗╄竟鐣屽潗鏍�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+        
+        String landNumber = targetDikuai.getLandNumber();
+        String landName = targetDikuai.getLandName();
+        String boundary = targetDikuai.getBoundaryCoordinates();
+        
+        // 鑾峰彇闅滅鐗╁潗鏍囷紙浼樺厛浣跨敤鐢熸垚鐨勮竟鐣屽潗鏍囷紝濡傛灉娌℃湁鍒欎娇鐢ㄥ師濮嬪潗鏍囷級
+        String obstacleCoords = generatedBoundary;
+        String shapeKey = formData.get("obstacleShape");
+        String obstacleName = formData.get("obstacleName");
+        
+        // 瀵逛簬鍦嗗舰闅滅鐗╋紝鐢熸垚鐨勮竟鐣屽潗鏍囨牸寮忓氨鏄殰纰嶇墿鍧愭爣鏍煎紡锛屽彲浠ョ洿鎺ヤ娇鐢�
+        // 瀵逛簬澶氳竟褰㈤殰纰嶇墿锛屼篃闇�瑕佷娇鐢ㄧ敓鎴愮殑杈圭晫鍧愭爣
+        // 濡傛灉鐢熸垚鐨勮竟鐣屽潗鏍囦笉鍙敤锛屽皾璇曚娇鐢ㄥ師濮嬮殰纰嶇墿鍧愭爣
+        if (!isMeaningfulValue(obstacleCoords)) {
+            obstacleCoords = formData.get("obstacleCoordinates");
+            if (!isMeaningfulValue(obstacleCoords)) {
+                JOptionPane.showMessageDialog(this, "鏃犳硶鑾峰彇闅滅鐗╁潗鏍囪繘琛岄瑙�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+        }
+        
+        // 鏋勫缓闅滅鐗╂暟鎹瓧绗︿覆锛屽寘鍚悕绉般�佸舰鐘跺拰鍧愭爣
+        // 鏍煎紡锛氶殰纰嶇墿鍚嶇О::褰㈢姸::鍧愭爣 鎴� 闅滅鐗╁悕绉�:褰㈢姸:鍧愭爣
+        final String obstacleData;
+        if (isMeaningfulValue(obstacleName) && isMeaningfulValue(shapeKey)) {
+            // 浣跨敤 :: 鍒嗛殧绗︽牸寮忥細鍚嶇О::褰㈢姸::鍧愭爣
+            obstacleData = obstacleName.trim() + "::" + shapeKey.trim() + "::" + obstacleCoords;
+        } else if (isMeaningfulValue(shapeKey)) {
+            // 鍙湁褰㈢姸锛氬舰鐘�::鍧愭爣
+            obstacleData = shapeKey.trim() + "::" + obstacleCoords;
+        } else {
+            // 鍙湁鍧愭爣
+            obstacleData = obstacleCoords;
+        }
+        
+        // 鍏抽棴褰撳墠瀵硅瘽妗�
+        setVisible(false);
+        
+        SwingUtilities.invokeLater(() -> {
+            Shouye shouye = Shouye.getInstance();
+            if (shouye != null) {
+                // 浼犻�掑洖璋冧互閲嶆柊鎵撳紑鏂板闅滅鐗╂楠�2椤甸潰
+                shouye.startMowingPathPreview(
+                    landNumber,
+                    landName,
+                    boundary,
+                    obstacleData,  // 浣跨敤鍖呭惈鍚嶇О鍜屽舰鐘剁殑闅滅鐗╂暟鎹�
+                    null,
+                    () -> SwingUtilities.invokeLater(() -> {
+                        // 閲嶆柊鎵撳紑鏂板闅滅鐗╂楠�2椤甸潰
+                        Window owner = SwingUtilities.getWindowAncestor(shouye);
+                        setVisible(true);
+                    })
+                );
+            } else {
+                JOptionPane.showMessageDialog(null, "鏃犳硶鎵撳紑涓婚〉闈㈣繘琛岄瑙�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                setVisible(true);
+            }
+        });
+    }
 
     private boolean persistObstacleToConfig(String landNumber, String previousName, String obstacleName,
                                             String shapeKey, String xyCoords, String originalCoords) {
@@ -1696,10 +2267,25 @@
         if (step < 2) {
             nextButton.setVisible(true);
             saveButton.setVisible(false);
+            if (previewButton != null) {
+                previewButton.setVisible(false);
+            }
         } else {
             nextButton.setVisible(false);
             saveButton.setVisible(true);
             updateDrawingStatus();
+            updatePreviewButtonState();
+            // 瀵逛簬鍦嗗舰闅滅鐗╋紝纭繚棰勮鎸夐挳鍜岀敓鎴愯竟鐣屾寜閽殣钘�
+            String shapeKey = formData.get("obstacleShape");
+            boolean isCircle = "circle".equals(shapeKey);
+            if (isCircle) {
+                if (previewButton != null) {
+                    previewButton.setVisible(false);
+                }
+                if (generateBoundaryButton != null) {
+                    generateBoundaryButton.setVisible(false);
+                }
+            }
         }
         updateSaveButtonState();
         revalidate();
@@ -1743,6 +2329,24 @@
         }
 
         updateDrawingStatus();
+        
+        // 濡傛灉宸叉湁鐢熸垚鐨勮竟鐣屽潗鏍囷紝鏇存柊杈圭晫鐘舵�佹爣绛�
+        String generatedBoundary = session.data.get("generatedBoundaryCoordinates");
+        if (isMeaningfulValue(generatedBoundary)) {
+            int boundaryPointCount = countCoordinatePairs(generatedBoundary);
+            updateBoundaryStatusLabel(boundaryPointCount);
+        } else {
+            // 濡傛灉娌℃湁鐢熸垚鐨勮竟鐣屽潗鏍囷紝闅愯棌杈圭晫鐘舵�佹爣绛�
+            if (boundaryStatusLabel != null) {
+                boundaryStatusLabel.setVisible(false);
+                boundaryStatusLabel.setText("");
+            }
+        }
+        
+        // 鏇存柊鎸夐挳鐘舵��
+        updatePreviewButtonState();
+        updateSaveButtonState();
+        
         currentStep = 2;
         showStep(2);
     }
@@ -1866,15 +2470,14 @@
     }
 
     private JButton createPrimaryButton(String text, int fontSize) {
-        JButton button = new JButton(text);
+        JButton button = buttonset.createStyledButton(text, PRIMARY_COLOR);
         button.setFont(new Font("寰蒋闆呴粦", Font.BOLD, fontSize));
-        button.setBackground(PRIMARY_COLOR);
-        button.setForeground(WHITE);
         button.setBorder(BorderFactory.createCompoundBorder(
                 BorderFactory.createLineBorder(PRIMARY_DARK, 2),
                 BorderFactory.createEmptyBorder(10, 22, 10, 22)));
         button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-        button.setFocusPainted(false);
+        button.setOpaque(true);
+        button.setContentAreaFilled(true);
         button.addMouseListener(new MouseAdapter() {
             @Override
             public void mouseEntered(MouseEvent e) {
@@ -1887,6 +2490,9 @@
             public void mouseExited(MouseEvent e) {
                 if (button.isEnabled()) {
                     button.setBackground(PRIMARY_COLOR);
+                } else {
+                    // 绂佺敤鏃朵繚鎸佺伆鑹茶儗鏅�
+                    button.setBackground(MEDIUM_GRAY);
                 }
             }
         });
@@ -1894,15 +2500,15 @@
     }
 
     private JButton createSecondaryButton(String text) {
-        JButton button = new JButton(text);
+        JButton button = buttonset.createStyledButton(text, MEDIUM_GRAY);
         button.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 16));
-        button.setBackground(MEDIUM_GRAY);
         button.setForeground(TEXT_COLOR);
         button.setBorder(BorderFactory.createCompoundBorder(
                 BorderFactory.createLineBorder(BORDER_COLOR, 2),
                 BorderFactory.createEmptyBorder(10, 22, 10, 22)));
         button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-        button.setFocusPainted(false);
+        button.setOpaque(true);
+        button.setContentAreaFilled(true);
         return button;
     }
 

--
Gitblit v1.10.0