考虑以下交叉线示例:
l1 = ((20,5),(40,20))
l2 = ((20,20),(40,5))
l3 = ((30,30),(30,5)) # vertical line
我开发了以下代码来计算交叉点的 x,y(参见理论细节)
def gradient(l):
"""Returns gradient 'm' of a line"""
m = None
# Ensure that the line is not vertical
if l[0][0] != l[1][0]:
m = (1./(l[0][0]-l[1][0]))*(l[0][1] - l[1][1])
return m
def parallel(l1,l2):
if gradient(l1) != gradient(l2):
return False
return True
def intersect(l):
"""Returns intersect (b) of a line using the equation of
a line in slope and intercepet form (y = mx+b)"""
return l[0][1] - (gradient(l)*l[0][0])
def line_intersection(l1,l2):
"""Returns the intersection point (x,y) of two line segments. Returns False
for parallel lines"""
# Not parallel
if not parallel(l1,l2):
if gradient(l1) is not None and gradient(l2) is not None:
x = (1./(gradient(l1) - gradient(l2))) * (intersect(l2) - intersect(l1))
y = (gradient(l1)*x) + intersect(l1)
else:
if gradient(l1) is None:
x = l1[0][0]
y = (gradient(l2)*x) + intersect(l2)
elif gradient(l2) is None:
x = l2[0][0]
y = (gradient(l1)*x) + intersect(l1)
return (x,y)
else:
return False
示例会话:
>>> line_intersection(l1,l2)
(30.0, 12.5)
>>> line_intersection(l2,l3)
(30, 12.5)
在长度有限的线段的情况下,我希望以一种有效的方式改进我的代码,并且它们实际上可能不会相交。
l1 = ((4,4),(10,10))
l2 = ((11,5),(5,11))
l3 = ((11,5),(9,7))
line_intersection(l1,l2) #valid
(8.0, 8.0)
line_intersection(l1,l3) # they don't cross each other
(8.0, 8.0)
line_intersection(l2,l3) #line parallel
False
我不优雅的解决方案如下。
def crosses(l1,l2):
if not parallel(l1,l2):
x = line_intersection(l1,l2)[0]
xranges = [max(min(l1[0][0],l1[1][0]),min(l2[0][0],l2[1][0])),min(max(l1[0][0],l1[1][0]),max(l2[0][0],l2[1][0]))]
if min(xranges) <= x <= max(xranges):
return True
else:
return False
else:
return False
crosses(l1,l2)
True
crosses(l2,l3)
False
我正在寻找是否可以改进我在 python 中的函数样式