Increase Spirograph Loop Speed in Turtle

Asked

Viewed 337 times

-1

Using these references: Spirograph Patterns and python 3.4 Spirograph error the following code has been created:

Code

import turtle
import math
import random

def Xcord(R,r,p,t):
    return (R-r) * math.cos(t) - (r+p) * math.cos((R-r)//r*t)

def Ycord (R,r,p,t):
    return (R-r) * math.sin(t) - (r+p) * math.sin((R-r)//r*t)

def t_iter(R,r,p):
    t=0
    turtle.up()
    Xcord(R,r,p,t)
    Ycord(R,r,p,t)
    while t < 2*math.pi:
        t+=0.01
        turtle.goto(Xcord(R,r,p,t),Ycord(R,r,p,t))
        random_hex = random_color()
        turtle.color(random_hex)
        turtle.pencolor(random_hex)
        turtle.down()
    return float(Xcord(R,r,p,t))
    return float(Ycord(R,r,p,t))

def p_iter(count, p_iter_length):
        return 10.0 + (count*p_iter_length)

def random_color():
    r = lambda: random.randint(0, 255)
    return('#%02X%02X%02X' % (r(), r(), r()))

def main():
    window = turtle.Screen()
    window.bgcolor("black")
    turtle.speed(0)
    turtle.shape("turtle")
    R=100
    r=4
    count=0
    p = 10.0
    while p <=100.0:
        p = p_iter(count, 10.0)
        t_iter(R,r,p)
        Xcord(R,r,p,t_iter(R,r,p))
        Ycord(R,r,p,t_iter(R,r,p))
        count+=1
    window.exitonclick()

main()

See working on Repl.it

Problem

How to Speed up a Spirograph Program on Turtle?

Increasing the value of the loop t (ex.: from 0.01 to 0.2), the spirograph loses shape and the higher speed of Turtle is turtle.speed(0).

The spirograph of the several extra turns in lines already made before exiting the loop, to optimize there would be the possibility of exiting the loop after finishing a turn in the spirograph. But I couldn’t find a way to accomplish this.

How to exit the loop after a turn on the spirograph?

1 answer

1


How to Speed up a Spirograph Program on Turtle?

Turtle is slow - but the biggest slowness really comes from the fact that she updates the screen after every step, no matter how small, by default. In addition to speed(0), you can call the method turtle.tracer which accepts two parameters: every few "steps" it will actually update the screen, and how much to wait between each update. That alone makes your program fast enough for you to experience more - just below the line

window = turtle.Screen()

Put

turtle.tracer(100,0)

You may also want to hide the turtle - I don’t see much point in showing the figure itself in this program, where the most important thing is drawing, and not understanding "which way the turtle is going". Instead of calling turtle.shape(...), try calling turtle.hideturtle().

Now, there are some conceptual errors in your program - in particular the Xcoord and Ycoord functions are called several times, calculate their values and nothing is done with the return value of them, - only the call the same as parameters to turtle.goto and in the Return line has some effect.

These functions are not so complex as redundant calls once for every step - but you can simply store their values in local variables, instead of calling them again each time you need the values. In the same way two commands return inside a function do nothing: only the first is executed, and the function is stopped.

How to get out of the loop?

I asked this question why it is simpler to do: the call window.exitonclick() It’s cool, but it stops your program - so it can’t be done inside the loop. As, it seems to me, the most important thing is that you can leave when the drawing is complete to run the program with other parameters, it is possible to reach the links of Tkinter "inside" of Turtle, and directly connect a click with the end of the program.

Within its main function, before the while put these three lines:

canvas = window.getcanvas()
root = canvas._nametowidget(canvas.winfo_parent())
canvas.bind("<Button-1>", lambda event: root.destroy())

ready - we added an Handler to the event by clicking the same button-1 while the drawing is being done. The Turtle module has its "onclick" method as well - but for some reason it doesn’t work while the drawing is being done.

Note that with the above method, you can use the "root" window to extend your application with Turtle to a normal Tkinter application - you can add inboxes (tkinter.Entry) and buttons to change your Turtle parameters within the window itself - no need to exit the program to reconfigure drawing parameters.

How to exit the loop after a turn on the spirograph?

I didn’t detect the loop re-drawing full laps in the spirograph. The correct way is to compare the value of "t" to 2 * pi - or if you have a "t" divider within the sine and co-sine functions, worry that the value passed to them is at most 2 * pi. Your code already does that.

As I cleared the extra calls to Xcoord functions, and put the two or three more things, I put the entire program back:

import turtle
import math
import random

def Xcord(R,r,p,t):
    return (R-r) * math.cos(t) - (r+p) * math.cos((R-r)//r*t)

def Ycord (R,r,p,t):
    return (R-r) * math.sin(t) - (r+p) * math.sin((R-r)//r*t)

def t_iter(R,r,p):
    t=0
    turtle.up()
    while t < 2*math.pi:
        t+=0.01
        x = Xcord(R,r,p,t)
        y = Ycord(R,r,p,t)
        turtle.goto(x, y)
        random_hex = random_color()
        turtle.color(random_hex)
        turtle.pencolor(random_hex)
        turtle.down()


def p_iter(count, p_iter_length):
        return 10.0 + (count*p_iter_length)

def random_color():
    r = lambda: random.randint(0, 255)
    return('#%02X%02X%02X' % (r(), r(), r()))

def main():
    window = turtle.Screen()
    turtle.tracer(100,0)

    canvas = window.getcanvas()
    root = canvas._nametowidget(canvas.winfo_parent())
    canvas.bind("<Button-1>", lambda event: root.destroy())

    window.bgcolor("black")
    turtle.speed(0)
    turtle.hideturtle()
    R=100
    r=4
    count=0
    p = 10.0
    while p <=100.0:
        p = p_iter(count, 10.0)
        t_iter(R,r,p)
        count+=1
    window.exitonclick()

main()
  • I learned a lot from these changes, very detailed =]. What about Como sair do loop após uma volta no espirógrafo?, if you notice in the Repl.it of the question. It really overwrites what has already been drawn, at least apparently. But with these optimizations, even if you pass it will not be very visible. I will be able to test Turtle more!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.