Skip to content

Instantly share code, notes, and snippets.

@fogleman
Last active May 24, 2016 13:48
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 fogleman/e398657f7b3ce84c397b380aa6ed9da7 to your computer and use it in GitHub Desktop.
Save fogleman/e398657f7b3ce84c397b380aa6ed9da7 to your computer and use it in GitHub Desktop.
Sunburst
from collections import Counter
from math import pi
import cairo
COLORS = {
'a': (0, 0, 180),
'b': (175, 13, 102),
'c': (146, 248, 70),
'd': (255, 200, 47),
'e': (255, 118, 0),
'f': (185, 185, 185),
'g': (235, 235, 222),
'h': (100, 100, 100),
'i': (255, 255, 0),
'j': (55, 19, 112),
'k': (255, 255, 150),
'l': (202, 62, 94),
'm': (205, 145, 63),
'n': (12, 75, 100),
'o': (255, 0, 0),
'p': (175, 155, 50),
'q': (0, 0, 0),
'r': (37, 70, 25),
's': (121, 33, 135),
't': (83, 140, 208),
'u': (0, 154, 37),
'v': (178, 220, 205),
'w': (255, 152, 213),
'x': (0, 0, 74),
'y': (175, 200, 74),
'z': (63, 25, 12),
}
def load_words(path):
with open(path) as fp:
data = fp.read()
return [x.strip().lower() for x in data.split()]
def count(words):
counter = Counter([x[0] for x in words])
items = sorted(counter.items())
total = float(sum(x[1] for x in items))
return [(x[0], x[1] / total) for x in items]
def step(words, dc, cx, cy, angle1, angle2, depth):
if depth > 1:
return
r1 = 512 + depth * (512 + 32)
r2 = r1 + 512
offset = 0
f1 = 0.1
f2 = 1.0 - f1
da = angle2 - angle1
data = count(words)
for index, (letter, pct) in enumerate(data):
r, g, b = COLORS[letter]
dc.set_source_rgb(r / 255.0, g / 255.0, b / 255.0)
s = angle1 + index * da * f1 / len(data)
a1 = s + da * f2 * offset
offset += pct
a2 = s + da * f2 * offset
dc.arc(cx, cy, r1, a1, a2)
dc.arc_negative(cx, cy, r2, a2, a1)
dc.close_path()
dc.fill()
new_words = filter(None, [x[1:] for x in words if x[0] == letter])
step(new_words, dc, cx, cy, a1, a2, depth + 1)
def render(path):
words = load_words('TWL06.txt')
width = height = 4096
cx = cy = width / 2
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
dc = cairo.Context(surface)
dc.set_source_rgb(1, 1, 1)
dc.paint()
dc.set_source_rgb(0, 0, 0)
dc.set_line_width(1)
step(words, dc, cx, cy, -pi / 2, 2 * pi - pi / 2, 0)
# dc.stroke()
surface.write_to_png(path)
def main():
render('output.png')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment