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;
|
}
|
}
|