张世豪
2025-12-12 3e3bd3a148990fb485323b67b9c0edb5bfb4b5e5
删除了自检提示功能
已添加7个文件
已修改2个文件
160 ■■■■■ 文件已修改
image/gps0.png 补丁 | 查看 | 原始文档 | blame | 历史
image/gps1.png 补丁 | 查看 | 原始文档 | blame | 历史
image/gps2.png 补丁 | 查看 | 原始文档 | blame | 历史
image/gps4.png 补丁 | 查看 | 原始文档 | blame | 历史
image/gps5.png 补丁 | 查看 | 原始文档 | blame | 历史
set.properties 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/gecaoji/MowerBoundaryChecker.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/AppLauncher.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/zhuye/Shouye.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
image/gps0.png
image/gps1.png
image/gps2.png
image/gps4.png
image/gps5.png
set.properties
@@ -1,5 +1,5 @@
#Current work land selection updated
#Thu Dec 11 17:40:50 CST 2025
#Fri Dec 12 15:13:55 CST 2025
appVersion=-1
currentWorkLandNumber=LAND1
cuttingWidth=200
src/gecaoji/MowerBoundaryChecker.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,117 @@
package gecaoji;
import java.awt.geom.Point2D;
import java.util.List;
/**
 * å‰²è‰æœºè¾¹ç•Œæ£€æŸ¥å·¥å…·ç±»ã€‚
 *
 * ç”¨æ³•契约:
 * - è¾“入的地块边界为闭合的多边形点序列(顺序为顺时针或逆时针均可),每个点包含 X(米)、Y(米)坐标。
 * - è‹¥ç‚¹ä½äºŽå¤šè¾¹å½¢å†…部或位于边界线上,返回 true;否则返回 false。
 */
public final class MowerBoundaryChecker {
    private MowerBoundaryChecker() { }
    /**
     * åˆ¤æ–­ç»™å®šç‚¹æ˜¯å¦åœ¨è¾¹ç•Œå¤šè¾¹å½¢å†…部(含边界)。
     *
     * @param polygonPoints è¾¹ç•Œç‚¹åˆ—表,每个元素为 double[2],索引0为x,索引1为y;至少需要3个点
     * @param x å‰²è‰æœºå®žæ—¶X坐标(米)
     * @param y å‰²è‰æœºå®žæ—¶Y坐标(米)
     * @return å¦‚果点在多边形内部或边界上则返回 true;否则返回 false
     */
    public static boolean isInsideBoundary(List<double[]> polygonPoints, double x, double y) {
        if (polygonPoints == null || polygonPoints.size() < 3) {
            return false;
        }
        int n = polygonPoints.size();
        boolean inside = false;
        for (int i = 0, j = n - 1; i < n; j = i++) {
            double xi = polygonPoints.get(i)[0];
            double yi = polygonPoints.get(i)[1];
            double xj = polygonPoints.get(j)[0];
            double yj = polygonPoints.get(j)[1];
            // åˆ¤æ–­ç‚¹æ˜¯å¦åœ¨å½“前边上(考虑浮点容差)
            if (pointOnSegment(xj, yj, xi, yi, x, y)) {
                return true;
            }
            boolean intersect = ((yi > y) != (yj > y)) &&
                    (x < (xj - xi) * (y - yi) / (yj - yi + 0.0) + xi);
            if (intersect) {
                inside = !inside;
            }
        }
        return inside;
    }
    /**
     * é‡è½½ï¼šæŽ¥å— Point2D åˆ—表
     */
    public static boolean isInsideBoundaryPoints(List<Point2D.Double> polygonPoints, double x, double y) {
        if (polygonPoints == null || polygonPoints.size() < 3) {
            return false;
        }
        int n = polygonPoints.size();
        boolean inside = false;
        for (int i = 0, j = n - 1; i < n; j = i++) {
            double xi = polygonPoints.get(i).x;
            double yi = polygonPoints.get(i).y;
            double xj = polygonPoints.get(j).x;
            double yj = polygonPoints.get(j).y;
            if (pointOnSegment(xj, yj, xi, yi, x, y)) {
                return true;
            }
            boolean intersect = ((yi > y) != (yj > y)) &&
                    (x < (xj - xi) * (y - yi) / (yj - yi + 0.0) + xi);
            if (intersect) {
                inside = !inside;
            }
        }
        return inside;
    }
    /**
     * é‡è½½ï¼šæŽ¥å—二维数组 double[][],每行 [x,y]
     */
    public static boolean isInsideBoundary(double[][] polygon, double x, double y) {
        if (polygon == null || polygon.length < 3) {
            return false;
        }
        int n = polygon.length;
        boolean inside = false;
        for (int i = 0, j = n - 1; i < n; j = i++) {
            double xi = polygon[i][0];
            double yi = polygon[i][1];
            double xj = polygon[j][0];
            double yj = polygon[j][1];
            if (pointOnSegment(xj, yj, xi, yi, x, y)) {
                return true;
            }
            boolean intersect = ((yi > y) != (yj > y)) &&
                    (x < (xj - xi) * (y - yi) / (yj - yi + 0.0) + xi);
            if (intersect) {
                inside = !inside;
            }
        }
        return inside;
    }
    // åˆ¤æ–­ç‚¹æ˜¯å¦åœ¨çº¿æ®µ (x1,y1)-(x2,y2) ä¸Šï¼ˆåŒ…括端点),允许小的数值误差
    private static boolean pointOnSegment(double x1, double y1, double x2, double y2, double px, double py) {
        double cross = (px - x1) * (y2 - y1) - (py - y1) * (x2 - x1);
        double eps = 1e-8;
        if (Math.abs(cross) > eps) {
            return false;
        }
        double dot = (px - x1) * (px - x2) + (py - y1) * (py - y2);
        return dot <= eps;
    }
}
src/zhuye/AppLauncher.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,32 @@
package zhuye;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import udpdell.UDPServer;
/**
 * ç¨‹åºå…¥å£å¯åŠ¨ç±»ï¼ˆSwing æ¡Œé¢å¯åŠ¨å™¨ï¼‰ã€‚
 * ä½¿ç”¨æ­¤ç±»ä½œä¸ºè¿è¡Œé…ç½®çš„主类,保证有明确的 main æ–¹æ³•。
 */
