Reputation: 1125
I am looking to generate this pattern but within python:
Here is the code I have generated which generates the 5 full circles going across:
def fdShape():
win = GraphWin("pdShape",200,200)
centre = Point(20,100)
for x in range(5):
circle = Circle(centre, 20)
circle.setFill("red")
centre = Point((centre.getX() + 40),100)
circle.draw(win)
However I am completed puzzled on how to get the semi circles above and below. Anyone have any ideas? I am not sure how I would get the code to repeat along the y-axis.
Any help is much appreciated.
Thanks.
Upvotes: 1
Views: 3620
Reputation: 41872
Here's a solution using Python's turtle graphics that probably doesn't work the way you imagined:
from turtle import Turtle, Screen, Shape
COUNT = 5
SIZE = 400
RADIUS = SIZE / COUNT
STAMP_UNIT = 20
screen = Screen()
circle_in_square = Shape("compound")
turtle = Turtle(shape="square")
circle_in_square.addcomponent(turtle.get_shapepoly(), "white")
circle_in_square.addcomponent([(-10, 10), (-10, -10)], "black")
circle_in_square.addcomponent([(10, -10), (10, 10)], "black")
turtle.shapesize(SIZE / STAMP_UNIT * 1.01)
turtle.stamp() # stamp background to get a border
turtle.shape("circle")
turtle.shapesize(1.0)
circle_in_square.addcomponent(turtle.get_shapepoly(), "red", "black")
screen.register_shape("squircle", circle_in_square)
turtle.shape("squircle")
turtle.shapesize(RADIUS / STAMP_UNIT)
turtle.penup()
for y in range(1 - COUNT, 1):
for x in range(-COUNT//2 + 1, COUNT//2 + 1):
for sign in (1, -1):
turtle.goto(x * RADIUS, y * RADIUS/2 * sign)
turtle.stamp()
screen.exitonclick()
It first creates a stamp I call a squircle which is a red circle on a white square with black borders on the top and bottom:
It then stamps out a bunch of these, side-by-side on the horizontal, 50% overlapped on the vertical:
With a little bit of outer border stamped in. This is part of my "Better Living Through Stamping" series (as opposed to drawing which your solution and the other answer attempted.
Upvotes: 2
Reputation: 365717
Without having any idea what graphics library you're using, it's hard to give a concrete answer. But there are four possibilities:
The library may have an Arc
class similar to the Circle
class, or maybe a way of restricting a Circle
object to display just a (filled) arc, or something similar. If so, to get your semicircles, you'd use something like Arc(centre, 20, -math.pi/2, math.pi/2)
and Arc(centre, 20, math.pi/2, 3*math.pi/2)
.
The library may have a way to set an explicit bounding box to truncate any object. So, you'd do something like: bb = circle.getBoundingBox(); bb.top = (bb.top + bb.bottom) / 2; circle.setBoundingBox(bb)
.
The library may not have any explicit way to do this, but may let you draw things on top of other things in the Z-order. So, first you draw the five complete circles cross the top, then you draw a big white rectangle that covers up the lower half of all the circles. (That could even give you those rectangular lines for free, if there's a way to set border color as well as fill color.)
The library may not have any way to do this at all, in which case you have to use a different library.
Meanwhile, for "how I would get the code to repeat along the y-axis", that's just another loop outside the one you already have. Something like this:
def fdShape():
win = GraphWin("pdShape",200,200)
centre = Point(20,100)
for y in range(9):
for x in range(5):
circle = Circle(centre, 20)
circle.setFill("red")
centre = Point((centre.getX() + 40), centre.getY())
circle.draw(win)
centre = Point(20, centre.getY() + 40)
However, it would probably be better to just create the points from x and y instead of adding to them explicitly:
for y in range(9):
for x in range(5):
centre = Point(x * 40 + 20, y * 40 + 60)
circle = Circle(centre, 20)
circle.setFill("red")
circle.draw(win)
Looking at the library link you gave in the comments, there doesn't seem to be any way to do either 1 or 2. The full documentation is in a textbook that I don't have, but there's reference docs online, and the code is pretty simple. Neither Circle
nor any of its parent classes have any way to specify an arc, or a box to truncate to. (There is a bounding box, but cutting that in half will just result in a squashed ellipse half the height of the original circle, not a semicircle.)
And presumably you're taking a course that's requiring this library, so 4 isn't an option.
Which leaves 3. That means you're actually going to have to change the loop up a bit. Something like this:
for y in range(4):
# draw row of circles y
# draw row 8-y
# draw rectangle y
# draw rectangle 8-y
# draw row of circles 4
Note that rectangle 3 and rectangle 5 will be the same one, so it's a bit wasteful to draw both, but I think in this case, keeping the code simpler is worth the waste. If your teacher disagrees, it should be pretty easy to figure out how to restructure the code.
Finally, speaking of restructuring the code, given that you have to do "draw row of circles" twice with different values, you should probably turn that into a function, and likewise for "draw rectangle". Then the pseudocode above turns into real code:
for y in range(4):
drawRowOfCircles(win, y)
drawRowOfCircles(win, 8-y)
drawRectangle(win, y)
drawRectangle(win, 8-y)
drawRowOfCircles(win, 4)
Upvotes: 1