Author Topic: Territories Importer issues  (Read 1879 times)

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #45 on: August 01, 2021, 05:27:57 PM »
I've integrated the new code, and it works as described. Now I don't need to create the extra Ocean country.
The described problems with borders and frontiers are still there though. I found that the project I sent wasn't complete, so
perhaps you could'nt reproduce the problems. I had removed code needed for the tooltip (showing province name and country name),
and the world textures. I've added those, so hopefully the new project I've sent is complete.

After clicking "Assign provinces", where all provinces are assigned from "Main Country" to either Argentine or United Kingdom, it's
the following errors:
- highlighting are making all province borders black (they should remain slim white as before)
- old country frontiers remain (should be removed if possible)
- new country frontiers aren't shown (perhaps I can live without them if I show ownership some other way)

Like you mentioned, I don't want to use any non-reversable methods (like CountryTransferProvinceRegion) since all provinces
could change owners repeatedly during a game session. The world I use is static in the sense that during the game I will not
change any of the land or sea, only changing ownership of land provinces. Optimally, no geodata will be changed during a game
session. But if country frontiers aren't part of geodata, perhaps they can be regenerated after all provinces have changed their owner?

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #46 on: August 02, 2021, 10:14:40 AM »
I've started to debug DrawFrontiers() since the incorrect Frontiers gameobject is created there.
As the last step of the "Assign Provinces" logic, I have the _map.Redraw() call.
In this situation needOptimizeFrontiers is false, so the frontiers aren't recreated.
When I override the code and set it to true, the frontiers are regenerated here, but things are still incorrect.
All the land province borders have become frontiers.
This seems directly related to the first issue with the black border highlighting, so the root cause of all issues might be the same.
« Last Edit: August 02, 2021, 10:17:42 AM by Pollyfun »

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #47 on: August 02, 2021, 02:42:57 PM »
Hi,

I got your updated code. The issue is that you're using CountryTransferProvince() method which is designed for adding provinces to a country but it doesn't merge frontiers (so it's a lot faster).
The correct method is CountryTransferProvinceRegion(). This method is slower but merges regions correctly after they change owners (if you uncomment those lines in your Logic.cs you can verify this).

I'm adding a new method similar to CountryTransferProvinceRegion() that accepts multiple provinces so it's faster as it optimizes some operations.

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #48 on: August 02, 2021, 07:11:58 PM »
New beta.
It includes the new CountryTransferProvinces method, which allows you to pass a list of provinces. It does the job significantly faster, from a previous benchmark of 50 seconds to 8.
I've also sent you a pm with the updated project which makes use of this new API.
I think it will be harder to reduce that timing since there're many provinces and regions involved in the operation but give it a try and let me know how it goes.

p.s. the old CountryTransferProvince has been removed since it was not operating correctly (was fast, but incomplete).

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #49 on: August 03, 2021, 09:22:48 AM »
Thanks, that was a great update. Now the important things looks correct (borders, frontiers, highlighting) after loading.
I think the loading time is ok for this scenario (with around 80 provinces). I'll show a loading screen.

A theoretical question, could skipping frontiers for all coastlines speed things up? For this scenario, it would mean
only creating a frontier where Argentine and United Kingdom directly borders each other.


Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #50 on: August 03, 2021, 10:01:04 AM »
Not really. The slowest part has to do with polygon sanitization. This is a process that takes place after the polygon operations have finished that ensure that the resulting polygons are correct. I'll keep trying to reduce those times in next updates.

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #51 on: August 03, 2021, 10:29:52 AM »
Ok, I understand. Later optimizations are always welcome. :)

But lets say for purely graphical reasons, would it be difficult to add a parameter to skip the creation of all coastline frontiers?
I get the impression that this scenario could look better/clearer that way.

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #52 on: August 03, 2021, 10:39:37 AM »
Visually speaking, yes. You have some options to hide coast lines in the inspector. See attached.

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #53 on: August 03, 2021, 10:51:19 AM »
Ah, okay. I got it to work in the default world map, but not in this scenario. I suspect the sea provinces are treated just as land provinces so the frontier is created anyway. Any idea for this?
Thanks

