Distance measuring with turtle Python - python

I have written a programme that creates a random walk using certain distribution. For example, if it is a Cauchy distribution, the program generates an adequate random number and appends it to the list. Then this list is used by the turtle as a list of steps in a random direction. Now I would like to measure the distance between the turtle in each step and point (0,0) where the random walk is starting and I can't seem to find a good solution for that. It cannot be done with turtle.distance() because I want to draw a graph of dependence this distance on step count. My first idea was to get coordinates of each point that my turtle stops and then try to calculate distance using the Pythagoras theorem, but I make mistakes somewhere along the road and can't acquire them. Could someone explain why, please? Or maybe there is a better way to do this?
cauchylist = []
for i in randomlist:
cauchylist.append(0.15*math.tan(((i-0.5)*math.pi)) )
Franklin = turtle.Turtle()
u = input("Which walk to walk? C - Cauchy or G - Gauss.")
if u == "C":
start()
walk(Franklin, cauchylist)
cv = turtle.getcanvas()
cv.postscript(file="walk_cauchy.ps")
Franklin.penup()
Franklin.fd()
Franklin.end_poly()
coordinates = Franklin.get_poly()
turtle.done()

The distance of the current position of the turtle to the origin is calculated by squaring the posi-values, adding them and getting the square root from that:
from turtle import *
from math import sqrt
from random import seed, choice
seed(42) # ensure same randoms for demonstation purposes
def calc_dist(t):
return sqrt(sum(map(lambda x:x*x, t.pos())))
t = Turtle()
dists = []
for _ in range(20):
t.forward(choice(range(100))-50)
t.left(choice(range(360))-180)
dists.append(calc_dist(t))
print(dists)
Output:
[31.0, 68.97157492789178, 87.25113481192517, 98.48389701852805, 134.17622966161073,
141.40760908816227, 138.90181656585844, 128.76423765225354, 113.79561063931857,
108.70118700467432, 66.53516784607132, 87.40888728250773, 113.65616399911761,
115.22672747425487, 122.12225694530929, 128.35176588895283, 157.57222689310848,
128.33399580245668, 129.3846600939952, 153.87822281203412]
Do the calculation sqrt(sum(map(lambda x:x*x, t.pos()))) after each move of the turtle and store the result in a list.

get_poly() will return a tuple of tuples.
Example:
coordinates = turtle.get_poly()
coordinates = ((0.00,0.00), (100.00,0.00), (128.19,10.26), (136.87,59.50))
You can easily acess each tuple with a for loop
for c in coordinates:
print(c)
Output:
(0.00,0.00)
(100.00,0.00)
(128.19,10.26)
(136.87,59.50)

I would like to measure the distance between the turtle in each step
and point (0,0) where the random walk is starting and I can't seem to
find a good solution for that. It cannot be done with
turtle.distance()
This premise doesn't hold. We can do turtle.distance(0, 0) which doesn't affect the turtle's state but gives us the distance to the origin. To demonstrate, my rework of #PatrickArtner's example using distance():
from turtle import Screen, Turtle
from random import seed, randint
seed(42) # repeatable randomness for demonstration purposes
screen = Screen()
turtle = Turtle()
distances = []
for _ in range(20):
turtle.forward(randint(-50, 50))
turtle.left(randint(-180, 180))
distances.append(turtle.distance(0, 0))
print(distances)
screen.exitonclick()
Console Output
> python3 test.py
[31.0, 68.97157492789178, 87.25113481192517, 98.48389701852807, 134.17622966161073,
141.40760908816227, 138.90181656585844, 128.7642376522535, 113.79561063931855,
108.70118700467431, 66.5351678460713, 87.4088872825077, 113.65616399911758,
115.22672747425486, 122.12225694530927, 128.35176588895283, 157.57222689310848,
128.33399580245668, 129.3846600939952, 153.87822281203412]
>
I cannot use t.forward and t.left commands because I get an error
"invalid command name . canvas turtle". I think it's because my turtle
walk is defined by function looking like that:
def walk(turtle, steps):
x = 0
y = 0
for i in steps:
kat = random.random() * 360
turtle.setheading(kat)
turtle.forward(math.fabs(i))
bounds(turtle)
However, if I don't use it as on the example You gave, I create list
full of only last distance value. Can anything be done about that?
We'd need to see more code to address this issue, e.g. the definition of bounds() and so forth.

Related

How to choose a random coordinate for the position of a turtle circle?

