SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

You can subscribe to this list here.

2007 Jan
Feb
Mar
Apr
May
Jun
Jul
(115)
Aug
(120)
Sep
(137)
Oct
(170)
Nov
(461)
Dec
(263)
2008 Jan
(120)
Feb
(74)
Mar
(35)
Apr
(74)
May
(245)
Jun
(356)
Jul
(240)
Aug
(115)
Sep
(78)
Oct
(225)
Nov
(98)
Dec
(271)
2009 Jan
(132)
Feb
(84)
Mar
(74)
Apr
(56)
May
(90)
Jun
(79)
Jul
(83)
Aug
(296)
Sep
(214)
Oct
(76)
Nov
(82)
Dec
(66)
2010 Jan
(46)
Feb
(58)
Mar
(51)
Apr
(77)
May
(58)
Jun
(126)
Jul
(128)
Aug
(64)
Sep
(50)
Oct
(44)
Nov
(48)
Dec
(54)
2011 Jan
(68)
Feb
(52)
Mar
Apr
May
Jun
Jul
Aug
Sep
Oct
Nov
Dec
(1)
2018 Jan
Feb
Mar
Apr
May
(1)
Jun
Jul
Aug
Sep
Oct
Nov
Dec
S M T W T F S






1
2
(1)
3
(4)
4
(9)
5
(14)
6
(8)
7
(14)
8
(1)
9
(2)
10
(9)
11
(5)
12
(11)
13
(4)
14
(4)
15
(1)
16
17
(1)
18
(2)
19
(4)
20
(10)
21
(3)
22
(3)
23
(2)
24
(8)
25
(6)
26
(5)
27
28
(3)
29
30
(3)






Showing results of 137

<< < 1 2 3 4 .. 6 > >> (Page 2 of 6)
From: <js...@us...> - 2007年09月23日 13:50:04
Revision: 3878
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3878&view=rev
Author: jswhit
Date: 2007年09月23日 06:50:01 -0700 (2007年9月23日)
Log Message:
-----------
update
Modified Paths:
--------------
 trunk/toolkits/basemap/Changelog
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog	2007年09月23日 12:34:34 UTC (rev 3877)
+++ trunk/toolkits/basemap/Changelog	2007年09月23日 13:50:01 UTC (rev 3878)
@@ -1,4 +1,4 @@
-version 0.9.6 (svn revision 3875)
+version 0.9.6 (svn revision 3878)
 * labelling of meridians and parallels now works with
 very small map regions (less than 0.2 degrees square).
 * Subregions of the globe may be specified with llcrnrlat,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年09月23日 12:34:36
Revision: 3877
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3877&view=rev
Author: jswhit
Date: 2007年09月23日 05:34:34 -0700 (2007年9月23日)
Log Message:
-----------
changed opendap server (old one no longer works)
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/pnganim.py
Modified: trunk/toolkits/basemap/examples/pnganim.py
===================================================================
--- trunk/toolkits/basemap/examples/pnganim.py	2007年09月22日 17:27:53 UTC (rev 3876)
+++ trunk/toolkits/basemap/examples/pnganim.py	2007年09月23日 12:34:34 UTC (rev 3877)
@@ -47,10 +47,10 @@
 raise ValueError,'dates must be in same year'
 
 # set OpenDAP server URL.
-URLbase="http://www.cdc.noaa.gov/cgi-bin/nph-nc/Datasets/ncep.reanalysis/surface/"
-URL=URLbase+'slp.'+YYYY+'.nc'
-URLu=URLbase+'uwnd.sig995.'+YYYY+'.nc'
-URLv=URLbase+'vwnd.sig995.'+YYYY+'.nc'
+URLbase="http://nomad3.ncep.noaa.gov:9090/dods/reanalyses/reanalysis-2/6hr/pgb/"
+URL=URLbase+'pres'
+URLu=URLbase+'wind'
+URLv=URLbase+'wind'
 print URL
 print URLu
 print URLv
@@ -71,7 +71,8 @@
 # put times in YYYYMMDDHH format.
 dates=[]
 for t in times:
- fdate = hrs_since_day1CE_todate(int(t)) 
+ t = t*24
+ fdate = hrs_since_day1CE_todate(int(t))
 dates.append(fdate.strftime('%Y%m%d%H'))
 if YYYYMMDDHH1 not in dates or YYYYMMDDHH2 not in dates:
 raise ValueError, 'date1 or date2 not a valid date (must be in form YYYYMMDDHH, where HH is 00,06,12 or 18)'
@@ -82,13 +83,13 @@
 if ntime1 >= ntime2:
 raise ValueError,'date2 must be greater than date1'
 # get sea level pressure and 10-m wind data.
-slpdata = data['slp']
-udata = datau['uwnd']
-vdata = datav['vwnd']
+slpdata = data['presmsl']
+udata = datau['ugrdprs']
+vdata = datau['vgrdprs']
 # mult slp by 0.01 to put in units of millibars.
-slpin = 0.01*(slpdata.scale_factor*p.squeeze(slpdata[ntime1:ntime2+1,:,:]) + slpdata.add_offset)
-uin = udata.scale_factor*p.squeeze(udata[ntime1:ntime2+1,:,:]) + udata.add_offset
-vin = vdata.scale_factor*p.squeeze(vdata[ntime1:ntime2+1,:,:]) + vdata.add_offset
+slpin = 0.01*p.squeeze(slpdata[ntime1:ntime2+1,:,:])
+uin = p.squeeze(udata[ntime1:ntime2+1,0,:,:]) 
+vin = p.squeeze(vdata[ntime1:ntime2+1,0,:,:]) 
 datelabels = dates[ntime1:ntime2+1]
 # add cyclic points
 slp = p.zeros((slpin.shape[0],slpin.shape[1],slpin.shape[2]+1),p.Float64)
@@ -109,6 +110,12 @@
 # make orthographic basemap.
 m = Basemap(resolution='c',projection='ortho',lat_0=60.,lon_0=-60.)
 p.ion() # interactive mode on.
+uin = p.squeeze(udata[ntime1:ntime2+1,0,:,:]) 
+vin = p.squeeze(vdata[ntime1:ntime2+1,0,:,:]) 
+datelabels = dates[ntime1:ntime2+1]
+# make orthographic basemap.
+m = Basemap(resolution='c',projection='ortho',lat_0=60.,lon_0=-60.)
+p.ion() # interactive mode on.
 # create figure, add axes (leaving room for colorbar on right)
 fig = p.figure()
 ax = fig.add_axes([0.1,0.1,0.7,0.7])
@@ -135,12 +142,10 @@
 # plot wind vectors on projection grid (looks better).
 # first, shift grid so it goes from -180 to 180 (instead of 0 to 360
 # in longitude). Otherwise, interpolation is messed up.
- # also reverse latitudes (since interpolation expects monotonically
- # increasing x and y).
- ugrid,newlons = shiftgrid(180.,u[nt,::-1,:],longitudes,start=False)
- vgrid,newlons = shiftgrid(180.,v[nt,::-1,:],longitudes,start=False)
+ ugrid,newlons = shiftgrid(180.,u[nt,:,:],longitudes,start=False)
+ vgrid,newlons = shiftgrid(180.,v[nt,:,:],longitudes,start=False)
 # transform vectors to projection grid.
- urot,vrot,xx,yy = m.transform_vector(ugrid,vgrid,newlons,latitudes[::-1],51,51,returnxy=True,masked=True)
+ urot,vrot,xx,yy = m.transform_vector(ugrid,vgrid,newlons,latitudes,51,51,returnxy=True,masked=True)
 # plot wind vectors over map.
 Q = m.quiver(xx,yy,urot,vrot,scale=500)
 # make quiver key.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年09月22日 17:27:55
Revision: 3876
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3876&view=rev
Author: jswhit
Date: 2007年09月22日 10:27:53 -0700 (2007年9月22日)
Log Message:
-----------
updated URL
Modified Paths:
--------------
 trunk/toolkits/basemap/examples/fcstmaps.py
Modified: trunk/toolkits/basemap/examples/fcstmaps.py
===================================================================
--- trunk/toolkits/basemap/examples/fcstmaps.py	2007年09月22日 15:10:00 UTC (rev 3875)
+++ trunk/toolkits/basemap/examples/fcstmaps.py	2007年09月22日 17:27:53 UTC (rev 3876)
@@ -50,7 +50,7 @@
 # set OpenDAP server URL.
 HH='09'
 URLbase="http://nomad3.ncep.noaa.gov:9090/dods/sref/sref"
-URL=URLbase+YYYYMMDD+"/sref_eta1_"+HH+"z.ctl"
+URL=URLbase+YYYYMMDD+"/sref_eta_ctl1_"+HH+"z"
 print URL+'\n'
 try:
 data = client.open(URL)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <js...@us...> - 2007年09月22日 15:10:04
Revision: 3875
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3875&view=rev
Author: jswhit
Date: 2007年09月22日 08:10:00 -0700 (2007年9月22日)
Log Message:
-----------
version 0.9.6 is finished
Modified Paths:
--------------
 trunk/toolkits/basemap/Changelog
Modified: trunk/toolkits/basemap/Changelog
===================================================================
--- trunk/toolkits/basemap/Changelog	2007年09月22日 06:48:49 UTC (rev 3874)
+++ trunk/toolkits/basemap/Changelog	2007年09月22日 15:10:00 UTC (rev 3875)
@@ -1,4 +1,4 @@
-version 0.9.6 (not yet released)
+version 0.9.6 (svn revision 3875)
 * labelling of meridians and parallels now works with
 very small map regions (less than 0.2 degrees square).
 * Subregions of the globe may be specified with llcrnrlat,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jo...@us...> - 2007年09月22日 06:48:51
Revision: 3874
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3874&view=rev
Author: jouni
Date: 2007年09月21日 23:48:49 -0700 (2007年9月21日)
Log Message:
-----------
Replace some generator expressions by list comprehensions for
Python 2.3 compatibility
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
 trunk/matplotlib/lib/matplotlib/dviread.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年09月21日 16:54:32 UTC (rev 3873)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py	2007年09月22日 06:48:49 UTC (rev 3874)
@@ -541,10 +541,10 @@
 widths[ch] = afmdata.get_width_char(ch, isord=True)
 except KeyError:
 pass
- not_None = (ch for ch in range(256) 
- if widths[ch] is not None)
- firstchar = not_None.next()
- lastchar = max(not_None)
+ not_None = [ch for ch in range(256) 
+ if widths[ch] is not None]
+ firstchar = not_None[0]
+ lastchar = not_None[-1]
 widths = widths[firstchar:lastchar+1]
 for i,w in enumerate(widths):
 if w is None: widths[i] = 0
Modified: trunk/matplotlib/lib/matplotlib/dviread.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/dviread.py	2007年09月21日 16:54:32 UTC (rev 3873)
+++ trunk/matplotlib/lib/matplotlib/dviread.py	2007年09月22日 06:48:49 UTC (rev 3874)
@@ -350,9 +350,9 @@
 def _xxx(self, special):
 matplotlib.verbose.report(
 'Dvi._xxx: encountered special: %s'
- % ''.join((32 <= ord(ch) < 127) and ch 
- or '<%02x>' % ord(ch)
- for ch in special),
+ % ''.join([(32 <= ord(ch) < 127) and ch 
+ or '<%02x>' % ord(ch)
+ for ch in special]),
 'debug')
 
 def _fnt_def(self, k, c, s, d, a, l, n):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月21日 16:54:35
Revision: 3873
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3873&view=rev
Author: mdboom
Date: 2007年09月21日 09:54:32 -0700 (2007年9月21日)
Log Message:
-----------
Merged revisions 3870-3872 via svnmerge from 
http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib
........
 r3871 | dsdale | 2007年09月21日 11:33:18 -0400 (2007年9月21日) | 2 lines
 
 changed cbooks reversed to agree with the python builtin
........
Modified Paths:
--------------
 branches/transforms/API_CHANGES
 branches/transforms/CHANGELOG
 branches/transforms/lib/matplotlib/cbook.py
Property Changed:
----------------
 branches/transforms/
Property changes on: branches/transforms
___________________________________________________________________
Name: svnmerge-integrated
 - /trunk/matplotlib:1-3869
 + /trunk/matplotlib:1-3872
Modified: branches/transforms/API_CHANGES
===================================================================
--- branches/transforms/API_CHANGES	2007年09月21日 16:52:50 UTC (rev 3872)
+++ branches/transforms/API_CHANGES	2007年09月21日 16:54:32 UTC (rev 3873)
@@ -1,3 +1,8 @@
+ Changed cbook.reversed so it yields a tuple rather than a 
+ (index, tuple). This agrees with the python reversed builtin,
+ and cbook only defines reversed if python doesnt provide the 
+ builtin.
+
 Made skiprows=1 the default on csv2rec
 
 The gd and paint backends have been deleted.
Modified: branches/transforms/CHANGELOG
===================================================================
--- branches/transforms/CHANGELOG	2007年09月21日 16:52:50 UTC (rev 3872)
+++ branches/transforms/CHANGELOG	2007年09月21日 16:54:32 UTC (rev 3873)
@@ -1,3 +1,6 @@
+2007年09月21日 Changed cbook.reversed to yield the same result as the 
+ python reversed builtin - DSD
+
 2007年09月13日 The usetex support in the pdf backend is more usable now,
 so I am enabling it. - JKS
 
Modified: branches/transforms/lib/matplotlib/cbook.py
===================================================================
--- branches/transforms/lib/matplotlib/cbook.py	2007年09月21日 16:52:50 UTC (rev 3872)
+++ branches/transforms/lib/matplotlib/cbook.py	2007年09月21日 16:54:32 UTC (rev 3873)
@@ -482,7 +482,7 @@
 enumerate() is new in Python 2.3
 """
 for i in range(len(seq)-1,-1,-1):
- yield i, seq[i]
+ yield seq[i]
 
 
 # use itertools.izip if available, else use python version
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月21日 16:52:54
Revision: 3872
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3872&view=rev
Author: mdboom
Date: 2007年09月21日 09:52:50 -0700 (2007年9月21日)
Log Message:
-----------
Further progress on arbitrary transformations -- zooming and panning
now works without any log-scale-specific hacks. (Though the
underlying model is slightly wrong.)
Added graphviz output support for debugging transformation trees.
Masked array handling much more robust.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年09月21日 15:33:18 UTC (rev 3871)
+++ branches/transforms/lib/matplotlib/axes.py	2007年09月21日 16:52:50 UTC (rev 3872)
@@ -637,10 +637,14 @@
 # self.viewLim, self.bbox)
 self.preDataTransform = mtransforms.BboxTransform(
 self.viewLim, mtransforms.Bbox.unit())
- self.dataTransform = mtransforms.TestLogTransform()
- # self.dataTransform = mtransforms.Affine2D().scale(1.5)
+# self.dataTransform = mtransforms.TestPolarTransform()
+# self.dataTransform = mtransforms.blended_transform_factory(
+# mtransforms.TestLogTransform(),
+# mtransforms.Affine2D())
+ self.dataTransform = mtransforms.Affine2D()
 self.transData = self.preDataTransform + self.dataTransform + mtransforms.BboxTransform(
 mtransforms.Bbox.unit(), self.bbox)
+ self.transData.make_graphviz(open("trans.dot", "w"))
 
 	 
 def get_position(self, original=False):
@@ -1523,7 +1527,7 @@
 'return the xaxis scale string: log or linear'
 	# MGDTODO
 # return self.scaled[self.transData.get_funcx().get_type()]
-	return 'linear'
+	return 'log'
 
 def set_xscale(self, value, basex = 10, subsx=None):
 """
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月21日 15:33:18 UTC (rev 3871)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月21日 16:52:50 UTC (rev 3872)
@@ -1655,60 +1655,30 @@
 #multiple button can get pressed during motion...
 if self._button_pressed==1:
 		inverse = trans.inverted()
- lastx, lasty = inverse.transform_point((lastx, lasty))
- x, y = inverse.transform_point( (event.x, event.y) )
- if a.get_xscale()=='log':
- dx=1-lastx/x
- else:
- dx=x-lastx
- if a.get_yscale()=='log':
- dy=1-lasty/y
- else:
- dy=y-lasty
-
- dx,dy=format_deltas(event,dx,dy)
-
- if a.get_xscale()=='log':
- xmin *= 1-dx
- xmax *= 1-dx
- else:
- xmin -= dx
- xmax -= dx
- if a.get_yscale()=='log':
- ymin *= 1-dy
- ymax *= 1-dy
- else:
- ymin -= dy
- ymax -= dy
+ dx, dy = event.x - lastx, event.y - lasty
+ dx, dy = format_deltas(event, dx, dy)
+ delta = npy.array([[dx, dy], [dx, dy]], npy.float_)
+ bbox = transforms.Bbox(a.bbox.get_points() - delta)
+ result = bbox.transformed(inverse)
 elif self._button_pressed==3:
 try:
+ inverse = trans.inverted()
 dx=(lastx-event.x)/float(a.bbox.width)
 dy=(lasty-event.y)/float(a.bbox.height)
- dx,dy=format_deltas(event,dx,dy)
- if a.get_aspect() != 'auto':
- dx = 0.5*(dx + dy)
- dy = dx
- alphax = pow(10.0,dx)
- alphay = pow(10.0,dy)#use logscaling, avoid singularities and smother scaling...
-		 inverse = trans.inverted()
- lastx, lasty = inverse.transform_point( (lastx, lasty) )
- if a.get_xscale()=='log':
- xmin = lastx*(xmin/lastx)**alphax
- xmax = lastx*(xmax/lastx)**alphax
- else:
- xmin = lastx+alphax*(xmin-lastx)
- xmax = lastx+alphax*(xmax-lastx)
- if a.get_yscale()=='log':
- ymin = lasty*(ymin/lasty)**alphay
- ymax = lasty*(ymax/lasty)**alphay
- else:
- ymin = lasty+alphay*(ymin-lasty)
- ymax = lasty+alphay*(ymax-lasty)
+ alphax = pow(10.0, dx)
+ alphay = pow(10.0, dy)
+ # MGDTODO: Make better use of numpy
+ lastx, lasty = inverse.transform_point((lastx, lasty))
+ xmin = (lastx + alphax * (xmin - lastx))
+ xmax = (lastx + alphax * (xmax - lastx))
+ ymin = (lasty + alphay * (ymin - lasty))
+ ymax = (lasty + alphay * (ymax - lasty))
+ result = transforms.Bbox.from_lbrt(xmin, ymin, xmax, ymax)
 except OverflowError:
 warnings.warn('Overflow while panning')
 return
- a.set_xlim(xmin, xmax)
- a.set_ylim(ymin, ymax)
+ a.set_xlim(*result.intervalx)
+ a.set_ylim(*result.intervaly)
 
 self.dynamic_update()
 
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月21日 15:33:18 UTC (rev 3871)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月21日 16:52:50 UTC (rev 3872)
@@ -25,6 +25,53 @@
 (TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN,
 CARETLEFT, CARETRIGHT, CARETUP, CARETDOWN) = range(8)
 
+def unmasked_index_ranges(mask, compressed = True):
+ '''
+ Calculate the good data ranges in a masked 1-D npy.array, based on mask.
+
+ Returns Nx2 npy.array with each row the start and stop indices
+ for slices of the compressed npy.array corresponding to each of N
+ uninterrupted runs of unmasked values.
+ If optional argument compressed is False, it returns the
+ start and stop indices into the original npy.array, not the
+ compressed npy.array.
+ Returns None if there are no unmasked values.
+
+ Example:
+
+ y = ma.array(npy.arange(5), mask = [0,0,1,0,0])
+ #ii = unmasked_index_ranges(y.mask())
+ ii = unmasked_index_ranges(ma.getmask(y))
+ # returns [[0,2,] [2,4,]]
+
+ y.compressed().filled()[ii[1,0]:ii[1,1]]
+ # returns npy.array [3,4,]
+ # (The 'filled()' method converts the masked npy.array to a numerix npy.array.)
+
+ #i0, i1 = unmasked_index_ranges(y.mask(), compressed=False)
+ i0, i1 = unmasked_index_ranges(ma.getmask(y), compressed=False)
+ # returns [[0,3,] [2,5,]]
+
+ y.filled()[ii[1,0]:ii[1,1]]
+ # returns npy.array [3,4,]
+
+ '''
+ m = npy.concatenate(((1,), mask, (1,)))
+ indices = npy.arange(len(mask) + 1)
+ mdif = m[1:] - m[:-1]
+ i0 = npy.compress(mdif == -1, indices)
+ i1 = npy.compress(mdif == 1, indices)
+ assert len(i0) == len(i1)
+ if len(i1) == 0:
+ return None
+ if not compressed:
+ return npy.concatenate((i0[:, npy.newaxis], i1[:, npy.newaxis]), axis=1)
+ seglengths = i1 - i0
+ breakpoints = npy.cumsum(seglengths)
+ ic0 = npy.concatenate(((0,), breakpoints[:-1]))
+ ic1 = breakpoints
+ return npy.concatenate((ic0[:, npy.newaxis], ic1[:, npy.newaxis]), axis=1)
+
 def segment_hits(cx,cy,x,y,radius):
 """Determine if any line segments are within radius of a point. Returns
 the list of line segments that are within that radius.
@@ -302,7 +349,7 @@
 self._picker = p
 
 def get_window_extent(self, renderer):
- xy = self.get_transform()(self._xy)
+ xy = self.get_transform().transform(self._xy)
 
 	x = xy[:, 0]
 	y = xy[:, 1]
@@ -343,9 +390,6 @@
 self._yorig = y
 self.recache()
 
- # MGDTODO: Masked data arrays are broken
- _masked_array_to_path_code_mapping = npy.array(
- [Path.LINETO, Path.MOVETO, Path.MOVETO], Path.code_type)
 def recache(self):
 #if self.axes is None: print 'recache no axes'
 #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
@@ -363,24 +407,15 @@
 if len(x) != len(y):
 raise RuntimeError('xdata and ydata must be the same length')
 
-	self._xy = npy.vstack((npy.asarray(x, npy.float_),
-			 npy.asarray(y, npy.float_))).transpose()
+ x = x.reshape((len(x), 1))
+ y = y.reshape((len(y), 1))
+ 
+	self._xy = ma.concatenate((x, y), 1)
 	self._x = self._xy[:, 0] # just a view
 	self._y = self._xy[:, 1] # just a view
 self._logcache = None
-
- mx = ma.getmask(x)
- my = ma.getmask(y)
- mask = ma.mask_or(mx, my)
- codes = None
- if mask is not ma.nomask:
- m = npy.concatenate(((1,), mask, (1,)))
- mdif = m[1:] - m[:-1]
- mdif = npy.maximum((mdif[:-1] * -2), mask)
- codes = npy.take(
- self._masked_array_to_path_code_mapping,
- mdif)
- self._path = Path(self._xy, codes, closed=False)
+ # Masked arrays are now handled by the Path class itself
+ self._path = Path(self._xy, closed=False)
 # MGDTODO: If _draw_steps is removed, remove the following line also
 self._step_path = None
 
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月21日 15:33:18 UTC (rev 3871)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月21日 16:52:50 UTC (rev 3872)
@@ -1,4 +1,5 @@
 import numpy as npy
+from numpy import ma as ma
 
 class Path(object):
 # Path codes
@@ -21,10 +22,8 @@
 code_type = npy.uint8
 
 def __init__(self, vertices, codes=None, closed=True):
- vertices = npy.asarray(vertices, npy.float_)
-	assert vertices.ndim == 2
-	assert vertices.shape[1] == 2
- 
+ vertices = ma.asarray(vertices, npy.float_)
+
 	if codes is None:
 	 if closed:
 		codes = self.LINETO * npy.ones(
@@ -41,10 +40,27 @@
 assert codes.ndim == 1
 assert len(codes) == len(vertices)
 
+ # The path being passed in may have masked values. However,
+ # the backends are not expected to deal with masked arrays, so
+ # we must remove them from the array (using compressed), and
+ # add MOVETO commands to the codes array accordingly.
+ mask = ma.getmask(vertices)
+ if mask is not ma.nomask:
+ mask1d = ma.mask_or(mask[:, 0], mask[:, 1])
+ vertices = ma.compress(npy.invert(mask1d), vertices, 0)
+ codes = npy.where(npy.concatenate((mask1d[-1:], mask1d[:-1])),
+ self.MOVETO, codes)
+ codes = ma.masked_array(codes, mask=mask1d).compressed()
+ codes = npy.asarray(codes, self.code_type)
+
+ vertices = npy.asarray(vertices, npy.float_)
+
+ assert vertices.ndim == 2
+ assert vertices.shape[1] == 2
+	assert codes.ndim == 1
+ 
 self._codes = codes
 	self._vertices = vertices
- 
-	assert self._codes.ndim == 1
 
 def __repr__(self):
 	return "Path(%s, %s)" % (self.vertices, self.codes)
@@ -91,10 +107,11 @@
 def unit_regular_polygon(cls, numVertices):
 	path = cls._unit_regular_polygons.get(numVertices)
 	if path is None:
-	 theta = 2*npy.pi/numVertices * npy.arange(numVertices)
-	 # This is to make sure the polygon always "points-up"
+	 theta = 2*npy.pi/numVertices * npy.arange(numVertices).reshape((numVertices, 1))
+	 # This initial rotation is to make sure the polygon always
+ # "points-up"
 	 theta += npy.pi / 2.0
-	 verts = npy.vstack((npy.cos(theta), npy.sin(theta))).transpose()
+	 verts = npy.concatenate((npy.cos(theta), npy.sin(theta)))
 	 path = Path(verts)
 	 cls._unit_regular_polygons[numVertices] = path
 	return path
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月21日 15:33:18 UTC (rev 3871)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月21日 16:52:50 UTC (rev 3872)
@@ -5,6 +5,7 @@
 """
 
 import numpy as npy
+from numpy import ma as ma
 from numpy.linalg import inv
 from sets import Set
 
@@ -19,6 +20,7 @@
 class TransformNode(object):
 def __init__(self):
 self._parents = Set()
+ self._children = []
 
 def invalidate(self):
 self._do_invalidation()
@@ -33,7 +35,34 @@
 getattr(self, child)._parents.add(self)
 self._children = children
 
+ def make_graphviz(self, fobj):
+ def recurse(root):
+ fobj.write('%s [label="%s"];\n' %
+ (hash(root), root.__class__.__name__))
+ if isinstance(root, Affine2DBase):
+ fobj.write('%s [style=filled, color=".7 .7 .9"];\n' %
+ hash(root))
+ elif isinstance(root, BboxBase):
+ fobj.write('%s [style=filled, color=".9 .9 .7"];\n' %
+ hash(root))
+ for child_name in root._children:
+ child = getattr(root, child_name)
+ fobj.write("%s -> %s;\n" % (
+ hash(root),
+ hash(child)))
+ recurse(child)
 
