Revision: 3928
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3928&view=rev
Author: mdboom
Date: 2007-10-08 11:10:11 -0700 (Mon, 08 Oct 2007)
Log Message:
-----------
More work on collections.
Modified Paths:
--------------
branches/transforms/examples/collections_demo.py
branches/transforms/lib/matplotlib/axes.py
branches/transforms/lib/matplotlib/backends/backend_agg.py
branches/transforms/lib/matplotlib/collections.py
branches/transforms/lib/matplotlib/legend.py
branches/transforms/lib/matplotlib/lines.py
branches/transforms/lib/matplotlib/transforms.py
branches/transforms/setupext.py
branches/transforms/src/_backend_agg.cpp
branches/transforms/src/_backend_agg.h
Modified: branches/transforms/examples/collections_demo.py
===================================================================
--- branches/transforms/examples/collections_demo.py 2007-10-08 12:45:23 UTC
(rev 3927)
+++ branches/transforms/examples/collections_demo.py 2007-10-08 18:10:11 UTC
(rev 3928)
@@ -45,6 +45,8 @@
a = fig.add_subplot(2,2,1)
col = collections.LineCollection([spiral], offsets=xyo,
transOffset=a.transData)
+trans = transforms.Affine2D().scale(fig.dpi/72.0)
+col.set_transform(trans) # the points to pixels transform
# Note: the first argument to the collection initializer
# must be a list of sequences of x,y tuples; we have only
# one sequence, but we still have to put it in a list.
@@ -59,9 +61,6 @@
# Make a transform for the line segments such that their size is
# given in points:
-trans = transforms.scale_transform(fig.dpi/transforms.Value(72.),
- fig.dpi/transforms.Value(72.))
-col.set_transform(trans) # the points to pixels transform
col.set_color(colors)
a.autoscale_view() # See comment above, after a.add_collection.
@@ -74,28 +73,25 @@
col = collections.PolyCollection([spiral], offsets=xyo,
transOffset=a.transData)
-a.add_collection(col, autolim=True)
-trans = transforms.scale_transform(fig.dpi/transforms.Value(72.),
- fig.dpi/transforms.Value(72.))
+trans = transforms.Affine2D().scale(fig.dpi/72.0)
col.set_transform(trans) # the points to pixels transform
+a.add_collection(col, autolim=True)
col.set_color(colors)
a.autoscale_view()
a.set_title('PolyCollection using offsets')
-
# 7-sided regular polygons
a = fig.add_subplot(2,2,3)
col = collections.RegularPolyCollection(fig.dpi, 7,
- sizes = N.fabs(xx)*10, offsets=xyo,
+ sizes = N.fabs(xx) / 10.0, offsets=xyo,
transOffset=a.transData)
-a.add_collection(col, autolim=True)
-trans = transforms.scale_transform(fig.dpi/transforms.Value(72.),
- fig.dpi/transforms.Value(72.))
+trans = transforms.Affine2D().scale(fig.dpi/72.0)
col.set_transform(trans) # the points to pixels transform
+a.add_collection(col, autolim=True)
col.set_color(colors)
a.autoscale_view()
a.set_title('RegularPolyCollection using offsets')
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py 2007-10-08 12:45:23 UTC (rev
3927)
+++ branches/transforms/lib/matplotlib/axes.py 2007-10-08 18:10:11 UTC (rev
3928)
@@ -1046,7 +1046,7 @@
self._set_artist_props(collection)
collection.set_clip_path(self.axesPatch)
if autolim:
- self.update_datalim(collection.get_verts(self.transData))
+ self.update_datalim(collection.get_datalim(self.transData))
collection._remove_method = lambda h: self.collections.remove(h)
def add_line(self, line):
@@ -1105,6 +1105,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
+ # MGDTODO: This isn't always the most efficient way to do this... in
+ # some cases things should use update_datalim_bounds
+
if not ma.isMaskedArray(xys):
xys = npy.asarray(xys)
self.update_datalim_numerix(xys[:, 0], xys[:, 1])
@@ -1119,6 +1122,10 @@
self.dataLim.update_from_data(x, y, self.ignore_existing_data_limits)
self.ignore_existing_data_limits = False
+ def update_datalim_bounds(self, bounds):
+ # MGDTODO: Document me
+ self.dataLim.bounds = Bbox.union([self.dataLim, bounds]).bounds
+
def _get_verts_in_data_coords(self, trans, xys):
if trans == self.transData:
return xys
@@ -4006,8 +4013,8 @@
shading='faceted --> edgecolors=None
edgecolors also can be any mpl color or sequence of colors.
- Optional kwargs control the PatchCollection properties:
- %(PatchCollection)s
+ Optional kwargs control the Collection properties:
+ %(Collection)s
"""
if not self._hold: self.cla()
@@ -4439,7 +4446,7 @@
* alpha=1.0 : the alpha blending value
- Return value is a mcoll.PatchCollection
+ Return value is a mcoll.Collection
object
Grid Orientation
@@ -4627,7 +4634,7 @@
* alpha=1.0 : the alpha blending value
- Return value is a collections.PatchCollection
+ Return value is a collections.Collection
object
See pcolor for an explantion of the grid orientation and the
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-10-08
12:45:23 UTC (rev 3927)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-10-08
18:10:11 UTC (rev 3928)
@@ -131,11 +131,15 @@
self._renderer.draw_markers(gc, marker_path, marker_trans.frozen(),
path, trans.frozen(), rgbFace)
def draw_path_collection(self, master_transform, clipbox, clippath,
clippath_trans,
- paths, transforms, facecolors, edgecolors,
linewidths, linestyles, antialiaseds):
+ paths, transforms, offsets, transOffset,
facecolors, edgecolors,
+ linewidths, linestyles, antialiaseds):
assert master_transform.is_affine
+ if transOffset is not None:
+ transOffset = transOffset.frozen()
self._renderer.draw_path_collection(
master_transform.frozen(), clipbox, clippath, clippath_trans,
- paths, transforms, facecolors, edgecolors, linewidths, linestyles,
antialiaseds)
+ paths, transforms, offsets, transOffset, facecolors, edgecolors,
linewidths,
+ linestyles, antialiaseds)
def draw_mathtext(self, gc, x, y, s, prop, angle):
"""
Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py 2007-10-08 12:45:23 UTC
(rev 3927)
+++ branches/transforms/lib/matplotlib/collections.py 2007-10-08 18:10:11 UTC
(rev 3928)
@@ -19,67 +19,20 @@
import matplotlib.nxutils as nxutils
import matplotlib.path as path
-# MGDTODO: Now that everything draws through draw_path_collection,
-# perhaps more stuff could be moved into the Collection base class
-# here
+# MGDTODO: Move this stuff
+from matplotlib.backends._backend_agg import get_path_collection_extents, \
+ point_in_path_collection
-class Collection(artist.Artist):
+class Collection(artist.Artist, cm.ScalarMappable):
"""
+ Base class for Collections. Must be subclassed to be usable.
+
All properties in a collection must be sequences or scalars;
if scalars, they will be converted to sequences. The
property of the ith element of the collection is the
prop[i % len(props)].
- """
-
- def __init__(self):
- artist.Artist.__init__(self)
-
-
- def get_verts(self):
- 'return seq of (x,y) in collection'
- raise NotImplementedError('Derived must override')
-
- def _get_value(self, val):
- try: return (float(val), )
- except TypeError:
- if cbook.iterable(val) and len(val):
- try: float(val[0])
- except TypeError: pass # raise below
- else: return val
-
- raise TypeError('val must be a float or nonzero sequence of floats')
-
-
-# these are not available for the object inspector until after the
-# class is built so we define an initial set here for the init
-# function and they will be overridden after object defn
-artist.kwdocd['PatchCollection'] = """\
- Valid PatchCollection kwargs are:
-
- edgecolors=None,
- facecolors=None,
- linewidths=None,
- antialiaseds = None,
- offsets = None,
- transOffset = transforms.identity_transform(),
- norm = None, # optional for cm.ScalarMappable
- cmap = None, # ditto
-
- offsets and transOffset are used to translate the patch after
- rendering (default no offsets)
-
- If any of edgecolors, facecolors, linewidths, antialiaseds are
- None, they default to their patch.* rc params setting, in sequence
- form.
-"""
-
-class PatchCollection(Collection, cm.ScalarMappable):
- """
- Base class for filled regions such as PolyCollection etc.
- It must be subclassed to be usable.
-
kwargs are:
edgecolors=None,
@@ -103,30 +56,45 @@
draw time a call to scalar mappable will be made to set the face
colors.
"""
+ _offsets = npy.zeros((1, 2))
+ _transOffset = transforms.IdentityTransform()
+
+ _facecolors = [None]
+ _edgecolors = [None]
+ _lw = [1.0]
+ _ls = [None]
+ _aa = [True]
+ _pickradius = 5.0
+ _transforms = [None]
+
zorder = 1
def __init__(self,
edgecolors=None,
facecolors=None,
linewidths=None,
+ linestyles='solid',
antialiaseds = None,
offsets = None,
transOffset = None,
norm = None, # optional for ScalarMappable
cmap = None, # ditto
+ pickradius = 5.0,
+ **kwargs
):
"""
Create a PatchCollection
%(PatchCollection)s
"""
- Collection.__init__(self)
+ artist.Artist.__init__(self)
cm.ScalarMappable.__init__(self, norm, cmap)
if facecolors is None: facecolors = mpl.rcParams['patch.facecolor']
if edgecolors is None: edgecolors = mpl.rcParams['patch.edgecolor']
if linewidths is None: linewidths = (mpl.rcParams['patch.linewidth'],)
if antialiaseds is None: antialiaseds =
(mpl.rcParams['patch.antialiased'],)
-
+ self.set_linestyles(linestyles)
+
self._facecolors = _colors.colorConverter.to_rgba_list(facecolors)
if edgecolors == 'None':
self._edgecolors = self._facecolors
@@ -135,13 +103,80 @@
self._edgecolors = _colors.colorConverter.to_rgba_list(edgecolors)
self._linewidths = self._get_value(linewidths)
self._antialiaseds = self._get_value(antialiaseds)
- #self._offsets = offsets
- self._offsets = offsets
- self._transOffset = transOffset
- self._verts = []
- __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
+ self._uniform_offsets = None
+ self._offsets = npy.zeros((1, 2))
+ if offsets is not None:
+ offsets = npy.asarray(offsets)
+ if len(offsets.shape) == 1:
+ offsets = offsets[npy.newaxis,:] # Make it Nx2.
+ if transOffset is not None:
+ Affine2D = transforms.Affine2D
+ self._offsets = offsets
+ self._transOffset = transOffset
+ else:
+ self._uniform_offsets = offsets
+ self._pickradius = pickradius
+ self.update(kwargs)
+
+ def _get_value(self, val):
+ try: return (float(val), )
+ except TypeError:
+ if cbook.iterable(val) and len(val):
+ try: float(val[0])
+ except TypeError: pass # raise below
+ else: return val
+
+ raise TypeError('val must be a float or nonzero sequence of floats')
+
+ def get_paths(self):
+ raise NotImplementedError
+
+ def get_transforms(self):
+ return self._transforms
+
+ def get_datalim(self, transData):
+ result = transforms.Bbox.from_lbrt(*get_path_collection_extents(
+ self.get_transform().frozen(),
+ self.get_paths(),
+ self.get_transforms(),
+ self._offsets,
+ self._transOffset.frozen()))
+ result = result.transformed(transData.inverted())
+ return result
+
+ def draw(self, renderer):
+ if not self.get_visible(): return
+ renderer.open_group(self.__class__.__name__)
+ transform = self.get_transform()
+ transOffset = self._transOffset
+ offsets = self._offsets
+
+ # MGDTODO: Transform the paths (since we don't keep track of segments
anymore
+ if self.have_units():
+ segments = []
+ for segment in self._segments:
+ xs, ys = zip(*segment)
+ xs = self.convert_xunits(xs)
+ ys = self.convert_yunits(ys)
+ segments.append(zip(xs, ys))
+# if self._offsets is not None:
+# xs = self.convert_xunits(self._offsets[:0])
+# ys = self.convert_yunits(self._offsets[:1])
+# offsets = zip(xs, ys)
+
+ self.update_scalarmappable()
+
+ #print 'calling renderer draw line collection'
+ clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
+
+ renderer.draw_path_collection(
+ transform, self.clipbox, clippath, clippath_trans,
+ self.get_paths(), self.get_transforms(), offsets, transOffset,
+ self._facecolors, self._edgecolors, self._lw, self._ls, self._aa)
+ renderer.close_group(self.__class__.__name__)
+
def contains(self, mouseevent):
"""
Test whether the mouse event occurred in the collection.
@@ -149,25 +184,13 @@
Returns T/F, dict(ind=itemlist), where every item in itemlist contains
the event.
"""
if callable(self._contains): return self._contains(self,mouseevent)
- # TODO: Consider doing the test in data coordinates
- # Patch transforms the mouse into data coordinates and does the
- # test for membership there. This is more efficient though it
- # may not match the visual appearance of the polygon on the
- # screen. Regardless, patch and patch collection should use
- # the same algorithm. Here's the code in patch:
- #
- # x, y = self.get_transform().inverse_xy_tup((mouseevent.x,
mouseevent.y))
- # xyverts = self.get_verts()
- # inside = nxutils.pnpoly(x, y, xyverts)
- #
- ind = []
- x, y = mouseevent.x, mouseevent.y
- for i, thispoly in enumerate(self.get_transformed_patches()):
- inside = nxutils.pnpoly(x, y, thispoly)
- if inside: ind.append(i)
+ ind = point_in_path_collection(
+ mouseevent.x, mouseevent.y, self._pickradius,
+ self.get_transform(), self._paths, self._transforms, self._offsets,
+ self._offsetTrans, self._facecolors)
return len(ind)>0,dict(ind=ind)
-
+ # MGDTODO
def get_transformed_patches(self):
"""
get a sequence of the polygons in the collection in display
(transformed) space
@@ -206,12 +229,9 @@
data.append(tverts)
return data
- def get_transoffset(self):
- if self._transOffset is None:
- self._transOffset = transforms.identity_transform()
- return self._transOffset
-
-
+ def set_pickradius(self,pickradius): self.pickradius = 5
+ def get_pickradius(self): return self.pickradius
+
def set_linewidth(self, lw):
"""
Set the linewidth(s) for the collection. lw can be a scalar or a
@@ -224,6 +244,36 @@
def set_linewidths(self, lw):
self.set_linewidth(lw)
+ def set_linestyles(self, ls):
+ """
+ Set the linestyles(s) for the collection.
+ ACCEPTS: ['solid' | 'dashed', 'dashdot', 'dotted' | (offset,
on-off-dash-seq) ]
+ """
+ try:
+ if cbook.is_string_like(ls):
+ dashes = [backend_bases.GraphicsContextBase.dashd[ls]]
+ elif cbook.iterable(ls):
+ try:
+ dashes = []
+ for x in ls:
+ if cbook.is_string_like(x):
+
dashes.append(backend_bases.GraphicsContextBase.dashd[ls])
+ elif cbook.iterator(x) and len(x) == 2:
+ dashes.append(x)
+ else:
+ raise ValueError()
+ except ValueError:
+ if len(ls)==2:
+ dashes = ls
+ else:
+ raise ValueError()
+ else:
+ raise ValueError()
+ except ValueError:
+ raise ValueError('Do not know how to convert %s to dashes'%ls)
+
+ self._ls = dashes
+
def set_color(self, c):
"""
Set both the edgecolor and the facecolor.
@@ -277,6 +327,15 @@
if cbook.is_string_like(self._edgecolors) and self._edgecolors !=
'None':
self._edgecolors = [(r,g,b,alpha) for r,g,b,a in
self._edgecolors]
+ def get_linewidth(self):
+ return self._lw
+
+ def get_linestyle(self):
+ return self._ls
+
+ def get_dashes(self):
+ return self._ls
+
def update_scalarmappable(self):
"""
If the scalar mappable array is not none, update facecolors
@@ -289,7 +348,31 @@
self._facecolors = self.to_rgba(self._A, self._alpha)
#print self._facecolors
-class QuadMesh(PatchCollection):
+
+# these are not available for the object inspector until after the
+# class is built so we define an initial set here for the init
+# function and they will be overridden after object defn
+artist.kwdocd['Collection'] = """\
+ Valid Collection kwargs are:
+
+ edgecolors=None,
+ facecolors=None,
+ linewidths=None,
+ antialiaseds = None,
+ offsets = None,
+ transOffset = transforms.identity_transform(),
+ norm = None, # optional for cm.ScalarMappable
+ cmap = None, # ditto
+
+ offsets and transOffset are used to translate the patch after
+ rendering (default no offsets)
+
+ If any of edgecolors, facecolors, linewidths, antialiaseds are
+ None, they default to their patch.* rc params setting, in sequence
+ form.
+"""
+
+class QuadMesh(Collection):
"""
Class for the efficient drawing of a quadrilateral mesh.
A quadrilateral mesh consists of a grid of vertices. The dimensions
@@ -315,7 +398,7 @@
(0, 2) .. (0, meshWidth), (1, 0), (1, 1), and so on.
"""
def __init__(self, meshWidth, meshHeight, coordinates, showedges):
- PatchCollection.__init__(self)
+ Collection.__init__(self)
self._meshWidth = meshWidth
self._meshHeight = meshHeight
self._coordinates = coordinates
@@ -329,7 +412,7 @@
# when creating/changing ****** Why not? speed?
if not self.get_visible(): return
transform = self.get_transform()
- transoffset = self.get_transoffset()
+ transoffset = self._transOffset
transform.freeze()
transoffset.freeze()
#print 'QuadMesh draw'
@@ -342,63 +425,26 @@
transform.thaw()
transoffset.thaw()
-class PolyCollection(PatchCollection):
+class PolyCollection(Collection):
def __init__(self, verts, **kwargs):
"""
verts is a sequence of ( verts0, verts1, ...) where verts_i is
a sequence of xy tuples of vertices, or an equivalent
numpy array of shape (nv,2).
- %(PatchCollection)s
+ %(Collection)s
"""
- PatchCollection.__init__(self,**kwargs)
- self._verts = verts
+ Collection.__init__(self,**kwargs)
+ self.set_verts(verts)
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
def set_verts(self, verts):
'''This allows one to delay initialization of the vertices.'''
- self._verts = verts
+ self._paths = [path.Path(v, closed=True) for v in verts]
- def draw(self, renderer):
- if not self.get_visible(): return
- renderer.open_group('polycollection')
- transform = self.get_transform()
- transoffset = self.get_transoffset()
-
-
- transform.freeze()
- transoffset.freeze()
- self.update_scalarmappable()
- if cbook.is_string_like(self._edgecolors) and self._edgecolors[:2] ==
'No':
- self._linewidths = (0,)
- #self._edgecolors = self._facecolors
- renderer.draw_poly_collection(
- self._verts, transform, self.clipbox,
- self._facecolors, self._edgecolors,
- self._linewidths, self._antialiaseds,
- self._offsets, transoffset)
- transform.thaw()
- transoffset.thaw()
- renderer.close_group('polycollection')
-
-
- def get_verts(self, dataTrans=None):
- '''Return vertices in data coordinates.
- The calculation is incomplete in general; it is based
- on the vertices or the offsets, whichever is using
- dataTrans as its transformation, so it does not take
- into account the combined effect of segments and offsets.
- '''
- verts = []
- if self._offsets is None:
- for seg in self._verts:
- verts.extend(seg)
- return [tuple(xy) for xy in verts]
- if self.get_transoffset() == dataTrans:
- return [tuple(xy) for xy in self._offsets]
- raise NotImplementedError('Vertices in data coordinates are
calculated\n'
- + 'with offsets only if _transOffset == dataTrans.')
-
+ def get_paths(self):
+ return self._paths
+
class BrokenBarHCollection(PolyCollection):
"""
A colleciton of horizontal bars spanning yrange with a sequence of
@@ -409,7 +455,7 @@
xranges : sequence of (xmin, xwidth)
yrange : ymin, ywidth
- %(PatchCollection)s
+ %(Collection)s
"""
ymin, ywidth = yrange
ymax = ymin + ywidth
@@ -417,7 +463,7 @@
PolyCollection.__init__(self, verts, **kwargs)
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
-class RegularPolyCollection(PatchCollection):
+class RegularPolyCollection(Collection):
def __init__(self,
dpi,
numsides,
@@ -437,7 +483,7 @@
* rotation is the rotation of the polygon in radians
- %(PatchCollection)s
+ %(Collection)s
Example: see examples/dynamic_collection.py for complete example
@@ -459,14 +505,18 @@
"""
- PatchCollection.__init__(self,**kwargs)
+ Collection.__init__(self,**kwargs)
self._sizes = sizes
self._dpi = dpi
- self.numsides = numsides
- self.rotation = rotation
- self._update_verts()
+ self._paths = [path.Path.unit_regular_polygon(numsides)]
+ self._transforms = [transforms.Affine2D().scale(x) for x in sizes]
+
__init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
+ def get_paths(self):
+ return self._paths
+
+ # MGDTODO
def get_transformed_patches(self):
# Shouldn't need all these calls to asarray;
# the variables should be converted when stored.
@@ -485,62 +535,6 @@
return polys
- def _update_verts(self):
- r = 1.0/math.sqrt(math.pi) # unit area
- theta = (2*math.pi/self.numsides)*npy.arange(self.numsides) +
self.rotation
- self._verts = zip( r*npy.sin(theta), r*npy.cos(theta) )
-
- def draw(self, renderer):
- if not self.get_visible(): return
- renderer.open_group('regpolycollection')
- transform = self.get_transform()
- transoffset = self.get_transoffset()
-
- transform.freeze()
- transoffset.freeze()
- self.update_scalarmappable()
- self._update_verts()
- scales = npy.sqrt(npy.asarray(self._sizes)*self._dpi.get()/72.0)
-
-
- offsets = self._offsets
- if self._offsets is not None:
- xs, ys = zip(*offsets)
- #print 'converting: units=%s,
converter=%s'%(self.axes.xaxis.units, self.axes.xaxis.converter)
- xs = self.convert_xunits(xs)
- ys = self.convert_yunits(ys)
- offsets = zip(xs, ys)
- else:
- offsets = None
-
- #print 'drawing offsets', offsets
- #print 'drawing verts', self._verts
- #print 'drawing scales', scales
- if cbook.is_string_like(self._edgecolors) and self._edgecolors[:2] ==
'No':
- #self._edgecolors = self._facecolors
- self._linewidths = (0,)
- renderer.draw_regpoly_collection(
- self.clipbox,
- offsets, transoffset,
- self._verts, scales,
- self._facecolors, self._edgecolors,
- self._linewidths, self._antialiaseds)
-
- transform.thaw()
- transoffset.thaw()
- renderer.close_group('regpolycollection')
-
-
- def get_verts(self, dataTrans=None):
- '''Return vertices in data coordinates.
- The calculation is incomplete; it uses only
- the offsets, and only if _transOffset is dataTrans.
- '''
- if self.get_transoffset() == dataTrans:
- return [tuple(xy) for xy in self._offsets]
- raise NotImplementedError('Vertices in data coordinates are
calculated\n'
- + 'only with offsets and only if _transOffset == dataTrans.')
-
class StarPolygonCollection(RegularPolyCollection):
def __init__(self,
dpi,
@@ -561,7 +555,7 @@
* rotation is the rotation of the polygon in radians
- %(PatchCollection)s
+ %(Collection)s
"""
RegularPolyCollection.__init__(self, dpi, numsides, rotation, sizes,
**kwargs)
@@ -595,7 +589,7 @@
* rotation is the rotation of the polygon in radians
- %(PatchCollection)s
+ %(Collection)s
"""
RegularPolyCollection.__init__(self, dpi, numsides, rotation, sizes,
**kwargs)
@@ -621,9 +615,8 @@
colors = None,
antialiaseds = None,
linestyles = 'solid',
- # MGDTODO: Deal with offsets (mayb
-# offsets = None,
-# transOffset = None,#transforms.identity_transform(),
+ offsets = None,
+ transOffset = None,
norm = None,
cmap = None,
pickradius = 5,
@@ -668,168 +661,52 @@
matrix _A is not None (ie a call to set_array has been made), at
draw time a call to scalar mappable will be made to set the colors.
"""
- Collection.__init__(self)
- cm.ScalarMappable.__init__(self, norm, cmap)
+ if colors is None: colors = mpl.rcParams['lines.color']
+ if linewidths is None: linewidths = (mpl.rcParams['lines.linewidth'],)
+ if antialiaseds is None: antialiaseds =
(mpl.rcParams['lines.antialiased'],)
+ self.set_linestyles(linestyles)
- if linewidths is None :
- linewidths = (mpl.rcParams['lines.linewidth'], )
- if colors is None :
- colors = (mpl.rcParams['lines.color'],)
- if antialiaseds is None :
- antialiaseds = (mpl.rcParams['lines.antialiased'], )
+ Collection.__init__(
+ self,
+ edgecolors=colors,
+ linewidths=linewidths,
+ linestyles=linestyles,
+ antialiaseds=antialiaseds,
+ offsets=offsets,
+ transOffset=transOffset,
+ norm=norm,
+ cmap=cmap,
+ pickradius=pickradius,
+ **kwargs)
- self._colors = _colors.colorConverter.to_rgba_list(colors)
- self._aa = self._get_value(antialiaseds)
- self._lw = self._get_value(linewidths)
- self.set_linestyles(linestyles)
- self._uniform_offsets = None
- # MGDTODO: Deal with offsets
-# if offsets is not None:
-# offsets = npy.asarray(offsets)
-# if len(offsets.shape) == 1:
-# offsets = offsets[npy.newaxis,:] # Make it Nx2.
-# if transOffset is None:
-# if offsets is not None:
-# self._uniform_offsets = offsets
-# offsets = None
-# transOffset = transforms.IdentityTransform()
-# self._offsets = offsets
-# self._transOffset = transOffset
+ self._facecolors = [None]
self.set_segments(segments)
- self.pickradius = pickradius
- self.update(kwargs)
- def contains(self, mouseevent):
- """
- Test whether the mouse event occurred in the collection.
-
- Returns T/F, dict(ind=itemlist), where every item in itemlist contains
the event.
- """
- import matplotlib.lines as ML
- if callable(self._contains): return self._contains(self,mouseevent)
-
- # TODO: add offset processing; adjusting the mouse for each offset
- # will be somewhat cheaper than adjusting the segments.
- if self._offsets != None:
- raise NotImplementedError, "LineCollection does not yet support
picking with offsets"
-
- mx,my = mouseevent.x,mouseevent.y
- transform = self.get_transform()
-
- # MGDTODO: Numpify
- ind = []
- for this in xrange(len(self._segments)):
- xy = transform.transform_point(self._segments[this])
- this_ind = ML.segment_hits(mx,my,xy[:,0],xy[:,1],self.pickradius)
- ind.extend([(this,k) for k in this_ind])
- return len(ind)>0,dict(ind=ind)
-
- def set_pickradius(self,pickradius): self.pickradius = 5
- def get_pickradius(self): return self.pickradius
-
- # MGDTODO: Support offsets (maybe)
-# def get_transoffset(self):
-# if self._transOffset is None:
-# self._transOffset = transforms.identity_transform()
-# return self._transOffset
-
+ def get_paths(self):
+ return self._paths
+
def set_segments(self, segments):
if segments is None: return
+ segments = [npy.asarray(seg, npy.float_) for seg in segments]
+ if self._uniform_offsets is not None:
+ segments = self._add_offsets(segments)
self._paths = [path.Path(seg, closed=False) for seg in segments]
-# if self._uniform_offsets is not None:
-# self._add_offsets()
-
set_verts = set_segments # for compatibility with PolyCollection
- # MGDTODO: Support offsets (maybe)
-# def _add_offsets(self):
-# segs = self._segments
-# offsets = self._uniform_offsets
-# Nsegs = len(segs)
-# Noffs = offsets.shape[0]
-# if Noffs == 1:
-# for i in range(Nsegs):
-# segs[i] = segs[i] + i * offsets
-# else:
-# for i in range(Nsegs):
-# io = i%Noffs
-# segs[i] = segs[i] + offsets[io:io+1]
+ def _add_offsets(self, segs):
+ offsets = self._uniform_offsets
+ Nsegs = len(segs)
+ Noffs = offsets.shape[0]
+ if Noffs == 1:
+ for i in range(Nsegs):
+ segs[i] = segs[i] + i * offsets
+ else:
+ for i in range(Nsegs):
+ io = i%Noffs
+ segs[i] = segs[i] + offsets[io:io+1]
+ return segs
- def draw(self, renderer):
- if not self.get_visible(): return
- renderer.open_group('linecollection')
- transform = self.get_transform()
- # MGDTODO: Deal with offsets (maybe)
-# transoffset = self.get_transoffset()
-
- # segments = self._segments
- # MGDTODO: Deal with offsets (maybe)
- # offsets = self._offsets
-
- # MGDTODO: Transform the paths (since we don't keep track of segments
anymore
- if self.have_units():
- segments = []
- for segment in self._segments:
- xs, ys = zip(*segment)
- xs = self.convert_xunits(xs)
- ys = self.convert_yunits(ys)
- segments.append(zip(xs, ys))
-# if self._offsets is not None:
-# xs = self.convert_xunits(self._offsets[:0])
-# ys = self.convert_yunits(self._offsets[:1])
-# offsets = zip(xs, ys)
-
- self.update_scalarmappable()
- #print 'calling renderer draw line collection'
- clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
- renderer.draw_path_collection(
- transform, self.clipbox, clippath, clippath_trans,
- self._paths, [None], [None],
- self._colors, self._lw, self._ls, self._aa)
- renderer.close_group('linecollection')
-
- def set_linewidth(self, lw):
- """
- Set the linewidth(s) for the collection. lw can be a scalar or a
- sequence; if it is a sequence the patches will cycle through the
- sequence
-
- ACCEPTS: float or sequence of floats
- """
-
- self._lw = self._get_value(lw)
-
- def set_linestyles(self, ls):
- """
- Set the linestyles(s) for the collection.
- ACCEPTS: ['solid' | 'dashed', 'dashdot', 'dotted' | (offset,
on-off-dash-seq) ]
- """
- try:
- if cbook.is_string_like(ls):
- dashes = [backend_bases.GraphicsContextBase.dashd[ls]]
- elif cbook.iterable(ls):
- try:
- dashes = []
- for x in ls:
- if cbook.is_string_like(x):
-
dashes.append(backend_bases.GraphicsContextBase.dashd[ls])
- elif cbook.iterator(x) and len(x) == 2:
- dashes.append(x)
- else:
- raise ValueError()
- except ValueError:
- if len(ls)==2:
- dashes = ls
- else:
- raise ValueError()
- else:
- raise ValueError()
- except ValueError:
- raise ValueError('Do not know how to convert %s to dashes'%ls)
-
- self._ls = dashes
-
def set_color(self, c):
"""
Set the color(s) of the line collection. c can be a
@@ -839,7 +716,7 @@
ACCEPTS: matplotlib color arg or sequence of rgba tuples
"""
- self._colors = _colors.colorConverter.to_rgba_list(c)
+ self._edgecolors = _colors.colorConverter.to_rgba_list(c)
def color(self, c):
"""
@@ -853,48 +730,12 @@
warnings.warn('LineCollection.color deprecated; use set_color instead')
return self.set_color(c)
- def set_alpha(self, alpha):
- """
- Set the alpha tranpancies of the collection. Alpha can be a
- float, in which case it is applied to the entire collection,
- or a sequence of floats
-
- ACCEPTS: float or sequence of floats
- """
-
- try: float(alpha)
- except TypeError: raise TypeError('alpha must be a float')
- else:
- artist.Artist.set_alpha(self, alpha)
- self._colors = [(r,g,b,alpha) for r,g,b,a in self._colors]
-
- def get_linewidth(self):
- return self._lw
-
- def get_linestyle(self):
- return self._ls
-
- def get_dashes(self):
- return self._ls
-
def get_color(self):
- return self._colors
+ return self._edgecolors
get_colors = get_color # for compatibility with old versions
- def update_scalarmappable(self):
- """
- If the scalar mappable array is not none, update colors
- from scalar data
- """
- if self._A is None: return
- if len(self._A.shape)>1:
- raise ValueError('LineCollections can only map rank 1 arrays')
- self._colors = self.to_rgba(self._A, self._alpha)
-
-
-artist.kwdocd['Collection'] = artist.kwdoc(Collection)
-artist.kwdocd['PatchCollection'] = patchstr = artist.kwdoc(PatchCollection)
+artist.kwdocd['Collection'] = patchstr = artist.kwdoc(Collection)
for k in ('QuadMesh', 'PolyCollection', 'BrokenBarHCollection',
'RegularPolyCollection',
'StarPolygonCollection'):
artist.kwdocd[k] = patchstr
Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py 2007-10-08 12:45:23 UTC
(rev 3927)
+++ branches/transforms/lib/matplotlib/legend.py 2007-10-08 18:10:11 UTC
(rev 3928)
@@ -32,7 +32,7 @@
from lines import Line2D
from mlab import segments_intersect
from patches import Patch, Rectangle, RegularPolygon, Shadow, bbox_artist,
draw_bbox
-from collections import LineCollection, RegularPolyCollection, PatchCollection
+from collections import LineCollection, RegularPolyCollection
from text import Text
from transforms import Affine2D, Bbox, BboxTransform
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-10-08 12:45:23 UTC (rev
3927)
+++ branches/transforms/lib/matplotlib/lines.py 2007-10-08 18:10:11 UTC (rev
3928)
@@ -349,24 +349,14 @@
self._picker = p
def get_window_extent(self, renderer):
- # MGDTODO: Numpify
- xy = self.get_transform().transform(self._xy)
+ bbox = Bbox()
+ bbox.update_from_data(self.get_transform().transform(self._xy))
- x = xy[:, 0]
- y = xy[:, 1]
- left = x.min()
- bottom = y.min()
- width = x.max() - left
- height = y.max() - bottom
-
# correct for marker size, if any
if self._marker is not None:
ms = self._markersize / 72.0 * self.figure.dpi
- left -= ms/2
- bottom -= ms/2
- width += ms
- height += ms
- return Bbox.from_lbwh(left, bottom, width, height)
+ bbox = Bbox(bbox.get_points() + [[-ms/2.0, ms/2.0]])
+ return bbox
def set_axes(self, ax):
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py 2007-10-08 12:45:23 UTC
(rev 3927)
+++ branches/transforms/lib/matplotlib/transforms.py 2007-10-08 18:10:11 UTC
(rev 3928)
@@ -395,6 +395,8 @@
when False, include the existing bounds of the Bbox.
when None, use the last value passed to Bbox.ignore().
"""
+ # MGDTODO: It may be more efficient for some callers to use
update_from_data_xy instead
+
if ignore is None:
ignore = self._ignore
@@ -430,6 +432,18 @@
npy.float_)
self._minpos = npy.minimum(minpos, self._minpos)
self.invalidate()
+
+ def update_from_data_xy(self, xy, ignore=None):
+ """
+ Update the bounds of the Bbox based on the passed in data.
+
+ xy: a numpy array of 2D points
+ ignore:
+ when True, ignore the existing bounds of the Bbox.
+ when False, include the existing bounds of the Bbox.
+ when None, use the last value passed to Bbox.ignore().
+ """
+ return self.update_from_data(xy[:, 0], xy[:, 1], ignore)
def _set_xmin(self, val):
self._points[0, 0] = val
Modified: branches/transforms/setupext.py
===================================================================
--- branches/transforms/setupext.py 2007-10-08 12:45:23 UTC (rev 3927)
+++ branches/transforms/setupext.py 2007-10-08 18:10:11 UTC (rev 3928)
@@ -352,6 +352,7 @@
try_pkgconfig(module, 'libpng', 'png')
module.libraries.append('z')
add_base_flags(module)
+ add_numpy_flags(module)
module.include_dirs.extend(['src','swig', '%s/include'%AGG_VERSION, '.'])
# put these later for correct link order
@@ -823,7 +824,7 @@
# add agg flags before pygtk because agg only supports freetype1
# and pygtk includes freetype2. This is a bit fragile.
-
+
add_tk_flags(module) # do this first
add_agg_flags(module)
add_ft2font_flags(module)
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp 2007-10-08 12:45:23 UTC (rev
3927)
+++ branches/transforms/src/_backend_agg.cpp 2007-10-08 18:10:11 UTC (rev
3928)
@@ -336,9 +336,11 @@
if (bbox_obj.ptr() != Py_None) {
PyArrayObject* bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj.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) {
+ Py_XDECREF(bbox);
throw Py::TypeError
("Expected a Bbox object.");
+ }
*l = *(double*)PyArray_GETPTR2(bbox, 0, 0);
double _b = *(double*)PyArray_GETPTR2(bbox, 0, 1);
@@ -346,8 +348,11 @@
double _t = *(double*)PyArray_GETPTR2(bbox, 1, 1);
*b = height - _t;
*t = height - _b;
+
+ Py_XDECREF(bbox);
return true;
}
+
return false;
}
@@ -920,7 +925,7 @@
Py::Object
RendererAgg::draw_path_collection(const Py::Tuple& args) {
_VERBOSE("RendererAgg::draw_path_collection");
- args.verify_length(11);
+ args.verify_length(13);
//segments, trans, clipbox, colors, linewidths, antialiaseds
agg::trans_affine master_transform =
py_to_agg_transformation_matrix(args[0]);
@@ -929,23 +934,30 @@
agg::trans_affine clippath_trans =
py_to_agg_transformation_matrix(args[3], false);
Py::SeqBase<Py::Object> paths = args[4];
Py::SeqBase<Py::Object> transforms_obj = args[5];
- Py::SeqBase<Py::Object> facecolors_obj = args[6];
- Py::SeqBase<Py::Object> edgecolors_obj = args[7];
- Py::SeqBase<Py::Float> linewidths = args[8];
- Py::SeqBase<Py::Object> linestyles_obj = args[9];
- Py::SeqBase<Py::Int> antialiaseds = args[10];
+ Py::Object offsets_obj = args[6];
+ agg::trans_affine offset_trans =
py_to_agg_transformation_matrix(args[7], false);
+ Py::SeqBase<Py::Object> facecolors_obj = args[8];
+ Py::SeqBase<Py::Object> edgecolors_obj = args[9];
+ Py::SeqBase<Py::Float> linewidths = args[10];
+ Py::SeqBase<Py::Object> linestyles_obj = args[11];
+ Py::SeqBase<Py::Int> antialiaseds = args[12];
GCAgg gc(dpi, false);
+ PyArrayObject* offsets =
(PyArrayObject*)PyArray_FromObject(offsets_obj.ptr(), PyArray_DOUBLE, 2, 2);
+ if (!offsets || offsets->dimensions[1] != 2)
+ throw Py::ValueError("Offsets array must be Nx2");
+
size_t Npaths = paths.length();
- size_t Ntransforms = std::min(transforms_obj.length(), Npaths);
- size_t Nfacecolors = std::min(facecolors_obj.length(), Npaths);
- size_t Nedgecolors = std::min(edgecolors_obj.length(), Npaths);
+ size_t Noffsets = offsets->dimensions[0];
+ size_t N = std::max(Npaths, Noffsets);
+ size_t Ntransforms = std::min(transforms_obj.length(), N);
+ size_t Nfacecolors = std::min(facecolors_obj.length(), N);
+ size_t Nedgecolors = std::min(edgecolors_obj.length(), N);
size_t Nlinewidths = linewidths.length();
- size_t Nlinestyles = std::min(linestyles_obj.length(), Npaths);
+ size_t Nlinestyles = std::min(linestyles_obj.length(), N);
size_t Naa = antialiaseds.length();
- size_t N = Npaths;
size_t i = 0;
// Convert all of the transforms up front
@@ -983,7 +995,7 @@
}
}
- // Convert all of the edges up front
+ // Convert all of the edgecolors up front
typedef std::vector<agg::rgba> edgecolors_t;
edgecolors_t edgecolors;
edgecolors.reserve(Nedgecolors);
@@ -1016,18 +1028,23 @@
bool has_clippath = render_clippath(clippath, clippath_trans);
for (i = 0; i < N; ++i) {
- facepair_t& face = facecolors[i % Nfacecolors];
- gc.color = edgecolors[i % Nedgecolors];
- gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) * dpi/72.0;
- gc.dashes = dashes[i % Nlinestyles].second;
- gc.dashOffset = dashes[i % Nlinestyles].first;
- gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
+ double xo = *(double*)PyArray_GETPTR2(offsets, i %
Noffsets, 0);
+ double yo = *(double*)PyArray_GETPTR2(offsets, i %
Noffsets, 1);
+ offset_trans.transform(&xo, &yo);
+ agg::trans_affine_translation transOffset(xo, yo);
agg::trans_affine& trans = transforms[i % Ntransforms];
- PathIterator path(paths[i]);
+ facepair_t& face = facecolors[i % Nfacecolors];
+ gc.color = edgecolors[i % Nedgecolors];
+ gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) *
dpi/72.0;
+ gc.dashes = dashes[i % Nlinestyles].second;
+ gc.dashOffset = dashes[i % Nlinestyles].first;
+ gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
+ PathIterator path(paths[i % Npaths]);
bool snap = (path.total_vertices() == 2);
- _draw_path(path, trans, snap, has_clippath, face, gc);
+ _draw_path(path, trans * transOffset, snap, has_clippath, face, gc);
}
+ Py_XDECREF(offsets);
return Py::Object();
}
@@ -1482,11 +1499,9 @@
void get_path_extents(PathIterator& path, agg::trans_affine& trans,
double* x0, double* y0, double* x1, double* y1) {
- typedef agg::conv_transform<PathIterator> transformed_path_t;
- typedef agg::conv_curve<transformed_path_t> curve_t;
+ typedef agg::conv_curve<PathIterator> curve_t;
- transformed_path_t trans_path(path, trans);
- curve_t curved_path(trans_path);
+ curve_t curved_path(path);
double x, y;
curved_path.rewind(0);
@@ -1505,6 +1520,9 @@
if (x > *x1) *x1 = x;
if (y > *y1) *y1 = y;
}
+
+ trans.transform(x0, y0);
+ trans.transform(x1, y1);
}
Py::Object _backend_agg_module::get_path_extents(const Py::Tuple& args) {
@@ -1524,6 +1542,133 @@
return result;
}
+struct PathCollectionExtents {
+ double x0, y0, x1, y1;
+};
+
+Py::Object _backend_agg_module::get_path_collection_extents(const Py::Tuple&
args) {
+ args.verify_length(5);
+
+ //segments, trans, clipbox, colors, linewidths, antialiaseds
+ agg::trans_affine master_transform =
py_to_agg_transformation_matrix(args[0]);
+ Py::SeqBase<Py::Object> paths = args[1];
+ Py::SeqBase<Py::Object> transforms_obj = args[2];
+ Py::SeqBase<Py::Object> offsets = args[3];
+ agg::trans_affine offset_trans =
py_to_agg_transformation_matrix(args[4], false);
+
+ size_t Npaths = paths.length();
+ size_t Noffsets = offsets.length();
+ size_t N = std::max(Npaths, Noffsets);
+ size_t Ntransforms = std::min(transforms_obj.length(), N);
+ size_t i;
+
+ // Convert all of the transforms up front
+ typedef std::vector<agg::trans_affine> transforms_t;
+ transforms_t transforms;
+ transforms.reserve(Ntransforms);
+ for (i = 0; i < Ntransforms; ++i) {
+ agg::trans_affine trans = py_to_agg_transformation_matrix
+ (transforms_obj[i], false);
+ trans *= master_transform;
+ transforms.push_back(trans);
+ }
+
+ typedef std::vector<PathCollectionExtents> path_extents_t;
+ path_extents_t path_extents;
+ path_extents.resize(Npaths);
+
+ // Get each of the path extents first
+ i = 0;
+ for (path_extents_t::iterator p = path_extents.begin();
+ p != path_extents.end(); ++p, ++i) {
+ PathIterator path(paths[i]);
+ agg::trans_affine& trans = transforms[i % Ntransforms];
+ ::get_path_extents(path, trans, &p->x0, &p->y0, &p->x1, &p->y1);
+ }
+
+ // The offset each of those and collect the mins/maxs
+ double x0 = std::numeric_limits<double>::infinity();
+ double y0 = std::numeric_limits<double>::infinity();
+ double x1 = -std::numeric_limits<double>::infinity();
+ double y1 = -std::numeric_limits<double>::infinity();
+ for (i = 0; i < N; ++i) {
+ Py::SeqBase<Py::Float> offset = Py::SeqBase<Py::Float>(offsets[i %
Noffsets]);
+ double xo = Py::Float(offset[0]);
+ double yo = Py::Float(offset[1]);
+ offset_trans.transform(&xo, &yo);
+ PathCollectionExtents& ext = path_extents[i % Npaths];
+
+ x0 = std::min(x0, ext.x0 + xo);
+ y0 = std::min(y0, ext.y0 + yo);
+ x1 = std::max(x1, ext.x1 + xo);
+ y1 = std::max(y1, ext.y1 + yo);
+ }
+
+ Py::Tuple result(4);
+ result[0] = Py::Float(x0);
+ result[1] = Py::Float(y0);
+ result[2] = Py::Float(x1);
+ result[3] = Py::Float(y1);
+ return result;
+}
+
+Py::Object _backend_agg_module::point_in_path_collection(const Py::Tuple&
args) {
+ args.verify_length(9);
+
+ //segments, trans, clipbox, colors, linewidths, antialiaseds
+ double x = Py::Float(args[0]);
+ double y = Py::Float(args[1]);
+ double radius = Py::Float(args[2]);
+ agg::trans_affine master_transform =
py_to_agg_transformation_matrix(args[3]);
+ Py::SeqBase<Py::Object> paths = args[4];
+ Py::SeqBase<Py::Object> transforms_obj = args[5];
+ Py::SeqBase<Py::Object> offsets = args[6];
+ agg::trans_affine offset_trans =
py_to_agg_transformation_matrix(args[7], false);
+ Py::SeqBase<Py::Object> facecolors = args[8];
+
+ size_t Npaths = paths.length();
+ size_t Noffsets = offsets.length();
+ size_t N = std::max(Npaths, Noffsets);
+ size_t Ntransforms = std::min(transforms_obj.length(), N);
+ size_t Ncolors = facecolors.length();
+ size_t i;
+
+ // Convert all of the transforms up front
+ typedef std::vector<agg::trans_affine> transforms_t;
+ transforms_t transforms;
+ transforms.reserve(Ntransforms);
+ for (i = 0; i < Ntransforms; ++i) {
+ agg::trans_affine trans = py_to_agg_transformation_matrix
+ (transforms_obj[i], false);
+ trans *= master_transform;
+ transforms.push_back(trans);
+ }
+
+ Py::List result;
+
+ for (i = 0; i < N; ++i) {
+ PathIterator path(paths[i % Npaths]);
+
+ Py::SeqBase<Py::Float> offset = Py::SeqBase<Py::Float>(offsets[i %
Noffsets]);
+ double xo = Py::Float(offset[0]);
+ double yo = Py::Float(offset[1]);
+ offset_trans.transform(&xo, &yo);
+ agg::trans_affine_translation transOffset(xo, yo);
+ agg::trans_affine trans = transforms[i % Ntransforms] * transOffset;
+
+ const Py::Object& facecolor_obj = facecolors[i & Ncolors];
+ if (facecolor_obj.ptr() == Py_None) {
+ if (::point_on_path(x, y, radius, path, trans))
+ result.append(Py::Int((int)i));
+ } else {
+ if (::point_in_path(x, y, path, trans))
+ result.append(Py::Int((int)i));
+ }
+ }
+
+ return result;
+}
+
/* ------------ module methods ------------- */
Py::Object _backend_agg_module::new_renderer (const Py::Tuple &args,
const Py::Dict &kws)
@@ -1563,7 +1708,7 @@
add_varargs_method("draw_path", &RendererAgg::draw_path,
"draw_path(gc, path, transform, rgbFace)\n");
add_varargs_method("draw_path_collection",
&RendererAgg::draw_path_collection,
- "draw_path_collection(master_transform, cliprect,
clippath, clippath_trans, paths, transforms, facecolors, edgecolors,
linewidths, linestyles, antialiaseds)\n");
+ "draw_path_collection(master_transform, cliprect,
clippath, clippath_trans, paths, transforms, offsets, offsetTrans, facecolors,
edgecolors, linewidths, linestyles, antialiaseds)\n");
add_varargs_method("draw_markers", &RendererAgg::draw_markers,
"draw_markers(gc, marker_path, marker_trans, path,
rgbFace)\n");
add_varargs_method("draw_text_image", &RendererAgg::draw_text_image,
Modified: branches/transforms/src/_backend_agg.h
===================================================================
--- branches/transforms/src/_backend_agg.h 2007-10-08 12:45:23 UTC (rev
3927)
+++ branches/transforms/src/_backend_agg.h 2007-10-08 18:10:11 UTC (rev
3928)
@@ -244,6 +244,11 @@
"point_on_path(x, y, r, path, trans)");
add_varargs_method("get_path_extents",
&_backend_agg_module::get_path_extents,
"get_path_extents(path, trans)");
+ add_varargs_method("get_path_collection_extents",
&_backend_agg_module::get_path_collection_extents,
+ "get_path_collection_extents(trans, paths, transforms,
offsets, offsetTrans)");
+ add_varargs_method("point_in_path_collection",
&_backend_agg_module::point_in_path_collection,
+ "point_in_path_collection(x, y, r, trans, paths,
transforms, offsets, offsetTrans, colors)");
+
initialize( "The agg rendering backend" );
}
@@ -255,6 +260,8 @@
Py::Object point_in_path(const Py::Tuple& args);
Py::Object point_on_path(const Py::Tuple& args);
Py::Object get_path_extents(const Py::Tuple& args);
+ Py::Object get_path_collection_extents(const Py::Tuple& args);
+ Py::Object point_in_path_collection(const Py::Tuple& args);
};
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins