import turtle
window = turtle.Screen()
window.screensize(1920,1080)
window.setup(width=1.0, height=1.0, startx=None, starty=None)
# T is a global variable
T = turtle.Turtle()
T.shape('turtle')
T.speed(2)
def forward_and_rotate(distance, degree, t):
t.forward(distance)
t.left(degree)
def draw_square_recursion(distance, t, sides_left=4):
t.pendown()
if sides_left == 0:
return
else:
forward_and_rotate(distance, 90, t)
draw_square_recursion(distance, t, sides_left-1)
t.penup()
def draw_filled_square(t, side_len, color='black'):
current_color = T.pencolor()
t.pendown()
t.color(color)
t.begin_fill()
draw_square_recursion(side_len, t, 4)
t.end_fill()
t.penup()
T.color(current_color)
# Starter code
def sier_carp(t, l, n):
if n == 0:
home = t.pos()
t.goto(home + (l/3, l/3))
draw_filled_square(t, l/3)
t.goto(home)
else:
sier_carp(t, l/3, n - 1)
t.fd(l/3)
sier_carp(t, l/3, n -1)
t.fd(l/3)
sier_carp(t, l/3, n -1)
t.fd(l/3)
t.left(90)
t.fd(l/3)
sier_carp(t, l/3, n - 1)
t.fd(l/3)
sier_carp(t, l/3, n -1)
t.fd(l/3)
t.left(90)
t.fd(l/3)
sier_carp(t, l/3, n - 1)
t.fd(l/3)
sier_carp(t, l/3, n -1)
t.fd(l/3)
t.left(90)
t.fd(l/3)
sier_carp(t, l/3, n - 1)
t.fd(l/3)
sier_carp(t, l/3, n -1)
t.fd(l/3)
t.left(90)
t.fd(l/3)
# add more cases!
T.penup()
sl = 200
draw_square_recursion(sl, T, 4)
sier_carp(T, sl, 1)
I'm having a hard time drawing the Sierpinski carpet using recursion only and no loops. However after the first three squares are drawn and I try to rotate to the left and do the next 2 squares on the nest site, the squares go out of line. If you want you can try out this code and see how it looks like. Btw the color are inversed to white around and black inside and not the usual carpet version of black around and white square.
I'm going to do a simplied version of your code -- although repetitive, your starter code does achieve your goal of recursion only. However, I'm going to use stamping instead of drawing so we can focus on the recursive image and not the mechanics of drawing squares with turtles:
from turtle import Screen, Turtle
SIDE_LENGTH = 200
CURSOR_SIZE = 20
def draw_filled_square(t, side_len):
t.shapesize(side_len / CURSOR_SIZE)
t.stamp()
def sier_carp(t, l, n):
draw_filled_square(t, l)
if n < 1:
return
x, y = t.position()
t.setx(x + l)
sier_carp(t, l/3, n - 1)
t.sety(y + l)
sier_carp(t, l/3, n - 1)
t.setx(x)
sier_carp(t, l/3, n - 1)
t.setx(x - l)
sier_carp(t, l/3, n - 1)
t.sety(y)
sier_carp(t, l/3, n - 1)
t.sety(y - l)
sier_carp(t, l/3, n - 1)
t.setx(x)
sier_carp(t, l/3, n - 1)
t.setx(x + l)
sier_carp(t, l/3, n - 1)
t.goto(x, y)
screen = Screen()
screen.setup(width=1.0, height=1.0)
turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.penup()
sier_carp(turtle, SIDE_LENGTH, 4)
screen.exitonclick()
I intentionally avoided speeding things up with screen.tracer(False) as you should see how it's drawn in a counterclockwise pattern.
I believe the problem is simpler than you're making it. It's important in this sort of drawing that your recursive function return the turtle to where it was when the function started. This allows the caller to make valid assumptions about its position.
Here are the concepts I've noted before starting:
Define a function that takes in a coordinate and a square size, and return the 8 surrounding coordinates.
Define a function that takes in a coordinate and a square size, and draw a square with the given size as its length, and the given coordinate as its center point.
Define the main function that will take in a coordinate, a size and the number of recursions. The coordinate will be the center of the Sierpinski Carpet and the size will be the size of the finished Sierpinski Carpet.
With the above notes in mind, let's begin to construct our program:
Import the turtle module, turn off tracer (optional) for efficiency and hide the turtle cursor:
import turtle
turtle.tracer(0)
turtle.hideturtle()
Define the function that takes in coordinate and a unit, and return a list of all 8 coordinates surrounding the given coordinate:
def surrounding(cor, size):
x, y = cor
return [(x - size, y + size),
(x + size, y + size),
(x - size, y - size),
(x + size, y - size),
(x - size, y),
(x + size, y),
(x, y + size),
(x, y - size)]
Define a recursive function that will take in a coordinate, size and a count. It will draw a square with its center at the given coordinate and its size one third of the given size, so that the sides of the finished carpet will end up the given size. The count is there to tell the function when to stop recursing; when the count reaches 0:
def draw_square(cor, size, count):
size /= 3
count -= 1
turtle.penup()
turtle.goto(cor[0] - size / 2, cor[1] + size / 2)
turtle.pendown()
turtle.begin_fill()
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.end_fill()
if count:
func(surrounding(cor, size), size, count)
Define a recursive function that takes in a coordinate and a size. It will use the surroundings function defined earlier to convert that coordinate into a list of surround coordinates. Then, it will use the draw_square function defined earlier to draw a square at each of the surrounding coordinates:
def func(cors, size, count):
if len(cors) == 2:
draw_square(cors, size, count)
else:
draw_square(cors[0], size, count)
draw_square(cors[1], size, count)
draw_square(cors[2], size, count)
draw_square(cors[3], size, count)
draw_square(cors[4], size, count)
draw_square(cors[5], size, count)
draw_square(cors[6], size, count)
draw_square(cors[7], size, count)
Finally, call the main function, func, and update the turtle screen (if tracer was set to 0).
func((0, 0), 600, 5)
turtle.update()
Altogether:
import turtle
turtle.tracer(0)
turtle.hideturtle()
def surrounding(cor, size):
x, y = cor
return [(x - size, y + size),
(x + size, y + size),
(x - size, y - size),
(x + size, y - size),
(x - size, y),
(x + size, y),
(x, y + size),
(x, y - size)]
def draw_square(cor, size, count):
size /= 3
count -= 1
turtle.penup()
turtle.goto(cor[0] - size / 2, cor[1] + size / 2)
turtle.pendown()
turtle.begin_fill()
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.forward(size)
turtle.right(90)
turtle.end_fill()
if count:
func(surrounding(cor, size), size, count)
def func(cors, size, count):
if len(cors) == 2:
draw_square(cors, size, count)
else:
draw_square(cors[0], size, count)
draw_square(cors[1], size, count)
draw_square(cors[2], size, count)
draw_square(cors[3], size, count)
draw_square(cors[4], size, count)
draw_square(cors[5], size, count)
draw_square(cors[6], size, count)
draw_square(cors[7], size, count)
func((0, 0), 600, 5)
turtle.update()
Output:
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()
Why doesn't this code work when I try to graph? The y-intercept doesn't seem to work.
from turtle import *
m = float(input("What is the slope? "))
b = float(input("What is the y-intercept? "))
x= window_width()
y= window_height()
y= int(m*x + b)
pd()
goto(x , y)
pd()
goto(-x,-y)
pu()
goto(x/2,0)
pd()
goto(-x/2,0)
pu()
goto(0,2*y)
pd()
goto(0,-2*y)
update()
When I test values with y-intercepts, they go throgh the origin, which means it's not working. I'm trying to get the y-intercept working.
Why doesn't this code work when I try to graph?
I see two issues: 1) you seem to be doing things in the wrong order; 2) you incorrectly assume that if y is f(x) then f(-x) is -y which isn't true:
from turtle import *
m = float(input("What is the slope? "))
b = float(input("What is the y-intercept? "))
x, y = window_width(), window_height()
# Draw Axes
penup()
goto(x / 2, 0)
pendown()
goto(-x / 2, 0)
penup()
goto(0, y / 2)
pendown()
goto(0, -y / 2)
# Plot function
y = int(m * x + b)
penup()
goto(x, y)
x = -x
y = int(m * x + b)
pendown()
goto(x, y)
done()
USAGE
> python3 test.py
What is the slope? 0.5
What is the y-intercept? 100
>
OUTPUT
okay, i have a circle and i want get the point on circle in 90 degree of origin.
def point_on_circle():
'''
Finding the x,y coordinates on circle, based on given angle
'''
from math import cos, sin
#center of circle, angle in degree and radius of circle
center = [0,0]
angle = 90
radius = 100
#x = offsetX + radius * Cosine(Degree)
x = center[0] + (radius * cos(angle))
#y = offsetY + radius * Sine(Degree)
y = center[1] + (radius * sin(angle))
return x,y
>>> print point_on_circle()
[-44.8073616129 , 89.3996663601]
since pi start from 3 o'clock, i expected to get x=0 and y=100but i have no idea why i'm getting that.
what am i doing wrong?
Edit: even i convert to radians, still i get weird result.
def point_on_circle():
'''
Finding the x,y coordinates on circle, based on given angle
'''
from math import cos, sin, radians
#center of circle, angle in degree and radius of circle
center = [0,0]
angle = radians(90)
radius = 100
#x = offsetX + radius * Cosine(radians)
x = center[0] + (radius * cos(angle))
#y = offsetY + radius * Sine(radians)
y = center[1] + (radius * sin(angle))
return x,y
>>> print point_on_circle()
[6.12323399574e-15 , 100.0]
any idea how to get accurate number?
math.cos and math.sin expect radians, not degrees. Simply replace 90 by pi/2:
def point_on_circle():
'''
Finding the x,y coordinates on circle, based on given angle
'''
from math import cos, sin, pi
#center of circle, angle in degree and radius of circle
center = [0,0]
angle = pi / 2
radius = 100
x = center[0] + (radius * cos(angle))
y = center[1] + (radius * sin(angle))
return x,y
You'll get (6.123233995736766e-15, 100.0) which is close to (0, 100).
If you want better precision, you can try SymPy online before installing it yourself:
>>> from sympy import pi, mpmath
>>> mpmath.cos(pi/2)
6.12323399573677e−17
We're getting closer, but this is still using floating-point. However, mpmath.cospi gets you the correct result:
>>> mpmath.cospi(1/2)
0.0
The sin() & cos() expect radians use:
x = center[0] + (radius * cos(angle*pi/180));
Two things need to be changed.
First, you need to change range = 90 to range = radians(90) which means you need to import radians.
Second you need to subtract the range from radian(360) so you get it starting in quadrant I instead of quadrant IV. Once you are done, your should have changed range = 90 to range = radians(360 - 90) and have imported radians.
Then if you want to stop your answer from having floating-point, you have return int(x), int(y) instead of return x,y at the end of your function. I made these changes and it worked.
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