From 7881cef5c3dcea8e6037101db2c3eeb2fd3ba5da Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期六, 27 十二月 2025 23:42:36 +0800
Subject: [PATCH] 1211

---
 src/gecaoji/lujingdraw.java |  369 ++++++++++++++++++++++++++++++++--------------------
 1 files changed, 229 insertions(+), 140 deletions(-)

diff --git a/src/gecaoji/lujingdraw.java b/src/gecaoji/lujingdraw.java
index 95ed85a..4d14fda 100644
--- a/src/gecaoji/lujingdraw.java
+++ b/src/gecaoji/lujingdraw.java
@@ -1,5 +1,4 @@
 package gecaoji; // 鍖呭0鏄�
-
 import java.awt.BasicStroke; // 寮曞叆鍩虹鎻忚竟绫�
 import java.awt.Color; // 寮曞叆棰滆壊绫�
 import java.awt.Graphics2D; // 寮曞叆2D鍥惧舰涓婁笅鏂�
@@ -8,7 +7,6 @@
 import java.awt.geom.Point2D; // 寮曞叆浜岀淮鐐圭被
 import java.util.ArrayList; // 寮曞叆鍔ㄦ�佹暟缁�
 import java.util.List; // 寮曞叆鍒楄〃鎺ュ彛
-import lujing.Lunjingguihua; // 寮曞叆璺緞瑙勫垝绫�
 import org.locationtech.jts.geom.Coordinate; // 寮曞叆鍧愭爣绫�
 import org.locationtech.jts.geom.GeometryFactory; // 寮曞叆鍑犱綍宸ュ巶绫�
 import org.locationtech.jts.geom.Polygon; // 寮曞叆澶氳竟褰㈢被
@@ -24,13 +22,23 @@
     // 钃濊壊 - 鐢ㄤ簬闈炰綔涓氱Щ鍔ㄨ矾寰�
     private static final Color TRAVEL_PATH_COLOR = new Color(0, 0, 255);
     // 铏氱嚎鏍峰紡 - 鐢ㄤ簬闈炰綔涓氱Щ鍔ㄨ矾寰�
-    private static final float[] DASH_PATTERN = {10.0f, 5.0f};
+    private static final float[] DASH_PATTERN = {5.0f, 5.0f};
     private static final Color START_POINT_COLOR = new Color(0, 0, 0, 220); // 璧风偣绠ご棰滆壊
     private static final Color END_POINT_COLOR = new Color(0, 0, 0, 220); // 缁堢偣绠ご棰滆壊
 
     private lujingdraw() { // 绉佹湁鏋勯�犻槻姝㈠疄渚嬪寲
     } // 绌哄疄鐜�
 
+    // 瑙f瀽缁撴灉锛氬寘鍚偣涓庢瘡涓浉閭绘鐨勪綔涓氭爣娉紙size=points.size()-1锛�
+    public static final class ParsedPath {
+        public final List<Point2D.Double> points;
+        public final List<Boolean> isMowingFlags; // 姣忔瀵瑰簲鏍囨敞锛歵rue=浣滀笟娈碉紝false=鏃呰娈�
+        public ParsedPath(List<Point2D.Double> points, List<Boolean> flags) {
+            this.points = points;
+            this.isMowingFlags = flags;
+        }
+    }
+
     /** // 鏂囨。娉ㄩ噴寮�濮�
      * Parse the planned path string (semicolon-separated "x,y" pairs) into a list of points in meters. // 鏂规硶璇存槑
      */ // 鏂囨。娉ㄩ噴缁撴潫
@@ -78,6 +86,58 @@
         return points; // 杩斿洖缁撴灉
     } // 鏂规硶缁撴潫
 
+    /**
+     * 瑙f瀽甯︽鏍囨敞鐨勮矾寰勫瓧绗︿覆銆傛牸寮忥細绗竴涓偣 "x,y"锛涘悗缁偣鍙负 "x,y,M" 鎴� "x,y,T"锛屽垎鍒〃绀轰笂涓�鐐硅嚦褰撳墠鐐逛负浣滀笟娈垫垨鏃呰娈点��
+     * 鍏煎鏃ф牸寮忥紙鏃犵涓夊瓧娈碉級锛屾鏃� flags 杩斿洖 null銆�
+     */
+    public static ParsedPath parsePlannedPathWithFlags(String plannedPath) {
+        List<Point2D.Double> points = new ArrayList<>();
+        List<Boolean> flags = new ArrayList<>();
+        if (plannedPath == null) {
+            return new ParsedPath(points, null);
+        }
+        String normalized = plannedPath.trim();
+        if (normalized.isEmpty() || "-1".equals(normalized)) {
+            return new ParsedPath(points, null);
+        }
+        int commentIndex = normalized.indexOf('#');
+        if (commentIndex >= 0) {
+            normalized = normalized.substring(0, commentIndex).trim();
+        }
+        if (normalized.isEmpty()) {
+            return new ParsedPath(points, null);
+        }
+        String[] segments = normalized.split(";");
+        boolean sawTypeField = false;
+        for (int i = 0; i < segments.length; i++) {
+            String segment = segments[i];
+            if (segment == null) continue;
+            String trimmed = segment.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());
+                points.add(new Point2D.Double(x, y));
+                if (i > 0) {
+                    // 绗竴涓偣鏃犳爣娉紱鍚庣画鑻ュ瓨鍦ㄧ涓夊瓧娈靛垯瑙f瀽
+                    if (parts.length >= 3) {
+                        String t = parts[2].trim();
+                        boolean isMowing = t.equalsIgnoreCase("M") || t.equalsIgnoreCase("m") || t.equals("1") || t.equalsIgnoreCase("WORK");
+                        flags.add(isMowing);
+                        sawTypeField = true;
+                    } else {
+                        flags.add(Boolean.TRUE); // 榛樿浣滀笟娈碉紝渚夸簬鍚戝悗鍏煎
+                    }
+                }
+            } catch (NumberFormatException ignored) {
+                // 蹇界暐闈炴硶鍧愭爣
+            }
+        }
+        return new ParsedPath(points, sawTypeField ? flags : null);
+    }
+
     /** // 鏂囨。娉ㄩ噴寮�濮�
      * Draw the planned mowing path. // 缁樺埗璺緞
      */ // 鏂囨。娉ㄩ噴缁撴潫
@@ -93,7 +153,7 @@
      * @param obstaclesCoords 闅滅鐗╁潗鏍囧瓧绗︿覆
      * @param mowingPattern 鍓茶崏妯″紡锛�"parallel"鎴�"spiral"锛�
      */ // 鏂囨。娉ㄩ噴缁撴潫
-    public static void drawPlannedPath(Graphics2D g2d, List<Point2D.Double> path, double scale, double arrowScale,
+    public static void drawPlannedPath(Graphics2D g2d, List<Point2D.Double> path, double scale, double arrowScale, 
                                       String boundaryCoords, String mowingWidth, String safetyDistance, String obstaclesCoords, String mowingPattern) { // 缁樺埗涓绘柟娉曪紙閲嶈浇锛�
         if (path == null || path.size() < 2) { // 鍒ゅ畾鐐规暟
             return; // 鏁版嵁涓嶈冻鐩存帴杩斿洖
@@ -107,72 +167,151 @@
             drawInnerBoundary(g2d, boundaryCoords, safetyDistance, scale);
         }
         
-        // 2. 灏濊瘯閲嶆柊鐢熸垚璺緞娈典互鍖哄垎浣滀笟璺緞鍜岀Щ鍔ㄨ矾寰�
-        List<Lunjingguihua.PathSegment> segments = null;
-        if (boundaryCoords != null && mowingWidth != null) {
-            try {
-                // 瑙f瀽鍓茶崏妯″紡
-                String mode = "parallel"; // 榛樿骞宠妯″紡
-                if (mowingPattern != null && !mowingPattern.trim().isEmpty()) {
-                    String pattern = mowingPattern.trim().toLowerCase();
-                    if ("1".equals(pattern) || "spiral".equals(pattern) || "铻烘棆寮�".equals(pattern) || "铻烘棆".equals(pattern)) {
-                        mode = "spiral";
-                    } else if ("parallel".equals(pattern) || "骞宠绾�".equals(pattern) || "骞宠".equals(pattern)) {
-                        mode = "parallel";
-                    }
-                }
-                segments = Lunjingguihua.generatePathSegments(
-                    boundaryCoords, 
-                    obstaclesCoords != null ? obstaclesCoords : "", 
-                    mowingWidth, 
-                    safetyDistance, 
-                    mode
-                );
-            } catch (Exception e) {
-                // 濡傛灉閲嶆柊鐢熸垚澶辫触锛屼娇鐢ㄧ畝鍗曠粯鍒舵柟寮�
-                segments = null;
+        // 2. 鎸夋缁樺埗璺緞锛堥�愭缁樺埗锛岄伩鍏嶅皢涓嶇浉閭绘棣栧熬杩炴垚瓒婄晫鐩寸嚎锛�
+        org.locationtech.jts.geom.Geometry innerBoundaryGeom = buildInnerBoundaryGeom(boundaryCoords, safetyDistance);
+        for (int i = 1; i < path.size(); i++) {
+            Point2D.Double a = path.get(i - 1);
+            Point2D.Double b = path.get(i);
+
+            Path2D segment = new Path2D.Double();
+            segment.moveTo(a.x, a.y);
+            segment.lineTo(b.x, b.y);
+
+            boolean inside = true; // 榛樿鎸変綔涓氭缁樺埗
+            if (innerBoundaryGeom != null) {
+                inside = isSegmentInsideInnerBoundary(innerBoundaryGeom, a, b);
             }
+
+            if (inside) {
+                // 浣滀笟娈碉細瀹炵嚎 + 鎻愰绾�
+                g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+                g2d.setColor(MOWING_PATH_COLOR);
+            } else {
+                // 鏃呰娈碉紙鎴栨部杈圭晫娈碉級锛氳櫄绾� + 钃濊壊
+                g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, DASH_PATTERN, 0.0f));
+                g2d.setColor(TRAVEL_PATH_COLOR);
+            }
+            g2d.draw(segment);
         }
         
-        // 3. 鏍规嵁鏄惁鏈夋淇℃伅閫夋嫨涓嶅悓鐨勭粯鍒舵柟寮�
-        if (segments != null && !segments.isEmpty()) {
-            // 鏈夋淇℃伅锛氬垎鍒粯鍒朵綔涓氳矾寰勫拰绉诲姩璺緞
-            drawPathSegments(g2d, segments, scale, arrowScale);
-        } else {
-            // 鏃犳淇℃伅锛氫娇鐢ㄧ畝鍗曠粯鍒舵柟寮忥紙鎵�鏈夎矾寰勪娇鐢ㄤ綔涓氳矾寰勯鑹诧級
-            Path2D polyline = new Path2D.Double(); // 鍒涘缓鎶樼嚎
-            boolean move = true; // 棣栨鏍囪
-            for (Point2D.Double point : path) { // 閬嶅巻鐐归泦
-                if (move) { // 绗竴娈�
-                    polyline.moveTo(point.x, point.y); // 绉诲姩鍒伴鐐�
-                    move = false; // 鏇存柊鏍囪
-                } else { // 鍚庣画娈�
-                    polyline.lineTo(point.x, point.y); // 杩炵嚎鍒颁笅涓�鐐�
-                } // if缁撴潫
-            } // for缁撴潫
-            
-            g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); // 璁剧疆鍦嗗ご鍦嗚鎻忚竟
-            g2d.setColor(MOWING_PATH_COLOR); // 璁剧疆浣滀笟璺緞棰滆壊锛堟彁棣欑孩70%閫忔槑搴︼級
-            g2d.draw(polyline); // 缁樺埗鎶樼嚎
-            
-            Point2D.Double start = path.get(0); // 璧风偣
-            Point2D.Double second = path.get(1); // 绗簩涓偣
-            Point2D.Double end = path.get(path.size() - 1); // 缁堢偣
-            Point2D.Double prev = path.get(path.size() - 2); // 鍊掓暟绗簩涓偣
+        Point2D.Double start = path.get(0); // 璧风偣
+        Point2D.Double second = path.size() > 1 ? path.get(1) : path.get(0); // 绗簩涓偣
+        Point2D.Double end = path.get(path.size() - 1); // 缁堢偣
+        Point2D.Double prev = path.size() > 1 ? path.get(path.size() - 2) : path.get(path.size() - 1); // 鍊掓暟绗簩涓偣
 
-            drawArrowMarker(g2d, start, second, START_POINT_COLOR, scale, arrowScale); // 缁樺埗璧风偣绠ご
-            drawArrowMarker(g2d, prev, end, END_POINT_COLOR, scale, arrowScale); // 缁樺埗缁堢偣绠ご
-        }
+        drawArrowMarker(g2d, start, second, START_POINT_COLOR, scale, arrowScale); // 缁樺埗璧风偣绠ご
+        drawArrowMarker(g2d, prev, end, END_POINT_COLOR, scale, arrowScale); // 缁樺埗缁堢偣绠ご
 
         g2d.setStroke(previous); // 鎭㈠鍘熸弿杈�
     } // 鏂规硶缁撴潫
+
+    /**
+     * 浣跨敤绠楁硶绔彁渚涚殑娈垫爣娉ㄧ粯鍒惰矾寰勶紙浼樺厛浣跨敤鏍囨敞锛屼笉鍋氬唴缂╄竟鐣屾帹鏂級銆�
+     * flags.size() 蹇呴』涓� path.size()-1銆�
+     */
+    public static void drawPlannedPath(Graphics2D g2d, List<Point2D.Double> path, List<Boolean> flags,
+                                       double scale, double arrowScale,
+                                       String boundaryCoords, String mowingWidth, String safetyDistance,
+                                       String obstaclesCoords, String mowingPattern) {
+        if (path == null || path.size() < 2 || flags == null || flags.size() != path.size() - 1) {
+            // 鍥為��鍒版帹鏂増鏈�
+            drawPlannedPath(g2d, path, scale, arrowScale, boundaryCoords, mowingWidth, safetyDistance, obstaclesCoords, mowingPattern);
+            return;
+        }
+
+        Stroke previous = g2d.getStroke();
+        float strokeWidth = (float) (2.5 / Math.max(0.5, scale));
+
+        // 1. 缁樺埗鍐呯缉杈圭晫锛堝洿杈癸級
+        if (boundaryCoords != null && !boundaryCoords.trim().isEmpty() && !"-1".equals(boundaryCoords.trim())) {
+            drawInnerBoundary(g2d, boundaryCoords, safetyDistance, scale);
+        }
+
+        // 2. 鎸夋缁樺埗锛屽畬鍏ㄩ伒寰畻娉曠鏍囨敞
+        for (int i = 1; i < path.size(); i++) {
+            Point2D.Double a = path.get(i - 1);
+            Point2D.Double b = path.get(i);
+            boolean isMowing = Boolean.TRUE.equals(flags.get(i - 1));
+
+            Path2D segment = new Path2D.Double();
+            segment.moveTo(a.x, a.y);
+            segment.lineTo(b.x, b.y);
+
+            if (isMowing) {
+                g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+                g2d.setColor(MOWING_PATH_COLOR);
+            } else {
+                g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10.0f, DASH_PATTERN, 0.0f));
+                g2d.setColor(TRAVEL_PATH_COLOR);
+            }
+            g2d.draw(segment);
+        }
+
+        Point2D.Double start = path.get(0);
+        Point2D.Double second = path.size() > 1 ? path.get(1) : path.get(0);
+        Point2D.Double end = path.get(path.size() - 1);
+        Point2D.Double prev = path.size() > 1 ? path.get(path.size() - 2) : path.get(path.size() - 1);
+
+        drawArrowMarker(g2d, start, second, START_POINT_COLOR, scale, arrowScale);
+        drawArrowMarker(g2d, prev, end, END_POINT_COLOR, scale, arrowScale);
+
+        g2d.setStroke(previous);
+    }
+
+    // 鏋勫缓鍐呯缉杈圭晫鍑犱綍浣擄紝鐢ㄤ簬瀹夊叏妫�娴嬩笌鍒嗘缁樺埗
+    private static org.locationtech.jts.geom.Geometry buildInnerBoundaryGeom(String boundaryCoords, String safetyDistanceStr) {
+        try {
+            if (boundaryCoords == null || boundaryCoords.trim().isEmpty() || "-1".equals(boundaryCoords.trim())) {
+                return null;
+            }
+            List<Coordinate> boundary = parseCoordinates(boundaryCoords);
+            if (boundary.size() < 4) {
+                return null; // 杈圭晫鐐逛笉瓒�
+            }
+            double safetyDistance = 0.2; // 榛樿0.2绫�
+            if (safetyDistanceStr != null && !safetyDistanceStr.trim().isEmpty()) {
+                try {
+                    safetyDistance = Double.parseDouble(safetyDistanceStr.trim());
+                } catch (NumberFormatException ignored) {}
+            }
+            GeometryFactory gf = new GeometryFactory();
+            Polygon poly = gf.createPolygon(gf.createLinearRing(boundary.toArray(new Coordinate[0])));
+            if (!poly.isValid()) {
+                poly = (Polygon) poly.buffer(0);
+            }
+            org.locationtech.jts.geom.Geometry innerBoundary = poly.buffer(-safetyDistance);
+            if (innerBoundary == null || innerBoundary.isEmpty()) {
+                return null;
+            }
+            return innerBoundary;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    // 鍒ゆ柇涓�娈垫槸鍚﹀湪鍐呯缉杈圭晫鍐呮垨娌胯竟鐣岋紙涓嶈秺鐣岋級
+    private static boolean isSegmentInsideInnerBoundary(org.locationtech.jts.geom.Geometry innerBoundary, Point2D.Double a, Point2D.Double b) {
+        try {
+            GeometryFactory gf = new GeometryFactory();
+            Coordinate[] seg = new Coordinate[] { new Coordinate(a.x, a.y), new Coordinate(b.x, b.y) };
+            org.locationtech.jts.geom.LineString ls = gf.createLineString(seg);
+            // 鍖呭惈鎴栬鐩栧潎瑙嗕负鍚堟硶锛屼笉涓庡唴杈圭晫澶栭儴浜ゅ弶
+            if (innerBoundary.contains(ls) || innerBoundary.covers(ls)) {
+                return true;
+            }
+            // 濡備笌鍐呰竟鐣岃竟鐣岀浉浜わ紝瑙嗕负涓嶅湪鍐呴儴锛堢敤浜庢敼鍙樻牱寮忓苟鏂紑杩炵嚎锛�
+            return !ls.crosses(innerBoundary.getBoundary());
+        } catch (Exception e) {
+            return true; // 妫�娴嬪紓甯告椂锛屾寜浣滀笟娈靛鐞嗕互涓嶄腑鏂粯鍒�
+        }
+    }
     
     /** // 鏂囨。娉ㄩ噴寮�濮�
      * 缁樺埗鍐呯缉杈圭晫锛堝洿杈癸級- 椹皵鏂豢鑹�
      */ // 鏂囨。娉ㄩ噴缁撴潫
     private static void drawInnerBoundary(Graphics2D g2d, String boundaryCoords, String safetyDistanceStr, double scale) {
         try {
-            List<Coordinate> boundary = Lunjingguihua.parseCoordinates(boundaryCoords);
+            List<Coordinate> boundary = parseCoordinates(boundaryCoords);
             if (boundary.size() < 4) {
                 return; // 杈圭晫鐐逛笉瓒�
             }
@@ -258,89 +397,7 @@
         }
     } // 鏂规硶缁撴潫
     
-    /** // 鏂囨。娉ㄩ噴寮�濮�
-     * 缁樺埗璺緞娈碉紙鍖哄垎浣滀笟璺緞鍜岀Щ鍔ㄨ矾寰勶級
-     */ // 鏂囨。娉ㄩ噴缁撴潫
-    private static void drawPathSegments(Graphics2D g2d, List<Lunjingguihua.PathSegment> segments, double scale, double arrowScale) {
-        if (segments == null || segments.isEmpty()) {
-            return;
-        }
-        
-        float strokeWidth = (float) (2.5 / Math.max(0.5, scale));
-        Stroke previous = g2d.getStroke();
-        
-        // 鍒嗗埆缁樺埗浣滀笟璺緞鍜岀Щ鍔ㄨ矾寰�
-        Path2D.Double mowingPath = new Path2D.Double();
-        Path2D.Double travelPath = new Path2D.Double();
-        boolean mowingStarted = false;
-        boolean travelStarted = false;
-        
-        Coordinate lastMowingEnd = null;
-        Coordinate lastTravelEnd = null;
-        
-        for (Lunjingguihua.PathSegment seg : segments) {
-            if (seg == null || seg.start == null || seg.end == null) {
-                continue;
-            }
-            
-            if (seg.isMowing) {
-                // 浣滀笟璺緞 - 鎻愰绾�70%閫忔槑搴�
-                if (!mowingStarted || lastMowingEnd == null || !equals2D(lastMowingEnd, seg.start)) {
-                    mowingPath.moveTo(seg.start.x, seg.start.y);
-                    mowingStarted = true;
-                }
-                mowingPath.lineTo(seg.end.x, seg.end.y);
-                lastMowingEnd = seg.end;
-            } else {
-                // 绉诲姩璺緞 - 钃濊壊铏氱嚎
-                if (!travelStarted || lastTravelEnd == null || !equals2D(lastTravelEnd, seg.start)) {
-                    travelPath.moveTo(seg.start.x, seg.start.y);
-                    travelStarted = true;
-                }
-                travelPath.lineTo(seg.end.x, seg.end.y);
-                lastTravelEnd = seg.end;
-            }
-        }
-        
-        // 缁樺埗浣滀笟璺緞
-        if (mowingStarted) {
-            g2d.setColor(MOWING_PATH_COLOR); // 鎻愰绾�70%閫忔槑搴�
-            g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
-            g2d.draw(mowingPath);
-        }
-        
-        // 缁樺埗绉诲姩璺緞锛堣櫄绾匡級
-        if (travelStarted) {
-            g2d.setColor(TRAVEL_PATH_COLOR); // 钃濊壊
-            g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, DASH_PATTERN, 0));
-            g2d.draw(travelPath);
-        }
-        
-        // 缁樺埗璧风偣鍜岀粓鐐圭澶�
-        if (!segments.isEmpty()) {
-            Lunjingguihua.PathSegment firstSeg = segments.get(0);
-            if (firstSeg != null && firstSeg.start != null && segments.size() > 1) {
-                Lunjingguihua.PathSegment secondSeg = segments.get(1);
-                if (secondSeg != null && secondSeg.start != null) {
-                    Point2D.Double start = new Point2D.Double(firstSeg.start.x, firstSeg.start.y);
-                    Point2D.Double second = new Point2D.Double(secondSeg.start.x, secondSeg.start.y);
-                    drawArrowMarker(g2d, start, second, START_POINT_COLOR, scale, arrowScale);
-                }
-            }
-            
-            Lunjingguihua.PathSegment lastSeg = segments.get(segments.size() - 1);
-            if (lastSeg != null && lastSeg.end != null && segments.size() > 1) {
-                Lunjingguihua.PathSegment prevSeg = segments.get(segments.size() - 2);
-                if (prevSeg != null && prevSeg.end != null) {
-                    Point2D.Double prev = new Point2D.Double(prevSeg.end.x, prevSeg.end.y);
-                    Point2D.Double end = new Point2D.Double(lastSeg.end.x, lastSeg.end.y);
-                    drawArrowMarker(g2d, prev, end, END_POINT_COLOR, scale, arrowScale);
-                }
-            }
-        }
-        
-        g2d.setStroke(previous);
-    } // 鏂规硶缁撴潫
+
     
     /** // 鏂囨。娉ㄩ噴寮�濮�
      * 姣旇緝涓や釜鍧愭爣鏄惁鐩稿悓锛堝宸級
@@ -392,4 +449,36 @@
         g2d.setColor(color); // 璁剧疆棰滆壊
         g2d.fill(arrow); // 濉厖绠ご
     } // 鏂规硶缁撴潫
+
+    /**
+     * 瑙f瀽鍧愭爣瀛楃涓�
+     */
+    private static List<Coordinate> parseCoordinates(String s) {
+        List<Coordinate> list = new ArrayList<>();
+        if (s == null || s.trim().isEmpty()) return list;
+        // 澧炲己姝e垯锛氬鐞嗗彲鑳藉瓨鍦ㄧ殑澶氱鍒嗛殧绗�
+        String[] pts = s.split("[;\\s]+");
+        for (String p : pts) {
+            String trimmed = p.trim().replace("(", "").replace(")", "");
+            if (trimmed.isEmpty()) continue;
+            String[] xy = trimmed.split("[,锛孿\s]+");
+            if (xy.length >= 2) {
+                try {
+                    double x = Double.parseDouble(xy[0].trim());
+                    double y = Double.parseDouble(xy[1].trim());
+                    // 杩囨护鏃犳晥鍧愭爣
+                    if (!Double.isNaN(x) && !Double.isNaN(y) && !Double.isInfinite(x) && !Double.isInfinite(y)) {
+                        list.add(new Coordinate(x, y));
+                    }
+                } catch (NumberFormatException ex) {
+                    // 蹇界暐瑙f瀽閿欒鐨勭偣
+                }
+            }
+        }
+        // 纭繚澶氳竟褰㈤棴鍚�
+        if (list.size() > 2 && !list.get(0).equals2D(list.get(list.size() - 1))) {
+            list.add(new Coordinate(list.get(0)));
+        }
+        return list;
+    }
 } // 绫荤粨鏉�

--
Gitblit v1.10.0