Initial import master
authorAntonio Ospite <ao2@ao2.it>
Wed, 23 May 2018 14:37:19 +0000 (16:37 +0200)
committerAntonio Ospite <ao2@ao2.it>
Wed, 23 May 2018 15:05:28 +0000 (17:05 +0200)
.gitignore [new file with mode: 0644]
draw_circle_surrounded_by_circles.py [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..210b681
--- /dev/null
@@ -0,0 +1 @@
+circle-surrounded-by-circles.svg
diff --git a/draw_circle_surrounded_by_circles.py b/draw_circle_surrounded_by_circles.py
new file mode 100755 (executable)
index 0000000..0a1ed24
--- /dev/null
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+#
+# Draw a circle surrounded by other circles
+#
+# Copyright (C) 2018  Antonio Ospite <ao2@ao2.it>
+# SPDX-License-Identifier: WTFPL
+#
+# Using a formula from:
+# https://math.stackexchange.com/questions/12166/numbers-of-circles-around-a-circle
+
+from math import pi, sin, cos, degrees
+import svgwrite
+
+
+def calc_inner_circle_radius(outer_circles_radius, number_of_circles):
+    if outer_circles_radius <= 0:
+        raise ValueError("Radius of outer circles cannot be zero")
+
+    if number_of_circles < 3:
+        raise ValueError("Number of outer circles cannot be smaller than 3")
+
+    # Ratio between the inner circle and the outer circles
+    ratio = sin(pi / number_of_circles) / (1 - sin(pi / number_of_circles))
+
+    inner_circle_radius = outer_circles_radius / ratio
+
+    return inner_circle_radius
+
+
+def write_svg(filename, inner_circle_radius, outer_circles_radius,
+              number_of_circles, unit=""):
+    border = 10
+
+    width = height = (inner_circle_radius + outer_circles_radius + border) * 2
+
+    svg = svgwrite.Drawing(filename, profile='full',
+                           size=(str(width) + unit, str(height) + unit),
+                           viewBox=('0 0 %g %g') % (width, height))
+
+    cx_inner = cy_inner = width / 2
+
+    inner_circle = svgwrite.shapes.Circle(center=(cx_inner, cy_inner),
+                                          r=inner_circle_radius,
+                                          fill='none',
+                                          stroke='black',
+                                          stroke_width=0.5)
+    svg.add(inner_circle)
+
+    # Add a group for the first outer circle for extra flexibility.
+    outer_circle_group = svgwrite.container.Group()
+    svg.add(outer_circle_group)
+
+    cx_outer = cx_inner + sin(0) * (inner_circle_radius +
+                                    outer_circles_radius)
+    cy_outer = cy_inner + cos(0) * (inner_circle_radius +
+                                    outer_circles_radius)
+    outer_circle = svgwrite.shapes.Circle(center=(cx_outer, cy_outer),
+                                          r=outer_circles_radius,
+                                          fill='none',
+                                          stroke='black',
+                                          stroke_width=0.5)
+    outer_circle_group.add(outer_circle)
+
+    # Clone the group for the other outer circles to make it easier to keep
+    # visual symmetry by editing just the first group added above.
+    for i in range(1, number_of_circles):
+        theta = i * 2 * pi / number_of_circles
+        outer_circle_clone = svgwrite.container.Use(outer_circle_group,
+                                                    insert=(0, 0),
+                                                    transform="rotate(%f, %f, %f)" %
+                                                    (degrees(theta),
+                                                     cx_inner,
+                                                     cy_inner))
+        svg.add(outer_circle_clone)
+
+    svg.save()
+
+
+def main():
+    outer_circles_radius = 2.5
+    number_of_circles = 22
+
+    inner_circle_radius = calc_inner_circle_radius(outer_circles_radius, number_of_circles)
+
+    write_svg("circle-surrounded-by-circles.svg", inner_circle_radius,
+              outer_circles_radius, number_of_circles, unit="mm")
+
+
+if __name__ == "__main__":
+    main()