+ fobj.write("digraph G {\n")
+ recurse(self)
+ fobj.write("}\n")
+ 
+ def is_affine(self):
+ return isinstance(self, Affine2DBase)
+
+ def is_bbox(self):
+ return isinstance(self, BboxBase)
+ 
+ 
 class BboxBase(TransformNode):
 '''
 This is the read-only part of a bounding-box
@@ -169,12 +198,6 @@
 return Bbox(points)
 from_lbrt = staticmethod(from_lbrt)
 
- def __copy__(self):
- return Bbox(self._points.copy())
-
- def __deepcopy__(self, memo):
- return Bbox(self._points.copy())
- 
 def __cmp__(self, other):
 # MGDTODO: Totally suboptimal
 if isinstance(other, Bbox) and (self._points == other._points).all():
@@ -274,6 +297,8 @@
 """
 Return the Bbox that bounds all bboxes
 """
+ # MGDTODO: There's got to be a way to utilize numpy here
+ # to make this faster...
 assert(len(bboxes))
 
 if len(bboxes) == 1:
@@ -297,7 +322,7 @@
 
 class TransformedBbox(BboxBase):
 def __init__(self, bbox, transform):
- assert isinstance(bbox, Bbox)
+ assert bbox.is_bbox()
 assert isinstance(transform, Transform)
 
 BboxBase.__init__(self)
@@ -353,9 +378,6 @@
 def is_separable(self):
 return False
 
- def is_affine(self):
- return False
-
 
 class Affine2DBase(Transform):
 input_dims = 2
@@ -416,9 +438,9 @@
 # print "".join(traceback.format_stack())
 # print points
 mtx = self.get_matrix()
- points = npy.asarray(points, npy.float_)
+ points = ma.asarray(points, npy.float_)
 points = points.transpose()
- points = npy.dot(mtx[0:2, 0:2], points)
+ points = ma.dot(mtx[0:2, 0:2], points)
 points = points + mtx[0:2, 2:]
 return points.transpose()
 
@@ -437,9 +459,6 @@
 mtx = self.get_matrix()
 return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0
 
- def is_affine(self):
- return True
-
 
 class Affine2D(Affine2DBase):
 def __init__(self, matrix = None):
@@ -469,12 +488,6 @@
 return 0
 return -1
 
- def __copy__(self):
- return Affine2D(self._mtx.copy())
- 
- def __deepcopy__(self, memo):
- return Affine2D(self._mtx.copy())
- 
 #@staticmethod
 def from_values(a, b, c, d, e, f):
 return Affine2D(Affine2D.matrix_from_values(a, b, c, d, e, f))
@@ -542,9 +555,31 @@
 mtx = self.get_matrix()
 return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0
 
- def is_affine(self):
- return True
 
+class IdentityTransform(Affine2DBase):
+ """
+ A special class that does the identity transform quickly.
+ """
+ _mtx = npy.identity(3)
+
+ def __cmp__(self, other):
+ if (isinstance(other, Affine2D) and
+ (other == IDENTITY)):
+ return 0
+ return -1
+
+ def get_matrix(self):
+ return _mtx
+ 
+ def transform(self, points):
+ return points
+
+ def transform_without_affine(self, points):
+ return points, self
+
+ def inverted(self):
+ return self
+ 
 IDENTITY = Affine2D()
 
 class BlendedGenericTransform(Transform):
@@ -553,10 +588,9 @@
 
 def __init__(self, x_transform, y_transform):
 	# Here we ask: "Does it blend?"
- assert x_transform.is_separable()
- assert y_transform.is_separable()
- assert x_transform.input_dims == x_transform.output_dims == 2
- assert y_transform.input_dims == y_transform.output_dims == 2
+ # MGDTODO: Turn these checks back on
+ # assert x_transform.is_separable()
+ # assert y_transform.is_separable()
 
 Transform.__init__(self)
 self._x = x_transform
@@ -576,16 +610,18 @@
 return self._x(points)
 
 if x.input_dims == 2:
- x_points = x.transform(points)[:, 0]
+ x_points = x.transform(points)[:, 0:1]
 else:
 x_points = x.transform(points[:, 0])
-
+ x_points = x_points.reshape((len(x_points), 1))
+ 
 if y.input_dims == 2:
- y_points = y.transform(points)[:, 1]
+ y_points = y.transform(points)[:, 1:]
 else:
 y_points = y.transform(points[:, 1])
+ y_points = y_points.reshape((len(y_points), 1))
 
- return npy.vstack((x_points, y_points)).transpose()
+ return ma.concatenate((x_points, y_points), 1)
 
 def inverted(self):
 return BlendedGenericTransform(self._x.inverted(), self._y.inverted())
@@ -598,6 +634,9 @@
 def __init__(self, x_transform, y_transform):
 assert x_transform.is_affine()
 assert y_transform.is_affine()
+ # MGDTODO: Turn these checks back on
+ # assert x_transform.is_separable()
+ # assert y_transform.is_separable()
 Transform.__init__(self)
 self._x = x_transform
 self._y = y_transform
@@ -649,6 +688,8 @@
 self._b = b
 self.set_children(['_a', '_b'])
 
+ self.take_shortcut = b.is_affine()
+
 def __repr__(self):
 return "CompositeGenericTransform(%s, %s)" % (self._a, self._b)
 __str__ = __repr__
@@ -656,11 +697,15 @@
 def transform(self, points):
 return self._b.transform(self._a.transform(points))
 
+ def transform_without_affine(self, points):
+ if self.take_shortcut:
+ return self._a.transform(points), self._b
+ return self.transform(points), IDENTITY
+ 
 def inverted(self):
 return CompositeGenericTransform(self._b.inverted(), self._a.inverted())
 
 def is_separable(self):
- return True
 return self._a.is_separable() and self._b.is_separable()
 
 
@@ -702,35 +747,81 @@
 output_dims = 1
 
 def transform(self, a):
- m = npy.ma.masked_where(a < 0, a)
+ m = ma.masked_where(a < 0, a)
 return npy.log10(m)
 
 
 class TestLogTransform(Transform):
- input_dims = 2
- output_dims = 2
+ input_dims = 1
+ output_dims = 1
 def transform(self, xy):
- marray = npy.ma.masked_where(xy <= 0.0, xy * 10.0)
- return npy.log10(marray)
+ marray = ma.masked_where(xy <= 0.0, xy * 10.0)
+ return (npy.log10(marray) * 0.5) + 0.5
 
 def inverted(self):
 return TestInvertLogTransform()
 
+ def is_separable(self):
+ return True
+ 
 
 class TestInvertLogTransform(Transform):
- input_dims = 2
- output_dims = 2
+ input_dims = 1
+ output_dims = 1
 def transform(self, xy):
- return npy.power(10, xy) / 10.0
+ return ma.power(10, (xy - 0.5) * 2.0) / 10.0
 
 def inverted(self):
 return TestLogTransform()
 
+ def is_separable(self):
+ return True
+
+
+class TestPolarTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+
+ def transform(self, xy):
+ debug = len(xy) > 4
+ x = xy[:, 0:1]
+ y = xy[:, 1:]
+ x, y = ((y * npy.cos(x)) + 1.0) * 0.5, ((y * npy.sin(x)) + 1.0) * 0.5
+ if debug:
+ print npy.min(xy[:, 0:1]), npy.max(xy[:, 0:1]), npy.min(xy[:, 1:]), npy.max(xy[:, 1:])
+ print x.min(), x.max(), y.min(), y.max()
+ return ma.concatenate((x, y), 1)
+
+ def inverted(self):
+ return TestInvertPolarTransform()
 
+ def is_separable(self):
+ return False
+
+
+class TestInvertPolarTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+
+ def transform(self, xy):
+ x = xy[:, 0:1]
+ y = xy[:, 1:]
+ r = ma.sqrt(ma.power(x, 2) + ma.power(y, 2))
+ theta = ma.arccos(x / r)
+ theta = ma.where(y < 0, 2 * npy.pi - theta, theta)
+ return ma.concatenate((theta / (npy.pi * 2), r), 1)
+
+ def inverted(self):
+ return TestInvertPolarTransform()
+ 
+ def is_separable(self):
+ return False
+ 
+ 
 class BboxTransform(Affine2DBase):
 def __init__(self, boxin, boxout):
- assert isinstance(boxin, BboxBase)
- assert isinstance(boxout, BboxBase)
+ assert boxin.is_bbox()
+ assert boxout.is_bbox()
 
 Affine2DBase.__init__(self)
 self._boxin = boxin
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <ds...@us...> - 2007年09月21日 15:33:21
Revision: 3871
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3871&view=rev
Author: dsdale
Date: 2007年09月21日 08:33:18 -0700 (2007年9月21日)
Log Message:
-----------
changed cbooks reversed to agree with the python builtin
Modified Paths:
--------------
 trunk/matplotlib/API_CHANGES
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/lib/matplotlib/cbook.py
Modified: trunk/matplotlib/API_CHANGES
===================================================================
--- trunk/matplotlib/API_CHANGES	2007年09月20日 18:02:51 UTC (rev 3870)
+++ trunk/matplotlib/API_CHANGES	2007年09月21日 15:33:18 UTC (rev 3871)
@@ -1,3 +1,8 @@
+ Changed cbook.reversed so it yields a tuple rather than a 
+ (index, tuple). This agrees with the python reversed builtin,
+ and cbook only defines reversed if python doesnt provide the 
+ builtin.
+
 Made skiprows=1 the default on csv2rec
 
 The gd and paint backends have been deleted.
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年09月20日 18:02:51 UTC (rev 3870)
+++ trunk/matplotlib/CHANGELOG	2007年09月21日 15:33:18 UTC (rev 3871)
@@ -1,3 +1,6 @@
+2007年09月21日 Changed cbook.reversed to yield the same result as the 
+ python reversed builtin - DSD
+
 2007年09月13日 The usetex support in the pdf backend is more usable now,
 so I am enabling it. - JKS
 
Modified: trunk/matplotlib/lib/matplotlib/cbook.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/cbook.py	2007年09月20日 18:02:51 UTC (rev 3870)
+++ trunk/matplotlib/lib/matplotlib/cbook.py	2007年09月21日 15:33:18 UTC (rev 3871)
@@ -482,7 +482,7 @@
 enumerate() is new in Python 2.3
 """
 for i in range(len(seq)-1,-1,-1):
- yield i, seq[i]
+ yield seq[i]
 
 
 # use itertools.izip if available, else use python version
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 18:03:02
Revision: 3870
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3870&view=rev
Author: mdboom
Date: 2007年09月20日 11:02:51 -0700 (2007年9月20日)
Log Message:
-----------
Merged revisions 3866-3869 via svnmerge from 
http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib
........
 r3867 | jdh2358 | 2007年09月20日 10:13:51 -0400 (2007年9月20日) | 1 line
 
 committed rectangle selector lock patch
........
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/mlab.py
 branches/transforms/lib/matplotlib/widgets.py
Property Changed:
----------------
 branches/transforms/
Property changes on: branches/transforms
___________________________________________________________________
Name: svnmerge-integrated
 - /trunk/matplotlib:1-3865
 + /trunk/matplotlib:1-3869
Modified: branches/transforms/lib/matplotlib/mlab.py
===================================================================
--- branches/transforms/lib/matplotlib/mlab.py	2007年09月20日 18:00:32 UTC (rev 3869)
+++ branches/transforms/lib/matplotlib/mlab.py	2007年09月20日 18:02:51 UTC (rev 3870)
@@ -1255,7 +1255,7 @@
 if unpack: return X.transpose()
 else: return X
 
-def csv2rec(fname, comments='#', skiprows=1, checkrows=5, delimiter=',',
+def csv2rec(fname, comments='#', skiprows=0, checkrows=5, delimiter=',',
 converterd=None, names=None, missing=None):
 """
 Load data from comma/space/tab delimited file in fname into a
@@ -1314,6 +1314,14 @@
 else: return get_func(item, funcmap[func]) # recurse
 else: return func
 
+
+ # map column names that clash with builtins -- TODO - extend this list
+ itemd = {
+ 'return' : 'return_',
+ 'file' : 'file_',
+ 'print' : 'print_',
+ }
+ 
 def get_converters(reader):
 
 converters = None
@@ -1352,6 +1360,7 @@
 if not len(item):
 item = 'column%d'%i
 
+ item = itemd.get(item, item)
 cnt = seen.get(item, 0)
 if cnt>0:
 names.append(item + '%d'%cnt)
Modified: branches/transforms/lib/matplotlib/widgets.py
===================================================================
--- branches/transforms/lib/matplotlib/widgets.py	2007年09月20日 18:00:32 UTC (rev 3869)
+++ branches/transforms/lib/matplotlib/widgets.py	2007年09月20日 18:02:51 UTC (rev 3870)
@@ -955,24 +955,40 @@
 warnings.warn('Use SpanSelector instead!', DeprecationWarning)
 SpanSelector.__init__(self, ax, onselect, 'horizontal', **kwargs)
 
+
 class RectangleSelector:
 """
 Select a min/max range of the x axes for a matplotlib Axes
 
 Example usage:
 
- ax = subplot(111)
- ax.plot(x,y)
+ from matplotlib.widgets import RectangleSelector
+ from pylab import *
 
- def onselect(eclick, erelease):
+ def onselect(eclick, erelease):
 'eclick and erelease are matplotlib events at press and release'
- print 'startposition : (%f,%f)'%(eclick.xdata, eclick.ydata)
- print 'endposition : (%f,%f)'%(erelease.xdata, erelease.ydata)
- print 'used button : ', eclick.button
+ print ' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata)
+ print ' endposition : (%f, %f)' % (erelease.xdata, erelease.ydata)
+ print ' used button : ', eclick.button
 
- span = Selector(ax, onselect,drawtype='box')
- show()
+ def toggle_Selector(event):
+ print ' Key pressed.'
+ if event.key in ['Q', 'q'] and toggle_Selector.RS.active:
+ print ' RectangleSelector deactivated.'
+ toggle_Selector.RS.set_active(False)
+ if event.key in ['A', 'a'] and not toggle_Selector.RS.active:
+ print ' RectangleSelector activated.'
+ toggle_Selector.RS.set_active(True)
 
+ x = arange(100)/(99.0)
+ y = sin(x)
+ fig = figure
+ ax = subplot(111)
+ ax.plot(x,y)
+
+ toggle_Selector.RS = RectangleSelector(ax, onselect, drawtype='line')
+ connect('key_press_event', toggle_Selector)
+ show()
 """
 def __init__(self, ax, onselect, drawtype='box',
 minspanx=None, minspany=None, useblit=False,
@@ -1001,8 +1017,6 @@
 Use type if you want the mouse to draw a line, a box or nothing
 between click and actual position ny setting
 drawtype = 'line', drawtype='box' or drawtype = 'none'.
-
-
 """
 self.ax = ax
 self.visible = True
@@ -1012,6 +1026,7 @@
 self.canvas.mpl_connect('button_release_event', self.release)
 self.canvas.mpl_connect('draw_event', self.update_background)
 
+ self.active = True # for activation / deactivation
 self.to_draw = None
 self.background = None
 
@@ -1052,6 +1067,14 @@
 
 def ignore(self, event):
 'return True if event should be ignored'
+ # If RectangleSelector is not active :
+ if not self.active:
+ return True
+ 
+ # If canvas was locked
+ if not self.canvas.widgetlock.available(self):
+ return True
+ 
 # If no button was pressed yet ignore the event if it was out
 # of the axes
 if self.eventpress == None:
@@ -1142,6 +1165,17 @@
 self.update()
 return False
 
+ def set_active(self, active):
+ """ Use this to activate / deactivate the RectangleSelector
+
+ from your program with an boolean variable 'active'.
+ """
+ self.active = active
+
+ def get_active(self):
+ """ to get status of active mode (boolean variable)"""
+ return self.active 
+
 class Lasso(Widget):
 def __init__(self, ax, xy, callback=None, useblit=True):
 self.axes = ax
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 18:00:34
Revision: 3869
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3869&view=rev
Author: mdboom
Date: 2007年09月20日 11:00:32 -0700 (2007年9月20日)
Log Message:
-----------
First baby step in getting arbitrary non-linear transformations into
the pipeline.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/axis.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/text.py
 branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/axes.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -633,10 +633,16 @@
 self.transAxes = mtransforms.BboxTransform(
 mtransforms.Bbox.unit(), self.bbox)
 # self.set_transform(self.transAxes)
- self.transData = mtransforms.BboxTransform(
- self.viewLim, self.bbox)
+# self.transData = mtransforms.BboxTransform(
+# self.viewLim, self.bbox)
+ self.preDataTransform = mtransforms.BboxTransform(
+ self.viewLim, mtransforms.Bbox.unit())
+ self.dataTransform = mtransforms.TestLogTransform()
+ # self.dataTransform = mtransforms.Affine2D().scale(1.5)
+ self.transData = self.preDataTransform + self.dataTransform + mtransforms.BboxTransform(
+ mtransforms.Bbox.unit(), self.bbox)
+ 
 	 
-	 
 def get_position(self, original=False):
 'Return the axes rectangle left, bottom, width, height'
 if original:
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/axis.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -1032,18 +1032,17 @@
 else:
 bbox = Bbox.union(bboxes)
 bottom = bbox.ymin
-
- self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi / 72.0))
-
+ self.label.set_position( (x, bottom - self.LABELPAD*self.figure.dpi / 72.0))
+ 
 else:
 if not len(bboxes2):
 top = self.axes.bbox.ymax
 else:
 bbox = bbox_union(bboxes2)
 top = bbox.ymax
+ 
+ self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi / 72.0))
 
- self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi.get()/72.0))
-
 def _update_offset_text_position(self, bboxes, bboxes2):
 """
 Update the offset_text position based on the sequence of bounding
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -84,7 +84,8 @@
 from matplotlib.font_manager import findfont
 from matplotlib.ft2font import FT2Font, LOAD_DEFAULT
 from matplotlib.mathtext import MathTextParser
-from matplotlib.transforms import Bbox
+from matplotlib.path import Path
+from matplotlib.transforms import Affine2D, Bbox
 
 from _backend_agg import RendererAgg as _RendererAgg
 
@@ -117,8 +118,8 @@
 				 debug=False)
 if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
 'debug-annoying')
- self.draw_path = self._renderer.draw_path
- self.draw_markers = self._renderer.draw_markers
+ #self.draw_path = self._renderer.draw_path
+ #self.draw_markers = self._renderer.draw_markers
 self.draw_image = self._renderer.draw_image
 self.copy_from_bbox = self._renderer.copy_from_bbox
 self.restore_region = self._renderer.restore_region
@@ -129,6 +130,17 @@
 if __debug__: verbose.report('RendererAgg.__init__ done',
 'debug-annoying')
 
+ # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ def draw_path(self, gc, path, trans, rgbFace=None):
+ new_path, affine = path.transformed_without_affine(trans)
+ self._renderer.draw_path(gc, new_path, affine, rgbFace)
+
+ # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
+ assert marker_trans.is_affine()
+ new_path, affine = path.transformed_without_affine(trans)
+ self._renderer.draw_markers(gc, marker_path, marker_trans, new_path, affine, rgbFace)
+ 
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 """
 Draw the math text using matplotlib.mathtext
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -1102,12 +1102,14 @@
 """
 return self._dashcapstyle
 
+ 
 def get_solid_capstyle(self):
 """
 Get the cap style for solid linestyles
 """
 return self._solidcapstyle
 
+ 
 def is_dashed(self):
 'return True if line is dashstyle'
 return self._linestyle in ('--', '-.', ':')
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -70,6 +70,13 @@
 yield vertices[i]
 i += 1
 
+ def transformed(self, transform):
+ return Path(transform.transform(self.vertices), self.codes)
+
+ def transformed_without_affine(self, transform):
+ vertices, affine = transform.transform_without_affine(self.vertices)
+ return Path(vertices, self.codes), affine
+ 
 _unit_rectangle = None
 #@classmethod
 def unit_rectangle(cls):
Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/text.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -185,7 +185,8 @@
 
 xmin, ymin = thisx, thisy
 lines = self._text.split('\n')
- 
+
+ # MGDTODO: whs could be a numpy.array
 whs = []
 # Find full vertical extent of font,
 # including ascenders and descenders:
@@ -260,27 +261,21 @@
 else: offsety = ty - ymin
 
 xmin += offsetx
- xmax += offsetx
 ymin += offsety
- ymax += offsety
 
 bbox = Bbox.from_lbwh(xmin, ymin, width, height)
 
-	
-
 # now rotate the positions around the first x,y position
 xys = M.transform(offsetLayout)
-	tx = xys[:, 0]
-	ty = xys[:, 1]
-	tx += offsetx
-	ty += offsety
+ xys[:, 0] += offsetx
+ xys[:, 1] += offsety
 
 # now inverse transform back to data coords
 	inverse_transform = self.get_transform().inverted()
 xys = inverse_transform.transform(xys)
 
- xs, ys = zip(*xys)
-
+ xs, ys = xys[:, 0], xys[:, 1]
+ 
 ret = bbox, zip(lines, whs, xs, ys)
 self.cached[key] = ret
 return ret
@@ -331,15 +326,15 @@
 
 for line, wh, x, y in info:
 x, y = trans.transform_point((x, y))
-
+ 
 if renderer.flipy():
 canvasw, canvash = renderer.get_canvas_width_height()
 y = canvash-y
-
+ 
 renderer.draw_text(gc, x, y, line,
 self._fontproperties, angle,
 ismath=self.is_math_text(line))
-
+ 
 def get_color(self):
 "Return the color of the text"
 return self._color
@@ -407,7 +402,9 @@
 return (x, y, self._text, self._color,
 self._verticalalignment, self._horizontalalignment,
 hash(self._fontproperties), self._rotation,
- self.get_transform(),
+ # MGDTODO: Find a better way to determine if the
+ # transform as changed
+ str(self.get_transform())
 )
 
 def get_text(self):
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月20日 14:26:27 UTC (rev 3868)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月20日 18:00:32 UTC (rev 3869)
@@ -256,10 +256,10 @@
 self.invalidate()
 
 def transformed(self, transform):
- return Bbox(transform(self._points))
+ return Bbox(transform.transform(self._points))
 
 def inverse_transformed(self, transform):
- return Bbox(transform.inverted()(self._points))
+ return Bbox(transform.inverted().transform(self._points))
 
 def expanded(self, sw, sh):
 width = self.width
@@ -408,13 +408,13 @@
 # MGDTODO: The major speed trap here is just converting to
 # the points to an array in the first place. If we can use
 # more arrays upstream, that should help here.
- if not isinstance(points, npy.ndarray):
- import traceback
- print '-' * 60
- print 'A non-numpy array was passed in for transformation. Please '
- print 'correct this.'
- print "".join(traceback.format_stack())
- print points
+# if not isinstance(points, npy.ndarray):
+# import traceback
+# print '-' * 60
+# print 'A non-numpy array was passed in for transformation. Please '
+# print 'correct this.'
+# print "".join(traceback.format_stack())
+# print points
 mtx = self.get_matrix()
 points = npy.asarray(points, npy.float_)
 points = points.transpose()
@@ -563,6 +563,10 @@
 self._y = y_transform
 self.set_children(['_x', '_y'])
 
+ def __repr__(self):
+ return "BlendedGenericTransform(%s,%s)" % (self._x, self._y)
+ __str__ = __repr__
+ 
 def transform(self, points):
 # MGDTODO: Optimize the case where one of these is
 # an affine
@@ -590,28 +594,6 @@
 return True
 
 
-class BlendedSeparableTransform(Transform):
- input_dims = 2
- output_dims = 2
-
- def __init__(self, x_transform, y_transform):
-	# Here we ask: "Does it blend?"
- assert x_transform.is_separable()
- assert y_transform.is_separable()
- assert x_transform.input_dims == x.transform.output_dims == 1
- assert y_transform.input_dims == y.transform.output_dims == 1
- 
- Transform.__init__(self)
- self._x = x_transform
- self._y = y_transform
- self.set_children(['_x', '_y'])
-
- def transform(self, points):
- x_points = self._x(points[:, 0])
- y_points = self._y(points[:, 1])
- return npy.vstack((x_points[:, 0:1], y_points[:, 1:2])).transpose()
- 
- 
 class BlendedAffine2D(Affine2DBase, Transform):
 def __init__(self, x_transform, y_transform):
 assert x_transform.is_affine()
@@ -666,6 +648,10 @@
 self._a = a
 self._b = b
 self.set_children(['_a', '_b'])
+
+ def __repr__(self):
+ return "CompositeGenericTransform(%s, %s)" % (self._a, self._b)
+ __str__ = __repr__
 
 def transform(self, points):
 return self._b.transform(self._a.transform(points))
@@ -724,10 +710,21 @@
 input_dims = 2
 output_dims = 2
 def transform(self, xy):
- return xy * 2
+ marray = npy.ma.masked_where(xy <= 0.0, xy * 10.0)
+ return npy.log10(marray)
+ 
+ def inverted(self):
+ return TestInvertLogTransform()
 
+
+class TestInvertLogTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+ def transform(self, xy):
+ return npy.power(10, xy) / 10.0
+ 
 def inverted(self):
- return self
+ return TestLogTransform()
 
 
 class BboxTransform(Affine2DBase):
@@ -825,7 +822,7 @@
 
 assert bbox.bounds == (10, 15, 10, 10)
 
- print npy.asarray(bbox)
+ assert tuple(npy.asarray(bbox).flatten()) == (10, 15, 20, 25)
 
 bbox.intervalx = (11, 21)
 bbox.intervaly = (16, 26)
@@ -859,29 +856,35 @@
 scale = Affine2D().scale(10, 20)
 assert scale.to_values() == (10, 0, 0, 20, 0, 0)
 rotation = Affine2D().rotate_deg(30)
- print rotation.to_values() == (0.86602540378443871, 0.49999999999999994,
+ assert rotation.to_values() == (0.86602540378443871, 0.49999999999999994,
 -0.49999999999999994, 0.86602540378443871,
 0.0, 0.0)
 
 points = npy.array([[1,2],[3,4],[5,6],[7,8]], npy.float_)
- translated_points = translation(points)
+ translated_points = translation.transform(points)
 assert (translated_points == [[11., 22.], [13., 24.], [15., 26.], [17., 28.]]).all()
- scaled_points = scale(points)
+ scaled_points = scale.transform(points)
 print scaled_points
- rotated_points = rotation(points)
+ rotated_points = rotation.transform(points)
 print rotated_points
 
- tpoints1 = rotation(translation(scale(points)))
+ tpoints1 = rotation.transform(translation.transform(scale.transform(points)))
 trans_sum = scale + translation + rotation
- tpoints2 = trans_sum(points)
- print tpoints1, tpoints2
- print tpoints1 == tpoints2
+ tpoints2 = trans_sum.transform(points)
 # Need to do some sort of fuzzy comparison here?
- # assert (tpoints1 == tpoints2).all()
+ assert (tpoints1.round() == tpoints2.round()).all()
 
+ print points
+ 
+ comp = TestLogTransform() + Affine2D().rotate_deg(15)
+ tpoints = comp.transform(points)
+ itpoints = comp.inverted().transform(tpoints)
+ print tpoints, itpoints
+ assert (points.round() == itpoints.round()).all()
+ 
 # Here are some timing tests
 points = npy.asarray([(random(), random()) for i in xrange(10000)])
- t = timeit.Timer("trans_sum(points)", "from __main__ import trans_sum, points")
+ t = timeit.Timer("trans_sum.transform(points)", "from __main__ import trans_sum, points")
 print "Time to transform 10000 x 10 points:", t.timeit(10)
 
 __all__ = ['Transform', 'Affine2D']
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 14:26:32
Revision: 3868
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3868&view=rev
Author: mdboom
Date: 2007年09月20日 07:26:27 -0700 (2007年9月20日)
Log Message:
-----------
Don't copy path array to a contiguous one.
Modified Paths:
--------------
 branches/transforms/src/_backend_agg.cpp
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月20日 14:13:51 UTC (rev 3867)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月20日 14:26:27 UTC (rev 3868)
@@ -100,17 +100,18 @@
 Py::Object vertices_obj = path_obj.getAttr("vertices");
 Py::Object codes_obj = path_obj.getAttr("codes");
 
- vertices = (PyArrayObject*)PyArray_ContiguousFromObject
+ vertices = (PyArrayObject*)PyArray_FromObject
 (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2);
 if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2)
 throw Py::ValueError("Invalid vertices array.");
- codes = (PyArrayObject*)PyArray_ContiguousFromObject
+
+ codes = (PyArrayObject*)PyArray_FromObject
 (codes_obj.ptr(), PyArray_UINT8, 1, 1);
 if (!codes) 
 throw Py::ValueError("Invalid codes array.");
 
 if (codes->dimensions[0] != vertices->dimensions[0])
- throw Py::ValueError("Vertices and codes array are not the same length.");
+ throw Py::ValueError("vertices and codes arrays are not the same length.");
 
 m_total_vertices = codes->dimensions[0];
 }
@@ -125,10 +126,9 @@
 inline unsigned vertex(unsigned idx, double* x, double* y) {
 if (idx > m_total_vertices)
 throw Py::RuntimeError("Requested vertex past end");
- double* pv = (double*)(vertices->data + (idx * vertices->strides[0]));
- *x = *pv++;
- *y = *pv;
- return code_map[(unsigned int)*(codes->data + (idx * codes->strides[0]))];
+ *x = *(double*)PyArray_GETPTR2(vertices, idx, 0);
+ *y = *(double*)PyArray_GETPTR2(vertices, idx, 1);
+ return code_map[(int)*(char *)PyArray_GETPTR1(codes, idx)];
 }
 
 inline unsigned vertex(double* x, double* y) {
@@ -145,12 +145,14 @@
 }
 };
 
-const char PathIterator::code_map[] = {0, 
-				 agg::path_cmd_move_to, 
-				 agg::path_cmd_line_to, 
-				 agg::path_cmd_curve3,
-				 agg::path_cmd_curve4,
-				 agg::path_cmd_end_poly | agg::path_flags_close};
+// Maps path codes on the Python side to agg path commands
+const char PathIterator::code_map[] = 
+ {0, 
+ agg::path_cmd_move_to, 
+ agg::path_cmd_line_to, 
+ agg::path_cmd_curve3,
+ agg::path_cmd_curve4,
+ agg::path_cmd_end_poly | agg::path_flags_close};
 
 template<class VertexSource> class conv_quantize
 {
@@ -160,19 +162,16 @@
 
 void set_source(VertexSource& source) { m_source = &source; }
 
- void rewind(unsigned path_id) 
- { 
+ void rewind(unsigned path_id) { 
 m_source->rewind(path_id); 
 }
 
- unsigned vertex(double* x, double* y)
- {
+ unsigned vertex(double* x, double* y) {
 unsigned cmd = m_source->vertex(x, y);
- if(m_quantize && agg::is_vertex(cmd))
- {
-	*x = (int)(*x);
-	*y = (int)(*y);
- }
+ if (m_quantize && agg::is_vertex(cmd)) {
+ *x = (int)(*x + 0.5);
+ *y = (int)(*y + 0.5);
+ }
 return cmd;
 }
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2007年09月20日 14:13:53
Revision: 3867
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3867&view=rev
Author: jdh2358
Date: 2007年09月20日 07:13:51 -0700 (2007年9月20日)
Log Message:
-----------
committed rectangle selector lock patch
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/mlab.py
 trunk/matplotlib/lib/matplotlib/widgets.py
Modified: trunk/matplotlib/lib/matplotlib/mlab.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mlab.py	2007年09月20日 13:59:15 UTC (rev 3866)
+++ trunk/matplotlib/lib/matplotlib/mlab.py	2007年09月20日 14:13:51 UTC (rev 3867)
@@ -1255,7 +1255,7 @@
 if unpack: return X.transpose()
 else: return X
 
-def csv2rec(fname, comments='#', skiprows=1, checkrows=5, delimiter=',',
+def csv2rec(fname, comments='#', skiprows=0, checkrows=5, delimiter=',',
 converterd=None, names=None, missing=None):
 """
 Load data from comma/space/tab delimited file in fname into a
@@ -1314,6 +1314,14 @@
 else: return get_func(item, funcmap[func]) # recurse
 else: return func
 
+
+ # map column names that clash with builtins -- TODO - extend this list
+ itemd = {
+ 'return' : 'return_',
+ 'file' : 'file_',
+ 'print' : 'print_',
+ }
+ 
 def get_converters(reader):
 
 converters = None
@@ -1352,6 +1360,7 @@
 if not len(item):
 item = 'column%d'%i
 
+ item = itemd.get(item, item)
 cnt = seen.get(item, 0)
 if cnt>0:
 names.append(item + '%d'%cnt)
Modified: trunk/matplotlib/lib/matplotlib/widgets.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/widgets.py	2007年09月20日 13:59:15 UTC (rev 3866)
+++ trunk/matplotlib/lib/matplotlib/widgets.py	2007年09月20日 14:13:51 UTC (rev 3867)
@@ -955,24 +955,40 @@
 warnings.warn('Use SpanSelector instead!', DeprecationWarning)
 SpanSelector.__init__(self, ax, onselect, 'horizontal', **kwargs)
 
+
 class RectangleSelector:
 """
 Select a min/max range of the x axes for a matplotlib Axes
 
 Example usage:
 
- ax = subplot(111)
- ax.plot(x,y)
+ from matplotlib.widgets import RectangleSelector
+ from pylab import *
 
- def onselect(eclick, erelease):
+ def onselect(eclick, erelease):
 'eclick and erelease are matplotlib events at press and release'
- print 'startposition : (%f,%f)'%(eclick.xdata, eclick.ydata)
- print 'endposition : (%f,%f)'%(erelease.xdata, erelease.ydata)
- print 'used button : ', eclick.button
+ print ' startposition : (%f, %f)' % (eclick.xdata, eclick.ydata)
+ print ' endposition : (%f, %f)' % (erelease.xdata, erelease.ydata)
+ print ' used button : ', eclick.button
 
- span = Selector(ax, onselect,drawtype='box')
- show()
+ def toggle_Selector(event):
+ print ' Key pressed.'
+ if event.key in ['Q', 'q'] and toggle_Selector.RS.active:
+ print ' RectangleSelector deactivated.'
+ toggle_Selector.RS.set_active(False)
+ if event.key in ['A', 'a'] and not toggle_Selector.RS.active:
+ print ' RectangleSelector activated.'
+ toggle_Selector.RS.set_active(True)
 
+ x = arange(100)/(99.0)
+ y = sin(x)
+ fig = figure
+ ax = subplot(111)
+ ax.plot(x,y)
+
+ toggle_Selector.RS = RectangleSelector(ax, onselect, drawtype='line')
+ connect('key_press_event', toggle_Selector)
+ show()
 """
 def __init__(self, ax, onselect, drawtype='box',
 minspanx=None, minspany=None, useblit=False,
@@ -1001,8 +1017,6 @@
 Use type if you want the mouse to draw a line, a box or nothing
 between click and actual position ny setting
 drawtype = 'line', drawtype='box' or drawtype = 'none'.
-
-
 """
 self.ax = ax
 self.visible = True
@@ -1012,6 +1026,7 @@
 self.canvas.mpl_connect('button_release_event', self.release)
 self.canvas.mpl_connect('draw_event', self.update_background)
 
+ self.active = True # for activation / deactivation
 self.to_draw = None
 self.background = None
 
@@ -1052,6 +1067,14 @@
 
 def ignore(self, event):
 'return True if event should be ignored'
+ # If RectangleSelector is not active :
+ if not self.active:
+ return True
+ 
+ # If canvas was locked
+ if not self.canvas.widgetlock.available(self):
+ return True
+ 
 # If no button was pressed yet ignore the event if it was out
 # of the axes
 if self.eventpress == None:
@@ -1142,6 +1165,17 @@
 self.update()
 return False
 
+ def set_active(self, active):
+ """ Use this to activate / deactivate the RectangleSelector
+
+ from your program with an boolean variable 'active'.
+ """
+ self.active = active
+
+ def get_active(self):
+ """ to get status of active mode (boolean variable)"""
+ return self.active 
+
 class Lasso(Widget):
 def __init__(self, ax, xy, callback=None, useblit=True):
 self.axes = ax
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 13:59:16
Revision: 3866
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3866&view=rev
Author: mdboom
Date: 2007年09月20日 06:59:15 -0700 (2007年9月20日)
Log Message:
-----------
Merged revisions 3847-3865 via svnmerge from 
http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib
........
 r3853 | jouni | 2007年09月15日 00:01:56 -0400 (2007年9月15日) | 2 lines
 
 Bugfix and doc fixes in type1font.py
........
 r3861 | mdboom | 2007年09月20日 08:31:26 -0400 (2007年9月20日) | 2 lines
 
 Fix font.size from being saved in the fontManager.cache
........
 r3862 | mdboom | 2007年09月20日 08:40:41 -0400 (2007年9月20日) | 2 lines
 
 Removing debugging output in last commit.
........
 r3863 | jdh2358 | 2007年09月20日 09:50:27 -0400 (2007年9月20日) | 1 line
 
 added gradient bar example
........
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/font_manager.py
Added Paths:
-----------
 branches/transforms/examples/gradient_bar.py
Property Changed:
----------------
 branches/transforms/
Property changes on: branches/transforms
___________________________________________________________________
Name: svnmerge-integrated
 - /trunk/matplotlib:1-3846
 + /trunk/matplotlib:1-3865
Copied: branches/transforms/examples/gradient_bar.py (from rev 3863, trunk/matplotlib/examples/gradient_bar.py)
===================================================================
--- branches/transforms/examples/gradient_bar.py	 (rev 0)
+++ branches/transforms/examples/gradient_bar.py	2007年09月20日 13:59:15 UTC (rev 3866)
@@ -0,0 +1,26 @@
+from pylab import figure, show, nx, cm
+
+def gbar(ax, x, y, width=0.5, bottom=0):
+ X = [[.6, .6],[.7,.7]]
+ for left,top in zip(x, y):
+ right = left+width
+ ax.imshow(X, interpolation='bicubic', cmap=cm.Blues,
+ extent=(left, right, bottom, top), alpha=1)
+
+fig = figure()
+
+xmin, xmax = xlim = 0,10
+ymin, ymax = ylim = 0,1
+ax = fig.add_subplot(111, xlim=xlim, ylim=ylim,
+ autoscale_on=False)
+X = [[.6, .6],[.7,.7]]
+
+ax.imshow(X, interpolation='bicubic', cmap=cm.copper,
+ extent=(xmin, xmax, ymin, ymax), alpha=1)
+
+N = 10
+x = nx.arange(N)+0.25
+y = nx.mlab.rand(N)
+gbar(ax, x, y, width=0.7)
+ax.set_aspect('normal')
+show()
Modified: branches/transforms/lib/matplotlib/font_manager.py
===================================================================
--- branches/transforms/lib/matplotlib/font_manager.py	2007年09月20日 13:57:59 UTC (rev 3865)
+++ branches/transforms/lib/matplotlib/font_manager.py	2007年09月20日 13:59:15 UTC (rev 3866)
@@ -843,10 +843,9 @@
 """
 
 def __init__(self, size=None, weight='normal'):
- if not size : size = rcParams['font.size']
- self.__default_size = size
 self.__default_weight = weight
-
+ self.default_size = size
+ 
 paths = [os.path.join(rcParams['datapath'],'fonts','ttf'),
 os.path.join(rcParams['datapath'],'fonts','afm')]
 
@@ -899,7 +898,9 @@
 
 def get_default_size(self):
 "Return the default font size."
- return self.__default_size
+ if self.default_size is None:
+ return rcParams['font.size']
+ return self.default_size
 
 def set_default_weight(self, weight):
 "Set the default font weight. The initial value is 'normal'."
@@ -1085,6 +1086,7 @@
 
 try:
 fontManager = pickle_load(_fmcache)
+ fontManager.default_size = None
 verbose.report("Using fontManager instance from %s" % _fmcache)
 except:
 _rebuild()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 13:58:01
Revision: 3865
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3865&view=rev
Author: mdboom
Date: 2007年09月20日 06:57:59 -0700 (2007年9月20日)
Log Message:
-----------
Go all out with iterator (rather than copy) approach, as it is much faster.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/transforms.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月20日 13:57:32 UTC (rev 3864)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月20日 13:57:59 UTC (rev 3865)
@@ -17,11 +17,6 @@
 class RendererBase:
 """An abstract base class to handle drawing/rendering operations
 """
- # This will cache paths across rendering instances
- # Each subclass of RenderBase should define this a weak-keyed
- # dictionary to hold native paths
- # _native_paths = weakref.WeakKeyDictionary()
- 
 def __init__(self):
 self._texmanager = None
 
@@ -37,43 +32,16 @@
 """
 pass
 
- def _get_cached_native_path(self, path):
-	native_path = self._native_paths.get(path)
-	if native_path is None:
-	 print "CACHE MISS", path
-	 native_path = self.convert_to_native_path(path)
-	 self._native_paths[path] = native_path
-	return native_path
- 
 def draw_path(self, gc, path, transform, rgbFace=None):
 	"""
 	Handles the caching of the native path associated with the
 	given path and calls the underlying backend's _draw_path to
 	actually do the drawing.
 	"""
-	native_path = self._get_cached_native_path(path)
-	self._draw_native_path(gc, native_path, transform, rgbFace)
+ # MGDTODO: Update docstring
+ raise NotImplementedError
 
- def _draw_native_path(self, gc, native_path, transform, rgbFace):
-	"""
-	Draw the native path object with the given GraphicsContext and
-	transform. The transform passed in will always be affine.
-	"""
-	raise NotImplementedError
-	
- def convert_to_native_path(self, path):
-	"""
-	Backends will normally will override this, but if they don't need any
-	special optimizations, they can just have the generic path data
-	passed to them in draw_path.
-	"""
-	return path
-
 def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
-	native_marker_path = self._get_cached_native_path(marker_path)
-	self._draw_native_markers(gc, native_marker_path, marker_trans, path, trans, rgbFace)
-	
- def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
 """
 This method is currently underscore hidden because the
 draw_markers method is being used as a sentinel for newstyle
@@ -94,7 +62,11 @@
 vec6 = transform.as_vec6_val()
 ...backend dependent affine...
 """
+ # MGDTODO: Update docstring
 raise NotImplementedError
+	
+ def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
+ raise NotImplementedError
 
 def get_image_magnification(self):
 """
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月20日 13:57:32 UTC (rev 3864)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月20日 13:57:59 UTC (rev 3865)
@@ -117,8 +117,8 @@
 				 debug=False)
 if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
 'debug-annoying')
-
-	self.convert_to_native_path = self._renderer.convert_to_native_path
+ self.draw_path = self._renderer.draw_path
+ self.draw_markers = self._renderer.draw_markers
 self.draw_image = self._renderer.draw_image
 self.copy_from_bbox = self._renderer.copy_from_bbox
 self.restore_region = self._renderer.restore_region
@@ -129,16 +129,6 @@
 if __debug__: verbose.report('RendererAgg.__init__ done',
 'debug-annoying')
 
- def _draw_native_path(self, gc, path, transform, rgbFace):
-	return self._renderer.draw_path(gc, path, transform.get_matrix(), rgbFace)
- 
- def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
-	return self._renderer.draw_markers(
-	 gc,
-	 native_marker_path, marker_trans.get_matrix(),
-	 path.vertices, path.codes, trans.get_matrix(),
-	 rgbFace)
-
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 """
 Draw the math text using matplotlib.mathtext
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月20日 13:57:32 UTC (rev 3864)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月20日 13:57:59 UTC (rev 3865)
@@ -365,7 +365,7 @@
 Transform.__init__(self)
 self._inverted = None
 
- def __array__(self):
+ def __array__(self, *args, **kwargs):
 	return self.get_matrix()
 	
 def _do_invalidation(self):
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月20日 13:57:32 UTC (rev 3864)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月20日 13:57:59 UTC (rev 3865)
@@ -48,59 +48,42 @@
 agg::trans_affine py_to_agg_transformation_matrix(const Py::Object& obj) {
 PyArrayObject* matrix = NULL;
 
- double a = 1.0, b = 0.0, c = 0.0, d = 1.0, e = 0.0, f = 0.0;
-
 try {
- matrix = (PyArrayObject*) PyArray_ContiguousFromObject(obj.ptr(), PyArray_DOUBLE, 2, 2);
- if (!matrix || matrix->nd != 2 || matrix->dimensions[0] != 3 || matrix->dimensions[1] != 3) {
- throw Py::ValueError("Invalid affine transformation matrix.");
+ matrix = (PyArrayObject*) PyArray_FromObject(obj.ptr(), PyArray_DOUBLE, 2, 2);
+ if (!matrix) {
+ throw Py::Exception();
 }
-
- size_t stride0 = matrix->strides[0];
- size_t stride1 = matrix->strides[1];
- char* row0 = matrix->data;
- char* row1 = row0 + stride0;
-
- a = *(double*)(row0);
- row0 += stride1;
- c = *(double*)(row0);
- row0 += stride1;
- e = *(double*)(row0);
- 
- b = *(double*)(row1);
- row1 += stride1;
- d = *(double*)(row1);
- row1 += stride1;
- f = *(double*)(row1);
+ if (matrix->nd == 2 || matrix->dimensions[0] == 3 || matrix->dimensions[1] == 3) {
+ size_t stride0 = matrix->strides[0];
+ size_t stride1 = matrix->strides[1];
+ char* row0 = matrix->data;
+ char* row1 = row0 + stride0;
+ 
+ double a = *(double*)(row0);
+ row0 += stride1;
+ double c = *(double*)(row0);
+ row0 += stride1;
+ double e = *(double*)(row0);
+ 
+ double b = *(double*)(row1);
+ row1 += stride1;
+ double d = *(double*)(row1);
+ row1 += stride1;
+ double f = *(double*)(row1);
+ 
+ Py_XDECREF(matrix);
+ 
+ return agg::trans_affine(a, b, c, d, e, f);
+ }
 } catch (...) {
- Py_XDECREF(matrix);
+ 
 }
 
 Py_XDECREF(matrix);
-
- return agg::trans_affine(a, b, c, d, e, f);
+ throw Py::TypeError("Invalid affine transformation matrix");
 }
 
-/** Helper function to get the next vertex in a Numpy array of vertices.
- * Will generally be used through the GET_NEXT_VERTEX macro.
- */
-inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, 
-			 double& x, double& y,
-			 size_t next_vertex_stride, 
-			 size_t next_axis_stride,
-			 const char* & code_i, size_t code_stride) {
- if (vertex_i + next_axis_stride >= vertex_end)
- throw Py::ValueError("Error parsing path. Read past end of vertices");
- x = *(double*)vertex_i;
- y = *(double*)(vertex_i + next_axis_stride);
- vertex_i += next_vertex_stride;
- code_i += code_stride;
-}
-
-#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride, code_i, code_stride)
-
 Py::Object BufferRegion::to_string(const Py::Tuple &args) {
- 
 // owned=true to prevent memory leak
 return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true);
 }
@@ -145,7 +128,6 @@
 double* pv = (double*)(vertices->data + (idx * vertices->strides[0]));
 *x = *pv++;
 *y = *pv;
- // MGDTODO: Range check
 return code_map[(unsigned int)*(codes->data + (idx * codes->strides[0]))];
 }
 
@@ -170,9 +152,43 @@
 				 agg::path_cmd_curve4,
 				 agg::path_cmd_end_poly | agg::path_flags_close};
 
+template<class VertexSource> class conv_quantize
+{
+public:
+ conv_quantize(VertexSource& source, bool quantize) :
+ m_source(&source), m_quantize(quantize) {}
+ 
+ void set_source(VertexSource& source) { m_source = &source; }
+
+ void rewind(unsigned path_id) 
+ { 
+ m_source->rewind(path_id); 
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ unsigned cmd = m_source->vertex(x, y);
+ if(m_quantize && agg::is_vertex(cmd))
+ {
+	*x = (int)(*x);
+	*y = (int)(*y);
+ }
+ return cmd;
+ }
+
+ void activate(bool quantize) {
+ m_quantize = quantize;
+ }
+
+private:
+ VertexSource* m_source;
+ bool m_quantize;
+};
+
+
 GCAgg::GCAgg(const Py::Object &gc, double dpi, bool snapto) :
 dpi(dpi), snapto(snapto), isaa(true), linewidth(1.0), alpha(1.0),
- cliprect(NULL), clippath(NULL), 
+ cliprect(NULL), 
 Ndash(0), dashOffset(0.0), dasha(NULL)
 {
 _VERBOSE("GCAgg::GCAgg");
@@ -316,15 +332,7 @@
 
 _VERBOSE("GCAgg::_set_clip_path");
 
- Py_XINCREF(clippath);
- clippath = NULL;
- 
- Py::Object o = gc.getAttr("_clippath");
- if (o.ptr()==Py_None) {
- return;
- }
- 
- clippath = new PathAgg(o);
+ clippath = gc.getAttr("_clippath");
 }
 
 
@@ -337,8 +345,7 @@
 height(height),
 dpi(dpi),
 NUMBYTES(width*height*4),
- debug(debug),
- lastclippath(NULL)
+ debug(debug)
 {
 _VERBOSE("RendererAgg::RendererAgg");
 unsigned stride(width*4);
@@ -599,7 +606,7 @@
 
 Py::Object
 RendererAgg::draw_markers(const Py::Tuple& args) {
- typedef agg::conv_transform<agg::path_storage> transformed_path_t;
+ typedef agg::conv_transform<PathIterator> transformed_path_t;
 typedef agg::conv_curve<transformed_path_t> curve_t;
 typedef agg::conv_stroke<curve_t> stroke_t;
 typedef agg::conv_dash<curve_t> dash_t;
@@ -607,27 +614,29 @@
 
 theRasterizer->reset_clipping();
 
- args.verify_length(7);
+ args.verify_length(5, 6);
 
 GCAgg gc = GCAgg(args[0], dpi);
 Py::Object marker_path_obj = args[1];
- if (!PathAgg::check(marker_path_obj))
- throw Py::TypeError("Native path object is not of correct type");
- PathAgg* marker_path = static_cast<PathAgg*>(marker_path_obj.ptr());
 agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2]);
- Py::Object vertices_obj = args[3];
- Py::Object codes_obj = args[4];
- agg::trans_affine trans = py_to_agg_transformation_matrix(args[5]);
- facepair_t face = _get_rgba_face(args[6], gc.alpha);
+ Py::Object path_obj = args[3];
+ agg::trans_affine trans = py_to_agg_transformation_matrix(args[4]);
+ Py::Object face_obj;
+ if (args.size() == 6)
+ face_obj = args[5];
+ facepair_t face = _get_rgba_face(face_obj, gc.alpha);
 
 // Deal with the difference in y-axis direction
 marker_trans *= agg::trans_affine_scaling(1.0, -1.0);
 trans *= agg::trans_affine_scaling(1.0, -1.0);
 trans *= agg::trans_affine_translation(0.0, (double)height);
 
- marker_path->rewind(0);
- transformed_path_t marker_path_transformed(*marker_path, marker_trans);
+ PathIterator marker_path(marker_path_obj);
+ transformed_path_t marker_path_transformed(marker_path, marker_trans);
 curve_t marker_path_curve(marker_path_transformed);
+
+ PathIterator path(path_obj);
+ transformed_path_t path_transformed(path, trans);
 
 //maxim's suggestions for cached scanlines
 agg::scanline_storage_aa8 scanlines;
@@ -635,19 +644,8 @@
 
 agg::int8u* fillCache = NULL;
 agg::int8u* strokeCache = NULL;
- PyArrayObject* vertices = NULL;
- PyArrayObject* codes = NULL;
 
 try {
- vertices = (PyArrayObject*)PyArray_ContiguousFromObject
- (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2);
- if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2)
- throw Py::ValueError("Invalid vertices array.");
- codes = (PyArrayObject*)PyArray_ContiguousFromObject
- (codes_obj.ptr(), PyArray_UINT8, 1, 1);
- if (!codes) 
- throw Py::ValueError("Invalid codes array.");
-
 unsigned fillSize = 0;
 if (face.first) {
 theRasterizer->add_path(marker_path_curve);
@@ -681,53 +679,29 @@
 rendererBase->clip_box(l, height-(b+h),l+w, height-b);
 }
 
- size_t next_vertex_stride = vertices->strides[0];
- size_t next_axis_stride = vertices->strides[1];
- size_t code_stride = codes->strides[0];
-
- const char* vertex_i = vertices->data;
- const char* code_i = codes->data;
- const char* vertex_end = vertex_i + (vertices->dimensions[0] * vertices->strides[0]);
-
- size_t N = codes->dimensions[0];
 double x, y;
 
 agg::serialized_scanlines_adaptor_aa8 sa;
 agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl;
 
- for (size_t i=0; i < N; i++) {
- size_t num_vertices = NUM_VERTICES[(int)(*code_i)];
- if (num_vertices) {
-	for (size_t j=0; j<num_vertices; ++j)
-	 GET_NEXT_VERTEX(x, y);
-	if (*code_i == STOP || *code_i == CLOSEPOLY)
-	 continue;
-
-	trans.transform(&x, &y);
-	
-	if (face.first) {
-	 //render the fill
-	 sa.init(fillCache, fillSize, x, y);
-	 rendererAA->color(face.second);
-	 agg::render_scanlines(sa, sl, *rendererAA);
-	}
-
-	//render the stroke
-	sa.init(strokeCache, strokeSize, x, y);
-	rendererAA->color(gc.color);
+ while (path_transformed.vertex(&x, &y) != agg::path_cmd_stop) {
+ if (face.first) {
+	//render the fill
+	sa.init(fillCache, fillSize, x, y);
+	rendererAA->color(face.second);
 	agg::render_scanlines(sa, sl, *rendererAA);
 }
- code_i += code_stride;
+ 
+ //render the stroke
+ sa.init(strokeCache, strokeSize, x, y);
+ rendererAA->color(gc.color);
+ agg::render_scanlines(sa, sl, *rendererAA);
 }
 } catch(...) {
- Py_XDECREF(vertices);
- Py_XDECREF(codes);
 delete[] fillCache;
 delete[] strokeCache;
 }
 
- Py_XDECREF(vertices);
- Py_XDECREF(codes);
 delete [] fillCache;
 delete [] strokeCache;
 
@@ -888,98 +862,12 @@
 
 }
 
-Py::Object
-RendererAgg::convert_to_native_path(const Py::Tuple& args) {
- _VERBOSE("RendererAgg::draw_image");
- args.verify_length(1);
- 
- Py::Object path = args[0];
 
- return Py::asObject(new PathAgg(path));
-}
-
- 
-PathAgg::PathAgg(const Py::Object& path_obj) : curvy(false) {
- Py::Object vertices_obj = path_obj.getAttr("vertices");
- Py::Object codes_obj = path_obj.getAttr("codes");
- 
- PyArrayObject* vertices = NULL;
- PyArrayObject* codes = NULL;
-
- try {
- vertices = (PyArrayObject*)PyArray_ContiguousFromObject
- (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2);
- if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2)
- throw Py::ValueError("Invalid vertices array.");
- codes = (PyArrayObject*)PyArray_ContiguousFromObject
- (codes_obj.ptr(), PyArray_UINT8, 1, 1);
- if (!codes) 
- throw Py::ValueError("Invalid codes array.");
-
- size_t next_vertex_stride = vertices->strides[0];
- size_t next_axis_stride = vertices->strides[1];
- size_t code_stride = codes->strides[0];
-
- const char* vertex_i = vertices->data;
- const char* code_i = codes->data;
- const char* vertex_end = vertex_i + (vertices->dimensions[0] * vertices->strides[0]);
-
- size_t N = codes->dimensions[0];
- double x0, y0, x1, y1, x2, y2;
-
- for (size_t i = 0; i < N; ++i) {
- switch (*(unsigned char*)(code_i)) {
- case STOP:
-	GET_NEXT_VERTEX(x0, y0);
-	_VERBOSE("STOP");
-	// MGDTODO: If this isn't the end, we should raise an error
-	break;
- case MOVETO:
-	GET_NEXT_VERTEX(x0, y0);
-	move_to(x0, y0);
-	_VERBOSE("MOVETO");
-	break;
- case LINETO:
-	GET_NEXT_VERTEX(x0, y0);
-	line_to(x0, y0);
-	_VERBOSE("LINETO");
-	break;
- case CURVE3:
-	GET_NEXT_VERTEX(x0, y0);
-	GET_NEXT_VERTEX(x1, y1);
-	curve3(x0, y0, x1, y1);
-	curvy = true;
-	_VERBOSE("CURVE3");
-	break;
- case CURVE4:
-	GET_NEXT_VERTEX(x0, y0);
-	GET_NEXT_VERTEX(x1, y1);
-	GET_NEXT_VERTEX(x2, y2);
-	curve4(x0, y0, x1, y1, x2, y2);
-	curvy = true;
-	_VERBOSE("CURVE4");
-	break;
- case CLOSEPOLY:
-	close_polygon();
-	GET_NEXT_VERTEX(x0, y0);
-	_VERBOSE("CLOSEPOLY");
-	break;
- }
- }
- } catch(...) {
- Py_XDECREF(vertices);
- Py_XDECREF(codes);
- throw;
- }
-
- Py_XDECREF(vertices);
- Py_XDECREF(codes);
-}
-
 Py::Object
 RendererAgg::draw_path(const Py::Tuple& args) {
 typedef agg::conv_transform<PathIterator> transformed_path_t;
- typedef agg::conv_curve<transformed_path_t> curve_t;
+ typedef conv_quantize<transformed_path_t> quantize_t;
+ typedef agg::conv_curve<quantize_t> curve_t;
 typedef agg::conv_stroke<curve_t> stroke_t;
 typedef agg::conv_dash<curve_t> dash_t;
 typedef agg::conv_stroke<dash_t> stroke_dash_t;
@@ -991,61 +879,59 @@
 theRasterizer->reset_clipping();
 
 _VERBOSE("RendererAgg::draw_path");
- args.verify_length(4);
+ args.verify_length(3, 4);
 
- GCAgg gc = GCAgg(args[0], dpi);
+ Py::Object gc_obj = args[0];
 Py::Object path_obj = args[1];
-// if (!PathAgg::check(path_obj))
-// throw Py::TypeError("Native path object is not of correct type");
- // PathAgg* path = static_cast<PathAgg*>(path_obj.ptr());
 PathIterator path(path_obj);
 
 agg::trans_affine trans = py_to_agg_transformation_matrix(args[2]);
- facepair_t face = _get_rgba_face(args[3], gc.alpha);
 
 trans *= agg::trans_affine_scaling(1.0, -1.0);
 trans *= agg::trans_affine_translation(0.0, (double)height);
 
- transformed_path_t* tpath = NULL;
- agg::path_storage new_path;
+ bool snap = false;
+ if (path.total_vertices() == 2) {
+ double x0, y0, x1, y1;
+ path.vertex(0, &x0, &y0);
+ trans.transform(&x0, &y0);
+ path.vertex(1, &x1, &y1);
+ trans.transform(&x1, &y1);
+ snap = ((int)x0 == (int)x1) || ((int)y0 == (int)y1);
+ }
 
- bool has_clippath = (gc.clippath != NULL);
+ GCAgg gc = GCAgg(gc_obj, dpi, snap);
+ Py::Object face_obj;
+ if (args.size() == 4)
+ face_obj = args[3];
+ facepair_t face = _get_rgba_face(face_obj, gc.alpha);
 
- if (has_clippath && (gc.clippath != lastclippath || trans != lastclippath_transform)) {
-// rendererBaseAlphaMask->clear(agg::gray8(0, 0));
-// gc.clippath->rewind(0);
-// transformed_path_t transformed_clippath(*(gc.clippath), trans);
-// theRasterizer->add_path(transformed_clippath);
-// rendererAlphaMask->color(agg::gray8(255, 255));
-// agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
-// lastclippath = gc.clippath;
-// lastclippath_transform = trans;
+ bool has_clippath = (gc.clippath.ptr() != Py_None);
+
+ if (has_clippath && 
+ (gc.clippath.ptr() != lastclippath.ptr() || trans != lastclippath_transform)) {
+ PathIterator clippath(gc.clippath);
+ rendererBaseAlphaMask->clear(agg::gray8(0, 0));
+ transformed_path_t transformed_clippath(clippath, trans);
+ agg::conv_curve<transformed_path_t> curved_clippath(transformed_clippath);
+ theRasterizer->add_path(curved_clippath);
+ rendererAlphaMask->color(agg::gray8(255, 255));
+ agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
+ lastclippath = gc.clippath;
+ lastclippath_transform = trans;
 }
 
 try {
 // If this is a straight horizontal or vertical line, quantize to nearest 
 // pixels
-// if (path.total_vertices() == 2) {
-// double x0, y0, x1, y1;
-// path.vertex(0, &x0, &y0);
-// trans.transform(&x0, &y0);
-// path.vertex(1, &x1, &y1);
-// trans.transform(&x1, &y1);
-// if (((int)x0 == (int)x1) || ((int)y0 == (int)y1)) {
-// 	new_path.move_to((int)x0 + 0.5, (int)y0 + 0.5);
-// 	new_path.line_to((int)x1 + 0.5, (int)y1 + 0.5);
-// 	tpath = new transformed_path_t(new_path, agg::trans_affine());
-// }
-// }
 
- if (!tpath) {
- tpath = new transformed_path_t(path, trans);
- }
+ transformed_path_t tpath(path, trans);
+ quantize_t quantized(tpath, snap);
 
 // Benchmarking shows that there is no noticable slowdown to always
 // treating paths as having curved segments. Doing so greatly 
 // simplifies the code
- curve_t curve(*tpath);
+ curve_t curve(quantized);
 
 set_clipbox_rasterizer(gc.cliprect);
 
@@ -1106,12 +992,11 @@
 }
 }
 } catch (...) {
- delete tpath;
+ // MGDTODO: We don't have anything on the heap, so this catch
+ // clause isn't really necessary, but we might again soon...
 throw;
 }
 
- delete tpath;
-
 return Py::Object();
 }
 
@@ -1446,11 +1331,9 @@
 behaviors().doc("The agg backend extension module");
 
 add_varargs_method("draw_path", &RendererAgg::draw_path,
-		 "draw_path(gc, rgbFace, native_path, transform)\n");
- add_varargs_method("convert_to_native_path", &RendererAgg::convert_to_native_path,
-		 "convert_to_native_path(vertices, codes)\n");
+		 "draw_path(gc, path, transform, rgbFace)\n");
 add_varargs_method("draw_markers", &RendererAgg::draw_markers,
-		 "draw_markers(gc, marker_path, marker_trans, vertices, codes, rgbFace)\n");
+		 "draw_markers(gc, marker_path, marker_trans, path, rgbFace)\n");
 add_varargs_method("draw_text_image", &RendererAgg::draw_text_image,
 		 "draw_text_image(font_image, x, y, r, g, b, a)\n");
 add_varargs_method("draw_image", &RendererAgg::draw_image,
@@ -1476,12 +1359,6 @@
 		 "restore_region(region)");
 }
 
-void PathAgg::init_type()
-{
- behaviors().name("PathAgg");
- behaviors().doc("A native Agg path object");
-}
-
 extern "C"
 DL_EXPORT(void)
 init_backend_agg(void)
Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h	2007年09月20日 13:57:32 UTC (rev 3864)
+++ branches/transforms/src/_backend_agg.h	2007年09月20日 13:57:59 UTC (rev 3865)
@@ -105,20 +105,6 @@
 };
 };
 
-// A completely opaque data type used only to pass native path
-// data to/from Python. Python can't do anything with the data
-// other than create and then use it.
-class PathAgg : 
- public agg::path_storage, 
- public Py::PythonExtension<PathAgg> {
-public:
- static void init_type(void);
-
- PathAgg(const Py::Object& path_obj);
-
- bool curvy;
-};
-
 class GCAgg {
 public:
 GCAgg(const Py::Object& gc, double dpi, bool snapto=false);
@@ -126,7 +112,6 @@
 ~GCAgg() {
 delete [] dasha;
 delete [] cliprect;
- Py_XINCREF(clippath);
 }
 
 double dpi;
@@ -142,7 +127,7 @@
 agg::rgba color;
 
 double *cliprect;
- PathAgg *clippath;
+ Py::Object clippath;
 //dashes
 size_t Ndash;
 double dashOffset;
@@ -183,7 +168,6 @@
 Py::Object draw_text_image(const Py::Tuple & args);
 Py::Object draw_image(const Py::Tuple & args);
 Py::Object draw_path(const Py::Tuple & args);
- Py::Object convert_to_native_path(const Py::Tuple & args);
 
 Py::Object write_rgba(const Py::Tuple & args);
 Py::Object write_png(const Py::Tuple & args);
@@ -240,7 +224,7 @@
 void set_clipbox_rasterizer( double *cliprect);
 
 private:
- PathAgg *lastclippath;
+ Py::Object lastclippath;
 agg::trans_affine lastclippath_transform;
 };
 
@@ -253,7 +237,6 @@
 : Py::ExtensionModule<_backend_agg_module>( "_backend_agg" )
 {
 RendererAgg::init_type();
- PathAgg::init_type();
 
 add_keyword_method("RendererAgg", &_backend_agg_module::new_renderer,
 		 "RendererAgg(width, height, dpi)");
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月20日 13:57:33
Revision: 3864
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3864&view=rev
Author: mdboom
Date: 2007年09月20日 06:57:32 -0700 (2007年9月20日)
Log Message:
-----------
Simplification of marker paths.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/lines.py
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月20日 13:50:27 UTC (rev 3863)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月20日 13:57:32 UTC (rev 3864)
@@ -815,7 +815,7 @@
 			 path, self.get_transform())
 
 		
- _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]])
+ _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]], closed=False)
 def _draw_tickleft(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(-offset, 1.0)
@@ -830,7 +830,7 @@
 			 path, self.get_transform())
 
 	
- _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]])
+ _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]], closed=False)
 def _draw_tickup(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(1.0, offset)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jd...@us...> - 2007年09月20日 13:50:34
Revision: 3863
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3863&view=rev
Author: jdh2358
Date: 2007年09月20日 06:50:27 -0700 (2007年9月20日)
Log Message:
-----------
added gradient bar example
Added Paths:
-----------
 trunk/matplotlib/examples/gradient_bar.py
Added: trunk/matplotlib/examples/gradient_bar.py
===================================================================
--- trunk/matplotlib/examples/gradient_bar.py	 (rev 0)
+++ trunk/matplotlib/examples/gradient_bar.py	2007年09月20日 13:50:27 UTC (rev 3863)
@@ -0,0 +1,26 @@
+from pylab import figure, show, nx, cm
+
+def gbar(ax, x, y, width=0.5, bottom=0):
+ X = [[.6, .6],[.7,.7]]
+ for left,top in zip(x, y):
+ right = left+width
+ ax.imshow(X, interpolation='bicubic', cmap=cm.Blues,
+ extent=(left, right, bottom, top), alpha=1)
+
+fig = figure()
+
+xmin, xmax = xlim = 0,10
+ymin, ymax = ylim = 0,1
+ax = fig.add_subplot(111, xlim=xlim, ylim=ylim,
+ autoscale_on=False)
+X = [[.6, .6],[.7,.7]]
+
+ax.imshow(X, interpolation='bicubic', cmap=cm.copper,
+ extent=(xmin, xmax, ymin, ymax), alpha=1)
+
+N = 10
+x = nx.arange(N)+0.25
+y = nx.mlab.rand(N)
+gbar(ax, x, y, width=0.7)
+ax.set_aspect('normal')
+show()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3862
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3862&view=rev
Author: mdboom
Date: 2007年09月20日 05:40:41 -0700 (2007年9月20日)
Log Message:
-----------
Removing debugging output in last commit.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/font_manager.py
Modified: trunk/matplotlib/lib/matplotlib/font_manager.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/font_manager.py	2007年09月20日 12:31:26 UTC (rev 3861)
+++ trunk/matplotlib/lib/matplotlib/font_manager.py	2007年09月20日 12:40:41 UTC (rev 3862)
@@ -773,7 +773,6 @@
 else:
 if is_string_like(size):
 parent_size = fontManager.get_default_size()
- print "parent_size", parent_size, size
 scaling = font_scalings.get(size)
 if scaling is not None:
 size = parent_size * scaling
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 3861
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3861&view=rev
Author: mdboom
Date: 2007年09月20日 05:31:26 -0700 (2007年9月20日)
Log Message:
-----------
Fix font.size from being saved in the fontManager.cache
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/font_manager.py
Modified: trunk/matplotlib/lib/matplotlib/font_manager.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/font_manager.py	2007年09月19日 19:48:17 UTC (rev 3860)
+++ trunk/matplotlib/lib/matplotlib/font_manager.py	2007年09月20日 12:31:26 UTC (rev 3861)
@@ -773,6 +773,7 @@
 else:
 if is_string_like(size):
 parent_size = fontManager.get_default_size()
+ print "parent_size", parent_size, size
 scaling = font_scalings.get(size)
 if scaling is not None:
 size = parent_size * scaling
@@ -843,10 +844,9 @@
 """
 
 def __init__(self, size=None, weight='normal'):
- if not size : size = rcParams['font.size']
- self.__default_size = size
 self.__default_weight = weight
-
+ self.default_size = size
+ 
 paths = [os.path.join(rcParams['datapath'],'fonts','ttf'),
 os.path.join(rcParams['datapath'],'fonts','afm')]
 
@@ -899,7 +899,9 @@
 
 def get_default_size(self):
 "Return the default font size."
- return self.__default_size
+ if self.default_size is None:
+ return rcParams['font.size']
+ return self.default_size
 
 def set_default_weight(self, weight):
 "Set the default font weight. The initial value is 'normal'."
@@ -1085,6 +1087,7 @@
 
 try:
 fontManager = pickle_load(_fmcache)
+ fontManager.default_size = None
 verbose.report("Using fontManager instance from %s" % _fmcache)
 except:
 _rebuild()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月19日 19:48:22
Revision: 3860
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3860&view=rev
Author: mdboom
Date: 2007年09月19日 12:48:17 -0700 (2007年9月19日)
Log Message:
-----------
Use iterator rather than caching approach for paths
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月19日 19:46:34 UTC (rev 3859)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月19日 19:48:17 UTC (rev 3860)
@@ -112,8 +112,7 @@
 self.dpi = dpi
 self.width = width
 self.height = height
- if __debug__: verbose.report('RendererAgg.__init__ width=%s, \
- height=%s'%(width, height), 'debug-annoying')
+ if __debug__: verbose.report('RendererAgg.__init__ width=%s, height=%s'%(width, height), 'debug-annoying')
 self._renderer = _RendererAgg(int(width), int(height), dpi,
 				 debug=False)
 if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月19日 19:46:34 UTC (rev 3859)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月19日 19:48:17 UTC (rev 3860)
@@ -87,15 +87,17 @@
 inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, 
 			 double& x, double& y,
 			 size_t next_vertex_stride, 
-			 size_t next_axis_stride) {
+			 size_t next_axis_stride,
+			 const char* & code_i, size_t code_stride) {
 if (vertex_i + next_axis_stride >= vertex_end)
 throw Py::ValueError("Error parsing path. Read past end of vertices");
 x = *(double*)vertex_i;
 y = *(double*)(vertex_i + next_axis_stride);
 vertex_i += next_vertex_stride;
+ code_i += code_stride;
 }
 
-#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride)
+#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride, code_i, code_stride)
 
 Py::Object BufferRegion::to_string(const Py::Tuple &args) {
 
@@ -103,7 +105,71 @@
 return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true);
 }
 
+class PathIterator {
+ PyArrayObject* vertices;
+ PyArrayObject* codes;
+ size_t m_iterator;
+ size_t m_total_vertices;
 
+public:
+ PathIterator(const Py::Object& path_obj) :
+ vertices(NULL), codes(NULL), m_iterator(0) {
+ Py::Object vertices_obj = path_obj.getAttr("vertices");
+ Py::Object codes_obj = path_obj.getAttr("codes");
+ 
+ vertices = (PyArrayObject*)PyArray_ContiguousFromObject
+ (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2);
+ if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2)
+ throw Py::ValueError("Invalid vertices array.");
+ codes = (PyArrayObject*)PyArray_ContiguousFromObject
+ (codes_obj.ptr(), PyArray_UINT8, 1, 1);
+ if (!codes) 
+ throw Py::ValueError("Invalid codes array.");
+ 
+ if (codes->dimensions[0] != vertices->dimensions[0])
+ throw Py::ValueError("Vertices and codes array are not the same length.");
+
+ m_total_vertices = codes->dimensions[0];
+ }
+
+ ~PathIterator() {
+ Py_XDECREF(vertices);
+ Py_XDECREF(codes);
+ }
+
+ static const char code_map[];
+
+ inline unsigned vertex(unsigned idx, double* x, double* y) {
+ if (idx > m_total_vertices)
+ throw Py::RuntimeError("Requested vertex past end");
+ double* pv = (double*)(vertices->data + (idx * vertices->strides[0]));
+ *x = *pv++;
+ *y = *pv;
+ // MGDTODO: Range check
+ return code_map[(unsigned int)*(codes->data + (idx * codes->strides[0]))];
+ }
+
+ inline unsigned vertex(double* x, double* y) {
+ if(m_iterator >= m_total_vertices) return agg::path_cmd_stop;
+ return vertex(m_iterator++, x, y);
+ }
+
+ inline void rewind(unsigned path_id) {
+ m_iterator = path_id;
+ }
+
+ inline unsigned total_vertices() {
+ return m_total_vertices;
+ }
+};
+
+const char PathIterator::code_map[] = {0, 
+				 agg::path_cmd_move_to, 
+				 agg::path_cmd_line_to, 
+				 agg::path_cmd_curve3,
+				 agg::path_cmd_curve4,
+				 agg::path_cmd_end_poly | agg::path_flags_close};
+
 GCAgg::GCAgg(const Py::Object &gc, double dpi, bool snapto) :
 dpi(dpi), snapto(snapto), isaa(true), linewidth(1.0), alpha(1.0),
 cliprect(NULL), clippath(NULL), 
@@ -634,7 +700,7 @@
 if (num_vertices) {
 	for (size_t j=0; j<num_vertices; ++j)
 	 GET_NEXT_VERTEX(x, y);
-	if (code_i == IGNORE)
+	if (*code_i == STOP || *code_i == CLOSEPOLY)
 	 continue;
 
 	trans.transform(&x, &y);
@@ -863,9 +929,10 @@
 
 for (size_t i = 0; i < N; ++i) {
 switch (*(unsigned char*)(code_i)) {
- case IGNORE:
+ case STOP:
 	GET_NEXT_VERTEX(x0, y0);
-	_VERBOSE("IGNORE");
+	_VERBOSE("STOP");
+	// MGDTODO: If this isn't the end, we should raise an error
 	break;
 case MOVETO:
 	GET_NEXT_VERTEX(x0, y0);
@@ -894,10 +961,10 @@
 	break;
 case CLOSEPOLY:
 	close_polygon();
+	GET_NEXT_VERTEX(x0, y0);
 	_VERBOSE("CLOSEPOLY");
 	break;
 }
- code_i += code_stride;
 }
 } catch(...) {
 Py_XDECREF(vertices);
@@ -911,7 +978,7 @@
 
 Py::Object
 RendererAgg::draw_path(const Py::Tuple& args) {
- typedef agg::conv_transform<agg::path_storage> transformed_path_t;
+ typedef agg::conv_transform<PathIterator> transformed_path_t;
 typedef agg::conv_curve<transformed_path_t> curve_t;
 typedef agg::conv_stroke<curve_t> stroke_t;
 typedef agg::conv_dash<curve_t> dash_t;
@@ -928,9 +995,11 @@
 
 GCAgg gc = GCAgg(args[0], dpi);
 Py::Object path_obj = args[1];
- if (!PathAgg::check(path_obj))
- throw Py::TypeError("Native path object is not of correct type");
- PathAgg* path = static_cast<PathAgg*>(path_obj.ptr());
+// if (!PathAgg::check(path_obj))
+// throw Py::TypeError("Native path object is not of correct type");
+ // PathAgg* path = static_cast<PathAgg*>(path_obj.ptr());
+ PathIterator path(path_obj);
+
 agg::trans_affine trans = py_to_agg_transformation_matrix(args[2]);
 facepair_t face = _get_rgba_face(args[3], gc.alpha);
 
@@ -943,34 +1012,34 @@
 bool has_clippath = (gc.clippath != NULL);
 
 if (has_clippath && (gc.clippath != lastclippath || trans != lastclippath_transform)) {
- rendererBaseAlphaMask->clear(agg::gray8(0, 0));
- gc.clippath->rewind(0);
- transformed_path_t transformed_clippath(*(gc.clippath), trans);
- theRasterizer->add_path(transformed_clippath);
- rendererAlphaMask->color(agg::gray8(255, 255));
- agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
- lastclippath = gc.clippath;
- lastclippath_transform = trans;
+// rendererBaseAlphaMask->clear(agg::gray8(0, 0));
+// gc.clippath->rewind(0);
+// transformed_path_t transformed_clippath(*(gc.clippath), trans);
+// theRasterizer->add_path(transformed_clippath);
+// rendererAlphaMask->color(agg::gray8(255, 255));
+// agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
+// lastclippath = gc.clippath;
+// lastclippath_transform = trans;
 }
 
 try {
 // If this is a straight horizontal or vertical line, quantize to nearest 
 // pixels
- if (path->total_vertices() == 2) {
- double x0, y0, x1, y1;
- path->vertex(0, &x0, &y0);
- trans.transform(&x0, &y0);
- path->vertex(1, &x1, &y1);
- trans.transform(&x1, &y1);
- if (((int)x0 == (int)x1) || ((int)y0 == (int)y1)) {
-	new_path.move_to((int)x0 + 0.5, (int)y0 + 0.5);
-	new_path.line_to((int)x1 + 0.5, (int)y1 + 0.5);
-	tpath = new transformed_path_t(new_path, agg::trans_affine());
- }
- }
+// if (path.total_vertices() == 2) {
+// double x0, y0, x1, y1;
+// path.vertex(0, &x0, &y0);
+// trans.transform(&x0, &y0);
+// path.vertex(1, &x1, &y1);
+// trans.transform(&x1, &y1);
+// if (((int)x0 == (int)x1) || ((int)y0 == (int)y1)) {
+// 	new_path.move_to((int)x0 + 0.5, (int)y0 + 0.5);
+// 	new_path.line_to((int)x1 + 0.5, (int)y1 + 0.5);
+// 	tpath = new transformed_path_t(new_path, agg::trans_affine());
+// }
+// }
 
 if (!tpath) {
- tpath = new transformed_path_t(*path, trans);
+ tpath = new transformed_path_t(path, trans);
 }
 
 // Benchmarking shows that there is no noticable slowdown to always
Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h	2007年09月19日 19:46:34 UTC (rev 3859)
+++ branches/transforms/src/_backend_agg.h	2007年09月19日 19:48:17 UTC (rev 3860)
@@ -40,14 +40,14 @@
 #include "agg_vcgen_markers_term.h"
 
 // These are copied directly from path.py, and must be kept in sync
-#define IGNORE 0
+#define STOP 0
 #define MOVETO 1
 #define LINETO 2
 #define CURVE3 3
 #define CURVE4 4
 #define CLOSEPOLY 5
 
-const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 0 };
+const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 1 };
 
 typedef agg::pixfmt_rgba32 pixfmt;
 typedef agg::renderer_base<pixfmt> renderer_base;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月19日 19:46:41
Revision: 3859
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3859&view=rev
Author: mdboom
Date: 2007年09月19日 12:46:34 -0700 (2007年9月19日)
Log Message:
-----------
Lots of minor fixes
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/patches.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/pbox.py
 branches/transforms/lib/matplotlib/text.py
 branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -252,12 +252,9 @@
 if not is_numlike(self.pickradius):
 raise ValueError,"pick radius should be a distance"
 
- if self._newstyle:
- # transform in backend
- x = self._x
- y = self._y
- else:
- x, y = self._get_plottable()
+ # transform in backend
+ x = self._x
+ y = self._y
 if len(x)==0: return False,{}
 
 xt, yt = self.get_transform().numerix_x_y(x, y)
@@ -337,7 +334,6 @@
 
 ACCEPTS: (npy.array xdata, npy.array ydata)
 """
-
 if len(args)==1:
 x, y = args[0]
 else:
@@ -347,8 +343,9 @@
 self._yorig = y
 self.recache()
 
+ # MGDTODO: Masked data arrays are broken
 _masked_array_to_path_code_mapping = npy.array(
- [Path.LINETO, Path.IGNORE, Path.MOVETO], Path.code_type)
+ [Path.LINETO, Path.MOVETO, Path.MOVETO], Path.code_type)
 def recache(self):
 #if self.axes is None: print 'recache no axes'
 #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
@@ -387,18 +384,18 @@
 # MGDTODO: If _draw_steps is removed, remove the following line also
 self._step_path = None
 
-
 def _is_sorted(self, x):
 "return true if x is sorted"
 if len(x)<2: return 1
 return npy.alltrue(x[1:]-x[0:-1]>=0)
 
+ # MGDTODO: Remove me (seems to be used for old-style interface only)
 def _get_plottable(self):
 # If log scale is set, only pos data will be returned
 
 x, y = self._x, self._y
 
-	# MGDTODO: Deal with the log scale here
+	# MGDTODO: (log-scaling)
 	
 # try: logx = self.get_transform().get_funcx().get_type()==LOG10
 # except RuntimeError: logx = False # non-separable
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/patches.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -319,8 +319,6 @@
 return str(self.__class__).split('.')[-1] \
 + "(%g,%g;%gx%g)"%(self.xy[0],self.xy[1],self.width,self.height)
 
- # MGDTODO: Perhaps pass in a Bbox here instead, then the updates will
- # happen automatically (without needing to call set_x etc.
 def __init__(self, xy, width, height, **kwargs):
 """
 xy is an x,y tuple lower, left
@@ -459,17 +457,14 @@
 
 def __init__(self, xy, **kwargs):
 """
- xy is a sequence of (x,y) 2 tuples
+ xy is a numpy array with shape Nx2
 
 Valid kwargs are:
 %(Patch)s
 See Patch documentation for additional kwargs
 """
-	# MGDTODO: This should encourage the use of numpy arrays of shape Nx2
 Patch.__init__(self, **kwargs)
- if not isinstance(xy, list):
- xy = list(xy)
-	self._path = Path(xy, closed=False)
+	self._path = Path(xy, closed=True)
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
 def get_verts(self):
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -1,15 +1,13 @@
 import numpy as npy
 
-DEBUG = True
-
 class Path(object):
 # Path codes
- IGNORE = 0 # 1 vertex
+ STOP = 0 # 1 vertex
 MOVETO = 1 # 1 vertex
 LINETO = 2 # 1 vertex
 CURVE3 = 3 # 2 vertices
 CURVE4 = 4 # 3 vertices
- CLOSEPOLY = 5
+ CLOSEPOLY = 5 # 1 vertex
 ###
 # MGDTODO: I'm not sure these are supported by PS/PDF/SVG,
 # so if they don't, we probably shouldn't
@@ -18,38 +16,36 @@
 UBSPLINE = 8
 ####
 
- NUM_VERTICES = [1, 1, 1, 2, 3, 0]
+ NUM_VERTICES = [1, 1, 1, 2, 3, 1]
 
 code_type = npy.uint8
 
 def __init__(self, vertices, codes=None, closed=True):
-	self._vertices = npy.asarray(vertices, npy.float_)
-	assert self._vertices.ndim == 2
-	assert self._vertices.shape[1] == 2
-
+ vertices = npy.asarray(vertices, npy.float_)
+	assert vertices.ndim == 2
+	assert vertices.shape[1] == 2
+ 
 	if codes is None:
 	 if closed:
 		codes = self.LINETO * npy.ones(
-		 self._vertices.shape[0] + 1, self.code_type)
+		 vertices.shape[0] + 1, self.code_type)
 		codes[0] = self.MOVETO
-		codes[-1] = self.CLOSEPOLY
+ codes[-1] = self.CLOSEPOLY
+ vertices = npy.concatenate((vertices, [[0.0, 0.0]]))
 	 else:
 		codes = self.LINETO * npy.ones(
-		 self._vertices.shape[0], self.code_type)
+		 vertices.shape[0], self.code_type)
 		codes[0] = self.MOVETO
 else:
 	 codes = npy.asarray(codes, self.code_type)
-	self._codes = codes
-	 
+ assert codes.ndim == 1
+ assert len(codes) == len(vertices)
+
+ self._codes = codes
+	self._vertices = vertices
+ 
 	assert self._codes.ndim == 1
 
-	if DEBUG:
-	 i = 0
-	 NUM_VERTICES = self.NUM_VERTICES
-	 for code in codes:
-		i += NUM_VERTICES[code]
-	 assert i == len(self.vertices)
-
 def __repr__(self):
 	return "Path(%s, %s)" % (self.vertices, self.codes)
 	 
@@ -66,11 +62,13 @@
 	NUM_VERTICES = self.NUM_VERTICES
 	vertices = self.vertices
 	for code in self.codes:
-	 num_vertices = NUM_VERTICES[code]
-	 if num_vertices >= 1:
-		i += num_vertices - 1
-		yield vertices[i]
-		i += 1
+ if code == self.CLOSEPOLY:
+ i += 1
+ else:
+ num_vertices = NUM_VERTICES[code]
+ i += num_vertices - 1
+ yield vertices[i]
+ i += 1
 
 _unit_rectangle = None
 #@classmethod
@@ -118,16 +116,18 @@
 		 
 		 [-offset, -1.0],
 		 [-1.0, -offset],
-		 [-1.0, 0.0]],
-		npy.float_)
-	 codes = npy.array(
-		[cls.MOVETO,
-		 cls.CURVE4,
-		 cls.CURVE4,
-		 cls.CURVE4,
-		 cls.CURVE4,
-		 cls.CLOSEPOLY],
-		cls.code_type)
+		 [-1.0, 0.0],
+
+ [-1.0, 0.0]],
+ npy.float_)
+
+ codes = cls.CURVE4 + npy.ones((len(vertices)))
+	 codes[0] = cls.MOVETO
+ codes[-1] = cls.CLOSEPOLY
+
 	 cls._unit_circle = Path(vertices, codes)
 	return cls._unit_circle
 unit_circle = classmethod(unit_circle)
+
+# MGDTODO: Add a transformed path that would automatically invalidate
+# itself when its transform changes
Modified: branches/transforms/lib/matplotlib/pbox.py
===================================================================
--- branches/transforms/lib/matplotlib/pbox.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/pbox.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -1,5 +1,3 @@
-# MGDTODO: Just included verbatim for now
-
 class PBox(list):
 '''
 A left-bottom-width-height (lbwh) specification of a bounding box,
Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/text.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -231,7 +231,7 @@
 
 # now rotate the bbox
 
