From: Antonio Ospite Date: Wed, 23 May 2018 14:37:19 +0000 (+0200) Subject: Initial import X-Git-Url: https://git.ao2.it/experiments/circle-surrounded-by-circles.git/commitdiff_plain/16eec12b4f22f317a640cdd04ee73292530c677f?ds=sidebyside Initial import --- 16eec12b4f22f317a640cdd04ee73292530c677f diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..210b681 --- /dev/null +++ b/.gitignore @@ -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 index 0000000..0a1ed24 --- /dev/null +++ b/draw_circle_surrounded_by_circles.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# +# Draw a circle surrounded by other circles +# +# Copyright (C) 2018 Antonio Ospite +# 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()