Increase Spirograph loop speed in turtle

0

Using these references: Spirograph Patterns and python 3.4 spirograph error The following code was 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 at Repl.it

Problem

How to increase the speed of a Sprint program in turtle?

Increasing the loop value from t (eg from 0.01 to 0.2), the spirograph loses shape and the highest turtle speed is turtle.speed(0) .

The spirograph of several extra turns in lines already made before leaving the loop, to optimize there would be the possibility of leaving the loop after finishing a lap in the spirograph. But I could not find a way to accomplish this.

How to get out of the loop after a spin on the spirograph?

    
asked by anonymous 04.07.2018 / 19:42

1 answer

1
  

How to increase the speed of a sprint program in turtle?

Turtle is slow - but the biggest slowness actually comes from the fact that it refreshes the screen after every step, however small, by default. In addition to speed (0), you can call the turtle.tracer method that accepts two parameters: every "step" it actually updates the screen, and how long to wait between each update. That alone leaves 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 do not see much sense in showing the figure itself in this program, where the most important is the drawing, and not understand "to which side 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 functions XCoord and Ycoord are called several times, calculate their values and nothing is done with the return value of them, - just call them as parameters at turtle.goto and the return line has some effect.

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

  

How do I exit the loop?

I put this extra question because it is simpler to do: the window.exitonclick() call is cool, but it is for your program - so it can not be done inside the loop. As it seems to me, the most important thing is to be able to exit when the drawing is complete to run the program with other parameters, it is possible to get tkinter connections "inside" the turtle, and directly connect a click with the end of the program.

Inside your main function, before 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 a handler for the event of clicking the same-1 button while drawing is being done. The turtle module has its onclick method too - but for some reason it does not 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 parameters of your turtle within from the window itself - without leaving the program to reconfigure drawing parameters.

  

How do you get out of the loop after a spin on the spirograph?

I did not detect the loop by re-drawing full laps in the spirograph. The correct way is to compare the value of "t" with 2 * pi - or if you have a "t" divisor inside the sine and cosine functions, worry that the value passed to them is at most 2 * pi. Your code already does this.

As I have cleaned up calls to XCoord functions, and put the two or three more things, I put the whole 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()
    
04.07.2018 / 22:11