static void skeletonize_pass(DenseGrid2i grid, DenseGrid2i tmp, int iter)
        {
            int ni = grid.ni, nj = grid.nj;

            for (int i = 1; i < ni - 1; i++) {
                for (int j = 1; j < nj - 1; j++) {
                    int p2 = grid[i - 1, j];
                    int p3 = grid[i - 1, j + 1];
                    int p4 = grid[i, j + 1];
                    int p5 = grid[i + 1, j + 1];
                    int p6 = grid[i + 1, j];
                    int p7 = grid[i + 1, j - 1];
                    int p8 = grid[i, j - 1];
                    int p9 = grid[i - 1, j - 1];
                    int A =   ((p2 == 0 && p3 == 1) ? 1 : 0)
                            + ((p3 == 0 && p4 == 1) ? 1 : 0)
                            + ((p4 == 0 && p5 == 1) ? 1 : 0)
                            + ((p5 == 0 && p6 == 1) ? 1 : 0)
                            + ((p6 == 0 && p7 == 1) ? 1 : 0)
                            + ((p7 == 0 && p8 == 1) ? 1 : 0)
                            + ((p8 == 0 && p9 == 1) ? 1 : 0)
                            + ((p9 == 0 && p2 == 1) ? 1 : 0);
                    int B = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
                    int m1 = iter == 0 ? (p2 * p4 * p6) : (p2 * p4 * p8);
                    int m2 = iter == 0 ? (p4 * p6 * p8) : (p2 * p6 * p8);
                    if (A == 1 && B >= 2 && B <= 6 && m1 == 0 && m2 == 0) {
                        tmp[i, j] = 1;
                    }
                }
            }

            for (int i = 0; i < ni; ++i)
                for (int j = 0; j < nj; ++j)
                    grid[i,j] = grid[i, j] & ~tmp[i, j];
        }
        static void dilate(DenseGrid2i grid, DenseGrid2i tmp, bool corners = true)
        {
            if (tmp == null)
                tmp = new DenseGrid2i(grid.ni, grid.nj, 0);

            int ni = grid.ni, nj = grid.nj;

            for (int i = 1; i < ni - 1; i++) {
                for (int j = 1; j < nj - 1; j++) {
                    if ( grid[i,j] == 1 ) {
                        tmp[i, j] = 1;
                        tmp[i - 1, j] = 1;
                        tmp[i, j + 1] = 1;
                        tmp[i + 1, j] = 1;
                        tmp[i, j - 1] = 1;
                        if (corners) {
                            tmp[i - 1, j + 1] = 1;
                            tmp[i + 1, j + 1] = 1;
                            tmp[i + 1, j - 1] = 1;
                            tmp[i - 1, j - 1] = 1;
                        }
                    }
                }
            }
            grid.copy(tmp);
        }
        static void skeletonize_layer(DenseGrid3i grid, int j, int dilation_rounds = 1)
        {
            DenseGrid2i layer = grid.get_slice(j, 1);
            DenseGrid2i tmp = new DenseGrid2i(layer.ni, layer.nj, 0);

            for (int k = 0; k < dilation_rounds; ++k) {
                tmp.assign(0);
                dilate(layer, tmp);
            }

            bool done = false;
            while (!done) {
                int sum_before = layer.sum();
                tmp.assign(0);
                skeletonize_pass(layer, tmp, 0);
                tmp.assign(0);
                skeletonize_pass(layer, tmp, 1);
                int sum_after = layer.sum();
                if (sum_before == sum_after)
                    break;
            }

            for (int i = 0; i < grid.ni; ++i)
                for (int k = 0; k < grid.nk; ++k)
                    grid[i, j, k] = layer[i, k];
        }
 static DenseGrid2i binarize(DenseGrid2f grid, float thresh = 0)
 {
     DenseGrid2i result = new DenseGrid2i();
     result.resize(grid.ni, grid.nj);
     int size = result.size;
     for (int k = 0; k < size; ++k)
         result[k] = (grid[k] < thresh) ? 1 : 0;
     return result;
 }
 bool is_loner(DenseGrid2i grid, int i, int j)
 {
     if (grid[i, j] == 0)
         return false;
     int nbrs =
       grid[i - 1, j] + grid[i - 1, j + 1]
     + grid[i, j + 1] + grid[i + 1, j + 1]
     + grid[i + 1, j] + grid[i + 1, j - 1]
     + grid[i, j - 1] + grid[i - 1, j - 1];
     return nbrs == 0;
 }
