From f4a2ce6f608049dc11f00908ee8a829060882de3 Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期四, 25 十二月 2025 16:38:32 +0800
Subject: [PATCH] 优化了部分内容
---
src/lujing/AoxinglujingHaveObstacel.java | 245 +++++++++++++++++++-----------------------------
1 files changed, 97 insertions(+), 148 deletions(-)
diff --git a/src/lujing/AoxinglujingHaveObstacel.java b/src/lujing/AoxinglujingHaveObstacel.java
index 12e585e..5e2f046 100644
--- a/src/lujing/AoxinglujingHaveObstacel.java
+++ b/src/lujing/AoxinglujingHaveObstacel.java
@@ -5,8 +5,8 @@
import java.util.List;
/**
- * 鍑稿舰鑽夊湴璺緞瑙勫垝 (閬块殰浼樺寲鐗�)
- * 浼樺寲锛氬鍔犱簡闅滅鐗╁尯闂撮澶勭悊銆佽矾寰勮繛鎺ュ氨杩戝師鍒欍�佷互鍙婃洿绋冲仴鐨勫杈瑰舰澶栨墿
+ * 鍑稿舰鑽夊湴璺緞瑙勫垝 (閬块殰淇鐗�)
+ * 淇閲嶇偣锛氬己鍖栬法琛屽強閬块殰鍚庣殑璺緞杩炶疮鎬э紝纭繚姣忎竴娈靛垏鍓查兘鏈夋樉寮忕殑绉诲姩璺緞杩炴帴銆�
*/
public class AoxinglujingHaveObstacel {
@@ -35,7 +35,6 @@
public static class PolygonObstacle extends Obstacle {
public List<Point> points;
public PolygonObstacle(List<Point> points) { this.points = points; }
-
@Override
public boolean isInside(Point p) {
boolean result = false;
@@ -47,7 +46,6 @@
}
return result;
}
-
@Override
public List<Double> getIntersectionsX(double y, double angle) {
List<Point> rotated = rotatePolygon(this.points, -angle);
@@ -66,12 +64,8 @@
public Point center;
public double radius;
public CircleObstacle(Point center, double radius) { this.center = center; this.radius = radius; }
-
@Override
- public boolean isInside(Point p) {
- return Math.hypot(p.x - center.x, p.y - center.y) <= radius + EPSILON;
- }
-
+ public boolean isInside(Point p) { return Math.hypot(p.x - center.x, p.y - center.y) <= radius + EPSILON; }
@Override
public List<Double> getIntersectionsX(double y, double angle) {
List<Double> xInts = new ArrayList<>();
@@ -79,8 +73,7 @@
double dy = Math.abs(y - rCenter.y);
if (dy < radius) {
double dx = Math.sqrt(radius * radius - dy * dy);
- xInts.add(rCenter.x - dx);
- xInts.add(rCenter.x + dx);
+ xInts.add(rCenter.x - dx); xInts.add(rCenter.x + dx);
}
return xInts;
}
@@ -91,13 +84,11 @@
double width = Double.parseDouble(widthStr);
double margin = Double.parseDouble(marginStr);
List<Obstacle> obstacles = parseObstacles(obstacleStr, margin);
-
return planPathCore(boundary, obstacles, width, margin);
}
private static List<PathSegment> planPathCore(List<Point> boundary, List<Obstacle> obstacles, double width, double margin) {
if (boundary.size() < 3) return new ArrayList<>();
-
ensureCCW(boundary);
List<Point> workArea = shrinkPolygon(boundary, margin);
if (workArea.size() < 3) return new ArrayList<>();
@@ -107,109 +98,94 @@
List<Point> alignedWorkArea = alignBoundaryToStart(workArea, firstScanStart);
List<PathSegment> finalPath = new ArrayList<>();
-
- // 1. 鍥磋竟璺緞
+ // 1. 娣诲姞鍥磋竟璺緞
for (int i = 0; i < alignedWorkArea.size(); i++) {
finalPath.add(new PathSegment(alignedWorkArea.get(i), alignedWorkArea.get((i + 1) % alignedWorkArea.size()), true));
}
- // 2. 鍐呴儴濉厖
+ // 2. 鐢熸垚鍐呴儴寮撳瓧褰� (寮哄寲杩炴帴閫昏緫)
Point currentPos = alignedWorkArea.get(0);
- List<PathSegment> zigZagLines = generateOptimizedZigZag(workArea, obstacles, bestAngle, width, currentPos);
- finalPath.addAll(zigZagLines);
+ List<PathSegment> zigZag = generateFixedZigZag(workArea, obstacles, bestAngle, width, currentPos);
+ finalPath.addAll(zigZag);
return finalPath;
}
- private static List<PathSegment> generateOptimizedZigZag(List<Point> polygon, List<Obstacle> obstacles, double angle, double width, Point startPoint) {
+ private static List<PathSegment> generateFixedZigZag(List<Point> polygon, List<Obstacle> obstacles, double angle, double width, Point startPoint) {
List<PathSegment> result = new ArrayList<>();
List<Point> rotatedPoly = rotatePolygon(polygon, -angle);
-
double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE;
- for (Point p : rotatedPoly) {
- minY = Math.min(minY, p.y); maxY = Math.max(maxY, p.y);
- }
+ for (Point p : rotatedPoly) { minY = Math.min(minY, p.y); maxY = Math.max(maxY, p.y); }
Point currentPos = startPoint;
boolean leftToRight = true;
- for (double y = minY + width; y < maxY - width / 2; y += width) {
- List<Double> intersections = getXIntersections(rotatedPoly, y);
- if (intersections.size() < 2) continue;
- Collections.sort(intersections);
-
- double xBoundaryMin = intersections.get(0);
- double xBoundaryMax = intersections.get(intersections.size() - 1);
+ for (double y = minY + width; y < maxY - width/2; y += width) {
+ List<Double> polyInts = getXIntersections(rotatedPoly, y);
+ if (polyInts.size() < 2) continue;
+ Collections.sort(polyInts);
+ double xMin = polyInts.get(0), xMax = polyInts.get(polyInts.size() - 1);
- // 鏀堕泦褰撳墠琛屾墍鏈夐殰纰嶇墿浜ょ偣骞惰繘琛岃鍓�
- List<Double> splitPoints = new ArrayList<>();
- splitPoints.add(xBoundaryMin);
+ // 鏀堕泦鎵�鏈夊垎鍓茬偣锛堣竟鐣� + 闅滅鐗╀氦鐐癸級
+ List<Double> splits = new ArrayList<>();
+ splits.add(xMin); splits.add(xMax);
for (Obstacle obs : obstacles) {
- List<Double> obsX = obs.getIntersectionsX(y, angle);
- for (double ox : obsX) {
- if (ox > xBoundaryMin && ox < xBoundaryMax) splitPoints.add(ox);
+ for (double ox : obs.getIntersectionsX(y, angle)) {
+ if (ox > xMin + EPSILON && ox < xMax - EPSILON) splits.add(ox);
}
}
- Collections.sort(splitPoints);
+ Collections.sort(splits);
- // 鏋勫缓鏈夋晥娈�
- List<LineRange> validRanges = new ArrayList<>();
- for (int i = 0; i < splitPoints.size() - 1; i++) {
- double midX = (splitPoints.get(i) + splitPoints.get(i + 1)) / 2.0;
- Point midPoint = rotatePoint(new Point(midX, y), angle);
-
- boolean insideAnyObstacle = false;
- for (Obstacle obs : obstacles) {
- if (obs.isInside(midPoint)) {
- insideAnyObstacle = true;
- break;
- }
- }
- if (!insideAnyObstacle) {
- validRanges.add(new LineRange(splitPoints.get(i), splitPoints.get(i+1)));
+ // 鏋勫缓鏈鍊欓�夋
+ List<Double[]> rowSegments = new ArrayList<>();
+ for (int i = 0; i < splits.size() - 1; i++) {
+ double s = splits.get(i), e = splits.get(i+1);
+ Point mid = rotatePoint(new Point((s + e) / 2.0, y), angle);
+ if (!isPointInAnyObstacle(mid, obstacles)) {
+ rowSegments.add(new Double[]{s, e});
}
}
- // 鏍规嵁褰撳墠鏈濆悜鎺掑簭鏈夋晥娈�
+ // 鏍规嵁褰撳墠S鍨嬫柟鍚戞帓搴�
if (!leftToRight) {
- Collections.reverse(validRanges);
- for (LineRange range : validRanges) {
- double temp = range.start;
- range.start = range.end;
- range.end = temp;
- }
+ Collections.reverse(rowSegments);
+ for (Double[] seg : rowSegments) { double t = seg[0]; seg[0] = seg[1]; seg[1] = t; }
}
- // 杩炴帴璺緞
- for (LineRange range : validRanges) {
- Point pStart = rotatePoint(new Point(range.start, y), angle);
- Point pEnd = rotatePoint(new Point(range.end, y), angle);
+ // 鎵ц杩炴帴锛氬己鍒舵鏌� currentPos 鍒版瘡涓�娈佃捣鐐圭殑璺濈
+ for (Double[] seg : rowSegments) {
+ Point p1 = rotatePoint(new Point(seg[0], y), angle);
+ Point p2 = rotatePoint(new Point(seg[1], y), angle);
- if (Math.hypot(currentPos.x - pStart.x, currentPos.y - pStart.y) > 0.01) {
- result.add(new PathSegment(currentPos, pStart, false));
+ // 鏍稿績淇锛氭棤璁哄杩戯紝鍙涓嶆槸鍚屼竴鐐癸紝灏卞缓绔嬭櫄绾胯繛鎺ワ紝纭繚璺緞娴佽浆
+ if (dist(currentPos, p1) > 0.001) {
+ result.add(new PathSegment(currentPos, p1, false));
}
- result.add(new PathSegment(pStart, pEnd, true));
- currentPos = pEnd;
+ result.add(new PathSegment(p1, p2, true));
+ currentPos = p2;
}
leftToRight = !leftToRight;
}
return result;
}
- private static class LineRange {
- double start, end;
- LineRange(double s, double e) { this.start = s; this.end = e; }
+ private static boolean isPointInAnyObstacle(Point p, List<Obstacle> obstacles) {
+ for (Obstacle obs : obstacles) if (obs.isInside(p)) return true;
+ return false;
}
- // --- 闅滅鐗╄В鏋愪笌澶氳竟褰㈠鎵� ---
+ private static double dist(Point p1, Point p2) {
+ return Math.hypot(p1.x - p2.x, p1.y - p2.y);
+ }
+
+ // --- 杈呭姪宸ュ叿 (瑙f瀽涓庡彉鎹�) ---
private static List<Obstacle> parseObstacles(String obsStr, double margin) {
List<Obstacle> list = new ArrayList<>();
- if (obsStr == null || obsStr.trim().isEmpty()) return list;
-
+ if (obsStr == null || obsStr.isEmpty()) return list;
for (String part : obsStr.split("\\$")) {
List<Point> pts = parseCoords(part);
if (pts.size() == 2) {
- double r = Math.hypot(pts.get(0).x - pts.get(1).x, pts.get(0).y - pts.get(1).y);
+ double r = dist(pts.get(0), pts.get(1));
list.add(new CircleObstacle(pts.get(0), r + margin));
} else if (pts.size() > 2) {
ensureCCW(pts);
@@ -220,39 +196,26 @@
}
private static List<Point> expandPolygon(List<Point> poly, double margin) {
- List<Point> result = new ArrayList<>();
+ List<Point> res = new ArrayList<>();
int n = poly.size();
for (int i = 0; i < n; i++) {
- Point pPrev = poly.get((i - 1 + n) % n);
- Point pCurr = poly.get(i);
- Point pNext = poly.get((i + 1) % n);
-
- double d1x = pCurr.x - pPrev.x, d1y = pCurr.y - pPrev.y;
- double l1 = Math.hypot(d1x, d1y);
- double d2x = pNext.x - pCurr.x, d2y = pNext.y - pCurr.y;
- double l2 = Math.hypot(d2x, d2y);
-
- // 璁$畻澶栨硶绾�
+ Point p1 = poly.get((i - 1 + n) % n), p2 = poly.get(i), p3 = poly.get((i + 1) % n);
+ double d1x = p2.x - p1.x, d1y = p2.y - p1.y;
+ double d2x = p3.x - p2.x, d2y = p3.y - p2.y;
+ double l1 = Math.hypot(d1x, d1y), l2 = Math.hypot(d2x, d2y);
double n1x = d1y / l1, n1y = -d1x / l1;
double n2x = d2y / l2, n2y = -d2x / l2;
-
double bx = n1x + n2x, by = n1y + n2y;
double bLen = Math.hypot(bx, by);
if (bLen < EPSILON) { bx = n1x; by = n1y; } else { bx /= bLen; by /= bLen; }
-
- double cosHalf = n1x * bx + n1y * by;
- double d = margin / Math.max(cosHalf, 0.1);
- // 闄愬埗鏈�澶у鎵╋紝闃叉灏栬鐣稿彉
- d = Math.min(d, margin * 3);
- result.add(new Point(pCurr.x + bx * d, pCurr.y + by * d));
+ double d = margin / Math.max(n1x * bx + n1y * by, 0.1);
+ res.add(new Point(p2.x + bx * Math.min(d, margin * 2), p2.y + by * Math.min(d, margin * 2)));
}
- return result;
+ return res;
}
- // --- 鍩虹宸ュ叿绫绘柟娉� ---
private static List<Point> parseCoords(String s) {
List<Point> list = new ArrayList<>();
- if(s == null || s.isEmpty()) return list;
for (String p : s.split(";")) {
String[] xy = p.split(",");
if (xy.length >= 2) list.add(new Point(Double.parseDouble(xy[0]), Double.parseDouble(xy[1])));
@@ -269,55 +232,42 @@
if (s > 0) Collections.reverse(poly);
}
- private static List<Point> shrinkPolygon(List<Point> polygon, double margin) {
- List<Point> result = new ArrayList<>();
- int n = polygon.size();
+ private static List<Point> shrinkPolygon(List<Point> poly, double margin) {
+ List<Point> res = new ArrayList<>();
+ int n = poly.size();
for (int i = 0; i < n; i++) {
- Point pPrev = polygon.get((i - 1 + n) % n);
- Point pCurr = polygon.get(i);
- Point pNext = polygon.get((i + 1) % n);
- double d1x = pCurr.x - pPrev.x, d1y = pCurr.y - pPrev.y;
- double l1 = Math.hypot(d1x, d1y);
- double d2x = pNext.x - pCurr.x, d2y = pNext.y - pCurr.y;
- double l2 = Math.hypot(d2x, d2y);
+ Point p1 = poly.get((i - 1 + n) % n), p2 = poly.get(i), p3 = poly.get((i + 1) % n);
+ double d1x = p2.x - p1.x, d1y = p2.y - p1.y;
+ double d2x = p3.x - p2.x, d2y = p3.y - p2.y;
+ double l1 = Math.hypot(d1x, d1y), l2 = Math.hypot(d2x, d2y);
double n1x = -d1y / l1, n1y = d1x / l1;
double n2x = -d2y / l2, n2y = d2x / l2;
double bx = n1x + n2x, by = n1y + n2y;
double bLen = Math.hypot(bx, by);
if (bLen < EPSILON) { bx = n1x; by = n1y; } else { bx /= bLen; by /= bLen; }
- double cosHalf = n1x * bx + n1y * by;
- double d = margin / Math.max(cosHalf, 0.1);
- result.add(new Point(pCurr.x + bx * d, pCurr.y + by * d));
+ double d = margin / Math.max(n1x * bx + n1y * by, 0.1);
+ res.add(new Point(p2.x + bx * d, p2.y + by * d));
}
- return result;
+ return res;
}
- private static double findOptimalScanAngle(List<Point> polygon) {
+ private static double findOptimalScanAngle(List<Point> poly) {
double minH = Double.MAX_VALUE, bestA = 0;
- for (int i = 0; i < polygon.size(); i++) {
- Point p1 = polygon.get(i), p2 = polygon.get((i + 1) % polygon.size());
- double angle = Math.atan2(p2.y - p1.y, p2.x - p1.x);
- double h = calculatePolygonHeightAtAngle(polygon, angle);
- if (h < minH) { minH = h; bestA = angle; }
+ for (int i = 0; i < poly.size(); i++) {
+ Point p1 = poly.get(i), p2 = poly.get((i + 1) % poly.size());
+ double a = Math.atan2(p2.y - p1.y, p2.x - p1.x);
+ double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE;
+ double s = Math.sin(-a), c = Math.cos(-a);
+ for (Point p : poly) { double ry = p.x * s + p.y * c; minY = Math.min(minY, ry); maxY = Math.max(maxY, ry); }
+ if (maxY - minY < minH) { minH = maxY - minY; bestA = a; }
}
return bestA;
}
- private static double calculatePolygonHeightAtAngle(List<Point> poly, double angle) {
- double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE;
- double sin = Math.sin(-angle), cos = Math.cos(-angle);
- for (Point p : poly) {
- double ry = p.x * sin + p.y * cos;
- minY = Math.min(minY, ry); maxY = Math.max(maxY, ry);
- }
- return maxY - minY;
- }
-
private static List<Double> getXIntersections(List<Point> rotatedPoly, double y) {
List<Double> xInts = new ArrayList<>();
- int n = rotatedPoly.size();
- for (int i = 0; i < n; i++) {
- Point p1 = rotatedPoly.get(i), p2 = rotatedPoly.get((i + 1) % n);
+ for (int i = 0; i < rotatedPoly.size(); i++) {
+ Point p1 = rotatedPoly.get(i), p2 = rotatedPoly.get((i + 1) % rotatedPoly.size());
if ((p1.y <= y && p2.y > y) || (p2.y <= y && p1.y > y)) {
xInts.add(p1.x + (y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y));
}
@@ -325,36 +275,35 @@
return xInts;
}
- private static Point getFirstScanStartPoint(List<Point> polygon, double angle, double width) {
- List<Point> rotated = rotatePolygon(polygon, -angle);
+ private static Point getFirstScanStartPoint(List<Point> poly, double angle, double width) {
+ List<Point> rot = rotatePolygon(poly, -angle);
double minY = Double.MAX_VALUE;
- for (Point p : rotated) minY = Math.min(minY, p.y);
- double startY = minY + width + EPSILON;
- List<Double> xInts = getXIntersections(rotated, startY);
- if (xInts.isEmpty()) return polygon.get(0);
- Collections.sort(xInts);
- return rotatePoint(new Point(xInts.get(0), startY), angle);
+ for (Point p : rot) minY = Math.min(minY, p.y);
+ double sy = minY + width + EPSILON;
+ List<Double> x = getXIntersections(rot, sy);
+ Collections.sort(x);
+ return rotatePoint(new Point(x.isEmpty() ? 0 : x.get(0), sy), angle);
}
- private static List<Point> alignBoundaryToStart(List<Point> polygon, Point target) {
- int bestIdx = 0; double minDist = Double.MAX_VALUE;
- for (int i = 0; i < polygon.size(); i++) {
- double d = Math.hypot(polygon.get(i).x - target.x, polygon.get(i).y - target.y);
- if (d < minDist) { minDist = d; bestIdx = i; }
+ private static List<Point> alignBoundaryToStart(List<Point> poly, Point target) {
+ int idx = 0; double minD = Double.MAX_VALUE;
+ for (int i = 0; i < poly.size(); i++) {
+ double d = dist(poly.get(i), target);
+ if (d < minD) { minD = d; idx = i; }
}
- List<Point> aligned = new ArrayList<>();
- for (int i = 0; i < polygon.size(); i++) aligned.add(polygon.get((bestIdx + i) % polygon.size()));
- return aligned;
+ List<Point> res = new ArrayList<>();
+ for (int i = 0; i < poly.size(); i++) res.add(poly.get((idx + i) % poly.size()));
+ return res;
}
- private static Point rotatePoint(Point p, double angle) {
- double c = Math.cos(angle), s = Math.sin(angle);
+ private static Point rotatePoint(Point p, double a) {
+ double c = Math.cos(a), s = Math.sin(a);
return new Point(p.x * c - p.y * s, p.x * s + p.y * c);
}
- private static List<Point> rotatePolygon(List<Point> poly, double angle) {
+ private static List<Point> rotatePolygon(List<Point> poly, double a) {
List<Point> res = new ArrayList<>();
- for (Point p : poly) res.add(rotatePoint(p, angle));
+ for (Point p : poly) res.add(rotatePoint(p, a));
return res;
}
}
\ No newline at end of file
--
Gitblit v1.10.0