- cornersRotated = M(cornersHoriz)
+ cornersRotated = M.transform(cornersHoriz)
 
 txs = cornersRotated[:, 0]
 tys = cornersRotated[:, 1]
@@ -269,7 +269,7 @@
 	
 
 # now rotate the positions around the first x,y position
- xys = M(offsetLayout)
+ xys = M.transform(offsetLayout)
 	tx = xys[:, 0]
 	ty = xys[:, 1]
 	tx += offsetx
@@ -277,7 +277,7 @@
 
 # now inverse transform back to data coords
 	inverse_transform = self.get_transform().inverted()
- xys = inverse_transform(xys)
+ xys = inverse_transform.transform(xys)
 
 xs, ys = zip(*xys)
 
@@ -407,7 +407,7 @@
 return (x, y, self._text, self._color,
 self._verticalalignment, self._horizontalalignment,
 hash(self._fontproperties), self._rotation,
- self.get_transform().to_values(),
+ self.get_transform(),
 )
 
 def get_text(self):
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月19日 16:18:51 UTC (rev 3858)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月19日 19:46:34 UTC (rev 3859)
@@ -32,7 +32,8 @@
 for child in children:
 getattr(self, child)._parents.add(self)
 self._children = children
- 
+
+ 
 class BboxBase(TransformNode):
 '''
 This is the read-only part of a bounding-box
@@ -293,6 +294,7 @@
 return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
 union = staticmethod(union)
 
+ 
 class TransformedBbox(BboxBase):
 def __init__(self, bbox, transform):
 assert isinstance(bbox, Bbox)
@@ -313,16 +315,20 @@
 
 def get_points(self):
 if self._points is None:
- self._points = self.transform(self.bbox.get_points())
+ self._points = self.transform.transform(self.bbox.get_points())
 return self._points
+
 
 class Transform(TransformNode):
 def __init__(self):
 TransformNode.__init__(self)
 
- def __call__(self, points):
+ def transform(self, points):
 raise NotImplementedError()
 
+ def transform_without_affine(self, points):
+ return self.transform(points), IDENTITY
+ 
 def __add__(self, other):
 if isinstance(other, Transform):
 return composite_transform_factory(self, other)
@@ -336,7 +342,7 @@
 "Can not add Transform to object of type '%s'" % type(other))
 
 def transform_point(self, point):
- return self.__call__(npy.asarray([point]))[0]
+ return self.transform(npy.asarray([point]))[0]
 
 def has_inverse(self):
 raise NotImplementedError()
@@ -350,6 +356,7 @@
 def is_affine(self):
 return False
 
+ 
 class Affine2DBase(Transform):
 input_dims = 2
 output_dims = 2
@@ -390,7 +397,7 @@
 def get_matrix(self):
 raise NotImplementedError()
 
- def __call__(self, points):
+ def transform(self, points):
 """
 Applies the transformation to an array of 2D points and
 returns the result.
@@ -414,6 +421,11 @@
 points = npy.dot(mtx[0:2, 0:2], points)
 points = points + mtx[0:2, 2:]
 return points.transpose()
+
+ def transform_without_affine(self, points):
+ # MGDTODO: Should we copy the points here? I'd like to avoid it,
+ # if possible
+ return points, self
 
 def inverted(self):
 if self._inverted is None:
@@ -430,9 +442,6 @@
 
 
 class Affine2D(Affine2DBase):
- input_dims = 2
- output_dims = 2
- 
 def __init__(self, matrix = None):
 """
 Initialize an Affine transform from a 3x3 numpy float array.
@@ -535,40 +544,82 @@
 
 def is_affine(self):
 return True
+
+IDENTITY = Affine2D()
 
 class BlendedGenericTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+
 def __init__(self, x_transform, y_transform):
 	# Here we ask: "Does it blend?"
 assert x_transform.is_separable()
 assert y_transform.is_separable()
-
+ assert x_transform.input_dims == x_transform.output_dims == 2
+ assert y_transform.input_dims == y_transform.output_dims == 2
+ 
 Transform.__init__(self)
 self._x = x_transform
 self._y = y_transform
 self.set_children(['_x', '_y'])
 
- def __call__(self, points):
- if self._x == self._y:
+ def transform(self, points):
+ # MGDTODO: Optimize the case where one of these is
+ # an affine
+ x = self._x
+ y = self._y
+ if x == y and x.input_dims == 2:
 return self._x(points)
- 
- x_points = self._x(points)
- y_points = self._y(points)
- # This works because we already know the transforms are
- # separable
- return npy.hstack((x_points[:, 0:1], y_points[:, 1:2]))
 
-# def set_x_transform(self, x_transform):
-# self.replace_child(0, x_transform)
+ if x.input_dims == 2:
+ x_points = x.transform(points)[:, 0]
+ else:
+ x_points = x.transform(points[:, 0])
 
-# def set_y_transform(self, y_transform):
-# self.replace_child(1, y_transform)
+ if y.input_dims == 2:
+ y_points = y.transform(points)[:, 1]
+ else:
+ y_points = y.transform(points[:, 1])
 
+ return npy.vstack((x_points, y_points)).transpose()
+
+ def inverted(self):
+ return BlendedGenericTransform(self._x.inverted(), self._y.inverted())
 
-class BlendedAffine2D(Affine2DBase, BlendedGenericTransform):
+ def is_separable(self):
+ return True
+ 
+ 
+class BlendedSeparableTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+
 def __init__(self, x_transform, y_transform):
+	# Here we ask: "Does it blend?"
+ assert x_transform.is_separable()
+ assert y_transform.is_separable()
+ assert x_transform.input_dims == x.transform.output_dims == 1
+ assert y_transform.input_dims == y.transform.output_dims == 1
+ 
+ Transform.__init__(self)
+ self._x = x_transform
+ self._y = y_transform
+ self.set_children(['_x', '_y'])
+
+ def transform(self, points):
+ x_points = self._x(points[:, 0])
+ y_points = self._y(points[:, 1])
+ return npy.vstack((x_points[:, 0:1], y_points[:, 1:2])).transpose()
+ 
+ 
+class BlendedAffine2D(Affine2DBase, Transform):
+ def __init__(self, x_transform, y_transform):
 assert x_transform.is_affine()
 assert y_transform.is_affine()
- BlendedGenericTransform.__init__(self, x_transform, y_transform)
+ Transform.__init__(self)
+ self._x = x_transform
+ self._y = y_transform
+ self.set_children(['_x', '_y'])
 
 Affine2DBase.__init__(self)
 self._mtx = None
@@ -597,12 +648,14 @@
 # c to zero.
 self._mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
 return self._mtx
- 
+
+ 
 def blended_transform_factory(x_transform, y_transform):
 if x_transform.is_affine() and y_transform.is_affine():
 return BlendedAffine2D(x_transform, y_transform)
 return BlendedGenericTransform(x_transform, y_transform)
 
+
 class CompositeGenericTransform(Transform):
 def __init__(self, a, b):
 assert a.output_dims == b.input_dims
@@ -614,9 +667,17 @@
 self._b = b
 self.set_children(['_a', '_b'])
 
- def __call__(self, points):
- return self._b(self._a(points))
+ def transform(self, points):
+ return self._b.transform(self._a.transform(points))
+
+ def inverted(self):
+ return CompositeGenericTransform(self._b.inverted(), self._a.inverted())
 
+ def is_separable(self):
+ return True
+ return self._a.is_separable() and self._b.is_separable()
+
+ 
 class CompositeAffine2D(Affine2DBase):
 def __init__(self, a, b):
 assert a.is_affine()
@@ -643,11 +704,32 @@
 self._b.get_matrix())
 return self._mtx
 
+ 
 def composite_transform_factory(a, b):
 if a.is_affine() and b.is_affine():
 return CompositeAffine2D(a, b)
 return CompositeGenericTransform(a, b)
+
+
+class LogTransform(Transform):
+ input_dims = 1
+ output_dims = 1
 
+ def transform(self, a):
+ m = npy.ma.masked_where(a < 0, a)
+ return npy.log10(m)
+
+
+class TestLogTransform(Transform):
+ input_dims = 2
+ output_dims = 2
+ def transform(self, xy):
+ return xy * 2
+
+ def inverted(self):
+ return self
+
+ 
 class BboxTransform(Affine2DBase):
 def __init__(self, boxin, boxout):
 assert isinstance(boxin, BboxBase)
@@ -688,6 +770,7 @@
 self._mtx = affine._mtx
 return self._mtx
 
+ 
 def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
 '''
 Ensure the endpoints of a range are not too close together.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月19日 16:18:56
