Revision: 3939
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3939&view=rev
Author: mdboom
Date: 2007-10-12 10:30:17 -0700 (Fri, 12 Oct 2007)
Log Message:
-----------
More progress on examples.
Modified Paths:
--------------
branches/transforms/PASSED_DEMOS
branches/transforms/examples/collections_demo.py
branches/transforms/examples/simple_plot_fps.py
branches/transforms/lib/matplotlib/axes.py
branches/transforms/lib/matplotlib/axis.py
branches/transforms/lib/matplotlib/colorbar.py
branches/transforms/lib/matplotlib/contour.py
branches/transforms/lib/matplotlib/text.py
branches/transforms/lib/matplotlib/ticker.py
branches/transforms/lib/matplotlib/transforms.py
branches/transforms/src/_backend_agg.cpp
Modified: branches/transforms/PASSED_DEMOS
===================================================================
--- branches/transforms/PASSED_DEMOS 2007-10-12 14:29:57 UTC (rev 3938)
+++ branches/transforms/PASSED_DEMOS 2007-10-12 17:30:17 UTC (rev 3939)
@@ -16,10 +16,10 @@
arctest.py O
arrow_demo.py O
axes_demo.py O
-axes_props.py [SOMETHING FUNNY ABOUT DASHED LINES]
+axes_props.py O
axhspan_demo.py O
axis_equal_demo.py O
-backend_driver.py
+backend_driver.py [N/A]
barchart_demo.py O
barcode_demo.py O
barh_demo.py [BROKEN IN TRUNK]
@@ -29,14 +29,14 @@
broken_barh.py O
clippath_test.py O
clippedline.py O
-collections_demo.py -- [NEEDS ADDITIONAL WORK]
+collections_demo.py O
colorbar_only.py O
color_by_yvalue.py O
color_demo.py O
colours.py [???]
-contour_demo.py
-contourf_demo.py
-contour_image.py
+contour_demo.py O
+contourf_demo.py [FLOATING POINT EXCEPTION]
+contour_image.py [FLOATING POINT EXCEPTION]
coords_demo.py O
coords_report.py O
csd_demo.py O
Modified: branches/transforms/examples/collections_demo.py
===================================================================
--- branches/transforms/examples/collections_demo.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/examples/collections_demo.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -87,7 +87,7 @@
a = fig.add_subplot(2,2,3)
col = collections.RegularPolyCollection(fig.dpi, 7,
- sizes = N.fabs(xx) / 10.0, offsets=xyo,
+ sizes = N.fabs(xx)*10.0, offsets=xyo,
transOffset=a.transData)
trans = transforms.Affine2D().scale(fig.dpi/72.0)
col.set_transform(trans) # the points to pixels transform
Modified: branches/transforms/examples/simple_plot_fps.py
===================================================================
--- branches/transforms/examples/simple_plot_fps.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/examples/simple_plot_fps.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -21,11 +21,13 @@
#savefig('simple_plot')
import time
-
+from matplotlib import transforms
+
frames = 100.0
t = time.clock()
ion()
for i in xrange(int(frames)):
+ transforms.CATCH = True
part = i / frames
axis([0.0, 1.0 - part, -1.0 + part, 1.0 - part])
show()
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py 2007-10-12 14:29:57 UTC (rev
3938)
+++ branches/transforms/lib/matplotlib/axes.py 2007-10-12 17:30:17 UTC (rev
3939)
@@ -1110,7 +1110,6 @@
# 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])
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py 2007-10-12 14:29:57 UTC (rev
3938)
+++ branches/transforms/lib/matplotlib/axis.py 2007-10-12 17:30:17 UTC (rev
3939)
@@ -91,16 +91,18 @@
self._size = size
self._padPixels = self.figure.dpi * self._pad * (1/72.0)
+ self._locTransform = Affine2D()
+
+ self.tick1line = self._get_tick1line()
+ self.tick2line = self._get_tick2line()
+ self.gridline = self._get_gridline()
-
- self.tick1line = self._get_tick1line(loc)
- self.tick2line = self._get_tick2line(loc)
- self.gridline = self._get_gridline(loc)
-
- self.label1 = self._get_text1(loc)
+ self.label1 = self._get_text1()
self.label = self.label1 # legacy name
- self.label2 = self._get_text2(loc)
+ self.label2 = self._get_text2()
+ self.update_position(loc)
+
self.gridOn = gridOn
self.tick1On = tick1On
self.tick2On = tick2On
@@ -138,23 +140,23 @@
'Get the value of the tick label pad in points'
return self._pad.get()
- def _get_text1(self, loc):
+ def _get_text1(self):
'Get the default Text 1 instance'
pass
- def _get_text2(self, loc):
+ def _get_text2(self):
'Get the default Text 2 instance'
pass
- def _get_tick1line(self, loc):
+ def _get_tick1line(self):
'Get the default line2D instance for tick1'
pass
- def _get_tick2line(self, loc):
+ def _get_tick2line(self):
'Get the default line2D instance for tick2'
pass
- def _get_gridline(self, loc):
+ def _get_gridline(self):
'Get the default grid Line2d instance for this tick'
pass
@@ -183,22 +185,6 @@
renderer.close_group(self.__name__)
- def set_xy(self, loc):
- """
- Set the location of tick in data coords with scalar loc
-
- ACCEPTS: float
- """
- raise NotImplementedError('Derived must override')
-
- def set_label(self, s): # legacy name
- """
- Set the text of ticklabel
-
- ACCEPTS: str
- """
- self.label1.set_text(s)
-
def set_label1(self, s):
"""
Set the text of ticklabel
@@ -206,7 +192,8 @@
ACCEPTS: str
"""
self.label1.set_text(s)
-
+ set_label = set_label1
+
def set_label2(self, s):
"""
Set the text of ticklabel2
@@ -233,7 +220,7 @@
the label text and the grid line
"""
__name__ = 'xtick'
- def _get_text1(self, loc):
+ def _get_text1(self):
'Get the default Text instance'
# the y loc is 3 points below the min of y axis
# get the affine as an a,b,c,d,tx,ty list
@@ -242,7 +229,7 @@
trans, vert, horiz =
self.axes.get_xaxis_text1_transform(self._padPixels)
t = TextWithDash(
- x=loc, y=0,
+ x=0, y=0,
fontproperties=FontProperties(size=rcParams['xtick.labelsize']),
color=rcParams['xtick.color'],
verticalalignment=vert,
@@ -256,15 +243,15 @@
return t
- def _get_text2(self, loc):
+ def _get_text2(self):
'Get the default Text 2 instance'
# x in data coords, y in axes coords
#t = Text(
trans, vert, horiz =
self.axes.get_xaxis_text2_transform(self._padPixels)
- t = TextWithDash(
- x=loc, y=1,
+ t = TextWithDash(
+ x=0, y=1,
fontproperties=FontProperties(size=rcParams['xtick.labelsize']),
color=rcParams['xtick.color'],
verticalalignment=vert,
@@ -272,60 +259,55 @@
xaxis=True,
horizontalalignment=horiz,
)
-
t.set_transform(trans)
self._set_artist_props(t)
return t
- def _get_tick1line(self, loc):
+ def _get_tick1line(self):
'Get the default line2D instance'
# x in data coords, y in axes coords
- l = Line2D( xdata=(loc,), ydata=(0,),
- color='k',
- linestyle = 'None',
- marker = self._xtickmarkers[0],
- markersize=self._size,
- )
+ l = Line2D(xdata=(0,), ydata=(0,),
+ color='k',
+ linestyle = 'None',
+ marker = self._xtickmarkers[0],
+ markersize=self._size,
+ )
l.set_transform(self.axes.get_xaxis_transform())
self._set_artist_props(l)
return l
- def _get_tick2line(self, loc):
+ def _get_tick2line(self):
'Get the default line2D instance'
# x in data coords, y in axes coords
- l = Line2D( xdata=(loc,), ydata=(1,),
+ l = Line2D( xdata=(0,), ydata=(1,),
color='k',
linestyle = 'None',
marker = self._xtickmarkers[1],
markersize=self._size,
)
- l.set_transform(self.axes.get_xaxis_transform())
+ l.set_transform(self._locTransform + self.axes.get_xaxis_transform())
self._set_artist_props(l)
return l
- def _get_gridline(self, loc):
+ def _get_gridline(self):
'Get the default line2D instance'
# x in data coords, y in axes coords
- l = Line2D(xdata=(loc, loc), ydata=(0, 1.0),
+ l = Line2D(xdata=(0.0, 0.0), ydata=(0, 1.0),
color=rcParams['grid.color'],
linestyle=rcParams['grid.linestyle'],
linewidth=rcParams['grid.linewidth'],
)
- l.set_transform(self.axes.get_xaxis_transform())
+ l.set_transform(self._locTransform + self.axes.get_xaxis_transform())
self._set_artist_props(l)
return l
def update_position(self, loc):
'Set the location of tick in data coords with scalar loc'
- x = loc
-
- self.tick1line.set_xdata((x,))
- self.tick2line.set_xdata((x,))
- self.gridline.set_xdata((x, ))
- self.label1.set_x(x)
- self.label2.set_x(x)
+ self._locTransform.clear().translate(loc, 0.0)
+ self.label1.set_x(loc)
+ self.label2.set_x(loc)
self._loc = loc
def get_view_interval(self):
@@ -355,14 +337,14 @@
__name__ = 'ytick'
# how far from the y axis line the right of the ticklabel are
- def _get_text1(self, loc):
+ def _get_text1(self):
'Get the default Text instance'
# x in axes coords, y in data coords
#t = Text(
trans, vert, horiz =
self.axes.get_yaxis_text1_transform(self._padPixels)
t = TextWithDash(
- x=0, y=loc,
+ x=0, y=0,
fontproperties=FontProperties(size=rcParams['ytick.labelsize']),
color=rcParams['ytick.color'],
verticalalignment=vert,
@@ -375,14 +357,14 @@
self._set_artist_props(t)
return t
- def _get_text2(self, loc):
+ def _get_text2(self):
'Get the default Text instance'
# x in axes coords, y in data coords
#t = Text(
trans, vert, horiz =
self.axes.get_yaxis_text2_transform(self._padPixels)
- t = TextWithDash(
- x=1, y=loc,
+ t = TextWithDash(
+ x=1, y=0,
fontproperties=FontProperties(size=rcParams['ytick.labelsize']),
color=rcParams['ytick.color'],
verticalalignment=vert,
@@ -394,20 +376,20 @@
self._set_artist_props(t)
return t
- def _get_tick1line(self, loc):
+ def _get_tick1line(self):
'Get the default line2D instance'
# x in axes coords, y in data coords
- l = Line2D( (0,), (loc,), color='k',
+ l = Line2D( (0,), (0,), color='k',
marker = self._ytickmarkers[0],
linestyle = 'None',
markersize=self._size,
)
- l.set_transform(self.axes.get_yaxis_transform())
+ l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
self._set_artist_props(l)
return l
- def _get_tick2line(self, loc):
+ def _get_tick2line(self):
'Get the default line2D instance'
# x in axes coords, y in data coords
l = Line2D( (1,), (0,), color='k',
@@ -416,34 +398,29 @@
markersize=self._size,
)
- l.set_transform(self.axes.get_yaxis_transform())
+ l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
self._set_artist_props(l)
return l
- def _get_gridline(self, loc):
+ def _get_gridline(self):
'Get the default line2D instance'
# x in axes coords, y in data coords
- l = Line2D( xdata=(0,1), ydata=(loc,loc),
+ l = Line2D( xdata=(0,1), ydata=(0, 0),
color=rcParams['grid.color'],
linestyle=rcParams['grid.linestyle'],
linewidth=rcParams['grid.linewidth'],
)
- l.set_transform(self.axes.get_yaxis_transform())
+ l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
self._set_artist_props(l)
return l
def update_position(self, loc):
'Set the location of tick in data coords with scalar loc'
- y = loc
- self.tick1line.set_ydata((y,))
- self.tick2line.set_ydata((y,))
- self.gridline.set_ydata((y, ))
-
- self.label1.set_y( y )
- self.label2.set_y( y )
-
+ self._locTransform.clear().translate(0.0, loc)
+ self.label1.set_y(loc)
+ self.label2.set_y(loc)
self._loc = loc
@@ -558,9 +535,11 @@
popall(self.majorTicks)
popall(self.minorTicks)
- self.majorTicks.extend([self._get_tick(major=True) for i in range(1)])
- self.minorTicks.extend([self._get_tick(major=False) for i in range(1)])
-
+ self.majorTicks.extend([self._get_tick(major=True)])
+ self.minorTicks.extend([self._get_tick(major=False)])
+ self._lastNumMajorTicks = 1
+ self._lastNumMinorTicks = 1
+
self.converter = None
self.units = None
self.set_units(None)
@@ -744,16 +723,21 @@
'get the tick instances; grow as necessary'
if numticks is None:
numticks = len(self.get_major_locator()())
-
- if len(self.majorTicks)<numticks:
+
+ if len(self.majorTicks) < numticks:
# update the new tick label properties from the old
- protoTick = self.majorTicks[0]
- for i in range(numticks-len(self.majorTicks)):
+ for i in range(numticks - len(self.majorTicks)):
tick = self._get_tick(major=True)
- #tick = protoTick
+ self.majorTicks.append(tick)
+
+ if self._lastNumMajorTicks < numticks:
+ protoTick = self.majorTicks[0]
+ for i in range(self._lastNumMajorTicks, len(self.majorTicks)):
+ tick = self.majorTicks[i]
if self._gridOnMajor: tick.gridOn = True
self._copy_tick_props(protoTick, tick)
- self.majorTicks.append(tick)
+
+ self._lastNumMajorTicks = numticks
ticks = self.majorTicks[:numticks]
return ticks
@@ -764,13 +748,20 @@
if numticks is None:
numticks = len(self.get_minor_locator()())
- if len(self.minorTicks)<numticks:
+ if len(self.minorTicks) < numticks:
+ # update the new tick label properties from the old
+ for i in range(numticks - len(self.minorTicks)):
+ tick = self._get_tick(minor=True)
+ self.minorTicks.append(tick)
+
+ if self._lastNumMinorTicks < numticks:
protoTick = self.minorTicks[0]
- for i in range(numticks-len(self.minorTicks)):
- tick = self._get_tick(major=False)
+ for i in range(self._lastNumMinorTicks, len(self.minorTicks)):
+ tick = self.minorTicks[i]
if self._gridOnMinor: tick.gridOn = True
self._copy_tick_props(protoTick, tick)
- self.minorTicks.append(tick)
+
+ self._lastNumMinorTicks = numticks
ticks = self.minorTicks[:numticks]
return ticks
@@ -946,7 +937,6 @@
self.set_major_formatter( FixedFormatter(ticklabels) )
-
ret = []
for i, tick in enumerate(self.get_major_ticks()):
if i<len(ticklabels):
Modified: branches/transforms/lib/matplotlib/colorbar.py
===================================================================
--- branches/transforms/lib/matplotlib/colorbar.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/lib/matplotlib/colorbar.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -314,8 +314,7 @@
b = self._boundaries[self._inside]
locator = ticker.FixedLocator(b, nbins=10)
if isinstance(self.norm, colors.NoNorm):
- intv = transforms.Interval(transforms.Value(self._values[0]),
- transforms.Value(self._values[-1]))
+ intv = self._values[0], self._values[-1]
else:
intv = self.vmin, self.vmax
locator.create_dummy_axis()
Modified: branches/transforms/lib/matplotlib/contour.py
===================================================================
--- branches/transforms/lib/matplotlib/contour.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/lib/matplotlib/contour.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -8,6 +8,7 @@
import numpy as npy
import matplotlib.numerix.npyma as ma
import matplotlib._cntr as _cntr
+import matplotlib.path as path
import matplotlib.ticker as ticker
import matplotlib.transforms as transforms
import matplotlib.cm as cm
@@ -210,7 +211,7 @@
trans = self.ax.transData
- slc = trans.seq_xy_tups(linecontour)
+ slc = trans.transform(linecontour)
x,y = slc[ind]
xx= npy.asarray(slc)[:,0].copy()
yy=npy.asarray(slc)[:,1].copy()
@@ -247,8 +248,9 @@
new_x1, new_y1 = x-xlabel, y-ylabel
new_x2, new_y2 = x+xlabel, y+ylabel
- new_x1d, new_y1d = trans.inverse_xy_tup((new_x1, new_y1))
- new_x2d, new_y2d = trans.inverse_xy_tup((new_x2, new_y2))
+ inverse = trans.inverted()
+ new_x1d, new_y1d = inverse.transform_point((new_x1, new_y1))
+ new_x2d, new_y2d = inverse.transform_point((new_x2, new_y2))
new_xy1 = npy.array(((new_x1d, new_y1d),))
new_xy2 = npy.array(((new_x2d, new_y2d),))
@@ -333,20 +335,22 @@
con = self.collections[icon]
lw = self.get_label_width(lev, fmt, fsize)
additions = []
- for segNum, linecontour in enumerate(con._segments):
+ paths = con.get_paths()
+ for segNum, linepath in enumerate(paths):
+ linecontour = linepath.vertices
# for closed contours add one more point to
# avoid division by zero
if npy.all(linecontour[0] == linecontour[-1]):
linecontour = npy.concatenate((linecontour,
- linecontour[1][npy.newaxis,:]))
+
linecontour[1][npy.newaxis,:]))
#linecontour.append(linecontour[1])
# transfer all data points to screen coordinates
- slc = trans.seq_xy_tups(linecontour)
+ slc = trans.transform(linecontour)
if self.print_label(slc,lw):
x,y, rotation, ind = self.locate_label(slc, lw)
# transfer the location of the label back to
# data coordinates
- dx,dy = trans.inverse_xy_tup((x,y))
+ dx,dy = trans.inverted().transform_point((x,y))
t = text.Text(dx, dy, rotation = rotation,
horizontalalignment='center',
verticalalignment='center')
@@ -355,12 +359,14 @@
self.cl.append(t)
self.cl_cvalues.append(cvalue)
if inline:
- new = self.break_linecontour(linecontour, rotation,
- lw, ind)
- con._segments[segNum] = new[0]
- additions.append(new[1])
- con._segments.extend(additions)
+ new = self.break_linecontour(linecontour, rotation,
lw, ind)
+ if len(new[0]):
+ paths[segNum] = path.Path(new[0], closed=False)
+ if len(new[1]):
+ additions.append(path.Path(new[1], closed=False))
+ paths.extend(additions)
+
class ContourSet(cm.ScalarMappable, ContourLabeler):
"""
Create and store a set of contour lines or filled regions.
@@ -494,6 +500,7 @@
'''
if self.locator is None:
self.locator = ticker.MaxNLocator(N+1)
+ self.locator.create_dummy_axis()
locator = self.locator
zmax = self.zmax
zmin = self.zmin
Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py 2007-10-12 14:29:57 UTC (rev
3938)
+++ branches/transforms/lib/matplotlib/text.py 2007-10-12 17:30:17 UTC (rev
3939)
@@ -172,7 +172,6 @@
self._linespacing = other._linespacing
def _get_layout(self, renderer):
-
# layout the xylocs in display coords as if angle = zero and
# then rotate them around self._x, self._y
#return _unit_box
@@ -327,11 +326,10 @@
self._fontproperties, angle)
return
+ canvasw, canvash = renderer.get_canvas_width_height()
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,
Modified: branches/transforms/lib/matplotlib/ticker.py
===================================================================
--- branches/transforms/lib/matplotlib/ticker.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/lib/matplotlib/ticker.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -145,6 +145,11 @@
def set_data_interval(self, vmin, vmax):
self.axis.set_data_interval(vmin, vmax)
+
+ def set_bounds(self, vmin, vmax):
+ self.set_view_interval(vmin, vmax)
+ self.set_data_interval(vmin, vmax)
+
class Formatter(TickHelper):
"""
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py 2007-10-12 14:29:57 UTC
(rev 3938)
+++ branches/transforms/lib/matplotlib/transforms.py 2007-10-12 17:30:17 UTC
(rev 3939)
@@ -32,8 +32,10 @@
import cbook
from path import Path
-DEBUG = True
+DEBUG = False
+# MGDTODO: Cache get_affine???
+
class TransformNode(object):
"""
TransformNode is the base class for anything that participates in
@@ -81,7 +83,7 @@
# A list of the children is kept around for debugging purposes
# only.
self._children = []
-
+
def __copy__(self, *args):
raise NotImplementedError(
"TransformNode instances can not be copied. " +
@@ -402,13 +404,13 @@
self._points[0] + (W, H)])
def splitx(self, *args):
- '''
+ """
e.g., bbox.splitx(f1, f2, ...)
Returns a list of new BBoxes formed by
splitting the original one with vertical lines
at fractional positions f1, f2, ...
- '''
+ """
boxes = []
xf = [0] + list(args) + [1]
l, b, r, t = self.lbrt
@@ -418,13 +420,13 @@
return boxes
def splity(self, *args):
- '''
+ """
e.g., bbox.splitx(f1, f2, ...)
Returns a list of new PBoxes formed by
splitting the original one with horizontal lines
at fractional positions f1, f2, ...
- '''
+ """
boxes = []
yf = [0] + list(args) + [1]
l, b, r, t = self.lbrt
@@ -434,6 +436,11 @@
return boxes
def count_contains(self, vertices):
+ """
+ Count the number of vertices contained in the Bbox.
+
+ vertices is a Nx2 numpy array.
+ """
if len(vertices) == 0:
return 0
vertices = npy.asarray(vertices)
@@ -446,6 +453,11 @@
return N.sum(inside)
def count_overlaps(self, bboxes):
+ """
+ Count the number of bounding boxes that overlap this one.
+
+ bboxes is a sequence of Bbox objects
+ """
ax1, ay1, ax2, ay2 = self._get_lbrt()
if ax2 < ax1:
ax2, ax1 = ax1, ax2
@@ -454,7 +466,9 @@
count = 0
for bbox in bboxes:
- bx1, by1, bx2, by2 = bbox._get_lbrt()
+ # bx1, by1, bx2, by2 = bbox._get_lbrt()
+ # The above, inlined...
+ bx1, by1, bx2, by2 = bbox.get_points().flatten()
if bx2 < bx1:
bx2, bx1 = bx1, bx2
if by2 < by1:
@@ -464,7 +478,53 @@
(bx1 >= ax2) or
(by1 >= ay2)))
return count
-
+
+ def expanded(self, sw, sh):
+ """
+ Return a new Bbox which is this Bbox expanded around its
+ center by the given factors sw and sh.
+ """
+ width = self.width
+ height = self.height
+ deltaw = (sw * width - width) / 2.0
+ deltah = (sh * height - height) / 2.0
+ a = npy.array([[-deltaw, -deltah], [deltaw, deltah]])
+ return Bbox(self._points + a)
+
+ def translated(self, tx, ty):
+ """
+ Return a copy of the Bbox, translated by tx and ty.
+ """
+ return Bbox(self._points + (tx, ty))
+
+ [EMAIL PROTECTED]
+ def union(bboxes):
+ """
+ Return a Bbox that contains all of the given bboxes.
+ """
+ assert(len(bboxes))
+
+ if len(bboxes) == 1:
+ return bboxes[0]
+
+ xmin = npy.inf
+ ymin = npy.inf
+ xmax = -npy.inf
+ ymax = -npy.inf
+
+ for bbox in bboxes:
+ points = bbox.get_points()
+ xs = points[:, 0]
+ ys = points[:, 1]
+ xmin = min(xmin, npy.min(xs))
+ ymin = min(ymin, npy.min(ys))
+ xmax = max(xmax, npy.max(xs))
+ ymax = max(ymax, npy.max(ys))
+
+ return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
+ union = staticmethod(union)
+
+
class Bbox(BboxBase):
def __init__(self, points):
"""
@@ -535,7 +595,6 @@
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
@@ -569,7 +628,6 @@
max(y.max(), self.ymax)]],
npy.float_)
self._minpos = npy.minimum(minpos, self._minpos)
-
self.invalidate()
def update_from_data_xy(self, xy, ignore=None):
@@ -665,52 +723,7 @@
"""
self._points = other.get_points()
self.invalidate()
-
- def expanded(self, sw, sh):
- """
- Return a new Bbox which is this Bbox expanded around its
- center by the given factors sw and sh.
- """
- width = self.width
- height = self.height
- deltaw = (sw * width - width) / 2.0
- deltah = (sh * height - height) / 2.0
- a = npy.array([[-deltaw, -deltah], [deltaw, deltah]])
- return Bbox(self._points + a)
- def translated(self, tx, ty):
- """
- Return a copy of the Bbox, translated by tx and ty.
- """
- return Bbox(self._points + (tx, ty))
-
- [EMAIL PROTECTED]
- def union(bboxes):
- """
- Return a Bbox that contains all of the given bboxes.
- """
- assert(len(bboxes))
-
- if len(bboxes) == 1:
- return bboxes[0]
-
- xmin = npy.inf
- ymin = npy.inf
- xmax = -npy.inf
- ymax = -npy.inf
-
- for bbox in bboxes:
- points = bbox.get_points()
- xs = points[:, 0]
- ys = points[:, 1]
- xmin = min(xmin, npy.min(xs))
- ymin = min(ymin, npy.min(ys))
- xmax = max(xmax, npy.max(xs))
- ymax = max(ymax, npy.max(ys))
-
- return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
- union = staticmethod(union)
-
class TransformedBbox(BboxBase):
"""
@@ -1633,15 +1646,39 @@
else:
return npy.concatenate((x_points, y_points), 1)
transform.__doc__ = Transform.transform.__doc__
-
- transform_non_affine = transform
+
+ def transform_affine(self, points):
+ if self._x.is_affine and self._y.is_affine:
+ return self.transform(points)
+ return points
+ transform_affine.__doc__ = Transform.transform_affine.__doc__
+
+ def transform_non_affine(self, points):
+ if self._x.is_affine and self._y.is_affine:
+ return points
+ return self.transform(points)
transform_non_affine.__doc__ = Transform.transform_non_affine.__doc__
def inverted(self):
return BlendedGenericTransform(self._x.inverted(), self._y.inverted())
inverted.__doc__ = Transform.inverted.__doc__
-
+ def get_affine(self):
+ if self._x.is_affine and self._y.is_affine:
+ if self._x == self._y:
+ return self._x.get_affine()
+ else:
+ x_mtx = self._x.get_affine().get_matrix()
+ y_mtx = self._y.get_affine().get_matrix()
+ # This works because we already know the transforms are
+ # separable, though normally one would want to set b and
+ # c to zero.
+ mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
+ return Affine2D(mtx)
+ return IdentityTransform()
+ get_affine.__doc__ = Transform.get_affine.__doc__
+
+
class BlendedAffine1D(Affine2DBase):
"""
A "blended" transform uses one transform for the x-direction, and
@@ -1807,7 +1844,7 @@
is_affine = property(_get_is_affine)
def _get_is_separable(self):
- return self._a.is_separable() and self._b.is_separable()
+ return self._a.is_separable and self._b.is_separable
is_separable = property(_get_is_separable)
def __repr__(self):
@@ -1838,7 +1875,7 @@
def transform_path_affine(self, path):
return self._b.transform_path_affine(
- self._a.transform(path))
+ self._a.transform_path(path))
transform_path_affine.__doc__ = Transform.transform_path_affine.__doc__
def transform_path_non_affine(self, path):
@@ -1850,7 +1887,8 @@
def get_affine(self):
if self._a.is_affine and self._b.is_affine:
- return CompositeAffine2D(self._a.get_affine(),
self._b.get_affine())
+ return Affine2D(npy.dot(self._b.get_affine().get_matrix(),
+ self._a.get_affine().get_matrix()))
return self._b.get_affine()
get_affine.__doc__ = Transform.get_affine.__doc__
Modified: branches/transforms/src/_backend_agg.cpp
===================================================================
--- branches/transforms/src/_backend_agg.cpp 2007-10-12 14:29:57 UTC (rev
3938)
+++ branches/transforms/src/_backend_agg.cpp 2007-10-12 17:30:17 UTC (rev
3939)
@@ -82,7 +82,10 @@
return agg::trans_affine(a, b, c, d, e, f);
}
} catch (...) {
-
+ if (errors) {
+ Py_XDECREF(matrix);
+ throw;
+ }
}
Py_XDECREF(matrix);
@@ -333,8 +336,10 @@
bool
RendererAgg::bbox_to_rect(const Py::Object& bbox_obj, double* l, double* b,
double* r, double* t) {
+ PyArrayObject* bbox = NULL;
+
if (bbox_obj.ptr() != Py_None) {
- PyArrayObject* bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj.ptr(),
PyArray_DOUBLE, 2, 2);
+ bbox = (PyArrayObject*) PyArray_FromObject(bbox_obj.ptr(), PyArray_DOUBLE,
2, 2);
if (!bbox || bbox->nd != 2 || bbox->dimensions[0] != 2 ||
bbox->dimensions[1] != 2) {
Py_XDECREF(bbox);
@@ -559,9 +564,9 @@
PathIterator path(path_obj);
transformed_path_t path_transformed(path, trans);
- bool snap = should_snap(path, trans);
- GCAgg gc = GCAgg(gc_obj, dpi, snap);
- quantize_t path_quantized(path_transformed, snap);
+ // bool snap = should_snap(path, trans);
+ GCAgg gc = GCAgg(gc_obj, dpi, true);
+ quantize_t path_quantized(path_transformed, true);
path_quantized.rewind(0);
facepair_t face = _get_rgba_face(face_obj, gc.alpha);
@@ -638,6 +643,7 @@
} catch(...) {
delete[] fillCache;
delete[] strokeCache;
+ throw;
}
delete [] fillCache;
@@ -879,7 +885,7 @@
theRasterizer->add_path(stroke);
}
- if (gc.isaa && !(snap && gc.dashes.size())) {
+ if (gc.isaa && !(snap && gc.linewidth < 1.5)) {
if (has_clippath) {
pixfmt_amask_type pfa(*pixFmt, *alphaMask);
amask_ren_type r(pfa);
@@ -954,99 +960,110 @@
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");
+ PyArrayObject* offsets = NULL;
+ PyArrayObject* facecolors = NULL;
+ PyArrayObject* edgecolors = NULL;
- PyArrayObject* facecolors =
(PyArrayObject*)PyArray_FromObject(facecolors_obj.ptr(), PyArray_DOUBLE, 1, 2);
- if (!facecolors ||
- (facecolors->nd == 1 && facecolors->dimensions[0] != 0) ||
- (facecolors->nd == 2 && facecolors->dimensions[1] != 4))
- throw Py::ValueError("Facecolors must be a Nx4 numpy array or empty");
+ try {
+ 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");
- PyArrayObject* edgecolors =
(PyArrayObject*)PyArray_FromObject(edgecolors_obj.ptr(), PyArray_DOUBLE, 1, 2);
- if (!edgecolors ||
- (edgecolors->nd == 1 && edgecolors->dimensions[0] != 0) ||
- (edgecolors->nd == 2 && edgecolors->dimensions[1] != 4))
- throw Py::ValueError("Edgecolors must be a Nx4 numpy array");
+ PyArrayObject* facecolors =
(PyArrayObject*)PyArray_FromObject(facecolors_obj.ptr(), PyArray_DOUBLE, 1, 2);
+ if (!facecolors ||
+ (facecolors->nd == 1 && facecolors->dimensions[0] != 0) ||
+ (facecolors->nd == 2 && facecolors->dimensions[1] != 4))
+ throw Py::ValueError("Facecolors must be a Nx4 numpy array or empty");
- size_t Npaths = paths.length();
- 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 = facecolors->dimensions[0];
- size_t Nedgecolors = edgecolors->dimensions[0];
- size_t Nlinewidths = linewidths.length();
- size_t Nlinestyles = std::min(linestyles_obj.length(), N);
- size_t Naa = antialiaseds.length();
+ PyArrayObject* edgecolors =
(PyArrayObject*)PyArray_FromObject(edgecolors_obj.ptr(), PyArray_DOUBLE, 1, 2);
+ if (!edgecolors ||
+ (edgecolors->nd == 1 && edgecolors->dimensions[0] != 0) ||
+ (edgecolors->nd == 2 && edgecolors->dimensions[1] != 4))
+ throw Py::ValueError("Edgecolors must be a Nx4 numpy array");
+
+ size_t Npaths = paths.length();
+ 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 = facecolors->dimensions[0];
+ size_t Nedgecolors = edgecolors->dimensions[0];
+ size_t Nlinewidths = linewidths.length();
+ size_t Nlinestyles = std::min(linestyles_obj.length(), N);
+ size_t Naa = antialiaseds.length();
- if ((Nfacecolors == 0 && Nedgecolors == 0) || N == 0)
- return Py::Object();
-
- size_t i = 0;
-
- // 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);
- }
-
- // Convert all the dashes up front
- typedef std::vector<std::pair<double, GCAgg::dash_t> > dashes_t;
- dashes_t dashes;
- dashes.resize(Nlinestyles);
- i = 0;
- for (dashes_t::iterator d = dashes.begin();
- d != dashes.end(); ++d, ++i) {
- convert_dashes(Py::Tuple(linestyles_obj[i]), false, dpi, d->second,
d->first);
- }
-
- // Handle any clipping globally
- theRasterizer->reset_clipping();
- rendererBase->reset_clipping(true);
- set_clipbox(cliprect, theRasterizer);
- bool has_clippath = render_clippath(clippath, clippath_trans);
-
- // Set some defaults, assuming no face or edge
- gc.linewidth = 0.0;
- facepair_t face;
- face.first = Nfacecolors != 0;
-
- for (i = 0; i < N; ++i) {
- PathIterator path(paths[i % Npaths]);
- bool snap = (path.total_vertices() == 2);
- 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];
-
- if (Nfacecolors) {
- size_t fi = i % Nfacecolors;
- face.second = agg::rgba(*(double*)PyArray_GETPTR2(facecolors,
fi, 0),
- *(double*)PyArray_GETPTR2(facecolors,
fi, 1),
- *(double*)PyArray_GETPTR2(facecolors,
fi, 2),
- *(double*)PyArray_GETPTR2(facecolors,
fi, 3));
+ if ((Nfacecolors == 0 && Nedgecolors == 0) || N == 0)
+ return Py::Object();
+
+ size_t i = 0;
+
+ // 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);
}
-
- if (Nedgecolors) {
- size_t ei = i % Nedgecolors;
- gc.color = agg::rgba(*(double*)PyArray_GETPTR2(edgecolors,
ei, 0),
- *(double*)PyArray_GETPTR2(edgecolors,
ei, 1),
- *(double*)PyArray_GETPTR2(edgecolors,
ei, 2),
- *(double*)PyArray_GETPTR2(edgecolors,
ei, 3));
- gc.linewidth = double(Py::Float(linewidths[i % Nlinewidths])) *
dpi/72.0;
- gc.dashes = dashes[i % Nlinestyles].second;
- gc.dashOffset = dashes[i % Nlinestyles].first;
+
+ // Convert all the dashes up front
+ typedef std::vector<std::pair<double, GCAgg::dash_t> > dashes_t;
+ dashes_t dashes;
+ dashes.resize(Nlinestyles);
+ i = 0;
+ for (dashes_t::iterator d = dashes.begin();
+ d != dashes.end(); ++d, ++i) {
+ convert_dashes(Py::Tuple(linestyles_obj[i]), false, dpi, d->second,
d->first);
}
-
- gc.isaa = bool(Py::Int(antialiaseds[i % Naa]));
- _draw_path(path, trans * transOffset, snap, has_clippath, face, gc);
+
+ // Handle any clipping globally
+ theRasterizer->reset_clipping();
+ rendererBase->reset_clipping(true);
+ set_clipbox(cliprect, theRasterizer);
+ bool has_clippath = render_clippath(clippath, clippath_trans);
+
+ // Set some defaults, assuming no face or edge
+ gc.linewidth = 0.0;
+ facepair_t face;
+ face.first = Nfacecolors != 0;
+
+ for (i = 0; i < N; ++i) {
+ PathIterator path(paths[i % Npaths]);
+ bool snap = (path.total_vertices() == 2);
+ 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];
+
+ if (Nfacecolors) {
+ size_t fi = i % Nfacecolors;
+ face.second =
agg::rgba(*(double*)PyArray_GETPTR2(facecolors, fi, 0),
+
*(double*)PyArray_GETPTR2(facecolors, fi, 1),
+
*(double*)PyArray_GETPTR2(facecolors, fi, 2),
+
*(double*)PyArray_GETPTR2(facecolors, fi, 3));
+ }
+
+ if (Nedgecolors) {
+ size_t ei = i % Nedgecolors;
+ gc.color =
agg::rgba(*(double*)PyArray_GETPTR2(edgecolors, ei, 0),
+
*(double*)PyArray_GETPTR2(edgecolors, ei, 1),
+
*(double*)PyArray_GETPTR2(edgecolors, ei, 2),
+
*(double*)PyArray_GETPTR2(edgecolors, ei, 3));
+ 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]));
+ _draw_path(path, trans * transOffset, snap, has_clippath, face, gc);
+ }
+ } catch (...) {
+ Py_XDECREF(offsets);
+ Py_XDECREF(facecolors);
+ Py_XDECREF(edgecolors);
+ throw;
}
Py_XDECREF(offsets);
@@ -1518,18 +1535,15 @@
void get_path_extents(PathIterator& path, agg::trans_affine& trans,
double* x0, double* y0, double* x1, double* y1) {
- typedef agg::conv_curve<PathIterator> curve_t;
-
- curve_t curved_path(path);
+ typedef agg::conv_transform<PathIterator> transformed_path_t;
+ typedef agg::conv_curve<transformed_path_t> curve_t;
double x, y;
- curved_path.rewind(0);
+ unsigned code;
- unsigned code = curved_path.vertex(&x, &y);
+ transformed_path_t tpath(path, trans);
+ curve_t curved_path(tpath);
- *x0 = x;
- *y0 = y;
- *x1 = x;
- *y1 = y;
+ curved_path.rewind(0);
while ((code = curved_path.vertex(&x, &y)) != agg::path_cmd_stop) {
if (code & agg::path_cmd_end_poly == agg::path_cmd_end_poly)
@@ -1539,9 +1553,6 @@
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) {
@@ -1550,7 +1561,11 @@
PathIterator path(args[0]);
agg::trans_affine trans = py_to_agg_transformation_matrix(args[1]);
- double x0, y0, x1, y1;
+ 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();
+
::get_path_extents(path, trans, &x0, &y0, &x1, &y1);
Py::Tuple result(4);
@@ -1561,10 +1576,6 @@
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);
@@ -1572,57 +1583,58 @@
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];
+ Py::Object offsets_obj = 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;
+ PyArrayObject* offsets = NULL;
+ double x0, y0, x1, y1;
- // 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);
+ try {
+ 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");
- // 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);
- }
+ size_t Npaths = paths.length();
+ size_t Noffsets = offsets->dimensions[0];
+ size_t N = std::max(Npaths, Noffsets);
+ size_t Ntransforms = std::min(transforms_obj.length(), N);
+ size_t i;
- // 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];
+ // 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);
+ }
+
+ // The offset each of those and collect the mins/maxs
+ x0 = std::numeric_limits<double>::infinity();
+ y0 = std::numeric_limits<double>::infinity();
+ x1 = -std::numeric_limits<double>::infinity();
+ y1 = -std::numeric_limits<double>::infinity();
+ for (i = 0; i < N; ++i) {
+ PathIterator path(paths[i % Npaths]);
+
+ 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];
+ trans *= transOffset;
- 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);
+ ::get_path_extents(path, trans, &x0, &y0, &x1, &y1);
+ }
+ } catch (...) {
+ Py_XDECREF(offsets);
+ throw;
}
+ Py_XDECREF(offsets);
+
Py::Tuple result(4);
result[0] = Py::Float(x0);
result[1] = Py::Float(y0);
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