Python Turtle nested polygons/growing shapes - python

Basically we have to make this (20 units in between each polygon) using a function and a for loop:
But it has to work with any sided polygon with any side length. So far I have:
import turtle
tess = turtle.Turtle()
wn = turtle.Screen()
def draw_poly(t, n, sz):
"""
Makes Turtle t draw an n sided polygon of size sz
"""
for i in range(n):
t.forward(sz)
t.left(360/n)
sz = 20 #Length of sides
n = 4 #Number of sides
PosX = 0
PosY = 0
for i in range(5):
draw_poly(tess, n, sz)
tess.penup()
PosX = PosX - 20
PosY = PosY - 20
tess.goto(PosX,PosY)
sz = sz + 40
tess.pendown()
wn.mainloop()
My problem is that it only works with squares, and any other amount of sides/side length makes it off-center. How can I fix this?

You just need a bit of trigonometry. At the top of the script, add the line
from math import pi, tan
Then compute the new PosX, PosY as
PosX = PosX - 20
PosY = PosY - 20/tan(pi/n)

Related

Drawing radiating circular trapezoid pattern with Turtle

I was just wondering how to draw some trapezoids in my turtle code.
I want my output to be like this:
What my output is right now:
Here's the code I've written so far:
import turtle as trtl
num_sides = 6
side_length = 15
circumradius = side_length
trtl.pencolor((245, 176, 66))
trtl.pensize(8)
for move_turtle in range(1):
trtl.penup()
trtl.sety(-circumradius)
trtl.pendown()
trtl.circle(circumradius, steps = num_sides)
circumradius *= 2
side_length = side_length + 8
trtl.pensize(12)
for move_turtle in range(1):
trtl.pencolor((255, 83, 71))
trtl.penup()
trtl.sety(-circumradius)
trtl.pendown()
trtl.circle(circumradius, steps = num_sides)
circumradius *= 2
for move_turtle in range(1):
trtl.pencolor((247, 220, 67))
trtl.penup()
trtl.sety(-circumradius)
trtl.pendown()
trtl.circle(circumradius, steps = num_sides)
circumradius *= 2
trtl.hideturtle()
What techniques can I use to get the desired output?
The approach I often take when given patterns like this is to think about a slight-of-hand trick that can produce the result with less trouble than figuring out how to draw something potentially fussy like a trapezoid.
In this case, if you remove the white spaces, we have a "pie"-shaped circle of different solid colors radiating from the middle. If we can manage to solve that simpler problem, then we can draw white lines on top and wind up with the desired result.
The only trig we need is the angle-to-coordinates formula:
x = cos(radians(angle)) * radius
y = sin(radians(angle)) * radius
Using this, we can iterate over n points (with some rotational offset) along the circumference of a circle with a loop and fill in the colors to make a pie:
import math
import turtle
def draw_pie(t, r, n, colors, rot_offset=0.5):
for i in range(n + 1):
a = 360 / n * (i + rot_offset)
t.color(colors[i%len(colors)])
t.begin_fill()
t.goto(0, 0)
x = math.cos(math.radians(a)) * r
y = math.sin(math.radians(a)) * r
t.goto(x, y)
t.end_fill()
if __name__ == "__main__":
t = turtle.Turtle()
t.screen.setup(540, 540)
t.penup()
t.speed("fastest")
sides = 6
draw_pie(t, 450, sides, ["#dd2", "orange", "#d02"])
t.ht()
turtle.exitonclick()
Next, we need to draw a bunch of thick white lines with square corners. Unfortunately, turtle draws rounded edges by default which aren't suitable for our needs. There are many tricks for making square edges (stamping is a reasonable method). The approach I used here was writing a custom rectangle drawing function that takes advantage of turtle.distance and turtle.setheading(turtle.towards(x, y)) which lets me point to the next point along the circumference of the circle. The rest is just loops to compute angles and picking the right values.
Here's the code:
import math
import turtle
def draw_rect(t, x, y, xx, yy, width):
t.goto(x, y)
t.setheading(t.towards(xx, yy))
t.begin_fill()
for d in [t.distance(xx, yy), width] * 2:
t.forward(d)
t.left(90)
t.end_fill()
def draw_pie(t, r, n, colors, rot_offset=0.5):
for i in range(n + 1):
a = 360 / n * (i + rot_offset)
t.color(colors[i%len(colors)])
t.begin_fill()
t.goto(0, 0)
x = math.cos(math.radians(a)) * r
y = math.sin(math.radians(a)) * r
t.goto(x, y)
t.end_fill()
def draw_reg_polygon(t, r, n, thickness, rot_offset=0.5):
for i in range(n):
a = 360 / n * (i + rot_offset)
x = math.cos(math.radians(a)) * r
y = math.sin(math.radians(a)) * r
a = 360 / n * (1 + i + rot_offset)
xx = math.cos(math.radians(a)) * r
yy = math.sin(math.radians(a)) * r
draw_rect(t, x, y, xx, yy, thickness)
if __name__ == "__main__":
t = turtle.Turtle()
t.screen.setup(540, 540)
t.penup()
t.speed("fastest")
sides = 6
draw_pie(t, 450, sides, ["#dd2", "orange", "#d02"])
t.color("white")
for r in range(50, 500, 100):
draw_reg_polygon(t, r, sides, 45)
t.ht()
turtle.exitonclick()

