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 (Mon, 17 Sep 2007) 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. |