1

我有一个 2D 数组,它只包含布尔值,显示数组中的那个点是否有图块。它的工作原理如下,假设如果 array[5,6] 为真,那么在坐标 (5,6) 处有一个图块。数组描述的形状是一个连接的多边形,里面可能有孔。

基本上我需要的只是一个顶点和面的列表,它们描述了数组中的形状。

我已经寻找了一段时间,找不到解决这个问题的方法,任何帮助将不胜感激。

编辑:这一切都完成了,这样我就可以采取形状并将它们碰撞在一起。

这个项目只是我正在做的事情,以帮助提高我的编程技能/物理等。

Edit2:感谢所有帮助。基本上我的问题与将位图图像转换为矢量图像非常相似。http://cardhouse.com/computer/vector.htm如果将来其他人遇到与我相同的问题,它会很有用。

4

2 回答 2

1

你必须澄清你想要的结果。类似于以下内容

██  ██
  ██
██  ██

给定

1 0 1
0 1 0
1 0 1

作为输入?如果是,这似乎很简单——如果有一个,为什么不为每个数组条目生成一个四边形,否则什么都没有?

您可以使用简单的状态机来解决此问题。当前状态由当前位置 (x,y) 和当前方向组成 - 左 (L)、右 (R)、上 (U) 或下 (D)。“X”是当前位置,有八个邻居可以控制状态变化。

0 1 2
7 X 3
6 5 4

然后只需遵循以下规则 - 在状态 X、Y、D 中检查两个给定字段并相应地更改状态。

X,Y,R,23=00 => X+1,Y,D
X,Y,R,23=01 => X+1,Y,R
X,Y,R,23=10 => X+1,Y,U
X,Y,R,23=11 => X+1,Y,U

X,Y,D,56=00 => X,Y+1,L
X,Y,D,56=01 => X,Y+1,D
X,Y,D,56=10 => X,Y+1,R
X,Y,D,56=11 => X,Y+1,R

...
于 2009-10-05T19:14:11.537 回答
1

不要过分关注单个像素。专注于像素的角落 - 四个像素相交的点。这些角的坐标很像像素的半开坐标。半开边界在下限包含,但在上限不包含,因此从 1 到 3 的半开范围是 {1, 2}。

定义一组边缘 - 两个像素之间的单像素长线(垂直或水平)。然后形成一个邻接图 - 如果两条边共享一个点,则它们是相邻的。

接下来,识别连接的边集——每个点直接或间接地相互连接的子图。从逻辑上讲,大多数连通子图应该形成闭环,并且您应该确保所有环都被认为是简单的闭环。

一个问题是位图的边缘。如果您想象您的位图是无限位图的一小部分,它可能会简化事情,其中​​每个越界像素的值都为 0。根据该规则在位图边缘包括像素边缘。这应该确保所有循环都关闭。

另外,请考虑您有四个边界边缘的那些像素角 - 即像素图案是其中之一...

  1 0        0 1
  0 1        1 0

在这些情况下,“1”像素应被视为单独多边形的一部分(否则您最终会遇到缠绕规则的并发症)。在这些情况下调整邻接规则,以便您基本上得到两个连接的(直角)边,它们碰巧在一点接触,但不被认为是相邻的。它们仍然可以连接,但只能通过其他边缘间接连接。

此外,使用额外的标志数组来识别已在循环中使用的像素边缘 - 可能一个用于水平边缘,一个用于垂直边缘。这应该可以更容易地找到所有循环,而无需重复评估任何循环 - 您扫描主位图,当您发现相关边缘时,您会检查这些数组,然后再扫描以找到整个循环。当您扫描循环时,您在这些数组中设置相关标志(或循环 ID 号)。

顺便说一句 - 不要将这些步骤都视为字面上的构建此数据结构的步骤,而更多的是抽象层。关键是要意识到你正在做操作。您甚至可以使用引用您的位图的适配器,但提供适合某些图形算法直接使用的接口,就好像它使用专门的图形数据结构一样。

要测试特定循环是否是孔,请选择(例如)最左边的垂直像素边缘(在循环上)。如果右侧的像素被填充,则循环是多边形边界。如果左边的像素被填充,则循环是一个洞。注意 - 一个好的测试像素可能是您在跟踪循环之前找到第一个像素边缘时找到的像素。这可能不是最左边的边缘,但它将是该扫描线中最左边/最上面的边缘。

最后一个问题是简化——发现像素边缘一起变成直线的地方。这可能可以内置到首先识别循环的扫描中,但最好在开始正确扫描之前找到一个角落。完成后,使用 while-I-can-continue-tracing-the-same-direction 循环识别每一行 - 但请注意那些两个多边形接触角的问题。

尝试将所有这些东西结合起来可能听起来很复杂,但诀窍是将问题分成不同的类/函数,例如使用提供底层抽象视图的类,例如位图。不要太担心调用开销或优化 - 内联和其他编译器优化应该处理这个问题。

What would be really interesting is the more intelligent tracing that some vector graphics programs have been doing for a while now, where you can get diagonals, curves etc.

于 2009-10-05T22:35:14.093 回答