public override void Setup(SectorInfo sector, TerrainVerticesDatabase vertDatabase, Transform parent) { base.Setup(sector, vertDatabase, parent); TerrainVertData vertData = vertDatabase.GetNearestVertData(parent.position); Vector3 spawnPos = vertData.GetSurfacePos() - parent.position; GameObject spawn = Instantiate(objectToSpawn, childOfLevel ? parent : null); spawn.name = objectToSpawn.name; spawn.transform.localPosition = offset + (childOfLevel ? spawnPos : parent.position); }
// Called by LandMap.GetZones (), returns number of subregions public int ClusterLocationsAccordKMeans(MapPoint[,] points, TerrainVerticesDatabase vertDatabase) { // K-means cluster algorithm to separate locations in the regions int regionId = 0; for (int isleId = 0; isleId < regions.Count; isleId++) { MapRegion region = regions[isleId]; double[][] tileLocations = new double[region.turf.Count][]; for (int i = 0; i < tileLocations.Length; i++) { tileLocations[i] = new double[3]; TerrainVertData vertData = vertDatabase.GetVertDataFromRegionTile(region.turf[i], isleId); //LoggerTool.Post ("Requesting " + region.turf[i].ToString ()); if (vertData != null) { tileLocations[i][0] = region.turf[i].x; tileLocations[i][1] = vertData.inlandPosition; tileLocations[i][2] = region.turf[i].y; } else { LoggerTool.Post("Null from VertDB for " + region.turf[i].ToString()); tileLocations[i][0] = 0; tileLocations[i][1] = 0; tileLocations[i][2] = 0; } } int k = InitializeNumOfK(tileLocations.Length); Debug.Log(k + " centroid(s)"); KMeans kmeans = new KMeans(k); KMeansClusterCollection clusters = kmeans.Learn(tileLocations); int[] labels = clusters.Decide(tileLocations); Debug.Log("Number of labels (clusters) = " + labels.Length); for (int i = 0; i < labels.Length; i++) { points[(int)tileLocations[i][0], (int)tileLocations[i][2]].areaValue = regionId + labels[i]; } regionId += k; } return(regionId); }
// Called by LandMap.GetZones (), returns number of subregions public int ClusterLocationsDBSCAN(float epsilon, int minPts, MapPoint[,] points, TerrainVerticesDatabase vertDatabase) { // DBSCAN cluster algorithm to separate locations in the regions int regionId = 0; for (int isleId = 0; isleId < regions.Count; isleId++) { MapRegion region = regions[isleId]; List <TilePoint> tileLocations = new List <TilePoint> (); for (int i = 0; i < region.turf.Count; i++) { TerrainVertData vertData = vertDatabase.GetVertDataFromRegionTile(region.turf[i], isleId); if (vertData != null) { tileLocations.Add(new TilePoint(region.turf[i].x, vertData.inlandPosition, region.turf[i].y)); } else { LoggerTool.Post("Null from VertDB for " + region.turf[i].ToString()); } } HashSet <TilePoint[]> clusters; var dbscan = new DbscanImplementation.DbscanAlgorithm <TilePoint> ((t1, t2) => TilePoint.Dist(t1, t2)); dbscan.ComputeClusterDbscan(allPoints: tileLocations.ToArray(), epsilon: epsilon, minPts: minPts, clusters: out clusters); int k = clusters.Count; Debug.Log("Number of clusters = " + k); int clstCount = 0; foreach (var tiles in clusters) { for (int i = 0; i < tiles.Length; i++) { points[(int)tiles[i].X, (int)tiles[i].Z].areaValue = regionId + clstCount; } clstCount++; } regionId += k; } return(regionId); }
// Called by LandMap.GetZones (), returns number of subregions public int ClusterLocationsKMeans(MapPoint[,] points, TerrainVerticesDatabase vertDatabase) { // K-means cluster algorithm to separate locations in the regions int regionId = 0; for (int isleId = 0; isleId < regions.Count; isleId++) { MapRegion region = regions[isleId]; Vector3[] tileLocations = new Vector3[region.turf.Count]; for (int i = 0; i < tileLocations.Length; i++) { TerrainVertData vertData = vertDatabase.GetVertDataFromRegionTile(region.turf[i], isleId); if (vertData != null) { tileLocations[i] = new Vector3(region.turf[i].x, vertData.surfaceElevatedCurve, region.turf[i].y); } else { LoggerTool.Post("Null from VertDB for " + region.turf[i].ToString()); } } int k = InitializeNumOfK(tileLocations.Length); Debug.Log(k + " centroid(s)"); Vector3[] centroids = new Vector3[k]; for (int i = 0; i < k; i++) { // Assign centroid to first k data points centroids[i] = tileLocations[i * (tileLocations.Length / k)]; //centroids[i] = tileLocations[i]; } // Loop until converged int changes = -1; int iter = 0; while (changes != 0 /* && iter < 1*/) { changes = 0; for (int tIndex = 0; tIndex < tileLocations.Length; tIndex++) { Coord tile = region.turf[tIndex]; int initialArea = points[tile.x, tile.y].areaValue; float distanceToCentroid = float.MaxValue; for (int i = 0; i < k; i++) { //float currDistToCentroid = centroids[i].ManhattanDist (tileLocations[tIndex]); //float currDistToCentroid = Vector3.Distance (centroids[i], tileLocations[tIndex]); float currDistToCentroid = Vector2.Distance(centroids[i].ToVec2FromXZ(), tileLocations[tIndex].ToVec2FromXZ()); if (currDistToCentroid < distanceToCentroid) { distanceToCentroid = currDistToCentroid; points[tile.x, tile.y].areaValue = regionId + i; } } if (initialArea != points[tile.x, tile.y].areaValue) { changes++; } } int[] frequency = new int[k]; Vector3[] cumulativeCentroids = new Vector3[k]; for (int i = 0; i < k; i++) { frequency[i] = 0; cumulativeCentroids[i] = Vector3.zero; } for (int i = 0; i < tileLocations.Length; i++) { Coord tile = region.turf[i]; cumulativeCentroids[Mathf.Max(0, points[tile.x, tile.y].areaValue - regionId)] += tileLocations[i]; frequency[Mathf.Max(0, points[tile.x, tile.y].areaValue - regionId)]++; } for (int i = 0; i < k; i++) { if (frequency[i] != 0) { centroids[i] = cumulativeCentroids[i] / frequency[i]; } else { centroids[i] = tileLocations[Random.Range(0, tileLocations.Length)]; } } iter++; } for (int i = 0; i < k; i++) { Debug.Log("Centroid " + (regionId + i) + " at " + centroids[i].ToString()); } LoggerTool.Post("No of iteration: " + iter); regionId += k; } return(regionId); }