Skip to content

Commit e945650

Browse files
committed
added shadow effect
svn path=/trunk/matplotlib/; revision=816
1 parent 63bb757 commit e945650

File tree

11 files changed

+131
-18
lines changed

11 files changed

+131
-18
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
New entries should be added at the top
22

3+
2004-12-27 Added Shadow class and added shadow kwarg to legend and pie
4+
for shadow effect - JDH
5+
36
2004-12-27 Added pie charts and new example/pie_demo.py
47

58
2004-12-23 Fixed an agg text rotation alignment bug, fixed some text

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ RELEASE = matplotlib-${VERSION}
1212

1313
clean:
1414
${PYTHON} setup.py clean;\
15-
rm -f *.png *.ps *.eps *.svg
15+
rm -f *.png *.ps *.eps *.svg *.jpg
1616
find . -name "_tmp*.py" | xargs rm -f;\
1717
find . \( -name "*~" -o -name "*.pyc" \) | xargs rm -f;\
1818
find examples \( -name "*.svg" -o -name "*.png" -o -name "*.ps" -o -name "*.jpg" -o -name "*.eps" -o -name "*.tar" -name "*.gz" \) | xargs rm -f

examples/legend_demo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
ax = subplot(111)
1818
plot(a,c,'k--',a,d,'k:',a,c+d,'k')
1919
legend(('Model length', 'Data length', 'Total message length'),
20-
'upper center')
20+
'upper center', shadow=True)
2121
ax.set_ylim([-1,20])
2222
ax.grid(0)
2323
xlabel('Model complexity --->')

examples/legend_demo2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
l2, l3 = plot(t2, sin(2*pi*t2), '--go', t1, log(1+t1), '.')
1414
l4, = plot(t2, exp(-t2)*sin(2*pi*t2), 'rs-.')
1515

16-
legend( (l2, l4), ('oscillatory', 'damped'), 'upper right')
16+
legend( (l2, l4), ('oscillatory', 'damped'), 'upper right', shadow=True)
1717
xlabel('time')
1818
ylabel('volts')
1919
title('Damped oscillation')

examples/pie_demo.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
Make a pie chart - see
3+
http://matplotlib.sf.net/matplotlib.pylab.html#-pie for the docstring.
4+
5+
This example shows a basic pie chart with labels in figure 1, and in
6+
figure 2 uses a couple of optional features, like autolabeling the
7+
percentage a wedge represents and offsetting a slice
8+
9+
10+
"""
11+
from pylab import *
12+
13+
# make a square figure and axes
14+
figure(1, figsize=(8,8))
15+
ax = axes([0.1, 0.1, 0.8, 0.8])
16+
17+
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
18+
fracs = [15,30,45, 10]
19+
20+
figure(1)
21+
pie(fracs, labels=labels)
22+
23+
# figure(2) showa some optional features. autopct is used to label
24+
# the percentage of the pie, and can be a format string or a function
25+
# which takes a percentage and returns a string. explode is a
26+
# len(fracs) sequuence which gives the fraction of the radius to
27+
# offset that slice.
28+
29+
figure(2, figsize=(8,8))
30+
explode=(0, 0.05, 0, 0)
31+
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
32+
33+
savefig('pie_demo')
34+
show()
35+

lib/matplotlib/artist.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ def get_transform(self):
5959
def is_figure_set(self):
6060
return self.figure is not None
6161

62+
def get_figure(self):
63+
'return the figure instance'
64+
return self.figure
65+
6266
def set_figure(self, fig):
6367
"""
6468
Set the figure instance the artist belong to

