The Dragon Curve is an interesting and beautiful fractal. It is actually a family of self-similar fractals, but I will be focusing on the most famous, the Heighway Dragon, named after one of the NASA physicists who studied it, John Heighway. The Dragon Curve gets it's name for looking like dragon, perhaps a sea dragon (apparently). Even if it doesn't look like a dragon to you, you must admit it's a cool name.
And it's not just the name, or the shape, the Dragon Curve has lots of amazing properties:
-It can tessellate the plane
-It is made of only one line
-That line never goes over itself, so theoretically one big enough can hit every single point in a grid exactly once
-If you take a strip of paper and fold it in half, then fold that in half, and that in half, and so on, and then unfurl it, you will get a Dragon Curve
-If you take all the solutions to polynomials with coefficients in a certain range and graph them on an complex plane, you will find the dragon curve in places
Here are some sites that can tell you more:
In this Instructable, I will be showing you how to write a python 3 program using the turtle graphics module to generate the Dragon Curve.
Step 1: The Pattern
The Dragon Curve, like all fractals, has multiple, progressively more complex forms, called iterations. Above are the 2nd, 4rd, 6th, and 8th iterations of the Dragon Curve. They are all more complex than the last, but all have the same shape, though different orientations. From my personal observations, it seems to turn 45 degrees clockwise every iteration. The cover picture is the 17th iteration. Looking at the above pictures, you can see that the Curve is made of multiple segments at right angles. You can represent each iteration as a string of right and left turns.
For example, the first iteration is: R
The second iteration is: R R L
The third iteration is: R R L R R L L
And so on. You can therefor generate different iterations of the Dragon Curve by generating these strings. There are many more ways of generating the Curve, but I will be focusing on this method. In order to find the next iteration from one you already have:
1. Add a right turn to the string
2. Take the original string and flip it backward (first character last, last first)
3. Take the flipped version and switch all the rights to lefts and the lefts to rights
4. Add the flipped version to the new string we made in the first step
Lets try this out to to find the 4th iteration from the 3rd:
1. RRLRRLL + R = RRLRRLLR
2. RRLRRLL flipped = LLRRLRR
3. LLRRLRR switched = RRLLRLL
4. RRLRRLLR + RRLLRLL = RRLRRLLRRRLLRLL
This way we find that the 4th iteration can be represented as RRLRRLLRRRLLRLL.
In the next step I will show how to automate this task and draw it using python.
Step 2: The Program
In this step I will explain each part of the program. A fully commented version is available at the bottom.
To start we must have a few things:
This imports the turtle module, which we will be using to display the rights and lefts we generate. You use it to draw by giving commands to the 'turtle', which moves about the screen, drawing a line. This module is useful for our purposes as you can easily tell the turtle to turn right or left or go forward without having to calculate where to place lines.
r = 'r' l = 'l'
Here we create variables r and l and assign them their appropriate characters. This step is not truly necessary as you could just write it in the program as a string, but I believe the program flows more easily using variables rather than strings.
old = r new = old
This sets both old, which is the last iteration generated, and new, the iteration being generated, to a right. Old is set to right because that is the first iteration that all of them are based off of. New is also set to right just in case the first iteration it requested. In that case, it will not generate anything and immediately print new.
iteration=int(input('Enter iteration:'))length=int(input('Enter length of each segment:')) pencolor=input('Enter pen color:') bgcolor=input('Enter background color:')
This block of code takes in all of the users choices, the iteration to be generated (iteration), the length of each segment that makes up the Dragon Curve (length), the color to draw the Curve in (pencolor), and the background color of the turtle graphics window (bgcolor). The segment length can be useful when generating higher iterations as the the Curve can extend off screen with too long segments. The last two choices, the colors, are fun to play around with to make pretty designs.
cycle = 1
A certain iteration is generated by building up each iteration from the first R, cycling through some steps to get the next one each time. This variable holds the current cycle, so we first assign it the value of 1.
Now we can start generating the R and L pattern for the desired iteration:
We will continue generating the next iteration until the cycle variable tells us we have reached to iteration requested by no longer being less than it.
new = (old) + (r)
This is the first step of generating the next iteration, adding a right to the end of the last one. We will save this to the new iteration.
old = old[::-1]
This statement completes the second step by using an extended slice to reverse the order of the characters in the old iteration string. The syntax of this string slicing method is [begin:end:step]. Leaving off the begin and end and setting step to -1, makes the entire string switch around.
for char in range(0,len(old)): if old[char] == r: old = (old[:char])+ (l) + (old[char+1:]) elif old[char] == l: old = (old[:char]) + (r) + (old[char+1:])
This block of code switches all of the rights and lefts in the reversed old iteration. It is contained in a for loop which operates for each of the characters in the string, the range being the string length. For each character, it is called from the string and tested. If it's a right, it is replaced with a left by adding the part of the string before the character, a left, and the rest of the string after the character. Otherwise, if it is a left, the same method is used to replace the character with a right.
new = (new) + (old)
This takes new, which is the original old plus a right, and adds the reversed and switched old on the end. The result is saved to new. The next iteration has been generated!
old = new
By saving the new iteration to old, we can use it the next cycle to find the next iteration.
cycle = cycle + 1
This cycle is done and so we advance the cycle variable. The while loop keeps generating the next iteration until it is satisfied by the cycle variable reaching the iteration requested.
printans = input('Display r/l form? (y/n):') if printans=='y': print(new)
Especially with the higher iterations, the string of rights and lefts is so long it is impractical and messy to print it out. This code gives the user a choice. It takes a yes or no answer to whether or not the user wants it printed and, if the answer is yes, prints new, which holds the final iteration.
turtle.ht() turtle.speed(0) turtle.color(pencolor) turtle.bgcolor(bgcolor)
Here we set up the turtle graphics window. We started by hiding the turtle icon and switching off the animation so it is faster. In addition, we apply the user requested colors for the drawing and the background.
Here we tell the turtle to go forward the segment length, making the first line which all the rights and lefts come off of.
for direction in range(0,len(new)): if new[char] == (r): turtle.right(90) turtle.forward(length) elif new[char] == (l): turtle.left(90) turtle.forward(length)
This for loop is similar to the one that switched all the rights and lefts previously in the program. It checks each character in the right-left sequence and make the turtle turn right if it is a right and left if it is a left. After each turn, it also goes forward the desired segment length to complete the angle. In this way, it will graph the entire sequence.
Step 3: Have Fun!
This program is great to play around with! Try changing the iteration, segment length, and the colors to find something beautiful. Above are some of the ones I've made. Happy Dragon Curving!