Skip to content

Instantly share code, notes, and snippets.

@neizod
Last active May 26, 2021 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neizod/506e32d7841b27399e67e8826445b4df to your computer and use it in GitHub Desktop.
Save neizod/506e32d7841b27399e67e8826445b4df to your computer and use it in GitHub Desktop.
Megagon SVG!
#!/usr/bin/env python3
# NOTE
# LAYERS is a non-empty list of integers.
# The n-gon can be determine by calc_ngon(LAYERS), e.g.,
#LAYERS = [1, 2, 2] # heptagon (not constructible)
#LAYERS = [1, 4, 3] # heptadecagon (17 sides)
#LAYERS = [2, 2, 3, 2] # tetracontadigon (42)
#LAYERS = [4, 1, 4, 3, 2, 2] # 360-gon
#LAYERS = [4, 3, 2, 4, 3, 2] # chiliagon (1,000)
#LAYERS = [1, 9, 10, 10, 10] # myriagon (10,000)
#LAYERS = [1, 16, 15, 16, 16] # 65537-gon
LAYERS = [100, 99, 100] # megagon (1,000,000)
# NOTE
# Otherwise, just use NGON to describe the polygon,
# and let the program determine a pattern for LAYERS automatically.
#NGON = 17
PADDING = 50
RADIUS = 700
PRECISION = 9
##############################################################################
import sys
from types import SimpleNamespace as namespace
from math import sin, cos, tan, radians
from operator import mul
from functools import reduce
from itertools import product
from collections import Counter
def translate(center, x, y):
return x+center, y+center
def _rotate(angle, x, y):
return x*cos(angle) - y*sin(angle), x*sin(angle) + y*cos(angle)
def rotate(x, y, angle, center):
return translate(center, *_rotate(angle, *translate(-center, x, y)))
def iter_primes(memo=namespace(pi=0, ps=[2, 3])):
k = 0
while True:
while len(memo.ps) <= k:
head = memo.ps[memo.pi]**2 + 1
memo.pi += 1
tail = memo.ps[memo.pi]**2
seive = list(range(head, tail))
for p in memo.ps[:memo.pi]:
size = 1 + (tail - head + (head % -p)) // p
seive[-head%p::p] = [0] * size
memo.ps += (p for p in seive if p)
yield memo.ps[k]
k += 1
def factors(n):
if n == 1:
return [1]
fs = []
for p in iter_primes():
if p**2 > n:
break
while n % p == 0:
fs += [p]
n //= p
if n > 1:
fs += [n]
return fs
def divisors(n):
gfs = ({p**i for i in range(k+1)} for p, k in Counter(factors(n)).items())
return sorted(reduce(mul, ts) for ts in product(*gfs))
def calc_ngon(layers):
r = 1
for v in reversed(layers):
r *= v
r += 1
return r - 1
def calc_layers(ngon, memo=[()]):
while len(memo) < ngon+1:
row = [(d, *memo[len(memo)//d-1]) for d in divisors(len(memo))]
memo += [min(row, key=lambda r: (sum(r), len(r)))]
return memo[ngon]
class Polygon(object):
def __init__(self, data):
if isinstance(data, int):
self.ngon = data
self.rel_pieces = calc_layers(data)
elif isinstance(data, list) or isinstance(data, iter):
self.rel_pieces = data
self.ngon = calc_ngon(data)
else:
raise KeyError('initial data for polygon must be int or list of int.')
if self.ngon < 3:
raise KeyError('its absurd to draw a polygon with number of sides less than 3.')
self.angle = 360/self.ngon
self.abs_pieces = [self.rel_pieces[0]]
self.tot_pieces = [self.rel_pieces[0]]
self._init_pieces_info()
def _init_pieces_info(self):
for i in range(1, len(self.rel_pieces)):
self.abs_pieces += [self.abs_pieces[i-1] * self.rel_pieces[i]]
self.tot_pieces += [self.tot_pieces[i-1] + self.abs_pieces[i]]
def base_group(self, radius, padding):
center = radius + padding
x = center - (radius * tan(radians(self.angle/2)))
y = padding
spec = []
for _ in range(self.rel_pieces[0]+1):
spec += f'{round(x, PRECISION)},{round(y, PRECISION)}',
x, y = rotate(x, y, radians(self.angle), center)
return f'<g id="a0"><polyline points="{" ".join(spec)}" stroke="#000" fill="none" /></g>\n'
def make_group(self, k, radius, padding, precision):
if k == 0:
return self.base_group(radius, padding)
center = radius + padding
theta = self.angle * self.abs_pieces[k-1]
s = f'<g id="a{k}">\n'
for i in range(1, 1+self.rel_pieces[k]):
rot = round(theta*i, precision)
s += f'<use xlink:href="#a{k-1}" transform="rotate({rot} {center} {center})" />\n'
s += '</g>\n'
return s
def svg(self, radius, padding, precision):
size = 2 * (radius + padding)
header = 'xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"'
s = f'<!-- {self.ngon}-gon with layers {self.rel_pieces}. -->\n'
s += f'<svg {header} height="{size}" width="{size}">\n'
for i, _ in enumerate(self.rel_pieces):
s += self.make_group(i, radius, padding, precision)
s += '</svg>'
return s
if __name__ == '__main__':
if len(sys.argv) == 2:
print(Polygon(int(sys.argv[1])).svg(RADIUS, PADDING, PRECISION))
elif len(sys.argv) > 2:
print(Polygon(list(map(int, sys.argv[1:]))).svg(RADIUS, PADDING, PRECISION))
elif 'LAYERS' in globals():
print(Polygon(LAYERS).svg(RADIUS, PADDING, PRECISION))
elif 'NGON' in globals():
print(Polygon(NGON).svg(RADIUS, PADDING, PRECISION))
else:
raise NotImplementedError
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
<!-- 1000000-gon with layers [100, 99, 100]. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="1500" width="1500">
<g id="a0"><polyline points="749.997800885,50 750.002199115,50.0 750.006597345,50.000000028 750.010995574,50.000000083 750.015393804,50.000000166 750.019792034,50.000000276 750.024190263,50.000000415 750.028588493,50.00000058 750.032986723,50.000000774 750.037384953,50.000000995 750.041783182,50.000001244 750.046181412,50.00000152 750.050579642,50.000001824 750.054977871,50.000002156 750.059376101,50.000002515 750.063774331,50.000002902 750.06817256,50.000003316 750.07257079,50.000003758 750.07696902,50.000004228 750.08136725,50.000004726 750.085765479,50.000005251 750.090163709,50.000005803 750.094561939,50.000006384 750.098960168,50.000006992 750.103358398,50.000007627 750.107756628,50.00000829 750.112154857,50.000008981 750.116553087,50.0000097 750.120951317,50.000010446 750.125349546,50.00001122 750.129747776,50.000012021 750.134146005,50.00001285 750.138544235,50.000013707 750.142942465,50.000014591 750.147340694,50.000015503 750.151738924,50.000016443 750.156137154,50.00001741 750.160535383,50.000018405 750.164933613,50.000019427 750.169331842,50.000020477 750.173730072,50.000021555 750.178128302,50.000022661 750.182526531,50.000023794 750.186924761,50.000024954 750.19132299,50.000026143 750.19572122,50.000027359 750.200119449,50.000028602 750.204517679,50.000029873 750.208915908,50.000031172 750.213314138,50.000032499 750.217712367,50.000033853 750.222110597,50.000035234 750.226508826,50.000036644 750.230907056,50.000038081 750.235305285,50.000039546 750.239703515,50.000041038 750.244101744,50.000042558 750.248499974,50.000044105 750.252898203,50.00004568 750.257296433,50.000047283 750.261694662,50.000048914 750.266092891,50.000050572 750.270491121,50.000052258 750.27488935,50.000053971 750.279287579,50.000055712 750.283685809,50.000057481 750.288084038,50.000059277 750.292482268,50.000061101 750.296880497,50.000062952 750.301278726,50.000064831 750.305676955,50.000066738 750.310075185,50.000068673 750.314473414,50.000070635 750.318871643,50.000072624 750.323269873,50.000074642 750.327668102,50.000076687 750.332066331,50.000078759 750.33646456,50.00008086 750.340862789,50.000082988 750.345261019,50.000085143 750.349659248,50.000087326 750.354057477,50.000089537 750.358455706,50.000091775 750.362853935,50.000094042 750.367252164,50.000096335 750.371650393,50.000098657 750.376048623,50.000101006 750.380446852,50.000103382 750.384845081,50.000105786 750.38924331,50.000108218 750.393641539,50.000110678 750.398039768,50.000113165 750.402437997,50.00011568 750.406836226,50.000118222 750.411234455,50.000120792 750.415632684,50.00012339 750.420030913,50.000126015 750.424429141,50.000128668 750.42882737,50.000131349 750.433225599,50.000134057 750.437623828,50.000136793" stroke="#000" fill="none" /></g>
<g id="a1">
<use xlink:href="#a0" transform="rotate(0.036 750 750)" />
<use xlink:href="#a0" transform="rotate(0.072 750 750)" />
<use xlink:href="#a0" transform="rotate(0.108 750 750)" />
<use xlink:href="#a0" transform="rotate(0.144 750 750)" />
<use xlink:href="#a0" transform="rotate(0.18 750 750)" />
<use xlink:href="#a0" transform="rotate(0.216 750 750)" />
<use xlink:href="#a0" transform="rotate(0.252 750 750)" />
<use xlink:href="#a0" transform="rotate(0.288 750 750)" />
<use xlink:href="#a0" transform="rotate(0.324 750 750)" />
<use xlink:href="#a0" transform="rotate(0.36 750 750)" />
<use xlink:href="#a0" transform="rotate(0.396 750 750)" />
<use xlink:href="#a0" transform="rotate(0.432 750 750)" />
<use xlink:href="#a0" transform="rotate(0.468 750 750)" />
<use xlink:href="#a0" transform="rotate(0.504 750 750)" />
<use xlink:href="#a0" transform="rotate(0.54 750 750)" />
<use xlink:href="#a0" transform="rotate(0.576 750 750)" />
<use xlink:href="#a0" transform="rotate(0.612 750 750)" />
<use xlink:href="#a0" transform="rotate(0.648 750 750)" />
<use xlink:href="#a0" transform="rotate(0.684 750 750)" />
<use xlink:href="#a0" transform="rotate(0.72 750 750)" />
<use xlink:href="#a0" transform="rotate(0.756 750 750)" />
<use xlink:href="#a0" transform="rotate(0.792 750 750)" />
<use xlink:href="#a0" transform="rotate(0.828 750 750)" />
<use xlink:href="#a0" transform="rotate(0.864 750 750)" />
<use xlink:href="#a0" transform="rotate(0.9 750 750)" />
<use xlink:href="#a0" transform="rotate(0.936 750 750)" />
<use xlink:href="#a0" transform="rotate(0.972 750 750)" />
<use xlink:href="#a0" transform="rotate(1.008 750 750)" />
<use xlink:href="#a0" transform="rotate(1.044 750 750)" />
<use xlink:href="#a0" transform="rotate(1.08 750 750)" />
<use xlink:href="#a0" transform="rotate(1.116 750 750)" />
<use xlink:href="#a0" transform="rotate(1.152 750 750)" />
<use xlink:href="#a0" transform="rotate(1.188 750 750)" />
<use xlink:href="#a0" transform="rotate(1.224 750 750)" />
<use xlink:href="#a0" transform="rotate(1.26 750 750)" />
<use xlink:href="#a0" transform="rotate(1.296 750 750)" />
<use xlink:href="#a0" transform="rotate(1.332 750 750)" />
<use xlink:href="#a0" transform="rotate(1.368 750 750)" />
<use xlink:href="#a0" transform="rotate(1.404 750 750)" />
<use xlink:href="#a0" transform="rotate(1.44 750 750)" />
<use xlink:href="#a0" transform="rotate(1.476 750 750)" />
<use xlink:href="#a0" transform="rotate(1.512 750 750)" />
<use xlink:href="#a0" transform="rotate(1.548 750 750)" />
<use xlink:href="#a0" transform="rotate(1.584 750 750)" />
<use xlink:href="#a0" transform="rotate(1.62 750 750)" />
<use xlink:href="#a0" transform="rotate(1.656 750 750)" />
<use xlink:href="#a0" transform="rotate(1.692 750 750)" />
<use xlink:href="#a0" transform="rotate(1.728 750 750)" />
<use xlink:href="#a0" transform="rotate(1.764 750 750)" />
<use xlink:href="#a0" transform="rotate(1.8 750 750)" />
<use xlink:href="#a0" transform="rotate(1.836 750 750)" />
<use xlink:href="#a0" transform="rotate(1.872 750 750)" />
<use xlink:href="#a0" transform="rotate(1.908 750 750)" />
<use xlink:href="#a0" transform="rotate(1.944 750 750)" />
<use xlink:href="#a0" transform="rotate(1.98 750 750)" />
<use xlink:href="#a0" transform="rotate(2.016 750 750)" />
<use xlink:href="#a0" transform="rotate(2.052 750 750)" />
<use xlink:href="#a0" transform="rotate(2.088 750 750)" />
<use xlink:href="#a0" transform="rotate(2.124 750 750)" />
<use xlink:href="#a0" transform="rotate(2.16 750 750)" />
<use xlink:href="#a0" transform="rotate(2.196 750 750)" />
<use xlink:href="#a0" transform="rotate(2.232 750 750)" />
<use xlink:href="#a0" transform="rotate(2.268 750 750)" />
<use xlink:href="#a0" transform="rotate(2.304 750 750)" />
<use xlink:href="#a0" transform="rotate(2.34 750 750)" />
<use xlink:href="#a0" transform="rotate(2.376 750 750)" />
<use xlink:href="#a0" transform="rotate(2.412 750 750)" />
<use xlink:href="#a0" transform="rotate(2.448 750 750)" />
<use xlink:href="#a0" transform="rotate(2.484 750 750)" />
<use xlink:href="#a0" transform="rotate(2.52 750 750)" />
<use xlink:href="#a0" transform="rotate(2.556 750 750)" />
<use xlink:href="#a0" transform="rotate(2.592 750 750)" />
<use xlink:href="#a0" transform="rotate(2.628 750 750)" />
<use xlink:href="#a0" transform="rotate(2.664 750 750)" />
<use xlink:href="#a0" transform="rotate(2.7 750 750)" />
<use xlink:href="#a0" transform="rotate(2.736 750 750)" />
<use xlink:href="#a0" transform="rotate(2.772 750 750)" />
<use xlink:href="#a0" transform="rotate(2.808 750 750)" />
<use xlink:href="#a0" transform="rotate(2.844 750 750)" />
<use xlink:href="#a0" transform="rotate(2.88 750 750)" />
<use xlink:href="#a0" transform="rotate(2.916 750 750)" />
<use xlink:href="#a0" transform="rotate(2.952 750 750)" />
<use xlink:href="#a0" transform="rotate(2.988 750 750)" />
<use xlink:href="#a0" transform="rotate(3.024 750 750)" />
<use xlink:href="#a0" transform="rotate(3.06 750 750)" />
<use xlink:href="#a0" transform="rotate(3.096 750 750)" />
<use xlink:href="#a0" transform="rotate(3.132 750 750)" />
<use xlink:href="#a0" transform="rotate(3.168 750 750)" />
<use xlink:href="#a0" transform="rotate(3.204 750 750)" />
<use xlink:href="#a0" transform="rotate(3.24 750 750)" />
<use xlink:href="#a0" transform="rotate(3.276 750 750)" />
<use xlink:href="#a0" transform="rotate(3.312 750 750)" />
<use xlink:href="#a0" transform="rotate(3.348 750 750)" />
<use xlink:href="#a0" transform="rotate(3.384 750 750)" />
<use xlink:href="#a0" transform="rotate(3.42 750 750)" />
<use xlink:href="#a0" transform="rotate(3.456 750 750)" />
<use xlink:href="#a0" transform="rotate(3.492 750 750)" />
<use xlink:href="#a0" transform="rotate(3.528 750 750)" />
<use xlink:href="#a0" transform="rotate(3.564 750 750)" />
</g>
<g id="a2">
<use xlink:href="#a1" transform="rotate(3.564 750 750)" />
<use xlink:href="#a1" transform="rotate(7.128 750 750)" />
<use xlink:href="#a1" transform="rotate(10.692 750 750)" />
<use xlink:href="#a1" transform="rotate(14.256 750 750)" />
<use xlink:href="#a1" transform="rotate(17.82 750 750)" />
<use xlink:href="#a1" transform="rotate(21.384 750 750)" />
<use xlink:href="#a1" transform="rotate(24.948 750 750)" />
<use xlink:href="#a1" transform="rotate(28.512 750 750)" />
<use xlink:href="#a1" transform="rotate(32.076 750 750)" />
<use xlink:href="#a1" transform="rotate(35.64 750 750)" />
<use xlink:href="#a1" transform="rotate(39.204 750 750)" />
<use xlink:href="#a1" transform="rotate(42.768 750 750)" />
<use xlink:href="#a1" transform="rotate(46.332 750 750)" />
<use xlink:href="#a1" transform="rotate(49.896 750 750)" />
<use xlink:href="#a1" transform="rotate(53.46 750 750)" />
<use xlink:href="#a1" transform="rotate(57.024 750 750)" />
<use xlink:href="#a1" transform="rotate(60.588 750 750)" />
<use xlink:href="#a1" transform="rotate(64.152 750 750)" />
<use xlink:href="#a1" transform="rotate(67.716 750 750)" />
<use xlink:href="#a1" transform="rotate(71.28 750 750)" />
<use xlink:href="#a1" transform="rotate(74.844 750 750)" />
<use xlink:href="#a1" transform="rotate(78.408 750 750)" />
<use xlink:href="#a1" transform="rotate(81.972 750 750)" />
<use xlink:href="#a1" transform="rotate(85.536 750 750)" />
<use xlink:href="#a1" transform="rotate(89.1 750 750)" />
<use xlink:href="#a1" transform="rotate(92.664 750 750)" />
<use xlink:href="#a1" transform="rotate(96.228 750 750)" />
<use xlink:href="#a1" transform="rotate(99.792 750 750)" />
<use xlink:href="#a1" transform="rotate(103.356 750 750)" />
<use xlink:href="#a1" transform="rotate(106.92 750 750)" />
<use xlink:href="#a1" transform="rotate(110.484 750 750)" />
<use xlink:href="#a1" transform="rotate(114.048 750 750)" />
<use xlink:href="#a1" transform="rotate(117.612 750 750)" />
<use xlink:href="#a1" transform="rotate(121.176 750 750)" />
<use xlink:href="#a1" transform="rotate(124.74 750 750)" />
<use xlink:href="#a1" transform="rotate(128.304 750 750)" />
<use xlink:href="#a1" transform="rotate(131.868 750 750)" />
<use xlink:href="#a1" transform="rotate(135.432 750 750)" />
<use xlink:href="#a1" transform="rotate(138.996 750 750)" />
<use xlink:href="#a1" transform="rotate(142.56 750 750)" />
<use xlink:href="#a1" transform="rotate(146.124 750 750)" />
<use xlink:href="#a1" transform="rotate(149.688 750 750)" />
<use xlink:href="#a1" transform="rotate(153.252 750 750)" />
<use xlink:href="#a1" transform="rotate(156.816 750 750)" />
<use xlink:href="#a1" transform="rotate(160.38 750 750)" />
<use xlink:href="#a1" transform="rotate(163.944 750 750)" />
<use xlink:href="#a1" transform="rotate(167.508 750 750)" />
<use xlink:href="#a1" transform="rotate(171.072 750 750)" />
<use xlink:href="#a1" transform="rotate(174.636 750 750)" />
<use xlink:href="#a1" transform="rotate(178.2 750 750)" />
<use xlink:href="#a1" transform="rotate(181.764 750 750)" />
<use xlink:href="#a1" transform="rotate(185.328 750 750)" />
<use xlink:href="#a1" transform="rotate(188.892 750 750)" />
<use xlink:href="#a1" transform="rotate(192.456 750 750)" />
<use xlink:href="#a1" transform="rotate(196.02 750 750)" />
<use xlink:href="#a1" transform="rotate(199.584 750 750)" />
<use xlink:href="#a1" transform="rotate(203.148 750 750)" />
<use xlink:href="#a1" transform="rotate(206.712 750 750)" />
<use xlink:href="#a1" transform="rotate(210.276 750 750)" />
<use xlink:href="#a1" transform="rotate(213.84 750 750)" />
<use xlink:href="#a1" transform="rotate(217.404 750 750)" />
<use xlink:href="#a1" transform="rotate(220.968 750 750)" />
<use xlink:href="#a1" transform="rotate(224.532 750 750)" />
<use xlink:href="#a1" transform="rotate(228.096 750 750)" />
<use xlink:href="#a1" transform="rotate(231.66 750 750)" />
<use xlink:href="#a1" transform="rotate(235.224 750 750)" />
<use xlink:href="#a1" transform="rotate(238.788 750 750)" />
<use xlink:href="#a1" transform="rotate(242.352 750 750)" />
<use xlink:href="#a1" transform="rotate(245.916 750 750)" />
<use xlink:href="#a1" transform="rotate(249.48 750 750)" />
<use xlink:href="#a1" transform="rotate(253.044 750 750)" />
<use xlink:href="#a1" transform="rotate(256.608 750 750)" />
<use xlink:href="#a1" transform="rotate(260.172 750 750)" />
<use xlink:href="#a1" transform="rotate(263.736 750 750)" />
<use xlink:href="#a1" transform="rotate(267.3 750 750)" />
<use xlink:href="#a1" transform="rotate(270.864 750 750)" />
<use xlink:href="#a1" transform="rotate(274.428 750 750)" />
<use xlink:href="#a1" transform="rotate(277.992 750 750)" />
<use xlink:href="#a1" transform="rotate(281.556 750 750)" />
<use xlink:href="#a1" transform="rotate(285.12 750 750)" />
<use xlink:href="#a1" transform="rotate(288.684 750 750)" />
<use xlink:href="#a1" transform="rotate(292.248 750 750)" />
<use xlink:href="#a1" transform="rotate(295.812 750 750)" />
<use xlink:href="#a1" transform="rotate(299.376 750 750)" />
<use xlink:href="#a1" transform="rotate(302.94 750 750)" />
<use xlink:href="#a1" transform="rotate(306.504 750 750)" />
<use xlink:href="#a1" transform="rotate(310.068 750 750)" />
<use xlink:href="#a1" transform="rotate(313.632 750 750)" />
<use xlink:href="#a1" transform="rotate(317.196 750 750)" />
<use xlink:href="#a1" transform="rotate(320.76 750 750)" />
<use xlink:href="#a1" transform="rotate(324.324 750 750)" />
<use xlink:href="#a1" transform="rotate(327.888 750 750)" />
<use xlink:href="#a1" transform="rotate(331.452 750 750)" />
<use xlink:href="#a1" transform="rotate(335.016 750 750)" />
<use xlink:href="#a1" transform="rotate(338.58 750 750)" />
<use xlink:href="#a1" transform="rotate(342.144 750 750)" />
<use xlink:href="#a1" transform="rotate(345.708 750 750)" />
<use xlink:href="#a1" transform="rotate(349.272 750 750)" />
<use xlink:href="#a1" transform="rotate(352.836 750 750)" />
<use xlink:href="#a1" transform="rotate(356.4 750 750)" />
</g>
</svg>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment