Skip to content

Instantly share code, notes, and snippets.

@justvanrossum
Last active February 10, 2016 12:32
Show Gist options
  • Save justvanrossum/8b2eaaf1307fa8dddccc to your computer and use it in GitHub Desktop.
Save justvanrossum/8b2eaaf1307fa8dddccc to your computer and use it in GitHub Desktop.
DrawBot: Create an animated flower-like pattern by drawing circles on a donut.
# nCirclesH = 18; nCirclesV = 6:
# http://dailydrawbot.tumblr.com/post/138985675364/psychodonut-2
# nCirclesH = 38; nCirclesV = 28:
# http://dailydrawbot.tumblr.com/post/139047595845/psychodonut-3
def project(x, y, innerR, outerR, phase):
# convert from "donut space" to normal space
angle = 2 * pi * x
f = (cos(phase + pi * y) + 1) / 2
R = innerR + f * (outerR - innerR)
x1 = R * cos(angle)
y1 = R * sin(angle)
return x1, y1
def projectZ(y, phase):
return sin(phase + pi * y)
nCirclesH = 18 # must be even
nCirclesV = 6 # ditto
canvasSize = 500
nFrames = 50
for frame in range(nFrames):
framePhase = frame / nFrames
newPage(canvasSize, canvasSize)
frameDuration(1/20)
rect(0, 0, canvasSize, canvasSize)
translate(canvasSize/2, canvasSize/2)
phase = -2 * pi * framePhase / nCirclesV
outerR = 0.48 * canvasSize
innerR = 0.0 * canvasSize
nGap = 6
steps = 35
circleW = 0.5 / nCirclesH
circleH = 1 / nCirclesV
polygons = []
for j in range(nCirclesV):
for i in range(nCirclesH):
if (i + j) % 2:
cx = i / nCirclesH - framePhase / nCirclesH
cy = 2 * j / nCirclesV
poly = []
for k in range(steps):
angle = 2 * pi * k / steps
x = cx + circleW * cos(angle)
y = cy + circleH * sin(angle)
poly.append((x, y))
poly = [project(x, y, innerR, outerR, phase) for x, y in poly]
polygons.append((projectZ(cy, phase), poly))
polygons.sort()
for y, pol in polygons:
gray = 0.1 + y/2.5 + 0.5
fill(gray, 0.3 + 0.7*gray, 0.9)
polygon(*pol)
saveImage("PsychoDonut.gif")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment