这是给你的问题;)
我有一个填充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
答案 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代码来计算连接的组件。对于发现为零的其他单元格重复它,您将最终得到面所在的所有连接区域。
当然,要使上述代码正常工作,就要求所选连接的面很紧。