generate poisson sampling for any point in csharp

Here's a code snippet for generating Poisson Disk Sampling for any point in C#. It uses an algorithm called "Bridson's Algorithm" to create a set of points that are at least a certain minimum distance apart from each other.

main.cs
public static List<Vector2> GeneratePoissonSampling(Vector2 point, float minimumDistance, int numSamples = 30, int numAttempts = 10)
{
    List<Vector2> points = new List<Vector2>();
    List<Vector2> activePoints = new List<Vector2>();
    float cellSize = minimumDistance / Mathf.Sqrt(2);
    int[,] grid = new int[Mathf.CeilToInt(1 / cellSize), Mathf.CeilToInt(1 / cellSize)];
    activePoints.Add(point);
    while (activePoints.Count > 0)
    {
        int randIndex = UnityEngine.Random.Range(0, activePoints.Count);
        Vector2 center = activePoints[randIndex];
        bool accepted = false;
        for (int i = 0; i < numAttempts; i++)
        {
            float angle = UnityEngine.Random.Range(0, Mathf.PI * 2);
            float radius = UnityEngine.Random.Range(minimumDistance, 2 * minimumDistance);
            Vector2 offset = new Vector2(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle));
            Vector2 candidate = center + offset;
            if (IsValid(candidate, points, grid, cellSize, minimumDistance))
            {
                points.Add(candidate);
                activePoints.Add(candidate);
                grid[Mathf.FloorToInt(candidate.x / cellSize), Mathf.FloorToInt(candidate.y / cellSize)] = points.Count;
                accepted = true;
                break;
            }
        }
        if (!accepted) { activePoints.Remove(center); }
        if (points.Count >= numSamples) { break; }
    }
    return points;
}

private static bool IsValid(Vector2 candidate, List<Vector2> points, int[,] grid, float cellSize, float minimumDistance)
{
    if (candidate.x < 0 || candidate.x > 1 || candidate.y < 0 || candidate.y > 1) { return false; }
    int cellX = Mathf.FloorToInt(candidate.x / cellSize);
    int cellY = Mathf.FloorToInt(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 sqrDistance = (candidate - points[pointIndex]).sqrMagnitude;
                if (sqrDistance < minimumDistance * minimumDistance)
                {
                    return false;
                }
            }
        }
    }
    return true;
}
2533 chars
60 lines

This function takes in a point, a minimum distance between points, and optional parameters for number of desired samples and number of attempts to place each sample. It returns a list of Vector2 points that are at least minimumDistance apart. The IsValid function is where the distance check is performed and ensures that no two points are closer than minimumDistance. The algorithm uses a grid to ensure that the sampling is evenly spaced and the search for nearby points is optimized.

gistlibby LogSnag