Dragon Curve¶
In this example, we use turtle graphics to generate fractals.

The curve is generated from a self-similar sequence of left and right turns. The basic pattern is :
dragon(0) -> R
dragon(1) -> dragon(0) + R + inverse(dragon(0) -> RRL
dragon(2) -> dragon(0) + R + inverse(dragon(0) -> RRL
and so on. You find a detailed description on Dragon Curve (Wikipedia)
import numpy as np
from PIL import Image
LEFT, UP, RIGHT, DOWN = range(4)
def left(direction):
"""rotates the direction counter-clockwise"""
return (direction + 3) % 4
def right(direction):
"""rotates the direction clockwise"""
return (direction + 1) % 4
def forward(a, pos, dist, direction, color=0):
"""draws a line on the canvas"""
x, y = pos
if direction == RIGHT:
a[y, x:x+dist] = color
pos = x + dist, y
elif direction == LEFT:
a[y, x-dist:x] = color
pos = x - dist, y
elif direction == UP:
a[y-dist:y, x] = color
pos = x, y - dist
elif direction == DOWN:
a[y:y+dist, x] = color
pos = x, y + dist
return pos
def draw_sequence(a, sequence, pos, size, direction, color):
"""draws a sequence of L and R characters"""
for char in sequence:
pos = forward(a, pos, size, direction, color)
if char == 'R':
direction = right(direction)
else:
direction = left(direction)
pos = forward(a, pos, size, direction, color)
def invert(seq):
return ''.join(['L' if char == 'R' else 'R' for char in seq])
def dragon(fwd, depth):
if depth == 0:
return fwd
else:
bwd = invert(reversed(fwd))
return dragon(fwd + 'R' + bwd, depth-1)
a = np.zeros((600, 850, 3), dtype=np.uint8)
lightblue = (0, 128, 255)
seq = dragon('R', 12)
print(seq)
draw_sequence(a, seq,
pos=(500, 150),
size=4,
direction=UP,
color=lightblue)
im = Image.fromarray(a)
im.save('dragon.png')
Hints¶
generate the curve for a small depth first
if the
sizeparameter is too big, the program will crash because it reaches the array boundaries.
Challenge¶
Try the following self-similar sequence:
:::text
seq(0) -> LRRL
seq(1) -> seq(0) + L + seq(0) + R + seq(0) + R + seq(0) + L + seq(0)
...