Пример #1
0
        // Given a grid cell and an isolevel, calculate the triangular facets required to represent the isosurface through the cell.
        // Return the number of triangular facets, the array "triangles" will be loaded up with the vertices at most 5 triangular facets.
        // 0 will be returned if the grid cell is either totally above of totally below the isolevel.
        public static void Polygonise(GridCell grid, double isolevel, ref List <Triangle> theTriangleList)
        {
            // Determine the index into the edge table which tells us which vertices are inside of the surface
            int cubeindex = 0;

            if (grid.val[0] < isolevel)
            {
                cubeindex |= 1;
            }
            if (grid.val[1] < isolevel)
            {
                cubeindex |= 2;
            }
            if (grid.val[2] < isolevel)
            {
                cubeindex |= 4;
            }
            if (grid.val[3] < isolevel)
            {
                cubeindex |= 8;
            }
            if (grid.val[4] < isolevel)
            {
                cubeindex |= 16;
            }
            if (grid.val[5] < isolevel)
            {
                cubeindex |= 32;
            }
            if (grid.val[6] < isolevel)
            {
                cubeindex |= 64;
            }
            if (grid.val[7] < isolevel)
            {
                cubeindex |= 128;
            }

            // Cube is entirely in/out of the surface
            if (EdgeTable.LookupTable[cubeindex] == 0)
            {
                return;
            }

            Point3D[] vertlist = new Point3D[12];

            // Find the vertices where the surface intersects the cube
            if ((EdgeTable.LookupTable[cubeindex] & 1) > 0)
            {
                vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 2) > 0)
            {
                vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 4) > 0)
            {
                vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 8) > 0)
            {
                vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 16) > 0)
            {
                vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 32) > 0)
            {
                vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 64) > 0)
            {
                vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 128) > 0)
            {
                vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 256) > 0)
            {
                vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 512) > 0)
            {
                vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 1024) > 0)
            {
                vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]);
            }

            if ((EdgeTable.LookupTable[cubeindex] & 2048) > 0)
            {
                vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]);
            }

            // Create the triangle
            for (int i = 0; TriTable.LookupTable[cubeindex, i] != -1; i += 3)
            {
                Triangle aTriangle = new Triangle();

                aTriangle.p[0] = vertlist[TriTable.LookupTable[cubeindex, i]];
                aTriangle.p[1] = vertlist[TriTable.LookupTable[cubeindex, i + 1]];
                aTriangle.p[2] = vertlist[TriTable.LookupTable[cubeindex, i + 2]];

                theTriangleList.Add(aTriangle);
            }
        }
Пример #2
0
        private static List<Triangle> ComputeTriangles(CTSliceInfo[] slices, int theIsoValue)
        {
            // 1. Calculate the Center Point
            // =============================
            // For moving the 3D model with the mouse, the implementation is taken from Code Project 'WPF 3D Primer'.
            // See also: 'http://www.codeproject.com/Articles/23332/WPF-3D-Primer#'
            // However, this implementation needs the 3D model to be centered in the origin of the coordinate system.
            // As a consequence, all CT Slices have to be shifted by the Center Point (method 'AdjustPatientPositionToCenterPoint()')
            CTSliceInfo firstCT = slices[0];
            CTSliceInfo lastCT  = slices[slices.Length - 1];

            double Center_X = firstCT.UpperLeft_X + (firstCT.PixelSpacing_X * firstCT.ColumnCount / 2);
            double Center_Y = firstCT.UpperLeft_Y + (firstCT.PixelSpacing_Y * firstCT.RowCount / 2);

            // CT Slices are already sorted ascending in Z direction
            double Center_Z = firstCT.UpperLeft_Z + ((lastCT.UpperLeft_Z - firstCT.UpperLeft_Z) / 2);

            // Create the Center Point
            Point3D aCenterPoint = new Point3D(Center_X, Center_Y, Center_Z);

            // 2. The Marching Cubes algorithm
            // ===============================
            // For each Voxel of the CT Slice, an own GridCell is created.
            // The IsoValue and the x/y/z information for each corner of the GridCell is taken from the direct neighbor voxels (of the same or adjacant CT Slice).
            // Looping has to be done over all CT Slices.

            List<Triangle> triangles = new List<Triangle>();

            CTSliceInfo slice1 = null;
            CTSliceInfo slice2 = slices[0];

            slice2.AdjustPatientPositionToCenterPoint(aCenterPoint);

            for (int sliceIdx = 1; sliceIdx != slices.Length; ++sliceIdx)
            {
                slice1 = slice2;
                slice2 = slices[sliceIdx];
                slice2.AdjustPatientPositionToCenterPoint(aCenterPoint);

                for (int r = 0; r != slice1.RowCount - 1; ++r)
                {
                    for (int c = 0; c != slice1.ColumnCount - 1; ++c)
                    {
                        GridCell aGridCell = new GridCell(sliceIdx, r, c, slice1, slice2);
                        MarchingCubes.Polygonise(aGridCell, theIsoValue, ref triangles);
                    }
                }
            }
            return triangles;
        }
