Uniformly distribute x points inside a circle

Might as well tag on my Python translation.

from math import sqrt, sin, cos, pi
phi = (1 + sqrt(5)) / 2  # golden ratio

def sunflower(n, alpha=0, geodesic=False):
    points = []
    angle_stride = 360 * phi if geodesic else 2 * pi / phi ** 2
    b = round(alpha * sqrt(n))  # number of boundary points
    for k in range(1, n + 1):
        r = radius(k, n, b)
        theta = k * angle_stride
        points.append((r * cos(theta), r * sin(theta)))
    return points

def radius(k, n, b):
    if k > n - b:
        return 1.0
    else:
        return sqrt(k - 0.5) / sqrt(n - (b + 1) / 2)


# example
if __name__ == '__main__':
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    points = sunflower(500, alpha=2, geodesic=False)
    xs = [point[0] for point in points]
    ys = [point[1] for point in points]
    ax.scatter(xs, ys)
    ax.set_aspect('equal') # display as square plot with equal axes
    plt.show()

The goals of having a uniform distribution within the area and a uniform distribution on the boundary conflict; any solution will be a compromise between the two. I augmented the sunflower seed arrangement with an additional parameter alpha that indicates how much one cares about the evenness of boundary.

alpha=0 gives the typical sunflower arrangement, with jagged boundary:

alpha0

With alpha=2 the boundary is smoother:

alpha2

(Increasing alpha further is problematic: Too many points end up on the boundary).

The algorithm places n points, of which the kth point is put at distance sqrt(k-1/2) from the boundary (index begins with k=1), and with polar angle 2*pi*k/phi^2 where phi is the golden ratio. Exception: the last alpha*sqrt(n) points are placed on the outer boundary of the circle, and the polar radius of other points is scaled to account for that. This computation of the polar radius is done in the function radius.

It is coded in MATLAB.

function sunflower(n, alpha)   %  example: n=500, alpha=2
    clf
    hold on
    b = round(alpha*sqrt(n));      % number of boundary points
    phi = (sqrt(5)+1)/2;           % golden ratio
    for k=1:n
        r = radius(k,n,b);
        theta = 2*pi*k/phi^2;
        plot(r*cos(theta), r*sin(theta), 'r*');
    end
end

function r = radius(k,n,b)
    if k>n-b
        r = 1;            % put on the boundary
    else
        r = sqrt(k-1/2)/sqrt(n-(b+1)/2);     % apply square root
    end
end

Stumbled across this question and the answer above (so all cred to user3717023 & Matt).
Just adding my translation into R here, in case someone else needed that :)

library(tibble)
library(dplyr)
library(ggplot2)

sunflower <- function(n, alpha = 2, geometry = c('planar','geodesic')) {
  b <- round(alpha*sqrt(n))  # number of boundary points
  phi <- (sqrt(5)+1)/2  # golden ratio

  r <- radius(1:n,n,b)
  theta <- 1:n * ifelse(geometry[1] == 'geodesic', 360*phi, 2*pi/phi^2)

  tibble(
    x = r*cos(theta),
    y = r*sin(theta)
  )
}

radius <- function(k,n,b) {
  ifelse(
    k > n-b,
    1,
    sqrt(k-1/2)/sqrt(n-(b+1)/2)
  )
}

# example:
sunflower(500, 2, 'planar') %>%
    ggplot(aes(x,y)) +
    geom_point()

Tags:

Math

Geometry