/*
  * Marks each exposed voxel as 1.
  */
 public void MarkExternal(VoxelGrid voxelGrid)
 {
     for (int x = 1; x < xBound - 1; x++)
     {
         for (int y = 1; y < yBound - 1; y++)
         {
             for (int z = 1; z < zBound - 1; z++)
             {
                 if (voxelGrid.coordinateGrid[x][y][z] && voxelGrid.HasEmptyNeighbor(x, y, z))
                 {
                     grid[x][y][z] = 1;
                 }
             }
         }
     }
 }
        private void CreateStartGrid(VoxelGrid voxelGrid)
        {
            xBound = voxelGrid.xBound;
            yBound = voxelGrid.yBound;
            zBound = voxelGrid.zBound;


            grid = new int[xBound][][];
            for (int i = 0; i < grid.Length; i++)
            {
                grid[i] = new int[yBound][];

                for (int j = 0; j < grid[i].Length; j++)
                {
                    grid[i][j] = new int[zBound];
                }
            }
        }
Beispiel #3
0
        /**
         * Pre processing for the skeletonizing. Removes the outer most layers.
         */
        private static void ThinByDistanceMapping(DistanceGrid distanceGrid, VoxelGrid voxelGrid)
        {
            int outerLayersToRemove = Convert.ToInt32(voxelGrid.ComponentWiseResolutionDivider * outerLayerLimit);

            for (int x = 1; x < distanceGrid.xBound; x++)
            {
                for (int y = 1; y < distanceGrid.yBound; y++)
                {
                    for (int z = 1; z < distanceGrid.zBound; z++)
                    {
                        if (distanceGrid.grid[x][y][z] <= outerLayersToRemove)
                        {
                            distanceGrid.grid[x][y][z] = 0;
                        }
                    }
                }
            }
        }
        public override bool Equals(Object obj)
        {
            //Check for null and compare run-time types.
            if ((obj == null) || !this.GetType().Equals(obj.GetType()))
            {
                return(false);
            }
            else
            {
                VoxelGrid other = (VoxelGrid)obj;

                return(this.resolution == other.resolution &&
                       this.voxelStartCoordinate == other.voxelStartCoordinate &&
                       this.coordinateGrid.Length == other.coordinateGrid.Length &&
                       this.coordinateGrid[0].Length == other.coordinateGrid[0].Length &&
                       this.coordinateGrid[0][0].Length == other.coordinateGrid[0][0].Length &&
                       System.Linq.Enumerable.SequenceEqual(this.coordinateGrid, other.coordinateGrid));
            }
        }
Beispiel #5
0
        public bool Matches(VoxelGrid voxelGrid, int startX, int startY, int startZ)
        {
            bool shouldTestX = false;
            bool passedXTest = false;

            for (int x = 0; x <= 2; x++)
            {
                for (int y = 0; y <= 2; y++)
                {
                    for (int z = 0; z <= 2; z++)
                    {
                        if (voxelGrid.coordinateGrid[startX - 1 + x][startY - 1 + y][startZ - 1 + z] /*is Black*/)
                        {
                            if (pointMask[x][y][z] == PointType.WHITE)
                            {
                                return(false);
                            }

                            if (pointMask[x][y][z] == PointType.X)
                            {
                                passedXTest = true;
                            }
                        }
                        else /*is White*/
                        {
                            if (pointMask[x][y][z] == PointType.BLACK)
                            {
                                return(false);
                            }

                            if (pointMask[x][y][z] == PointType.X)
                            {
                                shouldTestX = true;
                            }
                        }
                    }
                }
            }
            return(!shouldTestX || passedXTest);
        }
 /*
  * Creates a DistanceGrid based on a VoxelGrid
  */
 public DistanceGrid(VoxelGrid voxelGrid)
 {
     CreateStartGrid(voxelGrid);
     MarkExternal(voxelGrid);
     MarkInternal(voxelGrid);
 }
