Turtle art!
This notebook recreates some famous works of art with simple turtle code β and every drawing is a WasmMakie.jl figure, so the interactive ones recompute right in your browser via WebAssembly.
using WasmMakie, PlutoUI"The Starry Night"
Vincent van Gogh (1889)
function draw_star(turtle, points, size)
for i in 1:points
right!(turtle, 360 / points)
forward!(turtle, size)
backward!(turtle, size)
end
end"Tableau I"
Piet Mondriaan (1913)
"Een Boom"
Luka van der Plas (2020)
# Built inline (a plain `let`, NOT a `do` closure): the L-system is written
# ITERATIVELY with an explicit work-stack of (x, y, heading, depth), so we never
# mutate-and-restore turtle fields across recursive calls β and we don't pass a
# bond-capturing closure that allocates a stack to `turtle_drawing_fast`, both of
# which WasmTarget can't yet compile. Same strokes + same render as the others.
fractal = let
t = Turtle()
penup!(t)
backward!(t, 15)
pendown!(t)
stack = NTuple{4,Float64}[(t.pos[1], t.pos[2], t.heading, 0.0)]
while !isempty(stack)
st = pop!(stack)
x = st[1]; y = st[2]; h = st[3]; depth = st[4]
depth >= 10.0 && continue
size = fractal_base * 0.5 ^ (depth * 0.5)
t.pos = (x, y)
t.heading = h
color_hsl!(t, depth * 30.0, 0.8, 0.5)
forward!(t, size * 8.0)
nx = t.pos[1]; ny = t.pos[2]
push!(stack, (nx, ny, h + fractal_tilt / 2.0, depth + 1.0))
push!(stack, (nx, ny, h + fractal_tilt / 2.0 - fractal_angle, depth + 1.0))
end
# same figure render as `turtle_drawing` (white background β no backdrop span)
fig = Figure(size = (320, 320))
ax = Axis(fig[1, 1])
hidedecorations!(ax)
hidespines!(ax)
ax.xmin = -15.0; ax.xmax = 15.0
ax.ymin = -15.0; ax.ymax = 15.0
for k in 1:length(t.xs)
lines!(ax, t.xs[k], t.ys[k]; color = t.cols[k], linewidth = 1.5)
end
fig
end"Een coole spiraal"
fonsi (2020)
@bind angle Slider(0:90; default=20)turtle_drawing() do t
let i = 0.0
while i <= 10.0
right!(t, angle)
forward!(t, i)
i += 0.1
end
end
end# A tiny deterministic PRNG (xorshift64*) β pure Julia, so the random art
# recomputes identically inside the wasm islands. Seeded by the buttons.
begin
mutable struct ArtRNG
state::UInt64
end
ArtRNG(seed::Integer) = ArtRNG(UInt64(seed + 1) * 0x9e3779b97f4a7c15 + 0x2545f4914f6cdd1d)
function nextfloat!(r::ArtRNG)
s = r.state
s β»= s << 13
s β»= s >> 7
s β»= s << 17
r.state = s
Float64(s >> 11) / 9.007199254740992e15 # [0, 1)
end
rand_between!(r::ArtRNG, lo, hi) = Float64(lo) + nextfloat!(r) * (Float64(hi) - Float64(lo))
rand_choice!(r::ArtRNG, xs) = xs[1 + Int(floor(nextfloat!(r) * length(xs)))]
end