/// <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); }
/// <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); }