Revision: 3858
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3858&view=rev
Author: mdboom
Date: 2007年09月19日 09:18:51 -0700 (2007年9月19日)
Log Message:
-----------
Got steps_demo.py working
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/transforms.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -40,7 +40,7 @@
 def _get_cached_native_path(self, path):
 	native_path = self._native_paths.get(path)
 	if native_path is None:
-	 # print "CACHE MISS", path
+	 print "CACHE MISS", path
 	 native_path = self.convert_to_native_path(path)
 	 self._native_paths[path] = native_path
 	return native_path
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -25,53 +25,6 @@
 (TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN,
 CARETLEFT, CARETRIGHT, CARETUP, CARETDOWN) = range(8)
 
-def unmasked_index_ranges(mask, compressed = True):
- '''
- Calculate the good data ranges in a masked 1-D npy.array, based on mask.
-
- Returns Nx2 npy.array with each row the start and stop indices
- for slices of the compressed npy.array corresponding to each of N
- uninterrupted runs of unmasked values.
- If optional argument compressed is False, it returns the
- start and stop indices into the original npy.array, not the
- compressed npy.array.
- Returns None if there are no unmasked values.
-
- Example:
-
- y = ma.array(npy.arange(5), mask = [0,0,1,0,0])
- #ii = unmasked_index_ranges(y.mask())
- ii = unmasked_index_ranges(ma.getmask(y))
- # returns [[0,2,] [2,4,]]
-
- y.compressed().filled()[ii[1,0]:ii[1,1]]
- # returns npy.array [3,4,]
- # (The 'filled()' method converts the masked npy.array to a numerix npy.array.)
-
- #i0, i1 = unmasked_index_ranges(y.mask(), compressed=False)
- i0, i1 = unmasked_index_ranges(ma.getmask(y), compressed=False)
- # returns [[0,3,] [2,5,]]
-
- y.filled()[ii[1,0]:ii[1,1]]
- # returns npy.array [3,4,]
-
- '''
- m = npy.concatenate(((1,), mask, (1,)))
- indices = npy.arange(len(mask) + 1)
- mdif = m[1:] - m[:-1]
- i0 = npy.compress(mdif == -1, indices)
- i1 = npy.compress(mdif == 1, indices)
- assert len(i0) == len(i1)
- if len(i1) == 0:
- return None
- if not compressed:
- return npy.concatenate((i0[:, npy.newaxis], i1[:, npy.newaxis]), axis=1)
- seglengths = i1 - i0
- breakpoints = npy.cumsum(seglengths)
- ic0 = npy.concatenate(((0,), breakpoints[:-1]))
- ic1 = breakpoints
- return npy.concatenate((ic0[:, npy.newaxis], ic1[:, npy.newaxis]), axis=1)
-
 def segment_hits(cx,cy,x,y,radius):
 """Determine if any line segments are within radius of a point. Returns
 the list of line segments that are within that radius.
@@ -117,7 +70,7 @@
 '--' : '_draw_dashed',
 '-.' : '_draw_dash_dot',
 ':' : '_draw_dotted',
- 'steps': '_draw_solid',
+ 'steps': '_draw_steps',
 'None' : '_draw_nothing',
 ' ' : '_draw_nothing',
 '' : '_draw_nothing',
@@ -394,6 +347,8 @@
 self._yorig = y
 self.recache()
 
+ _masked_array_to_path_code_mapping = npy.array(
+ [Path.LINETO, Path.IGNORE, Path.MOVETO], Path.code_type)
 def recache(self):
 #if self.axes is None: print 'recache no axes'
 #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
@@ -411,36 +366,28 @@
 if len(x) != len(y):
 raise RuntimeError('xdata and ydata must be the same length')
 
-	# MGDTODO: Deal with segments
+	self._xy = npy.vstack((npy.asarray(x, npy.float_),
+			 npy.asarray(y, npy.float_))).transpose()
+	self._x = self._xy[:, 0] # just a view
+	self._y = self._xy[:, 1] # just a view
+ self._logcache = None
+
 mx = ma.getmask(x)
 my = ma.getmask(y)
 mask = ma.mask_or(mx, my)
+ codes = None
 if mask is not ma.nomask:
- x = ma.masked_array(x, mask=mask).compressed()
- y = ma.masked_array(y, mask=mask).compressed()
- self._segments = unmasked_index_ranges(mask)
- else:
- self._segments = None
-
-	self._xy = npy.vstack((npy.asarray(x, npy.float_),
-			 npy.asarray(y, npy.float_))).transpose()
-	self._x = self._xy[:, 0]
-	self._y = self._xy[:, 1]
- self._logcache = None
+ m = npy.concatenate(((1,), mask, (1,)))
+ mdif = m[1:] - m[:-1]
+ mdif = npy.maximum((mdif[:-1] * -2), mask)
+ codes = npy.take(
+ self._masked_array_to_path_code_mapping,
+ mdif)
+ self._path = Path(self._xy, codes, closed=False)
+ # MGDTODO: If _draw_steps is removed, remove the following line also
+ self._step_path = None
 
- if self._linestyle == 'steps':
- siz=len(xt)
- if siz<2: return
- xt, yt = self._x, self._y
- xt2=npy.ones((2*siz,), xt.dtype)
- xt2[0:-1:2], xt2[1:-1:2], xt2[-1] = xt, xt[1:], xt[-1]
- yt2=npy.ones((2*siz,), yt.dtype)
- yt2[0:-1:2], yt2[1::2] = yt, yt
- self._path = Path(npy.vstack((xt2, yt2)).transpose(), closed=False)
- else:
- self._path = Path(self._xy, closed=False)
 
-
 def _is_sorted(self, x):
 "return true if x is sorted"
 if len(x)<2: return 1
@@ -507,14 +454,7 @@
 
 funcname = self._lineStyles.get(self._linestyle, '_draw_nothing')
 lineFunc = getattr(self, funcname)
-
-	# MGDTODO: Deal with self._segments
- if self._segments is not None:
- for ii in self._segments:
- lineFunc(renderer, gc, xt[ii[0]:ii[1]], yt[ii[0]:ii[1]])
-
- else:
- lineFunc(renderer, gc, self._path)
+ lineFunc(renderer, gc, self._path)
 	 
 	# MGDTODO: Deal with markers
 if self._marker is not None:
@@ -709,7 +649,29 @@
 def _draw_nothing(self, renderer, gc, path):
 pass
 
- 
+
+ def _draw_steps(self, renderer, gc, path):
+ # We generate the step function path on-the-fly, and then cache it.
+ # The cache may be later invalidated when the data changes
+ # (in self.recache())
+
+ # MGDTODO: Untested -- using pylab.step doesn't actually trigger
+ # this code -- the path is "stepped" before even getting to this
+ # class. Perhaps this should be removed here, since it is not as
+ # powerful as what is in axes.step() anyway.
+ if self._step_path is None:
+ vertices = self._path.vertices
+ codes = self._path.codes
+ siz = len(vertices)
+ if siz<2: return
+ new_vertices = npy.zeros((2*siz, 2), vertices.dtype)
+ new_vertices[0:-1:2, 0], new_vertices[1:-1:2, 0], newvertices[-1, 0] = vertices[:, 0], vertices[1:, 0], vertices[-1, 0]
+ new_vertices[0:-1:2, 1], new_vertices[1::2, 1] = vertices[:, 1], vertices[:, 1]
+ self._step_path = Path(new_vertices, closed=False)
+ gc.set_linestyle('solid')
+	renderer.draw_path(gc, self._step_path, self.get_transform())
+
+ 
 def _draw_solid(self, renderer, gc, path):
 gc.set_linestyle('solid')
 	renderer.draw_path(gc, path, self.get_transform())
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -1,10 +1,10 @@
 import numpy as npy
 
-VALIDATE_PATHS = True
+DEBUG = True
 
 class Path(object):
 # Path codes
- STOP = 0
+ IGNORE = 0 # 1 vertex
 MOVETO = 1 # 1 vertex
 LINETO = 2 # 1 vertex
 CURVE3 = 3 # 2 vertices
@@ -18,7 +18,7 @@
 UBSPLINE = 8
 ####
 
- NUM_VERTICES = [0, 1, 1, 2, 3, 0]
+ NUM_VERTICES = [1, 1, 1, 2, 3, 0]
 
 code_type = npy.uint8
 
@@ -43,7 +43,7 @@
 	 
 	assert self._codes.ndim == 1
 
-	if VALIDATE_PATHS:
+	if DEBUG:
 	 i = 0
 	 NUM_VERTICES = self.NUM_VERTICES
 	 for code in codes:
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -32,18 +32,6 @@
 for child in children:
 getattr(self, child)._parents.add(self)
 self._children = children
-
- # MGDTODO: decide whether we need this in-place updating and
- # remove if not
-# def replace_child(self, index, child):
-# children = self._children
-# getattr(self, children[index])._parents.remove(self)
-# setattr(self, children[index], child)
-# # We have to reset children in case two or more
-# # of the children are the same
-# for child in children:
-# getattr(self, child)._parents.add(self)
-# self.invalidate()
 
 class BboxBase(TransformNode):
 '''
@@ -327,53 +315,7 @@
 if self._points is None:
 self._points = self.transform(self.bbox.get_points())
 return self._points
-
-# MGDTODO: This code probably works, but I don't think it's a good idea
-# (from a code clarity perspective)
-# class BlendedBbox(BboxBase):
-# def __init__(self, bbox_x, bbox_y):
-# assert isinstance(bbox_x, BboxBase)
-# assert isinstance(bbox_y, BboxBase)
-
-# BboxBase.__init__(self)
-# self._x = bbox_x
-# self._y = bbox_y
-# self.set_children(['_x', '_y'])
-# self._points = None
-
-# def __repr__(self):
-# return "TransformedBbox(%s, %s)" % (self.bbox, self.transform)
-# __str__ = __repr__
 
-# def _do_invalidation(self):
-# self._points = None
-
-# def get_points(self):
-# if self._points is None:
-# # MGDTODO: Optimize
-# if self._x == self._y:
-# self._points = self._x.get_points()
-# else:
-# x_points = self._x.get_points()
-# y_points = self._y.get_points()
-# self._points = npy.array(
-# [[x_points[0,0], y_points[0,1]],
-# [x_points[1,0], y_points[1,1]]],
-# npy.float_)
-# return self._points
-
-# def _set_intervalx(self, pair):
-# # MGDTODO: Optimize
-# bbox = Bbox([[pair[0], 0.0], [pair[1], 0.0]])
-# self.replace_child(0, bbox)
-# intervalx = property(BboxBase._get_intervalx, _set_intervalx)
-
-# def _set_intervaly(self, pair):
-# # MGDTODO: Optimize
-# bbox = Bbox([[0.0, pair[0]], [0.0, pair[1]]])
-# self.replace_child(1, bbox)
-# intervaly = property(BboxBase._get_intervaly, _set_intervaly)
- 
 class Transform(TransformNode):
 def __init__(self):
 TransformNode.__init__(self)
@@ -746,7 +688,6 @@
 self._mtx = affine._mtx
 return self._mtx
 
-# MGDTODO: There's probably a better place for this
 def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
 '''
 Ensure the endpoints of a range are not too close together.
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -634,6 +634,9 @@
 if (num_vertices) {
 	for (size_t j=0; j<num_vertices; ++j)
 	 GET_NEXT_VERTEX(x, y);
+	if (code_i == IGNORE)
+	 continue;
+
 	trans.transform(&x, &y);
 	
 	if (face.first) {
@@ -860,6 +863,10 @@
 
 for (size_t i = 0; i < N; ++i) {
 switch (*(unsigned char*)(code_i)) {
+ case IGNORE:
+	GET_NEXT_VERTEX(x0, y0);
+	_VERBOSE("IGNORE");
+	break;
 case MOVETO:
 	GET_NEXT_VERTEX(x0, y0);
 	move_to(x0, y0);
Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h	2007年09月19日 13:28:11 UTC (rev 3857)
+++ branches/transforms/src/_backend_agg.h	2007年09月19日 16:18:51 UTC (rev 3858)
@@ -40,14 +40,14 @@
 #include "agg_vcgen_markers_term.h"
 
 // These are copied directly from path.py, and must be kept in sync
-#define STOP 0
+#define IGNORE 0
 #define MOVETO 1
 #define LINETO 2
 #define CURVE3 3
 #define CURVE4 4
 #define CLOSEPOLY 5
 
-const size_t NUM_VERTICES[] = { 0, 1, 1, 2, 3, 0 };
+const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 0 };
 
 typedef agg::pixfmt_rgba32 pixfmt;
 typedef agg::renderer_base<pixfmt> renderer_base;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月19日 13:28:21
Revision: 3857
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3857&view=rev
Author: mdboom
Date: 2007年09月19日 06:28:11 -0700 (2007年9月19日)
Log Message:
-----------
Got legend working with new transforms
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/legend.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/patches.py
 branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年09月18日 19:29:21 UTC (rev 3856)
+++ branches/transforms/lib/matplotlib/axes.py	2007年09月19日 13:28:11 UTC (rev 3857)
@@ -632,6 +632,7 @@
 	
 self.transAxes = mtransforms.BboxTransform(
 mtransforms.Bbox.unit(), self.bbox)
+ # self.set_transform(self.transAxes)
 self.transData = mtransforms.BboxTransform(
 self.viewLim, self.bbox)
 	 
@@ -724,6 +725,7 @@
 self.axesPatch.set_figure(self.figure)
 self.axesPatch.set_transform(self.transAxes)
 self.axesPatch.set_linewidth(rcParams['axes.linewidth'])
+ # MGDTODO: What is axesFrame for? We already have axesPatch
 self.axesFrame = mlines.Line2D((0,1,1,0,0), (0,0,1,1,0),
 linewidth=rcParams['axes.linewidth'],
 color=rcParams['axes.edgecolor'],
@@ -5201,7 +5203,7 @@
 Subplot(211) # 2 rows, 1 column, first (upper) plot
 """
 def __str__(self):
