Пример #1
0
        private static void CompareAdjacency(PolygonF polygon, AdjacencyInfo adjacencyInfo, out int startIndex, out int endIndex, out bool forward)
        {
            var index2 = polygon.Vertices.IndexOf(adjacencyInfo.Vertices[1]);

            startIndex = polygon.Vertices.LastIndexOf(adjacencyInfo.Vertices[0], index2);
            if (startIndex == -1)
            {
                startIndex = polygon.Vertices.IndexOf(adjacencyInfo.Vertices[0], index2);

                if (startIndex > 0)
                {
                    // if the one vertex is repeated multiple times, find the closest copy
                    var tmp1 = polygon.Vertices.IndexOf(adjacencyInfo.Vertices[1], startIndex - 1);
                    var tmp2 = polygon.Vertices.IndexOf(adjacencyInfo.Vertices[1], startIndex + 1);

                    if (tmp1 != -1)
                    {
                        if (tmp2 != -1)
                        {
                            index2 = Math.Abs(startIndex - tmp1) < Math.Abs(startIndex - tmp2)
                                ? tmp1
                                : tmp2;
                        }
                        else
                        {
                            index2 = tmp1;
                        }
                    }
                    else if (tmp2 != -1)
                    {
                        index2 = tmp2;
                    }
                }
            }

            endIndex = adjacencyInfo.Vertices.Length > 2
                ? polygon.Vertices.IndexOf(adjacencyInfo.Vertices[adjacencyInfo.Vertices.Length - 1])
                : index2;

            forward = Math.Abs(index2 - startIndex) == 1 ? startIndex <index2 : startIndex> index2;
        }
Пример #2
0
        public void MergeWithDistrict(DistrictGenerator other, AdjacencyInfo adjacency)
        {
            MergeWith(other, adjacency);

            foreach (var yetAnother in other.AdjacentDistricts)
            {
                yetAnother.AdjacentDistricts.Remove(other);

                if (yetAnother != this && !yetAnother.AdjacentDistricts.Contains(this))
                {
                    yetAnother.AdjacentDistricts.Add(this);
                }
            }

            var toAdd = other.AdjacentDistricts
                        .Where(d => d != this && !AdjacentDistricts.Contains(d));

            foreach (var district in toAdd)
            {
                AdjacentDistricts.Add(district);
            }
        }
Пример #3
0
        public void MergeWith(PolygonF otherPolygon, AdjacencyInfo adjacencyInfo)
        {
            if (Area == 0)
            {
                Vertices.Clear();
                Vertices.AddRange(otherPolygon.Vertices);
                Area = otherPolygon.Area;
                return;
            }

            if (otherPolygon.Area == 0)
            {
                return;
            }

            Area += otherPolygon.Area;

            if (adjacencyInfo.Vertices.Length >= otherPolygon.Vertices.Count)
            {
                // Other polygon is entirely contained in this one.
                // If it's fully wrapped, remove all its vertices, otherwise remove all but the first and last adjacent vertices.
                bool firstLastEqual = adjacencyInfo.Vertices[0] == adjacencyInfo.Vertices[adjacencyInfo.Vertices.Length - 1];
                var  toRemove       = adjacencyInfo.Vertices.Skip(1);
                if (!firstLastEqual)
                {
                    toRemove = toRemove.Take(adjacencyInfo.Vertices.Length - 2);
                }

                foreach (var vertex in toRemove)
                {
                    Vertices.Remove(vertex);
                }
                return;
            }
            else if (adjacencyInfo.Vertices.Length >= Vertices.Count)
            {
                // This polygon is entirely contained the other one one.
                // If it's fully wrapped, remove all its vertices, otherwise remove all but the first and last adjacent vertices.
                bool firstLastEqual = adjacencyInfo.Vertices[0] == adjacencyInfo.Vertices[adjacencyInfo.Vertices.Length - 1];
                var  toRemove       = adjacencyInfo.Vertices.Skip(1);
                if (!firstLastEqual)
                {
                    toRemove = toRemove.Take(adjacencyInfo.Vertices.Length - 2);
                }

                foreach (var vertex in toRemove)
                {
                    otherPolygon.Vertices.Remove(vertex);
                }

                // and then use those on this one
                Vertices.Clear();
                Vertices.AddRange(otherPolygon.Vertices);
                return;
            }

            CompareAdjacency(this, adjacencyInfo, out int localStartIndex, out int localEndIndex, out bool localForward);
            CompareAdjacency(otherPolygon, adjacencyInfo, out int otherStartIndex, out int otherEndIndex, out bool otherForward);

            // remove any "mid" points in the adjacent edge array from this polygon
            int insertIndex = RemoveMidPoints(this, localStartIndex, localEndIndex, localForward);

            // remove ALL points in the adjacent edge array from the other polygon
            otherStartIndex = WrapIndex(otherStartIndex, otherPolygon.Vertices.Count, !otherForward);
            otherEndIndex   = WrapIndex(otherEndIndex, otherPolygon.Vertices.Count, otherForward);
            RemoveMidPoints(otherPolygon, otherStartIndex, otherEndIndex, otherForward);

            // add all remaining vertices from the other polgyon, reversing them if necessary
            if (localForward == otherForward)
            {
                otherPolygon.Vertices.Reverse();
            }

            Vertices.InsertRange(insertIndex, otherPolygon.Vertices);
        }
Пример #4
0
        private bool MergeDistricts(List <DistrictGenerator> districts, Func <DistrictGenerator, bool> districtFilter, Func <DistrictGenerator, bool> targetFilter)
        {
            bool addedAny = false;

            for (int iPolygon = 0; iPolygon < districts.Count; iPolygon++)
            {
                var testPolygon = districts[iPolygon];

                if (!districtFilter(testPolygon))
                {
                    continue;
                }

                // This polygon should be merged onto the adjacent polygon that shares its longest edge

                AdjacencyInfo     bestAdjacency = null;
                DistrictGenerator bestPolygon   = null;

                foreach (var polygon in districts)
                {
                    if (polygon == testPolygon)
                    {
                        continue; // don't merge with self
                    }
                    if (!targetFilter(polygon))
                    {
                        continue;
                    }

                    if (!testPolygon.AdjacentDistricts.Contains(polygon))
                    {
                        continue; // filter out non-adjacent districts quickly
                    }
                    var adjacency = testPolygon.GetAdjacencyInfo(polygon);
                    if (adjacency == null)
                    {
                        continue; // don't merge if not adjacent
                    }
                    if (bestAdjacency != null && adjacency.Length < bestAdjacency.Length)
                    {
                        continue; // don't merge if we already have a polygon we share longer edge(s) with
                    }
                    bestAdjacency = adjacency;
                    bestPolygon   = polygon;
                }

                if (bestPolygon == null)
                {
                    continue;
                }

                bestPolygon.MergeWithDistrict(testPolygon, bestAdjacency);

                districts.RemoveAt(iPolygon);
                iPolygon--;

                addedAny = true;
            }

            return(addedAny);
        }