2

I'm trying to implement an L-System generated Hilbert curve ,making use of python turtle graphics and recursion. My code seems to be working for the first two levels of recursion n=1 and n=2 but beyond that , the graphics just entangled (although I´m able to observe further modules within them), and I can´t seem to grasp what might be wrong here, do I need some intermediate steps to regenerate the Hilbert modules for deeper levels of recursion? Please see my code below , its relatively simple:

import turtle

def Hilbert_curve(A,rule,t,n):

    if n>=1:
        if rule:
            t.left(90)
            Hilbert_curve(A,not rule,t, n-1)
            t.forward(A)
            t.right(90)
            Hilbert_curve(A, rule,t, n-1)
            t.forward(A)
            Hilbert_curve(A,rule,t, n-1)
            t.right(90)
            t.forward(A)
            Hilbert_curve(A,not rule,t, n-1)
            t.left(90)
        else:
            t.right(90)
            Hilbert_curve(A,rule,t, n-1)
            t.forward(A)
            t.left(90)
            Hilbert_curve(A,not rule,t, n-1)
            t.forward(A)
            Hilbert_curve(A,not rule,t, n-1)
            t.left(90)
            t.forward(A)
            Hilbert_curve(A, rule,t, n-1)
            t.right(90)

def main():
    A=10
    t=turtle.Turtle()
    my_win=turtle.Screen()
    n=2
    rule=True
    Hilbert_curve(A,rule,t,n)
    my_win.exitonclick()

main()

Hilbert n=2

Hilbert n=3

cdlane
  • 40,441
  • 5
  • 32
  • 81
JFT
  • 23
  • 1
  • 5
  • if you like R, here's the one line code `n=scan();a=1+1i;b=1-1i;z=0;for(k in 1:n)z=c((w<-1i*Conj(z))-a,z-b,z+a,b-w)/2;plot(z,t="s")` just change `n` in for loop, e.g. `for(k in 1:5)z=...` This doesn't solve your problem here, but just in case you want to look around :) – dejanmarich Nov 10 '18 at 22:34
  • Well I´m not familiar with R so I don´t really understand what´s your line of code but I´ll check it out – JFT Nov 11 '18 at 15:25

1 Answers1

9

The problem is with your else clause. The rule is already inverted coming in to the function, so you need to treat the rule the same as the then clause:

    else:
        t.right(90)
        Hilbert_curve(A, not rule, t, n - 1)
        t.forward(A)
        t.left(90)
        Hilbert_curve(A, rule, t, n - 1)
        t.forward(A)
        Hilbert_curve(A, rule, t, n - 1)
        t.left(90)
        t.forward(A)
        Hilbert_curve(A, not rule, t, n - 1)
        t.right(90)

However, if we change rule from a boolean to a number, parity, that's either 1 or -1, and then multiply parity by the angle, we can eliminate one of the two clauses of the orignal if statement:

from turtle import Screen, Turtle

def hilbert_curve(turtle, A, parity, n):

    if n < 1:
        return

    turtle.left(parity * 90)
    hilbert_curve(turtle, A, - parity, n - 1)
    turtle.forward(A)
    turtle.right(parity * 90)
    hilbert_curve(turtle, A, parity, n - 1)
    turtle.forward(A)
    hilbert_curve(turtle, A, parity, n - 1)
    turtle.right(parity * 90)
    turtle.forward(A)
    hilbert_curve(turtle, A, - parity, n - 1)
    turtle.left(parity * 90)

screen = Screen()

yertle = Turtle()
yertle.speed('fastest')  # because I have no patience

hilbert_curve(yertle, 10, 1, 4)

screen.exitonclick()

enter image description here

cdlane
  • 40,441
  • 5
  • 32
  • 81
  • Thank you , this works very well. Thank you for giving me the parity variable idea , I hadn´t considered before . My idea was to generate two cases for the two generation rules given in the L-System. Your parity solution is much more elegant – JFT Nov 11 '18 at 15:38