Example #1
0
        /// <summary>
        /// http://alienryderflex.com/polygon_fill/
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="polygon"></param>
        /// <param name="fillVolume"></param>
        /// <param name="dimX"></param>
        /// <param name="dimY"></param>
        /// <param name="dimZ"></param>
        /// <param name="sliceZ"></param>
        /// <param name="fillValue"></param>
        /// <returns></returns>
        private static VoxelCounts FillPolygonAndCount(
            PointF[] polygon,
            ushort[] fillVolume,
            ushort fillValue,
            Volume2D <byte> countVolume,
            byte foregroundId)
        {
            var         bounds            = GetBoundingBox(polygon);
            const float epsilon           = 0.01f;
            var         length            = polygon.Length;
            var         nodeIntersections = new IntersectionXPoint[length * 2];
            var         nodeX             = new float[length];
            var         polygonX          = new float[length];
            var         polygonY          = new float[length];

            for (var index = 0; index < length; index++)
            {
                var point = polygon[index];
                polygonX[index] = point.X;
                polygonY[index] = point.Y;
            }

            var voxelCounts = new VoxelCounts();

            // Loop through the rows of the image.
            for (int y = 0; y < countVolume.DimY; y++)
            {
                float yPlusEpsilon  = y + epsilon;
                float yMinusEpsilon = y - epsilon;

                if ((yPlusEpsilon < bounds.Top && yMinusEpsilon < bounds.Top) ||
                    (yPlusEpsilon > bounds.Bottom && yMinusEpsilon > bounds.Bottom))
                {
                    continue;
                }

                // Build a list of nodes, sorted
                int nodesBoth = FindIntersections(polygonX, polygonY, nodeIntersections, y, yPlusEpsilon, yMinusEpsilon);

                // Merge
                int nodes = MergeIntersections(nodeIntersections, nodeX, nodesBoth);

                // Fill the pixels between node pairs.
                voxelCounts += FillNodePairsAndCount(
                    fillVolume,
                    fillValue,
                    epsilon,
                    nodeX,
                    y,
                    nodes,
                    countVolume,
                    foregroundId);
            }

            return(voxelCounts);
        }
Example #2
0
        /// <summary>
        /// http://alienryderflex.com/polygon_fill/
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="polygon"></param>
        /// <param name="result"></param>
        /// <param name="dimX"></param>
        /// <param name="dimY"></param>
        /// <param name="dimZ"></param>
        /// <param name="sliceZ"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int Fill <T>(
            PointF[] polygon,
            T[] result,
            int dimX,
            int dimY,
            int dimZ,
            int sliceZ,
            T value)
        {
            if (polygon == null)
            {
                throw new ArgumentNullException(nameof(polygon), "The polygon is null");
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result), "The result array is null");
            }

            if (polygon.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(polygon), "The polygon does not contain any points.");
            }

            if (dimX < 0 || dimY < 0 || dimZ < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(polygon), "The polygon dimension lengths cannot be less than 0.");
            }

            if (sliceZ < 0 || (dimZ == 0 && sliceZ != 0) || (dimZ > 0 && sliceZ > dimZ - 1))
            {
                throw new ArgumentOutOfRangeException(nameof(polygon), "The Z slice must be within the Z dimensions.");
            }

            var dimXy = dimX * dimY;

            if (result.Length != (dimZ == 0 ? dimXy : dimXy *dimZ))
            {
                throw new ArgumentException("The result array does not have the correct size. The size must equal dimX * dimY * dimZ.", nameof(result));
            }

            var bounds = GetBoundingBox(polygon);

            const float epsilon           = 0.01f;
            var         zOffset           = sliceZ * dimX * dimY;
            var         length            = polygon.Length;
            var         nodeIntersections = new IntersectionXPoint[length * 2];
            int         total             = 0;
            var         nodeX             = new float[length];
            var         polygonX          = new float[length];
            var         polygonY          = new float[length];

            for (var index = 0; index < length; index++)
            {
                var point = polygon[index];
                polygonX[index] = point.X;
                polygonY[index] = point.Y;
            }

            // Loop through the rows of the image.
            for (int y = 0; y < dimY; y++)
            {
                float yPlusEpsilon  = y + epsilon;
                float yMinusEpsilon = y - epsilon;

                if ((yPlusEpsilon < bounds.Top && yMinusEpsilon < bounds.Top) ||
                    (yPlusEpsilon > bounds.Bottom && yMinusEpsilon > bounds.Bottom))
                {
                    continue;
                }

                // Build a list of nodes, sorted
                int nodesBoth = FindIntersections(polygonX, polygonY, nodeIntersections, y, yPlusEpsilon, yMinusEpsilon);

                // Merge
                int nodes = MergeIntersections(nodeIntersections, nodeX, nodesBoth);

                // Fill the pixels between node pairs.
                total = FillNodePairs(result, dimX, value, epsilon, zOffset, nodeX, total, y, nodes);
            }

            return(total);
        }