Sunflower seeds and the golden angle
Why do the seeds of a sunflower lie 137.5° apart? The seeds form at the center of the head, one after the other, each turned from the one before by the same divergence angle, and in the sunflower this angle is close to the golden angle, \(360^\circ/\varphi^2 \approx 137.508^\circ\). Vogel’s model of the head places the \(n\)-th seed at the angle \(n \cdot 137.508^\circ\) and at the radius \(c\sqrt{n}\), so that every seed gets the same area, \(\pi c^2\). At the golden angle, every seed keeps its distance from the others, and the head fills evenly. At an angle a tenth of a degree off, the seeds crowd together along spiral arms and leave gaps between them. The spirals that the eye picks out in a head come in consecutive Fibonacci numbers, such as 34 and 55.
The example places a thousand seeds by Vogel’s model. At the golden angle, the smallest distance between neighboring seeds must approach \(\sqrt{2\pi/\sqrt{5}}\,c \approx 1.676\,c\) away from the center, close to the spacing of a hexagonal packing of the same density, the densest there is. Discs of a diameter of \(1.6\,c\) must not overlap there, and at angles nearby they must.

[1]:
import math
import matplotlib.pyplot as plt
import numpy as np
import planex as px
Vogel’s model
seeds places the seeds 1 to \(n\) for a divergence angle, with \(c = 1\), and nearest gives each seed’s distance to its nearest neighbor:
[3]:
golden = 360 / ((1 + math.sqrt(5)) / 2) ** 2
def seeds(angle, n=1000):
"""the centers of the seeds 1 to n at the divergence angle, in degrees, by Vogel's model with c = 1"""
k = np.arange(1, n + 1)
return np.c_[np.sqrt(k) * np.cos(np.radians(k * angle)), np.sqrt(k) * np.sin(np.radians(k * angle))]
def nearest(points):
"""each point's distance to its nearest neighbor"""
d = np.sqrt(((points[:, None] - points[None]) ** 2).sum(axis=-1))
np.fill_diagonal(d, np.inf)
return d.min(axis=1)
print("golden angle", golden, "degrees")
golden angle 137.50776405003785 degrees
The golden angle
For the seeds from the hundredth on, away from the center, the smallest distance to the nearest neighbor is compared with \(\sqrt{2\pi/\sqrt{5}}\,c\), and with \(\sqrt{2\pi/\sqrt{3}}\,c\), the distance between neighbors in a hexagonal packing of the same density:
[4]:
smallest = nearest(seeds(golden))[99:].min()
hexagonal = math.sqrt(2 * math.pi / math.sqrt(3))
print("smallest distance", smallest, "| √(2π/√5)", math.sqrt(2 * math.pi / math.sqrt(5)))
print("hexagonal packing", hexagonal, "| ratio", smallest / hexagonal)
smallest distance 1.67547404332855 | √(2π/√5) 1.6762833568392579
hexagonal packing 1.9046256137279147 | ratio 0.8796868167960592
The smallest distance comes within a thousandth of \(\sqrt{2\pi/\sqrt{5}}\,c\), the limit for a head of many seeds, and it is 88 % of the spacing of a hexagonal packing.
Angles near it
As discs, the seeds of a diameter of \(1.6\,c\) fit between the bounds at the golden angle. px.Unify joins the discs, and the area that the union lacks against the sum of the discs is their overlap. At the golden angle the overlap is zero, and at 137.3°, 137.6° and at \(\tfrac{8}{21}\) and \(\tfrac{13}{34}\) of a turn, fractions near the golden angle, it is not:
[5]:
def head(angle):
"""the seeds as discs of radius 0.8 and the overlap of the discs"""
discs = [px.Circle(tuple(p), 0.8).Face() for p in seeds(angle)]
union = px.Unify(discs)
return union, max(len(discs) * math.pi * 0.8**2 - union.mass, 0.0) # no overlap: zero to rounding
angles = {"golden": golden, "137.3°": 137.3, "137.6°": 137.6, "8/21 of a turn": 360 * 8 / 21, "13/34 of a turn": 360 * 13 / 34}
heads = {}
for name, angle in angles.items():
heads[name], overlap = head(angle)
print(name, round(angle, 4), "| smallest distance", round(nearest(seeds(angle))[99:].min(), 4), "| overlap", round(overlap, 3))
golden 137.5078 | smallest distance 1.6755 | overlap 0.0
137.3° 137.3 | smallest distance 1.0995 | overlap 139.202
137.6° 137.6 | smallest distance 0.9743 | overlap 397.642
8/21 of a turn 137.1429 | smallest distance 0.3338 | overlap 1098.622
13/34 of a turn 137.6471 | smallest distance 0.5422 | overlap 692.481
At the fractions of a turn, the seeds line up in 21 or 34 straight rays. At 137.3° and 137.6°, they lie along curved arms with gaps between them:

The Fibonacci spirals
Seeds whose numbers differ by a Fibonacci number lie close together, because the Fibonacci fractions \(\tfrac{13}{34}\), \(\tfrac{21}{55}\), \(\tfrac{34}{89}\) of a turn come ever closer to the golden angle. The seeds \(n\), \(n + 34\), \(n + 68\), … therefore form one spiral, and the head has 34 of them winding one way. The seeds \(n\), \(n + 55\), \(n + 110\), … form 55 spirals winding the other way. The figure colors every other spiral of each family:

See Many faces at once for px.Unify.