/// <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();
        }
        /// <summary>
        /// Makes one country region to annex another country
        /// </summary>
        public void CountryRegionTransferTo()
        {
            if (countryIndex < 0 || GUICountryTransferToCountryIndex < 0 || GUICountryTransferToCountryIndex >= countryNames.Length || countryRegionIndex < 0)
            {
                return;
            }

            // Get target country
            // recover GUI country index selection
            int targetCountryIndex = -1;

            string[] s = countryNames [GUICountryTransferToCountryIndex].Split(new char[] {
                '(',
                ')'
            }, System.StringSplitOptions.RemoveEmptyEntries);
            if (s.Length >= 2)
            {
                if (!int.TryParse(s [1], out targetCountryIndex))
                {
                    return;
                }
            }

            Country sourceCountry = map.countries [countryIndex];
            Country targetCountry = map.countries [targetCountryIndex];
            Region  sourceRegion  = sourceCountry.regions [countryRegionIndex];
            Region  targetRegion  = targetCountry.regions [targetCountry.mainRegionIndex];

            // Transfer all provinces records to target country
            if (targetCountry.provinces == null && !map.showProvinces)
            {
                map.showProvinces = true;                                                                                                                 // Forces loading of provinces
                map.showProvinces = false;
            }
            if (sourceCountry.provinces != null)
            {
                List <Province> destProvinces;
                if (targetCountry.provinces != null)
                {
                    destProvinces = new List <Province> (targetCountry.provinces);
                }
                else
                {
                    destProvinces = new List <Province> ();
                }
                List <Province> sourceProvinces = new List <Province> (sourceCountry.provinces);
                for (int k = 0; k < sourceCountry.provinces.Length; k++)
                {
                    Province province = sourceCountry.provinces [k];
                    if (sourceRegion.Contains(province.center))
                    {
                        province.countryIndex = targetCountryIndex;
                        destProvinces.Add(province);
                        sourceProvinces.Remove(province);
                        provinceChanges = true;
                    }
                }
                sourceCountry.provinces = sourceProvinces.ToArray();
                targetCountry.provinces = destProvinces.ToArray();
            }

            // Add region to target country's polygon - only if the province is touching or crossing target country frontier
            PolygonClipper pc = new PolygonClipper(targetRegion, sourceRegion);

            if (pc.OverlapsSubjectAndClipping())
            {
                pc.Compute(PolygonOp.UNION);
            }
            else
            {
                // Add new region to country
                Region newCountryRegion = new Region(targetCountry, targetCountry.regions.Count);
                newCountryRegion.points = new List <Vector3> (sourceRegion.points).ToArray();
                targetCountry.regions.Add(newCountryRegion);
            }

            // Transfer cities & mount points
            TransferRegionCities(countryIndex, sourceRegion, targetCountryIndex);
            TransferRegionMountPoints(countryIndex, sourceRegion, targetCountryIndex);

            // Remove region from source country
            sourceCountry.regions.Remove(sourceRegion);

            // Finish operation
            map.HideCountryRegionHighlights(true);
            map.HideProvinceRegionHighlights(true);
            map.RefreshCountryDefinition(countryIndex, null);
            map.RefreshCountryDefinition(targetCountryIndex, null);
            countryChanges     = true;
            countryIndex       = targetCountryIndex;
            countryRegionIndex = targetCountry.mainRegionIndex;
            CountryRegionSelect();
            map.RedrawMapLabels();
        }
        /// <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());
        }
        public bool GetVertexNearSpherePos(Vector3 mapPos, out Vector2 nearPoint)
        {
            // Iterate country regions
            int     numCountries = _map.countries.Length;
            Vector2 np           = mapPos;
            float   minDist      = float.MaxValue;

            // Countries
            for (int c = 0; c < numCountries; c++)
            {
                Country country  = _map.countries [c];
                int     regCount = country.regions.Count;
                for (int cr = 0; cr < regCount; cr++)
                {
                    Region region     = country.regions [cr];
                    int    pointCount = region.points.Length;
                    for (int p = 0; p < pointCount; p++)
                    {
                        float dist = (mapPos - region.points [p]).sqrMagnitude;
                        if (dist < minDist)
                        {
                            minDist = dist;
                            np      = region.points [p];
                        }
                    }
                }
            }
            // Provinces
            if (_map.editor.editingMode == EDITING_MODE.PROVINCES)
            {
                int numProvinces = _map.provinces.Length;
                for (int p = 0; p < numProvinces; p++)
                {
                    Province province = _map.provinces [p];
                    if (province.regions == null)
                    {
                        _map.ReadProvincePackedString(province);
                    }
                    if (province.regions == null)
                    {
                        continue;
                    }
                    int regCount = province.regions.Count;
                    for (int pr = 0; pr < regCount; pr++)
                    {
                        Region region     = province.regions [pr];
                        int    pointCount = region.points.Length;
                        for (int po = 0; po < pointCount; po++)
                        {
                            float dist = (mapPos - region.points [po]).sqrMagnitude;
                            if (dist < minDist)
                            {
                                minDist = dist;
                                np      = region.points [p];
                            }
                        }
                    }
                }
            }

            nearPoint = np;
            return(nearPoint.x != mapPos.x || nearPoint.y != mapPos.y);
        }
        public void SplitVertically()
        {
            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.x > currentRegion.center.x)
                {
                    half1.Add(p);
                    if (prevSide == -1)
                    {
                        half2.Add(p);
                    }
                    prevSide = 1;
                }
                if (p.x <= currentRegion.center.x)
                {
                    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();
            }
            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();
        }
