我已经使用了这里发布的代码。以下是代码:
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
制作的一个图,展示了这个问题:
我还有一个名为Triangle
的类,其中包含3个Line
对象,它进一步展示了这个问题,因为该类还具有自己的intersect(...)
函数,该函数接受另一个三角形并检查两个三角形的哪些边相交以及在哪里:
我想使用链接中的算法检测线段交点。上述线段没有交点。我该怎么做?我有两个类-
Point
和Line
,用于以更可读的方式处理这些几何元素。我已经维护了上面的脚本并将其封装在其中(请参见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
结果为:
结果:
这看起来很不错,正是我想要的。 然而,我添加了一条线(坐标大致随意,但易于在图中检查),即 Line(Point(-4, 12), Point(12, -4))
。当我再次得到单个误报时,可以想象我的惊讶: