【问题标题】:Polygon from a grid of squares正方形网格中的多边形
【发布时间】:2018-11-25 21:00:37
【问题描述】:

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

.

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

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

我在下面的链接中发现了一个类似的问题,但我想详细说明我的案例所特有的算法类型,特别是考虑到我已经存储的关于边缘的数据。我也更喜欢算法来避免计算每个正方形的顶点并运行一堆简单的搜索来消除共享的顶点,因为我觉得这对于我的特定应用程序来说可能在计算上过于昂贵。我只是怀疑必须有更好的方法。

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

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

【问题讨论】:

  • 我完全不明白您在寻找什么。你能发布示例输入和输出吗? (您是在实际图像上操作吗?)
  • 我没有对图像进行操作。我正在对 Vector2Ints 给出的网格位置进行操作。我已经更新了我的问题,所以希望我的问题更清楚。
  • 你有什么样的边组成正方形是什么意思?正方形不总是由四个边组成吗?你的意思是你已经过滤掉了内部边缘?然后你需要做的就是从任意边缘开始沿着轮廓走(继续到与当前边缘的结束顶点具有相同起始顶点的边缘)。
  • @NicoSchertler 我的意思是暴露在周围区域的边缘。例如,在我的示例图像中,右上角的正方形将有一个左上角的枚举。没有暴露边缘的正方形有一个枚举来指定这个,所以是的,你可以说我已经过滤掉了内部边缘。如果只需要沿着大纲走,那么我会很感激能够完成此任务的算法大纲。我曾尝试编写这样的算法,但遇到了一些复杂情况。
  • @NicoSchertler 我应该说我已经过滤掉了一些内部边缘(只是那些根本不暴露在外面的正方形,除了可能在角落里)。我还没有计算出正方形的实际顶点。我的输入只是网格位置,例如 (0, 1)、(0, 2)、(0, 3),它们将在网格中形成一条由三个正方形组成的线。

标签: algorithm polygon graph-algorithm computational-geometry


【解决方案1】:

看到这篇文章正在寻找我的解决方案的替代方案。这是我想出的:

对于单元格:

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

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

  • 顶部:((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 路径算法绘制结果,这很方便。

【讨论】:

  • 嗨,很抱歉在将近一年后发布。该算法如何转换为在 O(N) 时间内运行?
【解决方案2】:

我不确定你的数据结构包含什么,我假设你有一个由某个点(角或中心)的坐标已知的正方形列表。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    • 2022-11-24
    • 1970-01-01
    相关资源
    最近更新 更多