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); } } }
/// <summary> /// Adjusts all countries frontiers to match the hexagonal grid /// </summary> public IEnumerator HexifyCountries(HexifyOpContext context) { Cell[] cells = _map.cells; if (cells == null) { yield break; } // Initialization cancelled = false; hexifyContext = context; if (procCells == null || procCells.Length < cells.Length) { procCells = new RegionCell[cells.Length]; } for (int k = 0; k < cells.Length; k++) { procCells [k].entityIndex = -1; } // Compute area of a single cell; for optimization purposes we'll ignore all regions whose surface is smaller than a 20% the size of a cell float minArea = 0; Region templateCellRegion = null; for (int k = 0; k < cells.Length; k++) { if (cells [k] != null) { templateCellRegion = new Region(null, 0); templateCellRegion.UpdatePointsAndRect(cells [k].points, true); minArea = templateCellRegion.rect2DArea * 0.2f; break; } } if (templateCellRegion == null) { yield break; } if (hexagonPoints == null || hexagonPoints.Length != 6) { hexagonPoints = new Vector2[6]; } for (int k = 0; k < 6; k++) { hexagonPoints [k] = templateCellRegion.points [k] - templateCellRegion.center; } // Pass 1: remove minor regions yield return(RemoveSmallRegions(minArea, _map.countries)); // Pass 2: assign all region centers to each country from biggest country to smallest country if (!cancelled) { yield return(AssignRegionCenters(_map.countries)); } // Pass 3: add cells to target countries if (!cancelled) { yield return(AddHexagons(_map.countries)); } // Pass 4: merge adjacent regions if (!cancelled) { yield return (MergeAdjacentRegions(_map.countries)); } // Pass 5: remove cells from other countries if (!cancelled) { yield return(RemoveHexagons(_map.countries)); } // Pass 6: update geometry of resulting countries if (!cancelled) { yield return(UpdateCountries()); } if (!cancelled) { _map.OptimizeFrontiers(); _map.Redraw(true); } hexifyContext.progress(1f, hexifyContext.title, ""); // hide progress bar yield return(null); if (hexifyContext.finish != null) { hexifyContext.finish(cancelled); } }