I tried to create a recursive process for making the dragon curve. Here’s what I made.
Firstly, the output of this algorithm will be a list of Lefts and Rights, e.g.
LRRLRLRLRLRLR (this is just a random list)
To follow these instructions, draw a line of length 1, then turn whichever letter is first (in this case, Left 90 degrees). then draw another line of length 1, and so on. When doing the dragon curve, you can start with an L, or an R, providing mirrored versions of the curve.
Here is the process:
- Start with an “L” or an “R” – R
- Take this term, and flip it backwards – “R”
- Change all “L”‘s to “R”‘s, and “R”‘s to “L”‘s – L
- Append this term to your original series (R), but leave a gap in the middle – R_L
- Put an “R” in the gap – RRL
It’s hard to see with few terms, so I’ll demonstrate the next stage as well
- Flip it – LRR
- Change all “L”‘s to “R”‘s, and visa versa – RLL
- Append this to the original (RRL), and leave a gap between them – RRL_RLL
- Put an “R” in the gap – RRLRRLL
And keep going. This isn’t the most elegant process for calculating the Dragon curve, but it has some advantages.
At this point, I decided to make a program that draws it.
import turtle import os import tempfile import shutil from Tkinter import * def Invert(n): n = n[::-1] new = "" for x in n: if x is "R": new += "L" elif x is "L": new += "R" return new def Iter(n): return n + "R" + Invert(n) def Dragon(n): LastIteration = "R" for x in range(0,n-1): #Edited to do the right number of iterations LastIteration = Iter(LastIteration) return LastIteration def Colour(n): n += 1 colour = "" for x in range(1,2**n): if is_power(x) == False: colour += "R" else: colour += "B" return colour def is_power(n): n = float(n) if n == 1: return True if n == 2: return True n = float(n/2) if n == 2.0: return True elif n > 2.0: return is_power(n) else: return False turtle.tracer(0, 0) def DrawDragon(R,N,T=0): dragon = turtle.Turtle() dragon.right(T) dragon.hideturtle() dragon.turtlesize(0) turtle.update() turtle.setup( width = 1500, height = 1000, startx = None, starty = None) dragon.speed(0) dragon.penup() dragon.setx(200) dragon.sety(0) dragon.pendown() C = Colour(R) R = Dragon(R) n = 0.0 m = 0.0 dragon.pencolor("blue") #r = lambda: random.randint(0,255) import random for x in range(0,len(R)): dragon.forward(N) if C[x] is "B": dragon.pencolor((m,m,n)) turtle.update() #dragon.pencolor(('#%02X%02X%02X' % (r(),r(),r()))) #r = lambda: random.randint(0,255) if n >= 0.0: if n <= 0.92: n += 0.08 else: if m < 0.6: m += 0.1 if R[x] is "R": dragon.right(90) else: dragon.left(90) print "Done" #ts = turtle.getscreen() #ts.getcanvas().postscript(file="DohertyDragon.eps") turtle.done() DrawDragon(17,1,0)
The main function here is DrawDragon, which takes 3 variables – number of iterations, the size of the line drawn, and the angle to draw at. There are a few other variables set within the function itself, such as the x and y starting position (alter these if the image goes offscreen), and the colour generation, which I set to blue for various school related house prize reasons. Here are some sample images generated:
Because of the finite resolution, when tilting the dragon while drawing you can get some cool effects.