Update: I could easily loop through the provinces and set a property on each one. I saw there's an attrib property. Perhaps this one could be used, or a new property to mark it as ocean?
Then this property could be used for ignoring sea provinces when creating frontiers (when Coastline is unchecked).
« Last Edit: August 03, 2021, 11:03:39 AM by Pollyfun »

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #54 on: August 03, 2021, 04:04:35 PM »
Another general question. Why are regions merged at all? Is for performance reasons (fewer separate objects to render simultaneously), and/or is it a necessity before creating frontiers?

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #55 on: August 03, 2021, 05:17:38 PM »
A region represents a continuous area of land or domain. It's represented by a polygons, which are the ones that get merged. Polygons are then triangulated to create a color or texture surface when highlighting or customizing the region.
In this case, regions are merged so a continuous polygon shows the frontiers of a country.

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #56 on: August 04, 2021, 07:41:13 AM »
Update: I could easily loop through the provinces and set a property on each one. I saw there's an attrib property. Perhaps this one could be used, or a new property to mark it as ocean?
Then this property could be used for ignoring sea provinces when creating frontiers (when Coastline is unchecked).

You can skip this request. I'm trying to fix frontiers in another way. I'll give an update later.

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #57 on: August 07, 2021, 06:04:57 PM »
I've tested more using the new CountryTransferProvinces() when loading countries, and then using the CountryTransferProvinceRegion() method
when changing province owners one at a time. It often works as expected for a few provinces, but then some problem occur. I've recorded two examples.

In this first case I can change owner of 3 provinces but clicking the fourth the game crashes with an exception, and the following call stack.

Code
NullReferenceException: Object reference not set to an instance of an object
WorldMapStrategyKit.Poly2Tri.DTSweep.FlipEdgeEvent (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx, WorldMapStrategyKit.Poly2Tri.TriangulationPoint ep, WorldMapStrategyKit.Poly2Tri.TriangulationPoint eq, WorldMapStrategyKit.Poly2Tri.DelaunayTriangle t, WorldMapStrategyKit.Poly2Tri.TriangulationPoint p) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:585)
WorldMapStrategyKit.Poly2Tri.DTSweep.FlipEdgeEvent (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx, WorldMapStrategyKit.Poly2Tri.TriangulationPoint ep, WorldMapStrategyKit.Poly2Tri.TriangulationPoint eq, WorldMapStrategyKit.Poly2Tri.DelaunayTriangle t, WorldMapStrategyKit.Poly2Tri.TriangulationPoint p) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:612)
WorldMapStrategyKit.Poly2Tri.DTSweep.EdgeEvent (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx, WorldMapStrategyKit.Poly2Tri.TriangulationPoint ep, WorldMapStrategyKit.Poly2Tri.TriangulationPoint eq, WorldMapStrategyKit.Poly2Tri.DelaunayTriangle triangle, WorldMapStrategyKit.Poly2Tri.TriangulationPoint point) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:579)
WorldMapStrategyKit.Poly2Tri.DTSweep.EdgeEvent (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx, WorldMapStrategyKit.Poly2Tri.TriangulationPoint ep, WorldMapStrategyKit.Poly2Tri.TriangulationPoint eq, WorldMapStrategyKit.Poly2Tri.DelaunayTriangle triangle, WorldMapStrategyKit.Poly2Tri.TriangulationPoint point) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:537)
WorldMapStrategyKit.Poly2Tri.DTSweep.EdgeEvent (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx, WorldMapStrategyKit.Poly2Tri.DTSweepConstraint edge, WorldMapStrategyKit.Poly2Tri.AdvancingFrontNode node) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:353)
WorldMapStrategyKit.Poly2Tri.DTSweep.Sweep (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:101)
WorldMapStrategyKit.Poly2Tri.DTSweep.Triangulate (WorldMapStrategyKit.Poly2Tri.DTSweepContext tcx) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/Triangulation/Delaunay/Sweep/DTSweep.cs:64)
WorldMapStrategyKit.Poly2Tri.P2T.Triangulate (WorldMapStrategyKit.Poly2Tri.TriangulationContext tcx) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/P2T.cs:75)
WorldMapStrategyKit.Poly2Tri.P2T.Triangulate (WorldMapStrategyKit.Poly2Tri.TriangulationAlgorithm algorithm, WorldMapStrategyKit.Poly2Tri.ITriangulatable t) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/P2T.cs:68)
WorldMapStrategyKit.Poly2Tri.P2T.Triangulate (WorldMapStrategyKit.Poly2Tri.Polygon p) (at Assets/WorldMapStrategyKit/Scripts/ThirdParty/PolyTri/P2T.cs:44)
WorldMapStrategyKit.WMSK.GenerateCountryRegionSurface (System.Int32 countryIndex, System.Int32 regionIndex, UnityEngine.Material material, UnityEngine.Vector2 textureScale, UnityEngine.Vector2 textureOffset, System.Single textureRotation) (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivCountry.cs:796)
WorldMapStrategyKit.WMSK.HighlightCountryRegionSingle (System.Int32 countryIndex, System.Int32 regionIndex, System.Boolean refreshGeometry, System.Boolean drawOutline) (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivCountry.cs:660)
WorldMapStrategyKit.WMSK.HighlightCountryRegion (System.Int32 countryIndex, System.Int32 regionIndex, System.Boolean refreshGeometry, System.Boolean drawOutline) (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivCountry.cs:608)
WorldMapStrategyKit.WMSK.CheckMousePos () (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivate.cs:1801)
WorldMapStrategyKit.WMSK.PerformUserInteraction () (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivate.cs:699)
WorldMapStrategyKit.WMSK.Update () (at Assets/WorldMapStrategyKit/Scripts/Core/Internal/WMSKPrivate.cs:245)

