【问题标题】:Creating a polygon shape from a 2d tile array从 2d 平铺阵列创建多边形形状
【发布时间】:2009-10-05 18:52:23
【问题描述】:

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

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

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

编辑:这一切都已完成,以便我可以获取形状并将它们碰撞在一起。

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

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

【问题讨论】:

  • 这听起来像是家庭作业。是吗,你试过什么?我建议先发现相反的算法。给自己一个简单的形状,然后决定哪些坐标会用瓷砖覆盖形状。
  • 不是作业,基本上它是一种使用数组创建形状然后将它们碰撞在一起的方法,如果我理解正确,我需要创建的形状多边形来使用分离轴定理。我尝试了各种方法来循环数组的边缘,但是它错过了边缘并且非常混乱。

标签: algorithm arrays 2d polygon


【解决方案1】:

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

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

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

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

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

  1 0        0 1
  0 1        1 0

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

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

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

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

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

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

真正有趣的是一些矢量图形程序已经做了一段时间的更智能的跟踪,您可以在其中获得对角线、曲线等。

【讨论】:

    【解决方案2】:

    您必须阐明您想要的结果。类似于以下内容

    ██  ██
      ██
    ██  ██
    

    给定

    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
    
    ...
    

    【讨论】:

    • 所有的都将通过上/下/左/右而不是对角线连接。有没有一种特定的方法可以将所有这些四边形组合成一个大多边形?连续的边被组合在一起的地方等等。
    • 所以数组描述了一个连接的多边形,你想要一个连接的多边形作为输出,对吧?它可能有洞吗?
    • 数组描述了一个连通的多边形。孔将是一个奖励,但在项目的这个早期阶段它不需要找到它们。
    • 所以基本上你想通过确定位图中直线的替代物来将原则上位图的内容转换为一组矢量?
    • 是的,我想是的,我没想过这样说。所以每个向量都是一个顶点,每个向量都以某种方式连接到另外两个向量,这样也可以找到人脸?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 2022-06-10
    • 2015-05-19
    • 2015-08-02
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多