Пример #3
0
        // Given a grid cell and an isolevel, calculate the triangular facets required to represent the isosurface through the cell.
        // Return the number of triangular facets, the array "triangles" will be loaded up with the vertices at most 5 triangular facets.
        // 0 will be returned if the grid cell is either totally above of totally below the isolevel.
        public static void Polygonise(GridCell grid, double isolevel, ref List<Triangle> theTriangleList)
        {
            // Determine the index into the edge table which tells us which vertices are inside of the surface
            int cubeindex = 0;
            if (grid.val[0] < isolevel) cubeindex |= 1;
            if (grid.val[1] < isolevel) cubeindex |= 2;
            if (grid.val[2] < isolevel) cubeindex |= 4;
            if (grid.val[3] < isolevel) cubeindex |= 8;
            if (grid.val[4] < isolevel) cubeindex |= 16;
            if (grid.val[5] < isolevel) cubeindex |= 32;
            if (grid.val[6] < isolevel) cubeindex |= 64;
            if (grid.val[7] < isolevel) cubeindex |= 128;

            // Cube is entirely in/out of the surface
            if (EdgeTable.LookupTable[cubeindex] == 0)
                return;

            Point3D[] vertlist = new Point3D[12];

            // Find the vertices where the surface intersects the cube
            if ((EdgeTable.LookupTable[cubeindex] & 1) > 0)
                vertlist[0] = VertexInterp(isolevel, grid.p[0], grid.p[1], grid.val[0], grid.val[1]);

            if ((EdgeTable.LookupTable[cubeindex] & 2) > 0)
                vertlist[1] = VertexInterp(isolevel, grid.p[1], grid.p[2], grid.val[1], grid.val[2]);

            if ((EdgeTable.LookupTable[cubeindex] & 4) > 0)
                vertlist[2] = VertexInterp(isolevel, grid.p[2], grid.p[3], grid.val[2], grid.val[3]);

            if ((EdgeTable.LookupTable[cubeindex] & 8) > 0)
                vertlist[3] = VertexInterp(isolevel, grid.p[3], grid.p[0], grid.val[3], grid.val[0]);

            if ((EdgeTable.LookupTable[cubeindex] & 16) > 0)
                vertlist[4] = VertexInterp(isolevel, grid.p[4], grid.p[5], grid.val[4], grid.val[5]);

            if ((EdgeTable.LookupTable[cubeindex] & 32) > 0)
                vertlist[5] = VertexInterp(isolevel, grid.p[5], grid.p[6], grid.val[5], grid.val[6]);

            if ((EdgeTable.LookupTable[cubeindex] & 64) > 0)
                vertlist[6] = VertexInterp(isolevel, grid.p[6], grid.p[7], grid.val[6], grid.val[7]);

            if ((EdgeTable.LookupTable[cubeindex] & 128) > 0)
                vertlist[7] = VertexInterp(isolevel, grid.p[7], grid.p[4], grid.val[7], grid.val[4]);

            if ((EdgeTable.LookupTable[cubeindex] & 256) > 0)
                vertlist[8] = VertexInterp(isolevel, grid.p[0], grid.p[4], grid.val[0], grid.val[4]);

            if ((EdgeTable.LookupTable[cubeindex] & 512) > 0)
                vertlist[9] = VertexInterp(isolevel, grid.p[1], grid.p[5], grid.val[1], grid.val[5]);

            if ((EdgeTable.LookupTable[cubeindex] & 1024) > 0)
                vertlist[10] = VertexInterp(isolevel, grid.p[2], grid.p[6], grid.val[2], grid.val[6]);

            if ((EdgeTable.LookupTable[cubeindex] & 2048) > 0)
                vertlist[11] = VertexInterp(isolevel, grid.p[3], grid.p[7], grid.val[3], grid.val[7]);

            // Create the triangle
            for (int i = 0; TriTable.LookupTable[cubeindex, i] != -1; i += 3)
            {
                Triangle aTriangle = new Triangle();

                aTriangle.p[0] = vertlist[TriTable.LookupTable[cubeindex, i]];
                aTriangle.p[1] = vertlist[TriTable.LookupTable[cubeindex, i + 1]];
                aTriangle.p[2] = vertlist[TriTable.LookupTable[cubeindex, i + 2]];

                theTriangleList.Add(aTriangle);
            }
        }