/// <summary>
        /// Given possible polygons and specific source polygons, this takes two delegates for if an edge and a polygon is relevant and finds all the polygons that match its criteria (see the other FindAdjacent* methods in this file for examples)
        /// </summary>
        /// <param name="allBuiltPolygons">All possible polygons.</param>
        /// <param name="selectedSourcePolygons">Selected source polygons.</param>
        /// <param name="isEdgeRelevant">Is edge relevant.</param>
        /// <param name="isPolygonRelevant">Is polygon relevant.</param>
        /// <param name="applyPolygonRuleToSource">When True, isPolygonRelevant must be true for both polygons involved in the adjacency test</param>
        /// <param name="filter">Filter to further refine acceptable adjacency criteria, pass null for no filter.</param>
        public static List <int> FindAdjacentGeometry(List <Polygon> allBuiltPolygons,
                                                      List <Polygon> selectedSourcePolygons,
                                                      IsPolygonRelevant isPolygonRelevant,
                                                      ArePolygonsRelevant arePolygonsRelevant,
                                                      bool applyPolygonRuleToSource,
                                                      AdjacencyFilters.BaseFilter filter)
        {
            List <Polygon> unselectedPolygons    = new List <Polygon>(allBuiltPolygons);
            List <Polygon> selectedBuiltPolygons = new List <Polygon>();

            // Sort the built polygons into those that are selected and those that aren't
            // This starts off with all the polygons in the unselected list then picks out all those that are actually
            // selected.
            IEqualityComparer <Polygon> comparer = new Polygon.PolygonUIDComparer();

            for (int i = 0; i < unselectedPolygons.Count; i++)
            {
                if (selectedSourcePolygons.Contains(unselectedPolygons[i], comparer))
                {
                    selectedBuiltPolygons.Add(unselectedPolygons[i]);

                    unselectedPolygons.RemoveAt(i);
                    i--;
                }
            }

            // Now extract all the target edges of the selected polygons
            Dictionary <Polygon, Edge[]> groupedEdges = new Dictionary <Polygon, Edge[]>();

            for (int polygonIndex = 0; polygonIndex < selectedBuiltPolygons.Count; polygonIndex++)
            {
                Edge[] edges = selectedBuiltPolygons[polygonIndex].GetEdges();
                groupedEdges[selectedBuiltPolygons[polygonIndex]] = edges;
            }

            // Walk through all the unselected polygons and see if any match the target edges (if a isPolygonRelevant
            // delegate is also supplied then the unselected polygon must also be considered relevant)
            for (int unselectedPolygonIndex = 0; unselectedPolygonIndex < unselectedPolygons.Count; unselectedPolygonIndex++)
            {
                // If the polygon is not relevant, ignore it
                if (isPolygonRelevant != null && !isPolygonRelevant(unselectedPolygons[unselectedPolygonIndex]))
                {
                    continue;
                }

                // If the polygon is not acceptable to the filter, ignore it
                if (filter != null && !filter.IsPolygonAcceptable(unselectedPolygons[unselectedPolygonIndex]))
                {
                    continue;
                }

                // Grab all the edges of the polygon
                Edge[] edges = unselectedPolygons[unselectedPolygonIndex].GetEdges();

                foreach (KeyValuePair <Polygon, Edge[]> group in groupedEdges)
                {
                    if (applyPolygonRuleToSource &&
                        isPolygonRelevant != null &&
                        !isPolygonRelevant(group.Key))
                    {
                        continue;
                    }

                    if (arePolygonsRelevant != null &&
                        !arePolygonsRelevant(group.Key, unselectedPolygons[unselectedPolygonIndex]))
                    {
                        continue;
                    }

                    Edge[] targetEdges = group.Value;

                    bool matched = false;
                    // Test each edge to see if it matches the target edges
                    for (int edgeIndex = 0; edgeIndex < edges.Length; edgeIndex++)
                    {
                        for (int targetEdgeIndex = 0; targetEdgeIndex < targetEdges.Length; targetEdgeIndex++)
                        {
                            if (edges[edgeIndex].Intersects(targetEdges[targetEdgeIndex]))
                            {
                                matched = true;
                                selectedBuiltPolygons.Add(unselectedPolygons[unselectedPolygonIndex]);
                                break;
                            }
                        }
                        if (matched)
                        {
                            break;
                        }
                    }
                    if (matched)
                    {
                        break;
                    }
                }
            }

            // Return all the unique set of polygon IDs
            return(selectedBuiltPolygons.Select(polygon => polygon.UniqueIndex).Distinct().ToList());
        }
        public static List <int> FindAdjacentGeometry(List <Polygon> allBuiltPolygons,
                                                      List <Polygon> selectedSourcePolygons,
                                                      IsEdgeRelevant isEdgeRelevant,
                                                      IsPolygonRelevant isPolygonRelevant)
        {
            List <Polygon> unselectedPolygons    = new List <Polygon>(allBuiltPolygons);
            List <Polygon> selectedBuiltPolygons = new List <Polygon>();

            // Sort the built polygons into those that are selected and those that aren't
            // This starts off with all the polygons in the unselected list then picks out all those that are actually
            // selected.
            IEqualityComparer <Polygon> comparer = new Polygon.PolygonUIDComparer();

            for (int i = 0; i < unselectedPolygons.Count; i++)
            {
                if (selectedSourcePolygons.Contains(unselectedPolygons[i], comparer))
                {
                    selectedBuiltPolygons.Add(unselectedPolygons[i]);

                    unselectedPolygons.RemoveAt(i);
                    i--;
                }
            }

            // Now extract all the target edges of the selected polygons that satisfy the edge relevant requirement
            List <Edge> targetEdges = new List <Edge>();

            for (int polygonIndex = 0; polygonIndex < selectedBuiltPolygons.Count; polygonIndex++)
            {
                Edge[] edges = selectedBuiltPolygons[polygonIndex].GetEdges();
                for (int edgeIndex = 0; edgeIndex < edges.Length; edgeIndex++)
                {
                    if (isEdgeRelevant == null || isEdgeRelevant(edges[edgeIndex]))
                    {
                        targetEdges.Add(edges[edgeIndex]);
                    }
                }
            }

            // Walk through all the unselected polygons and see if any match the target edges (if a isPolygonRelevant
            // delegate is also supplied then the unselected polygon must also be considered relevant)
            for (int polygonIndex = 0; polygonIndex < unselectedPolygons.Count; polygonIndex++)
            {
                if (isPolygonRelevant != null && !isPolygonRelevant(unselectedPolygons[polygonIndex]))
                {
                    continue;
                }

                // Grab all the edges of the polygon
                Edge[] edges = unselectedPolygons[polygonIndex].GetEdges();

                // Test each edge to see if it matches the target edges
                for (int edgeIndex = 0; edgeIndex < edges.Length; edgeIndex++)
                {
                    bool matched = false;
                    for (int targetEdgeIndex = 0; targetEdgeIndex < targetEdges.Count; targetEdgeIndex++)
                    {
                        if (edges[edgeIndex].Intersects(targetEdges[targetEdgeIndex]))
                        {
                            matched = true;
                            selectedBuiltPolygons.Add(unselectedPolygons[polygonIndex]);
                            break;
                        }
                    }
                    if (matched)
                    {
                        break;
                    }
                }
            }

            // Return all the unique set of polygon IDs
            return(selectedBuiltPolygons.Select(polygon => polygon.UniqueIndex).Distinct().ToList());
        }