【问题标题】:Order orthogonal polygon python订购正交多边形python
【发布时间】:2018-09-13 03:49:03
【问题描述】:

如何排序正交多边形点列表?

例如,我有一个正交多边形点列表

data = [(2, 0), (5, 0), (5, 7), (4, 7), (4, 5), (3, 5),(3, 3), (2, 3), (2, 2), (3, 2), (3, 7), (2, 7)]

不按顺序。 我想以这样的逆时针方式订购它:

out = [(2,0),(5,0),(5,7),(4,7),(4,5),(3,5),(3,7),(2,7),(2,3),(3,3),(3,2),(2,2)]

我已经尝试使用deflate _hull,但它不正确。 有没有什么算法可以解决这个问题?

我明白了:

但预期:

【问题讨论】:

  • 你如何决定哪一点是起点?它是任何给定列表中的第一个点吗?
  • 第一个点将是左下角,
  • 这似乎定义不足:(4, 5), (3, 5), (3, 7) 是右转,(3, 3) 可用于左转...(3, 5), (3, 7), (2, 7) 是左转,(3, 3) 可作为 U 型转弯,并且更近...(2, 7), (2, 3), (3, 3) 是一个 L 型转弯,其中(2, 2) 可用作前进,更近。请说明您要查找的船体规则。
  • 如果(1, 1)有一个点,(2, 0)有一个点,x=1以西或y=0以南没有点,左下角是哪一个?
  • @ReblochonMasque 这不是一组正交多边形点。

标签: python polygon computational-geometry


【解决方案1】:

您可以使用以下递归函数:

def sort_ortho_poly(points, current=None, start=None, go_x=True):
    # initialize the starting point at the bottom left, which should have the least sum of x and y
    if not current:
        start = current = min(points, key=sum)
    # if we're going x-wards, v would be the y index (1), h would be the x index (0), and vice versa 
    v, h = go_x, not go_x
    # remove the current point from the list of points so the next recursion would be processing the remaining points
    remaining = points[:]
    remaining.remove(current)
    # if there is no more remaining point
    if not remaining:
        # we've found a path if we are able to connect back to the starting point, or else we don't
        return [current] if start[v] == current[v] else []
    # try each point in the remaining points that goes in the right direction from the current point
    for next in [p for p in remaining if p[v] == current[v]]:
        # recursively find a valid path from the remaining points after flipping the direction
        path = sort_ortho_poly(remaining, next, start, not go_x)
        # if we get a path that does go back to the starting point, we have to make sure the path is valid
        if path:
            # the current edge (e1, e2)
            e1, e2 = current, next
            # make sure e1 is lower than or left of e2
            if e1[h] > e2[h]:
                e1, e2 = e2, e1
            # for each edge (p1, p2) in the path, including the final edge connecting to the starting point
            for p1, p2 in zip(path, path[1:] + [start]):
                # make sure p1 is lower than or left of p2
                if p1[0] == p2[0] and p1[1] > p2[1] or p1[1] == p2[1] and p1[0] > p2[0]:
                    p1, p2 = p2, p1
                # if the edge is in the same line as the current edge
                if p1[v] == p2[v] == e1[v]:
                    # make sure the two edges don't overlap
                    if e1[h] < p1[h] < e2[h] or e1[h] < p2[h] < e2[h] or p1[h] < e1[h] < p2[h] or p1[h] < e2[h] < p2[h]:
                        break
                # if the edge is perpendicular to the current edge, make sure they don't cross over
                elif p1[h] == p2[h] and e1[h] < p1[h] < e2[h] and p1[v] < e1[v] < p2[v]:
                    break
            else:
                # the path is valid! we append the path to the current point and return
                return [current, *path]
    # return empty if it's a dead end
    return []

这样:

data = [(2, 0), (5, 0), (5, 7), (4, 7), (4, 5), (3, 5),(3, 3), (2, 3), (2, 2), (3, 2), (3, 7), (2, 7)]
print(sort_ortho_poly(data))

会输出:

[(2, 0), (5, 0), (5, 7), (4, 7), (4, 5), (3, 5), (3, 7), (2, 7), (2, 3), (3, 3), (3, 2), (2, 2)]

【讨论】:

  • 感谢您的帮助,我会仔细阅读以了解并尝试更多测试用例。
  • 当然。如果您发现任何问题,请告诉我。如果您确实认为它是正确的,您可以将此答案标记为已接受。
  • 我是 python 和堆栈的新手,所以我需要比平时更多的时间来清楚地理解你的缩短代码。如果通过我所有的测试用例,我会标记它。非常感谢代码中的评论。
  • # 如果 p1[0] == p2[0] and p1[1] > p2[1] or p1[1] == p2[1, 请确保 p1 在 p2 的下方或左侧] 和 p1[0] > p2[1]: p1[0]> p2[1] 关心我:我想一定是 p1[0] > p2[0]: 你能解释一下吗
  • 好收获!那肯定是一个错字。感谢您仔细查看我的代码!我已相应地更正了我的答案。
猜你喜欢
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-02
  • 2019-03-18
  • 2012-06-05
  • 2012-06-28
相关资源
最近更新 更多