コード例 #1
0
 public Region(IAdminEntity entity, int regionIndex)
 {
     this.entity      = entity;
     this.regionIndex = regionIndex;
     this.sanitized   = true;
     neighbours       = new List <Region> ();
 }
コード例 #2
0
        IEnumerator RemoveHexagons(IAdminEntity[] entities)
        {
            Clipper clipper = new Clipper();

            Cell[] cells = _map.cells;
            for (int j = 0; j < cells.Length; j++)
            {
                if (j % 100 == 0)
                {
                    if (hexifyContext.progress != null)
                    {
                        if (hexifyContext.progress((float)j / cells.Length, hexifyContext.title, "Pass 5/6: removing cells from neighbours..."))
                        {
                            cancelled = true;
                            hexifyContext.finish(true);
                            yield break;
                        }
                    }
                    yield return(null);
                }

                int entityIndex = procCells [j].entityIndex;
                if (entityIndex < 0)
                {
                    continue;
                }

                RegionCell   regionCell = procCells [j];
                IAdminEntity entity     = entities [entityIndex];

                // Substract cell region from any other entity
                List <Region> otherRegions;
                if (entity is Country)
                {
                    otherRegions = _map.GetCountryRegionsOverlap(regionCell.cellRegion);
                }
                else
                {
                    otherRegions = _map.GetProvinceRegionsOverlap(regionCell.cellRegion);
                }
                int orCount = otherRegions.Count;
                for (int o = 0; o < orCount; o++)
                {
                    Region       otherRegion = otherRegions [o];
                    IAdminEntity otherEntity = otherRegion.entity;
                    if (otherEntity == entity)
                    {
                        continue;
                    }
                    clipper.Clear();
                    clipper.AddPath(otherRegion, PolyType.ptSubject);
                    clipper.AddPath(regionCell.cellRegion, PolyType.ptClip);
                    clipper.Execute(ClipType.ctDifference, otherEntity);
                }
            }
        }
コード例 #3
0
 void RestoreRegions(List <Region> savedRegions)
 {
     for (int k = 0; k < savedRegions.Count; k++)
     {
         IAdminEntity entity      = savedRegions [k].entity;
         int          regionIndex = savedRegions [k].regionIndex;
         entity.regions [regionIndex] = savedRegions [k];
     }
     RedrawFrontiers();
 }
コード例 #4
0
        void SnapRegion(Region region)
        {
            int regionPointsCount = region.points.Length;
            int entitiesCount     = entities.Count;

            int   m         = Mathf.Max(tw, th);
            float threshold = 2f / m;

            threshold *= threshold;

            for (int k = 0; k < regionPointsCount; k++)
            {
                Vector2 p         = region.points [k];
                Vector2 nearPoint = Misc.Vector2zero;
                float   minDist   = float.MaxValue;
                for (int e = 0; e < entitiesCount; e++)
                {
                    IAdminEntity entity = entities [e];
                    if (entity.regions == null)
                    {
                        continue;
                    }
                    int entityRegionsCount = entity.regions.Count;
                    for (int r = 0; r < entityRegionsCount; r++)
                    {
                        Region entityRegion = entity.regions [r];
                        if (entityRegion == region)
                        {
                            continue;
                        }
                        int entityRegionsPointsCount = entityRegion.points.Length;
                        for (int j = 0; j < entityRegionsPointsCount; j++)
                        {
                            Vector2 op = entityRegion.points [j];

                            // Check if both points are near
                            float d = (p.x - op.x) * (p.x - op.x) + (p.y - op.y) * (p.y - op.y);
                            if (d < threshold && d < minDist)
                            {
                                nearPoint = op;
                                minDist   = d;
                            }
                        }
                    }
                }
                // Snap point?
                if (minDist < float.MaxValue)
                {
                    region.points [k] = nearPoint;
                }
            }

            region.RemoveDuplicatePoints();
        }
コード例 #5
0
 void EntityAdd(IAdminEntity newEntity)
 {
     if (newEntity is Country)
     {
         map.CountryAdd((Country)newEntity);
     }
     else
     {
         map.ProvinceAdd((Province)newEntity);
     }
 }
コード例 #6
0
        public void MergeAdjacentRegions(IAdminEntity entity)
        {
            // Searches for adjacency - merges in first region
            int regionCount = entity.regions.Count;

            for (int k = 0; k < regionCount; k++)
            {
                Region region1 = entity.regions [k];
                if (region1 == null || region1.points == null || region1.points.Length == 0)
                {
                    continue;
                }
                for (int j = k + 1; j < regionCount; j++)
                {
                    Region region2 = entity.regions [j];
                    if (region2 == null || region2.points == null || region2.points.Length == 0)
                    {
                        continue;
                    }
                    if (!region1.Intersects(region2))
                    {
                        continue;
                    }
                    RegionMagnet(region1, region2);
                    Clipper clipper = new Clipper();
                    clipper.AddPath(region1, PolyType.ptSubject);
                    clipper.AddPath(region2, PolyType.ptClip);
                    clipper.Execute(ClipType.ctUnion);

                    // Add new neighbours
                    int rnCount = region2.neighbours.Count;
                    for (int n = 0; n < rnCount; n++)
                    {
                        Region neighbour = region2.neighbours [n];
                        if (neighbour != null && neighbour != region1 && !region1.neighbours.Contains(neighbour))
                        {
                            region1.neighbours.Add(neighbour);
                        }
                    }
                    // Remove merged region

                    entity.regions.RemoveAt(j);
                    region1.sanitized = false;
                    j = k;
                    regionCount--;
                    entity.mainRegionIndex = 0;                         // will need to refresh country definition later in the process
                }
            }
        }
コード例 #7
0
        IEnumerator AddHexagons(IAdminEntity[] entities)
        {
            Cell[]  cells   = _map.cells;
            Clipper clipper = new Clipper();

            for (int j = 0; j < cells.Length; j++)
            {
                if (j % 100 == 0)
                {
                    if (hexifyContext.progress != null)
                    {
                        if (hexifyContext.progress((float)j / cells.Length, hexifyContext.title, "Pass 3/6: adding hexagons to frontiers..."))
                        {
                            cancelled = true;
                            hexifyContext.finish(true);
                            yield break;
                        }
                    }
                    yield return(null);
                }

                int entityIndex = procCells [j].entityIndex;
                if (entityIndex < 0)
                {
                    continue;
                }
                Cell cell = cells [j];

                // Create a region for the cell
                IAdminEntity entity    = entities [entityIndex];
                Vector2[]    newPoints = new Vector2[6];
                for (int k = 0; k < 6; k++)
                {
                    newPoints [k].x = hexagonPoints [k].x + cell.center.x;
                    newPoints [k].y = hexagonPoints [k].y + cell.center.y;
                }
                procCells [j].cellRegion = new Region(entity, entity.regions.Count);
                procCells [j].cellRegion.UpdatePointsAndRect(newPoints);

                // Add region to target entity's polygon - only if the entity is touching or crossing target entity frontier
                Region targetRegion = procCells [j].entityRegion;
                clipper.Clear();
                clipper.AddPath(targetRegion, PolyType.ptSubject);
                clipper.AddPath(procCells [j].cellRegion, PolyType.ptClip);
                clipper.Execute(ClipType.ctUnion);
            }
        }
