来自正方形网格

时间:2018-06-16 05:50:53

标签: algorithm polygon graph-algorithm computational-geometry

我正在寻找一种算法来找到围绕没有孔的连续方格网格的多边形,如下所示:

Problem Illustration

我已经有了每个网格方块存储有关边缘区域的数据以及它们所组成的周围区域(即顶部,右上角,上下,没有边缘等),所以我是认为算法可以利用这些数据。如果有人可以为这样的算法提供一些伪代码,那也很棒。

算法的输入将是一个数据对象列表,每个数据对象都有一个描述网格位置的Vector2Int(请注意,这些只是网格中的位置,而不是顶点)以及给出边缘类型的Enum。广场与周边地区。输出将是描述周围多边形顶点的Vector2s的有序列表,假设每个网格方块的大小为一个单位。

我在下面的链接中找到了一个类似的问题,但是我想要对我的情况特定的算法类型进行一些详细说明,特别是考虑到我已经存储的关于边缘的数据。我也更喜欢算法避免计算每个正方形的顶点并运行一堆简单的搜索以消除共享的顶点,因为我觉得这对于我的特定应用来说可能计算成本太高。我只是怀疑必须有更好的方法。

Outline (circumference) polygon extraction from geometry constructed from equal squares

编辑:现在我开始认为某种迷宫行走算法可能实际上适合我的情况。我正在研究一种我认为可以解决的解决方案,但是编写起来非常麻烦(涉及对方形边缘和围绕圆周行进的方向的数吨条件检查)并且可能没有它可能的那么快

2 个答案:

答案 0 :(得分:1)

我不确定要了解您的数据结构包含什么,并且我假设您有一个通过某个点(角或中心)的坐标已知的正方形列表。

计算边界框并创建相同大小的二进制位图。除非几何图形真正稀疏,否则位图的面积将与平方数的数量级相同。

对于每个正方形,将相应的像素涂成黑色。然后使用contouring algorithm。要获得正方形的轮廓,您需要设计像素到像素移动与要附加的轮廓片段之间的对应表。

答案 1 :(得分:0)

来此帖子中寻找我的解决方案的替代方案。这是我想出的:

对于一个单元格:

     |             |
---(0, 0)--------(1, 0)---
     |             |
     |             |
     |    R0C0     |
     |             |
     |             |
---(0, 1)--------(1, 1)---
     |             |

将每个单元格的边界计算为一组两个角坐标:

  • 顶部:((c, r), (c, r + 1))
  • 右:((c, r + 1), (c + 1, r + 1))
  • 底部:((c + 1, r + 1), (c + 1, r))
  • 左:((c + 1, r), (c, r))

注意这些是如何顺时针定义的,这很重要

所以对于网格

R0C0 R0C1 R0C2 R0C3
          R1C2 R1C3
     R2C1 R2C2

您将获得以下优势:

R0C0 (top, bottom, left): (0, 0)-(1, 0), (1, 1)-(0, 1), (0, 1)-(0, 0)
R0C1 (top, bottom): (1, 0)-(2, 0), (2, 1)-(1, 1)
R0C2 (top): (2, 0)-(3, 0)
R0C3 (top, right): (3, 0)-(4, 0), (4, 0)-(4, 1)
R1C2 (left): (2, 2)-(2, 1)
R1C3 (right, bottom): (4, 1)-(4, 2), (4, 2)-(3, 2)
R2C1 (top, bottom, left): (1, 2)-(2, 2), (2, 3)-(1, 3), (1, 3)-(1, 2)
R2C2 (right, bottom): (3, 2)-(3, 3), (3, 3)-(2, 3)

现在这是一个问题,如何以一个元素的第一个坐标与其前一个元素的第二个坐标相同的方式对这些元素进行排序。

(0, 0)-(1, 0)          (0, 0)-(1, 0)
(1, 1)-(0, 1)          (1, 0)-(2, 0)
(0, 1)-(0, 0)          (2, 0)-(3, 0)
(1, 0)-(2, 0)          (3, 0)-(4, 0)
(2, 1)-(1, 1)          (4, 0)-(4, 1)
(2, 0)-(3, 0)          (4, 1)-(4, 2)
(3, 0)-(4, 0)          (4, 2)-(3, 2)
(4, 0)-(4, 1)    =>    (3, 2)-(3, 3)
(2, 2)-(2, 1)          (3, 3)-(2, 3)
(4, 1)-(4, 2)          (2, 3)-(1, 3)
(4, 2)-(3, 2)          (1, 3)-(1, 2)
(1, 2)-(2, 2)          (1, 2)-(2, 2)
(2, 3)-(1, 3)          (2, 2)-(2, 1)
(1, 3)-(1, 2)          (2, 1)-(1, 1)
(3, 2)-(3, 3)          (1, 1)-(0, 1)
(3, 3)-(2, 3)          (0, 1)-(0, 0)

现在,让我们仅获取第一个坐标,这是您的多边形:

(0, 0)
(1, 0)
(2, 0)
(3, 0)
(4, 0)
(4, 1)
(4, 2)
(3, 2)
(3, 3)
(2, 3)
(1, 3)
(1, 2)
(2, 2)
(2, 1)
(1, 1)
(0, 1)

您现在可以通过消除一行上的连续点(即,在三个具有相同x或y坐标的连续点中,消除中间的点)来简化它

(0, 0)
(4, 0)
(4, 2)
(3, 2)
(3, 3)
(1, 3)
(1, 2)
(2, 2)
(2, 1)
(0, 1)

现在这是您按顺时针顺序排列的多边形:

(0, 0)--------------------------------------(4, 0)
  |                                           |
  |                                           |
(0, 1)----------------(2, 1)                  |
                        |                     |
                        |                     |
           (1, 2)-----(2, 2)     (3, 2)-----(4, 2)
             |                     |
             |                     |
           (1, 3)----------------(3, 3)

此算法也可以扩展为处理孔。在订购边缘时,您只需要考虑多个多边形。方便地,将沿逆时针方向定义孔,如果要使用svg路径或其他允许多边形重叠的d2路径算法绘制结果,这将非常方便。