public class AppLauncher {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("AutoMow - é¦–页");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400, 800);
            frame.setLocationRelativeTo(null);
            Shouye shouye = new Shouye();
            frame.add(shouye);
            frame.setVisible(true);
            // å¯åŠ¨æ•°æ®æŽ¥æ”¶çº¿ç¨‹ï¼ˆå¦‚æžœå·²å®žçŽ°ï¼‰
            try {
                UDPServer.startAsync();
            } catch (Throwable ignored) {
                // å¿½ç•¥å¯åŠ¨è¿‡ç¨‹ä¸­å¯èƒ½å‘ç”Ÿçš„å¼‚å¸¸ï¼Œé¿å…ä¸»çº¿ç¨‹å´©æºƒ
            }
        });
    }
}
src/zhuye/Shouye.java
@@ -213,7 +213,8 @@
    }
    private void showInitialMowerSelfCheckDialogIfNeeded() {
        zijian.showInitialPromptIfNeeded(this, this::showRemoteControlDialog);
        // å·²ç§»é™¤è¿›å…¥ä¸»é¡µæ—¶çš„自检提示(按用户要求删除)
        // ä»¥å‰è¿™é‡Œä¼šè°ƒç”¨ zijian.showInitialPromptIfNeeded(...) å±•示自检对话框,现已禁用。
    }
    private void applyIdleTrailDurationFromSettings() {
@@ -1125,9 +1126,9 @@
            return;
        }
        if (startButtonShowingPause) {
            if (!zijian.ensureBeforeMowing(this, this::showRemoteControlDialog)) {
                return;
            }
            // ç‚¹å‡»å¼€å§‹æŒ‰é’®æ—¶ä¸å†å¼¹å‡ºè‡ªæ£€æç¤ºï¼ˆæŒ‰ç”¨æˆ·è¦æ±‚删除)
            // æ—§é€»è¾‘:调用 zijian.ensureBeforeMowing(...) å¹¶åœ¨æœªç¡®è®¤è‡ªæ£€æ—¶é˜»æ­¢å¼€å§‹
            // æ–°é€»è¾‘:直接允许开始作业
        }
        startButtonShowingPause = !startButtonShowingPause;
        if (!startButtonShowingPause) {