Added TODO and DEVELOPMENT.
[faces-project.git] / faces / charting / patches.py
blobfcb9413c8463f6bc8429398b2a5cc4b39be8ec2f
1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
3 # mreithinger@web.de
5 # This file is part of faces.
6 #
7 # faces is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # faces is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
23 import math
24 import tools
25 import matplotlib.patches as _patches
26 import matplotlib.transforms as _transforms
27 import matplotlib.artist as _artist
30 Arrow = _patches.Arrow
31 Polygon = _patches.Polygon
32 Shadow = _patches.Shadow
33 Wedge = _patches.Wedge
35 class Rectangle(_patches.Rectangle):
36 def __init__(self, xy, width, height, **kwargs):
37 _patches.Rectangle.__init__(self, (0,0), width, height, **kwargs)
38 self.xy = xy
41 class RegularPolygon(_patches.RegularPolygon):
42 def __init__(self, xy, numVertices, radius,
43 orientation=0, **kwargs):
45 _patches.Patch.__init__(self, **kwargs)
47 self.xy = xy
48 self.numVertices = numVertices
49 self.radius = radius
50 self.orientation = orientation
51 hstretch = tools.HSEP / tools.VSEP
53 theta = 2*math.pi/self.numVertices * _patches.arange(self.numVertices) + \
54 self.orientation
55 r = self.radius
56 xs = map(lambda t: self.xy[0] + r * math.cos(t) * hstretch, theta)
57 ys = map(lambda t: self.xy[1] + r * math.sin(t), theta)
59 self.verts = zip(xs, ys)
62 def get_verts(self):
63 return self.verts
66 class Circle(RegularPolygon):
67 """
68 A circle patch
69 """
70 def __init__(self, xy, radius, resolution=20, # the number of vertices
71 **kwargs):
72 self.center = xy
73 self.radius = radius
74 RegularPolygon.__init__(self, xy,
75 resolution,
76 radius,
77 orientation=0,
78 **kwargs)
80 try:
81 import PIL.Image as _Image
82 from matplotlib.image import pil_to_array as _pil_to_array
83 import matplotlib._image as _mimage
85 def pil_to_image(pilImage):
86 if pilImage.mode in ('RGBA', 'RGBX'):
87 im = pilImage # no need to convert images in rgba format
88 else: # try to convert to an rgba image
89 try:
90 im = pilImage.convert('RGBA')
91 except ValueError:
92 raise RuntimeError('Unknown image mode')
95 w, h = im.size
96 return _mimage.frombuffer(im.tostring('raw',im.mode,0,-1), w, h, 1)
99 class Icon(_artist.Artist):
100 def __init__(self, xy, image,
101 verticalalignment='bottom',
102 horizontalalignment='left'):
103 _artist.Artist.__init__(self)
105 if isinstance(image, basestring):
106 image =_Image.open(image)
108 self.dpi = image.info.get("dpi", (72, 72))
109 self.image = image
110 self.cache = pil_to_image(self.image)
111 self.cache.dpi = 0
112 self.xy = xy
115 def draw(self, renderer):
116 if not self.get_visible(): return
117 self.make_cache()
118 xy = self._transform.xy_tup(self.xy)
119 renderer.draw_image(xy[0], xy[1], self.cache, self.clipbox)
122 def get_window_extent(self, renderer=None):
123 w, h = self.image.size
124 xy = self._transform.xy_tup(self.xy)
125 dpi = self.figure.get_dpi()
126 return _transforms.lbwh_to_bbox(xy[0], xy[1],
127 w * dpi / self.dpi[0],
128 h * dpi / self.dpi[1])
131 def make_cache(self):
132 dpi = self.figure.get_dpi()
133 if self.cache.dpi != dpi:
134 w, h = self.image.size
135 tmp = self.image.resize((int(w * dpi / self.dpi[0]),
136 int(h * dpi / self.dpi[1])))
137 self.cache = pil_to_image(tmp)
138 self.cache.is_grayscale = False
139 self.cache.dpi = dpi
142 except ImportError:
143 pass