P4.4.3Creating a set of SVG image files
Write a Python program to create a directory, test in the user's home directory and to populate it with 20 SVG files depicting a small, filled red circle inside a large, black, unfilled circle, for example:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="500" height="500" style="background: #ffffff">
<circle cx="250.0" cy="250.0" r="200" style="stroke: black; stroke-width: 2px; fill: none;"/>
<circle cx="430.0" cy="250.0" r="20" style="stroke: red; fill: red;"/>
</svg>
Each file should move the red circle around the inside rim of the larger circle so that the 20 files together could form an animation.
One way to achieve this using the free ImageMagick software. Ensure the SVG files are named: fig00.svg, fig01.svg, etc. and issue the following command from your operating system's command line:
$ convert -delay 5 -loop 0 fig*.svg animation.gif
to produce an animated GIF image.
Show solution
Here is one approach.
import os
import math
nfigs = 20
HOME = os.getenv('HOME')
pathdir = os.path.join(HOME, 'test')
if not os.path.exists(pathdir):
os.mkdir(pathdir)
canvas_height, canvas_width = 500, 500
cx, cy = canvas_height / 2, canvas_width / 2
r1, r2 = 200, 20
# A list of angles to rotate the small red circle through:
alphas = [2*math.pi / nfigs * n for n in range(nfigs)]
for n, alpha in enumerate(alphas):
filename = os.path.join(pathdir, f'fig{n:02d}.svg')
with open(filename, 'w') as fo:
# SVG preamble
print("""<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="{}" height="{}" style="background: {}">""".format(
canvas_width, canvas_height, '#ffffff'), file=fo)
# Large, open black circle
print(f'<circle cx="{cx}" cy="{cy}" r="{r1}" style="stroke: black;'
f' stroke-width: 2px; fill: none;"/>', file=fo)
# Small, filled red circle on the inner rim of the black one,
# displaced from the x-axis by the angle alpha
cx2, cy2 = cx+(r1-r2) * math.cos(alpha), cy+(r1-r2) * math.sin(alpha)
print(f'<circle cx="{cx2}" cy="{cy2}" r="{r2}" style="stroke: red; fill: red;"/>',
file=fo)
print('</svg>', file=fo)
Running these files through ImageMagick's convert program as suggested generates the animated GIF below.