lib/matplotlib/axes.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
from mlab import meshgrid
3333
from matplotlib import rcParams
34-
from patches import Rectangle, Circle, Polygon, Wedge, bbox_artist
34+
from patches import Rectangle, Circle, Polygon, Wedge, Shadow, bbox_artist
3535
from table import Table
3636
from text import Text, _process_text_args
3737
from transforms import Bbox, Point, Value, Affine, NonseparableTransformation
@@ -322,7 +322,7 @@ def __init__(self, fig, rect,
322322
# funcs used to format x and y - fall back on major formatters
323323
self.fmt_xdata = None
324324
self.fmt_ydata = None
325-
325+
326326
def set_figure(self, fig):
327327
"""
328328
Set the Axes figure
@@ -1643,6 +1643,7 @@ def legend(self, *args, **kwargs):
16431643
handlelen = 0.05 # the length of the legend lines
16441644
handletextsep = 0.02 # the space between the legend line and legend text
16451645
axespad = 0.02 # the border between the axes and legend edge
1646+
shadow = False # if True, draw a shadow behind legend
16461647
"""
16471648

16481649
def get_handles():
@@ -1980,6 +1981,7 @@ def pcolor_classic(self, *args, **kwargs):
19801981
def pie(self, x, explode=None, labels=None,
19811982
colors=('b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'),
19821983
autopct=None,
1984+
shadow=False
19831985
):
19841986
"""
19851987
Make a pie chart of array x. The fractional area of each wedge is
@@ -1999,6 +2001,8 @@ def pie(self, x, explode=None, labels=None,
19992001
the wedge. If it is a format string, the label will be fmt%pct.
20002002
If it is a function, it will be called
20012003
2004+
- shadow, if True, will draw a shadow beneath the pie.
2005+
20022006
The pie chart will probably look best if the figure and axes are
20032007
square. Eg,
20042008
@@ -2044,10 +2048,20 @@ def pie(self, x, explode=None, labels=None,
20442048

20452049
w = Wedge((x,y), radius, 360.*theta1, 360.*theta2,
20462050
facecolor=colors[i%len(colors)])
2047-
slices.append(w)
2051+
slices.append(w)
20482052
self.add_patch(w)
20492053
self.set_label(label)
20502054

2055+
if shadow:
2056+
# make sure to add a shadow after the call to
2057+
# add_patch so the figure and transform props will be
2058+
# set
2059+
shad = Shadow(w, -0.02, -0.02,
2060+
#props={'facecolor':w.get_facecolor()}
2061+
)
2062+
shad.set_zorder(0.9*w.get_zorder())
2063+
self.add_patch(shad)
2064+
20512065

20522066
xt = x + 1.1*radius*math.cos(thetam)
20532067
yt = y + 1.1*radius*math.sin(thetam)

lib/matplotlib/backends/backend_ps.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,9 @@ def _draw_ps(self, ps, gc, rgbFace, command=None):
400400
self._pswriter.write('%s clipbox\n' % _nums_to_str(w,h,x,y))
401401
self._pswriter.write(ps.strip()+'\n')
402402
if rgbFace:
403+
#print 'rgbface', rgbFace
403404
self._pswriter.write("gsave\n")
404-
self.set_color(store=0,*rgbFace)
405+
self.set_color(store=0, *rgbFace)
405406
self._pswriter.write("fill\n")
406407
self._pswriter.write("grestore\n")
407408
self._pswriter.write("stroke\n")

lib/matplotlib/colors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,4 +583,5 @@ def is_mappable(self):
583583
return hasattr(self, '_A') and self._A is not None and self._A.shape<=2
584584

585585

586-
586+
587+

lib/matplotlib/legend.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from font_manager import FontProperties
3232
from lines import Line2D
3333
from mlab import linspace
34-
from patches import Patch, Rectangle, bbox_artist, draw_bbox
34+
from patches import Patch, Rectangle, Shadow, bbox_artist, draw_bbox
3535
from collections import LineCollection
3636
from text import Text
3737
from transforms import Bbox, Point, Value, get_bbox_transform, bbox_all,\
@@ -89,6 +89,7 @@ def __init__(self, parent, handles, labels, loc,
8989
handletextsep = 0.02, # the space between the legend line and legend text
9090
axespad = 0.02, # the border between the axes and legend edge
9191

92+
shadow=False,
9293
):
9394
"""
9495
parent # the artist that contains the legend
@@ -99,6 +100,7 @@ def __init__(self, parent, handles, labels, loc,
99100
numpoints = 4 # the number of points in the legend line
100101
fontprop = FontProperties('smaller') # the font property
101102
pad = 0.2 # the fractional whitespace inside the legend border
103+
shadow # if True, draw a shadow behind legend
102104
103105
The following dimensions are in axes coords
104106
labelsep = 0.005 # the vertical space between the legend entries
@@ -119,6 +121,7 @@ def __init__(self, parent, handles, labels, loc,
119121
self.handlelen = handlelen
120122
self.handletextsep = handletextsep
121123
self.axespad = axespad
124+
self.shadow = shadow
122125

123126
if isaxes: # parent is an Axes
124127
self.set_figure(parent.figure)
@@ -162,7 +165,13 @@ def _approx_text_height(self):
162165
def draw(self, renderer):
163166
renderer.open_group('legend')
164167
self._update_positions(renderer)
165-
if self._drawFrame: self.legendPatch.draw(renderer)
168+
if self._drawFrame:
169+
if self.shadow:
170+
shadow = Shadow(self.legendPatch, -0.005, -0.005)
171+
shadow.draw(renderer)
172+
self.legendPatch.draw(renderer)
173+
174+
166175
for h in self.handles:
167176
if h is not None:
168177
h.draw(renderer)

lib/matplotlib/patches.py

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,14 @@ def __init__(self,
4545
func(v)
4646

4747
def copy_properties(self, other):
48-
self._edgecolor = other._edgecolor
49-
self._facecolor = other._facecolor
50-
self.fill = other.fill
51-
self._linewidth= other._linewidth
52-
48+
self.set_edgecolor(other.get_edgecolor())
49+
self.set_facecolor(other.get_facecolor())
50+
self.set_fill(other.get_fill())
51+
self.set_linewidth(other.get_linewidth())
52+
self.set_transform(other.get_transform())
53+
self.set_figure(other.get_figure())
54+
self.set_alpha(other.get_alpha())
55+
5356
def get_antialiased(self):
5457
return self._antialiased
5558

@@ -102,7 +105,12 @@ def set_fill(self, b):
102105
"""
103106
self.fill = b
104107

105-
108+
def get_fill(self):
109+
'return whether fill is set'
110+
return self.fill
111+
112+
113+
106114
def draw(self, renderer):
107115

108116
#renderer.open_group('patch')
@@ -120,9 +128,9 @@ def draw(self, renderer):
120128

121129
verts = self.get_verts()
122130
tverts = self._transform.seq_xy_tups(verts)
123-
124131
renderer.draw_polygon(gc, rgbFace, tverts)
125132

133+
126134
#renderer.close_group('patch')
127135

128136
def get_verts(self):
@@ -171,7 +179,45 @@ def get_ec(self):
171179
def get_fc(self):
172180
'alias for get_facecolor'
173181
return self.get_facecolor()
174-
182+
183+
class Shadow(Patch):
184+
def __init__(self, patch, ox, oy, props=None):
185+
"""
186+
Create a shadow of the patch offset by ox, oy. props, if not None is
187+
a patch property update dictionary. If None, the shadow will have
188+
have the same color as the face, but darkened
189+
"""
190+
Patch.__init__(self)
191+
self.ox, self.oy = ox, oy
192+
self.patch = patch
193+
self.props = props
194+
self._update()
195+
196+
def _update(self):
197+
self.copy_properties(self.patch)
198+
if self.props is not None:
199+
self.update(self.props)
200+
else:
201+
r,g,b,a = colorConverter.to_rgba(self.patch.get_facecolor())
202+
rho = 0.3
203+
r = rho*r
204+
g = rho*g
205+
b = rho*b
206+
207+
self.set_facecolor((r,g,b))
208+
self.set_edgecolor((r,g,b))
209+
210+
def get_verts(self):
211+
verts = self.patch.get_verts()
212+
xs = [x+self.ox for x,y in verts]
213+
ys = [y+self.oy for x,y in verts]
214+
return zip(xs, ys)
215+
216+
def _draw(self, renderer):
217+
'draw the shadow'
218+
self._update()
219+
Patch.draw(self, renderer)
220+
175221
class Rectangle(Patch):
176222
"""
177223
Draw a rectangle with lower left at xy=(x,y) with specified

0 commit comments

Comments
 (0)