def g55_spindrift(rng):
"""SPIN DRIFT — triangles rotated to face a vortex centre, scaled by radius.
A logarithmic term in the angle pulls the whole field into a spiral. One or
two weaker secondary vortices, each with a fraction of the primary's pull
and a limited reach, bend the field locally without overpowering it."""
N = 24
c = Canvas(N, "GEOMETRIC", "tri", "spindrift", tiles=False)
C = c.C
cx, cy = rng.uniform(.25, .75), rng.uniform(.25, .75)
spin = rng.uniform(-90, 90)
twist = rng.uniform(20, 140) * rng.choice([1, -1])
grow = rng.uniform(0.55, 1.15)
extras = []
for _ in range(rng.randint(1, 2)):
vx, vy = rng.uniform(0.1, 0.9), rng.uniform(0.1, 0.9)
pull = rng.uniform(0.15, 0.4) # fraction of the primary vortex's pull
reach = rng.uniform(0.15, 0.32) # influence fades to zero past this radius
extras.append((vx, vy, pull, reach))
for i in range(N):
for j in range(N):
u, v = (i + 0.5) / N, (j + 0.5) / N
dx, dy = u - cx, v - cy
d = math.hypot(dx, dy) + 1e-6
wx, wy = dx / d, dy / d
for vx, vy, pull, reach in extras:
edx, edy = u - vx, v - vy
ed = math.hypot(edx, edy) + 1e-6
fall = clamp(1 - ed / reach)
if fall <= 0:
continue
w = pull * fall
wx += w * edx / ed
wy += w * edy / ed
a = math.degrees(math.atan2(wy, wx)) + spin + twist * math.log(d + 0.12)
r = 0.46 * C * clamp(0.42 + grow * d * 1.3)
x, y = c.center(i, j)
c.tri(x, y, r, rot=a)
return c