/* this is very unefficient and stack intensive recursive algorithm */ void floodFill(int x, int y, int z, int level) { if (level > MAXLEVEL) return; level++; if (x <= 0 || y <= 0 || z <= 0 || x >= nx1 || y >= ny1 || z >= nz1) { // we don't test boundary poins return; } if (mask.get(x, y, z) != 0) { // voxel already was visited return; } if (!compareState(grid, x, y, z, state)) // different material return; // voxel of our material - add it and check 6 heighbors if (m_component != null) m_component.add(x, y, z); updateBounds(x, y, z); m_volume++; mask.set(x, y, z, 1); floodFill(x + 1, y, z, level); floodFill(x - 1, y, z, level); floodFill(x, y + 1, z, level); floodFill(x, y - 1, z, level); floodFill(x, y, z + 1, level); floodFill(x, y, z - 1, level); }
/** similar to recursive fill, but uses no system stack */ void floodFillQue(int start[]) { // int start_state = grid.getState(start[0], start[1], start[2] ); LinkedList<int[]> que = new LinkedList<int[]>(); que.add(start); mask.set(start[0], start[1], start[2], 1); while (!que.isEmpty()) { int vc[] = que.remove(); int i = vc[0]; int j = vc[1]; int k = vc[2]; if (compareState(grid, i, j, k, state)) { if (m_component != null) m_component.add(i, j, k); updateBounds(i, j, k); m_volume++; // test adjacent voxels for (int n1 = -1; n1 < 2; n1++) { for (int n2 = -1; n2 < 2; n2++) { for (int n3 = -1; n3 < 2; n3++) { if (n1 == 0 && n2 == 0 && n3 == 0) continue; int ni = i + n1; int nj = j + n2; int nk = k + n3; if (mask.get(ni, nj, nk) == 0) { if (!compareState(grid, ni, nj, nk, state)) continue; que.offer(new int[] {ni, nj, nk}); mask.set(ni, nj, nk, 1); // printf("que: %d (%d,%d,%d)\n",que.size(),ni,nj,nk); } } } } } } }
/** fills region using analog of scan line algorithm */ boolean fillScanLineStack(int start[]) { StackInt3 stack = new StackInt3(100); int pnt[] = new int[3]; // point to pop from stack boolean spanxLeft, spanxRight, spanzLeft, spanzRight; int x = start[0], y = start[1], z = start[2]; stack.push(x, y, z); while (stack.pop(pnt)) { x = pnt[0]; y = pnt[1]; z = pnt[2]; if (mask.get(x, y, z) != 0) { // this line was already visited continue; } int y1 = y; // go down in y as far as possible while (y1 >= 0 && compareState(grid, x, y1, z, state)) { y1--; } y1++; // increment back // printf("scanline [%2d,%2d,%2d]->", x,y1,z); spanxLeft = spanxRight = spanzLeft = spanzRight = false; while ((y1 <= ny1) && compareState(grid, x, y1, z, state)) { // fill one scan line // mark voxel visited mask.set(x, y1, z, 1); if (m_component != null) m_component.add(x, y1, z); updateBounds(x, y1, z); m_volume++; // check x-direction if (!spanxLeft && (x > 0) && (mask.get(x - 1, y1, z) == 0) && compareState(grid, x - 1, y1, z, state)) { // start of potential new span if (!stack.push(x - 1, y1, z)) return false; spanxLeft = true; } else if (spanxLeft && (x > 0) && ((mask.get(x - 1, y1, z) != 0) || !compareState(grid, x - 1, y1, z, state))) { // end of potential new span spanxLeft = false; } if (!spanxRight && x < nx1 && (mask.get(x + 1, y1, z) == 0) && compareState(grid, x + 1, y1, z, state)) { // start of potential new span if (!stack.push(x + 1, y1, z)) return false; // stack overflow spanxRight = true; } else if (spanxRight && x < nx1 && ((mask.get(x + 1, y1, z) != 0) || !compareState(grid, x + 1, y1, z, state))) { // end of potential new span spanxRight = false; } // check z direction if (!spanzLeft && (z > 0) && (mask.get(x, y1, z - 1) == 0) && compareState(grid, x, y1, z - 1, state)) { // start of potential new span if (!stack.push(x, y1, z - 1)) return false; spanzLeft = true; } else if (spanzLeft && (z > 0) && ((mask.get(x, y1, z - 1) != 0) || !compareState(grid, x, y1, z - 1, state))) { // end of potential new span spanzLeft = false; } if (!spanzRight && z < nz1 && (mask.get(x, y1, z + 1) == 0) && compareState(grid, x, y1, z + 1, state)) { // start of potential new span if (!stack.push(x, y1, z + 1)) return false; // stack overflow spanzRight = true; } else if (spanzRight && z < nz1 && ((mask.get(x, y1, z + 1) != 0) || !compareState(grid, x, y1, z + 1, state))) { // end of potential new span spanzRight = false; } y1++; } // printf("[%2d,%2d,%2d]\n ", x,y1,z); } // stack.printStat(); return true; } // fillScanLine
/** fills region using analog of scan line algorithm */ boolean fillScanLineQueue(int start[]) { // LinkedList<int[]> que = new LinkedList<int[]>(); // ArrayDeque<int[]> que = new ArrayDeque<int[]>(); QueueInt que = new QueueInt(100000); boolean spanxLeft, spanxRight, spanzLeft, spanzRight; int x = start[0], y = start[1], z = start[2]; int pnt[] = new int[3]; que.offer(x, y, z); while (!que.isEmpty()) { // int pnt[] = que.remove(); que.remove(pnt); x = pnt[0]; y = pnt[1]; z = pnt[2]; if (mask.get(x, y, z) != 0) { // this line was already visited continue; } // printf("new scanline: [%d,%d,%d]\n", x, y, z); // dumpScanLine(x,y,z); int y1 = y; // go down in y as far as possible while (y1 >= 0 && compareState(grid, x, y1, z, state)) { y1--; } y1++; // increment back // printf("scanline [%2d,%2d,%2d]->", x,y1,z); spanxLeft = spanxRight = spanzLeft = spanzRight = false; while ((y1 <= ny1) && compareState(grid, x, y1, z, state)) { // fill one scan line // mark voxel visited mask.set(x, y1, z, 1); if (m_component != null) m_component.add(x, y1, z); updateBounds(x, y1, z); m_volume++; // check x-direction if (!spanxLeft && (x > 0) && (mask.get(x - 1, y1, z) == 0) && compareState(grid, x - 1, y1, z, state)) { // start of potential new span // que.offer(new int[]{x - 1, y1, z}); que.offer(x - 1, y1, z); spanxLeft = true; } else if (spanxLeft && (x > 0) && ((mask.get(x - 1, y1, z) != 0) || !compareState(grid, x - 1, y1, z, state))) { // end of potential new span spanxLeft = false; } if (!spanxRight && x < nx1 && (mask.get(x + 1, y1, z) == 0) && compareState(grid, x + 1, y1, z, state)) { // start of potential new span // que.offer(new int[]{x + 1, y1, z}); que.offer(x + 1, y1, z); spanxRight = true; } else if (spanxRight && x < nx1 && ((mask.get(x + 1, y1, z) != 0) || !compareState(grid, x + 1, y1, z, state))) { // end of potential new span spanxRight = false; } // check z direction if (!spanzLeft && (z > 0) && (mask.get(x, y1, z - 1) == 0) && compareState(grid, x, y1, z - 1, state)) { // start of potential new span // que.offer(new int[]{x, y1, z-1}); que.offer(x, y1, z - 1); spanzLeft = true; } else if (spanzLeft && (z > 0) && ((mask.get(x, y1, z - 1) != 0) || !compareState(grid, x, y1, z - 1, state))) { // end of potential new span spanzLeft = false; } if (!spanzRight && z < nz1 && (mask.get(x, y1, z + 1) == 0) && compareState(grid, x, y1, z + 1, state)) { // start of potential new span // que.offer(new int[]{x, y1, z+1}); que.offer(x, y1, z + 1); spanzRight = true; } else if (spanzRight && z < nz1 && ((mask.get(x, y1, z + 1) != 0) || !compareState(grid, x, y1, z + 1, state))) { // end of potential new span spanzRight = false; } y1++; } // printf("[%2d,%2d,%2d]\n ", x,y1,z); } // que.printStat(); return true; } // fillScanLineQue