Random Turtle movement, bound in window

Created the program to randomize the movement of the turtle but cannot get it to break the loop once it touches a boundary (window). Tried a few solutions posted with similar questions but still no luck.
from turtle import Turtle, Screen
import random
def createTurtle(color, width):
tempName = Turtle("turtle")
tempName.speed("fastest")
tempName.color(color)
tempName.width(width)
return tempName
def inScreen(screen, turt):
min_x, max_x = -wn.window_width() / 2 , wn.window_width() / 2
min_y, max_y = -wn.window_height() / 2 , wn.window_height() / 2
turtleX, turtleY = turt.pos()
while (min_x < turtleX < max_x) and (min_y < turtleY < max_y):
turt.left(random.randrange(360))
turt.fd(random.randrange(100))
turtleX, turtleY = turt.pos()
print(turtleX, ",", turtleY)
wn = Screen()
alpha = createTurtle("red", 3)
inScreen(wn, alpha)
wn.exitonclick()
The variables turtleX and turtleY are being used in your while condition, but you never reevaluate them within the loop.
This is why your print function only ever outputs 0.0 , 0.0

Turtle Gradient Color (review code)

I am trying to use Turtle to print 30 hexagons that are spiralling and have a gradient color change from red to black.
I am multiplying my for loop i in order to change the set values in (r, b, g) so, at some point, it will exceed r=255. I include an if statement to have it not exceed this, but it's giving me the error:
File "<ipython-input-4-35d45ac44fdd>", line 20
if r > '255'
^
SyntaxError: invalid syntax
What is causing this error?
FYI I am using Anaconda and a Jupyter notebook.
Here is my code:
import turtle
def draw_hexagon (t, size):
n=6
angle= 360/n
for i in range(n):
t.forward(size)
t.left(angle)
turtle.colormode(255)
mega=turtle.Turtle()
mega.speed(1000)
leng = 100
for i in range(30):
r = 5+(i*10)
g = 0
b = 0
color = (r, b, g)
if r > 255
print color(r,b,g)
mega.fillcolor(color)
mega.begin_fill()
draw_hexagon(mega, leng)
mega.end_fill()
leng = leng + 5
mega.left(5)
turtle.exitonclick()
My advice is to not use the if statement to get around the error but rather fix your math to avoid it in the first place. Plus some code cleanup:
from turtle import Turtle, Screen
MIN_COLOR = 5
MAX_COLOR = 255
COUNT = 30
ANGLE = 5
STARTING_LENGTH = 100
LENGTH_INCREMENT = 5
N = 6
def draw_polygon(turtle, size):
angle = 360 / N
for _ in range(N):
turtle.forward(size)
turtle.left(angle)
screen = Screen()
screen.colormode(255)
mega = Turtle()
mega.speed('fastest')
length = STARTING_LENGTH
for r in range(COUNT):
red = round(r * ((MAX_COLOR - MIN_COLOR) / (COUNT - 1))) + MIN_COLOR
color = (red, 0, 0)
mega.fillcolor(color)
mega.begin_fill()
draw_polygon(mega, length)
mega.end_fill()
length += LENGTH_INCREMENT
mega.left(ANGLE)
mega.hideturtle()
screen.exitonclick()

Python: draw tangent graph using math & turtle libraries