コード例 #8
0
        IEnumerator RemoveSmallRegions(float minArea, IAdminEntity[] _entities)
        {
            // Clear small regions
            for (int c = 0; c < _entities.Length; c++)
            {
                if (c % 10 == 0)
                {
                    if (hexifyContext.progress != null)
                    {
                        if (hexifyContext.progress((float)c / _entities.Length, hexifyContext.title, "Pass 1/6: removing small regions..."))
                        {
                            cancelled = true;
                            hexifyContext.finish(true);
                            yield break;
                        }
                    }
                    yield return(null);
                }

                IAdminEntity entity = _entities [c];
                int          rCount = entity.regions.Count;
                bool         recalc = false;
                for (int r = 0; r < rCount; r++)
                {
                    if (entity.regions [r].rect2DArea < minArea)
                    {
                        entity.regions [r].Clear();
                        recalc = true;
                    }
                }
                if (recalc)
                {
                    if (entity is Country)
                    {
                        _map.RefreshCountryGeometry(entity);
                    }
                    else
                    {
                        _map.RefreshProvinceGeometry(entity);
                    }
                }
            }
        }
コード例 #9
0
 int EntityAdd(IAdminEntity newEntity)
 {
     if (newEntity is Country)
     {
         Country c = (Country)newEntity;
         if (map.CountryAdd(c) >= 0)
         {
             return(map.GetCountryIndex(c));
         }
     }
     else
     {
         Province p = (Province)newEntity;
         if (map.ProvinceAdd(p))
         {
             return(map.GetProvinceIndex(p));
         }
     }
     return(-1);
 }
コード例 #10
0
        void FilterSnapRegions()
        {
            if (snapEntityIndex >= entities.Count)
            {
                progress = 1f;
                return;
            }
            progress = (float)snapEntityIndex / entities.Count;
            IAdminEntity entity = entities [snapEntityIndex];

            if (entity.regions != null)
            {
                int entityRegionsCount = entity.regions.Count;
                for (int k = 0; k < entityRegionsCount; k++)
                {
                    Region regionTosnap = entities [snapEntityIndex].regions [k];
                    SnapRegion(regionTosnap);
                }
            }
            snapEntityIndex++;
        }
コード例 #11
0
        void FilterPolishJoints()
        {
            if (polishEntityIndex >= entities.Count)
            {
                progress = 1f;
                return;
            }
            progress = (float)polishEntityIndex / entities.Count;
            IAdminEntity entity = entities [polishEntityIndex];

            if (entity.regions != null)
            {
                int entityRegionsCount = entity.regions.Count;
                for (int k = 0; k < entityRegionsCount; k++)
                {
                    Region region = entities [polishEntityIndex].regions [k];
                    PolishRegionJoints(region);
                }
            }
            polishEntityIndex++;
        }
コード例 #12
0
        public void Execute(ClipType clipType, IAdminEntity entity)
        {
            List <List <IntPoint> > solution = new List <List <IntPoint> > ();

            Execute(clipType, solution);
            int contourCount = solution.Count;

            entity.regions.Clear();
            for (int c = 0; c < contourCount; c++)
            {
                List <IntPoint> points    = solution [c];
                int             count     = points.Count;
                Vector2[]       newPoints = new Vector2[count];
                for (int k = 0; k < count; k++)
                {
                    newPoints [k] = new Vector2((float)points [k].X / MULTIPLIER, (float)points [k].Y / MULTIPLIER);
                }
                Region region = new Region(entity, entity.regions.Count);
                region.UpdatePointsAndRect(newPoints);
                entity.regions.Add(region);
            }
        }
