[Rod Stephens Books]
Index Books Python Examples About Rod Contact
[Mastodon] [Bluesky] [Facebook]
[Build Your Own Python Action Arcade!]

[Build Your Own Ray Tracer With Python]

[Beginning Database Design Solutions, Second Edition]

[Beginning Software Engineering, Second Edition]

[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

[WPF 3d, Three-Dimensional Graphics with WPF and C#]

[The C# Helper Top 100]

[Interview Puzzles Dissected]

Title: Make a ring of small, tangent circles inside a larger circle in Python

[Five green circles inside a pink circle]

My earlier post Place three small circles inside a larger circle so they are all tangent in Python explained how you can place three small circles inside a larger circle so they are all mutually tangent. You can do something similar with a larger number of circles, although they won't all touch each other. In this case, each of the smaller circles is tangent to the outer circle and its two neighbors.

Finding the Inner Circles

[Measuring the circles] The way you find the radii of the smaller circles is the same as it was in the previous post. The only difference is that, in the earlier post, we knew from symmetry that the triangle that gives the relationship between the larger and smaller radii is a 30-60-90 triangle. Now the angles are different.

Let R be the radius of the outer circle, let r be the radius of the smaller circles, and consider the picture on the right. If there are n smaller circles, then the angle α is 2×π/n/2. Triangle △ ABC is a right triangle, so sin(α) = r/(R-r) by definition.

We know α, so it's easy to calculate r.

[Calculating the smaller circle radius r]

in the previous example, we could use the 30-60-90 triangle's geometry to find the centers of the smaller circles. That won't work this time, but the solution is still simple. Put the centers distance R - r from the larger circle's center. Make an angle θ vary from 0 to 2π in steps of 2π/n and use that angle's sine and cosine to find the position of the centers.

Calculating the Inner Circles

The following get_inner_circles function returns a list holding the centers and radii of the inner circles.

def get_inner_circles(n, cx, cy, R): '''Find the n circles inside the circle at (cx, cy) with radius R.''' alpha = math.pi * 2 / (2 * n) r = R * math.sin(alpha) / (1 + math.sin(alpha)) d = R - r centers = [] theta = -math.pi / 2 dtheta = 2 * math.pi / n for i in range(n): x = cx + d * math.cos(theta) y = cy + d * math.sin(theta) centers.append((x, y, r)) theta += dtheta return centers

This function sets alpha to 2π/(2n) and then uses it to calculate r. It then sets d to the distance from the larger circle's center to the centers of the smaller circles.

The code then uses a loop to define each of the smaller circles. As the angle theta ranges from -π/2 to 2π-π/2, the code uses sines and cosines to find the position of each circle's center and appends the circle's information to the circles list.

Drawing the Circles

When you click Draw, the program calls the following method to draw its circles.

def draw(self, *args): '''Draw a big circle with three smaller circles inside it.''' # Create a PIL image to hold the drawing. wid = hgt = 400 transparent = (0, 0, 0, 0) image = Image.new('RGBA', (wid, hgt), transparent) dr = ImageDraw.Draw(image) n = int(self.num_circles_var.get()) margin = 10 R = min(wid, hgt) / 2 - margin cx = wid / 2 cy = hgt / 2 # Draw the big circle. rect = (cx - R, cy - R, cx + R, cy + R) dr.ellipse(rect, outline='red', fill='pink', width=5) # Draw the smaller inside circles. centers = get_inner_circles(n, cx, cy, R) for x, y, r in centers: rect = (x-r, y-r, x+r, y+r) dr.ellipse(rect, outline='green', fill='lightgreen', width=2) # Display the image. self.canvas.config(width=wid, height=hgt) self.photo_image = ImageTk.PhotoImage(image) self.canvas.create_image(0, 0, anchor=tk.NW, image=self.photo_image) # Save the image. image.save('circles.png')

The code first creates a PIL image. It gets the number of circles that you entered, calculates the larger circle's radius and center position, and draws the outer circle.

Next, the program calls get_inner_circles to get the inner circle information. It loops through that data and draws the smaller circles.

The code converts the image into a ImageTk.PhotoImage and displays it on the program's Canvas widget. It finishes by saving the image into the file circles.png. [11 circles inside a larger circle]

Conclusion

Finding the more than three inner circles isn't any harder than finding three inner circles. In fact, this example works if you set the number of circles to 3 or even 2. (It doesn't work for 1 or fewer inner circles.)

Download the example to experiment with it and to see additional details.

© 2025 - 2026 Rocky Mountain Computer Consulting, Inc. All rights reserved.