using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; using Random = UnityEngine.Random; public static class PoissonDiskSampling { public static List PoissonGenerate(float radius, Vector2 sampleRegionSize, int numSamplesBeforeRejection = 30) { float cellSize = radius / Mathf.Sqrt(2); int[,] grid = new int[Mathf.CeilToInt(sampleRegionSize.x / cellSize), Mathf.CeilToInt(sampleRegionSize.y / cellSize)]; List points = new List(); List spawnPoints = new List(); spawnPoints.Add(sampleRegionSize / 2); while (spawnPoints.Count > 0) { int spawnIndex = Random.Range(0, spawnPoints.Count); Vector2 spawnCentre = spawnPoints[spawnIndex]; bool isCandidateAccepted = false; for (int i = 0; i < numSamplesBeforeRejection; i++) { float angle = Random.value * Mathf.PI * 2; Vector2 dir = new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)); Vector2 candidate = spawnCentre + dir * Random.Range(radius, 2 * radius); if (IsValid(candidate, sampleRegionSize, cellSize, radius, points, grid)) { points.Add(candidate); spawnPoints.Add(candidate); grid[(int)(candidate.x / cellSize), (int)(candidate.y / cellSize)] = points.Count; isCandidateAccepted = true; break; } } if (!isCandidateAccepted) spawnPoints.RemoveAt(spawnIndex); } return points; } static bool IsValid(Vector2 candidate, Vector2 sampleRegionSize, float cellSize, float radius, List points, int[,] grid) { if (candidate.x >= 0 && candidate.x < sampleRegionSize.x && candidate.y >= 0 && candidate.y < sampleRegionSize.y) { int cellX = (int) (candidate.x / cellSize); int cellY = (int) (candidate.y / cellSize); int searchStartX = Mathf.Max(0, cellX - 2); int searchEndX = Mathf.Min(cellX + 2, grid.GetLength(0) - 1); int searchStartY = Mathf.Max(0, cellY - 2); int searchEndY = Mathf.Min(cellY + 2, grid.GetLength(1) - 1); for (int x = searchStartX; x <= searchEndX; x++) { for (int y = searchStartY; y <= searchEndY; y++) { int pointIndex = grid[x, y] - 1; if (pointIndex != -1) { float sqrDst = (candidate - points[pointIndex]).sqrMagnitude; if (sqrDst < radius * radius) { return false; } } } } return true; } return false; } // float squaredEuclideanDistance(Array point1, Array point2) // { // // } // // // void PoissonDiskGenerate() // { // // } }