/// <summary> /// Finds the interior contours of the area. /// </summary> /// <param name="area">The area to analyze.</param> /// <param name="neighborhood">What type of neighborhood to segerate contours by.</param> /// <returns> /// A list of the contours. Each index corresponds to the distance from the outer edge (0 is right next to it, 1 is futher inside, etc). /// </returns> public static IReadOnlyList <IReadOnlySet <Position> > DetermineInteriorContours( this ConnectedArea area, Neighborhood neighborhood) { Func <Position, IEnumerable <Position> > getNeighborhood = neighborhood == Neighborhood.Moore ? PositionExtensions.GetMooreNeighbors : PositionExtensions.GetVonNeumannNeighbors; HashSet <Position> remainingPositions = new(area); List <IReadOnlySet <Position> > edges = new(); // Find outer edge var outerEdge = remainingPositions.Where(p => getNeighborhood(p).Any(p => !area.Contains(p))).ToHashSet(); edges.Add(outerEdge); remainingPositions.ExceptWith(outerEdge); // Find remaining boundaries while (remainingPositions.Any()) { var lastEdge = edges.Last(); var edge = remainingPositions.Where(p => getNeighborhood(p).Any(lastEdge.Contains)).ToHashSet(); edges.Add(edge); remainingPositions.ExceptWith(edge); } return(edges); }
public static IReadOnlyDictionary <Position, int> DetermineInteriorEdgeDistance( this ConnectedArea area, Neighborhood neighborhood) { var edges = DetermineInteriorContours(area, neighborhood); var output = new Dictionary <Position, int>(); for (int distance = 0; distance < edges.Count; distance++) { foreach (var p in edges[distance]) { output.Add(p, distance); } } return(output); }