#Please retain this and other comments, which contain Python code to generate this SVG. """
import re, math, colorsys
def fmt(string): ## string.format(**vars()) using tags {expression!format} by CMG Lee
def f(tag): i_sep = tag.rfind('!'); return (re.sub('\.0+$', '', str(eval(tag[1:-1])))
if (i_sep < 0) else ('{:%s}' % tag[i_sep + 1:-1]).format(eval(tag[1:i_sep])))
return (re.sub(r'(?<!{){[^{}]+}', lambda m:f(m.group()), string)
.replace('{{', '{').replace('}}', '}'))
def append(obj, string): return obj.append(fmt(string))
def tabbify(cellss, separator='|'):
cellpadss = [list(rows) + [''] * (len(max(cellss, key=len)) - len(rows)) for rows in cellss]
fmts = ['%%%ds' % (max([len(str(cell)) for cell in cols])) for cols in zip(*cellpadss)]
return '\n'.join([separator.join(fmts) % tuple(rows) for rows in cellpadss])
def draw(circles):
radius = abs(scale / circles[0])
# radius += 20 if (radius == size) else -20
if (radius > 0):
colour = '#%06x' % (0xffffff * ((radius / size + 0.65) % 1))
# colour = '#%02x%02x%02x' % tuple(
# [int(255 * component) for component in colorsys.hsv_to_rgb((radius / size) ** 0.75, 1, 1)])
# luma = 0xff * (radius / size) ** 0.25; colour = '#%02x%02x%02x' % (0, 0xff - luma * 3 // 4, luma)
# out_mains.append('''<circles cx="%.0f" cy="%.0f" r="%.0f" stroke="%s"/>''' %
# (scale * circles[1] / circles[0], scale * circles[2] / circles[0], radius, colour))
# out_mains.append('''<use xlink:href="#s" transform="translate(%.0f,%.0f) scale(%.0f)"/>''' %
# (scale * circles[1] / circles[0], scale * circles[2] / circles[0], radius))
out_mains.append(
'''<use xlink:href="#s" transform="translate(%.0f,%.0f) scale(%.0f)" fill="%s"/>''' %
(scale * circles[1] / circles[0], scale * circles[2] / circles[0], radius, colour))
def distance(point1s,point2s):
return ((point1s[0] - point2s[0]) ** 2 + (point1s[1] - point2s[1]) ** 2) ** 0.5
# centress = [[0,-17/15.*32], [-16/17.*32, 161/255.*32], [18/17.*33,48/85.*33]]
centress = [[math.sin(math.radians(angle * 120)),math.cos(math.radians(angle * 120))]
for angle in range(3)]
(centre0s, centre1s, centre2s) = centress
d01 = distance(centre0s,centre1s)
d12 = distance(centre1s,centre2s)
d20 = distance(centre2s,centre0s)
(k0, k1, k2) = ((d01 - d12 + d20) / 2, (d01 + d12 - d20) / 2, (-d01 + d20 + d12) / 2)
k3 = k0 + k1 + k2 - 2 * (k0 * k1 + k1 * k2 + k2 * k0) ** 0.5
circless = [[k3,0.,0.], [k0,centre0s[0]/k0,centre0s[1]/k0],
[k1,centre1s[0]/k1,centre1s[1]/k1], [k2,centre2s[0]/k2,centre2s[1]/k2]]
# circless = [[-6.,0.,0.], [10.,2/3.,0.], [15.,-3/2.,0.], [19.,-5/6.,2.]]
# circless = [[-15.,0.,0.], [32.,0.,-17/15.], [32.,-16/17.,161/255.], [33.,18/17.,48/85.]]
print(circless)
size = 10000
scale = -size * circless[0][0]
queue = []
(out_defs, out_mains) = ([], [])
# append(out_mains, ''' <g fill="none" stroke="#000000" stroke-width="{size / 1000.}">''')
append(out_mains, ''' <g stroke="none">''')
for circles in circless:
queue.append(circless)
draw(circless[0])
circless = circless[1:] + [circless[0]]
while (len(queue) > 0):
circless = queue[0]
circles = [2 * (circless[0][i] + circless[1][i] + circless[2][i]) - circless[3][i]
for i in range(3)]
if (circles[0] < scale / 20):
for i in range(6, 0, -2):
queue.append([circless[i % 3], circless[(i - 1) % 3], circles, circless[(i - 2) % 3]])
draw(circles)
queue = queue[1:]
append(out_mains, ''' </g>''')
(x, width) = (-1.01 * size, 2.02 * size)
out_p = fmt('''width="100%" height="100%" viewBox="{x} {x} {width} {width}"''')
## Compile everything into an .svg file
myself = open(__file__, 'r').read() ## the contents of this very file
file_out = open(__file__[:__file__.rfind('.')] + '.svg', 'wb') ## *.* -> *.svg
try: ## use try/finally so that file is closed even if write fails
file_out.write('''<?xml version="1.0" encoding="utf-8"?><!%s%s
%s%s%s\n%s%s\n%s%s''' % ('-', '-', ## because SVG comments cannot have 2 consecutive '-'s
myself[:myself.find('width',myself.find('<svg'))], ## assume width specified before height/viewBox
out_p, ## replace SVG width/height/viewBox with {out_p} & dynamic SVG blocks with {out*s} contents
myself[myself.find ('>',myself.find('<svg')):
myself.find ('\n',myself.find('BEGIN_'+'DYNAMIC_DEFS'))], '\n'.join(out_defs),
myself[myself.rfind('\n',0,myself.find('END_'+'DYNAMIC_DEFS')):
myself.find ('\n',myself.find('BEGIN_'+'DYNAMIC_MAIN'))], '\n'.join(out_mains),
myself[myself.rfind('\n',0,myself.find('END_'+'DYNAMIC_MAIN')):]))
finally:
file_out.close()
## SVG-Python near-polyglot framework version 3 by CMG Lee (March 2018)