https://www.youtube.com/watch?v=VzYHv-9sZ7Q

In the second case I change owner of the provinces No Man's Land and Teal Inlet to UK. Then I change back Teal Inlet to Argentine.
This makes No Man's Land province to disappear. At least it's not possible to interact with it anymore.

https://www.youtube.com/watch?v=HT_8EBhEhq4

Note that you won't have to try and fix these issues, I just want to explain why I won't use these methods going forward. I've come to the conclusion that these operations can probably never be 100% succesful due to all the low-level operations taking place.
For the game I'm making stability of the core features (like changing province owner) must be 100 %. So there can be no merging of regions and so on.

I will inactivate frontiers, and use the CountryTransferProvince() method instead. It's much quicker, and hopefully reliable (as far as I've tested it).
I plan to create other frontiers that are totally separate objects that are rendered on top of the world objects.

« Last Edit: August 07, 2021, 08:53:19 PM by Pollyfun »

Pollyfun

  • Jr. Member
  • **
  • Posts: 71
    • View Profile
Re: Territories Importer issues
« Reply #58 on: August 07, 2021, 08:51:03 PM »
When disabling frontiers and using CountryTransferProvince() for loading provinces and for changing owner one by one, it mostly works. But there's a couple of issues that would be great if they could be fixed. The first one is that regions are not removed from the sourcecountry. I'm using this code:

