/// <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>
        /// Attempts to get a collection of edges in CCW order that is a small cycle.  Uses PolygonSplittingGraphNode to
        /// extract small cycles.
        /// </summary>
        /// <param name="edgeColl"></param>
        /// <returns>CCW collection of edges that forms a small loop(s).</returns>
        public static List <EdgeCollection <TileEdge> > GetSmallClosedLoops(this EdgeCollection <TileEdge> edgeColl)
        {
            if (edgeColl is null)
            {
                throw new ArgumentNullException(nameof(edgeColl));
            }

            EdgeCollection <TileEdge>                   connectedColl = edgeColl.GetOrderedCollection();
            Dictionary <PolyEdge, TileEdge>             polyToTileMap = _InitTilePolyBiDict(connectedColl);
            SortedList <int, PolygonSplittingGraphNode> polygonNodes  = _CreatePolygonGraphSplittingNodes(polyToTileMap);
            var graph = new PolygonSplittingGraph(polygonNodes.Values.ToList());
            List <ChordlessPolygon> smallLoops = graph.GetMinCycles();

            var allTileEdgeLoops = new List <EdgeCollection <TileEdge> >();

            foreach (ChordlessPolygon poly in smallLoops)
            {
                List <TileEdge> smallLoopsEdges = _ConvertChordlessPolygonToPolyEdges(poly.outerPerimUnsimplified, polyToTileMap);
                allTileEdgeLoops.Add(new EdgeCollection <TileEdge>(smallLoopsEdges));
            }
            return(allTileEdgeLoops);
        }
Beispiel #3
0
        /// <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);
        }