Java AWT中Line2D.Double intersectsLine方法未按预期工作
Java AWT Line2D.Double intersectsLine() 无法检测到视觉上明显相交的线段
我使用Java AWT的Line2D.Double类时遇到异常情况:调用linePath.intersectsLine(barrier)后,后续的打印日志和标记设置操作完全没有触发。已经通过可视化确认两条线段明显相交,且参数传递无误。
相关代码如下:
var linePath = new Line2D.Double(dronelnglat.longitude, dronelnglat.latitude, nextPos.longitude(), nextPos.latitude()); // 检查飞行路径是否与禁飞区多边形的边相交 for (int i = 0; i < noFlyZones.size(); i++) { var nfzPoly = noFlyZones.get(i); var nfzPoints = nfzPoly.coordinates().get(0); for (int j = 0; j < nfzPoints.size() - 1; j++) { Line2D barrier = new Line2D.Double(nfzPoints.get(j).longitude(), nfzPoints.get(j).latitude(), nfzPoints.get(j + 1).longitude(), nfzPoints.get(j + 1).latitude()); if (linePath.intersectsLine(barrier)) { System.out.println("Surprise me!"); crossNoFlyZone = true; break; } } }
复现步骤:
- 准备飞行路径的GeoJSON坐标文件(flightpath-2023-01-01.json)
- 获取禁飞区的GeoJSON坐标数据
- 将两个文件导入GeoJSON可视化工具,可确认飞行路径与禁飞区边明显相交
可能的原因及解决方法
- 浮点数精度问题
Line2D.intersectsLine()依赖精确浮点数计算,地理坐标(经纬度)的高精度特性可能引发计算误差,导致判断失效。可以改用带误差容忍的自定义相交判断逻辑:
public static boolean linesIntersectWithTolerance(Line2D l1, Line2D l2, double tolerance) { double x1 = l1.getX1(), y1 = l1.getY1(); double x2 = l1.getX2(), y2 = l1.getY2(); double x3 = l2.getX1(), y3 = l2.getY1(); double x4 = l2.getX2(), y4 = l2.getY2(); double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); if (Math.abs(denom) < tolerance) { return isPointOnLineWithTolerance(l1, new Point2D.Double(x3, y3), tolerance) || isPointOnLineWithTolerance(l1, new Point2D.Double(x4, y4), tolerance) || isPointOnLineWithTolerance(l2, new Point2D.Double(x1, y1), tolerance) || isPointOnLineWithTolerance(l2, new Point2D.Double(x2, y2), tolerance); } double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; return ua >= -tolerance && ua <= 1 + tolerance && ub >= -tolerance && ub <= 1 + tolerance; } public static boolean isPointOnLineWithTolerance(Line2D line, Point2D point, double tolerance) { return line.ptSegDist(point) <= tolerance && Math.min(line.getX1(), line.getX2()) - tolerance <= point.getX() && point.getX() <= Math.max(line.getX1(), line.getX2()) + tolerance && Math.min(line.getY1(), line.getY2()) - tolerance <= point.getY() && point.getY() <= Math.max(line.getY1(), line.getY2()) + tolerance; }
替换原判断逻辑:
if (linesIntersectWithTolerance(linePath, barrier, 1e-6)) { System.out.println("Surprise me!"); crossNoFlyZone = true; break; }
- 禁飞区多边形未闭合
若禁飞区坐标列表未闭合(最后一个点未回到第一个点),会遗漏最后一条边的检测。修改内层循环逻辑:
for (int j = 0; j < nfzPoints.size(); j++) { var p1 = nfzPoints.get(j); var p2 = nfzPoints.get((j + 1) % nfzPoints.size()); Line2D barrier = new Line2D.Double(p1.longitude(), p1.latitude(), p2.longitude(), p2.latitude()); if (linesIntersectWithTolerance(linePath, barrier, 1e-6)) { System.out.println("Surprise me!"); crossNoFlyZone = true; break; } }
- 坐标系顺序错误
确认Line2D.Double构造参数的顺序:若误将纬度(Y轴)和经度(X轴)颠倒,会导致线段绘制错误,进而影响相交判断。
内容的提问来源于stack exchange,提问作者user21313191
相关产品推荐
相关产品推荐

