我有一个2D数组,其中只包含布尔值,显示数组中该点是否有图块。这样做如下,假设如果数组[5,6]为真,那么在坐标(5,6)处有一个瓦片。阵列描述的形状是连接的多边形,可能在其内部有孔。
基本上我只需要一个顶点和面的列表来描述数组中的形状。
我已经找了一段时间,找不到解决这个问题的方法,任何帮助都会受到赞赏。
编辑:这一切都已完成,以便我可以获取形状并将它们碰撞在一起。
这个项目正是我正在做的事情,以帮助提高我的编程技能/物理等。
Edit2:感谢您的帮助。基本上我的问题非常类似于将位图图像转换为矢量图像。如果将来有其他人遇到我所做过的同样问题,http://cardhouse.com/computer/vector.htm会很有用。
答案 0 :(得分: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
...
答案 1 :(得分:1)
不要过分关注单个像素。专注于像素的角落 - 四个像素相交的点。这些角落的坐标将像像素的半开坐标一样工作。半开边界在下界是包含的,但在上限处是独占的,因此半开的范围从1到3是{1,2}。
定义一组边 - 两个像素之间的单像素长线(垂直或水平)。然后形成一个邻接图 - 如果它们共享一个点,则两个边相邻。
接下来,识别连接的边集 - 每个点直接或间接连接到彼此的子图。从逻辑上讲,大多数连接的子图应该形成闭环,你应该确保所有的循环都被认为是简单的闭环。
一个问题是位图的边缘。如果您想象您的位图是无限位图的一小部分,其中每个越界像素的值为0,则可能会简化操作。根据该规则在位图边缘包含像素边。这应该确保所有循环都关闭。
另外,考虑那些有四个边界边的像素角 - 即像素图案是......的一个...
1 0 0 1
0 1 1 0
在这些情况下,'1'像素应该被视为单独多边形的一部分(否则你最终会出现缠绕规则的复杂化)。在这些情况下调整邻接规则,这样你基本上会得到两个连接(直角)边缘碰巧碰到一个点,但不被认为是相邻的。它们仍然可以连接,但只能通过其他边缘间接连接。
此外,使用额外的标志数组来识别已在循环中使用的像素边 - 可能一个用于水平边,一个用于垂直边。这样可以更容易地找到所有循环而无需重复评估任何循环 - 您扫描主位图,当您发现相关边缘时,在扫描周围找到整个循环之前检查这些数组。在循环中扫描时,可以在这些数组中设置相关的标志(或循环ID号)。
BTW - 不要认为这些步骤都是文字构建 - 这个数据结构步骤,而是更多的抽象层。关键是要意识到您正在进行graph操作。您甚至可以使用引用位图的适配器,但提供适合某些图算法直接使用的接口,就像它使用专门的图形数据结构一样。要测试特定循环是否为孔,请选择(例如)最左侧的垂直像素边(在循环上)。如果填充了右边的像素,则循环是多边形边界。如果左边的像素被填满,则循环是一个洞。注意 - 在跟踪循环之前,找到第一个像素边缘时,可能是一个很好的测试像素。这可能不是最左边的这样的边缘,但它将是该扫描线中最左边/最上面的边缘。
最后一个问题是简化 - 发现像素边缘一起运行成直线的位置。这可能会被构建到首先识别循环的扫描中,但最好在开始扫描之前找到一个角。完成后,使用while-I-can-continue-tracing-the-direction-loop循环识别每一行 - 但要注意那些两个多边形触及角落的问题。
尝试将所有这些东西结合起来可能听起来像一个复杂的混乱,但诀窍是将问题分成不同的类/功能,例如使用提供底层图层(如位图)的抽象视图的类。不要过分担心调用开销或优化 - 内联和其他编译器优化应该处理它。
真正有趣的是一些矢量图形程序已经做了一段时间的智能跟踪,你可以获得对角线,曲线等。