From 13d032241e1a2938a8be4f64c9171e1240e9ea1e Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期一, 22 十二月 2025 18:50:42 +0800
Subject: [PATCH] 新增了边界管理页面和首页边界虚线功能
---
src/dikuai/ObstacleManagementPage.java | 317 +++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 273 insertions(+), 44 deletions(-)
diff --git a/src/dikuai/ObstacleManagementPage.java b/src/dikuai/ObstacleManagementPage.java
index 43cd9e4..9a9dd25 100644
--- a/src/dikuai/ObstacleManagementPage.java
+++ b/src/dikuai/ObstacleManagementPage.java
@@ -14,10 +14,14 @@
import zhangaiwu.Obstacledge;
import zhuye.Shouye;
+import zhuye.Coordinate;
+import bianjie.bianjieguihua2;
/**
* 闅滅鐗╃鐞嗛〉闈� - UI浼樺寲鐗�
*/
+import publicway.Gpstoxuzuobiao;
+
public class ObstacleManagementPage extends JDialog {
private static final long serialVersionUID = 1L;
@@ -297,7 +301,17 @@
JTextArea xyArea = createDataTextArea(genCoords, 3); // 寮曠敤浠ヤ究鏇存柊
JScrollPane scrollXY = new JScrollPane(xyArea);
scrollXY.setBorder(BorderFactory.createEmptyBorder()); // 澶栭儴鐢盤anel鎻愪緵杈规
-
+ // 璁剧疆婊氬姩鏉$瓥鐣ワ細闇�瑕佹椂鏄剧ず鍨傜洿婊氬姩鏉★紝涓嶄娇鐢ㄦ按骞虫粴鍔ㄦ潯锛堝洜涓哄惎鐢ㄤ簡鑷姩鎹㈣锛�
+ scrollXY.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ scrollXY.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ // 璁剧疆婊氬姩鏉″崟浣嶅閲忥紝浣挎粴鍔ㄦ洿娴佺晠
+ scrollXY.getVerticalScrollBar().setUnitIncrement(16);
+ // 璁剧疆婊氬姩闈㈡澘鐨勯閫夊ぇ灏忥紝纭繚鍦ㄥ唴瀹硅秴鍑烘椂鏄剧ず婊氬姩鏉�
+ int lineHeight = xyArea.getFontMetrics(xyArea.getFont()).getHeight();
+ int preferredHeight = 3 * lineHeight + 10; // 3琛岀殑楂樺害
+ scrollXY.setPreferredSize(new Dimension(Integer.MAX_VALUE, preferredHeight));
+ scrollXY.setMaximumSize(new Dimension(Integer.MAX_VALUE, 200)); // 鏈�澶ч珮搴�200鍍忕礌
+
JPanel xyWrapper = createWrapperPanel("鐢熸垚鍧愭爣 (XY绫�)", scrollXY);
card.add(xyWrapper);
card.add(Box.createVerticalStrut(15));
@@ -307,15 +321,21 @@
actionPanel.setLayout(new BoxLayout(actionPanel, BoxLayout.X_AXIS));
actionPanel.setOpaque(false);
- JButton generateBtn = createStyledButton("閲嶆柊鐢熸垚鍧愭爣", PRIMARY_COLOR, true);
- generateBtn.addActionListener(e -> generateObstacleCoordinates(obstacle, xyArea));
+ // 瀵逛簬鍦嗗舰闅滅鐗╋紝涓嶆樉绀�"閲嶆柊鐢熸垚鍧愭爣"鎸夐挳锛屽彧鏄剧ず棰勮鎸夐挳
+ Obstacledge.ObstacleShape shape = obstacle.getShape();
+ boolean isCircle = (shape == Obstacledge.ObstacleShape.CIRCLE);
+
+ if (!isCircle) {
+ // 鍙湁闈炲渾褰㈤殰纰嶇墿鎵嶆樉绀�"閲嶆柊鐢熸垚鍧愭爣"鎸夐挳
+ JButton generateBtn = createStyledButton("閲嶆柊鐢熸垚鍧愭爣", PRIMARY_COLOR, true);
+ generateBtn.addActionListener(e -> generateObstacleCoordinates(obstacle, xyArea));
+ actionPanel.add(generateBtn);
+ actionPanel.add(Box.createHorizontalStrut(10));
+ }
JButton previewBtn = createStyledButton("棰勮", TEXT_SECONDARY, false);
previewBtn.setPreferredSize(new Dimension(70, 36)); // 绋嶅井绐勪竴鐐�
previewBtn.addActionListener(e -> previewObstacle(obstacle));
-
- actionPanel.add(generateBtn);
- actionPanel.add(Box.createHorizontalStrut(10));
actionPanel.add(previewBtn);
card.add(actionPanel);
@@ -330,6 +350,16 @@
JTextArea area = createDataTextArea(content, rows);
JScrollPane scroll = new JScrollPane(area);
scroll.setBorder(BorderFactory.createEmptyBorder());
+ // 璁剧疆婊氬姩鏉$瓥鐣ワ細闇�瑕佹椂鏄剧ず鍨傜洿婊氬姩鏉★紝涓嶄娇鐢ㄦ按骞虫粴鍔ㄦ潯锛堝洜涓哄惎鐢ㄤ簡鑷姩鎹㈣锛�
+ scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ // 璁剧疆婊氬姩鏉″崟浣嶅閲忥紝浣挎粴鍔ㄦ洿娴佺晠
+ scroll.getVerticalScrollBar().setUnitIncrement(16);
+ // 璁剧疆婊氬姩闈㈡澘鐨勯閫夊ぇ灏忥紝纭繚鍦ㄥ唴瀹硅秴鍑烘椂鏄剧ず婊氬姩鏉�
+ int lineHeight = area.getFontMetrics(area.getFont()).getHeight();
+ int preferredHeight = rows * lineHeight + 10; // 鏍规嵁琛屾暟璁$畻棣栭�夐珮搴�
+ scroll.setPreferredSize(new Dimension(Integer.MAX_VALUE, preferredHeight));
+ scroll.setMaximumSize(new Dimension(Integer.MAX_VALUE, 200)); // 鏈�澶ч珮搴�200鍍忕礌
return createWrapperPanel(title, scroll);
}
@@ -358,12 +388,13 @@
JTextArea area = new JTextArea(text);
area.setRows(rows);
area.setEditable(false);
+ // 鍚敤鑷姩鎹㈣
area.setLineWrap(true);
area.setWrapStyleWord(true);
area.setBackground(BG_INPUT);
area.setForeground(new Color(50, 50, 50));
// 浣跨敤绛夊瀛椾綋鏄剧ず鏁版嵁锛岀湅璧锋潵鏇翠笓涓�
- area.setFont(new Font("Monospaced", Font.PLAIN, 12));
+ area.setFont(new Font("Monospaced", Font.PLAIN, 12));
return area;
}
@@ -537,28 +568,111 @@
return;
}
+ // 璁$畻闅滅鐗╃殑涓績鐐瑰潗鏍�
+ double[] centerCoords = calculateObstacleCenter(obstacle);
+
List<Obstacledge.Obstacle> allObstacles = loadObstacles();
String allObstaclesCoords = buildAllObstaclesCoordinates(allObstacles);
- setVisible(false);
+ // 鍏抽棴闅滅鐗╃鐞嗛〉闈�
+ dispose();
SwingUtilities.invokeLater(() -> {
Shouye shouye = Shouye.getInstance();
if (shouye != null) {
+ // 浼犻�掑洖璋冧互閲嶆柊鎵撳紑闅滅鐗╃鐞嗛〉闈�
shouye.startMowingPathPreview(
landNumber,
landName,
boundary,
allObstaclesCoords,
null,
- () -> SwingUtilities.invokeLater(() -> setVisible(true))
+ () -> SwingUtilities.invokeLater(() -> {
+ // 閲嶆柊鎵撳紑闅滅鐗╃鐞嗛〉闈�
+ Window owner = SwingUtilities.getWindowAncestor(shouye);
+ ObstacleManagementPage newPage = new ObstacleManagementPage(owner, dikuai);
+ newPage.setVisible(true);
+ })
);
+
+ // 灏嗗湴鍥捐鍥句腑蹇冭缃负闅滅鐗╃殑涓績浣嶇疆
+ if (centerCoords != null && shouye.getMapRenderer() != null) {
+ double currentScale = shouye.getMapRenderer().getScale();
+ // 灏嗚鍥句腑蹇冭缃负闅滅鐗╀腑蹇冿紙浣跨敤璐熷�硷紝鍥犱负translate鏄浉瀵逛簬鍘熺偣鐨勫亸绉伙級
+ shouye.getMapRenderer().setViewTransform(currentScale, -centerCoords[0], -centerCoords[1]);
+ }
} else {
JOptionPane.showMessageDialog(null, "鏃犳硶鎵撳紑涓婚〉闈㈣繘琛岄瑙�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
- setVisible(true);
}
});
}
+
+ /**
+ * 璁$畻闅滅鐗╃殑涓績鐐瑰潗鏍�
+ * @param obstacle 闅滅鐗�
+ * @return 涓績鐐瑰潗鏍� [centerX, centerY]锛屽鏋滄棤娉曡绠楀垯杩斿洖null
+ */
+ private double[] calculateObstacleCenter(Obstacledge.Obstacle obstacle) {
+ if (obstacle == null) {
+ return null;
+ }
+
+ List<Obstacledge.XYCoordinate> xyCoords = obstacle.getXyCoordinates();
+ if (xyCoords == null || xyCoords.isEmpty()) {
+ return null;
+ }
+
+ Obstacledge.ObstacleShape shape = obstacle.getShape();
+ double centerX, centerY;
+
+ if (shape == Obstacledge.ObstacleShape.CIRCLE) {
+ // 鍦嗗舰闅滅鐗╋細绗竴涓潗鏍囩偣灏辨槸鍦嗗績
+ if (xyCoords.size() < 1) {
+ return null;
+ }
+ Obstacledge.XYCoordinate centerCoord = xyCoords.get(0);
+ centerX = centerCoord.getX();
+ centerY = centerCoord.getY();
+ } else if (shape == Obstacledge.ObstacleShape.POLYGON) {
+ // 澶氳竟褰㈤殰纰嶇墿锛氳绠楅噸蹇�
+ centerX = 0.0;
+ centerY = 0.0;
+ double area = 0.0;
+ int n = xyCoords.size();
+
+ for (int i = 0; i < n; i++) {
+ Obstacledge.XYCoordinate current = xyCoords.get(i);
+ Obstacledge.XYCoordinate next = xyCoords.get((i + 1) % n);
+ double x0 = current.getX();
+ double y0 = current.getY();
+ double x1 = next.getX();
+ double y1 = next.getY();
+ double cross = x0 * y1 - x1 * y0;
+ area += cross;
+ centerX += (x0 + x1) * cross;
+ centerY += (y0 + y1) * cross;
+ }
+
+ double areaFactor = area * 0.5;
+ if (Math.abs(areaFactor) < 1e-9) {
+ // 濡傛灉闈㈢Н涓�0鎴栨帴杩�0锛屼娇鐢ㄧ畝鍗曞钩鍧�
+ for (Obstacledge.XYCoordinate coord : xyCoords) {
+ centerX += coord.getX();
+ centerY += coord.getY();
+ }
+ int size = Math.max(1, xyCoords.size());
+ centerX /= size;
+ centerY /= size;
+ } else {
+ centerX = centerX / (6.0 * areaFactor);
+ centerY = centerY / (6.0 * areaFactor);
+ }
+ } else {
+ return null;
+ }
+
+ return new double[]{centerX, centerY};
+ }
private String buildAllObstaclesCoordinates(List<Obstacledge.Obstacle> obstacles) {
if (obstacles == null || obstacles.isEmpty()) return null;
@@ -612,23 +726,23 @@
return;
}
- double baseLat = parseDMToDecimal(baseParts[0].trim(), baseParts[1].trim());
- double baseLon = parseDMToDecimal(baseParts[2].trim(), baseParts[3].trim());
+ Obstacledge.ObstacleShape shape = obstacle.getShape();
+ List<Obstacledge.XYCoordinate> xyCoords;
- List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>();
- for (int i = 0; i < originalCoordsList.size(); i += 2) {
- if (i + 1 >= originalCoordsList.size()) break;
- double lat = originalCoordsList.get(i).toDecimalDegree();
- double lon = originalCoordsList.get(i + 1).toDecimalDegree();
-
- if (Double.isFinite(lat) && Double.isFinite(lon)) {
- double[] localXY = convertLatLonToLocal(lat, lon, baseLat, baseLon);
- xyCoords.add(new Obstacledge.XYCoordinate(localXY[0], localXY[1]));
- }
+ // 鏍规嵁闅滅鐗╁舰鐘惰皟鐢ㄤ笉鍚岀殑绠楁硶
+ if (shape == Obstacledge.ObstacleShape.POLYGON) {
+ // 澶氳竟褰細浣跨敤 bianjieguihua2 绠楁硶
+ xyCoords = generatePolygonCoordinates(originalCoordsList, baseStation);
+ } else if (shape == Obstacledge.ObstacleShape.CIRCLE) {
+ // 鍦嗗舰锛氫娇鐢ㄧ畝鍗曠殑鍧愭爣杞崲锛堜繚鎸佸師鏈夐�昏緫锛�
+ xyCoords = generateCircleCoordinates(originalCoordsList, baseStation);
+ } else {
+ JOptionPane.showMessageDialog(this, "鏈煡鐨勯殰纰嶇墿褰㈢姸", "閿欒", JOptionPane.ERROR_MESSAGE);
+ return;
}
- if (xyCoords.isEmpty()) {
- JOptionPane.showMessageDialog(this, "鍧愭爣杞崲澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
+ if (xyCoords == null || xyCoords.isEmpty()) {
+ JOptionPane.showMessageDialog(this, "鍧愭爣鐢熸垚澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
return;
}
@@ -641,6 +755,132 @@
}
}
+ /**
+ * 浣跨敤 bianjieguihua2 绠楁硶鐢熸垚澶氳竟褰㈠潗鏍�
+ */
+ private List<Obstacledge.XYCoordinate> generatePolygonCoordinates(
+ List<Obstacledge.DMCoordinate> originalCoordsList, String baseStation) {
+
+ // 淇濆瓨褰撳墠鐨� Coordinate.coordinates
+ List<Coordinate> savedCoordinates = new ArrayList<>(Coordinate.coordinates);
+
+ try {
+ // 灏嗛殰纰嶇墿鐨勫師濮嬪潗鏍囪浆鎹负 Coordinate 瀵硅薄鍒楄〃
+ List<Coordinate> coordinateList = new ArrayList<>();
+ for (int i = 0; i < originalCoordsList.size(); i += 2) {
+ if (i + 1 >= originalCoordsList.size()) break;
+
+ Obstacledge.DMCoordinate latCoord = originalCoordsList.get(i);
+ Obstacledge.DMCoordinate lonCoord = originalCoordsList.get(i + 1);
+
+ // 杞崲涓� Coordinate 瀵硅薄
+ // DMCoordinate 鐨� degreeMinute 鏄害鍒嗘牸寮忥紙濡� 2324.200273 琛ㄧず 23搴�24.200273鍒嗭級
+ // 闇�瑕佹牸寮忓寲涓哄瓧绗︿覆锛屼繚鎸佸害鍒嗘牸寮�
+ double latDM = latCoord.getDegreeMinute();
+ double lonDM = lonCoord.getDegreeMinute();
+
+ // 鏍煎紡鍖栧害鍒嗘牸寮忥細纭繚鏁存暟閮ㄥ垎鑷冲皯2浣嶏紙搴︼級锛屽皬鏁伴儴鍒嗘槸鍒�
+ String latStr = formatDegreeMinute(latDM);
+ String lonStr = formatDegreeMinute(lonDM);
+ char latDir = latCoord.getDirection();
+ char lonDir = lonCoord.getDirection();
+
+ Coordinate coord = new Coordinate(
+ latStr,
+ String.valueOf(latDir),
+ lonStr,
+ String.valueOf(lonDir),
+ 0.0 // 楂樼▼鏁版嵁锛岄殰纰嶇墿鍙兘娌℃湁锛岃涓�0
+ );
+ coordinateList.add(coord);
+ }
+
+ if (coordinateList.isEmpty()) {
+ return null;
+ }
+
+ // 璁剧疆鍒板叏灞�鍧愭爣鍒楄〃
+ Coordinate.coordinates.clear();
+ Coordinate.coordinates.addAll(coordinateList);
+
+ // 璋冪敤 bianjieguihua2 绠楁硶鐢熸垚浼樺寲鍚庣殑澶氳竟褰㈠潗鏍�
+ String optimizedCoordsStr = bianjieguihua2.processCoordinateListAuto(baseStation);
+
+ if (optimizedCoordsStr == null || optimizedCoordsStr.trim().isEmpty()) {
+ return null;
+ }
+
+ // 瑙f瀽杩斿洖鐨勫潗鏍囧瓧绗︿覆锛屾牸寮忥細"X0,Y0;X1,Y1;X2,Y2;..."
+ List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>();
+ String[] pointStrings = optimizedCoordsStr.split(";");
+ for (String pointStr : pointStrings) {
+ pointStr = pointStr.trim();
+ if (pointStr.isEmpty()) continue;
+
+ String[] parts = pointStr.split(",");
+ if (parts.length >= 2) {
+ try {
+ double x = Double.parseDouble(parts[0].trim());
+ double y = Double.parseDouble(parts[1].trim());
+ if (Double.isFinite(x) && Double.isFinite(y)) {
+ xyCoords.add(new Obstacledge.XYCoordinate(x, y));
+ }
+ } catch (NumberFormatException e) {
+ // 璺宠繃鏃犳晥鐨勫潗鏍囩偣
+ continue;
+ }
+ }
+ }
+
+ return xyCoords;
+
+ } finally {
+ // 鎭㈠鍘熸潵鐨勫潗鏍囧垪琛�
+ Coordinate.coordinates.clear();
+ Coordinate.coordinates.addAll(savedCoordinates);
+ }
+ }
+
+ /**
+ * 鏍煎紡鍖栧害鍒嗘牸寮忓潗鏍�
+ * @param degreeMinute 搴﹀垎鍊硷紝濡� 2324.200273 琛ㄧず 23搴�24.200273鍒�
+ * @return 鏍煎紡鍖栫殑瀛楃涓�
+ */
+ private String formatDegreeMinute(double degreeMinute) {
+ // 搴﹀垎鏍煎紡锛氭暣鏁伴儴鍒嗘槸搴︼紝灏忔暟閮ㄥ垎鏄垎
+ // 渚嬪 2324.200273 -> "2324.200273"
+ return String.format("%.6f", degreeMinute);
+ }
+
+ /**
+ * 鐢熸垚鍦嗗舰鍧愭爣锛堜繚鎸佸師鏈夌畝鍗曡浆鎹㈤�昏緫锛�
+ */
+ private List<Obstacledge.XYCoordinate> generateCircleCoordinates(
+ List<Obstacledge.DMCoordinate> originalCoordsList, String baseStation) {
+
+ String[] baseParts = baseStation.split(",");
+ if (baseParts.length < 4) {
+ return null;
+ }
+
+ double baseLat = parseDMToDecimal(baseParts[0].trim(), baseParts[1].trim());
+ double baseLon = parseDMToDecimal(baseParts[2].trim(), baseParts[3].trim());
+
+ List<Obstacledge.XYCoordinate> xyCoords = new ArrayList<>();
+ for (int i = 0; i < originalCoordsList.size(); i += 2) {
+ if (i + 1 >= originalCoordsList.size()) break;
+ double lat = originalCoordsList.get(i).toDecimalDegree();
+ double lon = originalCoordsList.get(i + 1).toDecimalDegree();
+
+ if (Double.isFinite(lat) && Double.isFinite(lon)) {
+ double[] localXY = convertLatLonToLocal(lat, lon, baseLat, baseLon);
+ xyCoords.add(new Obstacledge.XYCoordinate(localXY[0], localXY[1]));
+ }
+ }
+
+ return xyCoords;
+ }
+
private void saveObstacleUpdate(Obstacledge.Obstacle obstacle, JTextArea coordArea) {
String landNumber = dikuai.getLandNumber();
try {
@@ -666,29 +906,11 @@
}
private double parseDMToDecimal(String dmm, String direction) {
- if (dmm == null || dmm.trim().isEmpty()) return Double.NaN;
- try {
- String trimmed = dmm.trim();
- int dotIndex = trimmed.indexOf('.');
- if (dotIndex < 2) return Double.NaN;
- int degrees = Integer.parseInt(trimmed.substring(0, dotIndex - 2));
- double minutes = Double.parseDouble(trimmed.substring(dotIndex - 2));
- double decimal = degrees + minutes / 60.0;
- if ("S".equalsIgnoreCase(direction) || "W".equalsIgnoreCase(direction)) decimal = -decimal;
- return decimal;
- } catch (NumberFormatException ex) {
- return Double.NaN;
- }
+ return Gpstoxuzuobiao.parseDMToDecimal(dmm, direction);
}
private double[] convertLatLonToLocal(double lat, double lon, double baseLat, double baseLon) {
- double deltaLat = lat - baseLat;
- double deltaLon = lon - baseLon;
- double meanLatRad = Math.toRadians((baseLat + lat) / 2.0);
- double METERS_PER_DEGREE_LAT = 111320.0;
- double eastMeters = deltaLon * METERS_PER_DEGREE_LAT * Math.cos(meanLatRad);
- double northMeters = deltaLat * METERS_PER_DEGREE_LAT;
- return new double[]{eastMeters, northMeters};
+ return Gpstoxuzuobiao.convertLatLonToLocal(lat, lon, baseLat, baseLon);
}
private void deleteObstacle(Obstacledge.Obstacle obstacle) {
@@ -757,3 +979,10 @@
return value != null && !value.trim().isEmpty() && !"-1".equals(value.trim());
}
}
+
+
+
+
+
+
+
--
Gitblit v1.10.0