- return "Subplot(%g,%g)"%(self.bottom.get(),self.left.get())
+ return "Subplot(%f,%f,%f,%f)" % (self.bbox.bounds)
 
 def __init__(self, fig, *args, **kwargs):
 """
Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py	2007年09月18日 19:29:21 UTC (rev 3856)
+++ branches/transforms/lib/matplotlib/legend.py	2007年09月19日 13:28:11 UTC (rev 3857)
@@ -164,7 +164,7 @@
 else:
 raise TypeError("Legend needs either Axes or Figure as parent")
 self.parent = parent
- self.set_transform( BboxTransform( Bbox.unit(), parent.bbox) )
+ self.set_transform( BboxTransform(Bbox.unit(), parent.bbox) )
 
 if loc is None:
 loc = rcParams["legend.loc"]
@@ -223,7 +223,7 @@
 a.set_transform(self.get_transform())
 
 def _approx_text_height(self):
- return self.fontsize/72.0*self.figure.dpi/self.parent.bbox.height()
+ return self.fontsize/72.0*self.figure.dpi/self.parent.bbox.height
 
 
 def draw(self, renderer):
@@ -531,7 +531,7 @@
 def get_tbounds(text): #get text bounds in axes coords
 bbox = text.get_window_extent(renderer)
 bboxa = bbox.inverse_transformed(self.get_transform())
- return bboxa.get_bounds()
+ return bboxa.bounds
 
 hpos = []
 for t, tabove in zip(self.texts[1:], self.texts[:-1]):
@@ -560,10 +560,10 @@
 # Set the data for the legend patch
 bbox = copy.copy(self._get_handle_text_bbox(renderer))
 
- bbox = bbox.scaled(1 + self.pad, 1 + self.pad)
- l,b,w,h = bbox.get_bounds()
- self.legendPatch.set_bounds(l,b,w,h)
-
+ bbox = bbox.expanded(1 + self.pad, 1 + self.pad)
+ l, b, w, h = bbox.bounds
+ self.legendPatch.set_bounds(l, b, w, h)
+ 
 ox, oy = 0, 0 # center
 
 if iterable(self._loc) and len(self._loc)==2:
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月18日 19:29:21 UTC (rev 3856)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月19日 13:28:11 UTC (rev 3857)
@@ -117,7 +117,7 @@
 '--' : '_draw_dashed',
 '-.' : '_draw_dash_dot',
 ':' : '_draw_dotted',
- 'steps': '_draw_steps',
+ 'steps': '_draw_solid',
 'None' : '_draw_nothing',
 ' ' : '_draw_nothing',
 '' : '_draw_nothing',
@@ -352,10 +352,10 @@
 self._picker = p
 
 def get_window_extent(self, renderer):
- xys = self.get_transform()(self._xys)
+ xy = self.get_transform()(self._xy)
 
-	x = xys[:, 0]
-	y = xys[:, 1]
+	x = xy[:, 0]
+	y = xy[:, 1]
 left = x.min()
 bottom = y.min()
 width = x.max() - left
@@ -426,9 +426,19 @@
 			 npy.asarray(y, npy.float_))).transpose()
 	self._x = self._xy[:, 0]
 	self._y = self._xy[:, 1]
-	self._path = Path(self._xy, closed=False)
-	
 self._logcache = None
+ 
+ if self._linestyle == 'steps':
+ siz=len(xt)
+ if siz<2: return
+ xt, yt = self._x, self._y
+ xt2=npy.ones((2*siz,), xt.dtype)
+ xt2[0:-1:2], xt2[1:-1:2], xt2[-1] = xt, xt[1:], xt[-1]
+ yt2=npy.ones((2*siz,), yt.dtype)
+ yt2[0:-1:2], yt2[1::2] = yt, yt
+ self._path = Path(npy.vstack((xt2, yt2)).transpose(), closed=False)
+ else:
+ self._path = Path(self._xy, closed=False)
 
 
 def _is_sorted(self, x):
@@ -700,24 +710,6 @@
 pass
 
 
- def _draw_steps(self, renderer, gc, xt, yt):
-	# MGDTODO: This is a quirky one. The step-plotting part
-	# should probably be moved to where the path is generated
-	# in recache, and then just drawn with _draw_solid
- siz=len(xt)
- if siz<2: return
- xt2=npy.ones((2*siz,), xt.dtype)
- xt2[0:-1:2], xt2[1:-1:2], xt2[-1]=xt, xt[1:], xt[-1]
- yt2=npy.ones((2*siz,), yt.dtype)
- yt2[0:-1:2], yt2[1::2]=yt, yt
- gc.set_linestyle('solid')
-
- if self._newstyle:
- renderer.draw_lines(gc, xt2, yt2, self.get_transform())
- else:
- renderer.draw_lines(gc, xt2, yt2)
-
-	 
 def _draw_solid(self, renderer, gc, path):
 gc.set_linestyle('solid')
 	renderer.draw_path(gc, path, self.get_transform())
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py	2007年09月18日 19:29:21 UTC (rev 3856)
+++ branches/transforms/lib/matplotlib/patches.py	2007年09月19日 13:28:11 UTC (rev 3857)
@@ -212,8 +212,8 @@
 gc.set_hatch(self._hatch )
 
 path = self.get_path()
- transform = self.get_transform()
-
+ transform = self.get_patch_transform() + self.get_transform()
+ 
 renderer.draw_path(gc, path, transform, rgbFace)
 
 #renderer.close_group('patch')
@@ -284,7 +284,7 @@
 self.patch = patch
 self.props = props
 	self.ox, self.oy = ox, oy
-	self._shadow_transform = transforms.Affine2D.translate(self.ox, self.oy)
+	self._shadow_transform = transforms.Affine2D().translate(self.ox, self.oy)
 self._update()
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
@@ -305,8 +305,8 @@
 def get_path(self):
 return self.patch.get_path()
 
- def get_transform(self):
-	return self._transform + self._shadow_transform
+ def get_patch_transform(self):
+	return self._shadow_transform
 
 class Rectangle(Patch):
 """
@@ -315,8 +315,6 @@
 
 """
 
- _path = Path.unit_rectangle()
- 
 def __str__(self):
 return str(self.__class__).split('.')[-1] \
 + "(%g,%g;%gx%g)"%(self.xy[0],self.xy[1],self.width,self.height)
@@ -346,16 +344,14 @@
 """
 Return the vertices of the rectangle
 """
-	# This is a "class-static" variable, so all rectangles in the plot
-	# will be shared (and merely have different transforms)
-	return self._path
+	return Path.unit_rectangle()
 
 # MGDTODO: Convert units
 # left, right = self.convert_xunits((x, x + self.width))
 # bottom, top = self.convert_yunits((y, y + self.height))
 
- def get_transform(self):
-	return self._rect_transform + self._transform
+ def get_patch_transform(self):
+	return self._rect_transform
 
 def get_x(self):
 "Return the left coord of the rectangle"
@@ -379,7 +375,8 @@
 
 ACCEPTS: float
 """
- self._bbox.xmin = x
+ w = self._bbox.width
+ self._bbox.intervalx = (x, x + w)
 
 def set_y(self, y):
 """
@@ -387,7 +384,8 @@
 
 ACCEPTS: float
 """
- self._bbox.ymin = y
+ h = self._bbox.height
+ self._bbox.intervaly = (y, y + h)
 
 def set_width(self, w):
 """
@@ -395,7 +393,7 @@
 
 ACCEPTS: float
 """
- self._bbox.width = w
+ self._bbox.xmax = self._bbox.xmin + w
 
 def set_height(self, h):
 """
@@ -403,7 +401,7 @@
 
 ACCEPTS: float
 """
- self._bbox.height = h
+ self._bbox.ymax = self._bbox.ymin + h
 
 def set_bounds(self, *args):
 """
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月18日 19:29:21 UTC (rev 3856)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月19日 13:28:11 UTC (rev 3857)
@@ -8,6 +8,8 @@
 from numpy.linalg import inv
 from sets import Set
 
+DEBUG = True
+
 # MGDTODO: This creates a ton of cyclical references. We may want to
 # consider using weak references
 
@@ -53,6 +55,13 @@
 
 def __array__(self):
 return self.get_points()
+
+ if DEBUG:
+ def invalidate(self):
+ points = self.get_points()
+ assert points[0, 0] <= points[1, 0]
+ assert points[0, 1] <= points[1, 1]
+ TransformNode.invalidate(self)
 
 # MGDTODO: Probably a more efficient ways to do this...
 def _get_xmin(self):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月18日 19:29:24
Revision: 3856
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3856&view=rev
Author: mdboom
Date: 2007年09月18日 12:29:21 -0700 (2007年9月18日)
Log Message:
-----------
Optimize shared axes (to prevent calling set_xlim/set_ylim more than
once per axes per update).
Save figure at correct dpi.
General cleanup and optimizations.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/axis.py
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/backends/backend_gtkagg.py
 branches/transforms/lib/matplotlib/backends/backend_tkagg.py
 branches/transforms/lib/matplotlib/cbook.py
 branches/transforms/lib/matplotlib/figure.py
 branches/transforms/lib/matplotlib/legend.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/transforms.py
 branches/transforms/src/_backend_agg.cpp
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/axes.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -435,6 +435,9 @@
 1 : 'log',
 }
 
+ _shared_x_axes = cbook.Grouper()
+ _shared_y_axes = cbook.Grouper()
+ 
 def __str__(self):
 return "Axes(%g,%g;%gx%g)" % tuple(self._position.bounds)
 def __init__(self, fig, rect,
@@ -491,6 +494,10 @@
 # must be set before set_figure
 self._sharex = sharex
 self._sharey = sharey
+	if sharex is not None:
+	 self._shared_x_axes.join(self, sharex)
+	if sharey is not None:
+	 self._shared_y_axes.join(self, sharey)
 # Flag: True if some other Axes instance is sharing our x or y axis
 self._masterx = False
 self._mastery = False
@@ -502,7 +509,6 @@
 # this call may differ for non-sep axes, eg polar
 self._init_axis()
 
-
 if axisbg is None: axisbg = rcParams['axes.facecolor']
 self._axisbg = axisbg
 self._frameon = frameon
@@ -616,55 +622,28 @@
 #these will be updated later as data is added
 self._set_lim_and_transforms()
 
- def _shared_xlim_callback(self, ax):
-	xmin, xmax = ax.get_xlim()
-	self.set_xlim(xmin, xmax, emit=False)
-	self.figure.canvas.draw_idle()
-
- def _shared_ylim_callback(self, ax):
-	ymin, ymax = ax.get_ylim()
-	self.set_ylim(ymin, ymax, emit=False)
-	self.figure.canvas.draw_idle()
-	
 def _set_lim_and_transforms(self):
 """
 set the dataLim and viewLim BBox attributes and the
 transData and transAxes Transformation attributes
 """
-	Bbox = mtransforms.Bbox
-	self.viewLim = Bbox.unit()
+	self.viewLim = mtransforms.Bbox.unit()
+	self.dataLim = mtransforms.Bbox.unit()
 	
- if self._sharex is not None:
-	 # MGDTODO: This may be doing at least one too many updates
-	 # than necessary
-	 self._sharex.callbacks.connect(
- 		'xlim_changed', self._shared_xlim_callback)
-	 self.viewLim.intervalx = self._sharex.viewLim.intervalx
- if self._sharey is not None:
- 	 self._sharey.callbacks.connect(
- 		'ylim_changed', self._shared_ylim_callback)
-	 self.viewLim.intervaly = self._sharex.viewLim.intervaly
-
-	self.dataLim = Bbox.unit()
-	
 self.transAxes = mtransforms.BboxTransform(
- Bbox.unit(), self.bbox)
-
+ mtransforms.Bbox.unit(), self.bbox)
 self.transData = mtransforms.BboxTransform(
 self.viewLim, self.bbox)
 	 
 	 
 def get_position(self, original=False):
 'Return the axes rectangle left, bottom, width, height'
-	# MGDTODO: This changed from returning a list to returning a Bbox
-	# If you get any errors with the result of this function, please
-	# update the calling code
 if original:
- return copy.copy(self._originalPosition)
+ return self._originalPosition
 else:
- return copy.copy(self._position)
-	 # return [val.get() for val in self._position]
+ return self._position
 
+	
 def set_position(self, pos, which='both'):
 """
 Set the axes position with pos = [left, bottom, width, height]
@@ -699,8 +678,7 @@
 self.xaxis.cla()
 self.yaxis.cla()
 
-	# MGDTODO
- # self.dataLim.ignore(1)
+	self.ignore_existing_data_limits = True
 self.callbacks = cbook.CallbackRegistry(('xlim_changed', 'ylim_changed'))
 
 if self._sharex is not None:
@@ -886,7 +864,7 @@
 return
 
 
- l,b,w,h = self.get_position(original=True)
+ l,b,w,h = self.get_position(original=True).bounds
 box_aspect = fig_aspect * (h/w)
 data_ratio = box_aspect / A
 
@@ -1152,7 +1130,7 @@
 # Otherwise, it will compute the bounds of it's current data
 # and the data in xydata
 xys = npy.asarray(xys)
- self.dataLim.update_numerix_xy(xys, -1)
+ self.update_datalim_numerix(xys[:, 0], xys[:, 1])
 
 
 def update_datalim_numerix(self, x, y):
@@ -1161,10 +1139,9 @@
 # limits and set the bound to be the bounds of the xydata.
 # Otherwise, it will compute the bounds of it's current data
 # and the data in xydata
- #print type(x), type(y)
-	# MGDTODO
 ## self.dataLim.update_numerix(x, y, -1)
-	self.dataLim.update_from_data(x, y)
+	self.dataLim.update_from_data(x, y, self.ignore_existing_data_limits)
+	self.ignore_existing_data_limits = False
 
 def _get_verts_in_data_coords(self, trans, xys):
 if trans == self.transData:
@@ -1264,9 +1241,7 @@
 if not self.get_visible(): return
 renderer.open_group('axes')
 self.apply_aspect()
-	# MGDTODO -- this is where we can finalize all of the transforms
- # self.transData.freeze() # eval the lazy objects
- # self.transAxes.freeze()
+
 if self.axison and self._frameon: self.axesPatch.draw(renderer)
 artists = []
 
@@ -1314,17 +1289,13 @@
 if self.axison and self._frameon:
 artists.append(self.axesFrame)
 
- # keep track of i to guarantee stable sort for python 2.2
- dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)
- if not a.get_animated()]
+	dsu = [ (a.zorder, a) for a in artists
+		if not a.get_animated() ]
 dsu.sort()
 
- for zorder, i, a in dsu:
+ for zorder, a in dsu:
 a.draw(renderer)
 
-	# MGDTODO
-	# self.transData.thaw() # release the lazy objects
- # self.transAxes.thaw() # release the lazy objects
 renderer.close_group('axes')
 self._cachedRenderer = renderer
 
@@ -1509,7 +1480,6 @@
 
 ACCEPTS: len(2) sequence of floats
 """
-
 if xmax is None and iterable(xmin):
 xmin,xmax = xmin
 
@@ -1534,11 +1504,10 @@
 	self.viewLim.intervalx = (xmin, xmax)
 if emit:
 	 self.callbacks.process('xlim_changed', self)
-	 # MGDTODO: It would be nice to do this is in the above callback list,
-	 # but it's difficult to tell how to initialize this at the
-	 # right time
-	 if self._sharex:
-		self._sharex.set_xlim(*self.viewLim.intervalx)
+	 # Call all of the other x-axes that are shared with this one
+	 for other in self._shared_x_axes.get_siblings(self):
+		if other is not self:
+		 other.set_xlim(self.viewLim.xmin, self.viewLim.xmax, emit=False)
 	 
 return xmin, xmax
 
@@ -1665,11 +1634,10 @@
 	self.viewLim.intervaly = (ymin, ymax)
 if emit:
 	 self.callbacks.process('ylim_changed', self)
-	 # MGDTODO: It would be nice to do this is in the above callback list,
-	 # but it's difficult to tell how to initialize this at the
-	 # right time
-	 if self._sharey:
-		self._sharey.set_ylim(*self.viewLim.intervaly)
+	 # Call all of the other y-axes that are shared with this one
+	 for other in self._shared_y_axes.get_siblings(self):
+		if other is not self:
+		 other.set_ylim(self.viewLim.ymin, self.viewLim.ymax, emit=False)
 	 
 return ymin, ymax
 
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/axis.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -1033,8 +1033,7 @@
 bbox = Bbox.union(bboxes)
 bottom = bbox.ymin
 
- self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi/72.0))
-# self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi.get()/72.0)) MGDTODO
+ self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi / 72.0))
 
 else:
 if not len(bboxes2):
@@ -1057,7 +1056,6 @@
 bbox = Bbox.union(bboxes)
 bottom = bbox.ymin
 self.offsetText.set_position((x, bottom-self.OFFSETTEXTPAD*self.figure.dpi/72.0))
-# self.offsetText.set_position((x, bottom-self.OFFSETTEXTPAD*self.figure.dpi.get()/72.0)) MGDTODO
 	
 def set_ticks_position(self, position):
 """
@@ -1225,7 +1223,6 @@
 left = bbox.xmin
 
 self.label.set_position( (left-self.LABELPAD*self.figure.dpi/72.0, y))
-	 # self.label.set_position( (left-self.LABELPAD*self.figure.dpi.get()/72.0, y)) MGDTODO
 	 
 else:
 if not len(bboxes2):
@@ -1245,7 +1242,6 @@
 x,y = self.offsetText.get_position()
 top = self.axes.bbox.ymax
 self.offsetText.set_position((x, top+self.OFFSETTEXTPAD*self.figure.dpi/72.0))
-# self.offsetText.set_position((x, top+self.OFFSETTEXTPAD*self.figure.dpi.get()/72.0)) MGDTODO
 	
 def set_offset_position(self, position):
 assert position == 'left' or position == 'right'
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -18,8 +18,9 @@
 """An abstract base class to handle drawing/rendering operations
 """
 # This will cache paths across rendering instances
- # Each subclass of RenderBase should define this -->
- # _paths = weakref.WeakKeyDictionary()
+ # Each subclass of RenderBase should define this a weak-keyed
+ # dictionary to hold native paths
+ # _native_paths = weakref.WeakKeyDictionary()
 
 def __init__(self):
 self._texmanager = None
@@ -44,7 +45,7 @@
 	 self._native_paths[path] = native_path
 	return native_path
 
- def draw_path(self, gc, path, transform, rgbFace = None):
+ def draw_path(self, gc, path, transform, rgbFace=None):
 	"""
 	Handles the caching of the native path associated with the
 	given path and calls the underlying backend's _draw_path to
@@ -67,17 +68,31 @@
 	passed to them in draw_path.
 	"""
 	return path
+
+ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
+	native_marker_path = self._get_cached_native_path(marker_path)
+	self._draw_native_markers(gc, native_marker_path, marker_trans, path, trans, rgbFace)
 	
- def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2,
- rotation):
+ def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
 """
- Draw an arc using GraphicsContext instance gcEdge, centered at x,y,
- with width and height and angles from 0.0 to 360.0
- 0 degrees is at 3-o'clock
- positive angles are anti-clockwise
- draw rotated 'rotation' degrees anti-clockwise about x,y
+ This method is currently underscore hidden because the
+ draw_markers method is being used as a sentinel for newstyle
+ backend drawing
 
- If the color rgbFace is not None, fill the arc with it.
+ path - a matplotlib.agg.path_storage instance
+
+ Draw the marker specified in path with graphics context gc at
+ each of the locations in arrays x and y. trans is a
+ matplotlib.transforms.Transformation instance used to
+ transform x and y to display coords. It consists of an
+ optional nonlinear component and an affine. You can access
+ these two components as
+
+ if transform.need_nonlinear():
+ x,y = transform.nonlinear_only_numerix(x, y)
+ # the a,b,c,d,tx,ty affine which transforms x and y
+ vec6 = transform.as_vec6_val()
+ ...backend dependent affine...
 """
 raise NotImplementedError
 
@@ -109,30 +124,21 @@
 """
 return False
 
- def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
-	native_marker_path = self._get_cached_native_path(marker_path)
-	self._draw_native_markers(gc, native_marker_path, marker_trans, path, trans, rgbFace)
-	
- def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
+ ######################################################################
+ ## OLD API IS BELOW
+ ## These functions no longer need to be implemented in the backends --
+ ## they now perform all of their functions in terms of the new API.
+ 
+ def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2,
+ rotation):
 """
- This method is currently underscore hidden because the
- draw_markers method is being used as a sentinel for newstyle
- backend drawing
+ Draw an arc using GraphicsContext instance gcEdge, centered at x,y,
+ with width and height and angles from 0.0 to 360.0
+ 0 degrees is at 3-o'clock
+ positive angles are anti-clockwise
+ draw rotated 'rotation' degrees anti-clockwise about x,y
 
- path - a matplotlib.agg.path_storage instance
-
- Draw the marker specified in path with graphics context gc at
- each of the locations in arrays x and y. trans is a
- matplotlib.transforms.Transformation instance used to
- transform x and y to display coords. It consists of an
- optional nonlinear component and an affine. You can access
- these two components as
-
- if transform.need_nonlinear():
- x,y = transform.nonlinear_only_numerix(x, y)
- # the a,b,c,d,tx,ty affine which transforms x and y
- vec6 = transform.as_vec6_val()
- ...backend dependent affine...
+ If the color rgbFace is not None, fill the arc with it.
 """
 raise NotImplementedError
 
@@ -346,8 +352,10 @@
 
 If rgbFace is not None, fill the rectangle with it.
 """
- raise NotImplementedError
-
+	warnings.warn("draw_rectangle called", warnings.PendingDeprecationWarning)
+	transform = transforms.Affine2D().scale(width, height).translate(x, y)
+	self.draw_path(gcEdge, Path.unit_rectangle(), transform, rgbFace)
+	
 def draw_regpoly_collection(
 self, clipbox, offsets, transOffset, verts, sizes,
 facecolors, edgecolors, linewidths, antialiaseds):
@@ -1221,8 +1229,6 @@
 origfacecolor = self.figure.get_facecolor()
 origedgecolor = self.figure.get_edgecolor()
 
-	# MGDTODO
- # self.figure.dpi.set(dpi)
 self.figure.dpi = dpi
 self.figure.set_facecolor(facecolor)
 self.figure.set_edgecolor(edgecolor)
@@ -1236,12 +1242,12 @@
 orientation=orientation,
 **kwargs)
 finally:
-	 # MGDTODO
- # self.figure.dpi.set(origDPI)
 self.figure.dpi = origDPI
 self.figure.set_facecolor(origfacecolor)
 self.figure.set_edgecolor(origedgecolor)
 self.figure.set_canvas(self)
+
+ self.draw()
 
 return result
 
@@ -1623,8 +1629,8 @@
 lims.append( (xmin, xmax, ymin, ymax) )
 # Store both the original and modified positions
 pos.append( (
-		 a.get_position(True),
- a.get_position() ) )
+		 copy.copy(a.get_position(True)),
+ copy.copy(a.get_position() )) )
 self._views.push(lims)
 self._positions.push(pos)
 self.set_history_buttons()
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -114,9 +114,6 @@
 self.height = height
 if __debug__: verbose.report('RendererAgg.__init__ width=%s, \
 height=%s'%(width, height), 'debug-annoying')
-	# MGDTODO
-# self._renderer = _RendererAgg(int(width), int(height), dpi.get(),
-# 				 debug=False)
 self._renderer = _RendererAgg(int(width), int(height), dpi,
 				 debug=False)
 if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
@@ -136,35 +133,6 @@
 def _draw_native_path(self, gc, path, transform, rgbFace):
 	return self._renderer.draw_path(gc, path, transform.get_matrix(), rgbFace)
 
- def draw_arc(self, gcEdge, rgbFace, x, y, width, height, angle1, angle2, rotation):
- """
- Draw an arc centered at x,y with width and height and angles
- from 0.0 to 360.0
-
- If rgbFace is not None, fill the rectangle with that color. gcEdge
- is a GraphicsContext instance
-
- Currently, I'm only supporting ellipses, ie angle args are
- ignored
- """
- if __debug__: verbose.report('RendererAgg.draw_arc', 'debug-annoying')
- self._renderer.draw_ellipse(
- gcEdge, rgbFace, x, y, width/2, height/2, rotation) # ellipse takes radius
-
-
- def draw_line(self, gc, x1, y1, x2, y2):
- """
- x and y are equal length arrays, draw lines connecting each
- point in x, y
- """
- if __debug__: verbose.report('RendererAgg.draw_line', 'debug-annoying')
- x = npy.array([x1,x2], float)
- y = npy.array([y1,y2], float)
- self._renderer.draw_lines(gc, x, y)
-
- def draw_lines(self, gc, x, y, transform):
-	return self._renderer.draw_lines(gc, x, y, transform.to_values())
-
 def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
 	return self._renderer.draw_markers(
 	 gc,
@@ -172,18 +140,6 @@
 	 path.vertices, path.codes, trans.get_matrix(),
 	 rgbFace)
 
- def draw_polygon(self, *args):
-	return self._renderer.draw_polygon(*args)
- 
- def draw_point(self, gc, x, y):
- """
- Draw a single point at x,y
- """
- if __debug__: verbose.report('RendererAgg.draw_point', 'debug-annoying')
- rgbFace = gc.get_rgb()
- self._renderer.draw_ellipse(
- gc, rgbFace, x, y, 0.5, 0.5, 0.0)
-
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 """
 Draw the math text using matplotlib.mathtext
@@ -192,8 +148,6 @@
 'debug-annoying')
 ox, oy, width, height, descent, font_image, used_characters = \
 self.mathtext_parser.parse(s, self.dpi, prop)
-# ox, oy, width, height, descent, font_image, used_characters = \
-# self.mathtext_parser.parse(s, self.dpi.get(), prop) MGDTODO
 
 x = int(x) + ox
 y = int(y) - oy
@@ -227,7 +181,6 @@
 # (in vector space) in the above call to font.set_text.
 self._renderer.draw_text_image(font.get_image(), int(x), int(y) + 1, angle, gc)
 
-
 def get_text_width_height_descent(self, s, prop, ismath, rgb=(0,0,0)):
 """
 get the width and height in display coords of the string s
@@ -241,7 +194,7 @@
 # todo: handle props
 size = prop.get_size_in_points()
 texmanager = self.get_texmanager()
- Z = texmanager.get_rgba(s, size, self.dpi.get(), rgb)
+ Z = texmanager.get_rgba(s, size, self.dpi, rgb)
 m,n,tmp = Z.shape
 # TODO: descent of TeX text (I am imitating backend_ps here -JKS)
 return n, m, 0
@@ -249,8 +202,6 @@
 if ismath:
 ox, oy, width, height, descent, fonts, used_characters = \
 self.mathtext_parser.parse(s, self.dpi, prop)
-# ox, oy, width, height, descent, fonts, used_characters = \
-# self.mathtext_parser.parse(s, self.dpi.get(), prop) MGDTODO
 return width, height, descent
 font = self._get_agg_font(prop)
 font.set_text(s, 0.0, flags=LOAD_DEFAULT) # the width and height of unrotated string
@@ -265,7 +216,7 @@
 # todo, handle props, angle, origins
 rgb = gc.get_rgb()
 size = prop.get_size_in_points()
- dpi = self.dpi.get()
+ dpi = self.dpi
 
 flip = angle==90
 w,h,d = self.get_text_width_height_descent(s, prop, 'TeX', rgb)
@@ -306,7 +257,6 @@
 'return the canvas width and height in display coords'
 return self.width, self.height
 
-
 def _get_agg_font(self, prop):
 """
 Get the font for text instance t, cacheing for efficiency
@@ -325,11 +275,9 @@
 font.clear()
 size = prop.get_size_in_points()
 font.set_size(size, self.dpi)
- # font.set_size(size, self.dpi.get()) MGDTODO
 
 return font
 
-
 def points_to_pixels(self, points):
 """
 convert point measures to pixes using dpi and the pixels per
@@ -337,8 +285,6 @@
 """
 if __debug__: verbose.report('RendererAgg.points_to_pixels',
 'debug-annoying')
-	# MGDTODO
- # return points*self.dpi.get()/72.0
 return points*self.dpi/72.0
 
 def tostring_rgb(self):
@@ -404,9 +350,7 @@
 self.figure.draw(self.renderer)
 
 def get_renderer(self):
- l,b,w,h = self.figure.bbox.bounds
-	# MGDTODO
- # key = w, h, self.figure.dpi.get()
+ l, b, w, h = self.figure.bbox.bounds
 key = w, h, self.figure.dpi
 try: self._lastKey, self.renderer
 except AttributeError: need_new_renderer = True
Modified: branches/transforms/lib/matplotlib/backends/backend_gtkagg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_gtkagg.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/backends/backend_gtkagg.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -60,7 +60,6 @@
 w,h = widget.window.get_size()
 if w==1 or h==1: return # empty fig
 
-	# dpival = self.figure.dpi.get() MGDTODO
 # compute desired figure size in inches
 dpival = self.figure.dpi
 winch = w/dpival
Modified: branches/transforms/lib/matplotlib/backends/backend_tkagg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_tkagg.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/backends/backend_tkagg.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -175,7 +175,6 @@
 self._resize_callback(event)
 
 # compute desired figure size in inches
-	# dpival = self.figure.dpi.get() MGDTODO
 	dpival = self.figure.dpi
 winch = width/dpival
 hinch = height/dpival
Modified: branches/transforms/lib/matplotlib/cbook.py
===================================================================
--- branches/transforms/lib/matplotlib/cbook.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/cbook.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -955,6 +955,84 @@
 outstream.write("Examining: %r\n" % (obj,))
 recurse(obj, obj, { }, [])
 
+class Grouper(object):
+ """
+ This class provides a lightweight way to group arbitrary objects
+ together into disjoint sets when a full-blown graph data structure
+ would be overkill.
+
+ Objects can be joined using .join(), tested for connectedness
+ using .joined(), and all disjoint sets can be retreived using
+ .get().
+
+ The objects being joined must be hashable.
+ 
+ For example:
+ 
+ >>> g = grouper.Grouper()
+ >>> g.join('a', 'b')
+ >>> g.join('b', 'c')
+ >>> g.join('d', 'e')
+ >>> list(g.get())
+ [['a', 'b', 'c'], ['d', 'e']]
+ >>> g.joined('a', 'b')
+ True
+ >>> g.joined('a', 'c')
+ True
+ >>> g.joined('a', 'd')
+ False""" 
+ def __init__(self, init=[]):
+	mapping = self._mapping = {}
+	for x in init:
+	 mapping[x] = [x]
+ 
+ def join(self, a, *args):
+	"""
+	Join given arguments into the same set.
+	Accepts one or more arguments.
+	"""
+	mapping = self._mapping
+	set_a = mapping.setdefault(a, [a])
+
+	for arg in args:
+	 set_b = mapping.get(arg)
+	 if set_b is None:
+		set_a.append(arg)
+		mapping[arg] = set_a
+	 elif set_b is not set_a:
+		if len(set_b) > len(set_a):
+		 set_a, set_b = set_b, set_a
+		set_a.extend(set_b)
+		for elem in set_b:
+		 mapping[elem] = set_a
+
+ def joined(self, a, b):
+	"""
+	Returns True if a and b are members of the same set.
+	"""
+	mapping = self._mapping
+	try:
+	 return mapping[a] is mapping[b]
+	except KeyError:
+	 return False
+
+ def __iter__(self):
+	"""
+	Returns an iterator returning each of the disjoint sets as a list.
+	"""
+	seen = set()
+	for elem, group in self._mapping.iteritems():
+	 if elem not in seen:
+		yield group
+		seen.update(group)
+
+ def get_siblings(self, a):
+	"""
+	Returns all of the items joined with the given item, including
+	itself.
+	"""
+	return self._mapping.get(a, [a])
+		
 if __name__=='__main__':
 assert( allequal([1,1,1]) )
 assert(not allequal([1,1,0]) )
Modified: branches/transforms/lib/matplotlib/figure.py
===================================================================
--- branches/transforms/lib/matplotlib/figure.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/figure.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -161,10 +161,8 @@
 def _get_dpi(self):
 	return self._dpi
 def _set_dpi(self, dpi):
-	print "setting dpi"
 	self._dpi = dpi
 	self._dpi_scale_trans.clear().scale(dpi, dpi)
-	print self._dpi_scale_trans
 dpi = property(_get_dpi, _set_dpi)
 	
 def autofmt_xdate(self, bottom=0.2, rotation=30, ha='right'):
@@ -178,10 +176,7 @@
 bottom : the bottom of the subplots for subplots_adjust
 rotation: the rotation of the xtick labels
 ha : the horizontal alignment of the xticklabels
-
-
 """
-
 for ax in self.get_axes():
 if not hasattr(ax, 'is_last_row'):
 raise RuntimeError('Axes must be subplot instances; found %s'%type(ax))
@@ -333,11 +328,8 @@
 
 	dpival = self.dpi
 	self.bbox_inches.max = w, h
- # self.figwidth.set(w) MGDTODO
- # self.figheight.set(h)
 	
 if forward:
- # dpival = self.dpi.get()
 dpival = self.dpi
 canvasw = w*dpival
 canvash = h*dpival
@@ -347,7 +339,6 @@
 
 def get_size_inches(self):
 return self.bbox_inches.max
- # return self.figwidth.get(), self.figheight.get() MGDTODO
 
 def get_edgecolor(self):
 'Get the edge color of the Figure rectangle'
@@ -360,7 +351,6 @@
 def get_figwidth(self):
 'Return the figwidth as a float'
 	return self.bbox_inches.xmax
- # return self.figwidth.get() MGDTODO
 
 def get_figheight(self):
 'Return the figheight as a float'
@@ -369,7 +359,6 @@
 def get_dpi(self):
 'Return the dpi as a float'
 return self.dpi
- # return self.dpi.get() MGDTODO
 
 def get_frameon(self):
 'get the boolean indicating frameon'
@@ -397,7 +386,6 @@
 
 ACCEPTS: float
 """
- # self.dpi.set(val) MGDTODO
 	self.dpi = val
 
 def set_figwidth(self, val):
@@ -406,7 +394,6 @@
 
 ACCEPTS: float
 """
- # self.figwidth.set(val) MGDTODO
 	self.bbox_inches.xmax = val
 	
 def set_figheight(self, val):