예제 #6
0
        public DenseGrid2i get_slice(int slice_i, int dimension)
        {
            DenseGrid2i slice;

            if (dimension == 0)
            {
                slice = new DenseGrid2i(nj, nk, 0);
                for (int k = 0; k < nk; ++k)
                {
                    for (int j = 0; j < nj; ++j)
                    {
                        slice[j, k] = Buffer[slice_i + ni * (j + nj * k)];
                    }
                }
            }
            else if (dimension == 1)
            {
                slice = new DenseGrid2i(ni, nk, 0);
                for (int k = 0; k < nk; ++k)
                {
                    for (int i = 0; i < ni; ++i)
                    {
                        slice[i, k] = Buffer[i + ni * (slice_i + nj * k)];
                    }
                }
            }
            else
            {
                slice = new DenseGrid2i(ni, nj, 0);
                for (int j = 0; j < nj; ++j)
                {
                    for (int i = 0; i < ni; ++i)
                    {
                        slice[i, j] = Buffer[i + ni * (j + nj * slice_i)];
                    }
                }
            }
            return(slice);
        }
        static void skeletonize(DenseGrid2i grid, DenseGrid2i tmp, int dilation_rounds = 1)
        {
            if ( tmp == null )
                tmp = new DenseGrid2i(grid.ni, grid.nj, 0);

            for (int k = 0; k < dilation_rounds; ++k) {
                tmp.clear();
                dilate(grid, tmp);
            }

            bool done = false;
            while (!done) {
                int sum_before = grid.sum();
                tmp.clear();
                skeletonize_pass(grid, tmp, 0);
                tmp.clear();
                skeletonize_pass(grid, tmp, 1);
                int sum_after = grid.sum();
                if (sum_before == sum_after)
                    break;
            }
        }
        static void dilate_loners(DenseGrid2i grid, DenseGrid2i tmp, int mode)
        {
            if (tmp == null)
                tmp = new DenseGrid2i(grid.ni, grid.nj, 0);

            int ni = grid.ni, nj = grid.nj;

            for (int i = 1; i < ni - 1; i++) {
                for (int j = 1; j < nj - 1; j++) {
                    if (grid[i, j] == 1) {
                        tmp[i, j] = 1;

                        int nbrs =
                          grid[i - 1, j] + grid[i - 1, j + 1]
                        + grid[i, j + 1] + grid[i + 1, j + 1]
                        + grid[i + 1, j] + grid[i + 1, j - 1]
                        + grid[i, j - 1] + grid[i - 1, j - 1];

                        if (nbrs == 0) {
                            if (mode != 3) {
                                tmp[i - 1, j] = 1;
                                tmp[i + 1, j] = 1;
                                tmp[i, j + 1] = 1;
                                tmp[i, j - 1] = 1;
                            }
                            if (mode == 2 || mode == 3) {
                                tmp[i - 1, j + 1] = 1;
                                tmp[i + 1, j + 1] = 1;
                                tmp[i + 1, j - 1] = 1;
                                tmp[i - 1, j - 1] = 1;
                            }
                        }
                    }
                }
            }
            grid.copy(tmp);
        }
        void process_version2(DenseGrid3f supportGrid, DenseGridTrilinearImplicit distanceField)
        {
            int ni = supportGrid.ni, nj = supportGrid.nj, nk = supportGrid.nk;
            float dx = (float)CellSize;
            Vector3f origin = this.GridOrigin;

            // sweep values down layer by layer
            DenseGrid2f prev = supportGrid.get_slice(nj - 1, 1);
            DenseGrid2f tmp = new DenseGrid2f(prev);

            Bitmap3 bmp = new Bitmap3(new Vector3i(ni, nj, nk));

            for (int j = nj - 2; j >= 0; j--) {

                // skeletonize prev layer
                DenseGrid2i prev_skel = binarize(prev, 0.0f);
                skeletonize(prev_skel, null, 2);
                //dilate_loners(prev_skel, null, 2);

                if (j == 0) {
                    dilate(prev_skel, null, true);
                    dilate(prev_skel, null, true);
                }

                for (int k = 1; k < nk - 1; ++k) {
                    for (int i = 1; i < ni - 1; ++i)
                        bmp[new Vector3i(i,j,k)] = (prev_skel[i, k] == 1) ? true : false;
                }

                smooth(prev, tmp, 0.5f, 5);

                DenseGrid2f cur = supportGrid.get_slice(j, 1);
                cur.set_min(prev);

                for (int k = 1; k < nk - 1; ++k) {
                    for (int i = 1; i < ni - 1; ++i) {
                        float skelf = prev_skel[i, k] > 0 ? -1.0f : int.MaxValue;
                        cur[i, k] = Math.Min(cur[i, k], skelf);

                        if (cur[i, k] < 0) {
                            Vector3d cell_center = new Vector3f(i * dx, j * dx, k * dx) + origin;
                            if (distanceField.Value(ref cell_center) < -CellSize)
                                cur[i, k] = 1;
                        }
                    }
                }

                for (int k = 1; k < nk - 1; ++k) {
                    for (int i = 1; i < ni - 1; ++i) {
                        if (is_loner(prev_skel, i, k)) {
                            foreach (Vector2i d in gIndices.GridOffsets8) {
                                float f = 1.0f / (float)Math.Sqrt(d.x*d.x + d.y*d.y);
                                cur[i + d.x, k + d.y] += -0.25f * f;
                            }
                        }
                    }
                }

                for (int k = 1; k < nk - 1; ++k) {
                    for (int i = 1; i < ni - 1; ++i) {
                        supportGrid[i, j, k] = cur[i, k];
                    }
                }

                prev.swap(cur);
            }

            VoxelSurfaceGenerator gen = new VoxelSurfaceGenerator() { Voxels = bmp };
            gen.Generate();
            Util.WriteDebugMesh(gen.Meshes[0], "c:\\scratch\\binary.obj");
        }
예제 #10
0
 public void copy(DenseGrid2i copy)
 {
     Array.Copy(copy.Buffer, this.Buffer, this.Buffer.Length);
 }
예제 #11
0
 public DenseGrid2i(DenseGrid2i copy)
 {
     resize(copy.ni, copy.nj);
     Array.Copy(copy.Buffer, this.Buffer, this.Buffer.Length);
 }