在列表中查找线段的集群

时间:2018-02-02 10:25:46

标签: python algorithm math

我有一个以xy坐标表示的线段列表,我试图找到线组,使得组内的所有角度都在20度以内。但我的问题是math.degrees(math.atan2(-0.1,-1))(= -174.29)和math.degrees(math.atan2(0.1,-1))(= 174.29)应该在同一组中产生两个点,但是面值的差异大于20.我想知道我的代码是否应该做我想做的事情并避免180 / -180问题:

import math

endpoints = [((2, 11), (2, 8)), ((11, 3), (2, 5)), ((13, 7), (9, 12)), ((5, 5), (15, 12)), ((15, 4), (8, 1)), ((15, 14), (14, 3)), ((2, 4), (6, 5)), ((1, 13), (13, 11)), ((8, 11), (12, 15)), ((12, 4), (7, 1))]

def find_angle(p1,p2):
    x1 = p1[0]
    y1 = p1[1]
    x2 = p2[0]
    y2 = p2[1]

    dx = max(x2-x1,x1-x2)
    if dx == x2-x1:
        dy = y2-y1
    else:
        dy = y1-y2

    return math.degrees(math.atan2(dy,dx))

endpointsbyangle = sorted([(find_angle(p1,p2), (p1,p2)) for p1, p2 in endpoints], key=lambda x: x[0])

prev = -190
group = []
allgroups = []
for (theta, (p1, p2)) in endpointsbyangle:
    if prev == -190:
        group.append((p1,p2))
        prev = theta
    else:
        if abs(prev - theta) < 20:
            group.append((p1,p2))
        else:
            allgroups.append(group)
            group = [(p1,p2)]
            prev = theta

print dict(enumerate(allgroups))

任何想法都赞赏。

1 个答案:

答案 0 :(得分:1)

一种方法是更换你的线

if abs(prev - theta) < 20 or abs(prev - theta) > 340:

if (abs(prev - theta) < 20
   or abs(prev - theta) > 340
   or abs(prev - theta - 180) < 20):

然后捕获计算出的角度接近360度的情况。

但是,如果我了解你,你还有另一个问题。如果角度ABC正好是5度(例如),并且角度CAB也是5度,那么角度ACB是170度并且将使测试失败。换句话说,&#34;组内的所有角度都不可能在20度以内。一组3分。您还应该允许角度在180度的20度范围内。所以也许你应该使用

{{1}}

这取决于你的要求究竟是什么意思&#34;组内的所有角度都在20度以内。&#34;