@@ -415,7 +402,6 @@
 
 ACCEPTS: float
 """
-	# MGDTODO (set())
 	self.bbox_inches.ymax = val
 
 def set_frameon(self, b):
@@ -598,8 +584,6 @@
 #print 'figure draw'
 if not self.get_visible(): return
 renderer.open_group('figure')
-	# MGDTODO
- # self.transFigure.freeze() # eval the lazy objects
 
 if self.frameon: self.figurePatch.draw(renderer)
 
@@ -633,8 +617,6 @@
 for legend in self.legends:
 legend.draw(renderer)
 
-	# MGDTODO
-	# self.transFigure.thaw() # release the lazy objects
 renderer.close_group('figure')
 
 self._cachedRenderer = renderer
Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/legend.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -21,7 +21,7 @@
 up the legend
 """
 from __future__ import division
-import sys, warnings
+import copy, sys, warnings
 
 import numpy as npy
 
@@ -558,9 +558,7 @@
 handle.set_height(h/2)
 
 # Set the data for the legend patch
-	# MGDTODO: This copy may no longer be needed now that Bboxes are
-	# essentially immutable
- bbox = self._get_handle_text_bbox(renderer).copy()
+ bbox = copy.copy(self._get_handle_text_bbox(renderer))
 
 bbox = bbox.scaled(1 + self.pad, 1 + self.pad)
 l,b,w,h = bbox.get_bounds()
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -352,32 +352,18 @@
 self._picker = p
 
 def get_window_extent(self, renderer):
- self._newstyle = hasattr(renderer, 'draw_markers')
- if self._newstyle:
- x = self._x
- y = self._y
- else:
- x, y = self._get_plottable()
+ xys = self.get_transform()(self._xys)
 
-	# MGDTODO: Put this in a single Nx2 array, rather than these
-	# separate ones
-	#### Conversion code
-	a = npy.vstack((x, y)).swapaxes(0, 1)
-	####
- x, y = self.get_transform()(a)
-	print "get_window_extent", self.get_transform()
-	
- #x, y = self.get_transform().seq_x_y(x, y)
+	x = xys[:, 0]
+	y = xys[:, 1]
+ left = x.min()
+ bottom = y.min()
+ width = x.max() - left
+ height = y.max() - bottom
 
- left = min(x)
- bottom = min(y)
- width = max(x) - left
- height = max(y) - bottom
-
 # correct for marker size, if any
 if self._marker is not None:
- ms = self._markersize/72.0*self.figure.dpi
- # ms = self._markersize/72.0*self.figure.dpi.get() MGDTODO
+ ms = self._markersize / 72.0 * self.figure.dpi
 left -= ms/2
 bottom -= ms/2
 width += ms
@@ -411,6 +397,7 @@
 def recache(self):
 #if self.axes is None: print 'recache no axes'
 #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
+	# MGDTODO: Deal with units
 x = ma.asarray(self.convert_xunits(self._xorig), float)
 y = ma.asarray(self.convert_yunits(self._yorig), float)
 
@@ -435,15 +422,15 @@
 else:
 self._segments = None
 
- self._x = npy.asarray(x, float)
- self._y = npy.asarray(y, float)
-	self._path = Path(npy.vstack((self._x, self._y)).transpose(),
-			 closed=False)
+	self._xy = npy.vstack((npy.asarray(x, npy.float_),
+			 npy.asarray(y, npy.float_))).transpose()
+	self._x = self._xy[:, 0]
+	self._y = self._xy[:, 1]
+	self._path = Path(self._xy, closed=False)
 	
 self._logcache = None
 
 
-
 def _is_sorted(self, x):
 "return true if x is sorted"
 if len(x)<2: return 1
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -19,9 +19,9 @@
 self._parents = Set()
 
 def invalidate(self):
- if not self._do_invalidation():
- for parent in self._parents:
- parent.invalidate()
+ self._do_invalidation()
+ for parent in self._parents:
+ parent.invalidate()
 
 def _do_invalidation(self):
 return False
@@ -187,14 +187,16 @@
 return 'Bbox(%s)' % repr(self._points)
 __str__ = __repr__
 
- # JDH: the update method will update the box limits from the
- # existing limits and the new data; it appears here you are just
- # using the new data. We use an "ignore" flag to specify whether
- # you want to include the existing data or not in the update
 def update_from_data(self, x, y, ignore=True):
- self._points = npy.array(
- [[x.min(), y.min()], [x.max(), y.max()]],
- npy.float_)
+	if ignore:
+	 self._points = npy.array(
+		[[x.min(), y.min()], [x.max(), y.max()]],
+		npy.float_)
+	else:
+	 self._points = npy.array(
+		[[min(x.min(), self.xmin), min(y.min(), self.ymin)],
+		 [max(x.max(), self.xmax), max(y.max(), self.ymax)]],
+		 npy.float_)
 self.invalidate()
 
 # MGDTODO: Probably a more efficient ways to do this...
@@ -409,9 +411,7 @@
 	return self.get_matrix()
 	
 def _do_invalidation(self):
- result = self._inverted is None
 self._inverted = None
- return result
 
 #@staticmethod
 def _concat(a, b):
@@ -494,6 +494,7 @@
 if matrix is None:
 matrix = npy.identity(3)
 else:
+	 matrix = npy.asarray(matrix, npy.float_)
 assert matrix.shape == (3, 3)
 self._mtx = matrix
 self._inverted = None
@@ -629,8 +630,6 @@
 if self._mtx is not None:
 self._mtx = None
 Affine2DBase._do_invalidation(self)
- return False
- return True
 
 def is_separable(self):
 return True
@@ -684,7 +683,7 @@
 
 def _do_invalidation(self):
 self._mtx = None
- Affine2DBase._do_invalidation(self)
+ return Affine2DBase._do_invalidation(self)
 
 def get_matrix(self):
 if self._mtx is None:
@@ -718,8 +717,6 @@
 if self._mtx is not None:
 self._mtx = None
 Affine2DBase._do_invalidation(self)
- return False
- return True
 
 def is_separable(self):
 return True
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月18日 16:21:37 UTC (rev 3855)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月18日 19:29:21 UTC (rev 3856)
@@ -456,7 +456,7 @@
 //return the agg::rect for bbox, flipping y
 PyArrayObject *bbox = (PyArrayObject *) PyArray_ContiguousFromObject(o.ptr(), PyArray_DOUBLE, 2, 2);
 
- if (!bbox || bbox->nd != 2 bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2)
+ if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2)
 throw Py::TypeError
 ("Expected a Bbox object.");
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年09月18日 16:21:40
Revision: 3855
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3855&view=rev
Author: mdboom
Date: 2007年09月18日 09:21:37 -0700 (2007年9月18日)
Log Message:
-----------
More code using new transformation framework. Lots of dead code
removed from backend_agg.cpp/h
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/transforms.py
 branches/transforms/lib/matplotlib/type1font.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -39,8 +39,7 @@
 def _get_cached_native_path(self, path):
 	native_path = self._native_paths.get(path)
 	if native_path is None:
-	 import matplotlib.patches
-	 print "CACHE MISS", path
+	 # print "CACHE MISS", path
 	 native_path = self.convert_to_native_path(path)
 	 self._native_paths[path] = native_path
 	return native_path
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -121,13 +121,9 @@
 				 debug=False)
 if __debug__: verbose.report('RendererAgg.__init__ _RendererAgg done',
 'debug-annoying')
- # self.draw_polygon = self._renderer.draw_polygon
- self.draw_rectangle = self._renderer.draw_rectangle
-	# MGDTODO -- remove these lines
- # self.draw_lines = self._renderer.draw_lines
- # self.draw_markers = self._renderer.draw_markers
- self.draw_image = self._renderer.draw_image
 
+	self.convert_to_native_path = self._renderer.convert_to_native_path
+ self.draw_image = self._renderer.draw_image
 self.copy_from_bbox = self._renderer.copy_from_bbox
 self.restore_region = self._renderer.restore_region
 self.mathtext_parser = MathTextParser('Agg')
@@ -137,12 +133,9 @@
 if __debug__: verbose.report('RendererAgg.__init__ done',
 'debug-annoying')
 
- def convert_to_native_path(self, path):
-	return self._renderer.convert_to_native_path(path.vertices, path.codes)
-
- def _draw_native_path(self, gc, native_path, transform, rgbFace):
-	return self._renderer.draw_path(gc, native_path, transform.to_values(), rgbFace)
-	
+ def _draw_native_path(self, gc, path, transform, rgbFace):
+	return self._renderer.draw_path(gc, path, transform.get_matrix(), rgbFace)
+ 
 def draw_arc(self, gcEdge, rgbFace, x, y, width, height, angle1, angle2, rotation):
 """
 Draw an arc centered at x,y with width and height and angles
@@ -175,8 +168,8 @@
 def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
 	return self._renderer.draw_markers(
 	 gc,
-	 native_marker_path, marker_trans.to_values(),
-	 path.vertices, path.codes, trans.to_values(),
+	 native_marker_path, marker_trans.get_matrix(),
+	 path.vertices, path.codes, trans.get_matrix(),
 	 rgbFace)
 
 def draw_polygon(self, *args):
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -712,6 +712,7 @@
 def _draw_nothing(self, renderer, gc, path):
 pass
 
+ 
 def _draw_steps(self, renderer, gc, xt, yt):
 	# MGDTODO: This is a quirky one. The step-plotting part
 	# should probably be moved to where the path is generated
@@ -729,6 +730,7 @@
 else:
 renderer.draw_lines(gc, xt2, yt2)
 
+	 
 def _draw_solid(self, renderer, gc, path):
 gc.set_linestyle('solid')
 	renderer.draw_path(gc, path, self.get_transform())
@@ -753,8 +755,15 @@
 
 	
 def _draw_point(self, renderer, gc, path):
-	self._draw_circle(renderer, gc, path, point = True)
+ w = renderer.points_to_pixels(self._markersize) * \
+	 self._point_size_reduction * 0.5
+ rgbFace = self._get_rgb_face()
+	transform = Affine2D().scale(w)
+	renderer.draw_markers(
+	 gc, Path.unit_circle(), transform, path, self.get_transform(),
+	 rgbFace)
 
+	
 def _draw_pixel(self, renderer, gc, path):
 	rgbFace = self._get_rgb_face()
 	transform = Affine2D().translate(-0.5, -0.5)
@@ -762,12 +771,8 @@
 			 path, self.get_transform(), rgbFace)
 	
 	
- def _draw_circle(self, renderer, gc, path, point=False):
- w = renderer.points_to_pixels(self._markersize)
- if point:
- w *= self._point_size_reduction
-	w *= 0.5
-
+ def _draw_circle(self, renderer, gc, path):
+ w = renderer.points_to_pixels(self._markersize) * 0.5
 rgbFace = self._get_rgb_face()
 	transform = Affine2D().scale(w, w)
 	renderer.draw_markers(
@@ -826,7 +831,8 @@
 	
 def _draw_thin_diamond(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
-	transform = Affine2D().translate(0.5, 0.5).rotate_deg(45).scale(offset * 0.8, offset)
+	transform = Affine2D().translate(0.5, 0.5) \
+	 .rotate_deg(45).scale(offset * 0.8, offset)
 rgbFace = self._get_rgb_face()
 	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
 			 path, self.get_transform(), rgbFace)
@@ -840,7 +846,7 @@
 			 path, self.get_transform(), rgbFace)
 
 	
- def _draw_hexagon1(self, renderer, gc, path, point=False):
+ def _draw_hexagon1(self, renderer, gc, path):
 offset = 0.5 * renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset)
 	rgbFace = self._get_rgb_face()
@@ -848,50 +854,44 @@
 			 path, self.get_transform(), rgbFace)
 
 	
- def _draw_hexagon2(self, renderer, gc, xt, yt):
+ def _draw_hexagon2(self, renderer, gc, path):
 offset = 0.5 * renderer.points_to_pixels(self._markersize)
 	transform = Affine2D().scale(offset).rotate_deg(30)
 	rgbFace = self._get_rgb_face()
 	renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
 			 path, self.get_transform(), rgbFace)
 
-	
- def _draw_vline(self, renderer, gc, xt, yt):
+
+ _line_marker_path = Path([[0.0, -1.0], [0.0, 1.0]], closed=False)
+ def _draw_vline(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, -offset)
- path.line_to(0, offset)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y-offset, x, y+offset)
+	transform = Affine2D().scale(offset)
+	renderer.draw_markers(gc, self._line_marker_path, transform,
+			 path, self.get_transform())
 
 		
- def _draw_hline(self, renderer, gc, xt, yt):
+ def _draw_hline(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset, 0)
- path.line_to(offset, 0)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y, x+offset, y)
+	transform = Affine2D().scale(offset).rotate_deg(90)
+	renderer.draw_markers(gc, self._line_marker_path, transform,
+			 path, self.get_transform())
 
+		
 _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]])
 def _draw_tickleft(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
-	marker_transform = Affine2D().scale(offset, 1.0)
+	marker_transform = Affine2D().scale(-offset, 1.0)
 	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
 			 path, self.get_transform())
 
+	
 def _draw_tickright(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
-	marker_transform = Affine2D().scale(-offset, 1.0)
+	marker_transform = Affine2D().scale(offset, 1.0)
 	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
 			 path, self.get_transform())
 
+	
 _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]])
 def _draw_tickup(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
@@ -899,174 +899,99 @@
 	renderer.draw_markers(gc, self._tickvert_path, marker_transform,
 			 path, self.get_transform())
 
+	
 def _draw_tickdown(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(1.0, -offset)
 	renderer.draw_markers(gc, self._tickvert_path, marker_transform,
 			 path, self.get_transform())
 
- def _draw_plus(self, renderer, gc, xt, yt):
+
+ _plus_path = Path([[-1.0, 0.0], [1.0, 0.0],
+		 [0.0, -1.0], [0.0, 1.0]],
+		 [Path.MOVETO, Path.LINETO,
+		 Path.MOVETO, Path.LINETO])
+ def _draw_plus(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- if self._newstyle:
+	transform = Affine2D().scale(offset)
+	renderer.draw_markers(gc, self._plus_path, transform,
+			 path, self.get_transform())
 
- path = agg.path_storage()
- path.move_to(-offset, 0)
- path.line_to( offset, 0)
- path.move_to( 0, -offset)
- path.line_to( 0, offset)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y, x+offset, y)
- renderer.draw_line(gc, x, y-offset, x, y+offset)
 
- def _draw_tri_down(self, renderer, gc, xt, yt):
+ _tri_path = Path([[0.0, 0.0], [0.0, -1.0],
+		 [0.0, 0.0], [0.8, 0.5],
+		 [0.0, 0.0], [-0.8, 0.5]],
+		 [Path.MOVETO, Path.LINETO,
+		 Path.MOVETO, Path.LINETO,
+		 Path.MOVETO, Path.LINETO])
+ def _draw_tri_down(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = offset*0.8
- offset2 = offset*0.5
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, 0)
- path.line_to(0, -offset)
- path.move_to(0, 0)
- path.line_to(offset1, offset2)
- path.move_to(0, 0)
- path.line_to(-offset1, offset2)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y, x, y-offset)
- renderer.draw_line(gc, x, y, x+offset1, y+offset2)
- renderer.draw_line(gc, x, y, x-offset1, y+offset2)
+	transform = Affine2D().scale(offset)
+	renderer.draw_markers(gc, self._tri_path, transform,
+			 path, self.get_transform())
 
- def _draw_tri_up(self, renderer, gc, xt, yt):
+	
+ def _draw_tri_up(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = offset*0.8
- offset2 = offset*0.5
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, 0)
- path.line_to(0, offset)
- path.move_to(0, 0)
- path.line_to(offset1, -offset2)
- path.move_to(0, 0)
- path.line_to(-offset1, -offset2)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y, x, y+offset)
- renderer.draw_line(gc, x, y, x+offset1, y-offset2)
- renderer.draw_line(gc, x, y, x-offset1, y-offset2)
+	transform = Affine2D().scale(offset).rotate_deg(180)
+	renderer.draw_markers(gc, self._tri_path, transform,
+			 path, self.get_transform())
 
- def _draw_tri_left(self, renderer, gc, xt, yt):
- offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = offset*0.8
- offset2 = offset*0.5
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, 0)
- path.line_to(-offset, 0)
- path.move_to(0, 0)
- path.line_to(offset2, offset1)
- path.move_to(0, 0)
- path.line_to(offset2, -offset1)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y, x-offset, y)
- renderer.draw_line(gc, x, y, x+offset2, y+offset1)
- renderer.draw_line(gc, x, y, x+offset2, y-offset1)
+	
+ def _draw_tri_left(self, renderer, gc, path):
+	offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset).rotate_deg(90)
+	renderer.draw_markers(gc, self._tri_path, transform,
+			 path, self.get_transform())
 
- def _draw_tri_right(self, renderer, gc, xt, yt):
- offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = offset*0.8
- offset2 = offset*0.5
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, 0)
- path.line_to(offset, 0)
- path.move_to(0, 0)
- path.line_to(-offset2, offset1)
- path.move_to(0, 0)
- path.line_to(-offset2, -offset1)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y, x+offset, y)
- renderer.draw_line(gc, x, y, x-offset2, y+offset1)
- renderer.draw_line(gc, x, y, x-offset2, y-offset1)
+	
+ def _draw_tri_right(self, renderer, gc, path):
+	offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset).rotate_deg(270)
+	renderer.draw_markers(gc, self._tri_path, transform,
+			 path, self.get_transform())
 
- def _draw_caretdown(self, renderer, gc, xt, yt):
+
+ _caret_path = Path([[-1.0, 1.5], [0.0, 0.0], [1.0, 1.5]], closed=False)
+ def _draw_caretdown(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = 1.5*offset
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset, offset1)
- path.line_to(0, 0)
- path.line_to(+offset, offset1)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y+offset1, x, y)
- renderer.draw_line(gc, x, y, x+offset, y+offset1)
+	transform = Affine2D().scale(offset)
+	renderer.draw_markers(gc, self._caret_path, transform,
+			 path, self.get_transform())
 
- def _draw_caretup(self, renderer, gc, xt, yt):
+	
+ def _draw_caretup(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = 1.5*offset
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset, -offset1)
- path.line_to(0, 0)
- path.line_to(+offset, -offset1)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y-offset1, x, y)
- renderer.draw_line(gc, x, y, x+offset, y-offset1)
+	transform = Affine2D().scale(offset).rotate_deg(180)
+	renderer.draw_markers(gc, self._caret_path, transform,
+			 path, self.get_transform())
 
- def _draw_caretleft(self, renderer, gc, xt, yt):
+	
+ def _draw_caretleft(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = 1.5*offset
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(offset1, -offset)
- path.line_to(0, 0)
- path.line_to(offset1, offset)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x+offset1, y-offset, x, y)
- renderer.draw_line(gc, x, y, x+offset1, y+offset)
+	transform = Affine2D().scale(offset).rotate_deg(90)
+	renderer.draw_markers(gc, self._caret_path, transform,
+			 path, self.get_transform())
 
- def _draw_caretright(self, renderer, gc, xt, yt):
+	
+ def _draw_caretright(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
- offset1 = 1.5*offset
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset1, -offset)
- path.line_to(0, 0)
- path.line_to(-offset1, offset)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset1, y-offset, x, y)
- renderer.draw_line(gc, x, y, x-offset1, y+offset)
+	transform = Affine2D().scale(offset).rotate_deg(270)
+	renderer.draw_markers(gc, self._caret_path, transform,
+			 path, self.get_transform())
 
+
+ _x_path = Path([[-1.0, -1.0], [1.0, 1.0],
+		 [-1.0, 1.0], [1.0, -1.0]],
+		 [Path.MOVETO, Path.LINETO,
+		 Path.MOVETO, Path.LINETO])
 def _draw_x(self, renderer, gc, xt, yt):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset)
+	renderer.draw_markers(gc, self._x_path, transform,
+			 path, self.get_transform())
 
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset, -offset)
- path.line_to(offset, offset)
- path.move_to(-offset, offset)
- path.line_to(offset, -offset)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y-offset, x+offset, y+offset)
- renderer.draw_line(gc, x-offset, y+offset, x+offset, y-offset)
-
+	
 def update_from(self, other):
 'copy properties from other to self'
 Artist.update_from(self, other)
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -50,6 +50,9 @@
 		i += NUM_VERTICES[code]
 	 assert i == len(self.vertices)
 
+ def __repr__(self):
+	return "Path(%s, %s)" % (self.vertices, self.codes)
+	 
 def _get_codes(self):
 	return self._codes
 codes = property(_get_codes)
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -88,11 +88,13 @@
 intervaly = property(_get_intervaly)
 
 def _get_width(self):
- return self.xmax - self.xmin
+	points = self.get_points()
+	return points[1, 0] - points[0, 0]
 width = property(_get_width)
 
 def _get_height(self):
- return self.ymax - self.ymin
+	points = self.get_points()
+	return points[1, 1] - points[0, 1]
 height = property(_get_height)
 
 def _get_bounds(self):
Modified: branches/transforms/lib/matplotlib/type1font.py
===================================================================
--- branches/transforms/lib/matplotlib/type1font.py	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/lib/matplotlib/type1font.py	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -1,15 +1,15 @@
 """
 A class representing a Type 1 font.
 
-This version merely allows reading in pfa and pfb files, stores the
-data in pfa format, and allows reading the parts of the data in a
-format suitable for embedding in pdf files. A more complete class
-might support subsetting.
+This version merely reads pfa and pfb files and splits them for
+embedding in pdf files. There is no support yet for subsetting or
+anything like that.
 
-Usage: font = Type1Font(filename)
- somefile.write(font.data) # writes out font in pfa format
- len1, len2, len3 = font.lengths() # needed for pdf embedding
+Usage (subject to change):
 
+ font = Type1Font(filename)
+ clear_part, encrypted_part, finale = font.parts
+
 Source: Adobe Technical Note #5040, Supporting Downloadable PostScript
 Language Fonts.
 
@@ -32,8 +32,7 @@
 def _read(self, file):
 rawdata = file.read()
 if not rawdata.startswith(chr(128)):
- self.data = rawdata
- return
+ return rawdata
 
 data = ''
 while len(rawdata) > 0:
@@ -101,4 +100,6 @@
 if __name__ == '__main__':
 import sys
 font = Type1Font(sys.argv[1])
- sys.stdout.write(font.data)
+ parts = font.parts
+ print len(parts[0]), len(parts[1]), len(parts[2])
+
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月17日 13:41:38 UTC (rev 3854)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月18日 16:21:37 UTC (rev 3855)
@@ -10,7 +10,6 @@
 #include <time.h>
 #include <algorithm>
 
-
 #include "agg_conv_transform.h"
 #include "agg_conv_curve.h"
 #include "agg_scanline_storage_aa.h"
@@ -43,28 +42,48 @@
 #define M_PI_2 1.57079632679489661923
 #endif
 
-agg::trans_affine py_sequence_to_agg_transformation_matrix(const Py::Object& obj) {
- Py::SeqBase<Py::Float> seq;
+/** A helper function to convert from a Numpy affine transformation matrix
+ * to an agg::trans_affine.
+ */
+agg::trans_affine py_to_agg_transformation_matrix(const Py::Object& obj) {
+ PyArrayObject* matrix = NULL;
+ 
+ double a = 1.0, b = 0.0, c = 0.0, d = 1.0, e = 0.0, f = 0.0;
+
 try {
- seq = obj;
- } catch(...) {
- throw Py::ValueError("Transformation matrix must be given as a 6-element list.");
- }
+ matrix = (PyArrayObject*) PyArray_ContiguousFromObject(obj.ptr(), PyArray_DOUBLE, 2, 2);
+ if (!matrix || matrix->nd != 2 || matrix->dimensions[0] != 3 || matrix->dimensions[1] != 3) {
+ throw Py::ValueError("Invalid affine transformation matrix.");
+ }
 
- if (seq.size() != 6) {
- throw Py::ValueError("Transformation matrix must be given as a 6-element list.");
+ size_t stride0 = matrix->strides[0];
+ size_t stride1 = matrix->strides[1];
+ char* row0 = matrix->data;
+ char* row1 = row0 + stride0;
+
+ a = *(double*)(row0);
+ row0 += stride1;
+ c = *(double*)(row0);
+ row0 += stride1;
+ e = *(double*)(row0);
+ 
+ b = *(double*)(row1);
+ row1 += stride1;
+ d = *(double*)(row1);
+ row1 += stride1;
+ f = *(double*)(row1);
+ } catch (...) {
+ Py_XDECREF(matrix);
 }
 
- return agg::trans_affine
- (Py::Float(seq[0]), 
- Py::Float(seq[1]), 
- Py::Float(seq[2]), 
- Py::Float(seq[3]), 
- Py::Float(seq[4]), 
- Py::Float(seq[5]));
+ Py_XDECREF(matrix);
+
+ return agg::trans_affine(a, b, c, d, e, f);
 }
 
-// MGDTODO: Implement this as a nice iterator
+/** Helper function to get the next vertex in a Numpy array of vertices.
+ * Will generally be used through the GET_NEXT_VERTEX macro.
+ */
 inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, 
 			 double& x, double& y,
 			 size_t next_vertex_stride, 
@@ -78,12 +97,18 @@
 
 #define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride)
 
+Py::Object BufferRegion::to_string(const Py::Tuple &args) {
+ 
+ // owned=true to prevent memory leak
+ return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true);
+}
+
+
 GCAgg::GCAgg(const Py::Object &gc, double dpi, bool snapto) :
 dpi(dpi), snapto(snapto), isaa(true), linewidth(1.0), alpha(1.0),
 cliprect(NULL), clippath(NULL), 
 Ndash(0), dashOffset(0.0), dasha(NULL)
 {
- 
 _VERBOSE("GCAgg::GCAgg");
 linewidth = points_to_pixels ( gc.getAttr("_linewidth") ) ;
 alpha = Py::Float( gc.getAttr("_alpha") );
@@ -100,7 +125,6 @@
 GCAgg::_set_antialiased(const Py::Object& gc) {
 _VERBOSE("GCAgg::antialiased");
 isaa = Py::Int( gc.getAttr( "_antialiased") );
- 
 }
 
 agg::rgba
@@ -123,13 +147,12 @@
 return p * dpi/72.0;
 }
 
-
 void
 GCAgg::_set_linecap(const Py::Object& gc) {
 _VERBOSE("GCAgg::_set_linecap");
 
 std::string capstyle = Py::String( gc.getAttr( "_capstyle" ) );
- 
+
 if (capstyle=="butt")
 cap = agg::butt_cap;
 else if (capstyle=="round")
@@ -138,7 +161,6 @@
 cap = agg::square_cap;
 else
 throw Py::ValueError(Printf("GC _capstyle attribute must be one of butt, round, projecting; found %s", capstyle.c_str()).str());
- 
 }
 
 void
@@ -155,7 +177,6 @@
 join = agg::bevel_join;
 else
 throw Py::ValueError(Printf("GC _joinstyle attribute must be one of butt, round, projecting; found %s", joinstyle.c_str()).str());
- 
 }
 
 void
@@ -193,7 +214,7 @@
 }
 }
 
-
+// MGDTODO: Convert directly from Bbox object (numpy)
 void
 GCAgg::_set_clip_rectangle( const Py::Object& gc) {
 //set the clip rectangle from the gc
@@ -204,7 +225,7 @@
 cliprect = NULL;
 
 Py::Object o ( gc.getAttr( "_cliprect" ) );
- if (o.ptr()==Py_None) {
+ if (o.ptr() == Py_None) {
 return;
 }
 
@@ -229,38 +250,18 @@
 
 _VERBOSE("GCAgg::_set_clip_path");
 
- delete clippath;
+ Py_XINCREF(clippath);
 clippath = NULL;
 
- Py::Object o = gc.getAttr( "_clippath" );
+ Py::Object o = gc.getAttr("_clippath");
 if (o.ptr()==Py_None) {
 return;
 }
 
- agg::path_storage *tmppath;
- swig_type_info * descr = SWIG_TypeQuery("agg::path_storage *");
- assert(descr);
- if (SWIG_ConvertPtr(o.ptr(),(void **)(&tmppath), descr, 0) == -1) {
- throw Py::TypeError("Could not convert gc path_storage");
- }
- 
- tmppath->rewind(0);
- clippath = new agg::path_storage();
- clippath->copy_from(*tmppath);
- clippath->rewind(0);
- tmppath->rewind(0);
+ clippath = new PathAgg(o);
 }
 
 
-Py::Object BufferRegion::to_string(const Py::Tuple &args) {
- 
- // owned=true to prevent memory leak
- return Py::String(PyString_FromStringAndSize((const char*)aggbuf.data,aggbuf.height*aggbuf.stride), true);
-}
-
-
-
-
 const size_t
 RendererAgg::PIXELS_PER_INCH(96);
 
@@ -311,19 +312,14 @@
 
 
 void
-RendererAgg::set_clipbox_rasterizer( double *cliprect) {
+RendererAgg::set_clipbox_rasterizer(double *cliprect) {
 //set the clip rectangle from the gc
 
 _VERBOSE("RendererAgg::set_clipbox_rasterizer");
- 
 
 theRasterizer->reset_clipping();
 rendererBase->reset_clipping(true);
 
- //if (cliprect==NULL) {
- // theRasterizer->reset_clipping();
- // rendererBase->reset_clipping(true);
- //}
 if (cliprect!=NULL) {
 
 double l = cliprect[0] ;
@@ -355,273 +351,10 @@
 
 }
 
-// MGDTODO: Remove this method (it has been conglomerated into draw_path
-template <class VS>
-void
-RendererAgg::_fill_and_stroke(VS& path,
-			 const GCAgg& gc,
-			 const facepair_t& face,
-			 bool curvy) {
- typedef agg::conv_curve<VS> curve_t;
- 
- //bool isclippath(gc.clippath!=NULL);
- //if (isclippath) _process_alpha_mask(gc); 
-
- if (face.first) {
- rendererAA->color(face.second);
- if (curvy) {
- curve_t curve(path);
- theRasterizer->add_path(curve);
- }
- else
- theRasterizer->add_path(path);
- 
- /*
- if (isclippath) {
-	typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
-	typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
-	pixfmt_amask_type pfa(*pixFmt, *alphaMask);
-	amask_ren_type r(pfa);
-	typedef agg::renderer_scanline_aa_solid<amask_ren_type> renderer_type;
-	renderer_type ren(r);
-	ren.color(gc.color);
-	//std::cout << "render clippath" << std::endl;
-	
-	agg::render_scanlines(*theRasterizer, *slineP8, ren);
- }
- else {
-	rendererAA->color(gc.color);
-	agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
- }
- */
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
- }
- 
- //now stroke the edge
- if (gc.linewidth) {
- if (curvy) {
- curve_t curve(path);
- agg::conv_stroke<curve_t> stroke(curve);
- stroke.width(gc.linewidth);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- theRasterizer->add_path(stroke);
- }
- else {
- agg::conv_stroke<VS> stroke(path);
- stroke.width(gc.linewidth);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- theRasterizer->add_path(stroke);
- }
- 
- 
- /*
- if ( gc.isaa ) {
- if (isclippath) {
-	typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
-	typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
-	pixfmt_amask_type pfa(*pixFmt, *alphaMask);
-	amask_ren_type r(pfa);
-	typedef agg::renderer_scanline_aa_solid<amask_ren_type> renderer_type;
-	renderer_type ren(r);
-	ren.color(gc.color);
-	//std::cout << "render clippath" << std::endl;
-	
-	agg::render_scanlines(*theRasterizer, *slineP8, ren);
- }
- else {
-	rendererAA->color(gc.color);
-	agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
- }
- }
- else {
- if (isclippath) {
-	typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
-	typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
-	pixfmt_amask_type pfa(*pixFmt, *alphaMask);
-	amask_ren_type r(pfa);
-	typedef agg::renderer_scanline_bin_solid<amask_ren_type> renderer_type;
-	renderer_type ren(r);
-	ren.color(gc.color);
-	agg::render_scanlines(*theRasterizer, *slineP8, ren);
- }
- else{
-	rendererBin->color(gc.color);
-	agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin);
- }
- }
-
- */
- 
- if ( gc.isaa ) {
- rendererAA->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
- }
- else {
- rendererBin->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin);
- }
- }
- 
-
-}
-
-Py::Object
-RendererAgg::draw_rectangle(const Py::Tuple & args) {
- _VERBOSE("RendererAgg::draw_rectangle");
- args.verify_length(6);
- 
- 
- GCAgg gc = GCAgg(args[0], dpi);
- facepair_t face = _get_rgba_face(args[1], gc.alpha);
- 
- 
- double l = Py::Float( args[2] );
- double b = Py::Float( args[3] );
- double w = Py::Float( args[4] );
- double h = Py::Float( args[5] );
- 
- b = height - (b+h);
- double r = l + w;
- double t = b + h;
- 
- //snapto pixel centers
- l = (int)l + 0.5;
- b = (int)b + 0.5;
- r = (int)r + 0.5;
- t = (int)t + 0.5;
- 
- 
- set_clipbox_rasterizer(gc.cliprect);
- 
- agg::path_storage path;
- 
- 
- path.move_to(l, t);
- path.line_to(r, t);
- path.line_to(r, b);
- path.line_to(l, b);
- path.close_polygon();
- 
- _fill_and_stroke(path, gc, face, false);
- 
- return Py::Object();
- 
-}
-
-Py::Object
-RendererAgg::draw_ellipse(const Py::Tuple& args) {
- _VERBOSE("RendererAgg::draw_ellipse");
- args.verify_length(7);
- 
- GCAgg gc = GCAgg(args[0], dpi);
- facepair_t face = _get_rgba_face(args[1], gc.alpha);
- 
- double x = Py::Float( args[2] );
- double y = Py::Float( args[3] );
- double w = Py::Float( args[4] );
- double h = Py::Float( args[5] );
- double rot = Py::Float( args[6] );
- 
- double r; // rot in radians
- 
- set_clipbox_rasterizer(gc.cliprect);
- 
- // Approximate the ellipse with 4 bezier paths
- agg::path_storage path;
- if (rot == 0.0) // simple case
- {
- path.move_to(x, height-(y+h));
- path.arc_to(w, h, 0.0, false, true, x+w, height-y);
- path.arc_to(w, h, 0.0, false, true, x, height-(y-h));
- path.arc_to(w, h, 0.0, false, true, x-w, height-y);
- path.arc_to(w, h, 0.0, false, true, x, height-(y+h));
- path.close_polygon();
- }
- else // rotate by hand :(
- {
- // deg to rad
- r = rot * (M_PI/180.0);
- path.move_to( x+(cos(r)*w), height-(y+(sin(r)*w)));
- path.arc_to(w, h, -r, false, true, x+(cos(r+M_PI_2*3)*h), height-(y+(sin(r+M_PI_2*3)*h)));
- path.arc_to(w, h, -r, false, true, x+(cos(r+M_PI)*w), height-(y+(sin(r+M_PI)*w)));
- path.arc_to(w, h, -r, false, true, x+(cos(r+M_PI_2)*h), height-(y+(sin(r+M_PI_2)*h)));
- path.arc_to(w, h, -r, false, true, x+(cos(r)*w), height-(y+(sin(r)*w)));
- path.close_polygon();
- }
- 
- _fill_and_stroke(path, gc, face);
- return Py::Object();
- 
-}
-
-Py::Object
-RendererAgg::draw_polygon(const Py::Tuple& args) {
- _VERBOSE("RendererAgg::draw_polygon");
- 
- args.verify_length(3);
- 
- GCAgg gc = GCAgg(args[0], dpi);
- facepair_t face = _get_rgba_face(args[1], gc.alpha);
- 
- Py::SeqBase<Py::Object> points( args[2] );
- 
- set_clipbox_rasterizer(gc.cliprect);
- 
- size_t Npoints = points.length();
- if (Npoints<=0)
- return Py::Object();
- 
- 
- // dump the x.y vertices into a double array for faster look ahead
- // and behind access
- double *xs = new double[Npoints];
- double *ys = new double[Npoints];
- 
- for (size_t i=0; i<Npoints; i++) {
- Py::SeqBase<Py::Object> xy(points[i]);
- xy = Py::Tuple(points[i]);
- xs[i] = Py::Float(xy[0]);
- ys[i] = Py::Float(xy[1]);
- ys[i] = height - ys[i];
- }
- 
- 
- 
- agg::path_storage path;
- for (size_t j=0; j<Npoints; j++) {
- 
- double x = xs[j];
- double y = ys[j];
- 
- //snapto pixel centers
- x = (int)x + 0.5;
- y = (int)y + 0.5;
- 
- if (j==0) path.move_to(x,y);
- else path.line_to(x,y);
- }
- path.close_polygon();
- 
- _fill_and_stroke(path, gc, face, false);
- 
- delete [] xs;
- delete [] ys;
- 
- _VERBOSE("RendererAgg::draw_polygon DONE");
- return Py::Object();
- 
-}
-
-
-
 SnapData
 SafeSnap::snap (const float& x, const float& y) {
 xsnap = (int)x + 0.5;
 ysnap = (int)y + 0.5;
-
-
 
 if ( first || ( (xsnap!=lastxsnap) || (ysnap!=lastysnap) ) ) {
 lastxsnap = xsnap;
@@ -690,9 +423,6 @@
 rb.copy_from(*renderingBuffer, &r, -r.x1, -r.y1);
 BufferRegion* reg = new BufferRegion(buf, r, true);
 return Py::asObject(reg);
- 
- 
- 
 }
 
 Py::Object
@@ -715,25 +445,20 @@
 rendererBase->copy_from(rbuf, 0, region->rect.x1, region->rect.y1);
 
 return Py::Object();
- 
- 
- 
 }
 
-
+/**
+ * Helper function to convert a Python Bbox object to an agg rectangle
+ */
 template<class T>
 agg::rect_base<T>
 RendererAgg::bbox_to_rect(const Py::Object& o) {
 //return the agg::rect for bbox, flipping y
 PyArrayObject *bbox = (PyArrayObject *) PyArray_ContiguousFromObject(o.ptr(), PyArray_DOUBLE, 2, 2);
 
- if (!bbox)
+ if (!bbox || bbox->nd != 2 bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2)
 throw Py::TypeError
 ("Expected a Bbox object.");
- 
- if (bbox->nd != 2 || bbox->dimensions[0] != 2 || bbox->dimensions[1] != 2)
- throw Py::TypeError
- ("Expected a Bbox object.");
 
 double l = bbox->data[0];
 double b = bbox->data[1];
@@ -805,469 +530,8 @@
 return numIntersect;
 }
 
-void RendererAgg::DrawQuadMesh(int meshWidth, int meshHeight, const agg::rgba8 colorArray[], const double xCoords[], const double yCoords[])
-{
- /* draw each quadrilateral */
- //	agg::renderer_primitives<agg::renderer_base<agg::pixfmt_rgba32> > lineRen(*rendererBase);
- int i = 0;
- int j = 0;
- int k = 0;
- double xs[4];
- double ys[4];
- int col[4];
- int numCol;
- double ymin;
- int firstRow;
- double ymax;
- int lastRow;
- for(i=0; i < meshHeight; i++)
- {
- for(j=0; j < meshWidth; j++)
-	{
-	 //currTime = clock();
-	 xs[0] = xCoords[(i * (meshWidth + 1)) + j];
-	 ys[0] = yCoords[(i * (meshWidth + 1)) + j];
-	 xs[1] = xCoords[(i * (meshWidth + 1)) + j+1];
-	 ys[1] = yCoords[(i * (meshWidth + 1)) + j+1];
-	 xs[3] = xCoords[((i+1) * (meshWidth + 1)) + j];
-	 ys[3] = yCoords[((i+1) * (meshWidth + 1)) + j];
-	 xs[2] = xCoords[((i+1) * (meshWidth + 1)) + j+1];
-	 ys[2] = yCoords[((i+1) * (meshWidth + 1)) + j+1];
-	 ymin = std::min(std::min(std::min(ys[0], ys[1]), ys[2]), ys[3]);
-	 ymax = std::max(std::max(std::max(ys[0], ys[1]), ys[2]), ys[3]);
-	 firstRow = (int)(ymin);
-	 lastRow = (int)(ymax);
-	 //timer1 += (clock() - currTime);
-	 //currTime = clock();
-	 //timer2 += (clock() - currTime);
-	 //currTime = clock();
-	 for(k = firstRow; k <= lastRow; k++)
-	 {
-	 numCol = inPolygon(k, xs, ys, col);
-	 if (numCol >= 2) rendererBase->copy_hline(col[0], k, col[1] - 1, colorArray[(i * meshWidth) + j]);
-	 if (numCol == 4) rendererBase->copy_hline(col[2], k, col[3] - 1, colorArray[(i * meshWidth) + j]);
-	 }
-	}
- }
- return;
-}
 
-void RendererAgg::DrawQuadMeshEdges(int meshWidth, int meshHeight, const agg::rgba8 colorArray[], const double xCoords[], const double yCoords[])
-{
- int i, j;
- agg::renderer_primitives<agg::renderer_base<agg::pixfmt_rgba32> > lineRen(*rendererBase);
- agg::rgba8 lc(0, 0, 0, 32);
- lineRen.line_color(lc);
- /* show the vertical edges */
- for(i=0; i <= meshWidth; i++)
- {
- lineRen.move_to((int)(256.0 * (xCoords[i])), (int)(256.0 * (yCoords[i])));
- for(j=1; j <= meshHeight; j++)
-	lineRen.line_to((int)(256.0 *(xCoords[(j * (meshWidth + 1))+i])), (int)(256.0 * (yCoords[(j * (meshWidth + 1))+i])));
- }
- /* show the horizontal edges */
- for(i=0; i <= meshHeight; i++)
- {
- lineRen.move_to((int)(256.0 * (xCoords[i * (meshWidth + 1)])), (int)(256.0 * (yCoords[i * (meshWidth + 1)])));
- for(j=1; j <= meshWidth; j++)
-	lineRen.line_to((int)(256.0 * (xCoords[(i * (meshWidth + 1))+j])), (int)(256.0 * (yCoords[(i * (meshWidth + 1))+j])));
- }
-}
-
-
-
 Py::Object
-RendererAgg::draw_lines(const Py::Tuple& args) {
- 
- _VERBOSE("RendererAgg::draw_lines");
- args.verify_length(4);
-
- Py::Object xo = args[1];
- Py::Object yo = args[2];
-
- PyArrayObject *xa = (PyArrayObject *) PyArray_ContiguousFromObject(xo.ptr(), PyArray_DOUBLE, 1, 1);
-
- if (xa==NULL)
- throw Py::TypeError("RendererAgg::draw_lines expected numerix array");
-
-
- PyArrayObject *ya = (PyArrayObject *) PyArray_ContiguousFromObject(yo.ptr(), PyArray_DOUBLE, 1, 1);
-
- if (ya==NULL)
- throw Py::TypeError("RendererAgg::draw_lines expected numerix array");
-
-
- size_t Nx = xa->dimensions[0];
- size_t Ny = ya->dimensions[0];
-
- if (Nx!=Ny)
- throw Py::ValueError(Printf("x and y must be equal length arrays; found %d and %d", Nx, Ny).str());
-
- // call gc with snapto==True if line len is 2 to fix grid line
- // problem
- bool snapto = false;
- if (Nx==2) {
- // disable subpiel rendering for len(2) horizontal or vertical
- // lines
- double x0 = *(double *)(xa->data + 0*xa->strides[0]);
- double x1 = *(double *)(xa->data + 1*xa->strides[0]);
- double y0 = *(double *)(ya->data + 0*ya->strides[0]);
- double y1 = *(double *)(ya->data + 1*ya->strides[0]);
- snapto = (x0==x1) || (y0==y1);
-
- }
- GCAgg gc = GCAgg(args[0], dpi, snapto);
-
- set_clipbox_rasterizer(gc.cliprect);
- //path_t transpath(path, xytrans);
- _process_alpha_mask(gc);
-
- agg::trans_affine xytrans = py_sequence_to_agg_transformation_matrix(args[3]);
-
- agg::path_storage path;
-
- // MGDTODO
- bool needNonlinear = false;
- // mpltransform->need_nonlinear_api();
-
- double thisx(0.0), thisy(0.0);
- double origdx(0.0), origdy(0.0), origdNorm2(0);
- bool moveto = true;
- double heightd = height;
-
- double lastx(0), lasty(0);
- double lastWrittenx(0), lastWritteny(0);
- bool clipped = false;
- 
- bool haveMin = false, lastMax = true;
- double dnorm2Min(0), dnorm2Max(0);
- double maxX(0), maxY(0), minX(0), minY(0);
- 
- double totdx, totdy, totdot;
- double paradx, parady, paradNorm2;
- double perpdx, perpdy, perpdNorm2;
- 
- int counter = 0;
- //idea: we can skip drawing many lines: lines < 1 pixel in length, lines 
- //outside of the drawing area, and we can combine sequential parallel lines
- //into a single line instead of redrawing lines over the same points.
- //The loop below works a bit like a state machine, where what it does depends 
- //on what it did in the last looping. To test whether sequential lines
- //are close to parallel, I calculate the distance moved perpendicular to the
- //last line. Once it gets too big, the lines cannot be combined.
- for (size_t i=0; i<Nx; i++) {
-
- thisx = *(double *)(xa->data + i*xa->strides[0]);
- thisy = *(double *)(ya->data + i*ya->strides[0]);
-
- if (needNonlinear)
- try {
-	// MGDTODO
- // mpltransform->nonlinear_only_api(&thisx, &thisy);
- }
- catch (...) {
- moveto = true;
- continue;
- }
- if (MPL_isnan64(thisx) || MPL_isnan64(thisy)) {
- moveto = true;
- continue;
- }
- 
- //use agg's transformer?
- xytrans.transform(&thisx, &thisy);
- thisy = heightd - thisy; //flipy
- 
- if (snapto) {
- //disable subpixel rendering for horizontal or vertical lines of len=2
- //because it causes irregular line widths for grids and ticks
- thisx = (int)thisx + 0.5;
- thisy = (int)thisy + 0.5;
- }
- 
- //if we are starting a new path segment, move to the first point + init
- if(moveto){
- path.move_to(thisx, thisy);
- lastx = thisx;
- lasty = thisy;
- origdNorm2 = 0; //resets the orig-vector variables (see if-statement below)
- moveto = false;
- continue;
- }
-
- //don't render line segments less that on pixel long!
- if (fabs(thisx-lastx) < 1.0 && fabs(thisy-lasty) < 1.0 ){
- continue; //don't update lastx this time!
- }
- 
- //skip any lines that are outside the drawing area. Note: More lines
- //could be clipped, but a more involved calculation would be needed
- if( (thisx < 0 && lastx < 0 ) ||
- (thisx > width && lastx > width ) ||
- (thisy < 0 && lasty < 0 ) ||
- (thisy > height && lasty > height) ){
- lastx = thisx;
- lasty = thisy;
- clipped = true; 
- continue;
- }
- 
- //if we have no orig vector, set it to this vector and continue.
- //this orig vector is the reference vector we will build up the line to
- if(origdNorm2 == 0){
- //if we clipped after the moveto but before we got here, redo the moveto
- if(clipped){
- path.move_to(lastx, lasty);
- clipped = false;
- }
- 
- origdx = thisx - lastx;
- origdy = thisy - lasty;
- origdNorm2 = origdx*origdx + origdy*origdy;
- 
- //set all the variables to reflect this new orig vecor
- dnorm2Max = origdNorm2;
- dnorm2Min = 0;
- haveMin = false;
- lastMax = true;
- maxX = thisx;
- maxY = thisy;
- minX = lastx; 
- minY = lasty; 
- 
- lastWrittenx = lastx;
- lastWritteny = lasty; 
- 
- //set the last point seen
- lastx = thisx;
- lasty = thisy; 
- continue;
- }
- 
- //if got to here, then we have an orig vector and we just got 
- //a vector in the sequence.
- 
- //check that the perpendicular distance we have moved from the
- //last written point compared to the line we are building is not too 
- //much. If o is the orig vector (we are building on), and v is the vector 
- //from the last written point to the current point, then the perpendicular 
- //vector is p = v - (o.v)o, and we normalize o (by dividing the 
- //second term by o.o). 
- 
- //get the v vector
- totdx = thisx - lastWrittenx;
- totdy = thisy - lastWritteny;
- totdot = origdx*totdx + origdy*totdy;
- 
- //get the para vector ( = (o.v)o/(o.o) )
- paradx = totdot*origdx/origdNorm2;
- parady = totdot*origdy/origdNorm2;
- paradNorm2 = paradx*paradx + parady*parady;
- 
- //get the perp vector ( = v - para )
- perpdx = totdx - paradx;
- perpdy = totdy - parady; 
- perpdNorm2 = perpdx*perpdx + perpdy*perpdy; 
- 
- //if the perp vector is less than some number of (squared) pixels in size,
- //then merge the current vector
- if(perpdNorm2 < 0.25 ){
- //check if the current vector is parallel or
- //anti-parallel to the orig vector. If it is parallel, test
- //if it is the longest of the vectors we are merging in that direction. 
- //If anti-p, test if it is the longest in the opposite direction (the 
- //min of our final line)
- 
- lastMax = false;
- if(totdot >= 0){
- if(paradNorm2 > dnorm2Max){
- lastMax = true;
- dnorm2Max = paradNorm2;
- maxX = lastWrittenx + paradx;
- maxY = lastWritteny + parady;
- }
- }
- else{
- 
- haveMin = true;
- if(paradNorm2 > dnorm2Min){
- dnorm2Min = paradNorm2;
- minX = lastWrittenx + paradx;
- minY = lastWritteny + parady;
- }
- }
- 
- lastx = thisx;
- lasty = thisy;
- continue;
- }
- 
- //if we get here, then this vector was not similar enough to the line
- //we are building, so we need to draw that line and start the next one.
- 
- //if the line needs to extend in the opposite direction from the direction
- //we are drawing in, move back to we start drawing from back there.
- if(haveMin){
- path.line_to(minX, minY); //would be move_to if not for artifacts
- }
- 
- path.line_to(maxX, maxY);
- 
- //if we clipped some segments between this line and the next line
- //we are starting, we also need to move to the last point.
- if(clipped){
- path.move_to(lastx, lasty);
- }
- else if(!lastMax){
- 	//if the last line was not the longest line, then move back to the end 
- //point of the last line in the sequence. Only do this if not clipped,
- //since in that case lastx,lasty is not part of the line just drawn.
- path.line_to(lastx, lasty); //would be move_to if not for artifacts
- } 
-
- //std::cout << "draw lines (" << lastx << ", " << lasty << ")" << std::endl;
-
- //now reset all the variables to get ready for the next line
- 
- origdx = thisx - lastx;
- origdy = thisy - lasty;
- origdNorm2 = origdx*origdx + origdy*origdy;
- 
- dnorm2Max = origdNorm2;
- dnorm2Min = 0;
- haveMin = false;
- lastMax = true;
- maxX = thisx;
- maxY = thisy;
- minX = lastx; 
- minY = lasty;
- 
- lastWrittenx = lastx;
- lastWritteny = lasty; 
- 
- clipped = false;
- 
- lastx = thisx;
- lasty = thisy;
- 
- counter++;
- }
-
- //draw the last line, which is usually not drawn in the loop
- if(origdNorm2 != 0){
- if(haveMin){
- path.line_to(minX, minY); //would be move_to if not for artifacts
- } 
- 
- path.line_to(maxX, maxY);
- }
- 
- //std::cout << "drew " << counter+1 << " lines" << std::endl;
-
- Py_XDECREF(xa);
- Py_XDECREF(ya);
-
- //typedef agg::conv_transform<agg::path_storage, agg::trans_affine> path_t;
- //path_t transpath(path, xytrans);
- _VERBOSE("RendererAgg::draw_lines rendering lines path");
- _render_lines_path(path, gc);
-
- _VERBOSE("RendererAgg::draw_lines DONE");
- return Py::Object();
-
-}
-
-bool 
-RendererAgg::_process_alpha_mask(const GCAgg& gc)
- //if gc has a clippath set, process the alpha mask and return True,
- //else return False
-{
- if (gc.clippath==NULL) {
- return false;
- }
- if (0 &(gc.clippath==lastclippath)) {
- //std::cout << "seen it" << std::endl;
- return true;
- }
- rendererBaseAlphaMask->clear(agg::gray8(0, 0));
- gc.clippath->rewind(0);
- theRasterizer->add_path(*(gc.clippath));
- rendererAlphaMask->color(agg::gray8(255,255));
- agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
- lastclippath = gc.clippath;
- return true;
-}
-
-template<class PathSource>
-void
-RendererAgg::_render_lines_path(PathSource &path, const GCAgg& gc) {
- _VERBOSE("RendererAgg::_render_lines_path");
- typedef PathSource path_t;
- //typedef agg::conv_transform<agg::path_storage, agg::trans_affine> path_t;
- typedef agg::conv_stroke<path_t> stroke_t;
- typedef agg::conv_dash<path_t> dash_t;
- 
- bool isclippath(gc.clippath!=NULL);
- 
- if (gc.dasha==NULL ) { //no dashes
- stroke_t stroke(path);
- stroke.width(gc.linewidth);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- theRasterizer->add_path(stroke);
- }
- else {
- dash_t dash(path);
- 
- //todo: dash.dash_start(gc.dashOffset);
- for (size_t i=0; i<gc.Ndash/2; i+=1)
- dash.add_dash(gc.dasha[2*i], gc.dasha[2*i+1]);
- 
- agg::conv_stroke<dash_t> stroke(dash);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- stroke.width(gc.linewidth);
- theRasterizer->add_path(stroke); //boyle freeze is herre
- }
- 
- 
- if ( gc.isaa ) {
- if (isclippath) {
- typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
- typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
- pixfmt_amask_type pfa(*pixFmt, *alphaMask);
- amask_ren_type r(pfa);
- typedef agg::renderer_scanline_aa_solid<amask_ren_type> renderer_type;
- renderer_type ren(r);
- ren.color(gc.color);
- //std::cout << "render clippath" << std::endl;
- 
- agg::render_scanlines(*theRasterizer, *slineP8, ren);
- }
- else {
- rendererAA->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
- }
- }
- else {
- if (isclippath) {
- typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
- typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
- pixfmt_amask_type pfa(*pixFmt, *alphaMask);
- amask_ren_type r(pfa);
- typedef agg::renderer_scanline_bin_solid<amask_ren_type> renderer_type;
- renderer_type ren(r);
- ren.color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineP8, ren);
- }
- else{
- rendererBin->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin);
- }
- }
-}
-
-Py::Object
 RendererAgg::draw_markers(const Py::Tuple& args) {
 typedef agg::conv_transform<agg::path_storage> transformed_path_t;
 typedef agg::conv_curve<transformed_path_t> curve_t;
@@ -1284,10 +548,10 @@
 if (!PathAgg::check(marker_path_obj))
 throw Py::TypeError("Native path object is not of correct type");
 PathAgg* marker_path = static_cast<PathAgg*>(marker_path_obj.ptr());
- agg::trans_affine marker_trans = py_sequence_to_agg_transformation_matrix(args[2]);
+ agg::trans_affine marker_trans = py_to_agg_transformation_matrix(args[2]);
 Py::Object vertices_obj = args[3];
 Py::Object codes_obj = args[4];
- agg::trans_affine trans = py_sequence_to_agg_transformation_matrix(args[5]);
+ agg::trans_affine trans = py_to_agg_transformation_matrix(args[5]);
 facepair_t face = _get_rgba_face(args[6], gc.alpha);
 
 // Deal with the difference in y-axis direction
@@ -1337,7 +601,8 @@
 unsigned strokeSize = scanlines.byte_size();
 strokeCache = new agg::int8u[strokeSize]; // or any container
 scanlines.serialize(strokeCache);
- 
+
+ // MGDTODO: Clean this up and support clippaths as well
 theRasterizer->reset_clipping();
 if (gc.cliprect==NULL) {
 rendererBase->reset_clipping(true);
@@ -1557,14 +822,20 @@
 Py::Object
 RendererAgg::convert_to_native_path(const Py::Tuple& args) {
 _VERBOSE("RendererAgg::draw_image");
- args.verify_length(2);
+ args.verify_length(1);
 
- Py::Object vertices_obj = args[0];
- Py::Object codes_obj = args[1];
+ Py::Object path = args[0];
+
+ return Py::asObject(new PathAgg(path));
+}
+
 
+PathAgg::PathAgg(const Py::Object& path_obj) : curvy(false) {
+ Py::Object vertices_obj = path_obj.getAttr("vertices");
+ Py::Object codes_obj = path_obj.getAttr("codes");
+ 
 PyArrayObject* vertices = NULL;
 PyArrayObject* codes = NULL;
- PathAgg* path = NULL; 
 
 try {
 vertices = (PyArrayObject*)PyArray_ContiguousFromObject
@@ -1576,8 +847,6 @@
 if (!codes) 
 throw Py::ValueError("Invalid codes array.");
 
- path = new PathAgg();
-
 size_t next_vertex_stride = vertices->strides[0];
 size_t next_axis_stride = vertices->strides[1];
 size_t code_stride = codes->strides[0];
@@ -1593,31 +862,31 @@
 switch (*(unsigned char*)(code_i)) {
 case MOVETO:
 	GET_NEXT_VERTEX(x0, y0);
-	path->move_to(x0, y0);
+	move_to(x0, y0);
 	_VERBOSE("MOVETO");
 	break;
 case LINETO:
 	GET_NEXT_VERTEX(x0, y0);
-	path->line_to(x0, y0);
+	line_to(x0, y0);
 	_VERBOSE("LINETO");
 	break;
 case CURVE3:
 	GET_NEXT_VERTEX(x0, y0);
 	GET_NEXT_VERTEX(x1, y1);
-	path->curve3(x0, y0, x1, y1);
-	path->curvy = true;
+	curve3(x0, y0, x1, y1);
+	curvy = true;
 	_VERBOSE("CURVE3");
 	break;
 case CURVE4:
 	GET_NEXT_VERTEX(x0, y0);
 	GET_NEXT_VERTEX(x1, y1);
 	GET_NEXT_VERTEX(x2, y2);
-	path->curve4(x0, y0, x1, y1, x2, y2);
-	path->curvy = true;
+	curve4(x0, y0, x1, y1, x2, y2);
+	curvy = true;
 	_VERBOSE("CURVE4");
 	break;
 case CLOSEPOLY:
-	path->close_polygon();
+	close_polygon();
 	_VERBOSE("CLOSEPOLY");
 	break;
 }
@@ -1626,14 +895,11 @@
 } catch(...) {
 Py_XDECREF(vertices);
 Py_XDECREF(codes);
- delete path;
 throw;
 }
 
 Py_XDECREF(vertices);
 Py_XDECREF(codes);
- 
- return Py::asObject(path);
 }
 
 Py::Object
@@ -1643,7 +909,11 @@
 typedef agg::conv_stroke<curve_t> stroke_t;
 typedef agg::conv_dash<curve_t> dash_t;
 typedef agg::conv_stroke<dash_t> stroke_dash_t;
- //draw_path(gc, rgbFace, path, transform)
+ typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
+ typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
+ typedef agg::renderer_scanline_aa_solid<amask_ren_type> amask_aa_renderer_type;
+ typedef agg::renderer_scanline_bin_solid<amask_ren_type> amask_bin_renderer_type;
+
 theRasterizer->reset_clipping();
 
 _VERBOSE("RendererAgg::draw_path");
@@ -1654,52 +924,118 @@
 if (!PathAgg::check(path_obj))
 throw Py::TypeError("Native path object is not of correct type");
 PathAgg* path = static_cast<PathAgg*>(path_obj.ptr());
- agg::trans_affine trans = py_sequence_to_agg_transformation_matrix(args[2]);
+ agg::trans_affine trans = py_to_agg_transformation_matrix(args[2]);
 facepair_t face = _get_rgba_face(args[3], gc.alpha);
 
 trans *= agg::trans_affine_scaling(1.0, -1.0);
 trans *= agg::trans_affine_translation(0.0, (double)height);
 
- transformed_path_t tpath(*path, trans);
- // MGDTODO: See if there is any advantage to only curving if necessary
- curve_t curve(tpath);
+ transformed_path_t* tpath = NULL;
+ agg::path_storage new_path;
 
- set_clipbox_rasterizer(gc.cliprect);
- 
- if (face.first) {
- rendererAA->color(face.second);
- theRasterizer->add_path(curve);
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
+ bool has_clippath = (gc.clippath != NULL);
+
+ if (has_clippath && (gc.clippath != lastclippath || trans != lastclippath_transform)) {
+ rendererBaseAlphaMask->clear(agg::gray8(0, 0));
+ gc.clippath->rewind(0);
+ transformed_path_t transformed_clippath(*(gc.clippath), trans);
+ theRasterizer->add_path(transformed_clippath);
+ rendererAlphaMask->color(agg::gray8(255, 255));
+ agg::render_scanlines(*theRasterizer, *scanlineAlphaMask, *rendererAlphaMask);
+ lastclippath = gc.clippath;
+ lastclippath_transform = trans;
 }
 
- if (gc.linewidth) {
- if (gc.dasha == NULL) {
- stroke_t stroke(curve);
- stroke.width(gc.linewidth);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- theRasterizer->add_path(stroke);
- } else {
- dash_t dash(curve);
- for (size_t i = 0; i < (gc.Ndash / 2); ++i)
-	dash.add_dash(gc.dasha[2 * i], gc.dasha[2 * i + 1]);
- stroke_dash_t stroke(dash);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- stroke.width(gc.linewidth);
- theRasterizer->add_path(stroke); //boyle freeze is herre
+ try {
+ // If this is a straight horizontal or vertical line, quantize to nearest 
+ // pixels
+ if (path->total_vertices() == 2) {
+ double x0, y0, x1, y1;
+ path->vertex(0, &x0, &y0);
+ trans.transform(&x0, &y0);
+ path->vertex(1, &x1, &y1);
+ trans.transform(&x1, &y1);
+ if (((int)x0 == (int)x1) || ((int)y0 == (int)y1)) {
+	new_path.move_to((int)x0 + 0.5, (int)y0 + 0.5);
+	new_path.line_to((int)x1 + 0.5, (int)y1 + 0.5);
+	tpath = new transformed_path_t(new_path, agg::trans_affine());
+ }
 }
+
+ if (!tpath) {
+ tpath = new transformed_path_t(*path, trans);
+ }
+
+ // Benchmarking shows that there is no noticable slowdown to always
+ // treating paths as having curved segments. Doing so greatly 
+ // simplifies the code
+ curve_t curve(*tpath);
 
- if ( gc.isaa ) {
- rendererAA->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
+ set_clipbox_rasterizer(gc.cliprect);
+ 
+ if (face.first) {
+ if (has_clippath) {
+	pixfmt_amask_type pfa(*pixFmt, *alphaMask);
+	amask_ren_type r(pfa);
+	amask_aa_renderer_type ren(r);
+	ren.color(gc.color);
+	agg::render_scanlines(*theRasterizer, *slineP8, ren);
+ } else{
+	rendererAA->color(face.second);
+	theRasterizer->add_path(curve);
+	agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
+ }
 }
- else {
- rendererBin->color(gc.color);
- agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin);
+ 
+ if (gc.linewidth) {
+ if (gc.dasha == NULL) {
+	stroke_t stroke(curve);
+	stroke.width(gc.linewidth);
+	stroke.line_cap(gc.cap);
+	stroke.line_join(gc.join);
+	theRasterizer->add_path(stroke);
+ } else {
+ 	dash_t dash(curve);
+	for (size_t i = 0; i < (gc.Ndash / 2); ++i)
+	dash.add_dash(gc.dasha[2 * i], gc.dasha[2 * i + 1]);
+	stroke_dash_t stroke(dash);
+	stroke.line_cap(gc.cap);
+	stroke.line_join(gc.join);
+	stroke.width(gc.linewidth);
+	theRasterizer->add_path(stroke);
+ }
+ 
+ if (gc.isaa) {
+	if (has_clippath) {
+	 pixfmt_amask_type pfa(*pixFmt, *alphaMask);
+	 amask_ren_type r(pfa);
+	 amask_aa_renderer_type ren(r);
+	 ren.color(gc.color);
+	 agg::render_scanlines(*theRasterizer, *slineP8, ren);
+	} else {
+	 rendererAA->color(gc.color);
+	 agg::render_scanlines(*theRasterizer, *slineP8, *rendererAA);
+	}
+ } else {
+	if (has_clippath) {
+	 pixfmt_amask_type pfa(*pixFmt, *alphaMask);
+	 amask_ren_type r(pfa);
+	 amask_bin_renderer_type ren(r);
+	 ren.color(gc.color);
+	 agg::render_scanlines(*theRasterizer, *slineP8, ren);
+	} else {
+	 rendererBin->color(gc.color);
+	 agg::render_scanlines(*theRasterizer, *slineBin, *rendererBin);
+	}
+ }
 }
+ } catch (...) {
+ delete tpath;
+ throw;
 }
 
+ delete tpath;
+
 return Py::Object();
 }
 
@@ -2033,18 +1369,10 @@
 behaviors().name("RendererAgg");
 behaviors().doc("The agg backend extension module");
 
- add_varargs_method("draw_rectangle", &RendererAgg::draw_rectangle,
-		 "draw_rectangle(gc, rgbFace, l, b, w, h)\n");
- add_varargs_method("draw_ellipse", &RendererAgg::draw_ellipse,
-		 "draw_ellipse(gc, rgbFace, x, y, w, h)\n");
- add_varargs_method("draw_polygon", &RendererAgg::draw_polygon,
-		 "draw_polygon(gc, rgbFace, points)\n");
 add_varargs_method("draw_path",...
 
[truncated message content]
From: <md...@us...> - 2007年09月17日 13:41:58
Revision: 3854
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3854&view=rev
Author: mdboom
Date: 2007年09月17日 06:41:38 -0700 (2007年9月17日)
Log Message:
-----------
Transferring work-in-progress
Modified Paths:
--------------
 branches/transforms/examples/shared_axis_demo.py
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/patches.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Modified: branches/transforms/examples/shared_axis_demo.py
===================================================================
--- branches/transforms/examples/shared_axis_demo.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/examples/shared_axis_demo.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -36,12 +36,12 @@
 s2 = exp(-t)
 s3 = sin(4*pi*t)
 ax1 = subplot(311)
-plot(t,s1)
+plot(t,s1, "bH")
 setp( ax1.get_xticklabels(), fontsize=6)
 
 ## share x only
 ax2 = subplot(312, sharex=ax1)
-plot(t, s2)
+plot(t, s2, "b<")
 # make these tick labels invisible
 setp( ax2.get_xticklabels(), visible=False)
 
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -36,21 +36,25 @@
 """
 pass
 
+ def _get_cached_native_path(self, path):
+	native_path = self._native_paths.get(path)
+	if native_path is None:
+	 import matplotlib.patches
+	 print "CACHE MISS", path
+	 native_path = self.convert_to_native_path(path)
+	 self._native_paths[path] = native_path
+	return native_path
+ 
 def draw_path(self, gc, path, transform, rgbFace = None):
 	"""
 	Handles the caching of the native path associated with the
 	given path and calls the underlying backend's _draw_path to
 	actually do the drawing.
 	"""
-	native_path = self._native_paths.get(path)
-	if native_path is None:
-	 import matplotlib.patches
-	 print "CACHE MISS", path
-	 native_path = self.convert_to_native_path(path)
-	 self._native_paths[path] = native_path
-	self._draw_path(gc, native_path, transform, rgbFace)
+	native_path = self._get_cached_native_path(path)
+	self._draw_native_path(gc, native_path, transform, rgbFace)
 
- def _draw_path(self, gc, native_path, transform, rgbFace):
+ def _draw_native_path(self, gc, native_path, transform, rgbFace):
 	"""
 	Draw the native path object with the given GraphicsContext and
 	transform. The transform passed in will always be affine.
@@ -107,9 +111,10 @@
 return False
 
 def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
-	pass
- 
- def _draw_markers(self, bgc, path, rgbFace, x, y, trans):
+	native_marker_path = self._get_cached_native_path(marker_path)
+	self._draw_native_markers(gc, native_marker_path, marker_trans, path, trans, rgbFace)
+	
+ def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
 """
 This method is currently underscore hidden because the
 draw_markers method is being used as a sentinel for newstyle
@@ -130,7 +135,7 @@
 vec6 = transform.as_vec6_val()
 ...backend dependent affine...
 """
- pass
+ raise NotImplementedError
 
 def draw_line_collection(self, segments, transform, clipbox,
 colors, linewidths, linestyle, antialiaseds,
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -140,7 +140,7 @@
 def convert_to_native_path(self, path):
 	return self._renderer.convert_to_native_path(path.vertices, path.codes)
 
- def _draw_path(self, gc, native_path, transform, rgbFace):
+ def _draw_native_path(self, gc, native_path, transform, rgbFace):
 	return self._renderer.draw_path(gc, native_path, transform.to_values(), rgbFace)
 	
 def draw_arc(self, gcEdge, rgbFace, x, y, width, height, angle1, angle2, rotation):
@@ -172,8 +172,12 @@
 def draw_lines(self, gc, x, y, transform):
 	return self._renderer.draw_lines(gc, x, y, transform.to_values())
 
- def draw_markers(self, gc, path, color, x, y, transform):
-	return self._renderer.draw_markers(gc, path, color, x, y, transform.to_values())
+ def _draw_native_markers(self, gc, native_marker_path, marker_trans, path, trans, rgbFace=None):
+	return self._renderer.draw_markers(
+	 gc,
+	 native_marker_path, marker_trans.to_values(),
+	 path.vertices, path.codes, trans.to_values(),
+	 rgbFace)
 
 def draw_polygon(self, *args):
 	return self._renderer.draw_polygon(*args)
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/lib/matplotlib/lines.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -520,7 +520,7 @@
 lineFunc(renderer, gc, self._path)
 	 
 	# MGDTODO: Deal with markers
- if self._marker is not None and False:
+ if self._marker is not None:
 gc = renderer.new_gc()
 self._set_gc_clip(gc)
 gc.set_foreground(self.get_markeredgecolor())
@@ -713,6 +713,9 @@
 pass
 
 def _draw_steps(self, renderer, gc, xt, yt):
+	# MGDTODO: This is a quirky one. The step-plotting part
+	# should probably be moved to where the path is generated
+	# in recache, and then just drawn with _draw_solid
 siz=len(xt)
 if siz<2: return
 xt2=npy.ones((2*siz,), xt.dtype)
@@ -727,323 +730,132 @@
 renderer.draw_lines(gc, xt2, yt2)
 
 def _draw_solid(self, renderer, gc, path):
- # if len(xt)<2: return
 gc.set_linestyle('solid')
 	renderer.draw_path(gc, path, self.get_transform())
 
 
- def _draw_dashed(self, renderer, gc, xt, yt):
- if len(xt)<2: return
+ def _draw_dashed(self, renderer, gc, path):
 gc.set_linestyle('dashed')
 if self._dashSeq is not None:
 gc.set_dashes(0, self._dashSeq)
 
- if self._newstyle:
- renderer.draw_lines(gc, xt, yt, self.get_transform())
- else:
- renderer.draw_lines(gc, xt, yt)
+	renderer.draw_path(gc, path, self.get_transform())
 
 
- def _draw_dash_dot(self, renderer, gc, xt, yt):
- if len(xt)<2: return
+ def _draw_dash_dot(self, renderer, gc, path):
 gc.set_linestyle('dashdot')
- if self._newstyle:
- renderer.draw_lines(gc, xt, yt, self.get_transform())
- else:
- renderer.draw_lines(gc, xt, yt)
+	renderer.draw_path(gc, path, self.get_transform())
 
- def _draw_dotted(self, renderer, gc, xt, yt):
-
- if len(xt)<2: return
+	 
+ def _draw_dotted(self, renderer, gc, path):
 gc.set_linestyle('dotted')
- if self._newstyle:
- renderer.draw_lines(gc, xt, yt, self.get_transform())
- else:
- renderer.draw_lines(gc, xt, yt)
+	renderer.draw_path(gc, path, self.get_transform())
 
- def _draw_point(self, renderer, gc, xt, yt):
+	
+ def _draw_point(self, renderer, gc, path):
+	self._draw_circle(renderer, gc, path, point = True)
 
- r = 0.5 * renderer.points_to_pixels(self._markersize)
- r *= self._point_size_reduction
- gc.set_linewidth(0)
- if r <= 0.5:
- self._draw_pixel(renderer, gc, xt, yt)
- elif r <= 2:
- self._draw_hexagon1(renderer, gc, xt, yt, point=True)
- else:
- self._draw_circle(renderer, gc, xt, yt, point=True)
-
- def _draw_pixel(self, renderer, gc, xt, yt):
- if self._newstyle:
- rgbFace = self._get_rgb_face()
- path = agg.path_storage()
- path.move_to(-0.5, -0.5)
- path.line_to(-0.5, 0.5)
- path.line_to(0.5, 0.5)
- path.line_to(0.5, -0.5)
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_point(gc, x, y)
-
-
- def _draw_circle(self, renderer, gc, xt, yt, point=False):
-
+ def _draw_pixel(self, renderer, gc, path):
+	rgbFace = self._get_rgb_face()
+	transform = Affine2D().translate(-0.5, -0.5)
+	renderer.draw_markers(gc, Path.unit_rectangle, transform,
+			 path, self.get_transform(), rgbFace)
+	
+	
+ def _draw_circle(self, renderer, gc, path, point=False):
 w = renderer.points_to_pixels(self._markersize)
 if point:
 w *= self._point_size_reduction
+	w *= 0.5
 
-
 rgbFace = self._get_rgb_face()
+	transform = Affine2D().scale(w, w)
+	renderer.draw_markers(
+	 gc, Path.unit_circle(), transform, path, self.get_transform(),
+	 rgbFace)
 
- if self._newstyle:
- N = 50.0
- r = w/2.
- rads = (2*math.pi/N)*npy.arange(N)
- xs = r*npy.cos(rads)
- ys = r*npy.sin(rads)
- # todo: use curve3!
- path = agg.path_storage()
- path.move_to(xs[0], ys[0])
- for x, y in zip(xs[1:], ys[1:]):
- path.line_to(x, y)
 
- path.end_poly()
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt,yt):
- renderer.draw_arc(gc, rgbFace,
- x, y, w, w, 0.0, 360.0, 0.0)
-
-
-
- def _draw_triangle_up(self, renderer, gc, xt, yt):
-
-
+ _triangle_path = Path([[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0]])
+ def _draw_triangle_up(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset, offset)
 rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, self._triangle_path, transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, offset)
- path.line_to(-offset, -offset)
- path.line_to(offset, -offset)
- path.end_poly()
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x, y+offset),
- (x-offset, y-offset),
- (x+offset, y-offset) )
- renderer.draw_polygon(gc, rgbFace, verts)
 
-
- def _draw_triangle_down(self, renderer, gc, xt, yt):
+ def _draw_triangle_down(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset, -offset)
 rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, self._triangle_path, transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
-
- path = agg.path_storage()
- path.move_to(-offset, offset)
- path.line_to(offset, offset)
- path.line_to(0, -offset)
- path.end_poly()
-
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x-offset, y+offset),
- (x+offset, y+offset),
- (x, y-offset))
- renderer.draw_polygon(gc, rgbFace, verts)
-
- def _draw_triangle_left(self, renderer, gc, xt, yt):
+	
+ def _draw_triangle_left(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset, offset).rotate_deg(90)
 rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, self._triangle_path, transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
 
- path = agg.path_storage()
- path.move_to(-offset, 0)
- path.line_to(offset, -offset)
- path.line_to(offset, offset)
- path.end_poly()
-
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x-offset, y),
- (x+offset, y-offset),
- (x+offset, y+offset))
- renderer.draw_polygon(gc, rgbFace, verts)
-
-
- def _draw_triangle_right(self, renderer, gc, xt, yt):
+ def _draw_triangle_right(self, renderer, gc, path):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset, offset).rotate_deg(-90)
 rgbFace = self._get_rgb_face()
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(offset, 0)
- path.line_to(-offset, -offset)
- path.line_to(-offset, offset)
- path.end_poly()
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x+offset, y),
- (x-offset, y-offset),
- (x-offset, y+offset))
- renderer.draw_polygon(gc, rgbFace, verts)
+	renderer.draw_markers(gc, self._triangle_path, transform,
+			 path, self.get_transform(), rgbFace)
 
 
-
- def _draw_square(self, renderer, gc, xt, yt):
+ def _draw_square(self, renderer, gc, path):
 side = renderer.points_to_pixels(self._markersize)
- offset = side*0.5
+	transform = Affine2D().translate(-0.5, -0.5).scale(side)
 rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
-
- path = agg.path_storage()
- path.move_to(-offset, -offset)
- path.line_to(-offset, offset)
- path.line_to(offset, offset)
- path.line_to(offset, -offset)
- path.end_poly()
-
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
-
- for (x,y) in zip(xt, yt):
- renderer.draw_rectangle(
- gc, rgbFace,
- x-offset, y-offset, side, side)
-
- def _draw_diamond(self, renderer, gc, xt, yt):
- offset = 0.6*renderer.points_to_pixels(self._markersize)
+	
+ def _draw_diamond(self, renderer, gc, path):
+ side = renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().translate(0.5, 0.5).rotate_deg(45).scale(side)
 rgbFace = self._get_rgb_face()
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(offset, 0)
- path.line_to(0, -offset)
- path.line_to(-offset, 0)
- path.line_to(0, offset)
- path.end_poly()
+	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
+			 path, self.get_transform(), rgbFace)
 
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
-
-
- for (x,y) in zip(xt, yt):
- verts = ( (x+offset, y),
- (x, y-offset),
- (x-offset, y),
- (x, y+offset))
- renderer.draw_polygon(gc, rgbFace, verts)
-
- def _draw_thin_diamond(self, renderer, gc, xt, yt):
- offset = 0.7*renderer.points_to_pixels(self._markersize)
- xoffset = 0.6*offset
+	
+ def _draw_thin_diamond(self, renderer, gc, path):
+ offset = renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().translate(0.5, 0.5).rotate_deg(45).scale(offset * 0.8, offset)
 rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, Path.unit_rectangle(), transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(xoffset, 0)
- path.line_to(0, -offset)
- path.line_to(-xoffset, 0)
- path.line_to(0, offset)
- path.end_poly()
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x+xoffset, y),
- (x, y-offset),
- (x-xoffset, y),
- (x, y+offset))
- renderer.draw_polygon(gc, rgbFace, verts)
+	
+ def _draw_pentagon(self, renderer, gc, path):
+ offset = 0.5 * renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset)
+	rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, Path.unit_regular_polygon(5), transform,
+			 path, self.get_transform(), rgbFace)
 
- def _draw_pentagon(self, renderer, gc, xt, yt):
- offset = 0.6*renderer.points_to_pixels(self._markersize)
- offsetX1 = offset*0.95
- offsetY1 = offset*0.31
- offsetX2 = offset*0.59
- offsetY2 = offset*0.81
- rgbFace = self._get_rgb_face()
+	
+ def _draw_hexagon1(self, renderer, gc, path, point=False):
+ offset = 0.5 * renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset)
+	rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
+			 path, self.get_transform(), rgbFace)
 
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, offset)
- path.line_to(-offsetX1, offsetY1)
- path.line_to(-offsetX2, -offsetY2)
- path.line_to(+offsetX2, -offsetY2)
- path.line_to(+offsetX1, offsetY1)
- path.end_poly()
-
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x, y+offset),
- (x-offsetX1, y+offsetY1),
- (x-offsetX2, y-offsetY2),
- (x+offsetX2, y-offsetY2),
- (x+offsetX1, y+offsetY1))
- renderer.draw_polygon(gc, rgbFace, verts)
-
- def _draw_hexagon1(self, renderer, gc, xt, yt, point=False):
- offset = 0.6*renderer.points_to_pixels(self._markersize)
- if point:
- offset *= self._point_size_reduction
- offsetX1 = offset*0.87
- offsetY1 = offset*0.5
- rgbFace = self._get_rgb_face()
-
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, offset)
- path.line_to(-offsetX1, offsetY1)
- path.line_to(-offsetX1, -offsetY1)
- path.line_to(0, -offset)
- path.line_to(offsetX1, -offsetY1)
- path.line_to(offsetX1, offsetY1)
- path.end_poly()
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x, y+offset),
- (x-offsetX1, y+offsetY1),
- (x-offsetX1, y-offsetY1),
- (x, y-offset),
- (x+offsetX1, y-offsetY1),
- (x+offsetX1, y+offsetY1))
- renderer.draw_polygon(gc, rgbFace, verts)
-
+	
 def _draw_hexagon2(self, renderer, gc, xt, yt):
- offset = 0.6*renderer.points_to_pixels(self._markersize)
- offsetX1 = offset*0.5
- offsetY1 = offset*0.87
- rgbFace = self._get_rgb_face()
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(offset, 0)
- path.line_to(offsetX1, offsetY1)
- path.line_to(-offsetX1, offsetY1)
- path.line_to(-offset, 0)
- path.line_to(-offsetX1, -offsetY1)
- path.line_to(offsetX1, -offsetY1)
- path.end_poly()
+ offset = 0.5 * renderer.points_to_pixels(self._markersize)
+	transform = Affine2D().scale(offset).rotate_deg(30)
+	rgbFace = self._get_rgb_face()
+	renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform,
+			 path, self.get_transform(), rgbFace)
 
- renderer.draw_markers(gc, path, rgbFace, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- verts = ( (x+offset, y),
- (x+offsetX1, y+offsetY1),
- (x-offsetX1, y+offsetY1),
- (x-offset, y),
- (x-offsetX1, y-offsetY1),
- (x+offsetX1, y-offsetY1))
- renderer.draw_polygon(gc, rgbFace, verts)
-
+	
 def _draw_vline(self, renderer, gc, xt, yt):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 if self._newstyle:
@@ -1055,6 +867,7 @@
 for (x,y) in zip(xt, yt):
 renderer.draw_line(gc, x, y-offset, x, y+offset)
 
+		
 def _draw_hline(self, renderer, gc, xt, yt):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
 if self._newstyle:
@@ -1066,46 +879,31 @@
 for (x,y) in zip(xt, yt):
 renderer.draw_line(gc, x-offset, y, x+offset, y)
 
- def _draw_tickleft(self, renderer, gc, xt, yt):
+ _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]])
+ def _draw_tickleft(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-offset, 0.5)
- path.line_to(0, 0.5)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x-offset, y, x, y)
+	marker_transform = Affine2D().scale(offset, 1.0)
+	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
+			 path, self.get_transform())
 
- def _draw_tickright(self, renderer, gc, xt, yt):
-
+ def _draw_tickright(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(0, 0.5)
- path.line_to(offset, 0.5)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y, x+offset, y)
+	marker_transform = Affine2D().scale(-offset, 1.0)
+	renderer.draw_markers(gc, self._tickhoriz_path, marker_transform,
+			 path, self.get_transform())
 
- _tickup_path = Path([[-0.5, 0.0], [-0.5, 1.0]])
- def _draw_tickup(self, renderer, gc, xt, yt):
+ _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]])
+ def _draw_tickup(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
 	marker_transform = Affine2D().scale(1.0, offset)
-	renderer.draw_markers(gc, self._tickup_path, marker_transform,
-			 self._path, self.get_transform())
+	renderer.draw_markers(gc, self._tickvert_path, marker_transform,
+			 path, self.get_transform())
 
- def _draw_tickdown(self, renderer, gc, xt, yt):
+ def _draw_tickdown(self, renderer, gc, path):
 offset = renderer.points_to_pixels(self._markersize)
- if self._newstyle:
- path = agg.path_storage()
- path.move_to(-0.5, -offset)
- path.line_to(-0.5, 0)
- renderer.draw_markers(gc, path, None, xt, yt, self.get_transform())
- else:
- for (x,y) in zip(xt, yt):
- renderer.draw_line(gc, x, y-offset, x, y)
+	marker_transform = Affine2D().scale(1.0, -offset)
+	renderer.draw_markers(gc, self._tickvert_path, marker_transform,
+			 path, self.get_transform())
 
 def _draw_plus(self, renderer, gc, xt, yt):
 offset = 0.5*renderer.points_to_pixels(self._markersize)
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/lib/matplotlib/patches.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -288,7 +288,6 @@
 self._update()
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
-
 def _update(self):
 self.update_from(self.patch)
 if self.props is not None:
@@ -316,8 +315,7 @@
 
 """
 
- _path = Path(
-	[[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])
+ _path = Path.unit_rectangle()
 
 def __str__(self):
 return str(self.__class__).split('.')[-1] \
@@ -424,8 +422,6 @@
 """
 A regular polygon patch.
 """
- _polygon_cache = {}
- 
 def __str__(self):
 return "Poly%d(%g,%g)"%(self.numVertices,self.xy[0],self.xy[1])
 
@@ -442,14 +438,7 @@
 """
 Patch.__init__(self, **kwargs)
 
-	path = self._polygon_cache[numVertices]
-	if path is None:
-	 theta = 2*npy.pi/numVertices * npy.arange(numVertices)
-	 verts = npy.hstack((npy.cos(theta), npy.sin(theta)))
-	 path = Path(verts)
-	 self._polygon_cache[numVertices] = path
-
-	self._path = path
+	self._path = Path.unit_regular_polygon(numVertices)
 	self._poly_transform = transforms.Affine2D() \
 	 .scale(radius) \
 	 .rotate(orientation) \
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/lib/matplotlib/path.py	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -1,21 +1,25 @@
 import numpy as npy
 
-class Path:
+VALIDATE_PATHS = True
+
+class Path(object):
 # Path codes
 STOP = 0
 MOVETO = 1 # 1 vertex
 LINETO = 2 # 1 vertex
 CURVE3 = 3 # 2 vertices
 CURVE4 = 4 # 3 vertices
+ CLOSEPOLY = 5
 ###
 # MGDTODO: I'm not sure these are supported by PS/PDF/SVG,
 # so if they don't, we probably shouldn't
- CURVEN = 5
- CATROM = 6
- UBSPLINE = 7
+ CURVEN = 6
+ CATROM = 7
+ UBSPLINE = 8
 ####
- CLOSEPOLY = 0x0F # 0 vertices
 
+ NUM_VERTICES = [0, 1, 1, 2, 3, 0]
+ 
 code_type = npy.uint8
 
 def __init__(self, vertices, codes=None, closed=True):
@@ -38,9 +42,14 @@
 	self._codes = codes
 	 
 	assert self._codes.ndim == 1
-	# MGDTODO: Maybe we should add some quick-and-dirty check that
-	# the number of vertices is correct for the code array
 
+	if VALIDATE_PATHS:
+	 i = 0
+	 NUM_VERTICES = self.NUM_VERTICES
+	 for code in codes:
+		i += NUM_VERTICES[code]
+	 assert i == len(self.vertices)
+
 def _get_codes(self):
 	return self._codes
 codes = property(_get_codes)
@@ -48,3 +57,74 @@
 def _get_vertices(self):
 	return self._vertices
 vertices = property(_get_vertices)
+
+ def iter_endpoints(self):
+	i = 0
+	NUM_VERTICES = self.NUM_VERTICES
+	vertices = self.vertices
+	for code in self.codes:
+	 num_vertices = NUM_VERTICES[code]
+	 if num_vertices >= 1:
+		i += num_vertices - 1
+		yield vertices[i]
+		i += 1
+
+ _unit_rectangle = None
+ #@classmethod
+ def unit_rectangle(cls):
+	if cls._unit_rectangle is None:
+	 cls._unit_rectangle = \
+		Path([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]])
+	return cls._unit_rectangle
+ unit_rectangle = classmethod(unit_rectangle)
+
+ _unit_regular_polygons = {}
+ #@classmethod
+ def unit_regular_polygon(cls, numVertices):
+	path = cls._unit_regular_polygons.get(numVertices)
+	if path is None:
+	 theta = 2*npy.pi/numVertices * npy.arange(numVertices)
+	 # This is to make sure the polygon always "points-up"
+	 theta += npy.pi / 2.0
+	 verts = npy.vstack((npy.cos(theta), npy.sin(theta))).transpose()
+	 path = Path(verts)
+	 cls._unit_regular_polygons[numVertices] = path
+	return path
+ unit_regular_polygon = classmethod(unit_regular_polygon)
+
+ _unit_circle = None
+ #@classmethod
+ def unit_circle(cls):
+	# MGDTODO: Optimize?
+	if cls._unit_circle is None:
+	 offset = 4.0 * (npy.sqrt(2) - 1) / 3.0
+	 vertices = npy.array(
+		[[-1.0, 0.0],
+		 
+		 [-1.0, offset],
+		 [-offset, 1.0],
+		 [0.0, 1.0],
+		 
+		 [offset, 1.0],
+		 [1.0, offset],
+		 [1.0, 0.0],
+		 
+		 [1.0, -offset],
+		 [offset, -1.0],
+		 [0.0, -1.0],
+		 
+		 [-offset, -1.0],
+		 [-1.0, -offset],
+		 [-1.0, 0.0]],
+		npy.float_)
+	 codes = npy.array(
+		[cls.MOVETO,
+		 cls.CURVE4,
+		 cls.CURVE4,
+		 cls.CURVE4,
+		 cls.CURVE4,
+		 cls.CLOSEPOLY],
+		cls.code_type)
+	 cls._unit_circle = Path(vertices, codes)
+	return cls._unit_circle
+ unit_circle = classmethod(unit_circle)
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/src/_backend_agg.cpp	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -64,6 +64,20 @@
 Py::Float(seq[5]));
 }
 
+// MGDTODO: Implement this as a nice iterator
+inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, 
+			 double& x, double& y,
+			 size_t next_vertex_stride, 
+			 size_t next_axis_stride) {
+ if (vertex_i + next_axis_stride >= vertex_end)
+ throw Py::ValueError("Error parsing path. Read past end of vertices");
+ x = *(double*)vertex_i;
+ y = *(double*)(vertex_i + next_axis_stride);
+ vertex_i += next_vertex_stride;
+}
+
+#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride)
+
 GCAgg::GCAgg(const Py::Object &gc, double dpi, bool snapto) :
 dpi(dpi), snapto(snapto), isaa(true), linewidth(1.0), alpha(1.0),
 cliprect(NULL), clippath(NULL), 
@@ -1255,146 +1269,134 @@
 
 Py::Object
 RendererAgg::draw_markers(const Py::Tuple& args) {
+ typedef agg::conv_transform<agg::path_storage> transformed_path_t;
+ typedef agg::conv_curve<transformed_path_t> curve_t;
+ typedef agg::conv_stroke<curve_t> stroke_t;
+ typedef agg::conv_dash<curve_t> dash_t;
+ typedef agg::conv_stroke<dash_t> stroke_dash_t;
+
 theRasterizer->reset_clipping();
 
- _VERBOSE("RendererAgg::_draw_markers_cache");
- args.verify_length(6);
+ args.verify_length(7);
 
- _VERBOSE("RendererAgg::_draw_markers_cache setting gc");
 GCAgg gc = GCAgg(args[0], dpi);
+ Py::Object marker_path_obj = args[1];
+ if (!PathAgg::check(marker_path_obj))
+ throw Py::TypeError("Native path object is not of correct type");
+ PathAgg* marker_path = static_cast<PathAgg*>(marker_path_obj.ptr());
+ agg::trans_affine marker_trans = py_sequence_to_agg_transformation_matrix(args[2]);
+ Py::Object vertices_obj = args[3];
+ Py::Object codes_obj = args[4];
+ agg::trans_affine trans = py_sequence_to_agg_transformation_matrix(args[5]);
+ facepair_t face = _get_rgba_face(args[6], gc.alpha);
+
+ // Deal with the difference in y-axis direction
+ marker_trans *= agg::trans_affine_scaling(1.0, -1.0);
+ trans *= agg::trans_affine_scaling(1.0, -1.0);
+ trans *= agg::trans_affine_translation(0.0, (double)height);
 
+ marker_path->rewind(0);
+ transformed_path_t marker_path_transformed(*marker_path, marker_trans);
+ curve_t marker_path_curve(marker_path_transformed);
 
- agg::path_storage *ppath;
- 
- swig_type_info * descr = SWIG_TypeQuery("agg::path_storage *");
- assert(descr);
- if (SWIG_ConvertPtr(args[1].ptr(),(void **)(&ppath), descr, 0) == -1) {
- throw Py::TypeError("Could not convert path_storage");
- }
- facepair_t face = _get_rgba_face(args[2], gc.alpha);
- 
- Py::Object xo = args[3];
- Py::Object yo = args[4];
- 
- PyArrayObject *xa = (PyArrayObject *) PyArray_ContiguousFromObject(xo.ptr(), PyArray_DOUBLE, 1, 1);
- 
- if (xa==NULL)
- throw Py::TypeError("RendererAgg::_draw_markers_cache expected numerix array");
- 
- 
- PyArrayObject *ya = (PyArrayObject *) PyArray_ContiguousFromObject(yo.ptr(), PyArray_DOUBLE, 1, 1);
- 
- if (ya==NULL)
- throw Py::TypeError("RendererAgg::_draw_markers_cache expected numerix array");
- 
- agg::trans_affine xytrans = py_sequence_to_agg_transformation_matrix(args[5]);
- 
- size_t Nx = xa->dimensions[0];
- size_t Ny = ya->dimensions[0];
- 
- if (Nx!=Ny)
- throw Py::ValueError(Printf("x and y must be equal length arrays; found %d and %d", Nx, Ny).str());
- 
- 
- double heightd = double(height);
- 
- 
- ppath->rewind(0);
- ppath->flip_y(0,0);
- typedef agg::conv_curve<agg::path_storage> curve_t;
- curve_t curve(*ppath);
- 
 //maxim's suggestions for cached scanlines
 agg::scanline_storage_aa8 scanlines;
 theRasterizer->reset();
 
 agg::int8u* fillCache = NULL;
- unsigned fillSize = 0;
- if (face.first) {
- theRasterizer->add_path(curve);
+ agg::int8u* strokeCache = NULL;
+ PyArrayObject* vertices = NULL;
+ PyArrayObject* codes = NULL;
+
+ try {
+ vertices = (PyArrayObject*)PyArray_ContiguousFromObject
+ (vertices_obj.ptr(), PyArray_DOUBLE, 2, 2);
+ if (!vertices || vertices->nd != 2 || vertices->dimensions[1] != 2)
+ throw Py::ValueError("Invalid vertices array.");
+ codes = (PyArrayObject*)PyArray_ContiguousFromObject
+ (codes_obj.ptr(), PyArray_UINT8, 1, 1);
+ if (!codes) 
+ throw Py::ValueError("Invalid codes array.");
+
+ unsigned fillSize = 0;
+ if (face.first) {
+ theRasterizer->add_path(marker_path_curve);
+ agg::render_scanlines(*theRasterizer, *slineP8, scanlines);
+ fillSize = scanlines.byte_size();
+ fillCache = new agg::int8u[fillSize]; // or any container
+ scanlines.serialize(fillCache);
+ }
+ 
+ stroke_t stroke(marker_path_curve);
+ stroke.width(gc.linewidth);
+ stroke.line_cap(gc.cap);
+ stroke.line_join(gc.join);
+ theRasterizer->reset();
+ theRasterizer->add_path(stroke);
 agg::render_scanlines(*theRasterizer, *slineP8, scanlines);
- fillSize = scanlines.byte_size();
- fillCache = new agg::int8u[fillSize]; // or any container
- scanlines.serialize(fillCache);
- }
+ unsigned strokeSize = scanlines.byte_size();
+ strokeCache = new agg::int8u[strokeSize]; // or any container
+ scanlines.serialize(strokeCache);
 
- agg::conv_stroke<curve_t> stroke(curve);
- stroke.width(gc.linewidth);
- stroke.line_cap(gc.cap);
- stroke.line_join(gc.join);
- theRasterizer->reset();
- theRasterizer->add_path(stroke);
- agg::render_scanlines(*theRasterizer, *slineP8, scanlines);
- unsigned strokeSize = scanlines.byte_size();
- agg::int8u* strokeCache = new agg::int8u[strokeSize]; // or any container
- scanlines.serialize(strokeCache);
- 
- theRasterizer->reset_clipping();
- 
- 
- if (gc.cliprect==NULL) {
- rendererBase->reset_clipping(true);
- }
- else {
- int l = (int)(gc.cliprect[0]) ;
- int b = (int)(gc.cliprect[1]) ;
- int w = (int)(gc.cliprect[2]) ;
- int h = (int)(gc.cliprect[3]) ;
- rendererBase->clip_box(l, height-(b+h),l+w, height-b);
- }
- 
- 
- double thisx, thisy;
- for (size_t i=0; i<Nx; i++) {
- thisx = *(double *)(xa->data + i*xa->strides[0]);
- thisy = *(double *)(ya->data + i*ya->strides[0]);
-
- // MGDTODO
-// if (mpltransform->need_nonlinear_api())
-// try {
-// 	mpltransform->nonlinear_only_api(&thisx, &thisy);
-// }
-// catch(...) {
-// 	continue;
-// }
+ theRasterizer->reset_clipping();
+ if (gc.cliprect==NULL) {
+ rendererBase->reset_clipping(true);
+ }
+ else {
+ int l = (int)(gc.cliprect[0]) ;
+ int b = (int)(gc.cliprect[1]) ;
+ int w = (int)(gc.cliprect[2]) ;
+ int h = (int)(gc.cliprect[3]) ;
+ rendererBase->clip_box(l, height-(b+h),l+w, height-b);
+ }
 
- xytrans.transform(&thisx, &thisy);
- 
- thisy = heightd - thisy; //flipy
- 
- thisx = (int)thisx + 0.5;
- thisy = (int)thisy + 0.5;
- if (thisx<0) continue;
- if (thisy<0) continue;
- if (thisx>width) continue;
- if (thisy>height) continue;
- 
+ size_t next_vertex_stride = vertices->strides[0];
+ size_t next_axis_stride = vertices->strides[1];
+ size_t code_stride = codes->strides[0];
+
+ const char* vertex_i = vertices->data;
+ const char* code_i = codes->data;
+ const char* vertex_end = vertex_i + (vertices->dimensions[0] * vertices->strides[0]);
+
+ size_t N = codes->dimensions[0];
+ double x, y;
+
 agg::serialized_scanlines_adaptor_aa8 sa;
 agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl;
- 
- if (face.first) {
- //render the fill
- sa.init(fillCache, fillSize, thisx, thisy);
- rendererAA->color(face.second);
- agg::render_scanlines(sa, sl, *rendererAA);
+
+ for (size_t i=0; i < N; i++) {
+ size_t num_vertices = NUM_VERTICES[(int)(*code_i)];
+ if (num_vertices) {
+	for (size_t j=0; j<num_vertices; ++j)
+	 GET_NEXT_VERTEX(x, y);
+	trans.transform(&x, &y);
+	
+	if (face.first) {
+	 //render the fill
+	 sa.init(fillCache, fillSize, x, y);
+	 rendererAA->color(face.second);
+	 agg::render_scanlines(sa, sl, *rendererAA);
+	}
+
+	//render the stroke
+	sa.init(strokeCache, strokeSize, x, y);
+	rendererAA->color(gc.color);
+	agg::render_scanlines(sa, sl, *rendererAA);
+ }
+ code_i += code_stride;
 }
- 
- //render the stroke
- sa.init(strokeCache, strokeSize, thisx, thisy);
- rendererAA->color(gc.color);
- agg::render_scanlines(sa, sl, *rendererAA);
- 
- } //for each marker
+ } catch(...) {
+ Py_XDECREF(vertices);
+ Py_XDECREF(codes);
+ delete[] fillCache;
+ delete[] strokeCache;
+ }
 
- Py_XDECREF(xa);
- Py_XDECREF(ya);
- 
- if (face.first)
- delete [] fillCache;
+ Py_XDECREF(vertices);
+ Py_XDECREF(codes);
+ delete [] fillCache;
 delete [] strokeCache;
 
- //jdh
- _VERBOSE("RendererAgg::_draw_markers_cache done");
 return Py::Object();
 
 }
@@ -1552,21 +1554,6 @@
 
 }
 
-inline void get_next_vertex(const char* & vertex_i, const char* vertex_end, 
-			 double& x, double& y,
-			 size_t next_vertex_stride, 
-			 size_t next_axis_stride) {
- if (vertex_i + next_axis_stride >= vertex_end)
- throw Py::ValueError("Error parsing path. Read past end of vertices");
- x = *(double*)vertex_i;
- y = *(double*)(vertex_i + next_axis_stride);
- vertex_i += next_vertex_stride;
-}
-
-#define GET_NEXT_VERTEX(x, y) get_next_vertex(vertex_i, vertex_end, x, y, next_vertex_stride, next_axis_stride)
-
-
-
 Py::Object
 RendererAgg::convert_to_native_path(const Py::Tuple& args) {
 _VERBOSE("RendererAgg::draw_image");
@@ -2059,7 +2046,7 @@
 add_varargs_method("draw_lines", &RendererAgg::draw_lines,
 		 "draw_lines(gc, x, y,)\n");
 add_varargs_method("draw_markers", &RendererAgg::draw_markers,
-		 "draw_markers(gc, path, x, y)\n");
+		 "draw_markers(gc, marker_path, marker_trans, vertices, codes, rgbFace)\n");
 add_varargs_method("draw_text_image", &RendererAgg::draw_text_image,
 		 "draw_text_image(font_image, x, y, r, g, b, a)\n");
 add_varargs_method("draw_image", &RendererAgg::draw_image,
Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h	2007年09月15日 04:01:56 UTC (rev 3853)
+++ branches/transforms/src/_backend_agg.h	2007年09月17日 13:41:38 UTC (rev 3854)
@@ -45,8 +45,10 @@
 #define LINETO 2
 #define CURVE3 3
 #define CURVE4 4
-#define CLOSEPOLY 0x0F
+#define CLOSEPOLY 5
 
+const size_t NUM_VERTICES[] = { 0, 1, 1, 2, 3, 0 };
+
 typedef agg::pixfmt_rgba32 pixfmt;
 typedef agg::renderer_base<pixfmt> renderer_base;
 typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.

Showing results of 137

<< < 1 2 3 4 .. 6 > >> (Page 2 of 6)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /