From f94b1436d7a28c8e28d010b2cb657ab7c064e353 Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期日, 28 十二月 2025 20:36:38 +0800
Subject: [PATCH] 修改了导航预览
---
src/gecaoji/Gecaoji.java | 5
dikuai.properties | 6
src/dikuai/daohangyulan.java | 48 ++
src/lujing/DebugPath.java | 105 +++++++
src/lujing/YixinglujingNoObstacle.java | 217 ++++++++++++++
src/lujing/YixinglujingHaveObstacel.java | 357 +++++++++++++++++++++++++
src/zhangaiwu/AddDikuai.java | 20 +
src/zhuye/MapRenderer.java | 24
set.properties | 6
src/zhuye/Shouye.java | 18 +
Obstacledge.properties | 2
11 files changed, 750 insertions(+), 58 deletions(-)
diff --git a/Obstacledge.properties b/Obstacledge.properties
index 12f403d..e66a7a4 100644
--- a/Obstacledge.properties
+++ b/Obstacledge.properties
@@ -1,5 +1,5 @@
# 鍓茶崏鏈哄湴鍧楅殰纰嶇墿閰嶇疆鏂囦欢
-# 鐢熸垚鏃堕棿锛�2025-12-27T23:31:09.655894400
+# 鐢熸垚鏃堕棿锛�2025-12-28T20:21:18.532091
# 鍧愭爣绯伙細WGS84锛堝害鍒嗘牸寮忥級
# ============ 鍦板潡鍩哄噯绔欓厤缃� ============
diff --git a/dikuai.properties b/dikuai.properties
index 74599a9..ac01d2b 100644
--- a/dikuai.properties
+++ b/dikuai.properties
@@ -1,5 +1,5 @@
#Dikuai Properties
-#Sat Dec 27 23:31:09 GMT+08:00 2025
+#Sun Dec 28 20:21:18 GMT+08:00 2025
LAND1.intelligentSceneAnalysis=-1
LAND1.mowingSafetyDistance=0.53
LAND1.landArea=577.12
@@ -11,8 +11,8 @@
LAND1.returnPathRawCoordinates=-1
LAND1.boundaryOriginalXY=-1
LAND1.mowingWidth=1.00
-LAND1.plannedPath=73.82,49.86;50.78,49.99,M;41.98,22.49,M;49.63,20.04,M;51.80,34.27,M;66.28,36.75,M;66.34,21.40,M;78.08,24.80,M;73.82,49.86,M;73.87,49.87;73.87,49.87,T;73.87,49.87,T;73.87,49.87,T;73.87,49.87,T;73.96,49.37,T;73.96,49.37,T;73.96,49.37,T;73.96,49.37,T;73.96,49.37,T;73.91,49.36;50.66,49.52,M;50.62,49.54;50.62,49.54,T;50.62,49.54,T;50.62,49.54,T;50.62,49.54,T;50.30,48.54,T;50.30,48.54,T;50.30,48.54,T;50.30,48.54,T;50.30,48.54,T;50.35,48.53;74.07,48.36,M;74.12,48.37;74.12,48.37,T;74.12,48.37,T;74.12,48.37,T;74.12,48.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.24,47.36;50.03,47.53,M;49.98,47.54;49.98,47.54,T;49.98,47.54,T;49.98,47.54,T;49.98,47.54,T;49.66,46.55,T;49.66,46.55,T;49.66,46.55,T;49.66,46.55,T;49.66,46.55,T;49.71,46.53;74.41,46.36,M;74.46,46.37;74.46,46.37,T;74.46,46.37,T;74.46,46.37,T;74.46,46.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.58,45.36;49.39,45.53,M;49.34,45.55;49.34,45.55,T;49.34,45.55,T;49.34,45.55,T;49.34,45.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.07,44.53;74.75,44.36,M;74.80,44.37;74.80,44.37,T;74.80,44.37,T;74.80,44.37,T;74.80,44.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.91,43.36;48.75,43.54,M;48.71,43.55;48.71,43.55,T;48.71,43.55,T;48.71,43.55,T;48.71,43.55,T;48.39,42.55,T;48.39,42.55,T;48.39,42.55,T;48.39,42.55,T;48.39,42.55,T;48.43,42.54;75.08,42.36,M;75.13,42.36;75.13,42.36,T;75.13,42.36,T;75.13,42.36,T;75.13,42.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.25,41.35;48.12,41.54,M;48.07,41.56;48.07,41.56,T;48.07,41.56,T;48.07,41.56,T;48.07,41.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;75.47,40.36,M;75.47,40.36,T;75.47,40.36,T;75.47,40.36,T;75.47,40.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.59,39.35;47.48,39.55,M;47.43,39.56;47.43,39.56,T;47.43,39.56,T;47.43,39.56,T;47.43,39.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.16,38.55;75.75,38.35,M;75.80,38.36;75.80,38.36,T;75.80,38.36,T;75.80,38.36,T;75.80,38.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;46.79,37.57,M;46.79,37.57,T;46.79,37.57,T;46.79,37.57,T;46.79,37.57,T;41.97,22.44,T;41.97,22.44,T;41.97,22.44,T;41.97,22.44,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;66.29,36.70,T;66.29,36.70,T;66.29,36.70,T;66.29,36.70,T;66.29,36.43,T;66.29,36.43,T;66.29,36.43,T;66.29,36.43,T;66.29,36.43,T;66.34,36.43;76.09,36.35,M;76.14,36.36;76.14,36.36,T;76.14,36.36,T;76.14,36.36,T;76.14,36.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;66.29,35.43,M;66.29,35.43,T;66.29,35.43,T;66.29,35.43,T;66.29,35.43,T;66.29,34.43,T;66.29,34.43,T;66.29,34.43,T;66.29,34.43,T;66.29,34.43,T;66.34,34.43;76.43,34.35,M;76.48,34.35;76.48,34.35,T;76.48,34.35,T;76.48,34.35,T;76.48,34.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.60,33.34;66.34,33.43,M;66.29,33.43;66.29,33.43,T;66.29,33.43,T;66.29,33.43,T;66.29,33.43,T;66.29,32.43,T;66.29,32.43,T;66.29,32.43,T;66.29,32.43,T;66.29,32.43,T;66.34,32.43;76.76,32.34,M;76.81,32.35;76.81,32.35,T;76.81,32.35,T;76.81,32.35,T;76.81,32.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.93,31.34;66.34,31.43,M;66.29,31.43;66.29,31.43,T;66.29,31.43,T;66.29,31.43,T;66.29,31.43,T;66.29,30.43,T;66.29,30.43,T;66.29,30.43,T;66.29,30.43,T;66.29,30.43,T;66.34,30.43;77.10,30.34,M;77.15,30.35;77.15,30.35,T;77.15,30.35,T;77.15,30.35,T;77.15,30.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.27,29.34;66.34,29.43,M;66.29,29.43;66.29,29.43,T;66.29,29.43,T;66.29,29.43,T;66.29,29.43,T;66.29,28.43,T;66.29,28.43,T;66.29,28.43,T;66.29,28.43,T;66.29,28.43,T;66.34,28.43;77.44,28.34,M;77.48,28.35;77.48,28.35,T;77.48,28.35,T;77.48,28.35,T;77.48,28.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.60,27.34;66.34,27.43,M;66.29,27.43;66.29,27.43,T;66.29,27.43,T;66.29,27.43,T;66.29,27.43,T;66.29,26.43,T;66.29,26.43,T;66.29,26.43,T;66.29,26.43,T;66.29,26.43,T;66.34,26.43;77.77,26.34,M;77.82,26.34;77.82,26.34,T;77.82,26.34,T;77.82,26.34,T;77.82,26.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.94,25.34;66.34,25.43,M;66.29,25.43;66.29,25.43,T;66.29,25.43,T;66.29,25.43,T;66.29,25.43,T;66.29,24.43,T;66.29,24.43,T;66.29,24.43,T;66.29,24.43,T;66.29,24.43,T;66.34,24.43;76.67,24.40,M;76.69,24.35;76.69,24.35,T;76.69,24.35,T;76.69,24.35,T;76.69,24.35,T;73.25,23.38,T;73.25,23.38,T;73.25,23.38,T;73.25,23.38,T;73.25,23.38,T;73.24,23.43;66.34,23.43,M;66.29,23.43;66.29,23.43,T;66.29,23.43,T;66.29,23.43,T;66.29,23.43,T;66.29,22.43,T;66.29,22.43,T;66.29,22.43,T;66.29,22.43,T;66.29,22.43,T;66.34,22.43;69.80,22.45,M;69.81,22.40;69.81,22.40,T;69.81,22.40,T;69.81,22.40,T;69.81,22.40,T;66.38,21.43,T;66.38,21.43,T;66.38,21.43,T;66.38,21.43,T;66.38,21.43,T;66.36,21.47;66.34,21.43,M;66.29,21.43;66.29,21.43,T;66.29,21.43,T;66.29,21.43,T;66.29,21.43,T;66.29,36.70,T;66.29,36.70,T;66.29,36.70,T;66.29,36.70,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;47.85,20.56,T;47.85,20.56,T;47.85,20.56,T;47.85,20.56,T;47.85,20.56,T;47.87,20.60;49.65,20.55,M;49.70,20.54;49.70,20.54,T;49.70,20.54,T;49.70,20.54,T;49.70,20.54,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;41.97,22.44,T;41.97,22.44,T;41.97,22.44,T;41.97,22.44,T;46.48,36.57,T;46.48,36.57,T;46.48,36.57,T;46.48,36.57,T;46.48,36.57,T;46.52,36.55;64.75,36.49,M;64.75,36.44;64.75,36.44,T;64.75,36.44,T;64.75,36.44,T;64.75,36.44,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.06,35.53;46.20,35.55,M;46.16,35.57;46.16,35.57,T;46.16,35.57,T;46.16,35.57,T;46.16,35.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.89,34.56;53.37,34.57,M;53.38,34.52;53.38,34.52,T;53.38,34.52,T;53.38,34.52,T;53.38,34.52,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.68,33.54;45.57,33.56,M;45.52,33.57;45.52,33.57,T;45.52,33.57,T;45.52,33.57,T;45.52,33.57,T;45.20,32.58,T;45.20,32.58,T;45.20,32.58,T;45.20,32.58,T;45.20,32.58,T;45.25,32.56;51.53,32.54,M;51.57,32.53;51.57,32.53,T;51.57,32.53,T;51.57,32.53,T;51.57,32.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.37,31.54;44.93,31.56,M;44.88,31.58;44.88,31.58,T;44.88,31.58,T;44.88,31.58,T;44.88,31.58,T;44.56,30.58,T;44.56,30.58,T;44.56,30.58,T;44.56,30.58,T;44.56,30.58,T;44.61,30.57;51.21,30.54,M;51.26,30.53;51.26,30.53,T;51.26,30.53,T;51.26,30.53,T;51.26,30.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.06,29.54;44.29,29.57,M;44.25,29.58;44.25,29.58,T;44.25,29.58,T;44.25,29.58,T;44.25,29.58,T;43.93,28.59,T;43.93,28.59,T;43.93,28.59,T;43.93,28.59,T;43.93,28.59,T;43.97,28.57;50.90,28.54,M;50.95,28.54;50.95,28.54,T;50.95,28.54,T;50.95,28.54,T;50.95,28.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.74,27.54;43.66,27.57,M;43.61,27.59;43.61,27.59,T;43.61,27.59,T;43.61,27.59,T;43.61,27.59,T;43.29,26.59,T;43.29,26.59,T;43.29,26.59,T;43.29,26.59,T;43.29,26.59,T;43.34,26.57;50.59,26.55,M;50.64,26.54;50.64,26.54,T;50.64,26.54,T;50.64,26.54,T;50.64,26.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.43,25.55;43.02,25.58,M;42.97,25.59;42.97,25.59,T;42.97,25.59,T;42.97,25.59,T;42.97,25.59,T;42.65,24.59,T;42.65,24.59,T;42.65,24.59,T;42.65,24.59,T;42.65,24.59,T;42.70,24.58;50.27,24.55,M;50.32,24.54;50.32,24.54,T;50.32,24.54,T;50.32,24.54,T;50.32,24.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.12,23.55;42.38,23.58,M;42.33,23.60;42.33,23.60,T;42.33,23.60,T;42.33,23.60,T;42.33,23.60,T;42.02,22.60,T;42.02,22.60,T;42.02,22.60,T;42.02,22.60,T;42.02,22.60,T;42.06,22.58;49.96,22.55,M;50.01,22.54;50.01,22.54,T;50.01,22.54,T;50.01,22.54,T;50.01,22.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.81,21.55;44.68,21.63,M
-LAND1.updateTime=2025-12-27 23\:31\:09
+LAND1.plannedPath=73.82,49.86;50.78,49.99,M;41.98,22.49,M;49.63,20.04,M;51.80,34.27,M;66.28,36.75,M;66.34,21.40,M;78.08,24.80,M;73.82,49.86,M;73.87,49.87;73.87,49.87,T;73.87,49.87,T;73.87,49.87,T;73.96,49.37,T;73.96,49.37,T;73.96,49.37,T;73.96,49.37,T;73.91,49.36;50.66,49.52,M;50.62,49.54;50.30,48.54,T;50.35,48.53;74.07,48.36,M;74.12,48.37;74.12,48.37,T;74.12,48.37,T;74.12,48.37,T;74.12,48.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.29,47.37,T;74.24,47.36;50.03,47.53,M;49.98,47.54;49.66,46.55,T;49.71,46.53;74.41,46.36,M;74.46,46.37;74.46,46.37,T;74.46,46.37,T;74.46,46.37,T;74.46,46.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.63,45.37,T;74.58,45.36;49.39,45.53,M;49.34,45.55;49.34,45.55,T;49.34,45.55,T;49.34,45.55,T;49.34,45.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.02,44.55,T;49.07,44.53;74.75,44.36,M;74.80,44.37;74.80,44.37,T;74.80,44.37,T;74.80,44.37,T;74.80,44.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.96,43.37,T;74.91,43.36;48.75,43.54,M;48.71,43.55;48.71,43.55,T;48.39,42.55,T;48.39,42.55,T;48.39,42.55,T;48.39,42.55,T;48.43,42.54;75.08,42.36,M;75.13,42.36;75.13,42.36,T;75.13,42.36,T;75.13,42.36,T;75.13,42.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.30,41.36,T;75.25,41.35;48.12,41.54,M;48.07,41.56;48.07,41.56,T;48.07,41.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;47.75,40.56,T;75.47,40.36,M;75.47,40.36,T;75.47,40.36,T;75.47,40.36,T;75.47,40.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.64,39.36,T;75.59,39.35;47.48,39.55,M;47.43,39.56;47.43,39.56,T;47.43,39.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.11,38.56,T;47.16,38.55;75.75,38.35,M;75.80,38.36;75.80,38.36,T;75.80,38.36,T;75.80,38.36,T;75.80,38.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;75.97,37.36,T;46.79,37.57,M;46.79,37.57,T;41.97,22.44,T;49.61,19.99,T;51.85,34.26,T;65.10,36.50,T;65.10,36.50,T;65.10,36.50,T;65.10,36.50,T;65.10,36.50,T;65.10,36.50,T;66.29,36.70,T;66.29,36.70,T;66.29,36.43,T;66.29,36.43,T;66.29,36.43,T;66.29,36.43,T;66.34,36.43;76.09,36.35,M;76.14,36.36;76.14,36.36,T;76.14,36.36,T;76.14,36.36,T;76.14,36.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;76.31,35.36,T;66.29,35.43,M;66.29,34.43,T;66.34,34.43;76.43,34.35,M;76.48,34.35;76.48,34.35,T;76.48,34.35,T;76.48,34.35,T;76.48,34.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.64,33.35,T;76.60,33.34;66.34,33.43,M;66.29,33.43;66.29,32.43,T;66.34,32.43;76.76,32.34,M;76.81,32.35;76.81,32.35,T;76.81,32.35,T;76.81,32.35,T;76.81,32.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.98,31.35,T;76.93,31.34;66.34,31.43,M;66.29,31.43;66.29,30.43,T;66.34,30.43;77.10,30.34,M;77.15,30.35;77.15,30.35,T;77.15,30.35,T;77.15,30.35,T;77.15,30.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.32,29.35,T;77.27,29.34;66.34,29.43,M;66.29,29.43;66.29,28.43,T;66.34,28.43;77.44,28.34,M;77.48,28.35;77.48,28.35,T;77.48,28.35,T;77.48,28.35,T;77.48,28.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.65,27.35,T;77.60,27.34;66.34,27.43,M;66.29,27.43;66.29,26.43,T;66.34,26.43;77.77,26.34,M;77.82,26.34;77.82,26.34,T;77.82,26.34,T;77.82,26.34,T;77.82,26.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.99,25.34,T;77.94,25.34;66.34,25.43,M;66.29,25.43;66.29,25.43,T;66.29,25.43,T;66.29,25.43,T;66.29,24.43,T;66.29,24.43,T;66.29,24.43,T;66.29,24.43,T;66.34,24.43;76.67,24.40,M;76.69,24.35;73.25,23.38,T;73.24,23.43;66.34,23.43,M;66.29,23.43;66.29,23.43,T;66.29,23.43,T;66.29,23.43,T;66.29,22.43,T;66.29,22.43,T;66.29,22.43,T;66.29,22.43,T;66.34,22.43;69.80,22.45,M;69.81,22.40;66.38,21.43,T;66.36,21.47;66.34,21.43,M;66.29,21.43;66.29,21.43,T;66.29,21.43,T;66.29,21.43,T;66.29,36.70,T;66.29,36.70,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.71,20.65,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;47.85,20.56,T;47.85,20.56,T;47.85,20.56,T;47.85,20.56,T;47.87,20.60;49.65,20.55,M;49.70,20.54;49.70,20.54,T;49.70,20.54,T;49.70,20.54,T;49.70,20.54,T;49.61,19.99,T;49.61,19.99,T;49.61,19.99,T;41.97,22.44,T;46.48,36.57,T;46.48,36.57,T;46.48,36.57,T;46.48,36.57,T;46.52,36.55;64.75,36.49,M;64.75,36.44;64.75,36.44,T;64.75,36.44,T;64.75,36.44,T;64.75,36.44,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.07,35.48,T;59.06,35.53;46.20,35.55,M;46.16,35.57;46.16,35.57,T;46.16,35.57,T;46.16,35.57,T;46.16,35.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.84,34.57,T;45.89,34.56;53.37,34.57,M;53.38,34.52;53.38,34.52,T;53.38,34.52,T;53.38,34.52,T;53.38,34.52,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.85,34.26,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.73,33.53,T;51.68,33.54;45.57,33.56,M;45.52,33.57;45.52,33.57,T;45.52,33.57,T;45.52,33.57,T;45.20,32.58,T;45.20,32.58,T;45.20,32.58,T;45.20,32.58,T;45.25,32.56;51.53,32.54,M;51.57,32.53;51.57,32.53,T;51.57,32.53,T;51.57,32.53,T;51.57,32.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.42,31.53,T;51.37,31.54;44.93,31.56,M;44.88,31.58;44.88,31.58,T;44.56,30.58,T;44.56,30.58,T;44.56,30.58,T;44.56,30.58,T;44.61,30.57;51.21,30.54,M;51.26,30.53;51.26,30.53,T;51.26,30.53,T;51.26,30.53,T;51.26,30.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.11,29.53,T;51.06,29.54;44.29,29.57,M;44.25,29.58;43.93,28.59,T;43.97,28.57;50.90,28.54,M;50.95,28.54;50.95,28.54,T;50.95,28.54,T;50.95,28.54,T;50.95,28.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.79,27.54,T;50.74,27.54;43.66,27.57,M;43.61,27.59;43.61,27.59,T;43.61,27.59,T;43.29,26.59,T;43.29,26.59,T;43.29,26.59,T;43.34,26.57;50.59,26.55,M;50.64,26.54;50.64,26.54,T;50.64,26.54,T;50.64,26.54,T;50.64,26.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.48,25.54,T;50.43,25.55;43.02,25.58,M;42.97,25.59;42.65,24.59,T;42.70,24.58;50.27,24.55,M;50.32,24.54;50.32,24.54,T;50.32,24.54,T;50.32,24.54,T;50.32,24.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.17,23.54,T;50.12,23.55;42.38,23.58,M;42.33,23.60;42.33,23.60,T;42.33,23.60,T;42.33,23.60,T;42.33,23.60,T;42.02,22.60,T;42.02,22.60,T;42.02,22.60,T;42.06,22.58;49.96,22.55,M;50.01,22.54;50.01,22.54,T;50.01,22.54,T;50.01,22.54,T;50.01,22.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.85,21.54,T;49.81,21.55;44.68,21.63,M
+LAND1.updateTime=2025-12-28 20\:21\:18
LAND1.baseStationCoordinates=3949.89151752,N,11616.79267501,E
LAND1.boundaryPointInterval=-1
LAND1.createTime=2025-12-23 17\:08\:09
diff --git a/set.properties b/set.properties
index 3df173d..453134b 100644
--- a/set.properties
+++ b/set.properties
@@ -1,5 +1,5 @@
#Mower Configuration Properties - Updated
-#Sat Dec 27 23:41:35 GMT+08:00 2025
+#Sun Dec 28 20:35:53 GMT+08:00 2025
appVersion=-1
simCardNumber=-1
currentWorkLandNumber=LAND1
@@ -7,8 +7,8 @@
boundaryLengthVisible=false
idleTrailDurationSeconds=60
handheldMarkerId=1872
-viewCenterX=-57.93
-viewCenterY=-27.08
+viewCenterX=-60.00
+viewCenterY=-34.94
manualBoundaryDrawingMode=false
mowerId=6258
serialPortName=COM15
diff --git a/src/dikuai/daohangyulan.java b/src/dikuai/daohangyulan.java
index d7a3ffd..bf29464 100644
--- a/src/dikuai/daohangyulan.java
+++ b/src/dikuai/daohangyulan.java
@@ -10,6 +10,7 @@
import zhuye.Shouye;
import zhuye.MapRenderer;
import gecaoji.Gecaoji;
+import gecaoji.Device;
import gecaoji.lujingdraw;
import publicway.buttonset;
@@ -101,6 +102,11 @@
this.currentDikuai = dikuai;
this.currentPathIndex = 0;
this.currentSpeed = DEFAULT_SPEED;
+ // 灏嗗綋鍓嶉�熷害(绫�/绉�)杞崲涓簁m/h鍐欏叆璁惧yaw灞炴��
+ try {
+ double kmh = this.currentSpeed * 3.6;
+ Device.getActiveDevice().setYaw(String.valueOf(kmh));
+ } catch (Exception ignore) { }
this.navigationTrack.clear();
// 鑾峰彇棣栭〉鍜屽湴鍥炬覆鏌撳櫒
@@ -449,9 +455,9 @@
/**
* 璁$畻涓ょ偣涔嬮棿鐨勬柟鍚戣锛堝害锛�
- * 鍥炬爣榛樿鏈濅笂锛屽悜鍙虫棆杞�90搴﹁溅澶存湞鍙�
- * atan2杩斿洖鐨勮搴︼細鍚戝彸鏄�0搴︼紝鍚戜笂鏄�90搴�
- * 闇�瑕佽浆鎹负鍥炬爣鏃嬭浆瑙掑害锛氬悜鍙抽渶瑕�90搴︼紝鍚戜笂闇�瑕�0搴�
+ * 杞﹁締鍥炬爣鐨勮溅澶撮粯璁ゆ槸鍦ㄥ睆骞曟涓嬫柟锛�270搴︼級
+ * atan2杩斿洖鐨勮搴︼細鍚戝彸鏄�0搴︼紝鍚戜笂鏄�90搴︼紝鍚戝乏鏄�180搴︼紝鍚戜笅鏄�-90搴︼紙270搴︼級
+ * 闇�瑕佽浆鎹负鍥炬爣鏃嬭浆瑙掑害锛屼娇杞﹀ご鏈濆悜琛岄┒鏂瑰悜
*/
private double calculateHeading(Point2D.Double from, Point2D.Double to) {
double dx = to.x - from.x;
@@ -464,13 +470,13 @@
atan2Angle += 360;
}
- // 鍥炬爣榛樿鏈濅笂锛�0搴︼級锛屽悜鍙虫棆杞�90搴﹁溅澶存湞鍙�
- // 鎵�浠ワ細杩愬姩鏂瑰悜鍚戝彸锛�0搴︼級鈫� 闇�瑕佹棆杞�90搴�
- // 杩愬姩鏂瑰悜鍚戜笂锛�90搴︼級鈫� 闇�瑕佹棆杞�0搴�
- // 杩愬姩鏂瑰悜鍚戝乏锛�180搴︼級鈫� 闇�瑕佹棆杞�270搴�
- // 杩愬姩鏂瑰悜鍚戜笅锛�270搴︼級鈫� 闇�瑕佹棆杞�180搴�
- // 鍏紡锛歨eading = (90 - atan2Angle + 360) % 360
- double heading = (90.0 - atan2Angle + 360.0) % 360.0;
+ // 鍥炬爣榛樿鏈濅笅锛�270搴︼級锛岄渶瑕佽绠楁棆杞搴︿娇杞﹀ご鏈濆悜琛岄┒鏂瑰悜
+ // 濡傛灉杩愬姩鏂瑰悜鍚戜笂锛�90搴︼級鈫� 闇�瑕佹棆杞�180搴︼紙270 - 90 = 180锛�
+ // 濡傛灉杩愬姩鏂瑰悜鍚戝彸锛�0搴︼級鈫� 闇�瑕佹棆杞�270搴︼紙270 - 0 = 270锛�
+ // 濡傛灉杩愬姩鏂瑰悜鍚戝乏锛�180搴︼級鈫� 闇�瑕佹棆杞�90搴︼紙270 - 180 = 90锛�
+ // 濡傛灉杩愬姩鏂瑰悜鍚戜笅锛�270搴︼級鈫� 闇�瑕佹棆杞�0搴︼紙270 - 270 = 0锛�
+ // 鍏紡锛歨eading = (270 - atan2Angle + 360) % 360
+ double heading = (270.0 - atan2Angle + 360.0) % 360.0;
return heading;
}
@@ -489,6 +495,11 @@
*/
private void speedUp() {
currentSpeed += SPEED_MULTIPLIER;
+ // 鍚屾鍒拌澶噛aw灞炴�э紙km/h锛�
+ try {
+ double kmh = currentSpeed * 3.6;
+ Device.getActiveDevice().setYaw(String.valueOf(kmh));
+ } catch (Exception ignore) { }
updateSpeedDisplay();
}
@@ -502,6 +513,11 @@
currentSpeed = 0.1;
}
}
+ // 鍚屾鍒拌澶噛aw灞炴�э紙km/h锛�
+ try {
+ double kmh = currentSpeed * 3.6;
+ Device.getActiveDevice().setYaw(String.valueOf(kmh));
+ } catch (Exception ignore) { }
updateSpeedDisplay();
}
@@ -509,8 +525,11 @@
* 鏇存柊閫熷害鏄剧ず
*/
private void updateSpeedDisplay() {
- // 鍙互鍦ㄥ湴鍥句笂鏄剧ず褰撳墠閫熷害
- // 杩欓噷鏆傛椂涓嶅疄鐜帮紝濡傛灉闇�瑕佸彲浠ュ湪MapRenderer涓坊鍔犻�熷害鏄剧ず
+ // 瀵艰埅棰勮涓嬪湪鍓茶崏鏈哄浘鏍囦笂鏂瑰疄鏃舵樉绀洪�熷害锛堝浐瀹氬儚绱犻棿璺濓級
+ if (mapRenderer != null) {
+ mapRenderer.setNavigationPreviewSpeed(currentSpeed);
+ mapRenderer.repaint();
+ }
}
/**
@@ -542,6 +561,11 @@
mapRenderer.setNavigationPreviewSpeed(0.0); // 娓呴櫎閫熷害鏄剧ず
mapRenderer.repaint();
}
+
+ // 閫�鍑烘椂灏嗚澶噛aw灞炴�ч噸缃负0
+ try {
+ Device.getActiveDevice().setYaw("0");
+ } catch (Exception ignore) { }
// 鎭㈠鍦板潡绠$悊椤甸潰
// 鍦ㄦ竻绌篶urrentDikuai涔嬪墠淇濆瓨鍦板潡缂栧彿锛屼娇鐢╢inal鍙橀噺浠ヤ究鍦╨ambda涓娇鐢�
diff --git a/src/gecaoji/Gecaoji.java b/src/gecaoji/Gecaoji.java
index 18493ec..9845d8c 100644
--- a/src/gecaoji/Gecaoji.java
+++ b/src/gecaoji/Gecaoji.java
@@ -151,8 +151,9 @@
double iconHeight = icon.getHeight(null);
double maxSide = Math.max(iconWidth, iconHeight);
double scaleFactor = worldSize / Math.max(maxSide, MIN_SCALE);
- // 鍓茶崏鏈哄浘鏍囬粯璁ゆ湞鍗楋紝Yaw=0琛ㄧず姝e寳锛岄渶瑕佹棆杞�180搴�
- double rotationRadians = Math.toRadians(headingDegrees + 180);
+ // 杞﹁締鍥炬爣鐨勮溅澶撮粯璁ゆ槸鍦ㄥ睆骞曟涓嬫柟锛�270搴︼級
+ // headingDegrees宸茬粡鏄绠楀ソ鐨勬棆杞搴︼紙0-360搴︼級锛岀洿鎺ヤ娇鐢�
+ double rotationRadians = Math.toRadians(headingDegrees);
AffineTransform original = g2d.getTransform();
AffineTransform transformed = new AffineTransform(original);
diff --git a/src/lujing/DebugPath.java b/src/lujing/DebugPath.java
new file mode 100644
index 0000000..f579c44
--- /dev/null
+++ b/src/lujing/DebugPath.java
@@ -0,0 +1,105 @@
+package lujing;
+
+import java.util.*;
+
+public class DebugPath {
+ public static void main(String[] args) {
+ String coordinates = "50.39,50.57;74.32,50.40;78.69,24.37;65.76,20.70;65.76,36.07;52.31,33.80;50.04,19.30;41.30,22.10";
+ String widthStr = "1";
+ String marginStr = "0.53";
+
+ List<YixinglujingNoObstacle.PathSegment> path = YixinglujingNoObstacle.planPath(coordinates, widthStr, marginStr);
+ // Validate that non-mowing segments do not cross outside polygon
+ List<YixinglujingNoObstacle.Point> rawPoints = parseCoordinates("50.39,50.57;74.32,50.40;78.69,24.37;65.76,20.70;65.76,36.07;52.31,33.80;50.04,19.30;41.30,22.10");
+ YixinglujingNoObstacle.ensureCounterClockwise(rawPoints);
+ List<YixinglujingNoObstacle.Point> polygonInset = YixinglujingNoObstacle.getInsetPolygon(rawPoints, Double.parseDouble(marginStr));
+
+ int total = path.size();
+ int mowing = 0, travel = 0, unsafe = 0;
+ for (YixinglujingNoObstacle.PathSegment s : path) {
+ if (s.isMowing) {
+ mowing++;
+ continue;
+ }
+ travel++;
+ boolean safe = isSegmentSafe(s.start, s.end, polygonInset);
+ if (!safe) {
+ // 鍏佽鈥滄部杈圭晫鈥濈殑鏃呰娈碉細涓ょ閮借创杩戣竟鐣屽嵆鍙涓哄畨鍏�
+ double d1 = minDistanceToBoundary(s.start, polygonInset);
+ double d2 = minDistanceToBoundary(s.end, polygonInset);
+ if (d1 <= 0.2 && d2 <= 0.2) {
+ // treat as safe boundary-following segment
+ continue;
+ }
+ unsafe++;
+ }
+ }
+ System.out.println("Segments total=" + total + ", mowing=" + mowing + ", travel=" + travel + ", unsafeTravel=" + unsafe);
+ if (unsafe == 0) {
+ System.out.println("Validation OK: no travel segment crosses the inset boundary.");
+ } else {
+ System.out.println("Validation FAILED: some travel segments cross boundary: " + unsafe);
+ }
+ }
+
+ // --- Helpers copied for validation ---
+ private static List<YixinglujingNoObstacle.Point> parseCoordinates(String coordinates) {
+ List<YixinglujingNoObstacle.Point> points = new ArrayList<>();
+ String[] pairs = coordinates.split(";");
+ for (String pair : pairs) {
+ String[] xy = pair.split(",");
+ if (xy.length == 2) points.add(new YixinglujingNoObstacle.Point(Double.parseDouble(xy[0]), Double.parseDouble(xy[1])));
+ }
+ return points;
+ }
+
+ private static boolean isSegmentSafe(YixinglujingNoObstacle.Point p1, YixinglujingNoObstacle.Point p2, List<YixinglujingNoObstacle.Point> polygon) {
+ YixinglujingNoObstacle.Point mid = new YixinglujingNoObstacle.Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+ if (!isPointInPolygon(mid, polygon)) return false;
+ for (int i = 0; i < polygon.size(); i++) {
+ YixinglujingNoObstacle.Point a = polygon.get(i);
+ YixinglujingNoObstacle.Point b = polygon.get((i + 1) % polygon.size());
+ if (segmentsIntersect(p1, p2, a, b)) return false;
+ }
+ return true;
+ }
+
+ private static boolean segmentsIntersect(YixinglujingNoObstacle.Point a, YixinglujingNoObstacle.Point b, YixinglujingNoObstacle.Point c, YixinglujingNoObstacle.Point d) {
+ return ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d);
+ }
+
+ private static boolean ccw(YixinglujingNoObstacle.Point a, YixinglujingNoObstacle.Point b, YixinglujingNoObstacle.Point c) {
+ return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
+ }
+
+ private static boolean isPointInPolygon(YixinglujingNoObstacle.Point p, List<YixinglujingNoObstacle.Point> polygon) {
+ boolean result = false;
+ for (int i = 0, j = polygon.size() - 1; i < polygon.size(); j = i++) {
+ if ((polygon.get(i).y > p.y) != (polygon.get(j).y > p.y) &&
+ (p.x < (polygon.get(j).x - polygon.get(i).x) * (p.y - polygon.get(i).y) / (polygon.get(j).y - polygon.get(i).y) + polygon.get(i).x)) {
+ result = !result;
+ }
+ }
+ return result;
+ }
+
+ private static double minDistanceToBoundary(YixinglujingNoObstacle.Point p, List<YixinglujingNoObstacle.Point> poly) {
+ double minD = Double.MAX_VALUE;
+ for (int i = 0; i < poly.size(); i++) {
+ YixinglujingNoObstacle.Point s = poly.get(i);
+ YixinglujingNoObstacle.Point e = poly.get((i + 1) % poly.size());
+ double l2 = (s.x - e.x)*(s.x - e.x) + (s.y - e.y)*(s.y - e.y);
+ if (l2 == 0) {
+ minD = Math.min(minD, Math.hypot(p.x - s.x, p.y - s.y));
+ continue;
+ }
+ double t = ((p.x - s.x) * (e.x - s.x) + (p.y - s.y) * (e.y - s.y)) / l2;
+ t = Math.max(0, Math.min(1, t));
+ double px = s.x + t * (e.x - s.x);
+ double py = s.y + t * (e.y - s.y);
+ double d = Math.hypot(p.x - px, p.y - py);
+ minD = Math.min(minD, d);
+ }
+ return minD;
+ }
+}
diff --git a/src/lujing/YixinglujingHaveObstacel.java b/src/lujing/YixinglujingHaveObstacel.java
index 6a14dc4..5784ef3 100644
--- a/src/lujing/YixinglujingHaveObstacel.java
+++ b/src/lujing/YixinglujingHaveObstacel.java
@@ -102,8 +102,8 @@
remainingSegments.addAll(clippedSegments);
}
- // 3. 閲嶆柊杩炴帴璺緞娈碉紙寮撳瓧褰㈣繛鎺ワ級
- return reconnectSegments(remainingSegments);
+ // 3. 閲嶆柊杩炴帴璺緞娈碉紙寮撳瓧褰㈣繛鎺ワ紝鏅鸿兘澶勭悊杈圭晫绌胯秺锛�
+ return reconnectSegments(remainingSegments, polygon);
}
/**
@@ -154,7 +154,6 @@
return result;
} else {
// 涓�绔湪鍐呴儴锛屼竴绔湪澶栭儴
- Point insidePoint = startInside ? segment.start : segment.end;
Point outsidePoint = startInside ? segment.end : segment.start;
List<Point> intersections = obstacle.getIntersections(segment);
@@ -178,8 +177,9 @@
/**
* 閲嶆柊杩炴帴璺緞娈碉紝褰㈡垚杩炵画寮撳瓧褰㈣矾寰�
+ * 浼樺寲锛氭櫤鑳藉鐞嗚竟鐣岀┛瓒婏紝褰撴崲琛岃矾寰勭┛瓒婅竟鐣屾椂锛屾部杈圭晫琛岃蛋
*/
- private static List<PathSegment> reconnectSegments(List<PathSegment> segments) {
+ private static List<PathSegment> reconnectSegments(List<PathSegment> segments, List<Point> boundary) {
if (segments.isEmpty()) return new ArrayList<>();
List<PathSegment> reconnected = new ArrayList<>();
@@ -189,7 +189,9 @@
if (seg.isMowing) {
// 鍓茶崏娈碉細妫�鏌ユ槸鍚﹂渶瑕佹坊鍔犵┖璧版
if (distance(currentPos, seg.start) > 0.01) {
- reconnected.add(new PathSegment(currentPos, seg.start, false));
+ // 浣跨敤鏅鸿兘杩炴帴鏂规硶鐢熸垚鎹㈣璺緞
+ List<PathSegment> connectionPath = buildSmartConnection(currentPos, seg.start, boundary);
+ reconnected.addAll(connectionPath);
}
reconnected.add(seg);
currentPos = seg.end;
@@ -204,6 +206,351 @@
}
/**
+ * 鏅鸿兘杩炴帴涓ょ偣锛氬鏋滅洿绾夸笉绌胯秺杈圭晫鍒欑洿鎺ヨ繛鎺ワ紝鍚﹀垯浣跨敤鐩寸嚎+杈圭晫娣峰悎璺緞
+ * 浼樺寲閫昏緫锛�
+ * 1. 濡傛灉AB绾夸笉绌胯秺杈圭晫C锛岀洿鎺ヤ娇鐢ˋB浣滀负鎹㈣璺嚎
+ * 2. 濡傛灉AB绾跨┛瓒婁簡杈圭晫C锛屾壘鍒版墍鏈変氦鐐癸紝灏咥B鍒嗘垚澶氫釜娈�
+ * - 瀵逛簬鍦ㄨ竟鐣屽唴閮ㄧ殑娈碉紙濡侱F娈点�丟H娈碉級锛屾部杈圭晫琛岃蛋
+ * - 瀵逛簬鍦ㄨ竟鐣屽閮ㄧ殑娈碉紝娌緼B鐩寸嚎琛岃蛋
+ * 璺緞绀轰緥锛欰 鈫� D(鐩寸嚎) 鈫� F(娌胯竟鐣�) 鈫� G(鐩寸嚎) 鈫� H(娌胯竟鐣�) 鈫� B(鐩寸嚎)
+ *
+ * @param pointA 璧风偣锛堜笂涓�娈电粨鏉熺殑缁堢偣锛�
+ * @param pointB 缁堢偣锛堜笅涓�娈甸渶瑕佸壊鑽夎矾寰勭殑璧峰鐐癸級
+ * @param boundary 瀹夊叏鍐呯缉杈圭晫C
+ * @return 杩炴帴璺緞娈靛垪琛紙鍏ㄩ儴涓篿sMowing=false鐨勭┖璧版锛�
+ */
+ private static List<PathSegment> buildSmartConnection(Point pointA, Point pointB, List<Point> boundary) {
+ List<PathSegment> result = new ArrayList<>();
+
+ // 1. 妫�鏌B鐩寸嚎鏄惁绌胯秺杈圭晫C
+ if (!segmentIntersectsBoundary(pointA, pointB, boundary)) {
+ // 涓嶇┛瓒婅竟鐣岋紝鐩存帴浣跨敤AB浣滀负鎹㈣璺嚎
+ result.add(new PathSegment(pointA, pointB, false));
+ return result;
+ }
+
+ // 2. AB绾跨┛瓒婁簡杈圭晫C锛岄渶瑕佹壘鍒版墍鏈変氦鐐�
+ List<IntersectionInfo> intersections = getAllBoundaryIntersections(pointA, pointB, boundary);
+
+ if (intersections.isEmpty()) {
+ // 娌℃湁浜ょ偣锛堜笉搴旇鍙戠敓锛屼絾瀹夊叏澶勭悊锛夛紝浣跨敤鐩寸嚎
+ result.add(new PathSegment(pointA, pointB, false));
+ return result;
+ }
+
+ // 3. 鎸夎窛绂昏捣鐐笰鐨勮窛绂绘帓搴忎氦鐐�
+ intersections.sort(Comparator.comparingDouble(inter -> distance(pointA, inter.point)));
+
+ // 4. 鏋勫缓瀹屾暣鐨勭偣搴忓垪锛欰, I1, I2, ..., In, B锛圛涓轰氦鐐癸級
+ List<Point> pointSequence = new ArrayList<>();
+ pointSequence.add(pointA);
+ for (IntersectionInfo inter : intersections) {
+ pointSequence.add(inter.point);
+ }
+ pointSequence.add(pointB);
+
+ // 5. 澶勭悊姣忎袱涓浉閭荤偣涔嬮棿鐨勬
+ Point currentPos = pointA;
+
+ for (int i = 0; i < pointSequence.size() - 1; i++) {
+ Point p1 = pointSequence.get(i);
+ Point p2 = pointSequence.get(i + 1);
+
+ // 鍒ゆ柇p1鍒皃2鐨勬锛圓B绾挎鐨勪竴閮ㄥ垎锛夋槸鍚﹀湪杈圭晫C鍐呴儴锛堟鏌ヤ腑鐐癸級
+ Point midPoint = new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+ boolean segmentInsideBoundary = isPointInPolygon(midPoint, boundary);
+
+ if (segmentInsideBoundary) {
+ // 娈靛湪杈圭晫鍐呴儴锛堝DF娈点�丟H娈碉級锛岄渶瑕佹部杈圭晫琛岃蛋
+ if (i == 0) {
+ // 绗竴涓锛氫粠A鍒扮涓�涓氦鐐笵
+ // 濡傛灉娈靛湪杈圭晫鍐呴儴锛岃鏄嶢鍦ㄨ竟鐣屽唴閮紝闇�瑕佸厛浠嶢娌胯竟鐣岃蛋鍒扮涓�涓氦鐐�
+ IntersectionInfo firstInter = intersections.get(0);
+ SnapResult snapA = snapToBoundary(currentPos, boundary);
+ List<PathSegment> boundaryPath = getBoundaryPathBetweenPoints(
+ snapA.onEdge, snapA.edgeIndex,
+ firstInter.point, firstInter.edgeIndex,
+ boundary);
+ result.addAll(boundaryPath);
+ currentPos = firstInter.point;
+ } else if (i == pointSequence.size() - 2) {
+ // 鏈�鍚庝竴涓锛氫粠鏈�鍚庝竴涓氦鐐笻鍒癇
+ // 闇�瑕佹部杈圭晫浠庡綋鍓嶇偣锛堝簲璇ユ槸鏈�鍚庝竴涓氦鐐笻锛夊埌B鍦ㄨ竟鐣屼笂鐨勬姇褰�
+ IntersectionInfo lastInter = intersections.get(intersections.size() - 1);
+ SnapResult snapB = snapToBoundary(pointB, boundary);
+ List<PathSegment> boundaryPath = getBoundaryPathBetweenPoints(
+ currentPos, lastInter.edgeIndex,
+ snapB.onEdge, snapB.edgeIndex,
+ boundary);
+ result.addAll(boundaryPath);
+ // 濡傛灉B涓嶅湪杈圭晫涓婏紝浠庤竟鐣屾姇褰辩洿绾垮埌B
+ if (distance(snapB.onEdge, pointB) > 1e-6) {
+ result.add(new PathSegment(snapB.onEdge, pointB, false));
+ }
+ currentPos = pointB;
+ } else {
+ // 涓棿娈碉細涓や釜浜ょ偣涔嬮棿鐨勬锛堥兘鍦ㄨ竟鐣屼笂锛夛紝娌胯竟鐣岃璧�
+ IntersectionInfo inter1 = intersections.get(i - 1);
+ IntersectionInfo inter2 = intersections.get(i);
+ List<PathSegment> boundaryPath = getBoundaryPathBetweenPoints(
+ inter1.point, inter1.edgeIndex,
+ inter2.point, inter2.edgeIndex,
+ boundary);
+ result.addAll(boundaryPath);
+ currentPos = inter2.point;
+ }
+ } else {
+ // 娈靛湪杈圭晫澶栭儴锛屽彲浠ョ洿鎺ユ部AB鐩寸嚎杩炴帴锛堝A鍒癉锛孎鍒癎锛孒鍒癇锛�
+ if (distance(p1, p2) > 1e-6) {
+ // 濡傛灉褰撳墠鐐逛笉鍦╬1锛屽厛杩炴帴鍒皃1
+ if (distance(currentPos, p1) > 1e-6) {
+ result.add(new PathSegment(currentPos, p1, false));
+ }
+ // 浠巔1鐩寸嚎鍒皃2
+ result.add(new PathSegment(p1, p2, false));
+ currentPos = p2;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * 妫�鏌ョ嚎娈垫槸鍚︾┛瓒婅竟鐣岋紙涓庤竟鐣岃竟鐩镐氦锛屼笉鍖呮嫭绔偣锛�
+ */
+ private static boolean segmentIntersectsBoundary(Point a, Point b, List<Point> boundary) {
+ for (int i = 0; i < boundary.size(); i++) {
+ Point c = boundary.get(i);
+ Point d = boundary.get((i + 1) % boundary.size());
+ // 蹇界暐鍏变韩绔偣鐨勭浉浜�
+ if (isSamePoint(a, c) || isSamePoint(a, d) || isSamePoint(b, c) || isSamePoint(b, d)) {
+ continue;
+ }
+ if (segmentsIntersect(a, b, c, d)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鑾峰彇绾挎涓庤竟鐣岀殑鎵�鏈変氦鐐逛俊鎭紙鍖呮嫭鐐瑰拰瀵瑰簲杈圭储寮曪級
+ */
+ private static List<IntersectionInfo> getAllBoundaryIntersections(Point a, Point b, List<Point> boundary) {
+ List<IntersectionInfo> intersections = new ArrayList<>();
+
+ for (int i = 0; i < boundary.size(); i++) {
+ Point c = boundary.get(i);
+ Point d = boundary.get((i + 1) % boundary.size());
+
+ // 蹇界暐鍏变韩绔偣
+ if (isSamePoint(a, c) || isSamePoint(a, d) || isSamePoint(b, c) || isSamePoint(b, d)) {
+ continue;
+ }
+
+ Point intersection = getLineIntersection(a, b, c, d);
+ if (intersection != null) {
+ intersections.add(new IntersectionInfo(intersection, i));
+ }
+ }
+
+ return intersections;
+ }
+
+ /**
+ * 鑾峰彇杈圭晫涓婁袱鐐逛箣闂寸殑璺緞锛堟部杈圭晫琛岃蛋锛�
+ * @param start 璧风偣锛堝繀椤诲湪杈圭晫涓婏級
+ * @param startEdgeIndex 璧风偣鎵�鍦ㄧ殑杈圭储寮�
+ * @param end 缁堢偣锛堝繀椤诲湪杈圭晫涓婏級
+ * @param endEdgeIndex 缁堢偣鎵�鍦ㄧ殑杈圭储寮�
+ * @param boundary 杈圭晫鐐瑰垪琛�
+ * @return 娌胯竟鐣岀殑璺緞娈靛垪琛�
+ */
+ private static List<PathSegment> getBoundaryPathBetweenPoints(
+ Point start, int startEdgeIndex,
+ Point end, int endEdgeIndex,
+ List<Point> boundary) {
+
+ List<PathSegment> result = new ArrayList<>();
+
+ if (startEdgeIndex == endEdgeIndex) {
+ // 鍦ㄥ悓涓�鏉¤竟涓婏紝鐩存帴杩炴帴
+ if (distance(start, end) > 1e-6) {
+ result.add(new PathSegment(start, end, false));
+ }
+ return result;
+ }
+
+ int n = boundary.size();
+
+ // 璁$畻椤烘椂閽堣矾寰�
+ List<Point> pathClockwise = new ArrayList<>();
+ pathClockwise.add(start);
+
+ int curr = startEdgeIndex;
+ while (curr != endEdgeIndex) {
+ pathClockwise.add(boundary.get((curr + 1) % n));
+ curr = (curr + 1) % n;
+ }
+ pathClockwise.add(end);
+
+ // 璁$畻閫嗘椂閽堣矾寰�
+ List<Point> pathCounterClockwise = new ArrayList<>();
+ pathCounterClockwise.add(start);
+ curr = startEdgeIndex;
+ while (curr != endEdgeIndex) {
+ pathCounterClockwise.add(boundary.get(curr));
+ curr = (curr - 1 + n) % n;
+ }
+ pathCounterClockwise.add(end);
+
+ // 閫夋嫨杈冪煭鐨勮矾寰�
+ List<Point> chosenPath = getPathLength(pathClockwise) < getPathLength(pathCounterClockwise)
+ ? pathClockwise : pathCounterClockwise;
+
+ // 杞崲涓鸿矾寰勬
+ for (int i = 0; i < chosenPath.size() - 1; i++) {
+ if (distance(chosenPath.get(i), chosenPath.get(i + 1)) > 1e-6) {
+ result.add(new PathSegment(chosenPath.get(i), chosenPath.get(i + 1), false));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * 璁$畻璺緞鎬婚暱搴�
+ */
+ private static double getPathLength(List<Point> path) {
+ double len = 0;
+ for (int i = 0; i < path.size() - 1; i++) {
+ len += distance(path.get(i), path.get(i + 1));
+ }
+ return len;
+ }
+
+ /**
+ * 鍒ゆ柇涓や釜鐐规槸鍚︾浉鍚岋紙鑰冭檻娴偣璇樊锛�
+ */
+ private static boolean isSamePoint(Point a, Point b) {
+ return Math.abs(a.x - b.x) < 1e-6 && Math.abs(a.y - b.y) < 1e-6;
+ }
+
+ /**
+ * 鍒ゆ柇涓ゆ潯绾挎鏄惁鐩镐氦锛堜笉鍖呮嫭绔偣锛�
+ */
+ private static boolean segmentsIntersect(Point a, Point b, Point c, Point d) {
+ return ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d);
+ }
+
+ /**
+ * 鍒ゆ柇涓夌偣鏄惁閫嗘椂閽堟帓鍒�
+ */
+ private static boolean ccw(Point a, Point b, Point c) {
+ return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
+ }
+
+ /**
+ * 浜ょ偣淇℃伅鍐呴儴绫�
+ */
+ private static class IntersectionInfo {
+ Point point; // 浜ょ偣鍧愭爣
+ int edgeIndex; // 浜ょ偣鎵�鍦ㄧ殑杈圭晫杈圭储寮�
+
+ IntersectionInfo(Point point, int edgeIndex) {
+ this.point = point;
+ this.edgeIndex = edgeIndex;
+ }
+ }
+
+ /**
+ * 杈圭晫鍚搁檮缁撴灉鍐呴儴绫�
+ */
+ private static class SnapResult {
+ Point onEdge; // 鍦ㄨ竟鐣屼笂鐨勬姇褰辩偣
+ int edgeIndex; // 鎵�鍦ㄧ殑杈圭晫杈圭储寮�
+
+ SnapResult(Point p, int idx) {
+ this.onEdge = p;
+ this.edgeIndex = idx;
+ }
+ }
+
+ /**
+ * 璁$畻鐐瑰埌杈圭晫鏈�杩戠殑鎶曞奖鐐逛互鍙婃墍鍦ㄨ竟绱㈠紩
+ * @param p 瑕佸惛闄勭殑鐐�
+ * @param poly 杈圭晫澶氳竟褰�
+ * @return 鍚搁檮缁撴灉
+ */
+ private static SnapResult snapToBoundary(Point p, List<Point> poly) {
+ double minD = Double.MAX_VALUE;
+ Point bestProj = p;
+ int bestIdx = -1;
+ for (int i = 0; i < poly.size(); i++) {
+ Point s = poly.get(i);
+ Point e = poly.get((i + 1) % poly.size());
+ double l2 = (s.x - e.x) * (s.x - e.x) + (s.y - e.y) * (s.y - e.y);
+ if (l2 < 1e-10) {
+ double d = Math.hypot(p.x - s.x, p.y - s.y);
+ if (d < minD) {
+ minD = d;
+ bestProj = s;
+ bestIdx = i;
+ }
+ continue;
+ }
+ double t = ((p.x - s.x) * (e.x - s.x) + (p.y - s.y) * (e.y - s.y)) / l2;
+ t = Math.max(0, Math.min(1, t));
+ Point proj = new Point(s.x + t * (e.x - s.x), s.y + t * (e.y - s.y));
+ double d = Math.hypot(p.x - proj.x, p.y - proj.y);
+ if (d < minD) {
+ minD = d;
+ bestProj = proj;
+ bestIdx = i;
+ }
+ }
+ return new SnapResult(bestProj, bestIdx == -1 ? 0 : bestIdx);
+ }
+
+ /**
+ * 鍒ゆ柇鐐规槸鍚﹀湪杈圭晫涓婏紙璺濈杈圭晫寰堣繎锛�
+ * @param p 瑕佹鏌ョ殑鐐�
+ * @param boundary 杈圭晫澶氳竟褰�
+ * @return 鏄惁鍦ㄨ竟鐣屼笂
+ */
+ @SuppressWarnings("unused")
+ private static boolean isPointOnBoundary(Point p, List<Point> boundary) {
+ double threshold = 1e-4; // 闃堝�硷紝鑰冭檻娴偣璇樊
+ for (int i = 0; i < boundary.size(); i++) {
+ Point s = boundary.get(i);
+ Point e = boundary.get((i + 1) % boundary.size());
+ double dist = distToSegment(p, s, e);
+ if (dist < threshold) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 璁$畻鐐瑰埌绾挎鐨勮窛绂�
+ * @param p 鐐�
+ * @param s 绾挎璧风偣
+ * @param e 绾挎缁堢偣
+ * @return 璺濈
+ */
+ private static double distToSegment(Point p, Point s, Point e) {
+ double l2 = (s.x - e.x) * (s.x - e.x) + (s.y - e.y) * (s.y - e.y);
+ if (l2 < 1e-10) {
+ return Math.hypot(p.x - s.x, p.y - s.y);
+ }
+ double t = ((p.x - s.x) * (e.x - s.x) + (p.y - s.y) * (e.y - s.y)) / l2;
+ t = Math.max(0, Math.min(1, t));
+ return Math.hypot(p.x - (s.x + t * (e.x - s.x)), p.y - (s.y + t * (e.y - s.y)));
+ }
+
+ /**
* 鐢熸垚鍘熷鎵弿璺緞锛堟棤闅滅鐗╃増鏈級
*/
private static List<PathSegment> generateGlobalScanPath(
diff --git a/src/lujing/YixinglujingNoObstacle.java b/src/lujing/YixinglujingNoObstacle.java
index 31e87d5..9cee24a 100644
--- a/src/lujing/YixinglujingNoObstacle.java
+++ b/src/lujing/YixinglujingNoObstacle.java
@@ -90,10 +90,14 @@
boolean endInside = isPointInPolygon(s.end, polygon);
boolean intersects = segmentIntersectsBoundary(s.start, s.end, polygon);
if (!s.isMowing) {
- // 闈炰綔涓氭缁熶竴鏇挎崲涓烘部杈圭晫璺緞
- List<Point> path = getBoundaryPathWithSnap(s.start, s.end, polygon);
- for (int i = 0; i < path.size() - 1; i++) {
- sanitized.add(new PathSegment(path.get(i), path.get(i+1), false));
+ // 闈炰綔涓氭锛氳嫢AB鐩寸嚎瀹夊叏锛堜笉璺ㄨ秺杈圭晫涓斾腑鐐瑰湪鍐咃級锛屼繚鐣欑洿绾匡紱鍚﹀垯娌胯竟鐣屾浛鎹�
+ if (isSegmentSafe(s.start, s.end, polygon)) {
+ sanitized.add(s);
+ } else {
+ List<Point> path = getBoundaryPathWithSnap(s.start, s.end, polygon);
+ for (int i = 0; i < path.size() - 1; i++) {
+ sanitized.add(new PathSegment(path.get(i), path.get(i+1), false));
+ }
}
} else {
if (!startInside || !endInside || intersects) {
@@ -240,9 +244,9 @@
}
PathSegment s = lineSegmentsInRow.get(idxInRow);
- // 棣栨杩炴帴鎴栬法鍖鸿繛鎺ュ潎寮哄埗娌胯竟鐣岋紝閬垮厤绌胯秺鍑归櫡鍖�
+ // 棣栨鎴栬法鍖鸿繛鎺ワ細浣跨敤鏅鸿兘鎹㈣璺緞锛堜紭鍏堢洿绾挎渶鐭紝蹇呰鏃舵部杈圭晫锛�
if (Math.hypot(currentPos.x - s.start.x, currentPos.y - s.start.y) > 0.01) {
- addBoundaryConnection(segments, currentPos, s.start, polygon);
+ addSafeConnection(segments, currentPos, s.start, polygon);
firstSegmentConnected = true;
}
segments.add(s);
@@ -369,14 +373,139 @@
}
private static void addSafeConnection(List<PathSegment> segments, Point start, Point end, List<Point> polygon) {
- if (!FORCE_BOUNDARY_TRAVEL && isSegmentSafe(start, end, polygon)) {
- segments.add(new PathSegment(start, end, false));
- return;
+ // 浣跨敤鏂扮殑鏅鸿兘鎹㈣璺緞绠楁硶
+ List<PathSegment> connectionPath = generateSmartConnectionPath(start, end, polygon);
+ segments.addAll(connectionPath);
+ }
+
+ /**
+ * 鏅鸿兘鎹㈣璺緞鐢熸垚锛氭牴鎹瓵B绾挎涓庡畨鍏ㄨ竟鐣孋鐨勪氦鐐癸紝鐢熸垚娣峰悎璺緞
+ * 閫昏緫锛�
+ * 1. 濡傛灉AB绾挎涓嶇┛瓒婅竟鐣岋紝鐩存帴杩斿洖AB鐩寸嚎
+ * 2. 濡傛灉AB绾挎绌胯秺杈圭晫锛屾壘鍒版墍鏈変氦鐐癸紙濡侱, F, G, H锛夛紝鐢熸垚璺緞锛�
+ * A -> D -> (娌胯竟鐣孌鍒癋) -> F -> G -> (娌胯竟鐣孏鍒癏) -> H -> B
+ */
+ private static List<PathSegment> generateSmartConnectionPath(Point A, Point B, List<Point> polygon) {
+ List<PathSegment> result = new ArrayList<>();
+
+ // 1. 妫�鏌B鐩寸嚎鏄惁瀹夊叏锛堜笉绌胯秺杈圭晫涓斾腑鐐瑰湪鍐呴儴锛夛紱涓庢槸鍚﹀己鍒舵部杈圭晫鏃犲叧
+ if (isSegmentSafe(A, B, polygon)) {
+ result.add(new PathSegment(A, B, false));
+ return result;
}
- List<Point> path = getBoundaryPathWithSnap(start, end, polygon);
- for (int i = 0; i < path.size() - 1; i++) {
- segments.add(new PathSegment(path.get(i), path.get(i+1), false));
+
+ // 2. 鑾峰彇AB涓庤竟鐣岀殑鎵�鏈変氦鐐�
+ List<IntersectionPoint> intersections = getSegmentBoundaryIntersections(A, B, polygon);
+
+ // 3. 濡傛灉娌℃湁浜ょ偣浣嗕笉瀹夊叏锛岃鏄庢暣鏉$嚎閮藉湪澶栭儴锛屽己鍒舵部杈圭晫
+ if (intersections.isEmpty()) {
+ List<Point> path = getBoundaryPathWithSnap(A, B, polygon);
+ for (int i = 0; i < path.size() - 1; i++) {
+ result.add(new PathSegment(path.get(i), path.get(i+1), false));
+ }
+ return result;
}
+
+ // 4. 鏍规嵁浜ょ偣鎴愬澶勭悊锛岃�冭檻A/B鏄惁鍦ㄥ唴渚�
+ Point currentPos = A;
+ boolean startInside = isPointInPolygon(A, polygon);
+ boolean endInside = isPointInPolygon(B, polygon);
+
+ for (int i = 0; i < intersections.size(); i += 2) {
+ IntersectionPoint entry = intersections.get(i);
+
+ // 浠庡綋鍓嶄綅缃埌绗竴涓氦鐐癸細璧风偣鍦ㄥ唴鈫掔洿绾匡紱璧风偣鍦ㄥ鈫掓部杈圭晫鍒颁氦鐐�
+ if (Math.hypot(currentPos.x - entry.point.x, currentPos.y - entry.point.y) > 1e-6) {
+ if (startInside) {
+ result.add(new PathSegment(currentPos, entry.point, false));
+ } else {
+ List<Point> pathToEntry = getBoundaryPathWithSnap(currentPos, entry.point, polygon);
+ for (int j = 0; j < pathToEntry.size() - 1; j++) {
+ result.add(new PathSegment(pathToEntry.get(j), pathToEntry.get(j+1), false));
+ }
+ }
+ }
+
+ // 妫�鏌ユ槸鍚︽湁閰嶅鐨勭寮�鐐�
+ if (i + 1 < intersections.size()) {
+ IntersectionPoint exit = intersections.get(i + 1);
+
+ // 浠庤繘鍏ョ偣D鍒扮寮�鐐笷锛氭部杈圭晫琛岃蛋
+ List<Point> boundaryPath = getBoundaryPathBetweenPoints(
+ entry.point, entry.edgeIndex,
+ exit.point, exit.edgeIndex,
+ polygon
+ );
+
+ for (int j = 0; j < boundaryPath.size() - 1; j++) {
+ result.add(new PathSegment(boundaryPath.get(j), boundaryPath.get(j+1), false));
+ }
+
+ currentPos = exit.point;
+ // 涔嬪悗鐨勮捣鐐硅涓哄唴渚�
+ startInside = true;
+ } else {
+ // 濡傛灉娌℃湁閰嶅鐨勭寮�鐐癸紝璇存槑缁堢偣鍦ㄥ閮紝娌胯竟鐣屽埌B
+ List<Point> path = getBoundaryPathWithSnap(entry.point, B, polygon);
+ for (int j = 0; j < path.size() - 1; j++) {
+ result.add(new PathSegment(path.get(j), path.get(j+1), false));
+ }
+ return result;
+ }
+ }
+
+ // 5. 浠庢渶鍚庝竴涓寮�鐐瑰埌缁堢偣B锛氱洿绾挎锛堝湪鍐呴儴锛�
+ if (Math.hypot(currentPos.x - B.x, currentPos.y - B.y) > 1e-6) {
+ if (endInside) {
+ result.add(new PathSegment(currentPos, B, false));
+ } else {
+ List<Point> pathToB = getBoundaryPathWithSnap(currentPos, B, polygon);
+ for (int j = 0; j < pathToB.size() - 1; j++) {
+ result.add(new PathSegment(pathToB.get(j), pathToB.get(j+1), false));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * 鍦ㄥ凡鐭ヨ竟鐣岃竟绱㈠紩鐨勬儏鍐典笅锛屾部杈圭晫鑾峰彇涓ょ偣涔嬮棿鐨勬渶鐭矾寰�
+ */
+ private static List<Point> getBoundaryPathBetweenPoints(
+ Point start, int startEdgeIdx,
+ Point end, int endEdgeIdx,
+ List<Point> polygon) {
+
+ int n = polygon.size();
+
+ // 濡傛灉鍦ㄥ悓涓�鏉¤竟涓婏紝鐩存帴杩炴帴
+ if (startEdgeIdx == endEdgeIdx) {
+ return Arrays.asList(start, end);
+ }
+
+ // 姝e悜璺緞锛堥『杈癸級
+ List<Point> pathFwd = new ArrayList<>();
+ pathFwd.add(start);
+ int curr = startEdgeIdx;
+ while (curr != endEdgeIdx) {
+ pathFwd.add(polygon.get((curr + 1) % n));
+ curr = (curr + 1) % n;
+ }
+ pathFwd.add(end);
+
+ // 鍙嶅悜璺緞锛堥�嗚竟锛�
+ List<Point> pathRev = new ArrayList<>();
+ pathRev.add(start);
+ curr = startEdgeIdx;
+ while (curr != endEdgeIdx) {
+ pathRev.add(polygon.get(curr));
+ curr = (curr - 1 + n) % n;
+ }
+ pathRev.add(end);
+
+ // 杩斿洖鍑犱綍闀垮害鏇寸煭鐨勮矾寰�
+ return getPathLength(pathFwd) <= getPathLength(pathRev) ? pathFwd : pathRev;
}
// 寮哄埗娌胯竟鐣岀粫琛岀殑杩炴帴锛堜笉鍋氱洿绾垮畨鍏ㄥ垽鏂級锛岀敤鏉ュ湪鍚屼竴鎵弿琛岀殑澶氫釜浣滀笟娈典箣闂磋烦杞�
@@ -470,6 +599,70 @@
return ccw(a, c, d) != ccw(b, c, d) && ccw(a, b, c) != ccw(a, b, d);
}
+ // 鑾峰彇绾挎AB涓庤竟鐣屽杈瑰舰鐨勬墍鏈変氦鐐癸紝鎸夌収璺濈A鐐圭殑椤哄簭鎺掑簭
+ private static class IntersectionPoint {
+ Point point; // 浜ょ偣鍧愭爣
+ int edgeIndex; // 浜ょ偣鎵�鍦ㄧ殑杈圭晫杈圭储寮�
+ double distFromStart; // 璺濈璧风偣A鐨勮窛绂�
+ boolean isEntry; // true琛ㄧず杩涘叆杈圭晫锛宖alse琛ㄧず绂诲紑杈圭晫
+
+ IntersectionPoint(Point p, int idx, double dist, boolean entry) {
+ this.point = p;
+ this.edgeIndex = idx;
+ this.distFromStart = dist;
+ this.isEntry = entry;
+ }
+ }
+
+ // 璁$畻绾挎AB涓庡杈瑰舰杈圭晫鐨勬墍鏈変氦鐐�
+ private static List<IntersectionPoint> getSegmentBoundaryIntersections(Point A, Point B, List<Point> polygon) {
+ List<IntersectionPoint> intersections = new ArrayList<>();
+ for (int i = 0; i < polygon.size(); i++) {
+ Point C = polygon.get(i);
+ Point D = polygon.get((i + 1) % polygon.size());
+ Point intersection = getLineSegmentIntersection(A, B, C, D);
+ if (intersection != null) {
+ if (isSamePoint(intersection, A) || isSamePoint(intersection, B)) continue;
+ double dist = Math.hypot(intersection.x - A.x, intersection.y - A.y);
+ intersections.add(new IntersectionPoint(intersection, i, dist, false));
+ }
+ }
+ // 璺濈鎺掑簭
+ Collections.sort(intersections, (i1, i2) -> Double.compare(i1.distFromStart, i2.distFromStart));
+ // 鍘婚噸杩戜技鐩稿悓浜ょ偣锛堥《鐐瑰弻浜わ級
+ List<IntersectionPoint> deduped = new ArrayList<>();
+ for (IntersectionPoint ip : intersections) {
+ boolean dup = false;
+ for (IntersectionPoint kept : deduped) {
+ if (Math.abs(ip.point.x - kept.point.x) < 1e-6 && Math.abs(ip.point.y - kept.point.y) < 1e-6) { dup = true; break; }
+ }
+ if (!dup) deduped.add(ip);
+ }
+ return deduped;
+ }
+
+ // 璁$畻涓ゆ潯绾挎鐨勪氦鐐癸紙濡傛灉瀛樺湪锛�
+ private static Point getLineSegmentIntersection(Point p1, Point p2, Point p3, Point p4) {
+ double x1 = p1.x, y1 = p1.y;
+ double x2 = p2.x, y2 = p2.y;
+ double x3 = p3.x, y3 = p3.y;
+ double x4 = p4.x, y4 = p4.y;
+
+ double denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
+ if (Math.abs(denom) < 1e-10) return null; // 骞宠鎴栭噸鍚�
+
+ double t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom;
+ double u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom;
+
+ // 妫�鏌ヤ氦鐐规槸鍚﹀湪涓ゆ潯绾挎涓婏紙浣跨敤鐣ュ井瀹芥澗鐨勮寖鍥翠互澶勭悊娴偣璇樊锛�
+ double epsilon = 1e-6;
+ if (t >= -epsilon && t <= 1 + epsilon && u >= -epsilon && u <= 1 + epsilon) {
+ return new Point(x1 + t * (x2 - x1), y1 + t * (y2 - y1));
+ }
+
+ return null;
+ }
+
private static boolean ccw(Point a, Point b, Point c) {
return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
}
diff --git a/src/zhangaiwu/AddDikuai.java b/src/zhangaiwu/AddDikuai.java
index b881409..770416f 100644
--- a/src/zhangaiwu/AddDikuai.java
+++ b/src/zhangaiwu/AddDikuai.java
@@ -1573,16 +1573,20 @@
* 娣诲姞 AoxinglujingNoObstacle.Point 鍒板瓧绗︿覆鏋勫缓鍣�
*/
private void appendAoxingPoint(StringBuilder sb, AoxinglujingNoObstacle.Point point) {
- private void appendAoxingPointWithType(StringBuilder sb, AoxinglujingNoObstacle.Point point, boolean isMowing) {
if (sb.length() > 0) {
sb.append(";");
}
- sb.append(String.format(java.util.Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T"));
+ sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
}
+
+ /**
+ * 娣诲姞 AoxinglujingNoObstacle.Point 鍒板瓧绗︿覆鏋勫缓鍣紙甯︾被鍨嬫爣璁帮級
+ */
+ private void appendAoxingPointWithType(StringBuilder sb, AoxinglujingNoObstacle.Point point, boolean isMowing) {
if (sb.length() > 0) {
sb.append(";");
}
- sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
+ sb.append(String.format(Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T"));
}
/**
@@ -1600,16 +1604,20 @@
* 娣诲姞 YixinglujingNoObstacle.Point 鍒板瓧绗︿覆鏋勫缓鍣�
*/
private void appendYixingPoint(StringBuilder sb, YixinglujingNoObstacle.Point point) {
- private void appendYixingPointWithType(StringBuilder sb, YixinglujingNoObstacle.Point point, boolean isMowing) {
if (sb.length() > 0) {
sb.append(";");
}
- sb.append(String.format(java.util.Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T"));
+ sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
}
+
+ /**
+ * 娣诲姞 YixinglujingNoObstacle.Point 鍒板瓧绗︿覆鏋勫缓鍣紙甯︾被鍨嬫爣璁帮級
+ */
+ private void appendYixingPointWithType(StringBuilder sb, YixinglujingNoObstacle.Point point, boolean isMowing) {
if (sb.length() > 0) {
sb.append(";");
}
- sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
+ sb.append(String.format(Locale.US, "%.2f,%.2f,%s", point.x, point.y, isMowing ? "M" : "T"));
}
private void previewMowingPath() {
diff --git a/src/zhuye/MapRenderer.java b/src/zhuye/MapRenderer.java
index 3574277..e354548 100644
--- a/src/zhuye/MapRenderer.java
+++ b/src/zhuye/MapRenderer.java
@@ -489,10 +489,7 @@
drawMower(g2d);
- // 缁樺埗瀵艰埅棰勮閫熷害锛堝鏋滄鍦ㄥ鑸瑙堬級
- if (navigationPreviewSpeed > 0 && mower != null && mower.hasValidPosition()) {
- drawNavigationPreviewSpeed(g2d, scale);
- }
+ // 宸叉寜闇�姹傜Щ闄わ細涓嶅湪鍓茶崏鏈哄浘鏍囦笂鏂规樉绀洪�熷害
// 缁樺埗娴嬮噺妯″紡锛堝鏋滄縺娲伙級
if (measurementModeActive) {
@@ -564,16 +561,21 @@
g2d.setFont(labelFont);
FontMetrics metrics = g2d.getFontMetrics(labelFont);
- // 璁$畻鏂囧瓧浣嶇疆锛堝湪鍓茶崏鏈哄浘鏍囦笂鏂癸級
+ // 璁$畻鏂囧瓧浣嶇疆锛堝湪鍓茶崏鏈哄浘鏍囨涓婃柟锛岄棿闅�20鍍忕礌鍥哄畾锛�
int textWidth = metrics.stringWidth(speedText);
int textHeight = metrics.getHeight();
int textX = (int)Math.round(screenPos.x - textWidth / 2.0);
- // 鍦ㄥ壊鑽夋満鍥炬爣涓婃柟锛岀暀鍑轰竴瀹氶棿璺�
- // 鍥炬爣鍦ㄤ笘鐣屽潗鏍囩郴涓殑澶у皬绾︿负 48 * 0.8 / scale 绫�
- // 杞崲涓哄睆骞曞儚绱狅細鍥炬爣楂樺害锛堝儚绱狅級= (48 * 0.8 / scale) * scale = 48 * 0.8 = 38.4 鍍忕礌
- double iconSizePixels = 48.0 * 0.8; // 鍥炬爣鍦ㄥ睆骞曚笂鐨勫ぇ灏忥紙鍍忕礌锛�
- int spacing = 8; // 闂磋窛锛堝儚绱狅級
- int textY = (int)Math.round(screenPos.y - iconSizePixels / 2.0 - spacing - textHeight);
+ // 鍦ㄥ壊鑽夋満鍥炬爣姝d笂鏂癸紝闂撮殧20鍍忕礌
+ // 浠巑ower瀵硅薄鑾峰彇鍥炬爣鍦ㄤ笘鐣屽潗鏍囩郴涓殑鍗婂緞锛岀劧鍚庤浆鎹负灞忓箷鍍忕礌
+ double iconWorldRadius = mower.getWorldRadius(scale);
+ double iconSizePixels = Double.isNaN(iconWorldRadius) ? 38.4 : (iconWorldRadius * 2.0 * scale); // 鍥炬爣鍦ㄥ睆骞曚笂鐨勫ぇ灏忥紙鍍忕礌锛�
+ int spacing = 20; // 闂磋窛锛堝儚绱狅級
+ // 鍥炬爣椤堕儴浣嶇疆 = 鍥炬爣涓績Y - 鍥炬爣楂樺害/2
+ double iconTopY = screenPos.y - iconSizePixels / 2.0;
+ // 绮剧‘绾︽潫锛氳鑳屾櫙鐭╁舰鐨勫簳杈逛笌鍥炬爣椤堕儴鐩歌窛鍥哄畾spacing鍍忕礌
+ // 鑳屾櫙搴曡竟 = textY + metrics.getDescent() + 2锛堢煩褰笅鏂瑰唴杈硅窛锛�
+ // 浠� 鑳屾櫙搴曡竟 = iconTopY - spacing锛岃В寰楋細
+ int textY = (int)Math.round(iconTopY - spacing - metrics.getDescent() - 2);
// 缁樺埗鏂囧瓧鑳屾櫙锛堝崐閫忔槑鐧借壊锛屽寮哄彲璇绘�э級
g2d.setColor(new Color(255, 255, 255, 200));
diff --git a/src/zhuye/Shouye.java b/src/zhuye/Shouye.java
index cd33de7..d8d6c82 100644
--- a/src/zhuye/Shouye.java
+++ b/src/zhuye/Shouye.java
@@ -2249,7 +2249,8 @@
mowingProgressLabel.setForeground(THEME_COLOR);
mowerSpeedValueLabel = new JLabel("--");
- mowerSpeedValueLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+ // 鏁板�煎ぇ灏忎笌鍗曚綅 km/h 鏄剧ず澶у皬涓�鑷�
+ mowerSpeedValueLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 9));
mowerSpeedValueLabel.setForeground(THEME_COLOR);
mowerSpeedUnitLabel = new JLabel("km/h");
@@ -2303,9 +2304,20 @@
String display = "--";
Device device = Device.getGecaoji();
if (device != null) {
- String sanitized = sanitizeSpeedValue(device.getRealtimeSpeed());
+ // 浣跨敤 yaw 鍊间綔涓洪�熷害鏄剧ず锛堝崟浣嶏細km/h锛�
+ String sanitized = sanitizeSpeedValue(device.getYaw());
if (sanitized != null) {
- display = sanitized;
+ // yaw涓�0鏃舵樉绀轰负"0"
+ try {
+ double v = Double.parseDouble(sanitized);
+ if (Math.abs(v) < 1e-9) {
+ display = "0";
+ } else {
+ display = sanitized;
+ }
+ } catch (NumberFormatException ex) {
+ display = sanitized;
+ }
}
}
mowerSpeedValueLabel.setText(display);
--
Gitblit v1.10.0