Title: Draw stars inside polygons with Python and tkinter
This example shows how to draw stars inside a polygon by connecting every M-th vertex as it draws. If the polygon has N sides and N and M are relatively prime (have no common factors except 1), then the lines visit every vertex and the result is a star. If M is 1, then the lines draw the polygon.
The draw method loops for i in range(num_points), drawing each star in the center of the program's canvas. It also draws each star near the i-th vertex.
The following code shows the draw method that arranges the star drawing.
def draw(self):
# Delete any previous drawing objects.
self.canvas.delete(tk.ALL)
try:
num_points = int(self.num_points_var.get())
if num_points < 3:
messagebox.showinfo('Invalid # Points',
'The polygon must have at least 3 points.')
return
# Get the polygon radii.
width = self.canvas.winfo_width()
height = self.canvas.winfo_height()
r3 = min(width, height) / 2
r1 = r3 / 2
r2 = r3 / 4
r3 = r1 + r2
# Position variables.
cx = width / 2
cy = height / 2
# Position the original points.
pts1 = []
pts2 = []
theta = -math.pi / 2
dtheta = 2 * math.pi / num_points
for i in range(num_points):
pts1.append((r1 * math.cos(theta), r1 * math.sin(theta)))
pts2.append((r2 * math.cos(theta), r2 * math.sin(theta)))
theta += dtheta
# Draw stars.
for skip in range(1, num_points):
# Draw the big version of the star.
self.draw_star(num_points, cx, cy, pts1, skip)
# Draw the smaller version.
theta = -math.pi / 2 + skip * 2 * math.pi / num_points
x = int(cx + r3 * math.cos(theta))
y = int(cy + r3 * math.sin(theta))
self.draw_star(num_points, x, y, pts2, skip)
except Exception as ex:
messagebox.showinfo('Drawing Error', ex)
The draw method starts by making arrays holding points to draw the central and outer stars. These points would draw a polygon centered at the origin if they were drawn as they are in the arrays.
Next the code starts a for loop to draw the smaller polygons. The program calls the draw_star method to draw the central star. It then calculates where the smaller polygon should be drawn and calls draw_star again to draw it there.
The draw_star method shown in the following code draws the lines connecting a polygon's vertices.
def draw_star(self, num_points, x, y, orig_pts, skip):
'''Draw a star centered at (x, y) using this skip value.'''
# Make a PointF array with the points in the proper order.
pts = []
for i in range(num_points):
pt = orig_pts[(i * skip) % num_points]
pts.append((pt[0] + x, pt[1] + y))
# Draw the star.
self.canvas.create_polygon(pts, fill='', outline='red')
This code makes a pts list to hold points. It loops through the vertex numbers. It calculates (i * skip) % num_points for each so it skips some vertices each time. It gets the appropriate vertex, adds the x and y values to center the star at the correct location, and adds the translated point to the pts list.
After building the pts list, the code uses it to create a polygon that draws the star.
Download the example to see all of the details.
|