张世豪
6 天以前 b315a6943e6c0d6bdf0d5f7565c570d719154d6c
src/zhuye/MapRenderer.java
@@ -52,6 +52,7 @@
    private static final Color GRASS_FILL_COLOR = new Color(144, 238, 144, 120);
    private static final Color GRASS_BORDER_COLOR = new Color(60, 179, 113);
    private static final Color BOUNDARY_POINT_COLOR = new Color(128, 0, 128);
    private static final Color OBSTACLE_POINT_COLOR = new Color(255, 140, 0); // 橙色,用于区分障碍物点
    private static final Color CIRCLE_SAMPLE_COLOR = new Color(220, 20, 60, 230);
    private static final double CIRCLE_SAMPLE_SIZE = 0.54d;
    private static final double BOUNDARY_POINT_MERGE_THRESHOLD = 0.05;
@@ -71,6 +72,7 @@
    private String currentObstacleLandNumber;
    private String boundaryName;
    private boolean boundaryPointsVisible;
    private boolean obstaclePointsVisible;
    private double boundaryPointSizeScale = 1.0d;
    private boolean previewSizingEnabled;
    private String currentBoundaryLandNumber;
@@ -114,14 +116,15 @@
        this.mowerUpdateTimer = createMowerTimer();
        this.mowerInfoManager = new GecaojiMeg(visualizationPanel, mower);
        setupMouseListeners();
        // 从配置文件读取上次保存的缩放比例
        loadScaleFromProperties();
        // 从配置文件读取上次保存的缩放比例和视图中心坐标
        loadViewSettingsFromProperties();
    }
    
    /**
     * 从配置文件读取缩放比例
     * 从配置文件读取缩放比例和视图中心坐标
     */
    private void loadScaleFromProperties() {
    private void loadViewSettingsFromProperties() {
        // 加载缩放比例
        String scaleValue = Setsys.getPropertyValue(MAP_SCALE_PROPERTY);
        if (scaleValue != null && !scaleValue.trim().isEmpty()) {
            try {
@@ -140,6 +143,28 @@
            // 如果没有保存的值,使用默认值
            scale = DEFAULT_SCALE;
        }
        // 加载视图中心坐标
        String viewCenterXValue = Setsys.getPropertyValue("viewCenterX");
        String viewCenterYValue = Setsys.getPropertyValue("viewCenterY");
        if (viewCenterXValue != null && !viewCenterXValue.trim().isEmpty()) {
            try {
                translateX = Double.parseDouble(viewCenterXValue.trim());
            } catch (NumberFormatException e) {
                translateX = 0.0;
            }
        } else {
            translateX = 0.0;
        }
        if (viewCenterYValue != null && !viewCenterYValue.trim().isEmpty()) {
            try {
                translateY = Double.parseDouble(viewCenterYValue.trim());
            } catch (NumberFormatException e) {
                translateY = 0.0;
            }
        } else {
            translateY = 0.0;
        }
    }
    
    /**
@@ -147,7 +172,8 @@
     */
    private void saveScaleToProperties() {
        Setsys setsys = new Setsys();
        setsys.updateProperty(MAP_SCALE_PROPERTY, String.valueOf(scale));
        // 保留2位小数
        setsys.updateProperty(MAP_SCALE_PROPERTY, String.format("%.2f", scale));
    }
    
    /**
@@ -322,14 +348,11 @@
        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);
        }
        yulanzhangaiwu.renderPreview(g2d, scale);
        if (!circleSampleMarkers.isEmpty()) {
@@ -342,10 +365,16 @@
    adddikuaiyulan.drawPreview(g2d, handheldBoundaryPreview, scale, handheldBoundaryPreviewActive, boundaryPreviewMarkerScale);
        // 绘制导航路径(中层)
        if (hasPlannedPath) {
            drawCurrentPlannedPath(g2d);
        }
        // 绘制障碍物(顶层,显示在地块和导航路径上方)
        if (hasObstacles) {
            Obstacledraw.drawObstacles(g2d, currentObstacles, scale, selectedObstacleName);
        }
        if (boundaryPointsVisible && hasBoundary) {
            double markerScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d);
            pointandnumber.drawBoundaryPoints(
@@ -358,6 +387,22 @@
            );
        }
        // 绘制障碍物坐标点
        if (obstaclePointsVisible && hasObstacles) {
            List<Point2D.Double> obstaclePoints = Obstacledraw.getObstaclePoints(currentObstacles);
            if (obstaclePoints != null && !obstaclePoints.isEmpty()) {
                double markerScale = boundaryPointSizeScale * (previewSizingEnabled ? PREVIEW_BOUNDARY_MARKER_SCALE : 1.0d);
                pointandnumber.drawBoundaryPoints(
                    g2d,
                    obstaclePoints,
                    scale,
                    BOUNDARY_POINT_MERGE_THRESHOLD,
                    OBSTACLE_POINT_COLOR,
                    markerScale
                );
            }
        }
        if (shouldRenderIdleTrail()) {
            tuowei.draw(g2d, idleMowerTrail, scale);
        }
@@ -1328,7 +1373,7 @@
    
    /**
     * 判断定位状态是否有效,可用于显示拖尾
     * 接受状态1(单点定位)和4(固定解)
     * 接受状态1(单点定位)、2(码差分)、3(无效PPS)、4(固定解)、5(浮点解)
     */
    private boolean isValidFixForTrail(String fixQuality) {
        if (fixQuality == null) {
@@ -1338,14 +1383,15 @@
        if (trimmed.isEmpty()) {
            return false;
        }
        // 接受状态1(单点定位)和4(固定解)
        if ("1".equals(trimmed) || "4".equals(trimmed)) {
        // 接受状态1,2,3,4,5(只要不是0或无效状态)
        if ("1".equals(trimmed) || "2".equals(trimmed) || "3".equals(trimmed) ||
            "4".equals(trimmed) || "5".equals(trimmed)) {
            return true;
        }
        try {
            double value = Double.parseDouble(trimmed);
            // 接受1.0或4.0
            return Math.abs(value - 1.0d) < 1e-6 || Math.abs(value - 4.0d) < 1e-6;
            // 接受1.0, 2.0, 3.0, 4.0, 5.0(只要不是0)
            return value >= 1.0 && value <= 5.0;
        } catch (NumberFormatException ex) {
            return false;
        }
@@ -1718,6 +1764,7 @@
        obstacleBounds = null;
        selectedObstacleName = null;
        currentObstacleLandNumber = null;
        obstaclePointsVisible = false;
    }
    private List<Obstacledge.Obstacle> parseObstacles(String obstaclesData, String landNumber) {
@@ -2005,6 +2052,11 @@
        visualizationPanel.repaint();
    }
    public void setObstaclePointsVisible(boolean visible) {
        this.obstaclePointsVisible = visible;
        visualizationPanel.repaint();
    }
    public void setBoundaryPointSizeScale(double sizeScale) {
        double normalized = (Double.isFinite(sizeScale) && sizeScale > 0.0d) ? sizeScale : 1.0d;
        if (Math.abs(boundaryPointSizeScale - normalized) < 1e-6) {