Browse Source

Start working on radar

pull/8/head
Florian Mounier 13 years ago
parent
commit
0ee9d3425c
  1. 13
      out.py
  2. 1
      pygal/__init__.py
  3. 27
      pygal/graph/radar.py
  4. 32
      pygal/svg.py

13
out.py

@ -1,6 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
from pygal import ( from pygal import (
Line, Bar, XY, Pie, StackedBar, Config, Line, Bar, XY, Pie, Radar, StackedBar, Config,
HorizontalBar, HorizontalStackedBar) HorizontalBar, HorizontalStackedBar)
from pygal.style import NeonStyle from pygal.style import NeonStyle
from math import cos, sin from math import cos, sin
@ -80,3 +80,14 @@ pie.add('test2', 29)
pie.title = "Pie test" pie.title = "Pie test"
with open('out-pie.svg', 'w') as f: with open('out-pie.svg', 'w') as f:
f.write(pie.render()) f.write(pie.render())
config = Config()
config.x_labels = (
'black', 'red', 'blue', 'yellow', 'orange', 'green', 'white')
radar = Radar(config)
radar.add('test', [9, 10, 3, 5, 7, 2, 5])
radar.add('test2', [10, 2, 0, 5, 1, 9, 4])
radar.title = "Radar test"
with open('out-radar.svg', 'w') as f:
f.write(radar.render())

1
pygal/__init__.py

@ -7,4 +7,5 @@ from pygal.graph.horizontal import HorizontalStackedBar
from pygal.graph.line import Line from pygal.graph.line import Line
from pygal.graph.xy import XY from pygal.graph.xy import XY
from pygal.graph.pie import Pie from pygal.graph.pie import Pie
from pygal.graph.radar import Radar
from pygal.config import Config from pygal.config import Config

27
pygal/graph/radar.py

@ -0,0 +1,27 @@
from pygal.graph.base import BaseGraph
from math import pi
class Radar(BaseGraph):
"""Kiviat graph"""
def _compute(self):
vals = [val for serie in self.series for val in serie.values]
self._box.ymax = 2 * max(vals)
self._box.ymin = - self._box.ymax
self._box.xmin = self._box.ymin
self._box.xmax = self._box.ymax
delta = 2 * pi / float(len(self.x_labels))
x_step = len(self.series[0].values)
self._x_pos = [.5 * pi - i * delta for i in range(x_step)]
self._y_pos = self._pos(self._box.ymin, self._box.ymax, self.y_scale
) if not self.y_labels else map(int, self.y_labels)
self._x_labels = self.x_labels and zip(self.x_labels, self._x_pos)
self._y_labels = zip(map(str, self._y_pos), self._y_pos)
def _plot(self):
for serie in self.series:
serie_node = self.svg.serie(serie.index)
# self.svg.web(serie_node, serie,
# [val / float(self._rmax) for val in serie.values])

32
pygal/svg.py

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import os import os
from lxml import etree from lxml import etree
from pygal.view import View from pygal.view import View
@ -20,7 +21,8 @@ class Svg(object):
None: self.ns, None: self.ns,
'xlink': 'http://www.w3.org/1999/xlink', 'xlink': 'http://www.w3.org/1999/xlink',
}) })
self.root.append(etree.Comment(u'Generated with pygal ©Kozea 2012'))
self.root.append(etree.Comment(u'http://github.com/Kozea/pygal'))
self.defs = self.node(tag='defs') self.defs = self.node(tag='defs')
self.add_style(self.graph.base_css or os.path.join( self.add_style(self.graph.base_css or os.path.join(
os.path.dirname(__file__), 'css', 'graph.css')) os.path.dirname(__file__), 'css', 'graph.css'))
@ -133,6 +135,22 @@ class Svg(object):
self.graph.y_label_rotation, x, y) self.graph.y_label_rotation, x, y)
text.text = label text.text = label
def web_axis(self):
axis = self.node(self.plot, class_="axis polar")
delta = 2 * pi / float(len(self.graph.x_labels))
center = self.view((0, 0))
f = lambda x: '%f %f' % x
for i, title in enumerate(self.graph.x_labels):
angle = .5 * pi - i * delta
end = self.view((cos(angle), sin(angle)))
self.node(axis, 'path',
d='M%s L%s' % (f(center), f(end)),
class_='line')
self.node(axis, 'text',
x=end[0],
y=end[1]
).text = str(i)
def legend(self): def legend(self):
if not self.graph.show_legend: if not self.graph.show_legend:
return return
@ -265,6 +283,18 @@ class Svg(object):
y=center[1] - text_r * sin(text_angle), y=center[1] - text_r * sin(text_angle),
).text = '{:.2%}'.format(perc) ).text = '{:.2%}'.format(perc)
def web(self, serie_node, serie, radius):
webs = self.node(serie_node, class_="webs")
web = self.node(webs, class_="web")
# view_radius = map(self.view, radius)
origin = '%f %f' % self.view((0, 0))
dot1 = '%f %f' % self.view((1, 1))
dot2 = '%f %f' % self.view((-1, -1))
self.node(web, 'path',
d='M%s L%s %s' % (
origin, dot1, dot2),
class_='web')
def render(self): def render(self):
return etree.tostring( return etree.tostring(
self.root, pretty_print=True, self.root, pretty_print=True,

Loading…
Cancel
Save