How to draw a dotted circle using python Turtle package - python

Something similar to the picture attached. I tried modifying the code I got online. But my code goes to infinity loop
[1]: https://i.stack.imgur.com/HfKog.png
def draw_circle(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
turtle.pendown() # pen down
times_y_crossed = 0
x_sign = 1.0
while times_y_crossed <= 1:
turtle.dot(5, "Red")
turtle.forward(5) # move by 1/360
turtle.right(1.0)
turtle.penup()
turtle.forward(5) # move by 1/360
turtle.right(1.0)
x_sign_new = math.copysign(1, turtle.xcor())
if x_sign_new != x_sign:
times_y_crossed += 10
x_sign = x_sign_new
turtle.up() # pen up
return

There are some issues with your code, like it does not count with the radius and the color for the pen was not set and as I've checked it did a half circle for me.
I show you a simple working example, first a dashed version because your original code looks like you wanted a dashed circle
import turtle
import math
def draw_circle_dashed(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
times_y_crossed = 0
dist=2*math.pi*radius/360
turtle.pencolor("red")
for _ in range(180):
turtle.pendown()
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.penup()
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.up() # pen up
return
draw_circle_dashed(200)
and a dotted variant as well because of the question title
import turtle
import math
def draw_circle_dotted(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
dist=2*math.pi*radius/360
for _ in range(360):
turtle.dot(2,"red")
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.up() # pen up
return
draw_circle_dotted(300)

We can use turtle's own circle() method to do this as we can arbitrarily start and stop it, leaving behind dots as we do:
from turtle import Screen, Turtle
from math import pi
DOT_DIAMETER = 5
def draw_circle(radius):
turtle.penup()
circumference = 2 * pi * radius
dot_extent = 360 * DOT_DIAMETER*2 / circumference # diameter to angle
extent = 0
while extent < 360:
turtle.dot(DOT_DIAMETER)
turtle.circle(radius, extent=dot_extent)
extent += dot_extent
screen = Screen()
turtle = Turtle()
turtle.color('red')
draw_circle(100)
turtle.hideturtle()
screen.exitonclick()
Using what we learned from that exercise, let's now fix your code. The issue I see is this:
turtle.right(1.0)
The angle to turn is dependent on the dot diameter, but we actually have to calculate it:
from turtle import Screen, Turtle
from math import pi, copysign
DOT_DIAMETER = 5
def draw_circle(radius):
turtle.penup()
turtle.sety(radius)
diameter = 2 * radius
circumference = pi * diameter
dot_extent = 360 * DOT_DIAMETER / circumference # diameter to angle
times_y_crossed = 0
x_sign = 1
while times_y_crossed < 2:
turtle.dot(DOT_DIAMETER, 'red') # draw the dot
turtle.right(dot_extent)
turtle.forward(DOT_DIAMETER)
turtle.right(dot_extent) # draw the gap
turtle.forward(DOT_DIAMETER)
x_sign_new = copysign(1, turtle.xcor())
if x_sign_new != x_sign:
times_y_crossed += 1
x_sign = x_sign_new
turtle.pendown()
screen = Screen()
turtle = Turtle()
turtle.color('red')
draw_circle(100)
turtle.hideturtle()
screen.exitonclick()
By not calculating the angle, and using a fixed angle of 1.0, you were off by a factor of two.

Related

Creating an irregular arc with python turtle

I'm trying to make a function which draws an irregular arc similar to figure 1, instead it has drawn a spiral. I'm not sure how to draw one correctly and there are no functions to do this to my knowledge
Long Arc - Figure 1
import turtle
char = turtle.Turtle()
char.speed(0)
screen = turtle.Screen()
screen.tracer(False)
def draw_arc(length, left_right):
sx = char.xcor()
sy = char.ycor()
def turn(angle):
if left_right:
char.left(angle)
else:
char.right(angle)
count = 1.8
turn(90)
char.forward(1)
while char.xcor() != sx and char.ycor() != sy and count >= 0:
char.forward(1)
turn(1 * count)
count -= 0.01
draw_arc(100, True)
screen.update()
turtle.listen()
turtle.mainloop()
import turtle
t = turtle.Pen(visible=False)
t.speed('fastest')
t.left(90)
for x in range(180):
t.forward(1)
t.right(1)
add this line and modify it until it fit ur need ( setx() or sety )
t.setx( x * 1.5)

How do I make this a 6 sized snowflake instead of 8?

Not originally my code:
import turtle
wn = turtle.Screen()
wn.bgcolor('Black')
wn.setup( width = 250, height = 250)
turtle = turtle.Turtle()
def snowflake (size, pensize, x, y):
""" function that draws a snowflake """
turtle.speed(100)
turtle.penup()
turtle.goto(x, y)
turtle.forward(10*size)
turtle.left(45)
turtle.pendown()
turtle.color('white')
for x in range (8):
branch(size)
turtle.left(45)
def branch (size):
for z in range (3):
for z in range (3):
turtle.forward(10.0*size/3)
turtle.backward(10.0*size/3)
turtle.right(45)
turtle.left(90)
turtle.backward(10.0*size/3)
turtle.left(45)
turtle.right(90)
turtle.forward(10.0*size)
snowflake(8, 6, 0, 0)
wn.exitonclick()
If it's not originally your code, your should provide proper blame, I mean credit for it. The issue with this code is that the base angle 45 is being used to generate the 8-sided snowflake as well as the angle of the small branches. So when we go to use 60 for a 6-sided snowflake, it's hard to know which 45's (or 90's) to replace and which to keep. The author of the original code didn't help any by starting the branch logic in the snowflake() function, before calling the branch() function. So let's tease out the two different uses of 45 degrees, make the code more explicit, and switch just the sides to 60 degrees:
from turtle import Screen, Turtle
SIDES = 6
BRANCH_ANGLE = 45
def snowflake(size, x, y):
""" function that draws a snowflake """
turtle.penup()
turtle.goto(x, y)
turtle.forward(size)
turtle.left(BRANCH_ANGLE)
turtle.pendown()
for _ in range(SIDES):
branch(size)
turtle.left(BRANCH_ANGLE)
def branch(size):
for _ in range(3):
for _ in range(3):
turtle.forward(size / 3)
turtle.backward(size / 3)
turtle.right(BRANCH_ANGLE)
turtle.left(2 * BRANCH_ANGLE)
turtle.backward(size / 3)
turtle.left(BRANCH_ANGLE)
turtle.right(BRANCH_ANGLE + 360 / SIDES)
turtle.forward(size)
screen = Screen()
screen.bgcolor('black')
screen.setup(width=250, height=250)
turtle = Turtle()
turtle.color('white')
turtle.speed('fastest')
snowflake(80, 0, 0)
turtle.hideturtle()
screen.exitonclick()

Turtle Graphics Hexagon Centering

I need some help. I want to center the hexagon into the larger hexagon but I don't now how to do it. Below I have the source code and an image link to the output.
import turtle
polygon = turtle.Turtle()
num_sides = 6
side_length = 20
move_left = 60
polygon.pensize(2)
polygon.pencolor((245, 176, 66))
for turtle_move in range(num_sides):
polygon.forward(side_length)
polygon.left(move_left)
polygon.penup()
polygon.left(2)
polygon.pendown()
side_length2 = 40
move_left2 = 60
I want to center the hexagon inside the larger hexagons, but I don't know what to do.
for turtle_move in range(num_sides):
polygon.forward(side_length2)
polygon.left(move_left2)
Here is the output:
There are any number of ways to do this if you read about the geometry of hexagons, eg. on Wikipedia:
from turtle import Screen, Turtle
NUM_SIDES = 6
SIDE_LENGTH = 20
ANGLE_LEFT = 60
screen = Screen()
turtle = Turtle()
for _ in range(NUM_SIDES):
turtle.forward(SIDE_LENGTH)
turtle.left(ANGLE_LEFT)
turtle.penup()
turtle.backward(SIDE_LENGTH / 2)
turtle.sety(-SIDE_LENGTH * 3**0.5/2)
turtle.pendown()
for _ in range(NUM_SIDES):
turtle.forward(SIDE_LENGTH*2)
turtle.left(ANGLE_LEFT)
turtle.hideturtle()
screen.exitonclick()
One alternate approach is to use the turtle circle() method to draw the hexagons, then it becomes a matter of centering two circles:
from turtle import Screen, Turtle
NUM_SIDES = 6
SIDE_LENGTH = 20
circumradius = SIDE_LENGTH
screen = Screen()
turtle = Turtle()
for _ in range(2):
turtle.penup()
turtle.sety(-circumradius)
turtle.pendown()
turtle.circle(circumradius, steps=NUM_SIDES)
circumradius *= 2
turtle.hideturtle()
screen.exitonclick()
I'm assuming by your use of pencolor((245, 176, 66)) you're using a site like Repl.it or some other non-standard Python turtle implementation, so you may need to adjust the examples above slightly to suit your environment.

How to make this wheel spin?

I have created the wheel, but when I try to make code to spin it will not work.
I have already tried to make it using a loop but that was near impossible for me. I am basically drawing the wheel over. Here is some code from the spinning wheel part:
turtle.listen()
if turtle.onkeypress("space"):
colors = ['#880000','#884400','#884400','#888800',
'#888800','#008800','#008800','#008800',
'#008800','#008800','#008888','#008888',
'#008888','#008888','#008888','#000088',
'#000088','#000088','#000088','#000088']
for color in colors:
slice_angle = 360 / len(colors)
heading, position = 90, (center[0] + radius, center[1])
turtle.color(color, color)
turtle.speed(0)
turtle.penup()
turtle.goto(position)
turtle.setheading(heading)
turtle.pendown()
turtle.begin_fill()
turtle.circle(radius, extent=slice_angle)
heading, position = turtle.heading(), turtle.position()
turtle.penup()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
time.sleep(0.2)
colors = ['#884400','#884400','#888800',
'#888800','#008800','#008800','#008800',
'#008800','#008800','#008888','#008888',
'#008888','#008888','#008888','#000088',
'#000088','#000088','#000088','#000088','#880000']
for color in colors:
slice_angle = 360 / len(colors)
heading, position = 90, (center[0] + radius, center[1])
turtle.color(color, color)
turtle.speed(0)
turtle.penup()
turtle.goto(position)
turtle.setheading(heading)
turtle.pendown()
turtle.begin_fill()
turtle.circle(radius, extent=slice_angle)
heading, position = turtle.heading(), turtle.position()
turtle.penup()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
time.sleep(0.2)
The code keeps on going to make the wheel 'spin'.
This is what I get:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/turtle.py", line 701, in eventfun
fun()
TypeError: 'str' object is not callable
My impression is that you're not trying to make the wheel spin but rather make it look like it's spinning by cycling its colors. Here's my example of doing such which uses tracer() and update() to turn off drawing while remaking the circle with the colors shifted. It uses a timer event to trigger redraws. Rather than your fixed list of colors, I'm going to use continuous hues, but you should be able to use any colors you wish:
from turtle import Screen, Turtle
from colorsys import hsv_to_rgb
RADIUS = 100
NUMBER_OF_WEDGES = 20
SLICE_ANGLE = 360 / NUMBER_OF_WEDGES
screen = Screen()
screen.tracer(False)
turtle = Turtle(visible=False)
turtle.penup()
center = turtle.position()
turtle.sety(turtle.ycor() - RADIUS)
hues = [color / NUMBER_OF_WEDGES for color in range(NUMBER_OF_WEDGES)] # precompute hues
index = 0
def draw_circle():
global index
for hue in range(NUMBER_OF_WEDGES):
turtle.color(hsv_to_rgb(hues[(hue + index) % NUMBER_OF_WEDGES], 1.0, 1.0))
turtle.pendown()
turtle.begin_fill()
turtle.circle(RADIUS, extent=SLICE_ANGLE)
position = turtle.position()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
turtle.goto(position)
screen.update()
index = (index + 1) % NUMBER_OF_WEDGES
screen.ontimer(draw_circle, 40)
draw_circle()
screen.exitonclick()
This works, but, on my system, inexplicably slows down over time.
Let's try a different approach that doesn't redraw anything at the Python level during the cycling of colors. We're going to design a new cursor shape, "wedge" and build our circle out of turtles! All the wedges will be prepositioned and not move nor be redrawn. The timer event handler will simply ask each turtle to take on the color of its neighbor:
from turtle import Screen, Turtle
from colorsys import hsv_to_rgb
RADIUS = 100
NUMBER_OF_WEDGES = 20
SLICE_ANGLE = 360 / NUMBER_OF_WEDGES
screen = Screen()
screen.tracer(False)
# create a pie wedge-shaped cursor
turtle = Turtle(visible=False)
turtle.begin_poly()
turtle.sety(turtle.ycor() - RADIUS)
turtle.circle(RADIUS, extent=SLICE_ANGLE)
turtle.home()
turtle.end_poly()
screen.register_shape("wedge", turtle.get_poly())
# create a turtle for each wedge in the pie
turtles = []
for hue in range(NUMBER_OF_WEDGES):
turtle = Turtle("wedge")
turtle.color(hsv_to_rgb(hue / NUMBER_OF_WEDGES, 1.0, 1.0))
turtle.setheading(hue * SLICE_ANGLE)
turtles.append(turtle)
def draw_circle():
# have each turtle take on the color of its neighbor
for index, turtle in enumerate(turtles):
turtle.color(*turtles[(index + 1) % NUMBER_OF_WEDGES].color())
screen.update()
screen.ontimer(draw_circle, 40)
draw_circle()
screen.exitonclick()
Notice how much simpler our main loop, draw_circle(), is and that the spinning doesn't slow down.

Drawing concentric squares

When going through the book "How to think like...", I got stuck with exercise 4.9.2.
The question is: "Write a program to draw this. Assume the innermost square is 20 units per side, and each successive square is 20 units bigger, per side, than the one inside it"
The following code represents how far I got till now:
import turtle
wn = turtle.Screen()
wn.bgcolor("lightgreen")
tess = turtle.Turtle()
def draw_square(t,size):
for i in range(4):
tess.forward(size)
tess.left(90)
size = 20
for j in range(3):
tess.pensize(3)
draw_square(tess,size)
size = size + 20
tess.penup()
tess.goto(-20, -20)
tess.pendown()
wn.mainloop()
Can someone be so kind and show me the right direction please?
Thanks!
Swen
The problem is here:
tess.goto(-20, -20)
You have two issues. First, if each square is 20 units bigger and you offset each square by (-20, -20) all squares would share one corner. Instead you want to offset the corner of the square by (-10, -10) so that the inner square is offset by 10 units on all sides.
The second issue is that .goto(x, y) sets an absolute position, not an offset. To move to an offset you need to calculate a new absolute position based on the offset:
tess.goto(tess.xcor()-10, tess.ycor()-10)
Or
tess.goto(tess.pos() + (-10, -10))
Sometimes when you're stuck, a good approach with turtle graphics is to think outside the square. If we consider the desired result as badly drawn concentric circles then the problem reduces to:
from turtle import Turtle, Screen
HYPOTENUSE = (2 ** 0.5) / 2
screen = Screen()
screen.bgcolor("lightgreen")
tess = Turtle()
tess.pencolor("red")
tess.setheading(45)
tess.width(3)
for radius in range(20, 20 * 5 + 1, 20):
tess.penup()
tess.goto(radius/2, -radius/2)
tess.pendown()
tess.circle(radius * HYPOTENUSE, steps=4)
screen.exitonclick()
OUTPUT
import turtle
def drawSquare (t, size):
for i in range (4):
t.forward(size)
t.left(90)
def main():
wn = turtle.Screen()
wn.bgcolor('black')
pat = turtle.Turtle()
pat.pensize(2)
pat.speed(10)
pat.color('blue')
space = -10
for i in range(20, 105, 20):
drawSquare(pat,i)
pat.up()
pat.goto(space, space)
pat.down()
space = space - 10
wn.exitonclick()
main()
import turtle
def draw_sqr(name,size):
for i in range(4):
name.forward(size)
name.left(90)
name.penup()
name.backward(10)
name.right(90)
name.forward(10)
name.left(90)
name.pendown()
window = turtle.Screen()
window.bgcolor('lightgreen')
window.title("conc_sqr")
x = turtle.Turtle()
x.color('hotpink')
x.pensize(3)
for i in range(5):
draw_sqr(x,20 + 20*i)
window.mainloop()
def draw_rectangle(animal, width, height):
for _ in range(2):
animal.forward(width)
animal.left(90)
animal.forward(height)
animal.left(90)
def draw_square(animal, size):
draw_rectangle(animal, size, size)
def make_window(back_color,title):
window = turtle.Screen()
window.bgcolor(back_color)
window.title(title)
return window
def make_turtle(color, size):
animal = turtle.Turtle()
animal.color(color)
animal.pensize(size)
return animal
import turtle
window = make_window("lightgreen","Squares")
tess = make_turtle("hotpink",3)
size_sqr=20
adjustment = 10
for _ in range(5):
draw_square(tess,size_sqr)
size_sqr += 20
tess.penup()
tess.backward(20/2)
tess.right(90)
tess.forward(20/2)
tess.left(90)
tess.pendown()
import turtle
def drawsquare(t,sz): #(turtle, size)
for i in range(4):
t.fd(sz)
t.right(90)
def main():
wn = turtle.Screen()
your_turtle = turtle.Turtle()
your_turtle.pensize(3)
wn.bgcolor("light green")
your_turtle.pencolor("hot pink")
for i in range(1,6):
drawsquare(your_turtle,20*i)
your_turtle.up()
your_turtle.left(135)
your_turtle.fd(14.142) #the distance between each square
your_turtle.right(135)
your_turtle.down()
main()
wn.exitonclick()

Categories

Resources