Python turtle program not drawing polygon properly - python-3.x

When I run the program using the turtle tool, it just makes one horizontal line and does not make a complete shape. I am not sure why this is happening. I have already made a working program that would draw a predetermined shape such as a square. I have already tested my computations and I believe my for-loop is correct. Am I making just some silly syntax error?
# polygon program
# get inputs
side_count = int(input( "How many sides does the polygon have?" ))
side_length = int(input( "How long is each side?" ))
# compute side angle
shape_angle = (side_count - 2) * 180
# import turtle modules
from turtle import *
# measure angles in
degrees()
# drawing speed
speed( 6 )
# square specs
color( 'green' )
width( 3 )
setheading( 0 )
# forloop to draw the polygon
for side in range ( side_count ):
forward ( side_length )
left ( shape_angle )
# all done drawing
done()

Although I agree with #TudorPopescu that this line is your primary issue:
shape_angle = (side_count - 2) * 180
That solution doesn't work for me, so I suggest something simpler to start:
shape_angle = 360 / side_count
Your code reworked with the above fix and style changes:
# polygon program
# import turtle modules
from turtle import *
# get inputs
side_count = int(input("How many sides does the polygon have? "))
side_length = int(input("How long is each side? "))
# compute side angle
shape_angle = 360 / side_count
# measure angles in
degrees() # the default
# drawing speed
speed('normal') # the default
# square specs
color('green')
width(3)
setheading(0) # the default initial heading
# for loop to draw the polygon
for side in range(side_count):
forward(side_length)
left(shape_angle)
# all done drawing
done()