Code
public bool CountryTransferProvince(int targetCountryIndex, int provinceIndex) {

if (provinceIndex < 0 || targetCountryIndex < 0 || targetCountryIndex >= _countries.Length)
return false;

// Province must belong to another country
Province province = provinces[provinceIndex];
int sourceCountryIndex = province.countryIndex;
if (sourceCountryIndex == targetCountryIndex)
return false;

// Remove province form source country
Country sourceCountry = _countries[sourceCountryIndex];

if (sourceCountry.provinces != null) {
List<Province> sourceProvinces = new List<Province>(sourceCountry.provinces);
if (sourceProvinces.Contains(province)) {
sourceProvinces.Remove(province);
sourceCountry.provinces = sourceProvinces.ToArray();
}
}

// Adds province to target country
Country targetCountry = _countries[targetCountryIndex];
List<Province> destProvinces;
if (targetCountry.provinces == null) {
destProvinces = new List<Province>();
} else {
destProvinces = new List<Province>(targetCountry.provinces);
}
destProvinces.Add(province);
destProvinces.Sort(ProvinceSizeComparer);
targetCountry.provinces = destProvinces.ToArray();

// Update owner index
province.countryIndex = targetCountryIndex;

// Adds province regions to target country regions
bool requireCountryGeometryRefresh = false;
if (province.regions == null) ReadProvincePackedString(province);
int regionsCount = province.regions.Count;
for (int k = 0; k < regionsCount; k++) {
Region provinceRegion = province.regions[k];
if (!targetCountry.Contains(provinceRegion)) {
Region newRegion = provinceRegion.Clone();
newRegion.entity = targetCountry;
targetCountry.regions.Add(newRegion);
requireCountryGeometryRefresh = true;
}

if (sourceCountry.regions.Contains(provinceRegion)) {
sourceCountry.regions.Remove(provinceRegion);
requireCountryGeometryRefresh = true;
}
}

if (requireCountryGeometryRefresh) {
RefreshCountryGeometry(targetCountry);
    }

    return true;
}

There's code to remove the region, but it doesnt' work
Code
if (sourceCountry.regions.Contains(provinceRegion)) {
    sourceCountry.regions.Remove(provinceRegion);
    requireCountryGeometryRefresh = true;
}


Here's a video showing the results.
https://www.youtube.com/watch?v=N2H75ECjwrs

« Last Edit: August 07, 2021, 08:57:11 PM by Pollyfun »

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 7565
    • View Profile
Re: Territories Importer issues
« Reply #59 on: August 09, 2021, 12:43:41 PM »
Hi,

The function CountryTransferProvince was replaced by an overload to CountryTransferProvinceRegion in latest version because it was misleading. Both methods operate similarly now, except that the first method requires a province index and the second one allows you to pass a Region. They do the same thing: they will try to extract from the source country and add it to the target country affecting country frontiers, cities, mount points and merging any affected regions (among other limitations, the old CountryTransferProvince method could not remove regions from source country properly because the country regions are different objects).

In latest beta I added 3 new methods:
- CountrySetProvinces
- CountryAddProvinces
- CountryRemoveProvinces

The way they work is quite different to CountryTransferProvince method.

- CountrySetProvinces will replace ALL provinces in a given country with the passed list. This call will also update the country regions by adding all regions from the provinces and merging them (optionally, by default, mergeRegions parameter is true).
- CountryAddProvinces will add ONE OR MORE provinces to an existing country and merge the regions of those provinces into the country regions.
- CountryRemoveProvinces will call CountrySetProvinces but excluding the given provinces.

The key difference here wrt CountryTransferRegion is that there's no substraction operation on the source country which can cause issues with some polygons.

To summarize:
- CountryTransferProvince will extract one province from a source country and add it to a target country. It performs substraction on the origin country polygon and addition to the target country polygon.
- The same result can be achieved by calling CountryRemoveProvinces on the source country and CountryAddProvinces on the target country. In these cases however, the country provinces list and regions are being recreated completely on the source country. There's no substraction. This operation can be slower (should be slower) on countries with many provinces but should be safer as there's no substraction.

For example, to replace the provinces in Spain with just 2 provinces (Sevilla and Cádiz):

Code
                int spain = map.GetCountryIndex("Spain");
                List<Province> provs = new List<Province>();
                provs.Add(map.GetProvince("Sevilla", "Spain"));
                provs.Add(map.GetProvince("Cádiz", "Spain"));
                map.CountrySetProvinces(spain, provs);
                map.Redraw(true);

Then to add Málage province:

Code
                int spain = map.GetCountryIndex("Spain");
                List<Province> provs = new List<Province>();
                provs.Add(map.GetProvince("Málaga", "Spain"));
                map.CountryAddProvinces(spain, provs);
                map.Redraw(true);

Please get the latest beta and let me know how this alternative works better for you (CountryRemoveProvinces + CountryAddProvinces).