I want to create concentric circles. I want the user to input how many circles they would like and at any specified radius. My problem is that the circles are not forming within one another.Any hints would be awesome
import turtle
import random
n1 = int(input("How many circles"))
n2 = int(input("Radius?"))
for i in range(n1):
turtle.penup()
turtle.right(50)
turtle.forward(i)
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(n2)
turtle.end_fill()
turtle.pendown()
turtle.home()
while i in range(n1):
turtle.pendown()
turtle.right(40)
turtle.forward(i)
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(n2-20)
turtle.end_fill()
turtle.penup()
import turtle
import random
num = int(input("How many circles? "))
radius = int(input("Radius? "))
# move to starting point - tangent to right edge of largest circle
turtle.forward(radius)
turtle.left(90)
# draw circles, largest to smallest
for circle in range(num, 0, -1): # (num .. 1)
# draw a filled circle
turtle.begin_fill()
turtle.color(random.random(), random.random(), random.random())
turtle.circle(radius * circle / num)
turtle.end_fill()
# shift inward to next circle starting-point
turtle.left(90)
turtle.forward(radius / num)
turtle.right(90)
given 6, 120 produces
Related
How can I create separate coins in a page that are not overlapping or not touching each other. The code below shows overlapping coins if the number is greater than 2.
import turtle
tegan = turtle.Turtle()
turtle.fillcolor('grey')
turtle.begin_fill()
numbers = int(input("How many 50 pence coins you have: "))
print(numbers)
length = 100
degrees = 51.42857
angle = 40
def draw_heptagon(tegan, length, numbers, angle):
for i in range(numbers):
for x in range(7):
turtle.forward(length)
turtle.left(degrees)
turtle.right(angle)
draw_heptagon(tegan, length, numbers, angle)
turtle.end_fill()
turtle.done()
Here's an approximate approach that you can refine. We'll keep track of the centers of the randomly placed heptagons we draw. We'll treat them as circles for purposes of drawing and checking the distances between them:
from turtle import Screen, Turtle
from random import randint
RADIUS = 100
ANGLE = 40
number = int(input("How many 50 pence coins you have: "))
def draw_heptagons(t, number):
coins = []
for _ in range(number):
while True:
x = randint(RADIUS - width/2, width/2 - RADIUS)
y = randint(RADIUS - height/2, height/2 - RADIUS)
t.goto(x, y)
t.right(ANGLE)
if coins and any(t.distance(position) < RADIUS * 2 for position in coins):
continue
break
t.right(90)
t.forward(RADIUS) # draw heptagon centered at x, y
t.left(90)
turtle.begin_fill()
t.circle(RADIUS, steps=7)
turtle.end_fill()
coins.append((x, y))
screen = Screen()
width, height = screen.window_width(), screen.window_height()
turtle = Turtle()
turtle.speed('fastest') # because I have no patience
turtle.penup()
draw_heptagons(turtle, number)
turtle.hideturtle()
screen.exitonclick()
This does what you describe but the heptagons could actually be closer (fit more of them in the window) than circles, so you need to modify the test, and what information you store in positions, if you want to pack them tighter:
I'm being really bugged by a task:
User inputs radius r and then turtle draws the circle then proceeds to draw another circle with the same center but 10 px smaller until the radius is 0
First let us approximate a circle as a regular polygon with 36 sides/segments.
To draw this shape given a radius r we need to know;
The length of each segment
The angle to turn between each segment
To calculate the length, we first need the circumference, which is 2πr (we will approximate pi as 3.1415), giving us
circumference = 2 * 3.1415 * radius
Next we divide this by the number of segments we are approximating, giving
circumference = 2 * 3.1415 * radius
seg_lenght = circumferece/36
Now we need the angle difference between the segments, or the external angle. This is simply 360/n for a regular n-gon(polygon with n sides), so we do 360/36 = 10
We can now define a function to generate the segment length and draw the circle:
def circle_around_point(radius):
circumference = 2 * 3.1415 * radius
seg_length = circumference/36
penup()
fd(radius) #Move from the centre to the circumference
right(90) #Face ready to start drawing the circle
pendown()
for i in range(36): #Draw each segment
fd(seg_length)
right(10)
penup()
right(90) #Face towards the centre of the circle
fd(radius) #Go back to the centre of the circle
right(180) #Restore original rotation
pendown()
Now for the concentric circles:
def concentric_circles(radius):
while radius > 0:
circle_around_point(radius)
radius -= 10
It's not clear why #IbraheemRodrigues felt the need to recode turtle's circle() function based on your problem description, but we can simplify his solution by not reinventing the wheel:
def circle_around_point(turtle, radius):
is_down = turtle.isdown()
if is_down:
turtle.penup()
turtle.forward(radius) # move from the center to the circumference
turtle.left(90) # face ready to start drawing the circle
turtle.pendown()
turtle.circle(radius)
turtle.penup()
turtle.right(90) # face awary from the center of the circle
turtle.backward(radius) # go back to the center of the circle
if is_down:
turtle.pendown() # restore original pen state
def concentric_circles(turtle, radius):
for r in range(radius, 0, -10):
circle_around_point(turtle, r)
The key to circle() is that the current position is on the edge of the circle so you need to shift your position by the radius to make a specific point the center of the circle.
However, to solve this problem, I might switch from drawing to stamping and do it this way to speed it up and simplify the code:
import turtle
STAMP_SIZE = 20
radius = int(input("Please input a radius: "))
turtle.shape('circle')
turtle.fillcolor('white')
for r in range(radius, 0, -10):
turtle.shapesize(r * 2 / STAMP_SIZE)
turtle.stamp()
turtle.mainloop()
However, this draws crude circles as it's blowing up a small one:
To fix that, I might compromise between the two solutions above and do:
import turtle
radius = int(input("Please input a radius: "))
turtle.penup()
turtle.forward(radius)
turtle.left(90)
turtle.pendown()
turtle.begin_poly()
turtle.circle(radius)
turtle.penup()
turtle.end_poly()
turtle.addshape('round', turtle.get_poly()) # 'circle' is already taken
turtle.right(90)
turtle.backward(radius)
turtle.shape('round')
turtle.fillcolor('white')
for r in range(radius - 10, 0, -10):
turtle.shapesize(r / radius)
turtle.stamp()
turtle.mainloop()
This improves circle quality by shrinking a large one instead of enlarging a small one:
Where quality of the circle can be controlled using the steps= argument to the call to circle().
But, if I really wanted to minimize code while keeping quality high and speed fast, I might do:
import turtle
radius = int(input("Please input a radius: "))
for diameter in range(radius * 2, 0, -20):
turtle.dot(diameter, 'black')
turtle.dot(diameter - 2, 'white')
turtle.hideturtle()
turtle.mainloop()
The dot() method draws from the center instead of the edge, uses diameters instead of radii, draws only filled circles, and seems our best solution to this particular exercise:
import turtle
#### ##### #### Below class draws concentric circles.
class Circle:
def __init__(self, pen, cx, cy, radius):
self.pen = pen
self.cx = cx
self.cy = cy
self.radius = radius
def drawCircle(self):
self.pen.up()
self.pen.setposition( self.cx, self.cy - self.radius )
self.pen.down()
self.pen.circle(self.radius)
def drawConCircle(self, minRadius = 10, delta = 10):
if( self.radius > minRadius ) :
self.drawCircle()
self.radius -= delta # reduce radius of next circle
self.drawConCircle()
#### End class circle #######
win = turtle.Screen()
win.bgcolor("white")
s = Circle( turtle.Turtle(), 0, 0, 200 )
s.drawConCircle()
win.exitonclick()
I have the following code which is supposed to draw a ring of colors around a circle but only one color if printed and changed 8 times before moving to the next
import turtle
def drawCircle(colorList, radius):
for color in colorList:
turtle.color(color)
for i in range(len(colorList)):
turtle.penup()
turtle.setpos(0, -radius)
xpos=turtle.xcor()
ypos=turtle.ycor()
head=turtle.heading()
turtle.begin_fill()
turtle.pendown()
turtle.home()
turtle.setpos(xpos,ypos)
turtle.setheading(head)
turtle.circle(radius)
turtle.end_fill()
turtle.penup()
return
colorList=["#880000","#884400","#888800","#008800",\
"#008888","#000088","#440088","#880088"]
drawCircle(colorList,200)
How would I make it that each arc around the circle is a different color. here is an example
you will need something like this
def drawSegment(color,x, y, r, angleStart, angleEnd, step=1):
#More efficient to work in radians
radianStart = angleStart*pi / 180
radianEnd = angleEnd*pi / 180
radianStep=step *pi/180
#Draw the segment
turtle.penup()
turtle.setpos(x,y)
turtle.color(color)
turtle.begin_fill()
turtle.pendown()
for theta in arange(radianStart,radianEnd,radianStep):
turtle.setpos(x + r * cos(theta), y + r * sin(theta))
turtle.setpos(x + r * cos(radianEnd), y + r * sin(radianEnd))
turtle.setpos(x, y);
turtle.end_fill()
def drawCircle(colorList,radius):
#do something to draw an equal segment for each color advancing it around 360 degree's
I'm trying to draw a checkerboard.
I drew the board, but now I have to define a function (a loop) that fills in every other square with black. I've been trying to write a loop to do this for a while, can someone help?
Here's my code:
import turtle
def drawGrid():
turtle.penup()
turtle.goto(-300, 250)
turtle.pendown()
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
turtle.right(90)
turtle.forward(300)
def drawColumns():
for i in range(4):
turtle.right(90)
turtle.forward(37.5)
turtle.right(90)
turtle.forward(300)
turtle.left(90)
turtle.forward(37.5)
turtle.left(90)
turtle.forward(300)
def drawRows():
turtle.left(180)
rows = 0
while rows <= 3:
rows += 1
turtle.forward(37.5)
turtle.right(90)
turtle.forward(300)
turtle.left(90)
turtle.forward(37.5)
turtle.left(90)
turtle.forward(300)
turtle.right(90)
def main():
drawGrid()
drawColumns()
drawRows()
if __name__ == "__main__":
main()
Turtles fill method works on shapes, i.e. a completely bounded area. So rather than drawing a grid you need to think in terms of drawing a series of squares.
So lets start by defining a simple function to draw a filled in square. It takes a turtle object and a size which is the length of the side.
import turtle
def draw_filled_square(this_turtle, size):
"""Draw a square by drawing a line and turning through 90 degrees 4 times"""
this_turtle.pendown()
this_turtle.fill(True)
for _ in range(4):
this_turtle.forward(size)
this_turtle.right(90)
this_turtle.fill(False)
this_turtle.penup()
we can call it like this:
window = turtle.Screen()
myturtle = turtle.Turtle()
square_size = 90
myturtle.goto(-300, 200)
draw__filled_square(myturtle, square_size)
Which draws a single square. Note that it puts it back at the starting place, so we need to move it before drawing the next square.
Now, in practice, as long as we draw the outline of the box we only need to draw filled squares, unfilled squares can be represented negative space. But for the purposes of explanation I'm going to also draw them.
Defining a function for an unfilled square is easy -- just duplicate the existing function but set this_turtle.fill(False) at the beginning instead.
Anytime something needs to count in a repeating sequence (1, 2, 3, 4, 1, 2, 3, 4, ...) it calls for use of modulo (remainder). Modulo means remainder so if x modulo y is 0 it means x is exactly divisible by y. This translates into code as if x % y == 0:
Here's a simple drum machine to demonstrate:
def drum_loop(x):
# go bang on the fourth beat
if x % 4 == 0:
print("bang!")
else:
print("tish")
# prints tish, tish, tish, bang! tish, tish, tish, bang!
for i in range(1,9):
drum_loop(i)
Alternating is just like counting 0, 1 , 0, 1 repeatedly.
So we can draw a row like this:
for i in range(8):
if i % 2 == 0:
draw_filled_square(myturtle, square_size)
else:
draw_unfilled_square(myturtle, square_size)
# move to start of next square
myturtle.forward(square_size)
Now just repeating this isn't going to do the trick, but it should be clear you can use modulo 2 again to make the rows alternate properly.
Do this by defining a row function that will alternate between starting with a black and starting with a white square, then calling this from within another loop. (Don't forget to go back to the beginning and move down every time you start a row).
Here's another example where drawing creates more work for the poor turtle than simply stamping. Rather than thinking about drawing and filling boxes, think about the board itself as a filled square onto which other filled squares are stamped:
from turtle import Turtle, Screen
NUMBER_SQUARES = 8
SQUARE_SIZE = 40
BOARD_SIZE = SQUARE_SIZE * NUMBER_SQUARES
BORDER_FRACTION = 1.025 # add a slight edge to board
STAMP_SIZE = 20 # size of turtle square image
turtle = Turtle(shape='square', visible=False)
turtle.shapesize(BOARD_SIZE / STAMP_SIZE * BORDER_FRACTION)
turtle.color('black')
turtle.stamp()
turtle.shapesize(SQUARE_SIZE / STAMP_SIZE)
turtle.color('white')
turtle.penup()
for y in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
parity = y % 2 == 0
for x in range(-NUMBER_SQUARES//2, NUMBER_SQUARES//2):
if parity:
turtle.goto(x * SQUARE_SIZE + SQUARE_SIZE//2, y * SQUARE_SIZE + SQUARE_SIZE//2)
turtle.stamp()
parity = not parity
Screen().exitonclick()
This solution can print a board in any two colors (e.g. black and red), it doesn't assume a white background. Just another example of better living through stamping.
import turtle
turtle.pensize(2)
turtle.penup()
turtle.goto(-160,-160)
turtle.pendown()
turtle.color("black")
for i in range(4):
turtle.forward(320)
turtle.left(90)
for y in range(-160,160,80):
for x in range(-160,160,80):
turtle.begin_fill()
turtle.penup()
turtle.goto(x,y)
turtle.pendown()
for k in range(4):
turtle.forward(40)
turtle.left(90)
turtle.end_fill()
for y in range(-120,160,80):
for x in range(-120,160,80):
turtle.begin_fill()
turtle.penup()
turtle.goto(x,y)
turtle.pendown()
for k in range(4):
turtle.forward(40)
turtle.left(90)
turtle.end_fill()
turtle.done()
Let's have a look at the zig-zag approach (the explanation of the code is commented inside):
import turtle
def drawGrid(rows, cols, size):
turtle.sety(turtle.ycor() + size * rows) # Draw the initial line
f = size * 2
turtle.begin_fill()
for j in range(cols): # Make the columns
if j % 2:
turtle.backward(f) # Make room for the zig-zag up and zig-zag down
for i in range(rows * 2): # rows * 2 because there will be both zig-zag down and a zig-zag up for each row
turtle.forward(size)
turtle.right(90)
if i % 2:
turtle.left, turtle.right = turtle.right, turtle.left # Switch the zig-zag direction
turtle.left(180)
turtle.end_fill()
turtle.sety(turtle.ycor() - size * rows) # Draw the final line
turtle.penup()
turtle.goto(-300, -50) # Set the bottom-left position of the grid
turtle.pendown()
turtle.speed("fastest") # Because I have no patience
drawGrid(8, 8, 40)
Output:
Note that the number of rows and columns must be even for this to work.
I am trying to draw a target like this:
(source: newscientist.com)
using turtle.
The problem is turtle includes the origin as part of the graph, as opposed to the origin being in the center. My question is, how do I get turtle draw a circle AROUND the origin rather than include it?
import turtle
radius = 100
turtle.speed(0)
for rings in range(10):
turtle.circle(radius)
radius += 10
import turtle
radius = 100
turtle.speed(0)
for rings in range(10):
turtle.penup()
turtle.goto(0, -radius)
turtle.pendown()
turtle.circle(radius)
radius += 10
It's nicer to use radius as the loop variable
import turtle
turtle.speed(0)
for radius in range(100, 200, 10):
turtle.penup()
turtle.goto(0, -radius)
turtle.pendown()
turtle.circle(radius)
Then you might wish to define a function
import turtle
turtle.speed(0)
def origin_circle(turtle, radius):
turtle.penup()
turtle.goto(0, -radius)
turtle.pendown()
turtle.circle(radius)
for radius in range(100, 200, 10):
origin_circle(turtle, radius)