First of all, import all your modules first, its not necessary until you have to use it, but it's a good habit. Also the shape_angle is the total of the whole shape.
To make it work you would have your original code:
shape_angle = (side_count - 2) * 180
Then put it in brackets and divide it by side_count to find the individual angle, the result:
shape_angle = ((side_count - 2) * 180) / side_count
Also get rid of the degrees
import turtle as *
side_count = int(input( "How many sides does the polygon have?" ))
side_length = int(input( "How long is each side?" ))
shape_angle = ((side_count - 2) * 180) / side_count
speed( 6 )
color( 'green' )
width( 3 )
setheading( 0 )
for side in range ( side_count ):
forward ( side_length )
left ( shape_angle )
done()
`

Related

Colors are not filling in certain places

I am utilizing turtle to make a xmastree. The task is to color the individual pieces. The "trunk" portion of code works and will fill correctly. The Layer1(), Layer2(), and Layer3() do not fill with color as they should. Any help would be appreciated.
I have looked through the other problems on stack overflow. I have repositioned my variables. Still, nothing.
""" Lab 9 Exercise 3
Author: Jonathan Wheatley
Define a function drawXmasTree(t, blc, scale = 1) You may add further parameters beyond the first three if you wish (note: give any additional parameters default values!). Your
tree should resemble three filed, superimposed green triangles (containing colored ball ornamets) over a brown trunk.
blc and scale should work as in the preceding exercise. Show results at two different scales.
"""
from turtle import Turtle
scale = 1.25
def drawXmasTree():
a = trunk()
b = Layer1()
c = Layer2()
d = Layer3()
def trunk():
t = Turtle()
t.pencolor("brown")
t.fillcolor("brown")
t.shape("turtle")
t.up()
t.goto((scale * -100), (scale * -100))
t.down()
for count in range(2):
t.begin_fill()
t.forward(scale * 10)
t.left(90)
t.forward(scale *100)
t.left(90)
t.end_fill()
t.hideturtle()
def Layer1():
t = Turtle()
t.pencolor("green")
t.fillcolor("green")
t.shape("turtle")
t.up()
t.goto((scale * -150), 0)
t.down()
for count in range(3):
t.begin_fill()
t.forward(scale * 110)
t. left(120)
t.end_fill()
t.hideturtle()
def Layer2():
t = Turtle()
t.pencolor("green")
t.fillcolor("green")
t.shape("turtle")
t.up()
t.goto((scale * -147), 15)
t.down()
for count in range(3):
t.begin_fill()
t.forward(scale * 104)
t.left(120)
t.end_fill()
t.hideturtle()
def Layer3():
t = Turtle()
t.fillcolor("green")
t.pencolor("green")
t.shape("turtle")
t.up()
t.goto((scale * -145), 30)
t.down()
for count in range(3):
t.begin_fill()
t.forward(scale * 100)
t.left(120)
t.end_fill()
t.hideturtle()
def main():
u = drawXmasTree()
main()
When the code is run the turtle should display, draw in the correct colored line, and then the shape should fill.
So, in running so more tests, I seem to be getting positive results by breaking the begin_fill() and end_fill out of the for loop. I don't know why this was working in the Trunk() section but it does not work in the subsequent sections.
Please, if you find a way to make this code better let me know. I would love to learn something and improve my coding.
Thank you.

review my circle creating code( turtle, python)

im new to python and just started touching turtle. I made this code of circle drawing and i have a few questions:
import turtle
jo = turtle.Turtle()
def polygon(t, r, n, l):
for i in range(30):
jo.fd(n * l)
jo.lt(r * 2 * 3.14)
print(polygon(jo, 2, 3, 4))
turtle.done()
1) i really dont understand how the code i wrote draw a circle.
2) are there any other ways to draw a circle in a similar sytax?
3) is this code is fine or I need to improve it?
i really dont understand how the code i wrote draw a circle.
By shear chance, perhaps. You'll notice that the radius of the circle you draw (~27) has nothing to do with the radius you passed into your polygon() function (2).
You pass radians to the left() function:
jo.lt(r * 2 * 3.14)
although it takes degrees unless told otherwise. You print the result of a function that doesn't return anything:
print(polygon(jo, 2, 3, 4))
Your turtle overshoots at the very end redrawing a small segment of the circle. Finally, you pass a turtle argument to the polygon() function but ignore it and uses the global one instead.
is this code is fine or I need to improve it?
I'd go with something more like:
from math import pi
from turtle import Turtle, Screen
TWO_PI = 2 * pi
def polygon(turtle, radius, sides):
circumference = radius * TWO_PI
for _ in range(sides):
turtle.fd(circumference / sides)
turtle.lt(TWO_PI / sides)
jo = Turtle()
jo.radians()
polygon(jo, 100, 30)
screen = Screen()
screen.mainloop()
are there any other ways to draw a circle in a similar sytax?
from turtle import Turtle, Screen
jo = Turtle()
jo.circle(100, steps=30)
screen = Screen()
screen.mainloop()

TkInter python - creating points on a canvas to obtain a Sierpinsky triangle

I want to make a program which plots a Sierpinsky triangle (of any modulo). In order to do it I've used TkInter. The program generates the fractal by moving a point randomly, always keeping it in the sides. After repeating the process many times, the fractal appears.
However, there's a problem. I don't know how to plot points on a canvas in TkInter. The rest of the program is OK, but I had to "cheat" in order to plot the points by drawing small lines instead of points. It works more or less, but it doesn't have as much resolution as it could have.
Is there a function to plot points on a canvas, or another tool to do it (using Python)? Ideas for improving the rest of the program are also welcome.
Thanks. Here's what I have:
from tkinter import *
import random
import math
def plotpoint(x, y):
global canvas
point = canvas.create_line(x-1, y-1, x+1, y+1, fill = "#000000")
x = 0 #Initial coordinates
y = 0
#x and y will always be in the interval [0, 1]
mod = int(input("What is the modulo of the Sierpinsky triangle that you want to generate? "))
points = int(input("How many points do you want the triangle to have? "))
tkengine = Tk() #Window in which the triangle will be generated
window = Frame(tkengine)
window.pack()
canvas = Canvas(window, height = 700, width = 808, bg = "#FFFFFF") #The dimensions of the canvas make the triangle look equilateral
canvas.pack()
for t in range(points):
#Procedure for placing the points
while True:
#First, randomly choose one of the mod(mod+1)/2 triangles of the first step. a and b are two vectors which point to the chosen triangle. a goes one triangle to the right and b one up-right. The algorithm gives the same probability to every triangle, although it's not efficient.
a = random.randint(0,mod-1)
b = random.randint(0,mod-1)
if a + b < mod:
break
#The previous point is dilated towards the origin of coordinates so that the big triangle of step 0 becomes the small one at the bottom-left of step one (divide by modulus). Then the vectors are added in order to move the point to the same place in another triangle.
x = x / mod + a / mod + b / 2 / mod
y = y / mod + b / mod
#Coordinates [0,1] converted to pixels, for plotting in the canvas.
X = math.floor(x * 808)
Y = math.floor((1-y) * 700)
plotpoint(X, Y)
tkengine.mainloop()
If you are wanting to plot pixels, a canvas is probably the wrong choice. You can create a PhotoImage and modify individual pixels. It's a little slow if you plot each individual pixel, but you can get dramatic speedups if you only call the put method once for each row of the image.
Here's a complete example:
from tkinter import *
import random
import math
def plotpoint(x, y):
global the_image
the_image.put(('#000000',), to=(x,y))
x = 0
y = 0
mod = 3
points = 100000
tkengine = Tk() #Window in which the triangle will be generated
window = Frame(tkengine)
window.pack()
the_image = PhotoImage(width=809, height=700)
label = Label(window, image=the_image, borderwidth=2, relief="raised")
label.pack(fill="both", expand=True)
for t in range(points):
while True:
a = random.randint(0,mod-1)
b = random.randint(0,mod-1)
if a + b < mod:
break
x = x / mod + a / mod + b / 2 / mod
y = y / mod + b / mod
X = math.floor(x * 808)
Y = math.floor((1-y) * 700)
plotpoint(X, Y)
tkengine.mainloop()
You can use canvas.create_oval with the same coordinates for the two corners of the bounding box:
from tkinter import *
import random
import math
def plotpoint(x, y):
global canvas
# point = canvas.create_line(x-1, y-1, x+1, y+1, fill = "#000000")
point = canvas.create_oval(x, y, x, y, fill="#000000", outline="#000000")
x = 0 #Initial coordinates
y = 0
#x and y will always be in the interval [0, 1]
mod = int(input("What is the modulo of the Sierpinsky triangle that you want to generate? "))
points = int(input("How many points do you want the triangle to have? "))
tkengine = Tk() #Window in which the triangle will be generated
window = Frame(tkengine)
window.pack()
canvas = Canvas(window, height = 700, width = 808, bg = "#FFFFFF") #The dimensions of the canvas make the triangle look equilateral
canvas.pack()
for t in range(points):
#Procedure for placing the points
while True:
#First, randomly choose one of the mod(mod+1)/2 triangles of the first step. a and b are two vectors which point to the chosen triangle. a goes one triangle to the right and b one up-right. The algorithm gives the same probability to every triangle, although it's not efficient.
a = random.randint(0,mod-1)
b = random.randint(0,mod-1)
if a + b < mod:
break
#The previous point is dilated towards the origin of coordinates so that the big triangle of step 0 becomes the small one at the bottom-left of step one (divide by modulus). Then the vectors are added in order to move the point to the same place in another triangle.
x = x / mod + a / mod + b / 2 / mod
y = y / mod + b / mod
#Coordinates [0,1] converted to pixels, for plotting in the canvas.
X = math.floor(x * 808)
Y = math.floor((1-y) * 700)
plotpoint(X, Y)
tkengine.mainloop()
with a depth of 3 and 100,000 points, this gives:
Finally found a solution: if a 1x1 point is to be placed in pixel (x,y), a command which does it exactly is:
point = canvas.create_line(x, y, x+1, y+1, fill = "colour")
The oval is a good idea for 2x2 points.
Something remarkable about the original program is that it uses a lot of RAM if every point is treated as a separate object.

I want to create a 90 degree curve

I have gotten as far as making a set of rays, but I need to connect them. Any help? My code is as follows
from math import *
from graphics import *
i = 1
segments = 15
lastPoint = Point(100,0)
print("Begin")
win = GraphWin("Trigonometry", 1500, 1500)
while i<=segments:
angle =i*pi/segments
y = int(sin(angle)*100)
x = int(cos(angle)*100)
i = i+1
p = Point(x,y)
l = Line(p, lastPoint)
l.draw(win)
print(p.x, p.y)
print("End")
OP code draws only "rays" because, while point p lays on the circle, lastPoint doesn't change between iterations.
We have to update the value of lastPoint to literally the last point calculated in order to draw the arc as a series of consecutive segments.
Here is a modified code, with further explanations as asked by OP in his comment:
from math import *
from graphics import *
# Function to calculate the integer coordinates of a Point on a circle
# given the center (c, a Point), the radius (r) and the angle (a, radians)
def point_on_circle( c, r, a ) :
return Point( int(round(c.x + r*cos(a))), int(round(c.y + r*sin(a))) )
# Define the graphical output window, I'll set the coordinates system so
# that the origin is the bottom left corner of the windows, y axis is going
# upwards and 1 unit corresponds to 1 pixel
win = GraphWin("Trigonometry", 800, 600)
win.setCoords(0,0,800,600)
# Arc data. Angles are in degrees (more user friendly, but later will be
# transformed in radians for calculations), 0 is East, positive values
# are counterclockwise. A value of 360 for angle_range_deg gives a complete
# circle (polygon).
angle_start_deg = 0
angle_range_deg = 90
center = Point(10,10)
radius = 200
segments = 16
angle_start = radians(angle_start_deg)
angle_step = radians(angle_range_deg) / segments
# Initialize lastPoint with the position corresponding to angle_start
# (or i = 0). Try different values of all the previous variables
lastPoint = point_on_circle(center, radius, angle_start)
print("Begin")
i = 1
while i <= segments :
# update the angle to calculate a new point on the circle
angle = angle_start + i * angle_step
p = point_on_circle(center, radius, angle)
# draw a line between the last two points
l = Line(p, lastPoint)
l.draw(win)
print(p.x, p.y)
# update the variables to move on to the next segment which share an edge
# (the last point) with the previous segment
i = i + 1
lastPoint = p
print("End")

How to get a rectangle to move along X axis using checkMouse()?

I'm trying to get a rectangle to move along the X axis but checkMouse() isn't working. What needs to be done to make it work?
from graphics import*
import time
from random import randrange
wd=GraphWin("Catch A Ball",500,500)
wd.setBackground("lightblue")
p1=220 #size of rectangle
p2=250
for i in range(1):
spt1=Point(p1,480)
spt2=Point(p2,500)
rct=Rectangle(spt1,spt2)
rct.setOutline("black")
rct.setFill("black")
rct.draw(wd)
p=wd.checkMouse()
c=rct.getCenter()
dx=p.getX() - c.getX()
dy=p.getY() - c.getY()
rct.move(dx,0)
You're missing a loop and I recommend working with getMouse() initially until you've a need to switch to checkMouse():
from graphics import *
window = GraphWin("Catch A Ball", 500, 500)
window.setBackground("lightblue")
point1 = Point(220, 480) # size of rectangle
point2 = Point(250, 500)
rectangle = Rectangle(point1, point2)
rectangle.setFill("black")
rectangle.draw(window)
while True:
point = window.getMouse()
if point is not None: # so we can switch to checkMouse() if desired
center = rectangle.getCenter()
dx = point.getX() - center.getX()
dy = point.getY() - center.getY()
rectangle.move(dx, 0)
You need to add some sort of action/event to break out of the while True: infinite loop.

Resources