Exemple #6
0
        /// <summary>
        /// Separates a province from its current country producing a new country
        /// </summary>
        public void ProvinceSeparate(string newCountryName)
        {
            if (provinceIndex < 0 || provinceIndex >= map.provinces.Length)
            {
                return;
            }

            // Remove province form source country
            Province province      = map.provinces [provinceIndex];
            Country  sourceCountry = map.countries [countryIndex];

            if (map.countries [countryIndex].provinces != null)
            {
                List <Province> sourceProvinces = new List <Province> (sourceCountry.provinces);
                int             provIndex       = -1;
                for (int k = 0; k < sourceCountry.provinces.Length; k++)
                {
                    if (sourceCountry.provinces [k].name.Equals(province.name))
                    {
                        provIndex = k;
                    }
                }
                if (provIndex >= 0)
                {
                    sourceProvinces.RemoveAt(provIndex);
                    sourceCountry.provinces = sourceProvinces.ToArray();
                }
            }

            // Adds province region to a new country
            Region  regionProvince = province.regions [provinceRegionIndex];
            Country targetCountry  = new Country(newCountryName, sourceCountry.continent);
            Region  region         = new Region(targetCountry, 0);

            region.points = new List <Vector3> (regionProvince.points).ToArray();
            targetCountry.regions.Add(region);
            map.CountryAdd(targetCountry);
            int targetCountryIndex = map.countries.Length - 1;

            map.RefreshCountryDefinition(targetCountryIndex, null);
            lastCountryCount = -1;

            // Add province to the new country
            if (targetCountry.provinces == null)
            {
                targetCountry.provinces = new Province[0];
            }
            List <Province> destProvinces = new List <Province> (targetCountry.provinces);

            destProvinces.Add(province);
            targetCountry.provinces = destProvinces.ToArray();

            // Apply boolean operations on country polygons
            Region provinceRegion = province.regions [provinceRegionIndex];
            Region sourceRegion   = sourceCountry.regions [sourceCountry.mainRegionIndex];

            // Extract from source country - only if province is in the frontier or is crossing the country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                otherSourceRegion.sanitized = true;
            }
            PolygonClipper pc = new PolygonClipper(sourceRegion, provinceRegion);

            if (pc.OverlapsSubjectAndClipping())
            {
                sourceRegion.sanitized = false;
                pc.Compute(PolygonOp.DIFFERENCE);
            }
            else
            {
                // Look for other regions to substract
                for (int k = 0; k < sourceCountry.regions.Count; k++)
                {
                    Region otherSourceRegion = sourceCountry.regions [k];
                    pc = new PolygonClipper(otherSourceRegion, provinceRegion);
                    if (pc.OverlapsSubjectAndClipping())
                    {
                        otherSourceRegion.sanitized = false;
                        pc.Compute(PolygonOp.DIFFERENCE);
                    }
                }
            }

            // Remove invalid regions from source country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                if (!otherSourceRegion.sanitized && otherSourceRegion.points.Length < 5)
                {
                    sourceCountry.regions.RemoveAt(k);
                    k--;
                }
            }

            // Transfer cities
            int cityCount = map.cities.Count;

            for (int k = 0; k < cityCount; k++)
            {
                City city = map.cities [k];
                if (city.countryIndex == countryIndex && city.province.Equals(province.name))
                {
                    city.countryIndex = targetCountryIndex;
                }
            }

            // Transfer mount points
            int mountPointCount = map.mountPoints.Count;

            for (int k = 0; k < mountPointCount; k++)
            {
                MountPoint mp = map.mountPoints [k];
                if (mp.countryIndex == countryIndex && mp.provinceIndex == provinceIndex)
                {
                    mp.countryIndex = targetCountryIndex;
                }
            }

            // Finish operation
            map.HideCountryRegionHighlights(true);
            map.HideProvinceRegionHighlights(true);
            map.RefreshCountryDefinition(province.countryIndex, null);
            province.countryIndex = targetCountryIndex;
            map.RefreshProvinceDefinition(provinceIndex);
            map.RefreshCountryDefinition(targetCountryIndex, null);
            countryChanges    = true;
            provinceChanges   = true;
            cityChanges       = true;
            mountPointChanges = true;
            ProvinceRegionSelect();
        }
        /// <summary>
        /// Makes one country to annex another
        /// </summary>
        public void CountryTransferTo()
        {
            if (countryIndex < 0 || GUICountryTransferToCountryIndex < 0 || GUICountryTransferToCountryIndex >= countryNames.Length)
            {
                return;
            }

            // Get target country
            // recover GUI country index selection
            int targetCountryIndex = -1;

            string[] s = countryNames [GUICountryTransferToCountryIndex].Split(new char[] {
                '(',
                ')'
            }, System.StringSplitOptions.RemoveEmptyEntries);
            if (s.Length >= 2)
            {
                if (!int.TryParse(s [1], out targetCountryIndex))
                {
                    return;
                }
            }
            // Transfer all provinces records to target country
            Country sourceCountry = map.countries [countryIndex];
            Country targetCountry = map.countries [targetCountryIndex];


            //MAX!
            mergeCountryData(sourceCountry, targetCountry);
            dataChanges = true;
            ndChanges   = true;


            if (targetCountry.provinces == null && !map.showProvinces)
            {
                map.showProvinces = true;                 // Forces loading of provinces
                map.showProvinces = false;
            }
            if (sourceCountry.provinces != null)
            {
                List <Province> destProvinces;
                if (targetCountry.provinces != null)
                {
                    destProvinces = new List <Province> (targetCountry.provinces);
                }
                else
                {
                    destProvinces = new List <Province> ();
                }
                for (int k = 0; k < sourceCountry.provinces.Length; k++)
                {
                    Province province = sourceCountry.provinces [k];
                    province.countryIndex = targetCountryIndex;
                    destProvinces.Add(province);
                }
                targetCountry.provinces = destProvinces.ToArray();
            }

            // Add main region of the source country to target if they are joint
            Region sourceRegion = sourceCountry.regions [sourceCountry.mainRegionIndex];
            Region targetRegion = targetCountry.regions [targetCountry.mainRegionIndex];


            //MAX!
            if (sourceRegion.neighbours.Contains(targetRegion))
            {
                // Add region to target country's polygon - only if the province is touching or crossing target country frontier
                PolygonClipper pc = new PolygonClipper(targetRegion, sourceRegion);
                if (pc.OverlapsSubjectAndClipping())
                {
                    pc.Compute(PolygonOp.UNION);
                }

                //MAX!
            }
            else
            {
                // Add new region to country
                Region newCountryRegion = new Region(targetCountry, targetCountry.regions.Count);
                newCountryRegion.points = new List <Vector3> (sourceRegion.points).ToArray();
                targetCountry.regions.Add(newCountryRegion);
            }

            // Transfer additional regions
            if (sourceCountry.regions.Count > 1)
            {
                List <Region> targetRegions = new List <Region> (targetCountry.regions);
                for (int k = 0; k < sourceCountry.regions.Count; k++)
                {
                    if (k != sourceCountry.mainRegionIndex)
                    {
                        targetRegions.Add(sourceCountry.regions [k]);
                    }
                }
                targetCountry.regions = targetRegions;
            }

            //MAX!
            if (!map.showCities && map.cities == null)
            {
                map.ReadCitiesPackedString();
            }
            // Transfer cities & mount points
            TransferCities(countryIndex, targetCountryIndex);
            TransferMountPoints(countryIndex, targetCountryIndex);

            // Finish operation
            map.HideCountryRegionHighlights(true);
            map.HideProvinceRegionHighlights(true);
            map.CountryDelete(countryIndex, false);
            map.RefreshCountryDefinition(targetCountryIndex, null);
            countryChanges     = true;
            provinceChanges    = true;
            countryIndex       = targetCountryIndex;
            countryRegionIndex = targetCountry.mainRegionIndex;
            CountryRegionSelect();
            map.RedrawMapLabels();
        }
Exemple #8
0
        /// <summary>
        /// Deletes current region or province if this was the last region
        /// </summary>
        public void ProvinceDelete()
        {
            if (provinceIndex < 0 || provinceIndex >= map.provinces.Length)
            {
                return;
            }

            // Apply boolean operations on country polygons
            Province province       = map.provinces [provinceIndex];
            Region   provinceRegion = province.regions [provinceRegionIndex];
            Country  sourceCountry  = map.countries [countryIndex];

            // Extract from source country - only if province is in the frontier or is crossing the country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                otherSourceRegion.sanitized = true;
            }
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region         otherSourceRegion = sourceCountry.regions [k];
                PolygonClipper pc = new PolygonClipper(otherSourceRegion, provinceRegion);
                if (pc.OverlapsSubjectAndClipping())
                {
                    otherSourceRegion.sanitized = false;
                    pc.Compute(PolygonOp.DIFFERENCE);
                }
            }

            // Remove invalid regions from source country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                if (!otherSourceRegion.sanitized && otherSourceRegion.points.Length < 5)
                {
                    sourceCountry.regions.RemoveAt(k);
                    k--;
                }
            }

            // Remove it from the country array
            List <Province> newProvinces = new List <Province> (map.countries [countryIndex].provinces.Length - 1);

            for (int k = 0; k < map.countries [countryIndex].provinces.Length; k++)
            {
                if (!map.countries [countryIndex].provinces [k].name.Equals(GUIProvinceName))
                {
                    newProvinces.Add(map.countries [countryIndex].provinces [k]);
                }
            }
            map.countries [countryIndex].provinces = newProvinces.ToArray();
            // Remove from the global array
            newProvinces = new List <Province> (map.provinces.Length - 1);
            for (int k = 0; k < map.provinces.Length; k++)
            {
                if (k != provinceIndex)
                {
                    newProvinces.Add(map.provinces [k]);
                }
            }
            map.provinces = newProvinces.ToArray();

            // Finish operation
            map.HideCountryRegionHighlights(true);
            map.HideProvinceRegionHighlights(true);
            map.RefreshCountryDefinition(countryIndex, null);
            ClearProvinceSelection();
            map.OptimizeFrontiers();
            map.Redraw();
            countryChanges  = true;
            provinceChanges = true;
            CountryRegionSelect();
        }
        /// <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(int provinceIndex)
        {
            lastProvinceLookupCount = -1;
            if (provinceIndex < 0 || provinceIndex >= provinces.Length)
            {
                return;
            }
            float    maxVol      = 0;
            Vector2  minProvince = Misc.Vector2one * 10;
            Vector2  maxProvince = -minProvince;
            Province province    = provinces [provinceIndex];

            if (province.regions == null)
            {
                ReadProvincePackedString(province);
            }
            int regionCount = province.regions.Count;

            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;
                Vector3 min       = Misc.Vector3one * 10;
                Vector3 max       = -min;
                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;
                    }
                }
                Vector3 normRegionCenter = (min + max) * 0.5f;
                provinceRegion.center = normRegionCenter;

                // Calculate country 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, Math.Abs(max.x - min.x), Mathf.Abs(max.y - min.y));
                float vol = (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));
        }
        bool DrawProvinces(List <Country> targetCountries, bool forceRefresh)
        {
            // optimize required lines
            if (frontiersPoints == null)
            {
                frontiersPoints = new List <Vector3> (1000000);
            }
            else
            {
                frontiersPoints.Clear();
            }
            if (frontiersCacheHit == null)
            {
                frontiersCacheHit = new Dictionary <double, Region> (500000);
            }
            else
            {
                frontiersCacheHit.Clear();
            }
            for (int c = 0; c < targetCountries.Count; c++)
            {
                Country targetCountry = targetCountries [c];
                if (targetCountry.provinces == null)
                {
                    continue;
                }
                for (int p = 0; p < targetCountry.provinces.Length; p++)
                {
                    Province province = targetCountry.provinces [p];
                    if (province.regions == null)                       // read province data the first time we need it
                    {
                        ReadProvincePackedString(province);
                    }
                    for (int r = 0; r < province.regions.Count; r++)
                    {
                        Region region = province.regions [r];
                        region.entity      = province;
                        region.regionIndex = r;
                        region.neighbours.Clear();
                        int numPoints = region.points.Length - 1;
                        for (int i = 0; i < numPoints; i++)
                        {
                            Vector3 p0 = region.points [i];
                            Vector3 p1 = region.points [i + 1];
                            double  v  = (p0.x + p1.x) + MAP_PRECISION * (p0.y + p1.y);
                            if (frontiersCacheHit.ContainsKey(v))
                            {
                                Region neighbour = frontiersCacheHit [v];
                                if (neighbour != region)
                                {
                                    if (!region.neighbours.Contains(neighbour))
                                    {
                                        region.neighbours.Add(neighbour);
                                        neighbour.neighbours.Add(region);
                                    }
                                }
                            }
                            else
                            {
                                frontiersCacheHit.Add(v, region);
                                frontiersPoints.Add(p0);
                                frontiersPoints.Add(p1);
                            }
                        }
                        // Close the polygon
                        frontiersPoints.Add(region.points [numPoints]);
                        frontiersPoints.Add(region.points [0]);
                    }
                }
            }

            int meshGroups = (frontiersPoints.Count / 65000) + 1;
            int meshIndex  = -1;

            int[][]     provincesIndices = new int[meshGroups][];
            Vector3[][] provincesBorders = new Vector3[meshGroups][];
            for (int k = 0; k < frontiersPoints.Count; k += 65000)
            {
                int max = Mathf.Min(frontiersPoints.Count - k, 65000);
                provincesBorders [++meshIndex] = new Vector3[max];
                provincesIndices [meshIndex]   = new int[max];
                for (int j = k; j < k + max; j++)
                {
                    provincesBorders [meshIndex] [j - k] = frontiersPoints [j];
                    provincesIndices [meshIndex] [j - k] = j - k;
                }
            }

            // Create province layer if needed
            if (provincesObj != null)
            {
                DestroyImmediate(provincesObj);
            }

            provincesObj           = new GameObject("Provinces");
            provincesObj.hideFlags = HideFlags.DontSave;
            provincesObj.transform.SetParent(transform, false);
            provincesObj.transform.localPosition = Misc.Vector3back * 0.002f;
            provincesObj.layer = gameObject.layer;

            for (int k = 0; k < provincesBorders.Length; k++)
            {
                GameObject flayer = new GameObject("flayer");
                flayer.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;
                flayer.transform.SetParent(provincesObj.transform, false);
                flayer.transform.localPosition = Misc.Vector3zero;
                flayer.transform.localRotation = Quaternion.Euler(Misc.Vector3zero);
                flayer.layer = provincesObj.layer;

                Mesh mesh = new Mesh();
                mesh.vertices = provincesBorders [k];
                mesh.SetIndices(provincesIndices [k], MeshTopology.Lines, 0);
                mesh.RecalculateBounds();
                mesh.hideFlags = HideFlags.DontSave;

                MeshFilter mf = flayer.AddComponent <MeshFilter> ();
                mf.sharedMesh = mesh;

                MeshRenderer mr = flayer.AddComponent <MeshRenderer> ();
                mr.receiveShadows       = false;
                mr.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
                mr.shadowCastingMode    = UnityEngine.Rendering.ShadowCastingMode.Off;
//				mr.useLightProbes = false;
                mr.sharedMaterial = provincesMat;
            }
            return(true);
        }
        /// <summary>
        /// Unpacks province geodata information. Used by Map Editor.
        /// </summary>
        /// <param name="province">Province.</param>
        public void ReadProvincePackedString(Province province)
        {
            string[] regions     = province.packedRegions.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
            int      regionCount = regions.Length;

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

            char[] separatorRegions = new char[] { ';' };
            for (int r = 0; r < regionCount; r++)
            {
                string[] coordinates = regions [r].Split(separatorRegions, StringSplitOptions.RemoveEmptyEntries);
                int      coorCount   = coordinates.Length;
                if (coorCount < 3)
                {
                    continue;
                }
                Vector3 min            = Misc.Vector3one * 10;
                Vector3 max            = -min;
                Region  provinceRegion = new Region(province, province.regions.Count);
                provinceRegion.points = new Vector3[coorCount];
                for (int c = 0; c < coorCount; c++)
                {
                    float x, y;
                    GetPointFromPackedString(coordinates [c], out x, out y);

                    Vector2 point = new Vector2(x, y);
                    provinceRegion.points [c] = point;
                    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;
                    }
                }
                Vector3 normRegionCenter = (min + max) * 0.5f;
                provinceRegion.center = normRegionCenter;
                province.regions.Add(provinceRegion);

                // Calculate country 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, Math.Abs(max.x - min.x), Mathf.Abs(max.y - min.y));
                float vol = (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));
        }
Exemple #12
0
        public void ProvinceTransferTo(int targetCountryIndex, int provinceIndex)
        {
            // Remove province form source country
            Province province      = map.provinces [provinceIndex];
            Country  sourceCountry = map.countries [countryIndex];

            if (map.countries [countryIndex].provinces != null)
            {
                List <Province> sourceProvinces = new List <Province> (sourceCountry.provinces);
                int             provIndex       = -1;
                for (int k = 0; k < sourceCountry.provinces.Length; k++)
                {
                    if (sourceCountry.provinces [k].name.Equals(province.name))
                    {
                        provIndex = k;
                    }
                }
                if (provIndex >= 0)
                {
                    sourceProvinces.RemoveAt(provIndex);
                    sourceCountry.provinces = sourceProvinces.ToArray();
                }
            }

            // Adds province to target country
            Country targetCountry = map.countries [targetCountryIndex];

            if (targetCountry.provinces == null)
            {
                targetCountry.provinces = new Province[0];
            }
            List <Province> destProvinces = new List <Province> (targetCountry.provinces);

            destProvinces.Add(province);
            targetCountry.provinces = destProvinces.ToArray();

            // Apply boolean operations on country polygons
            Region provinceRegion = province.regions [provinceRegionIndex];
            Region sourceRegion   = sourceCountry.regions [sourceCountry.mainRegionIndex];
            Region targetRegion   = targetCountry.regions [targetCountry.mainRegionIndex];

            // Extract from source country - only if province is in the frontier or is crossing the country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                otherSourceRegion.sanitized = true;
            }
            PolygonClipper pc = new PolygonClipper(sourceRegion, provinceRegion);

            if (pc.OverlapsSubjectAndClipping())
            {
                sourceRegion.sanitized = false;
                pc.Compute(PolygonOp.DIFFERENCE);
            }
            else
            {
                // Look for other regions to substract
                for (int k = 0; k < sourceCountry.regions.Count; k++)
                {
                    Region otherSourceRegion = sourceCountry.regions [k];
                    pc = new PolygonClipper(otherSourceRegion, provinceRegion);
                    if (pc.OverlapsSubjectAndClipping())
                    {
                        otherSourceRegion.sanitized = false;
                        pc.Compute(PolygonOp.DIFFERENCE);
                    }
                }
            }

            // Remove invalid regions from source country
            for (int k = 0; k < sourceCountry.regions.Count; k++)
            {
                Region otherSourceRegion = sourceCountry.regions [k];
                if (!otherSourceRegion.sanitized && otherSourceRegion.points.Length < 5)
                {
                    sourceCountry.regions.RemoveAt(k);
                    k--;
                }
            }

            // Add region to target country's polygon - only if the province is touching or crossing target country frontier
            pc = new PolygonClipper(targetRegion, provinceRegion);
            if (pc.OverlapsSubjectAndClipping())
            {
                pc.Compute(PolygonOp.UNION);
            }
            else
            {
                // Add new region to country
                Region newCountryRegion = new Region(targetCountry, targetCountry.regions.Count);
                newCountryRegion.points = new List <Vector3> (provinceRegion.points).ToArray();
                targetCountry.regions.Add(newCountryRegion);
            }

            //Max!
            if (!map.showCities && map.cities == null)
            {
                map.ReadCitiesPackedString();
            }

            // Transfer cities
            int cityCount = map.cities.Count;

            for (int k = 0; k < cityCount; k++)
            {
                City city = map.cities [k];
                if (city.countryIndex == countryIndex && city.province.Equals(province.name))
                {
                    city.countryIndex = targetCountryIndex;
                }
            }

            // Transfer mount points
            int mountPointCount = map.mountPoints.Count;

            for (int k = 0; k < mountPointCount; k++)
            {
                MountPoint mp = map.mountPoints [k];
                if (mp.countryIndex == countryIndex && mp.provinceIndex == provinceIndex)
                {
                    mp.countryIndex = targetCountryIndex;
                }
            }

            // Finish operation
            map.HideCountryRegionHighlights(true);
            map.HideProvinceRegionHighlights(true);
            map.RefreshCountryDefinition(province.countryIndex, null);
            province.countryIndex = targetCountryIndex;
            map.RefreshProvinceDefinition(provinceIndex);
            map.RefreshCountryDefinition(targetCountryIndex, null);
            countryChanges    = true;
            provinceChanges   = true;
            cityChanges       = true;
            mountPointChanges = true;
        }