/// <summary> /// Partitions a complex polygon (with chords and holes) into a group of chordless polygons. /// </summary> /// <param name="allIsoPerims">Array of lists of Vector2s, each describing a perimeter of a tile group.</param> /// <returns>A list of lists of Vector2s, each list describing a chordless polygon.</returns> // ReSharper disable once ReturnTypeCanBeEnumerable.Local private static (List <Chord>, List <ChordlessPolygon>) _ComplexToChordlessPolygons(List <Vector2>[] allIsoPerims) { HashSet <ConcaveVertex> concaveVertices = ConcaveVertexFinder.GetConcaveVertices(allIsoPerims); List <Chord> chords = _FindChords(concaveVertices, allIsoPerims); Dictionary <BipartiteGraphNode, Chord> bipartiteNodeToChords = _ConvertChordsToNodes(chords); var bipartiteGraph = new BipartiteGraph(bipartiteNodeToChords.Keys); HashSet <BipartiteGraphNode> maxIndependentSet = bipartiteGraph.GetMaxIndependentSet(); List <PolygonSplittingGraphNode> polygonSplittingNodes = _ConstructPolygonSplittingNodes(allIsoPerims, bipartiteNodeToChords, maxIndependentSet); var holes = new List <List <Vector2> >(); for (int i = 1; i < allIsoPerims.Length; i++) { holes.Add(allIsoPerims[i]); } var polygonSplittingGraph = new PolygonSplittingGraph(polygonSplittingNodes, holes); List <ChordlessPolygon> minCycles = polygonSplittingGraph.GetMinCycles(); return(chords, minCycles); }
/// <summary> /// Splits a chordless polygon into rectangles by extending its concave vertices according to the following criteria: /// 1. If the vertex has a bridge, extend in that direction. /// 2. If possible to extend in a direction that forms a chord, do NOT do it. /// 3. If neither of the above, either direction works. /// This method then builds PolygonSplittingGraphNodes to make a PolygonSplittingGraph and then runs the GetMinCycles /// func in order to get rectangles. /// </summary> /// <param name="chordlessPolygons">A list of chordless polygons.</param> /// <returns>A list of lists of four vector2s, AKA a list of lists of rectangles.</returns> public static List <List <Vector2> > DecomposeChordlessPolygonToRectangles(this List <ChordlessPolygon> chordlessPolygons, List <Chord> chords) { if (chordlessPolygons is null) { throw new ArgumentNullException(nameof(chordlessPolygons)); } var rectangles = new List <List <Vector2> >(); foreach (ChordlessPolygon polygon in chordlessPolygons) { HashSet <ConcaveVertex> concaveVertices = ConcaveVertexFinder.GetConcaveVertices(polygon); List <PolyEdge> extensionSegments = _FindVertexExtensions(polygon, concaveVertices, chords); HashSet <Vector2> extensionVertices = _GetNewVertices(polygon, extensionSegments); (List <Vector2> newPerim, List <List <Vector2> > newHoles) = _InsertNewVerticesIntoPerims(polygon, extensionVertices); List <PolygonSplittingGraphNode> nodes = _CreateNewNodes(newPerim, newHoles, extensionSegments); var polygonSplittingGraph = new PolygonSplittingGraph(nodes, newHoles); List <ChordlessPolygon> newRectangles = polygonSplittingGraph.GetMinCycles(); rectangles.AddRange(newRectangles.Select(rectangle => rectangle.outerPerim.ToList())); } return(rectangles); }