我有一个字典,其中包含线段的起点和终点坐标。我想比较字典中任意两个键的所有可能组合,以检查线段是否有交集。我怎么能这样做?
v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)]}
确定是否存在碰撞的功能就像这样
def segment_intersect(line1, line2):
i1 = [min(line1[0][0], line1[1][0]), max(line1[0][0], line1[1][0])]
i2 = [min(line2[0][0], line2[1][0]), max(line2[0][0], line2[1][0])]
ia = [max(i1[0], i2[0]), min(i1[1], i2[1])]
if max(line1[0][0], line1[1][0]) < min(line2[0][0], line2[1][0]):
return False
m1 = (line1[1][1] - line1[0][1]) * 1. / (line1[1][0] - line1[0][0]) * 1.
m2 = (line2[1][1] - line2[0][1]) * 1. / (line2[1][0] - line2[0][0]) * 1.
if m1 == m2:
return False
b1 = line1[0][1] - m1 * line1[0][0]
b2 = line2[0][1] - m2 * line2[0][0]
x1 = (b2 - b1) / (m1 - m2)
if (x1 < max(i1[0], i2[0])) or (x1 > min(i1[1], i2[1])):
return False
return True
答案 0 :(得分:2)
你可以写
comb = ((v[x], v[y]) for x in v for y in v if x < y)
if x < y
部分确保您只获得(1,2)
而不是(2,1)
,这将是相同的而不是(1,1)
,这是没有意义的。
你得到一个带组合的迭代器,你可以写:
for line1, line2 in comb:
segment_intersect(line1, line2)
请注意,如果密钥为1,2,3,则应使用list
而不是dict
。
答案 1 :(得分:2)
您可以为每个元素元素创建嵌套循环。以下示例仅执行此操作并使用绘图测试结果。
import matplotlib.pyplot as plt
v = {1:[(2,3),(10,12)],2:[(22,25),(14,42)],3:[(-8,10),(3,21)],4:[(10,3),(2,12)]}
keys = list(v.keys())
print(keys)
for i in range(len(keys)):
for j in range(i+1,len(keys)):
print(keys[i],keys[j],segment_intersect(v[keys[i]], v[keys[j]]))
plt.plot(*v[keys[i]],label=str(keys[i]))
plt.legend()
plt.show()
,结果是:
[1, 2, 3, 4]
1 2 False
1 3 False
1 4 True
2 3 False
2 4 False
3 4 False
,并且:
答案 2 :(得分:2)
您可以使用标准itertools.combinations
功能生成组合。
例如,
from itertools import combinations
for k1, k2 in combinations(v, 2):
print(k1, k2, segment_intersect(v[k1], v[k2]))
使用itertools.combinations
比使用嵌套for
循环更有效,更易读,特别是如果你想要长度&gt;的组合。 2。