From 48ee74129bb09a817a0bbbabe860c4007b74c66b Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期日, 21 十二月 2025 12:37:44 +0800
Subject: [PATCH] 新增了往返路径
---
src/lujing/MowingPathGenerationPage.java | 432 ++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 385 insertions(+), 47 deletions(-)
diff --git a/src/lujing/MowingPathGenerationPage.java b/src/lujing/MowingPathGenerationPage.java
index 8f96af2..503a1fd 100644
--- a/src/lujing/MowingPathGenerationPage.java
+++ b/src/lujing/MowingPathGenerationPage.java
@@ -1,7 +1,10 @@
package lujing;
import javax.swing.*;
+import javax.swing.SwingUtilities;
import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
@@ -10,7 +13,15 @@
import dikuai.Dikuai;
import lujing.Lunjingguihua;
import lujing.ObstaclePathPlanner;
+import lujing.Qufenxingzhuang;
+import lujing.AoxinglujingNoObstacle;
+import lujing.YixinglujingNoObstacle;
+import publicway.Fuzhibutton;
+import lujing.AoxinglujingHaveObstacel;
+import lujing.YixinglujingHaveObstacel;
import org.locationtech.jts.geom.Coordinate;
+import gecaoji.Device;
+import java.util.Locale;
/**
* 鐢熸垚鍓茶崏璺緞椤甸潰
@@ -124,6 +135,26 @@
widthField = createInfoTextField(widthValue != null ? widthValue : "", true);
contentPanel.add(createTextFieldSection("鍓茶崏瀹藉害 (鍘樼背)", widthField));
+ // 鍓茶崏瀹夊叏璺濈锛堝彧璇绘樉绀猴級
+ String displaySafetyDistance = "鏈缃�";
+ Device device = Device.getActiveDevice();
+ if (device != null) {
+ String safetyDistanceValue = device.getMowingSafetyDistance();
+ if (safetyDistanceValue != null && !"-1".equals(safetyDistanceValue) && !safetyDistanceValue.trim().isEmpty()) {
+ try {
+ double distanceMeters = Double.parseDouble(safetyDistanceValue.trim());
+ // 濡傛灉鍊煎ぇ浜�100锛岃涓烘槸鍘樼背锛岄渶瑕佽浆鎹负绫�
+ if (distanceMeters > 100) {
+ distanceMeters = distanceMeters / 100.0;
+ }
+ displaySafetyDistance = String.format("%.2f绫�", distanceMeters);
+ } catch (NumberFormatException e) {
+ displaySafetyDistance = "鏈缃�";
+ }
+ }
+ }
+ contentPanel.add(createInfoValueSection("鍓茶崏瀹夊叏璺濈", displaySafetyDistance));
+
// 鍓茶崏妯″紡锛堝彧璇绘樉绀猴級
contentPanel.add(createInfoValueSection("鍓茶崏妯″紡", formatMowingPatternForDialog(modeValue)));
@@ -143,14 +174,17 @@
buttonPanel.setBackground(BACKGROUND_COLOR);
JButton generateBtn = createPrimaryFooterButton("鐢熸垚鍓茶崏璺緞");
+ JButton previewBtn = createPrimaryFooterButton("棰勮");
JButton saveBtn = createPrimaryFooterButton("淇濆瓨璺緞");
JButton cancelBtn = createPrimaryFooterButton("鍙栨秷");
generateBtn.addActionListener(e -> generatePath(modeValue));
+ previewBtn.addActionListener(e -> previewPath());
saveBtn.addActionListener(e -> savePath());
cancelBtn.addActionListener(e -> dispose());
buttonPanel.add(generateBtn);
+ buttonPanel.add(previewBtn);
buttonPanel.add(saveBtn);
buttonPanel.add(cancelBtn);
add(buttonPanel, BorderLayout.SOUTH);
@@ -187,6 +221,123 @@
}
/**
+ * 棰勮璺緞
+ */
+ private void previewPath() {
+ // 鍏堜繚瀛樺綋鍓嶈矾寰勫埌鍦板潡锛堜复鏃朵繚瀛橈紝鐢ㄤ簬棰勮锛�
+ String pathNormalized = normalizeCoordinateInput(pathArea.getText());
+ if (!"-1".equals(pathNormalized)) {
+ pathNormalized = pathNormalized
+ .replace("\r\n", ";")
+ .replace('\r', ';')
+ .replace('\n', ';')
+ .replaceAll(";+", ";")
+ .replaceAll("\\s*;\\s*", ";")
+ .trim();
+ if (pathNormalized.isEmpty()) {
+ pathNormalized = "-1";
+ }
+ }
+
+ if ("-1".equals(pathNormalized)) {
+ JOptionPane.showMessageDialog(this, "璇峰厛鐢熸垚鍓茶崏璺緞", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // 涓存椂淇濆瓨璺緞鍒板湴鍧楀璞★紙涓嶆寔涔呭寲锛�
+ if (saveCallback != null) {
+ saveCallback.savePlannedPath(dikuai, pathNormalized);
+ }
+
+ // 淇濆瓨褰撳墠椤甸潰鐘舵�侊紝鐢ㄤ簬杩斿洖鏃舵仮澶�
+ String currentBaseStation = baseStationField.getText();
+ String currentBoundary = boundaryArea.getText();
+ String currentObstacle = obstacleArea.getText();
+ String currentWidth = widthField.getText();
+ String currentPath = pathArea.getText();
+
+ // 鑾峰彇鍦板潡淇℃伅
+ String landNumber = dikuai.getLandNumber();
+ String landName = dikuai.getLandName();
+
+ // 澶勭悊杈圭晫鍧愭爣锛岀‘淇濆彉閲忔槸 effectively final
+ String boundaryInput = normalizeCoordinateInput(boundaryArea.getText());
+ final String boundary;
+ if (!"-1".equals(boundaryInput)) {
+ String processed = boundaryInput.replace("\r\n", ";")
+ .replace('\r', ';')
+ .replace('\n', ';')
+ .replaceAll(";+", ";")
+ .replaceAll("\\s*;\\s*", ";")
+ .trim();
+ if (processed.isEmpty()) {
+ boundary = dikuai.getBoundaryCoordinates();
+ } else {
+ boundary = processed;
+ }
+ } else {
+ boundary = dikuai.getBoundaryCoordinates();
+ }
+
+ // 澶勭悊闅滅鐗╁潗鏍囷紝纭繚鍙橀噺鏄� effectively final
+ String obstaclesInput = normalizeCoordinateInput(obstacleArea.getText());
+ final String obstacles;
+ if (!"-1".equals(obstaclesInput)) {
+ String processed = obstaclesInput.replace("\r\n", " ")
+ .replace('\r', ' ')
+ .replace('\n', ' ')
+ .replaceAll("\\s{2,}", " ")
+ .trim();
+ if (processed.isEmpty()) {
+ obstacles = null;
+ } else {
+ obstacles = processed;
+ }
+ } else {
+ obstacles = null;
+ }
+
+ // 淇濆瓨鏈�缁堝�煎埌 final 鍙橀噺锛屼互渚垮湪 lambda 涓娇鐢�
+ final String finalPathNormalized = pathNormalized;
+ final String finalLandNumber = landNumber;
+ final String finalLandName = landName;
+
+ // 鍏抽棴璺緞瑙勫垝椤甸潰
+ setVisible(false);
+
+ // 鎵撳紑涓婚〉闈㈠苟鏄剧ず璺緞棰勮
+ SwingUtilities.invokeLater(() -> {
+ zhuye.Shouye shouye = zhuye.Shouye.getInstance();
+ if (shouye != null) {
+ // 鏄剧ず璺緞棰勮锛屽苟璁剧疆杩斿洖鍥炶皟
+ shouye.startMowingPathPreview(
+ finalLandNumber,
+ finalLandName,
+ boundary,
+ obstacles,
+ finalPathNormalized,
+ () -> {
+ // 杩斿洖鍥炶皟锛氶噸鏂版墦寮�璺緞瑙勫垝椤甸潰
+ SwingUtilities.invokeLater(() -> {
+ setVisible(true);
+ // 鎭㈠涔嬪墠鐨勭姸鎬�
+ baseStationField.setText(currentBaseStation);
+ boundaryArea.setText(currentBoundary);
+ obstacleArea.setText(currentObstacle);
+ widthField.setText(currentWidth);
+ pathArea.setText(currentPath);
+ });
+ }
+ );
+ } else {
+ // 濡傛灉涓婚〉闈笉瀛樺湪锛屾彁绀虹敤鎴峰苟閲嶆柊鏄剧ず璺緞瑙勫垝椤甸潰
+ JOptionPane.showMessageDialog(null, "鏃犳硶鎵撳紑涓婚〉闈㈣繘琛岄瑙�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+ setVisible(true);
+ }
+ });
+ }
+
+ /**
* 淇濆瓨璺緞
*/
private void savePath() {
@@ -348,64 +499,137 @@
obstacles = obstacles.replace("\r\n", " ").replace('\r', ' ').replace('\n', ' ');
}
+ // 鑾峰彇瀹夊叏璺濈
+ String safetyMarginStr = getSafetyDistanceString();
+ if (safetyMarginStr == null) {
+ // 濡傛灉娌℃湁璁剧疆瀹夊叏璺濈锛屼娇鐢ㄩ粯璁ゅ�硷細鍓茶崏瀹藉害鐨勪竴鍗� + 0.2绫�
+ double defaultSafetyDistance = widthMeters / 2.0 + 0.2;
+ safetyMarginStr = BigDecimal.valueOf(defaultSafetyDistance)
+ .setScale(3, RoundingMode.HALF_UP)
+ .stripTrailingZeros()
+ .toPlainString();
+ }
+
String mode = normalizeExistingMowingPattern(modeInput);
try {
+ // 1. 棣栧厛鍒ゆ柇鍦板潡绫诲瀷锛堝嚫褰㈣繕鏄紓褰級
+ Qufenxingzhuang shapeJudger = new Qufenxingzhuang();
+ int grassType = shapeJudger.judgeGrassType(boundary);
+ // grassType: 0=鏃犳硶鍒ゆ柇, 1=鍑稿舰, 2=寮傚舰
+
// 瑙f瀽闅滅鐗╁垪琛�
List<List<Coordinate>> obstacleList = Lunjingguihua.parseObstacles(obstacles);
if (obstacleList == null) {
obstacleList = new ArrayList<>();
}
- // 鍒ゆ柇鏄惁鏈夐殰纰嶇墿锛氬彧瑕佸師濮嬭緭鍏ユ湁闅滅鐗╁唴瀹癸紝灏变娇鐢∣bstaclePathPlanner
- // 鍗充娇瑙f瀽鍚庡垪琛ㄤ负绌猴紝涔熷皾璇曚娇鐢∣bstaclePathPlanner锛堝畠浼氬鐞嗙┖闅滅鐗╁垪琛ㄧ殑鎯呭喌锛�
- boolean hasObstacles = hasObstacleInput && !obstacleList.isEmpty();
+ // 鍒ゆ柇鏄惁鏈夋湁鏁堢殑闅滅鐗╋細鍙湁褰撹В鏋愭垚鍔熶笖鍒楄〃涓嶄负绌烘椂锛屾墠璁や负鏈夐殰纰嶇墿
+ boolean hasValidObstacles = !obstacleList.isEmpty();
- // 濡傛灉鍘熷杈撳叆鏈夐殰纰嶇墿浣嗚В鏋愬け璐ワ紝缁欏嚭鎻愮ず
- if (hasObstacleInput && obstacleList.isEmpty()) {
- if (showMessages) {
- JOptionPane.showMessageDialog(parentComponent,
- "闅滅鐗╁潗鏍囨牸寮忓彲鑳戒笉姝g‘锛屽皢灏濊瘯鐢熸垚璺緞銆傚鏋滆矾寰勪笉姝g‘锛岃妫�鏌ラ殰纰嶇墿鍧愭爣鏍煎紡銆�",
- "鎻愮ず", JOptionPane.WARNING_MESSAGE);
- }
- // 浠嶇劧灏濊瘯浣跨敤ObstaclePathPlanner锛屽嵆浣块殰纰嶇墿鍒楄〃涓虹┖
- // 杩欐牱鑷冲皯鍙互纭繚浣跨敤姝g‘鐨勮矾寰勮鍒掑櫒
- }
+ String generated = null;
- String generated;
-
- if (!hasObstacles && !hasObstacleInput) {
- // 瀹屽叏娌℃湁闅滅鐗╄緭鍏ユ椂锛屼娇鐢↙unjingguihua绫荤殑鏂规硶鐢熸垚璺緞
- generated = Lunjingguihua.generatePathFromStrings(
- boundary,
- obstacles != null ? obstacles : "",
- plannerWidth,
- mode
- );
- } else {
- // 鏈夐殰纰嶇墿杈撳叆鏃讹紙鍗充娇瑙f瀽澶辫触锛夛紝浣跨敤ObstaclePathPlanner澶勭悊璺緞鐢熸垚
- List<Coordinate> polygon = Lunjingguihua.parseCoordinates(boundary);
- if (polygon.size() < 4) {
- if (showMessages) {
- JOptionPane.showMessageDialog(parentComponent, "澶氳竟褰㈠潗鏍囨暟閲忎笉瓒筹紝鑷冲皯闇�瑕佷笁涓偣",
- "閿欒", JOptionPane.ERROR_MESSAGE);
+ // 2. 鏍规嵁鍦板潡绫诲瀷鍜屾槸鍚︽湁闅滅鐗╋紝璋冪敤涓嶅悓鐨勮矾寰勭敓鎴愮被
+ if (!hasValidObstacles) {
+ // 鏃犻殰纰嶇墿鐨勬儏鍐�
+ if (grassType == 1) {
+ // 鍑稿舰鍦板潡锛屾棤闅滅鐗� -> 璋冪敤 AoxinglujingNoObstacle
+ List<AoxinglujingNoObstacle.PathSegment> segments =
+ AoxinglujingNoObstacle.planPath(boundary, plannerWidth, safetyMarginStr);
+ generated = formatAoxingPathSegments(segments);
+ } else if (grassType == 2) {
+ // 寮傚舰鍦板潡锛屾棤闅滅鐗� -> 璋冪敤 YixinglujingNoObstacle
+ // 娉ㄦ剰锛氬鏋滆绫昏繕娌℃湁瀹炵幇锛岃繖閲屼細鎶涘嚭寮傚父鎴栬繑鍥瀗ull
+ try {
+ // 鍋囪 YixinglujingNoObstacle 鏈夌被浼肩殑鏂规硶绛惧悕
+ // 濡傛灉绫昏繕娌℃湁瀹炵幇锛屽彲鑳介渶瑕佷娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ generated = YixinglujingNoObstacle.planPath(boundary, plannerWidth, safetyMarginStr);
+ } catch (Exception e) {
+ // 濡傛灉绫昏繕娌℃湁瀹炵幇锛屼娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ if (showMessages) {
+ System.err.println("YixinglujingNoObstacle 灏氭湭瀹炵幇锛屼娇鐢ㄩ粯璁ゆ柟娉�: " + e.getMessage());
+ }
+ generated = Lunjingguihua.generatePathFromStrings(
+ boundary, obstacles != null ? obstacles : "", plannerWidth, safetyMarginStr, mode);
}
- return null;
- }
-
- // 鏍规嵁鏄惁鏈夐殰纰嶇墿璁剧疆涓嶅悓鐨勫畨鍏ㄨ窛绂�
- double safetyDistance;
- if (!obstacleList.isEmpty()) {
- // 鏈夐殰纰嶇墿鏃朵娇鐢ㄥ壊鑽夊搴︾殑涓�鍗� + 0.05绫抽澶栧畨鍏ㄨ窛绂�
- safetyDistance = widthMeters / 2.0 + 0.05;
} else {
- // 闅滅鐗╄В鏋愬け璐ヤ絾杈撳叆瀛樺湪锛屼娇鐢ㄨ緝灏忕殑瀹夊叏璺濈
- safetyDistance = 0.01;
+ // 鏃犳硶鍒ゆ柇鍦板潡绫诲瀷锛屼娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ if (showMessages) {
+ JOptionPane.showMessageDialog(parentComponent, "鏃犳硶鍒ゆ柇鍦板潡绫诲瀷锛屼娇鐢ㄩ粯璁よ矾寰勭敓鎴愭柟娉�",
+ "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+ }
+ generated = Lunjingguihua.generatePathFromStrings(
+ boundary, obstacles != null ? obstacles : "", plannerWidth, safetyMarginStr, mode);
}
-
- ObstaclePathPlanner pathPlanner = new ObstaclePathPlanner(
- polygon, widthMeters, mode, obstacleList, safetyDistance);
- List<Lunjingguihua.PathSegment> segments = pathPlanner.generate();
- generated = Lunjingguihua.formatPathSegments(segments);
+ } else {
+ // 鏈夐殰纰嶇墿鐨勬儏鍐�
+ if (grassType == 1) {
+ // 鍑稿舰鍦板潡锛屾湁闅滅鐗� -> 璋冪敤 AoxinglujingHaveObstacel
+ try {
+ // 鍋囪 AoxinglujingHaveObstacel 鏈夌被浼肩殑鏂规硶绛惧悕
+ generated = AoxinglujingHaveObstacel.planPath(boundary, obstacles, plannerWidth, safetyMarginStr);
+ } catch (Exception e) {
+ // 濡傛灉绫昏繕娌℃湁瀹炵幇锛屼娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ if (showMessages) {
+ System.err.println("AoxinglujingHaveObstacel 灏氭湭瀹炵幇锛屼娇鐢ㄩ粯璁ゆ柟娉�: " + e.getMessage());
+ }
+ List<Coordinate> polygon = Lunjingguihua.parseCoordinates(boundary);
+ if (polygon.size() < 4) {
+ if (showMessages) {
+ JOptionPane.showMessageDialog(parentComponent, "澶氳竟褰㈠潗鏍囨暟閲忎笉瓒筹紝鑷冲皯闇�瑕佷笁涓偣",
+ "閿欒", JOptionPane.ERROR_MESSAGE);
+ }
+ return null;
+ }
+ double safetyDistance = Double.parseDouble(safetyMarginStr);
+ ObstaclePathPlanner pathPlanner = new ObstaclePathPlanner(
+ polygon, widthMeters, mode, obstacleList, safetyDistance);
+ List<Lunjingguihua.PathSegment> segments = pathPlanner.generate();
+ generated = Lunjingguihua.formatPathSegments(segments);
+ }
+ } else if (grassType == 2) {
+ // 寮傚舰鍦板潡锛屾湁闅滅鐗� -> 璋冪敤 YixinglujingHaveObstacel
+ try {
+ // 鍋囪 YixinglujingHaveObstacel 鏈夌被浼肩殑鏂规硶绛惧悕
+ generated = YixinglujingHaveObstacel.planPath(boundary, obstacles, plannerWidth, safetyMarginStr);
+ } catch (Exception e) {
+ // 濡傛灉绫昏繕娌℃湁瀹炵幇锛屼娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ if (showMessages) {
+ System.err.println("YixinglujingHaveObstacel 灏氭湭瀹炵幇锛屼娇鐢ㄩ粯璁ゆ柟娉�: " + e.getMessage());
+ }
+ List<Coordinate> polygon = Lunjingguihua.parseCoordinates(boundary);
+ if (polygon.size() < 4) {
+ if (showMessages) {
+ JOptionPane.showMessageDialog(parentComponent, "澶氳竟褰㈠潗鏍囨暟閲忎笉瓒筹紝鑷冲皯闇�瑕佷笁涓偣",
+ "閿欒", JOptionPane.ERROR_MESSAGE);
+ }
+ return null;
+ }
+ double safetyDistance = Double.parseDouble(safetyMarginStr);
+ ObstaclePathPlanner pathPlanner = new ObstaclePathPlanner(
+ polygon, widthMeters, mode, obstacleList, safetyDistance);
+ List<Lunjingguihua.PathSegment> segments = pathPlanner.generate();
+ generated = Lunjingguihua.formatPathSegments(segments);
+ }
+ } else {
+ // 鏃犳硶鍒ゆ柇鍦板潡绫诲瀷锛屼娇鐢ㄥ師鏉ョ殑鏂规硶浣滀负鍚庡
+ if (showMessages) {
+ JOptionPane.showMessageDialog(parentComponent, "鏃犳硶鍒ゆ柇鍦板潡绫诲瀷锛屼娇鐢ㄩ粯璁よ矾寰勭敓鎴愭柟娉�",
+ "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+ }
+ List<Coordinate> polygon = Lunjingguihua.parseCoordinates(boundary);
+ if (polygon.size() < 4) {
+ if (showMessages) {
+ JOptionPane.showMessageDialog(parentComponent, "澶氳竟褰㈠潗鏍囨暟閲忎笉瓒筹紝鑷冲皯闇�瑕佷笁涓偣",
+ "閿欒", JOptionPane.ERROR_MESSAGE);
+ }
+ return null;
+ }
+ double safetyDistance = Double.parseDouble(safetyMarginStr);
+ ObstaclePathPlanner pathPlanner = new ObstaclePathPlanner(
+ polygon, widthMeters, mode, obstacleList, safetyDistance);
+ List<Lunjingguihua.PathSegment> segments = pathPlanner.generate();
+ generated = Lunjingguihua.formatPathSegments(segments);
+ }
}
String trimmed = generated != null ? generated.trim() : "";
@@ -436,6 +660,77 @@
return null;
}
+ /**
+ * 鑾峰彇瀹夊叏璺濈瀛楃涓诧紙绫筹級
+ */
+ private String getSafetyDistanceString() {
+ Device device = Device.getActiveDevice();
+ if (device != null) {
+ String safetyDistanceValue = device.getMowingSafetyDistance();
+ if (safetyDistanceValue != null && !"-1".equals(safetyDistanceValue) && !safetyDistanceValue.trim().isEmpty()) {
+ try {
+ double distanceMeters = Double.parseDouble(safetyDistanceValue.trim());
+ // 濡傛灉鍊煎ぇ浜�100锛岃涓烘槸鍘樼背锛岄渶瑕佽浆鎹负绫�
+ if (distanceMeters > 100) {
+ distanceMeters = distanceMeters / 100.0;
+ }
+ return BigDecimal.valueOf(distanceMeters)
+ .setScale(3, RoundingMode.HALF_UP)
+ .stripTrailingZeros()
+ .toPlainString();
+ } catch (NumberFormatException e) {
+ // 瑙f瀽澶辫触锛岃繑鍥瀗ull锛屼娇鐢ㄩ粯璁ゅ��
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 鏍煎紡鍖� AoxinglujingNoObstacle.PathSegment 鍒楄〃涓哄潗鏍囧瓧绗︿覆
+ */
+ private String formatAoxingPathSegments(List<AoxinglujingNoObstacle.PathSegment> segments) {
+ if (segments == null || segments.isEmpty()) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ AoxinglujingNoObstacle.Point last = null;
+ for (AoxinglujingNoObstacle.PathSegment segment : segments) {
+ // 鍙坊鍔犲壊鑽夊伐浣滄锛岃烦杩囪繃娓℃
+ if (segment.isMowing) {
+ // 濡傛灉璧风偣涓庝笂涓�涓粓鐐逛笉鍚岋紝娣诲姞璧风偣
+ if (last == null || !equals2D(last, segment.start)) {
+ appendPoint(sb, segment.start);
+ }
+ // 娣诲姞缁堢偣
+ appendPoint(sb, segment.end);
+ last = segment.end;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 姣旇緝涓や釜鐐规槸鍚︾浉鍚岋紙浣跨敤灏忕殑瀹瑰樊锛�
+ */
+ private boolean equals2D(AoxinglujingNoObstacle.Point p1, AoxinglujingNoObstacle.Point p2) {
+ if (p1 == null || p2 == null) {
+ return p1 == p2;
+ }
+ double tolerance = 1e-6;
+ return Math.abs(p1.x - p2.x) < tolerance && Math.abs(p1.y - p2.y) < tolerance;
+ }
+
+ /**
+ * 娣诲姞鐐瑰埌瀛楃涓叉瀯寤哄櫒
+ */
+ private void appendPoint(StringBuilder sb, AoxinglujingNoObstacle.Point point) {
+ if (sb.length() > 0) {
+ sb.append(";");
+ }
+ sb.append(String.format(Locale.US, "%.6f,%.6f", point.x, point.y));
+ }
+
// ========== UI杈呭姪鏂规硶 ==========
private JTextArea createInfoTextArea(String text, boolean editable, int rows) {
@@ -456,10 +751,31 @@
section.setBackground(BACKGROUND_COLOR);
section.setAlignmentX(Component.LEFT_ALIGNMENT);
+ // 鍒涘缓鏍囬闈㈡澘锛屽寘鍚爣棰樺拰澶嶅埗鍥炬爣
+ JPanel titlePanel = new JPanel(new BorderLayout());
+ titlePanel.setBackground(BACKGROUND_COLOR);
+ titlePanel.setOpaque(false);
+
JLabel titleLabel = new JLabel(title);
titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
titleLabel.setForeground(TEXT_COLOR);
- section.add(titleLabel, BorderLayout.NORTH);
+ titlePanel.add(titleLabel, BorderLayout.WEST);
+
+ // 鍒涘缓澶嶅埗鎸夐挳锛堜娇鐢� Fuzhibutton锛�
+ JButton copyButton = Fuzhibutton.createCopyButton(
+ () -> {
+ String text = textArea.getText();
+ if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+ return null; // 杩斿洖null浼氳Е鍙�"鏈缃�"鎻愮ず
+ }
+ return text;
+ },
+ "澶嶅埗" + title,
+ new Color(230, 250, 240)
+ );
+ titlePanel.add(copyButton, BorderLayout.EAST);
+
+ section.add(titlePanel, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
@@ -488,10 +804,31 @@
section.setBackground(BACKGROUND_COLOR);
section.setAlignmentX(Component.LEFT_ALIGNMENT);
+ // 鍒涘缓鏍囬闈㈡澘锛屽寘鍚爣棰樺拰澶嶅埗鍥炬爣
+ JPanel titlePanel = new JPanel(new BorderLayout());
+ titlePanel.setBackground(BACKGROUND_COLOR);
+ titlePanel.setOpaque(false);
+
JLabel titleLabel = new JLabel(title);
titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
titleLabel.setForeground(TEXT_COLOR);
- section.add(titleLabel, BorderLayout.NORTH);
+ titlePanel.add(titleLabel, BorderLayout.WEST);
+
+ // 鍒涘缓澶嶅埗鎸夐挳锛堜娇鐢� Fuzhibutton锛�
+ JButton copyButton = Fuzhibutton.createCopyButton(
+ () -> {
+ String text = textField.getText();
+ if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+ return null; // 杩斿洖null浼氳Е鍙�"鏈缃�"鎻愮ず
+ }
+ return text;
+ },
+ "澶嶅埗" + title,
+ new Color(230, 250, 240)
+ );
+ titlePanel.add(copyButton, BorderLayout.EAST);
+
+ section.add(titlePanel, BorderLayout.NORTH);
JPanel fieldWrapper = new JPanel(new BorderLayout());
fieldWrapper.setBackground(textField.isEditable() ? WHITE : new Color(245, 245, 245));
@@ -629,6 +966,7 @@
}
return "parallel";
}
+
}
--
Gitblit v1.10.0