Skip to content

Commit 8925f62

Browse files
committed
removed dependency on svgwrite library
1 parent f8be5c1 commit 8925f62

File tree

2 files changed

+73
-23
lines changed

2 files changed

+73
-23
lines changed

template.svg

Lines changed: 7 additions & 0 deletions
Loading

wordvis.py

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from __future__ import division
2-
import svgwrite
32
import math
43
import colorsys
54
import sys
@@ -19,6 +18,10 @@
1918
AND 22632024504
2019
TO 19347398077
2120
21+
A correctly formatted file containing about 100,000 words can be found at:
22+
23+
http://norvig.com/google-books-common-words.txt
24+
2225
To run the utility supply the path to the word file, and the path to the svg file as follows:
2326
2427
python wordvis.py words.txt word_chart.svg
@@ -76,13 +79,62 @@ def add_chars(parent_node, chars, count):
7679
add_chars(self.root, word, count)
7780

7881

82+
class Svg:
83+
def __init__(self, height, width):
84+
self.template = open('template.svg').read().replace('%height%', str(height)).replace('%width%', str(width))
85+
self.styles = []
86+
self.content = []
87+
88+
def add_styles(self, selector, styles):
89+
styles_txt = []
90+
for k,v in styles.iteritems():
91+
styles_txt.append('{0}:{1};'.format(k,v))
92+
93+
self.styles.append('{0}{{{1}}}'.format(selector,''.join(styles_txt)))
94+
95+
def add_text(self, text, x, y):
96+
self.content.append('<text x="{0}" y="{1}">{2}</text>'.format(x, y, text))
97+
98+
def add_path(self, d, clazz):
99+
self.content.append('<path d="{0}" class="{1}"/>'.format(d, clazz))
100+
101+
def add_segment(self, letter, start_x1, start_y1, end_x1, end_y1, start_x2, start_y2, end_x2, end_y2, r1, r2):
102+
path = "M{0} {1} A {2} {3}, 0, 0, 1, {4} {5} L {6} {7} A {8} {9}, 0, 0, 0, {10} {11} Z".format(
103+
start_x1, start_y1,
104+
r1, r1,
105+
end_x1, end_y1,
106+
end_x2, end_y2,
107+
r2, r2,
108+
start_x2, start_y2
109+
)
110+
self.add_path(path, letter)
111+
112+
def save(self, out_file):
113+
part1, tmp = self.template.split('%style%')
114+
part2, part3 = tmp.split('%substance%')
115+
116+
f=open(out_file, 'w')
117+
f.write(part1)
118+
for style in self.styles:
119+
f.write(style)
120+
f.write(part2)
121+
for content in self.content:
122+
f.write(content)
123+
f.write(part3)
124+
f.close()
125+
126+
79127
class CircleDiagram:
80-
def __init__(self, svg_file):
128+
def __init__(self, svg):
81129
self.ring_count = 0
82-
size = MAX_RINGS * RING_DEPTH * 2
83-
self.dwg = svgwrite.Drawing(svg_file, profile='tiny', size=(size, size))
130+
self.svg = svg
84131
self.center = (size/2, size/2)
85132

133+
for letter in 'abcdefghijklmnopqrstuvwxyz':
134+
svg.add_styles('.' + letter, {'fill' : self._colour_for_letter(letter), 'stroke' : LINE_COLOUR})
135+
136+
svg.add_styles('text', {'fill':FONT_COLOUR, 'font-family' : FONT_NAME, 'font-size' : FONT_SIZE})
137+
86138
def _colour_for_letter(self, letter):
87139
rgb = colorsys.hls_to_rgb((ord(letter) - ord('a')) / 26, COLOUR_LIGHTNESS, 1)
88140
return '#' + ''.join('%02x' % i for i in map(lambda x: x * 255, rgb))
@@ -91,8 +143,6 @@ def _calc_coords(self, r, a):
91143
return self.center[0] + math.sin(a) * r, self.center[1] + -math.cos(a) * r
92144

93145
def _draw_segment(self, letter, level, start_angle, end_angle):
94-
d = self.dwg
95-
96146
r1 = RING_DEPTH * level
97147
r2 = RING_DEPTH * (level + 1)
98148

@@ -101,24 +151,15 @@ def _draw_segment(self, letter, level, start_angle, end_angle):
101151
end_x1, end_y1 = self._calc_coords(r1, end_angle)
102152
end_x2, end_y2 = self._calc_coords(r2, end_angle)
103153

104-
d.add(d.path(d="M{0} {1} A {2} {3}, 0, 0, 1, {4} {5} L {6} {7} A {8} {9}, 0, 0, 0, {10} {11} Z".format(
105-
start_x1, start_y1,
106-
r1, r1,
107-
end_x1, end_y1,
108-
end_x2, end_y2,
109-
r2, r2,
110-
start_x2, start_y2
111-
), fill=self._colour_for_letter(letter), stroke=LINE_COLOUR))
154+
self.svg.add_segment(letter, start_x1, start_y1, end_x1, end_y1, start_x2, start_y2, end_x2, end_y2, r1, r2)
112155

113156
def _draw_letter(self, letter, level, start_angle, end_angle):
114-
d = self.dwg
115-
116157
r1 = RING_DEPTH * level
117158
r2 = RING_DEPTH * (level + 1)
118159

119160
letter_x, letter_y = self._calc_coords((r1 + r2) / 2, (start_angle + end_angle) / 2)
120-
d.add(d.text(letter.upper(), insert=(letter_x-2, letter_y+3),
121-
font_size=FONT_SIZE, fill=FONT_COLOUR, font_family=FONT_NAME))
161+
162+
self.svg.add_text(letter.upper(), letter_x-2, letter_y+3)
122163

123164
def add_ring(self, parts):
124165
level = self.ring_count
@@ -140,8 +181,8 @@ def add_ring(self, parts):
140181

141182
self.ring_count += 1
142183

143-
def save(self):
144-
self.dwg.save()
184+
def save(self, svg_file):
185+
self.svg.save(svg_file)
145186

146187

147188
class Rings:
@@ -186,10 +227,12 @@ def get(self):
186227
word, count = line.split('\t')
187228
tree.add(word.lower().strip(), int(count))
188229

189-
rings = Rings(tree)
190-
diagram = CircleDiagram(svg_file)
230+
size = MAX_RINGS * RING_DEPTH * 2
231+
svg = Svg(size, size)
232+
diagram = CircleDiagram(svg)
191233

234+
rings = Rings(tree)
192235
for ring in rings.get():
193236
diagram.add_ring(ring)
194237

195-
diagram.save()
238+
diagram.save(svg_file)

0 commit comments

Comments
 (0)