You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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可视化工具,可确认飞行路径与禁飞区边明显相交

可能的原因及解决方法

  1. 浮点数精度问题
    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;
}
  1. 禁飞区多边形未闭合
    若禁飞区坐标列表未闭合(最后一个点未回到第一个点),会遗漏最后一条边的检测。修改内层循环逻辑:
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;
    }
}
  1. 坐标系顺序错误
    确认Line2D.Double构造参数的顺序:若误将纬度(Y轴)和经度(X轴)颠倒,会导致线段绘制错误,进而影响相交判断。

内容的提问来源于stack exchange,提问作者user21313191

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 16:37:13