我使用了已经发布的here代码下面是代码:

from __future__ import division

def line(p1, p2):
    A = (p1[1] - p2[1])
    B = (p2[0] - p1[0])
    C = (p1[0]*p2[1] - p2[0]*p1[1])
    return A, B, -C

def intersection(L1, L2):
    D  = L1[0] * L2[1] - L1[1] * L2[0]
    Dx = L1[2] * L2[1] - L1[1] * L2[2]
    Dy = L1[0] * L2[2] - L1[2] * L2[0]
    if D != 0:
        x = Dx / D
        y = Dy / D
        return x,y
    else:
        return False

# Usage
L1 = line([0,1], [2,3])
L2 = line([2,3], [0,4])

R = intersection(L1, L2)
if R:
    print "Intersection detected:", R
else:
    print "No single intersection point detected"

它实现了cramer规则(适用于直线;如果为两条给定直线建立的线性方程的行列式为0,则直线不相交)。不过,我遇到的问题是,它还可以检测出交叉点,这是两条直线连续的结果。下面是我使用matplotlib绘制的一个图,它演示了这个问题:
algorithm - 使用Cramer检测两个线段是否相交-LMLPHP
我还有一个Triangle类,它包含3个Line对象,它进一步说明了这个问题,因为该类还有自己的intersect(...)函数,它接受另一个三角形,并检查两个三角形的哪些边相交,以及在哪里:
algorithm - 使用Cramer检测两个线段是否相交-LMLPHP
我想使用链接中的算法检测线段相交。以上线段没有交点。我该怎么做?
我有两个类——PointLine——它们用于以更可读的方式处理这些几何元素我维护了上述脚本并将其包装起来(请参见Line.intersect(...)):
class Point:
  def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

  # Override __add__, __sub__ etc. to allow arithmetic operations with Point objects
  # ...

class Line:
  def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2
  # ...
  def intersect(self, l):
        def line(p1, p2):
            A = (p1.y - p2.y)
            B = (p2.x - p1.x)
            C = (p1.x*p2.y - p2.x*p1.y)
            return A, B, -C

        L1 = line(self.p1, self.p2)
        L2 = line(l.p1, l.p2)

        D  = L1[0]*L2[1] - L1[1]*L2[0]
        Dx = L1[2]*L2[1] - L1[1]*L2[2]
        Dy = L1[0]*L2[2] - L1[2]*L2[0]

        if D != 0:
            x = Dx / D
            y = Dy / D
            p = Point(x, y)
            return True, p

        return False, None

#Usage
l1 = Line(Point(0, 0), Point(10, 4))
l2 = Line(Point(-4, -3), Point(-4, 10))

res, p = l1.intersect(l2)
if not res:
    print('Lines don\'t intersect')
else:
    print('Lines intersect at [%f, %f]' % (p.x, p.y))

我也在寻找一个最佳的解决方案(在尽可能少的内存占用的低成本操作中)。
一种可能的解决方案是通过使用欧几里德距离来确定生成的交点(不是两个线段的一部分)是否位于两个线段上。如果不是,则交集是一条或两条直线连续的结果,应视为无效然而,这是一个代价高昂的操作,还涉及到将所有交叉点(无论该点是否是两个线段的一部分)都考虑在内。
更新:我以为我已经解决了问题,但唉!下面有个问题。在仔细看了这些评论之后,我看到了@JerryCoffin所做的一个评论,他指出了一个可能重复的this post
def intersect(self, l, contious=False):
        # Before anything else check if lines have a mutual abcisses
        interval_1 = [min(self.p1.x, self.p2.x), max(self.p1.x, self.p2.x)]
        interval_2 = [min(l.p1.x, l.p2.x), max(l.p1.x, l.p2.x)]
        interval = [
            min(interval_1[1], interval_2[1]),
            max(interval_1[0], interval_2[0])
        ]

        if interval_1[1] < interval_2[0]:
            print('No mutual abcisses!')
            return False, None

        # Try to compute interception
        def line(p1, p2):
            A = (p1.y - p2.y)
            B = (p2.x - p1.x)
            C = (p1.x*p2.y - p2.x*p1.y)
            return A, B, -C

        L1 = line(self.p1, self.p2)
        L2 = line(l.p1, l.p2)

        D  = L1[0]*L2[1] - L1[1]*L2[0]
        Dx = L1[2]*L2[1] - L1[1]*L2[2]
        Dy = L1[0]*L2[2] - L1[2]*L2[0]

        if D != 0:
            x = Dx / D
            y = Dy / D
            p = Point(x, y)
            if contiuous: # continuous parameter allows switching between line and line segment interception
                return True, p
            else:
                if p.x < interval[1] or p.x > interval[0]:
                    print('Intersection out of bound')
                    return False, None
                else:
                    return True, p
        else:
            print('Not intersecting')
            return False, None

结果是:
algorithm - 使用Cramer检测两个线段是否相交-LMLPHP
看起来很好,正是我想要的不过,我添加了一条线(坐标或多或少是随机的,但对我来说很容易检查绘图),即Line(Point(-4, 12), Point(12, -4))。想象一下当我再次得到一个假阳性时我的惊讶:
algorithm - 使用Cramer检测两个线段是否相交-LMLPHP
如您所见,在我的线段开始处的左上角检测到一个交点。它确实与垂直线的延续相交,但与实际线段不相交。两条线段具有相同的x而其中一条是垂直的,这似乎是一个问题。所以我还是不知道怎么解决这个问题。

最佳答案

好吧,我们需要学习如何阅读……解决办法实际上是在@JerryCoffin提出的一个重复建议的评论中,即here

def intersect(self, l, contious=False):
        # Before anything else check if lines have a mutual abcisses
        interval_1 = [min(self.p1.x, self.p2.x), max(self.p1.x, self.p2.x)]
        interval_2 = [min(l.p1.x, l.p2.x), max(l.p1.x, l.p2.x)]
        interval = [
            min(interval_1[1], interval_2[1]),
            max(interval_1[0], interval_2[0])
        ]

        if interval_1[1] < interval_2[0]:
            print('No mutual abcisses!')
            return False, None

        # Try to compute interception
        def line(p1, p2):
            A = (p1.y - p2.y)
            B = (p2.x - p1.x)
            C = (p1.x*p2.y - p2.x*p1.y)
            return A, B, -C

        L1 = line(self.p1, self.p2)
        L2 = line(l.p1, l.p2)

        D  = L1[0]*L2[1] - L1[1]*L2[0]
        Dx = L1[2]*L2[1] - L1[1]*L2[2]
        Dy = L1[0]*L2[2] - L1[2]*L2[0]

        if D != 0:
            x = Dx / D
            y = Dy / D
            p = Point(x, y)
            if contiuous: # continuous parameter allows switching between line and line segment interception
                return True, p
            else:
                if p.x < interval[1] or p.x > interval[0]:
                    print('Intersection out of bound')
                    return False, None
                else:
                    return True, p
        else:
            print('Not intersecting')
            return False, None

结果是:
algorithm - 使用Cramer检测两个线段是否相交-LMLPHP

关于algorithm - 使用Cramer检测两个线段是否相交,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39394830/

10-12 01:29