public IEnumerable <MapSection> GetNeighbors(MapSection center) { HashSet <MapSection> retval; if (!NeighborsOfSection.TryGetValue(center, out retval)) { retval = new HashSet <MapSection>(); foreach (var neighboringCell in center.Cells.SelectMany(cell => Grid.GetNeighbors(cell))) { var sectionOfNeighbor = GetSectionOfCell(neighboringCell); if (sectionOfNeighbor != center) { retval.Add(sectionOfNeighbor); } } NeighborsOfSection[center] = retval; } return(retval); }
private bool TryExpandChunk( List <MapSection> chunk, HashSet <MapSection> unassignedSections, GridPartition partition, IMapTemplate mapTemplate, ExpansionWeightFunction weightFunction, bool mustBeContiguous ) { expansionCandidates.Clear(); foreach (MapSection section in chunk) { nearbySections.Clear(); sectionsWithinDistance.Clear(); if (mustBeContiguous) { foreach (var adjacentSection in partition.GetNeighbors(section)) { if (unassignedSections.Contains(adjacentSection)) { nearbySections.Add(adjacentSection); } } } else { foreach (IHexCell nearbyCell in Grid.GetCellsInRadius(section.CentroidCell, mapTemplate.HomelandExpansionMaxCentroidSeparation)) { MapSection sectionOfCell = partition.GetSectionOfCell(nearbyCell); if (unassignedSections.Contains(sectionOfCell)) { sectionsWithinDistance.Add(sectionOfCell); } } var sectionsSurroundedByUnassigned = sectionsWithinDistance.Where( nearby => partition.GetNeighbors(nearby).Count(neighbor => !unassignedSections.Contains(neighbor)) <= 0 ); if (sectionsSurroundedByUnassigned.Any()) { foreach (var surroundedSection in sectionsSurroundedByUnassigned) { nearbySections.Add(surroundedSection); } } else { foreach (var sectionWithin in sectionsWithinDistance) { nearbySections.Add(sectionWithin); } } } foreach (var nearby in nearbySections) { expansionCandidates.Add(nearby); } } if (expansionCandidates.Count > 0) { var newSection = MapSectionRandomSampler.SampleElementsFromSet( expansionCandidates, 1, section => weightFunction(section, chunk) ).FirstOrDefault(); if (newSection != null) { unassignedSections.Remove(newSection); chunk.Add(newSection); return(true); } } return(false); }
//Creates something akin to a Voronoi diagram of the cells, //using a process similiar to Lloyd's algorithm to make the //shapes more regular public GridPartition GetPartitionOfGrid(IHexGrid grid, IMapTemplate template) { float xMin = 0f, zMin = 0f; float xMax = (grid.CellCountX + grid.CellCountZ * 0.5f - grid.CellCountZ / 2) * RenderConfig.InnerRadius * 2f; float zMax = grid.CellCountZ * RenderConfig.OuterRadius * 1.5f; var randomPoints = new List <Vector3>(); var regionOfPoint = new Dictionary <Vector3, MapSection>(); for (int i = 0; i < template.VoronoiPointCount; i++) { var randomPoint = new Vector3( UnityEngine.Random.Range(xMin, xMax), 0f, UnityEngine.Random.Range(zMin, zMax) ); regionOfPoint[randomPoint] = new MapSection(grid); randomPoints.Add(randomPoint); } int iterationsLeft = template.VoronoiPartitionIterations; while (iterationsLeft > 0) { foreach (var cell in grid.Cells) { Vector3 nearestPoint = Vector3.zero; float shorestDistance = float.MaxValue; foreach (var voronoiPoint in regionOfPoint.Keys) { float distanceTo = Vector3.Distance(cell.GridRelativePosition, voronoiPoint); if (distanceTo < shorestDistance) { nearestPoint = voronoiPoint; shorestDistance = distanceTo; } } if (regionOfPoint.ContainsKey(nearestPoint)) { regionOfPoint[nearestPoint].AddCell(cell); } } if (--iterationsLeft > 0) { randomPoints.Clear(); var newRegionOfPoints = new Dictionary <Vector3, MapSection>(); foreach (var region in regionOfPoint.Values) { if (region.Cells.Count > 0) { randomPoints.Add(region.Centroid); newRegionOfPoints[region.Centroid] = new MapSection(grid); } } regionOfPoint = newRegionOfPoints; } } return(new GridPartition(regionOfPoint.Values, grid)); }