如何在Java中查找两个线段是否相交?

时间:2014-09-14 07:09:30

标签: java algorithm geometry

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

这就是我现在所拥有的。应该有2个段,ab和cd。

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

这是一个赋值,它说我可以通过使用delta方法来解决它,这是一种计算矩阵行列式的方法。

API

API

我已经实现了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);
}

那我怎么能弄清楚线段是否不相交?

3 个答案:

答案 0 :(得分: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));
}

答案: intersect:true

答案 1 :(得分:1)

函数delta是cross product的实现。这可以用于确定点或向量是否彼此顺时针或逆时针。如果是ab x cd > 0,则两个向量是顺时针方向,如果ab x cd < 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

答案 2 :(得分:0)

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

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);
}
相关问题