1 #!/usr/bin/env python3
2 #
3 # Draw a circle surrounded by other circles
4 #
5 # Copyright (C) 2018  Antonio Ospite <ao2@ao2.it>
7 #
8 # Using a formula from:
9 # https://math.stackexchange.com/questions/12166/numbers-of-circles-around-a-circle
11 from math import pi, sin, cos, degrees
12 import svgwrite
17         raise ValueError("Radius of outer circles cannot be zero")
19     if number_of_circles < 3:
20         raise ValueError("Number of outer circles cannot be smaller than 3")
22     # Ratio between the inner circle and the outer circles
23     ratio = sin(pi / number_of_circles) / (1 - sin(pi / number_of_circles))
31               number_of_circles, unit=""):
32     border = 10
34     width = height = (inner_circle_radius + outer_circles_radius + border) * 2
36     svg = svgwrite.Drawing(filename, profile='full',
37                            size=(str(width) + unit, str(height) + unit),
38                            viewBox=('0 0 %g %g') % (width, height))
40     cx_inner = cy_inner = width / 2
42     inner_circle = svgwrite.shapes.Circle(center=(cx_inner, cy_inner),
44                                           fill='none',
45                                           stroke='black',
46                                           stroke_width=0.5)
49     # Add a group for the first outer circle for extra flexibility.
50     outer_circle_group = svgwrite.container.Group()
53     cx_outer = cx_inner + sin(0) * (inner_circle_radius +
55     cy_outer = cy_inner + cos(0) * (inner_circle_radius +
57     outer_circle = svgwrite.shapes.Circle(center=(cx_outer, cy_outer),
59                                           fill='none',
60                                           stroke='black',
61                                           stroke_width=0.5)
64     # Clone the group for the other outer circles to make it easier to keep
65     # visual symmetry by editing just the first group added above.
66     for i in range(1, number_of_circles):
67         theta = i * 2 * pi / number_of_circles
68         outer_circle_clone = svgwrite.container.Use(outer_circle_group,
69                                                     insert=(0, 0),
70                                                     transform="rotate(%f, %f, %f)" %
71                                                     (degrees(theta),
72                                                      cx_inner,
73                                                      cy_inner))