コード例 #13
0
        bool AnyRegionContainsPoint(Vector2 p)
        {
            int entitiesCount = entities.Count;

            for (int k = 0; k < entitiesCount; k++)
            {
                IAdminEntity entity = entities [k];
                if (entity.regions == null)
                {
                    continue;
                }
                int entityRegionsCount = entity.regions.Count;
                for (int r = 0; r < entityRegionsCount; r++)
                {
                    Region region = entity.regions [r];
                    if (region.Contains(p))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
コード例 #14
0
        public void Execute(ClipType clipType, IAdminEntity entity)
        {
            if (solution == null)
            {
                solution = new List <List <IntPoint> > ();
            }
            Execute(clipType, solution);
            int contourCount = solution.Count;

            // Remove subject from entity
            if (subjects != null)
            {
                for (int k = 0; k < subjects.Count; k++)
                {
                    Region sub = subjects[k];
                    if (entity.regions.Contains(sub))
                    {
                        entity.regions.Remove(sub);
                    }
                }
            }
            // Add resulting regions
            for (int c = 0; c < contourCount; c++)
            {
                // In the case of difference operations, the resulting polytongs could be artifacts if the frontiers do not match perfectly. In that case, we ignore small isolated triangles.
                if (clipType == ClipType.ctUnion || solution[c].Count >= 5)
                {
                    Vector2[] newPoints = BuildPointArray(solution[c]);
                    Region    region    = new Region(entity, entity.regions.Count);
                    region.UpdatePointsAndRect(newPoints);
                    region.sanitized = true;
                    entity.regions.Add(region);
                }
            }
            entity.mainRegionIndex = 0;
        }
コード例 #15
0
        /// <summary>
        /// Used internally by the Map Editor. It will recalculate de boundaries and optimize frontiers based on new data of provinces array
        /// </summary>
        public void RefreshProvinceGeometry(IAdminEntity province)
        {
            lastProvinceLookupCount = -1;
            float maxVol = 0;

            if (province.regions == null)
            {
                ReadProvincePackedString(province);
            }
            if (province.regions == null)
            {
                return;
            }
            int     regionCount = province.regions.Count;
            Vector2 minProvince = Misc.Vector2one * 10;
            Vector2 maxProvince = -minProvince;
            Vector2 min         = Misc.Vector2one * 10f;
            Vector2 max         = -min;

            for (int r = 0; r < regionCount; r++)
            {
                Region provinceRegion = province.regions [r];
                provinceRegion.entity      = province;                  // just in case one country has been deleted
                provinceRegion.regionIndex = r;                         // just in case a region has been deleted
                int coorCount = provinceRegion.points.Length;
                min.x = min.y = 10f;
                max.x = max.y = -10f;
                for (int c = 0; c < coorCount; c++)
                {
                    float x = provinceRegion.points [c].x;
                    float y = provinceRegion.points [c].y;
                    if (x < min.x)
                    {
                        min.x = x;
                    }
                    if (x > max.x)
                    {
                        max.x = x;
                    }
                    if (y < min.y)
                    {
                        min.y = y;
                    }
                    if (y > max.y)
                    {
                        max.y = y;
                    }
                }
                FastVector.Average(ref min, ref max, ref provinceRegion.center);

                if (min.x < minProvince.x)
                {
                    minProvince.x = min.x;
                }
                if (min.y < minProvince.y)
                {
                    minProvince.y = min.y;
                }
                if (max.x > maxProvince.x)
                {
                    maxProvince.x = max.x;
                }
                if (max.y > maxProvince.y)
                {
                    maxProvince.y = max.y;
                }
                provinceRegion.rect2D     = new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
                provinceRegion.rect2DArea = provinceRegion.rect2D.width * provinceRegion.rect2D.height;
                float vol = FastVector.SqrDistance(ref max, ref min);                  // (max - min).sqrMagnitude;
                if (vol > maxVol)
                {
                    maxVol = vol;
                    province.mainRegionIndex = r;
                    province.center          = provinceRegion.center;
                }
            }
            province.regionsRect2D = new Rect(minProvince.x, minProvince.y, Math.Abs(maxProvince.x - minProvince.x), Mathf.Abs(maxProvince.y - minProvince.y));
        }
コード例 #16
0
        public void SplitVertically()
        {
            if (entityIndex < 0 || entityIndex >= entities.Length)
            {
                return;
            }

            IAdminEntity currentEntity = entities [entityIndex];
            Region       currentRegion = currentEntity.regions [regionIndex];

            List <Vector2> half1    = new List <Vector2> ();
            List <Vector2> half2    = new List <Vector2> ();
            int            prevSide = 0;
            Vector2        q        = currentRegion.latlon [0];

            for (int k = 0; k < currentRegion.latlon.Length; k++)
            {
                Vector2 p = currentRegion.latlon [k];
                if (p.y > splitVerticallyAt)                   // compare longitudes
                {
                    if (prevSide == -1)
                    {
                        float   t = (splitVerticallyAt - q.y) / (p.y - q.y);
                        Vector2 r = Vector2.Lerp(q, p, t);
                        half1.Add(r);
                        half2.Add(r);
                    }
                    half1.Add(p);
                    q        = p;
                    prevSide = 1;
                }
                else
                {
                    if (prevSide == 1)
                    {
                        float   t = (splitVerticallyAt - q.y) / (p.y - q.y);
                        Vector2 r = Vector2.Lerp(q, p, t);
                        half1.Add(r);
                        half2.Add(r);
                    }
                    half2.Add(p);
                    q        = p;
                    prevSide = -1;
                }
            }
            // Setup new entity
            IAdminEntity newEntity;

            if (currentEntity is Country)
            {
                string name = map.GetCountryUniqueName("New " + currentEntity.name);
                newEntity = new Country(name, ((Country)currentEntity).continent);
            }
            else
            {
                string name = map.GetProvinceUniqueName("New " + currentEntity.name);
                newEntity         = new Province(name, ((Province)currentEntity).countryIndex);
                newEntity.regions = new List <Region> ();
            }

            // Update polygons
            Region newRegion = new Region(newEntity, 0);

            if (entities [countryIndex].latlonCenter.y > splitVerticallyAt)
            {
                currentRegion.latlon = half1.ToArray();
                newRegion.latlon     = half2.ToArray();
            }
            else
            {
                currentRegion.latlon = half2.ToArray();
                newRegion.latlon     = half1.ToArray();
            }
            map.RegionSanitize(currentRegion);
            map.RegionSmooth(currentRegion, 1.5f);
            map.RegionSanitize(newRegion);
            map.RegionSmooth(newRegion, 1.5f);

            newEntity.regions.Add(newRegion);
            int newEntityIndex = EntityAdd(newEntity);

            // Refresh old entity and selects the new
            if (currentEntity is Country)
            {
                map.RefreshCountryDefinition(newEntityIndex, null);
                map.RefreshCountryDefinition(countryIndex, null);
                SplitCities(countryIndex, newRegion);
                ClearSelection();
                RedrawFrontiers();
                countryIndex       = newEntityIndex;
                countryRegionIndex = 0;
                CountryRegionSelect();
                countryChanges = true;
                cityChanges    = true;
            }
            else
            {
                map.RefreshProvinceDefinition(newEntityIndex);
                map.RefreshProvinceDefinition(provinceIndex);
                highlightedRegions = null;
                ClearSelection();
                RedrawFrontiers();
                provinceIndex       = newEntityIndex;
                provinceRegionIndex = 0;
                countryIndex        = map.provinces [provinceIndex].countryIndex;
                countryRegionIndex  = map.countries [countryIndex].mainRegionIndex;
                CountryRegionSelect();
                ProvinceRegionSelect();
                provinceChanges = true;
            }
            map.RedrawMapLabels();
        }
コード例 #17
0
        /// <summary>
        /// Exports the geographic data in packed string format with reduced quality.
        /// </summary>
        public string GetCountryGeoDataLowQuality()
        {
            // step 1: duplicate data
            IAdminEntity[] entities;
            if (editingMode == EDITING_MODE.COUNTRIES)
            {
                entities = map.countries;
            }
            else
            {
                entities = map.provinces;
            }
            List <IAdminEntity> entities1 = new List <IAdminEntity>(entities);

            // step 1: prepare data structures
            for (int k = 0; k < entities1.Count; k++)
            {
                entities1[k].regions = new List <Region>(entities1[k].regions);
            }

            // step 2: catalog points
            int            totalPoints = 0;
            List <Vector2> allPoints   = new List <Vector2>(150000);

            for (int k = 0; k < entities1.Count; k++)
            {
                for (int r = 0; r < entities1[k].regions.Count; r++)
                {
                    Region region1 = entities1[k].regions[r];
                    totalPoints += region1.latlon.Length;
                    allPoints.AddRange(region1.latlon);
                }
            }

            allPoints = DouglasPeucker.SimplifyCurve(allPoints, 0.1);
            Dictionary <Vector2, bool> allPointsLookup = new Dictionary <Vector2, bool>(allPoints.Count);

            for (int k = 0; k < allPoints.Count; k++)
            {
                if (!allPointsLookup.ContainsKey(allPoints[k]))
                {
                    allPointsLookup.Add(allPoints[k], true);
                }
            }

            // step 3: reduce region points according to exclusion catalog
            int            savings     = 0;
            List <Vector2> goodLatLons = new List <Vector2>(15000);

            for (int k = 0; k < entities1.Count; k++)
            {
                for (int r = 0; r < entities1[k].regions.Count; r++)
                {
                    goodLatLons.Clear();
                    Region region = entities1[k].regions[r];
                    for (int p = 0; p < region.latlon.Length; p++)
                    {
                        Vector2 latlon = region.latlon[p];
                        if (allPointsLookup.ContainsKey(latlon))
                        {
                            goodLatLons.Add(latlon);
                        }
                    }
                    PolygonSanitizer.RemoveCrossingSegments(goodLatLons);
                    if (goodLatLons.Count < 5)
                    {
                        entities1[k].regions.Remove(region);
                        r--;
                    }
                    else
                    {
                        totalPoints  += region.latlon.Length;
                        savings      += (region.latlon.Length - goodLatLons.Count);
                        region.latlon = goodLatLons.ToArray();
                    }
                }
            }
            Debug.Log(savings + " points removed of " + totalPoints + " (" + (((float)savings / totalPoints) * 100.0f).ToString("F1") + "%)");

            StringBuilder sb = new StringBuilder();

            for (int k = 0; k < entities1.Count; k++)
            {
                IAdminEntity entity = entities1[k];
                if (entity.regions.Count == 0)
                {
                    continue;
                }
                if (k > 0)
                {
                    sb.Append("|");
                }
                sb.Append(entity.name + "$");
                if (entity is Country)
                {
                    sb.Append(((Country)entity).continent + "$");
                }
                else
                {
                    sb.Append(map.countries[((Province)entity).countryIndex].name + "$");
                }
                for (int r = 0; r < entity.regions.Count; r++)
                {
                    if (r > 0)
                    {
                        sb.Append("*");
                    }
                    Region region = entity.regions [r];
                    for (int p = 0; p < region.latlon.Length; p++)
                    {
                        if (p > 0)
                        {
                            sb.Append(";");
                        }
                        Vector2 point = region.latlon [p] * WorldMapGlobe.MAP_PRECISION;
                        sb.Append(Mathf.RoundToInt(point.x).ToString() + ",");
                        sb.Append(Mathf.RoundToInt(point.y).ToString());
                    }
                }
            }
            return(sb.ToString());
        }
コード例 #18
0
        /// <summary>
        /// Creates a new province with the given region
        /// </summary>
        public void ProvinceCreate(Region region)
        {
            if (region == null)
            {
                return;
            }

            // Remove region from source entity
            IAdminEntity entity = region.entity;

            if (entity != null)
            {
                entity.regions.Remove(region);
                Country country;
                // Refresh entity definition
                if (region.entity is Country)
                {
                    int countryIndex = _map.GetCountryIndex((Country)region.entity);
                    country = _map.countries [countryIndex];
                    _map.RefreshCountryGeometry(country);
                }
                else
                {
                    int provinceIndex = map.GetProvinceIndex((Province)region.entity);
                    country = _map.countries [_map.provinces [provinceIndex].countryIndex];
                    _map.RefreshProvinceGeometry(provinceIndex);
                }
            }

            provinceIndex       = map.provinces.Length;
            provinceRegionIndex = 0;
            string   newProvinceName = GetProvinceUniqueName("New Province");
            Province newProvince     = new Province(newProvinceName, countryIndex, map.GetUniqueId(new List <IExtendableAttribute> (map.provinces)));
            Region   newRegion       = new Region(newProvince, 0);

            newRegion.UpdatePointsAndRect(region.points);
            newProvince.regions = new List <Region> ();
            newProvince.regions.Add(newRegion);
            map.ProvinceAdd(newProvince);
            map.RefreshProvinceDefinition(provinceIndex, false);

            // Update cities
            List <City> cities      = _map.GetCities(region);
            int         citiesCount = cities.Count;

            if (citiesCount > 0)
            {
                for (int k = 0; k < citiesCount; k++)
                {
                    if (cities [k].province != newProvinceName)
                    {
                        cities [k].province = newProvinceName;
                        cityChanges         = true;
                    }
                }
            }

            lastProvinceCount = -1;
            GUIProvinceName   = newProvince.name;
            SyncGUIProvinceSelection();
            ProvinceRegionSelect();
            provinceChanges = true;
        }
コード例 #19
0
        /// <summary>
        /// Used internally by the Map Editor. It will recalculate de boundaries and optimize frontiers based on new data of countries array
        /// </summary>
        public void RefreshCountryGeometry(IAdminEntity country)
        {
            float maxVol = 0;

            if (country.regions == null)
            {
                return;
            }
            int     regionCount = country.regions.Count;
            Vector2 min         = Misc.Vector2one * 10;
            Vector2 max         = -min;
            Vector2 minCountry  = Misc.Vector2one * 10;
            Vector2 maxCountry  = -minCountry;

            for (int r = 0; r < regionCount; r++)
            {
                Region countryRegion = country.regions [r];
                if (countryRegion.points == null)
                {
                    continue;
                }
                countryRegion.entity      = country;            // just in case one country has been deleted
                countryRegion.regionIndex = r;                  // just in case a region has been deleted
                int coorCount = countryRegion.points.Length;
                min.x = min.y = 10f;
                max.x = max.y = -10;
                for (int c = 0; c < coorCount; c++)
                {
                    float x = countryRegion.points [c].x;
                    float y = countryRegion.points [c].y;
                    if (x < min.x)
                    {
                        min.x = x;
                    }
                    if (x > max.x)
                    {
                        max.x = x;
                    }
                    if (y < min.y)
                    {
                        min.y = y;
                    }
                    if (y > max.y)
                    {
                        max.y = y;
                    }
                }
                FastVector.Average(ref min, ref max, ref countryRegion.center);                  // countryRegion.center = (min + max) * 0.5f;

                // Calculate country bounding rect
                if (min.x < minCountry.x)
                {
                    minCountry.x = min.x;
                }
                if (min.y < minCountry.y)
                {
                    minCountry.y = min.y;
                }
                if (max.x > maxCountry.x)
                {
                    maxCountry.x = max.x;
                }
                if (max.y > maxCountry.y)
                {
                    maxCountry.y = max.y;
                }
                // Calculate bounding rect
                countryRegion.rect2D     = new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
                countryRegion.rect2DArea = countryRegion.rect2D.width * countryRegion.rect2D.height;
                float vol = FastVector.SqrDistance(ref max, ref min);                  // (max - min).sqrMagnitude;
                if (vol > maxVol)
                {
                    maxVol = vol;
                    country.mainRegionIndex = r;
                    country.center          = countryRegion.center;
                }
            }
            country.regionsRect2D = new Rect(minCountry.x, minCountry.y, Math.Abs(maxCountry.x - minCountry.x), Mathf.Abs(maxCountry.y - minCountry.y));
        }
コード例 #20
0
        /// <summary>
        /// For each two points, locate a third point belonging to a different region which is not conected to them and below threshold. Add a new point at that position.
        /// </summary>
        void PolishRegionJoints(Region region)
        {
            int     regionPointsCount = region.points.Length;
            int     entitiesCount     = entities.Count;
            Vector2 midP = Misc.Vector3zero;

            for (int k = 0; k < regionPointsCount; k++)
            {
                Vector2 p0             = region.points [k];
                int     nextPointIndex = k == regionPointsCount - 1 ? 0 : k + 1;
                Vector2 p1             = region.points [nextPointIndex];
                float   p01d           = (p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y);
                bool    snapped        = false;
                for (int e = 0; e < entitiesCount && !snapped; e++)
                {
                    IAdminEntity entity = entities [e];
                    if (entity.regions == null)
                    {
                        continue;
                    }
                    int entityRegionsCount = entity.regions.Count;
                    for (int r = 0; r < entityRegionsCount && !snapped; r++)
                    {
                        Region entityRegion = entity.regions [r];
                        if (entityRegion == region)
                        {
                            continue;
                        }
                        int entityRegionsPointsCount = entityRegion.points.Length;
                        for (int j = 0; j < entityRegionsPointsCount; j++)
                        {
                            Vector2 v = entityRegion.points [j];
                            float   d = (v.x - p0.x) * (v.x - p0.x) + (v.y - p0.y) * (v.y - p0.y);
                            if (d > 0 && d < p01d)
                            {
                                d = (v.x - p1.x) * (v.x - p1.x) + (v.y - p1.y) * (v.y - p1.y);
                                if (d > 0 && d < p01d)
                                {
                                    // make sure center of triangle is not contained by any region (that would mean the change would create overlap)
                                    midP.x = (p0.x + p1.x + v.x) / 3f;
                                    midP.y = (p0.y + p1.y + v.y) / 3f;
                                    if (!AnyRegionContainsPoint(midP))
                                    {
                                        // Insert point v in k+1 position
                                        int       rpCount   = region.points.Length;
                                        Vector2[] newPoints = new Vector2[rpCount + 1];
                                        int       np        = -1;
                                        for (int i = 0; i < rpCount; i++)
                                        {
                                            ++np;
                                            if (np == nextPointIndex)
                                            {
                                                newPoints [np] = v;
                                                np++;
                                            }
                                            newPoints [np] = region.points [i];
                                        }
                                        region.points = newPoints;
                                        snapped       = true;
                                        regionPointsCount++;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #21
0
        /// <summary>
        /// Moves points of other regions towards current frontier
        /// </summary>
        public bool Magnet(Vector3 position, float circleSize)
        {
            if (entityIndex < 0 || entityIndex >= entities.Length)
            {
                return(false);
            }

            Region currentRegion = entities [entityIndex].regions [regionIndex];
            float  circleSizeSqr = circleSize * circleSize;

            Dictionary <Vector3, bool> attractorsUse = new Dictionary <Vector3, bool> ();
            // Attract points of other regions/countries
            List <Region> regions = new List <Region> ();

            for (int c = 0; c < entities.Length; c++)
            {
                IAdminEntity entity = entities [c];
                if (entity.regions == null)
                {
                    continue;
                }
                for (int r = 0; r < entity.regions.Count; r++)
                {
                    if (c != entityIndex || r != regionIndex)
                    {
                        regions.Add(entities [c].regions [r]);
                    }
                }
            }
            if (editingMode == EDITING_MODE.PROVINCES)
            {
                // Also add regions of current country and neighbours
                for (int r = 0; r < map.countries [countryIndex].regions.Count; r++)
                {
                    Region region = map.countries [countryIndex].regions [r];
                    regions.Add(region);
                    for (int n = 0; n < region.neighbours.Count; n++)
                    {
                        Region nregion = region.neighbours [n];
                        if (!regions.Contains(nregion))
                        {
                            regions.Add(nregion);
                        }
                    }
                }
            }

            bool    changes       = false;
            Vector3 goodAttractor = Misc.Vector3zero;

            for (int r = 0; r < regions.Count; r++)
            {
                Region region = regions [r];
                bool   changesInThisRegion = false;
                for (int p = 0; p < region.spherePoints.Length; p++)
                {
                    Vector3 rp   = region.spherePoints [p];
                    float   dist = (rp - position).sqrMagnitude;
                    if (dist < circleSizeSqr)
                    {
                        float minDist = float.MaxValue;
                        int   nearest = -1;
                        for (int a = 0; a < currentRegion.spherePoints.Length; a++)
                        {
                            Vector3 attractor = currentRegion.spherePoints [a];
                            dist = (rp - attractor).sqrMagnitude;
                            if (dist < circleSizeSqr && dist < minDist)
                            {
                                minDist       = dist;
                                nearest       = a;
                                goodAttractor = attractor;
                            }
                        }
                        if (nearest >= 0)
                        {
                            changes = true;
                            // Check if this attractor is being used by other point
                            bool used = attractorsUse.ContainsKey(goodAttractor);
                            if (!used || magnetAgressiveMode)
                            {
                                region.spherePoints [p] = goodAttractor;
                                if (!used)
                                {
                                    attractorsUse.Add(goodAttractor, true);
                                }
                                changesInThisRegion = true;
                            }
                        }
                    }
                }
                if (changesInThisRegion)
                {
                    // Remove duplicate points in this region
                    Dictionary <Vector3, bool> repeated = new Dictionary <Vector3, bool> ();
                    for (int k = 0; k < region.spherePoints.Length; k++)
                    {
                        if (!repeated.ContainsKey(region.spherePoints [k]))
                        {
                            repeated.Add(region.spherePoints [k], true);
                        }
                    }
                    region.spherePoints = new List <Vector3> (repeated.Keys).ToArray();
                }
            }
            return(changes);
        }
コード例 #22
0
        public void SplitHorizontally()
        {
            if (entityIndex < 0 || entityIndex >= entities.Length)
            {
                return;
            }

            IAdminEntity   currentEntity = entities [entityIndex];
            Region         currentRegion = currentEntity.regions [regionIndex];
            Vector2        center        = currentRegion.center;
            List <Vector3> half1         = new List <Vector3> ();
            List <Vector3> half2         = new List <Vector3> ();
            int            prevSide      = 0;

            for (int k = 0; k < currentRegion.points.Length; k++)
            {
                Vector3 p = currentRegion.points [k];
                if (p.y > currentRegion.center.y)
                {
                    half1.Add(p);
                    if (prevSide == -1)
                    {
                        half2.Add(p);
                    }
                    prevSide = 1;
                }
                if (p.y <= currentRegion.center.y)
                {
                    half2.Add(p);
                    if (prevSide == 1)
                    {
                        half1.Add(p);
                    }
                    prevSide = -1;
                }
            }
            // Setup new entity
            IAdminEntity newEntity;

            if (currentEntity is Country)
            {
                newEntity = new Country("New " + currentEntity.name, ((Country)currentEntity).continent);
            }
            else
            {
                newEntity         = new Province("New " + currentEntity.name, ((Province)currentEntity).countryIndex);
                newEntity.regions = new List <Region> ();
            }
            EntityAdd(newEntity);

            // Update polygons
            Region newRegion = new Region(newEntity, 0);

            if (entities [countryIndex].center.y > center.y)
            {
                currentRegion.points = half1.ToArray();
                newRegion.points     = half2.ToArray();
            }
            else
            {
                currentRegion.points = half2.ToArray();
                newRegion.points     = half1.ToArray();
            }
            newEntity.regions.Add(newRegion);

            // Refresh old entity and selects the new
            if (currentEntity is Country)
            {
                map.RefreshCountryDefinition(countryIndex, highlightedRegions);
                countryIndex       = map.countries.Length - 1;
                countryRegionIndex = 0;
            }
            else
            {
                map.RefreshProvinceDefinition(provinceIndex);
                provinceIndex       = map.provinces.Length - 1;
                provinceRegionIndex = 0;
            }

            // Refresh lines
            highlightedRegions.Add(newRegion);
            RedrawFrontiers();
            map.RedrawMapLabels();
        }
コード例 #23
0
        IEnumerator AssignRegionCenters(IAdminEntity[] entities)
        {
            List <Region> regions = new List <Region> ();

            for (int k = 0; k < entities.Length; k++)
            {
                IAdminEntity entity = entities [k];
                int          rCount = entity.regions.Count;
                for (int r = 0; r < rCount; r++)
                {
                    Region region = entity.regions [r];
                    if (region.points.Length > 0)
                    {
                        regions.Add(region);
                    }
                }
            }
            regions.Sort((Region x, Region y) => {
                return(y.rect2DArea.CompareTo(x.rect2DArea));
            });

            int regionsCount = regions.Count;

            for (int r = 0; r < regionsCount; r++)
            {
                Region region    = regions [r];
                int    cellIndex = _map.GetCellIndex(region.center);
                if (cellIndex >= 0 && procCells [cellIndex].entityIndex < 0)
                {
                    IAdminEntity entity = region.entity;
                    if (entity is Country)
                    {
                        procCells [cellIndex].entityIndex = _map.GetCountryIndex((Country)region.entity);
                    }
                    else
                    {
                        procCells [cellIndex].entityIndex = _map.GetProvinceIndex((Province)region.entity);
                    }
                    procCells [cellIndex].entityRegion = region;
                }
            }

            // Pass 2: iterate all frontier points
            for (int c = 0; c < entities.Length; c++)
            {
                if (c % 10 == 0)
                {
                    if (hexifyContext.progress != null)
                    {
                        if (hexifyContext.progress((float)c / entities.Length, hexifyContext.title, "Pass 2/6: assigning centers..."))
                        {
                            cancelled = true;
                            hexifyContext.finish(true);
                            yield break;
                        }
                    }
                    yield return(null);
                }
                IAdminEntity entity = entities [c];
                int          rCount = entity.regions.Count;
                for (int cr = 0; cr < rCount; cr++)
                {
                    Region region = entity.regions [cr];
                    for (int p = 0; p < region.points.Length; p++)
                    {
                        int cellIndex = _map.GetCellIndex(region.points [p]);
                        if (cellIndex >= 0 && procCells [cellIndex].entityIndex < 0)
                        {
                            procCells [cellIndex].entityIndex  = c;
                            procCells [cellIndex].entityRegion = region;
                        }
                    }
                }
            }
        }
コード例 #24
0
        /// <summary>
        /// Exports the geographic data in packed string format with reduced quality.
        /// </summary>
        public string GetCountryGeoDataLowQuality()
        {
            // step 1: duplicate data
            IAdminEntity[] entities;
            if (editingMode == EDITING_MODE.COUNTRIES)
            {
                entities = map.countries;
            }
            else
            {
                entities = map.provinces;
            }
            List <IAdminEntity> entities1 = new List <IAdminEntity> (entities);

            for (int k = 0; k < entities1.Count; k++)
            {
                entities1 [k].regions = new List <Region> (entities1 [k].regions);
                for (int r = 0; r < entities [k].regions.Count; r++)
                {
                    entities1 [k].regions [r].points = new List <Vector3> (entities1 [k].regions [r].points).ToArray();
                }
            }
            // step 2: ensure near points between neighbours
            float MAX_DIST = 0.00000001f;

            //			int join = 0;
            for (int k = 0; k < entities1.Count; k++)
            {
                for (int r = 0; r < entities1 [k].regions.Count; r++)
                {
                    Region region1 = entities1 [k].regions [r];
                    for (int p = 0; p < entities1 [k].regions [r].points.Length; p++)
                    {
                        // Search near points
                        for (int k2 = 0; k2 < region1.neighbours.Count; k2++)
                        {
                            for (int r2 = 0; r2 < entities1 [k2].regions.Count; r2++)
                            {
                                Region region2 = entities1 [k2].regions [r2];
                                for (int p2 = 0; p2 < entities1 [k2].regions [r2].points.Length; p2++)
                                {
                                    float dist = (region1.points [p].x - region2.points [p2].x) * (region1.points [p].x - region2.points [p2].x) +
                                                 (region1.points [p].y - region2.points [p2].y) * (region1.points [p].y - region2.points [p2].y);
                                    if (dist < MAX_DIST)
                                    {
                                        region2.points [p2] = region1.points [p];
                                        //										join++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            //			if (join>0)
            //				Debug.Log (join + " points fused.");


            // step 2: simplify
            Dictionary <Vector2, bool> frontiersHit = new Dictionary <Vector2, bool> ();
            List <IAdminEntity>        entities2 = new List <IAdminEntity> (entities1.Count);
            int   savings = 0, totalPoints = 0;
            float FACTOR = 1000f;

            for (int k = 0; k < entities1.Count; k++)
            {
                IAdminEntity refEntity = entities1 [k];
                IAdminEntity newEntity;
                if (refEntity is Country)
                {
                    newEntity = new Country(refEntity.name, ((Country)refEntity).continent);
                }
                else
                {
                    newEntity = new Province(refEntity.name, ((Province)refEntity).countryIndex);
                }
                for (int r = 0; r < refEntity.regions.Count; r++)
                {
                    Region region    = refEntity.regions [r];
                    int    numPoints = region.points.Length;
                    totalPoints += numPoints;
                    List <Vector3> points = new List <Vector3> (numPoints);
                    frontiersHit.Clear();

                    Vector3[] blockyPoints = new Vector3[numPoints];
                    for (int p = 0; p < numPoints; p++)
                    {
                        blockyPoints [p] = new Vector2(Mathf.RoundToInt(region.points [p].x * FACTOR) / FACTOR, Mathf.RoundToInt(region.points [p].y * FACTOR) / FACTOR);
                    }

                    points.Add(region.points [0] * WorldMap2D.MAP_PRECISION);
                    for (int p = 1; p < numPoints - 1; p++)
                    {
                        if (blockyPoints [p - 1].y == blockyPoints [p].y && blockyPoints [p].y == blockyPoints [p + 1].y ||
                            blockyPoints [p - 1].x == blockyPoints [p].x && blockyPoints [p].x == blockyPoints [p + 1].x)
                        {
                            savings++;
                            continue;
                        }
                        if (!frontiersHit.ContainsKey(blockyPoints [p]))                                                                                                                                                                            // add neighbour references
                        {
                            frontiersHit.Add(blockyPoints [p], true);
                            points.Add(region.points [p] * WorldMap2D.MAP_PRECISION);
                        }
                        else
                        {
                            savings++;
                        }
                    }
                    points.Add(region.points [numPoints - 1] * WorldMap2D.MAP_PRECISION);
                    if (points.Count >= 5)
                    {
                        Region newRegion = new Region(newEntity, newEntity.regions.Count);
                        newRegion.points = points.ToArray();
                        newEntity.regions.Add(newRegion);
                    }
                }
                if (newEntity.regions.Count > 0)
                {
                    entities2.Add(newEntity);
                }
            }

            Debug.Log(savings + " points removed of " + totalPoints + " (" + (((float)savings / totalPoints) * 100.0f).ToString("F1") + "%)");

            StringBuilder sb = new StringBuilder();

            for (int k = 0; k < entities2.Count; k++)
            {
                IAdminEntity entity = entities2 [k];
                if (k > 0)
                {
                    sb.Append("|");
                }
                sb.Append(entity.name + "$");
                if (entity is Country)
                {
                    sb.Append(((Country)entity).continent + "$");
                }
                else
                {
                    sb.Append(map.countries [((Province)entity).countryIndex].name + "$");
                }
                for (int r = 0; r < entity.regions.Count; r++)
                {
                    if (r > 0)
                    {
                        sb.Append("*");
                    }
                    Region region = entity.regions [r];
                    for (int p = 0; p < region.points.Length; p++)
                    {
                        if (p > 0)
                        {
                            sb.Append(";");
                        }
                        Vector2 point = region.points [p];
                        sb.Append(point.x.ToString(CultureInfo.InvariantCulture) + ",");
                        sb.Append(point.y.ToString(CultureInfo.InvariantCulture));
                    }
                }
            }
            return(sb.ToString());
        }
コード例 #25
0
        /// <summary>
        /// Creates a new country based on a given region. Existing region is removed from its source entity.
        /// </summary>
        /// <param name="region">Region.</param>
        public void CountryCreate(Region region)
        {
            // Remove region from source entity
            IAdminEntity entity = region.entity;

            entity.regions.Remove(region);
            Country country;

            // Refresh entity definition
            if (region.entity is Country)
            {
                int cIndex = _map.GetCountryIndex((Country)region.entity);
                country = _map.countries [cIndex];
                _map.RefreshCountryGeometry(cIndex);
            }
            else
            {
                int provinceIndex = map.GetProvinceIndex((Province)region.entity);
                country = _map.countries [_map.provinces [provinceIndex].countryIndex];
                _map.RefreshProvinceGeometry(provinceIndex);
            }

            // Create the new country indeed
            string  uniqueName = GetCountryUniqueName(country.name);
            Country newCountry = new Country(uniqueName, country.continent);

            if (entity is Country)
            {
                newCountry.regions.Add(region);
            }
            else
            {
                Region newRegion = new Region(newCountry, 0);
                newRegion.UpdatePointsAndRect(region.points);
                newCountry.regions.Add(newRegion);
            }
            countryIndex       = map.CountryAdd(newCountry);
            countryRegionIndex = 0;
            map.RefreshCountryDefinition(countryIndex, null);
            lastCountryCount = -1;
            GUICountryName   = "";
            ReloadCountryNames();
            countryChanges = true;

            // Update cities
            List <City> cities = _map.GetCities(region);

            if (cities.Count > 0)
            {
                cityChanges = true;
                for (int k = 0; k < cities.Count; k++)
                {
                    cities [k].countryIndex = countryIndex;
                }
            }

            // Update mount points
            List <MountPoint> mp = _map.GetMountPoints(region);

            if (mp.Count > 0)
            {
                mountPointChanges = true;
                for (int k = 0; k < mp.Count; k++)
                {
                    mp [k].countryIndex = countryIndex;
                }
            }

            // Transfer any contained province
            if (entity is Country)
            {
                List <Province> provinces = _map.GetProvinces(region);
                for (int k = 0; k < provinces.Count; k++)
                {
                    Province prov = provinces [k];
                    if (prov.regions == null)
                    {
                        _map.ReadProvincePackedString(prov);
                    }
                    if (prov.regions == null)
                    {
                        continue;
                    }
                    int pIndex = _map.GetProvinceIndex(prov);
                    ProvinceTransferTo(countryIndex, pIndex);
                    provinceChanges = true;
                }
            }

            map.Redraw();
            CountryRegionSelect();
        }
コード例 #26
0
        public void SplitVertically()
        {
            if (entityIndex < 0 || entityIndex >= entities.Length)
            {
                return;
            }

            IAdminEntity   currentEntity = entities[entityIndex];
            Region         currentRegion = currentEntity.regions[regionIndex];
            Vector3        center        = currentRegion.center;
            List <Vector3> half1         = new List <Vector3>();
            List <Vector3> half2         = new List <Vector3>();
            int            prevSide      = 0;
            double         centerX       = (currentRegion.minMaxLon.x + currentRegion.minMaxLon.y) * 0.5;

            for (int k = 0; k < currentRegion.latlon.Length; k++)
            {
                Vector3      p      = currentRegion.points[k];
                PolygonPoint latlon = currentRegion.latlon[k];
                if (latlon.Y > centerX)                 // compare longitudes
                {
                    half1.Add(p);
                    if (prevSide == -1)
                    {
                        half2.Add(p);
                    }
                    prevSide = 1;
                }
                if (latlon.Y <= centerX)
                {
                    half2.Add(p);
                    if (prevSide == 1)
                    {
                        half1.Add(p);
                    }
                    prevSide = -1;
                }
            }

            // Setup new entity
            IAdminEntity newEntity;

            if (currentEntity is Country)
            {
                newEntity = new Country("New " + currentEntity.name, ((Country)currentEntity).continent);
            }
            else
            {
                newEntity         = new Province("New " + currentEntity.name, ((Province)currentEntity).countryIndex);
                newEntity.regions = new List <Region>();
            }
            EntityAdd(newEntity);

            // Update polygons
            Region newRegion = new Region(newEntity, 0);

            if (entities[countryIndex].center.x > center.x)
            {
                currentRegion.points = half1.ToArray();
                newRegion.points     = half2.ToArray();
            }
            else
            {
                currentRegion.points = half2.ToArray();
                newRegion.points     = half1.ToArray();
            }
            UpdateLatLonFromPoints(currentRegion);
            UpdateLatLonFromPoints(newRegion);
            newEntity.regions.Add(newRegion);

            // Refresh old entity and selects the new
            if (currentEntity is Country)
            {
                map.RefreshCountryDefinition(countryIndex, highlightedRegions);
                countryIndex       = map.countries.Length - 1;
                countryRegionIndex = 0;
            }
            else
            {
                map.RefreshProvinceDefinition(provinceIndex);
                provinceIndex       = map.provinces.Length - 1;
                provinceRegionIndex = 0;
            }

            // Refresh lines
            highlightedRegions.Add(newRegion);
            RedrawFrontiers();
            map.RedrawMapLabels();
        }
コード例 #27
0
        /// <summary>
        /// Unpacks province geodata information. Used by Map Editor.
        /// </summary>
        /// <param name="province">Province.</param>
        public void ReadProvincePackedString(IAdminEntity entity)
        {
            Province province = (Province)entity;

            if (province == null || province.packedRegions == null)
            {
                return;
            }
            string[] regions     = province.packedRegions.Split(SPLIT_SEP_ASTERISK, StringSplitOptions.RemoveEmptyEntries);
            int      regionCount = regions.Length;

            province.regions = new List <Region> (regionCount);
            float   maxVol      = float.MinValue;
            Vector2 minProvince = Misc.Vector2one * 10;
            Vector2 maxProvince = -minProvince;

            for (int r = 0; r < regionCount; r++)
            {
                string[] coordinates    = regions [r].Split(SPLIT_SEP_SEMICOLON, StringSplitOptions.RemoveEmptyEntries);
                int      coorCount      = coordinates.Length;
                Vector2  min            = Misc.Vector2one * 10;
                Vector2  max            = -min;
                Region   provinceRegion = new Region(province, province.regions.Count);
                provinceRegion.points = new Vector2[coorCount];
                for (int c = 0; c < coorCount; c++)
                {
                    float x, y;
                    GetPointFromPackedString(ref coordinates [c], out x, out y);
                    if (x < min.x)
                    {
                        min.x = x;
                    }
                    if (x > max.x)
                    {
                        max.x = x;
                    }
                    if (y < min.y)
                    {
                        min.y = y;
                    }
                    if (y > max.y)
                    {
                        max.y = y;
                    }
                    provinceRegion.points [c].x = x;
                    provinceRegion.points [c].y = y;
                }
                FastVector.Average(ref min, ref max, ref provinceRegion.center);
                provinceRegion.sanitized = true;
                province.regions.Add(provinceRegion);

                // Calculate province bounding rect
                if (min.x < minProvince.x)
                {
                    minProvince.x = min.x;
                }
                if (min.y < minProvince.y)
                {
                    minProvince.y = min.y;
                }
                if (max.x > maxProvince.x)
                {
                    maxProvince.x = max.x;
                }
                if (max.y > maxProvince.y)
                {
                    maxProvince.y = max.y;
                }
                provinceRegion.rect2D     = new Rect(min.x, min.y, max.x - min.x, max.y - min.y);
                provinceRegion.rect2DArea = provinceRegion.rect2D.width * provinceRegion.rect2D.height;
                float vol = FastVector.SqrDistance(ref min, ref max);                  // (max - min).sqrMagnitude;
                if (vol > maxVol)
                {
                    maxVol = vol;
                    province.mainRegionIndex = r;
                    province.center          = provinceRegion.center;
                }
            }
            province.regionsRect2D = new Rect(minProvince.x, minProvince.y, Math.Abs(maxProvince.x - minProvince.x), Mathf.Abs(maxProvince.y - minProvince.y));
        }
コード例 #28
0
        public void SplitHorizontally()
        {
            if (entityIndex < 0 || entityIndex >= entities.Length)
            {
                return;
            }

            IAdminEntity currentEntity = entities[entityIndex];
            Region       currentRegion = currentEntity.regions[regionIndex];
            float        centerY       = currentRegion.latlonCenter.x; // (currentRegion.minMaxLon.x + currentRegion.minMaxLon.y)*0.5;

            List <Vector2> half1    = new List <Vector2>();
            List <Vector2> half2    = new List <Vector2>();
            int            prevSide = 0;

            for (int k = 0; k < currentRegion.latlon.Length; k++)
            {
                Vector2 p = currentRegion.latlon[k];
                if (p.x > centerY)
                {
                    half1.Add(p);
                    if (prevSide == -1)
                    {
                        half2.Add(p);
                    }
                    prevSide = 1;
                }
                else
                {
                    half2.Add(p);
                    if (prevSide == 1)
                    {
                        half1.Add(p);
                    }
                    prevSide = -1;
                }
            }
            // Setup new entity
            IAdminEntity newEntity;

            if (currentEntity is Country)
            {
                string name = map.GetCountryUniqueName("New " + currentEntity.name);
                newEntity = new Country(name, ((Country)currentEntity).continent);
            }
            else
            {
                string name = map.GetProvinceUniqueName("New " + currentEntity.name);
                newEntity         = new Province(name, ((Province)currentEntity).countryIndex);
                newEntity.regions = new List <Region>();
            }

            // Update polygons
            Region newRegion = new Region(newEntity, 0);

            if (entities[countryIndex].latlonCenter.x > centerY)
            {
                currentRegion.latlon = half1.ToArray();
                newRegion.latlon     = half2.ToArray();
            }
            else
            {
                currentRegion.latlon = half2.ToArray();
                newRegion.latlon     = half1.ToArray();
            }
            map.RegionSanitize(currentRegion);
            SmoothRegion(currentRegion);
            map.RegionSanitize(newRegion);
            SmoothRegion(newRegion);

            newEntity.regions.Add(newRegion);
            int newEntityIndex = EntityAdd(newEntity);

            // Refresh old entity and selects the new
            if (currentEntity is Country)
            {
                map.RefreshCountryDefinition(newEntityIndex, null);
                map.RefreshCountryDefinition(countryIndex, null);
                SplitCities(countryIndex, newRegion);
                ClearSelection();
                RedrawFrontiers();
                countryIndex       = newEntityIndex;
                countryRegionIndex = 0;
                CountryRegionSelect();
                countryChanges = true;
                cityChanges    = true;
            }
            else
            {
                map.RefreshProvinceDefinition(newEntityIndex);
                map.RefreshProvinceDefinition(provinceIndex);
                highlightedRegions = null;
                ClearSelection();
                RedrawFrontiers();
                provinceIndex       = newEntityIndex;
                provinceRegionIndex = 0;
                countryIndex        = map.provinces[provinceIndex].countryIndex;
                countryRegionIndex  = map.countries[countryIndex].mainRegionIndex;
                CountryRegionSelect();
                ProvinceRegionSelect();
                provinceChanges = true;
            }
            map.RedrawMapLabels();
        }