Beispiel #7
0
        /**
         * Generates a NodeGraph from a skeletonized voxelgrid, by traversing neighboring
         * voxels and creating nodes connected by edges to maintain the topology of the voxelgrid.
         */
        private static NodeGraph CreateNodeGraph(DistanceGrid distanceGrid, VoxelGrid voxelGrid)
        {
            bool[][][] visitedGrid = new bool[distanceGrid.xBound + 1][][];
            for (int i = 0; i < visitedGrid.Length; i++)
            {
                visitedGrid[i] = new bool[distanceGrid.yBound + 1][];

                for (int j = 0; j < visitedGrid[i].Length; j++)
                {
                    visitedGrid[i][j] = new bool[distanceGrid.zBound + 1];
                }
            }

            NodeGraph nodeGraph = new NodeGraph();

            Queue <(Point3, Point3)> startPoints = GetStartPoints(distanceGrid);

            Point3 initialPoint = startPoints.Peek().Item1;

            nodeGraph.AddNode(voxelGrid.LowestPositionAtCoordinate(initialPoint));
            visitedGrid[initialPoint.x][initialPoint.y][initialPoint.z] = true;

            //Breadth-first traversing of the Voxels
            while (startPoints.Count > 0)
            {
                (Point3 startPoint, Point3 currentPoint) = startPoints.Dequeue();

                //Special case for when connecting to an allready visited node
                if (visitedGrid[currentPoint.x][currentPoint.y][currentPoint.z])
                {
                    Vect3 pos1 = voxelGrid.LowestPositionAtCoordinate(startPoint);
                    Vect3 pos2 = voxelGrid.LowestPositionAtCoordinate(currentPoint);

                    Node startNode   = nodeGraph.GetNode(pos1);
                    Node currentNode = nodeGraph.GetNode(pos2);

                    if (nodeGraph.GetNode(pos1) == null || nodeGraph.GetNode(pos2) == null)
                    {
                        continue;
                    }

                    bool shouldLink = true;

                    foreach (var neighbor in currentNode.neighbors)
                    {
                        if (neighbor.nodeIndex == startNode.index)
                        {
                            shouldLink = false;
                        }
                        else
                        {
                            Node neighborNode = nodeGraph.GetNode(neighbor.nodeIndex);
                            foreach (var nextNeighbor in neighborNode.neighbors)
                            {
                                if (nextNeighbor.nodeIndex == startNode.index)
                                {
                                    shouldLink = false;
                                }
                            }
                        }

                        if (!shouldLink)
                        {
                            break;
                        }
                    }
                    if (shouldLink)
                    {
                        nodeGraph.LinkNodes(pos1, pos2);
                    }
                    else
                    {
                        continue;
                    }
                }


                Point3 cameFrom = startPoint;

                List <Point3> pathPoints = new List <Point3>()
                {
                    startPoint
                };

                Vect3 startCoordinate   = voxelGrid.LowestPositionAtCoordinate(startPoint);
                Vect3 currentCoordinate = voxelGrid.LowestPositionAtCoordinate(currentPoint);

                List <Vect3> intermediateCoords = new List <Vect3>();

                List <Point3> neighbors = new List <Point3>();

                bool distanceWasValid = false;

                //Traversing untill the Nodeplacement would make the Edge to far away from the voxels it represents,
                //an already visited node is reached, an intersection is found or it's a dead end.
                while (DistancesAreValid(startCoordinate, currentCoordinate, intermediateCoords, voxelGrid.resolution))
                {
                    // Node we found was visited
                    if (visitedGrid[currentPoint.x][currentPoint.y][currentPoint.z])
                    {
                        // Ensures nothing happens after we break
                        distanceWasValid = true;
                        break;
                    }

                    neighbors = distanceGrid.Get26AdjacentNeighbors(currentPoint);
                    pathPoints.Add(currentPoint);

                    if (neighbors.Count != 2)
                    {
                        visitedGrid[currentPoint.x][currentPoint.y][currentPoint.z] = true;
                        distanceWasValid = true;
                        break;
                    }

                    // Only one new neighbor
                    intermediateCoords.Add(voxelGrid.LowestPositionAtCoordinate(currentPoint));

                    Point3 temp = currentPoint;
                    currentPoint      = neighbors[0] == cameFrom ? neighbors[1] : neighbors[0];
                    currentCoordinate = voxelGrid.LowestPositionAtCoordinate(currentPoint);
                    cameFrom          = temp;

                    visitedGrid[cameFrom.x][cameFrom.y][cameFrom.z] = true;
                }

                double maxDistanceValue = 0;

                foreach (var point in pathPoints)
                {
                    maxDistanceValue += distanceGrid.grid[point.x][point.y][point.z] * voxelGrid.resolution * SquareRootOfThree; // Distance is 26-distance from edge
                    // double distanceValue = distanceGrid.grid[point.x][point.y][point.z]*voxelGrid.resolution*2;
                    // maxDistanceValue = distanceValue > maxDistanceValue ? distanceValue : maxDistanceValue;
                }

                maxDistanceValue /= (double)pathPoints.Count;

                double minWidth  = maxDistanceValue;
                double minHeight = maxDistanceValue;

                if (!distanceWasValid)
                {
                    nodeGraph.AddNode(intermediateCoords[intermediateCoords.Count - 1], minWidth, minHeight, nodeGraph.GetNode(startCoordinate).index);
                    visitedGrid[cameFrom.x][cameFrom.y][cameFrom.z] = true;
                    if (!visitedGrid[currentPoint.x][currentPoint.y][currentPoint.z])
                    {
                        startPoints.Enqueue((cameFrom, currentPoint));
                    }
                }
                else
                {
                    nodeGraph.AddNode(currentCoordinate, minWidth, minHeight, nodeGraph.GetNode(startCoordinate).index);
                    foreach (var neighbor in neighbors)
                    {
                        if (neighbor == cameFrom ||
                            visitedGrid[neighbor.x][neighbor.y][neighbor.z])
                        {
                            continue;
                        }
                        startPoints.Enqueue((currentPoint, neighbor));
                    }
                }
            }
            return(nodeGraph);
        }
Beispiel #8
0
 public static void Skeletonize(DistanceGrid distanceGrid, VoxelGrid voxelGrid)
 {
     ThinByDistanceMapping(distanceGrid, voxelGrid);
     ThinToSkeleton(distanceGrid);
 }