洪水填充三维多边形

时间:2011-07-07 19:42:55

标签: c++ math polygon computational-geometry flood-fill

这是给你的问题;)

我有一个填充1和0的三维数组。 1代表3维复杂多边形(不是简单的多边形)。只有多边形的边界值为1,内部填充0。现在问题在于:

我需要一个快速算法来用1填充这些多边形。阵列的尺寸通常约为。 512x512x100。

提前致谢!

以下是2d中的示例:

0000111110000
0000100010000
0000100010000
0000111110000

应该导致

0000111110000
0000111110000
0000111110000
0000111110000


这是@Mikolas算法的正确三维解决方案吗?

    void scan_polygon(int frames, int rows, int cols, char data[][][], char result[][][]){
for(int f=0; f < frames; ++f)
for(int r=0; r<rows; ++r)
for(int s = 0, c=0; c<cols-1; ++c)
{
    s ^= s ? ( data[f][r][c] && !data[f][r][c+1]) :
             (!data[f][r][c] &&  data[f][r][c-1]);

    result[f][r][c] = s;
}

for(int f=0; f < frames; ++f)
for(int c=0; c<cols; ++c)
for(int s = 0, r=0; r<rows-1; ++r)
{
    s ^= s ? ( data[f][r][c] && !data[f][r+1][c]) :
             (!data[f][r][c] &&  data[f][r-1][c]);

    result[f][r][c] &= s;
}

}

致以最诚挚的问候,

STEF

2 个答案:

答案 0 :(得分:3)

如果您假设多边形是多方形的,则可以在单个for循环中执行此操作。只需从左上​​角开始,并在越过边缘时跟踪奇偶校验。

一个简单的2D版本(添加了转置案例):

void scan_polygon(int rows, int cols, char** data, char** result)
{
    for(int r=0; r<rows; ++r)
    for(int s = 0, c=0; c<cols-1; ++c)
    {
        s ^= s ? ( data[r][c] && !data[r][c+1]) :
                 (!data[r][c] &&  data[r][c-1]);

        result[r][c] = s;
    }


    for(int c=0; c<cols; ++c)
    for(int s = 0, r=0; r<rows-1; ++r)
    {
        s ^= s ? ( data[r][c] && !data[r+1][c]) :
                 (!data[r][c] &&  data[r-1][c]);

        result[r][c] &= s;
    }
}

如果你有一个悬垂的像素或边沿着扫描线伸出,那么这可能会破坏,例如:

00000000000000000000        
00000000*11111111111   <--- Whoops!
000000*111*000000000
00000*11111*00000000

要解决此问题,您只需在转置数组上重复此过程,然后将所有结果重复在一起。 Sud等人使用类似的方法来对GPU上的网格进行体素化。它并不完美,因为你可以有多个非流形顶点的配置,其中它们的噪声锥相交,但如果你能保证不会发生(或者如果它只发生很少),它就是其中之一我知道最简单的方法可以获得快速的结果。

编辑:修改后的解决方案,展示如何在完成迭代后将数组重新组合在一起。

答案 1 :(得分:2)

我认为在这种情况下可以使用标准的填充方法:

active_cells = [seed]
while active_cells:
    new_active_cells = []
    for cell in active_cells:
        for nh in neighbor(cell):
            if not filled(nh):
                fill(nh)
                new_active_cells.append(nh)
    active_cells = new_active_cells

如果您不确定内部或外部是否已连接(因此无法找到单个“种子”),那么您可以做的是迭代所有单元格,并且一旦找到零点的单元格然后你可以调用上面的floodfill代码来计算连接的组件。对于发现为零的其他单元格重复它,您将最终得到面所在的所有连接区域。

当然,要使上述代码正常工作,就要求所选连接的面很紧。