Search code examples
pythontkinterturtle-graphicsfractalsl-systems

Why doesn't my program generate the dragon curve?


I've written a program that uses an L-System to draw fractals. It appears to work for the Sierpinski triangle, but not for the dragon curve.

I'm aware there are a few questions on the site about using turtle graphics to create a dragon curve but none of them seem to be especially applicable so I've opened my own question. The string my code generates, as the turtle instructions, appears to be correct. I believe the issue is with how turtle is interpreting that string. Why it should work for the Sierpinski triangle and not for the dragon curve is puzzling and led me to think the rules I'd input were wrong, however I've checked multiple sources and they seem correct.

from tkinter import *
import turtle 

Width=500
Height=500


def process_string(string):
    return string.translate(str.maketrans({'X':'X+YF+','Y':'−FX−Y'}))

def createSystem(seed,depth):
    string=seed
    for i in range(depth):  
        string=process_string(string)
        print(string)
    return(string)

def draw(string):

    t = turtle.RawTurtle(canvas) 
    t.penup()
    t.goto(-0.25*Width,0.25*Height)
    t.pendown()
    t.shape("circle")
    t.speed("fastest")

    for char in string:

        if char=="F":
            t.forward(5)
        elif char=="+":
            t.right(90)
        elif char=="-":
            t.left(90)


root=Tk()
canvas=Canvas(width=Width, height=Height)
canvas.pack()    
draw(createSystem("FX",10))
print("COMPLETE")
root.mainloop()

I would expect to see the dragon curve, however the program just produces a squiggly curve made of lines and boxes.


Solution

  • In this line:

     return string.translate(str.maketrans({'X':'X+YF+','Y':'−FX−Y'}))
    

    You're using the Unicode character "−" for the left turns. But in this line:

    elif char=="-":
    

    You're using a basic ASCII hyphen/minus for the left turn. Get these to agree on hyphen/minus and you should release your dragon!

    Although you have a tkinter wrapper around your embedded turtle, this can also be done using just standalone turtle:

    from turtle import Screen, Turtle
    
    TRANSLATION = str.maketrans({'X': "X+YF+", 'Y': "-FX-Y"})
    
    def process_string(string):
        return string.translate(TRANSLATION)
    
    def createSystem(string, depth):
    
        for _ in range(depth):
            string = process_string(string)
    
        return string
    
    def draw(string):
    
        for character in string:
            if character == 'F':
                turtle.forward(5)
            elif character == '+':
                turtle.right(90)
            elif character == '-':
                turtle.left(90)
    
    turtle = Turtle()
    turtle.shape('circle')
    turtle.shapesize(0.2)
    turtle.speed('fastest')
    
    draw(createSystem("FX", 10))
    
    turtle.hideturtle()
    
    screen = Screen()
    screen.exitonclick()
    

    enter image description here

    I assume you're going to use tkinter to add some controls to your program.