【问题标题】:How to find if two line segments intersect or not in Java?如何在Java中查找两条线段是否相交?
【发布时间】:2014-11-07 23:16:01
【问题描述】:

我需要实现一个名为 disjointSegments 的方法,如果线段不相交则返回 true,否则返回 false。

这就是我到目前为止所拥有的。应该有 2 个段,ab 和 cd。

public static boolean disjointSegments(Point2D.Double a, Point2D.Double b,
        Point2D.Double c, Point2D.Double d)

这是一个作业,它说我可以使用 delta 方法来计算它,这是一种计算矩阵行列式的方法。

我已经实现了 delta 方法。

public static double delta(Point2D.Double a, Point2D.Double b,
        Point2D.Double c) {
    return (a.getX() * b.getY() * 1) + ( a.getY() * 1 * c.getX()) + (1 * b.getX() * c.getY()) - (1 * b.getY() * c.getX())
            - (a.getX() * 1 * c.getY()) - (a.getX() * b.getY() * 1);
}

那么我怎么知道线段是否不相交?

【问题讨论】:

  • 你能用手做吗?

标签: java algorithm geometry


【解决方案1】:

由于您只需要二维空间中的真/假结果,因此有一种有效的计算方法:

bool segmentsIntersect(Point2D a, Point2D b, Point2D c, Point2D d) {
    float det = (b.x - a.x) * (d.y - c.y) - (d.x - c.x) * (b.y - a.y);
    if (det == 0)
        return false; //Lines are parallel
    float lambda = ((d.y - c.y) * (d.x - a.x) + (c.x - d.x) * (d.y - a.y)) / det;
    float gamma = ((a.y - b.y) * (d.x - a.x) + (b.x - a.x) * (d.y - a.y)) / det;
    return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
}

【讨论】:

    【解决方案2】:

    函数 delta 是 cross product 的实现。这可用于确定点或向量彼此是顺时针还是逆时针。如果ab x cd &gt; 0 两个向量是顺时针的,如果ab x cd &lt; 0 是逆时针的,如果ab x cd = 0 它们是共线的。

    要使用它来确定两个向量相交,您可以执行以下操作:

    假设您有 4 个点:a、b、c、d。然后你需要做4个计算:

    (a - c) x (d - c) < 0
    (b - c) x (d - c) > 0
    

    通过这 2 个计算,您可以确定点 a 是否是逆时针方向,b 是顺时针方向(反之亦然)到向量 cd。如果这成立,则这些点位于向量的不同侧,这就是您需要在它们之间有交集的地方。现在您必须测试 dc 是否相同。

    (d - a) x (b - a) < 0
    (c - a) x (b - a) > 0
    

    如果这也使您的两个向量相交。

    编辑:如果此示例中的所有 4 个计算都为真,则存在向量的交集。对于您的问题中不相交的示例,这是正确的,其中没有点与向量共线。如果您还必须对此进行测试,则需要进行共线测试。

    术语a - c 由两点组成一个向量。

    a - c => ac.x = a.x - c.x, ac.y = a.y - c.y
    

    【讨论】:

    • 那么您是说如果这 4 个计算为真,则两个向量相交,如果 4 个计算之一为假,则向量不相交?说 (a-c),你的意思是点 a 和 c 之间的距离?
    【解决方案3】:

    这是一般情况的解决方案。特殊情况见this-page 9

    public static int orientation(Point p, Point q, Point r) {
        double val = (q.getY() - p.getY()) * (r.getX() - q.getX())
                - (q.getX() - p.getX()) * (r.getY() - q.getY());
    
        if (val == 0.0)
            return 0; // colinear
        return (val > 0) ? 1 : 2; // clock or counterclock wise
    }
    
    public static boolean intersect(Point p1, Point q1, Point p2, Point q2) {
    
        int o1 = orientation(p1, q1, p2);
        int o2 = orientation(p1, q1, q2);
        int o3 = orientation(p2, q2, p1);
        int o4 = orientation(p2, q2, q1);
    
        if (o1 != o2 && o3 != o4)
            return true;
    
        return false;
    }
    
    public static void main(String[] args) {
        Point p1 = new Point(1,1);
        Point q1 = new Point(2,0);
        Point p2 = new Point(1,0);      
        Point q2 = new Point(3,2);      
        System.out.println("intersect: "+intersect(p1, q1, p2, q2));
    }
    

    回答: 相交:真

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-30
      • 2011-10-25
      • 1970-01-01
      • 2011-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多