How do I get a python turtle circle to choose it's position randomly?
Here is my code for one circle:
asteroid.pencolor('white')
asteroid.fillcolor('grey')
asteroid.begin_fill()
asteroid.hideturtle()
asteroid.penup()
asteroid.speed(11)
asteroid.setposition(350,-200)
asteroid.pendown()
asteroid.circle(40)
asteroid.end_fill()
Place this up top
from random import randint
And change your setposition to:
asteroid.setposition(randint({min-value},{max-values}), randint({min-value},{max-values}))
Where min and max-values are of course the minimum and maximum values you want.
https://www.codecademy.com/forum_questions/55c1eabde39efed2110002ae?locale=en
Take a look at Python's random package. Specifically:
import random
random_point = (random.randint(min_x, max_x), random.randint(min_y, max_y))
This will give you random x and y coordinates, within the bounds defined by variables min_x, max_x, min_y, and max_y.
import the random module, and use the randint method. An example for a random number: print(random.randint(1, 10))
In this case, point = (random.randint(low_x, high_x), random.randint(low_y, high_y))
Probably Something Like The Following:
import turtle
from random import *
asteroid = turtle.Pen()
asteroid.penup()
asteroid.goto(randint(-100,0),randint(0,100))
asteroid.pendown()
asteroid.pencolor('white')
asteroid.fillcolor('grey')
asteroid.begin_fill()
asteroid.hideturtle()
asteroid.penup()
asteroid.speed(11)
asteroid.setposition(350,-200)
asteroid.pendown()
asteroid.circle(40)
asteroid.end_fill()

Move turtle slightly closer to random coordinate on each update

I'm doing a homework and I want to know how can I move turtle to a random location a small step each time. Like can I use turtle.goto() in a slow motion?
Someone said I should use turtle.setheading() and turtle.forward() but I'm confused on how to use setheading() when the destination is random.
I'm hoping the turtle could move half radius (which is 3.5) each time I update the program to that random spot.
You use the term half radius twice in your question's title and text, but never really explain it. For purposes of your question, we're just talking about some arbitrary small distance -- correct?
I would avoid import time and time.sleep() as they work against an event-driven world like turtle. Instead, I would use turtle's own ontimer() method to keep things in synch:
from turtle import Screen, Turtle
from random import randrange
HALF_RADIUS = 3.5 # unexplained constant
DELAY = 1000 # milliseconds
WIDTH, HEIGHT = 640, 480
CURSOR_SIZE = 20
def forward_slowly(distance):
if distance > 0:
turtle.forward(min(distance, HALF_RADIUS))
remaining = max(distance - HALF_RADIUS, 0)
screen.ontimer(lambda d=remaining: forward_slowly(d), DELAY)
else:
screen.ontimer(move_target, DELAY)
def move_target():
x = randrange(CURSOR_SIZE - WIDTH//2, WIDTH//2 - CURSOR_SIZE)
y = randrange(CURSOR_SIZE - HEIGHT//2, HEIGHT//2 - CURSOR_SIZE)
target.goto(x, y)
target.pendown()
turtle.setheading(turtle.towards(target))
forward_slowly(turtle.distance(target))
screen = Screen()
screen.setup(WIDTH, HEIGHT)
turtle = Turtle('turtle')
turtle.speed('slowest')
turtle.width(3)
target = Turtle('turtle')
target.speed('fastest')
target.color('red')
target.penup()
move_target()
screen.exitonclick()
(Any resemblence to a Pepé Le Pew cartoon is purely coincidental.)
Do you mean that you want to move a small step, stop, and repeat? If so, you can ‘import time’ and add ‘time.sleep(0.1)’ after each ‘forward’

How to draw numbers from a random list to use as Y coordinates for turtle graphics

I am trying to generate a list of random Y coordinates for a turtle graphics program that needs to draw flowers, but to prevent the flowers from drawing over each other I need to draw them from back to front. What I need to do is sort the random list from largest to smallest, then have it draw the flowers in that order.
I have already set up the program to generate 9 random numbers and sort them from largest to smallest, but I don't know how to draw the numbers from that list in order and assign them the Y value of the flower
This is my code for generating the random list:
def draw_stem(t,StemX,StemY):
StemYcoordinates=random.sample(range(-200,0),9)
sorted(StemYcoordinates, key=int)
But I am having trouble connecting it to this part of the code where it goes to the xy position where I want the flower to be drawn
for i in range(9):
t.setheading(90)
t.pensize(7-(StemYcoordinate//40))
t.color("#39ff14")
t.penup()
t.goto(StemX,StemYcoordinates)
t.down()
any help would be greatly appreciated
I think for your code, you will need to use the setpos() method.
This method treats the screen in turtle like a coordinate plane with four quadrants.
Using this, set the x and y coordinates accordingly, or randomly if you want to.
For example, this puts the turtle in a random spot every time you run it:
from turtle import *
t = Turtle()
t.penup()
from random import randint
x = randint(-200, 200)
y = randint(-200, 200)
t.setpos(x, y)
Hope this Helps!!!
Based on the description of your problem, you seem to want something like:
from turtle import Screen, Turtle
from random import sample, random
RADIUS = 100
PETALS = 10
def draw_petal(t, radius):
heading = t.heading()
t.circle(radius, 60)
t.left(120)
t.circle(radius, 60)
t.setheading(heading)
def draw_flower(t):
for _ in range(PETALS):
draw_petal(t, RADIUS)
t.left(360 / PETALS)
def draw_flowers(t, stemX):
stemYcoordinates = sorted(sample(range(-200, 0), 9))
for stemYcoordinate in stemYcoordinates:
t.setheading(90)
t.pensize(7 + stemYcoordinate // 40)
t.color(random(), random(), random())
t.penup()
t.goto(stemX, stemYcoordinate)
t.pendown()
draw_flower(t)
screen = Screen()
turtle = Turtle(visible=False)
turtle.speed('fastest') # because I have no patience
draw_flowers(turtle, 0)
screen.exitonclick()
But if this isn't what you're looking for, take the time to reread and edit your question to clarify what you want to do. Add more (if not all) of the code you've written so far, to make it clear what you need help with.

Generate Random Numbers Within A Seed

Relatively new to python so apologies for any terrible coding.
I'm using blender to create random stimuli sets using the sapling add on to create something like
I also want to define a random camera position and angle in a hemisphere above the plane which I do by producing two random numbers (u and v in my example below).
However, calling the py.ops.curve.tree_add function (which generates the tree) sets some kind of seed which means that the random numbers I produce are always the same.
E.g. in the example code it creates a range of different trees depending on the randint() generated for basesize/ basesplit.
However, for each unique tree these generate, the random numbers u and v are always the same. This means for every random tree I generate, the camera angle is specific for that tree (and not completely random)
I assume this occurs via some seed, so I was wondering if there is a way to tell python to generate a random number and ignore any seeds?
Best,
Example code: (import bpy is the python api module for blender)
### libraries
import bpy
from random import random, randint
u = random()
v = random()
obj = bpy.ops.curve.tree_add(bevel = True,
prune = True,
showLeaves = True,
baseSize = randint(1,10)/10,
baseSplits = randint(0,4))
print(u)
print(v)
in case it helps, my function to generate a sphere to place the camera and then point it towards the object is (I haven't included the libraries/ rest of the script etc. here for brevity- it creates a point around a defined centre which is a radius r away and works apart from the above issue):
#generate the position of the new camera
def randomSpherePoint(sphere_centre, r, u, v):
theta = 2 * pi * u
phi = acos(2 * v - 1)
x = centre[0] + (r * sin(phi) * cos(theta))
y = centre[1] + (r * sin(phi) * sin(theta))
z = fabs(centre[2] + (r * cos(phi)))
return(x,y,z)
hemisphere_point = randomSpherePoint(centre, radius, u, v)
print(hemisphere_point)
#add a camera at this randomly generated hemispheric location
bpy.ops.object.camera_add(location = hemisphere_point)
the_camera = bpy.data.objects["Camera"]
#rotate the camera to the centre of the plane
camera_direction = centre - camera_location
camera_rotation = camera_direction.to_track_quat('-Z', 'Y')
the_camera.rotation_euler = camera_rotation.to_euler()
You can make a instance of random using the class random.Random.
An example would be:
randomgen = random.Random()
randomgen.uniform(0,1)
This reason is:
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state
(from https://docs.python.org/3/library/random.html)
Python's random module provides the seed() method for you to set the seed.
import random
random.seed(12)
random.randint(0,100)
Another option to get variations in your trees is to provide a different seed for the sapling addon to work with. You can find it in the operator adjustment panel above the tree scale, the python API also accepts a seed paramater.
bpy.ops.curve.tree_add(seed=myseed)

How to simplify my codes?

I wrote a program for a class using recursion to mimic certain kinds of simple branching structures like trees. I thought my code was great until I showed my professor. He told my code was too complicated and said I would need to simplify it. Besides spacing them out, I'm not sure what else I could do. Any tips? (I'm a beginner so go easy on me.) This program creates multiple trees with varying thickness, number of branch and at different coordinates.
import random
import turtle
##I'm using a python module called turtle to visualize results
p1 = turtle.Pen()
##Creates a pen
p1.tracer(True)
## Shows pen drawing
p1.up()
p1.left(90)
d=random.randint(0,2)
## Varying thickness of branch
length=150
##Length of branches
contract=random.uniform(.5,1)
## Varying degree of contraction
branch=random.randint(5,8)
## Varying amount of branches
first=random.randint(30,70)
## Varying first degree of branch
next=random.randint(1,30)
## Varying degree between each branches
number1=random.randint(10,20)
number2=random.randint(-100,100)
number3=random.randint(-100,100)
# Range of numbers used for coordinates
def drawFern1(pen, depth, length, contractBy, branches, firstBranchAngle, nextBranchAngle):
if depth > 0:
#Pen's Position and heading
heading = pen.heading()
position = pen.position()
pen.width(depth)
pen.forward(length)
pen.left(firstBranchAngle)
for i in range(branches):
drawFern1(pen, depth-1, contractBy*length, contractBy,branches,firstBranchAngle,nextBranchAngle)
pen.right(nextBranchAngle)
pen.setheading(heading)
pen.setposition(position)
# Ensures that multiple trees are created each at different coordinates.
for i in range(number1):
p1.sety(number2)
p1.setx(number3)
p1.down()
drawFern1(p1,d,length,contract,branch,first,next)
number2 = random.randint(-100,100)
number3 = random.randint(-100,100)
p1.up()
This code looks pretty solid to me, especially for a Python beginner. I've seen much worse.
If I were writing it, I think I'd calculate number2 and number3 only inside the main for loop - a priming definition as you have here is often convenient for a while loop, but not necessary in this case. I would also try to use more explanatory variable names, and depending on the problem statement I might require the randomly generated depth value to be at least 1 - if depth is generated as 0, nothing will be drawn.
My version of this would look like this:
import random
import turtle
def drawFern(pen, depth, length, contraction, branches, firstBranchAngle, nextBranchAngle):
if depth > 0:
# Pen's Position and heading
heading = pen.heading()
position = pen.position()
pen.width(depth)
pen.forward(length)
pen.left(firstBranchAngle)
for i in xrange(branches):
drawFern(pen, depth-1, contraction*length, contraction, branches, firstBranchAngle, nextBranchAngle)
pen.right(nextBranchAngle)
pen.setheading(heading)
pen.setposition(position)
# I'm using a python module called turtle to visualize results
# Creates a pen
pen = turtle.Pen()
# Shows pen drawing
pen.tracer(True)
pen.up()
pen.left(90)
# Configure initial state
# Varying depth of recursive fern
depth = random.randint(1,2)
# Length of branches
length = 150
# Varying degree of contraction
contraction = random.uniform(.5,1)
# Varying number of branches
branches = random.randint(5,8)
# Varying first degree of branch
first_angle = random.randint(30,70)
# Varying degree between each branches
next_angle = random.randint(1,30)
number_of_trees =random.randint(10,20)
for i in xrange(number_of_trees):
new_x = random.randint(-100, 100)
new_y = random.randint(-100, 100)
pen.setx(new_x)
pen.sety(new_y)
pen.down()
drawFern(pen, depth, length, contraction, branches, first_angle, next_angle)
pen.up()
In addition to moving the x and y coordinate randomization into the main loop, moving the recursive function definition earlier in the file, and using some more explicit variable names, I've used xrange calls instead of range calls - a trivial optimization if you're on Python 2.x. If you're on Python 3, range is correct. But these are minor changes.
You could also throw in an if clause before the range(branches) loop to not even try if depth equals 1 - that's another minor optimization, although not one that will make a big difference.
I thought my code was great until I showed my professor. He told my
code was too complicated and said I would need to simplify it.
This is rather complicated code given the quality of trees that it draws:
Drawing just vertical lines and blank screens are within the random parameters of the program as written! Let's rework the program to move some of the randomness from the static configuration code into the recursive routine itself. We'll also fine tune the random ranges a bit and clean up the code, primarily by eliminating variables that are only set and used once:
from random import randint, uniform
from turtle import Screen, Pen # Using python turtle module to visualize results
# Configure initial state
DEPTH = randint(3, 4) # Varying thickness and splitting of branches
LENGTH = randint(125, 150) # Length of branches
CONTRACT_BY = uniform(0.4, 0.8) # Varying degree of contraction
def drawFern(pen, depth, length, contractBy):
if depth < 1:
return
# Save pen's position and heading
heading = pen.heading()
position = pen.position()
pen.width(depth * 1.5) # pen thickness depends on branching
pen.forward(length)
pen.left(randint(30, 70)) # Varying first degree of branch)
for _ in range(randint(5, 8)): # Varying amount of branches
drawFern(pen, depth - 1, contractBy * length, contractBy)
pen.right(randint(5, 30)) # Varying degree between each branches
# Restore pen's Position and heading
pen.setheading(heading)
pen.setposition(position)
screen = Screen()
pen = Pen(visible=False)
pen.left(90)
screen.tracer(False)
# Ensure that multiple trees are created each at different coordinates.
for i in range(randint(10, 20)):
pen.penup()
pen.setposition(randint(-200, 200), randint(-300, 0))
pen.pendown()
drawFern(pen, DEPTH, LENGTH, CONTRACT_BY)
screen.tracer(True)
screen.mainloop()

Categories