I was stuck on this task for several days. Although, the solution should be simple. I apply math and turtle libraries for drawing 3 graphs: sine, cosine and tangent with amplitude 200. The problem is I cant build the tangent graph as It should be drawn.
This is what I should do:
This is what I got:
As you see, my turtle goes up and doesn't come back anymore.
Pls, don't suggest me to use numpy. It's out of my task.
Thank you for advance!
import math
import turtle
ws = turtle.Screen()
ws.bgcolor("white")
t = turtle.Turtle()
for i in [(0,250), (0,0), (0,-250), (0,0), (400,0), (0,0)]:
t.goto(i, None)
t.write(i, font=("Arial", 12))
t.color("red")
for angle in range(360):
y = math.sin(math.radians(angle))
t.goto(angle, y * 200)
t.penup()
t.setpos(0,200)
t.goto(0,200)
t.pendown()
t.color("blue")
for angle in range(360):
y = math.cos(math.radians(angle))
t.goto(angle, y * 200)
t.penup()
t.setpos(0,0)
t.goto(0,0)
t.pendown()
t.color("green")
for angle in range(360):
y = math.tan(math.radians(angle))
t.goto(angle, y * 200)
ws.exitonclick()
To show that it should work, below is my minimalist implementation of plotting sine, cosine and tangent using turtle graphics:
import math
from turtle import Turtle, Screen
RESOLUTION = 0.1
def plot(x_points, y_points):
for i, y in enumerate(y_points):
if abs(y) <= 2.0:
yertle.goto(x_points[i], y)
yertle.pendown()
else:
yertle.penup()
yertle.penup()
screen = Screen()
screen.setworldcoordinates(0, -1.5, 2 * math.pi / RESOLUTION, 1.5)
yertle = Turtle()
yertle.penup()
x = range(int(2 * math.pi / RESOLUTION))
yertle.color("blue")
plot(x, (math.cos(n * RESOLUTION) for n in x))
yertle.color("red")
plot(x, (math.sin(n * RESOLUTION) for n in x))
yertle.color("dark green")
plot(x, (math.tan(n * RESOLUTION) for n in x))
screen.exitonclick()
OUTPUT
My guess is you're not waiting long enough for tangent to plot, i.e. it's slowly plotting lots of points off the window and will eventually reappear on-screen. My code works around that issue.
try about this. Near to work for me, no time to get better:
for angle in range(360):
y=0
y = math.tan(math.radians(angle))
if y<1 and y>-1:
t.goto(angle, y * 200)
With asipmtotas
for angle in range(360):
t.penup()
y = math.tan(math.radians(angle))
if y<1 and y>-1:
t.pendown()
t.goto(angle, y * 200)
else:
t.penup()
#t.pendown()
t.goto(angle, 200)

How can I fill each petal separately using begin_fill()?

I have the following code that generates a petal pattern for a flower I'm trying to build. However, the problem is the fill part.
What should happen is each petal to be filled individually:
Instead, what happens is this:
import turtle
import math
wn = turtle.Screen()
wn.bgcolor("white")
def draw_leaf(turtle, side, theta = 0):
angle = 2
turtle.color("#67bd3c")
for x in range(-180,180):
y = math.sin(math.radians(angle))
angle += 1
y = y * side
x_axis = (x % 180) * math.cos(math.radians(theta)) + y * math.sin(math.radians(theta))
y_axis = (x % 180) * (-1 * (math.sin(math.radians(theta)))) + y * math.cos(math.radians(theta))
turtle.goto(-1 * x_axis, -1 * y_axis)
return
def draw_flower(turtle, petals):
for x in range(petals):
theta = 180/(petals - 1)
turtle.pendown()
turtle.begin_fill()
draw_leaf(turtle, 35, theta * x)
turtle.end_fill()
turtle.penup()
turtle.left(theta)
return
draw_flower(turtle,4)
wn.exitonclick()
It looks like each draw_leaf call begins when the turtle is at the far end of the leaf that it just previously drew. So the polygon that is filled during the current draw_leaf includes that end point. This is more apparent if you draw each leaf with a different color.
One possible solution is to goto the center of the flower after your penup, before you draw the next leaf.
def draw_flower(turtle, petals):
start = turtle.pos()
for x in range(petals):
theta = 180/(petals - 1)
turtle.pendown()
turtle.begin_fill()
draw_leaf(turtle, 35, theta * x)
turtle.end_fill()
turtle.penup()
turtle.goto(*start)
turtle.left(theta)
return

Categories