|
From: <md...@us...> - 2008-09-10 18:46:13
|
Revision: 6080
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6080&view=rev
Author: mdboom
Date: 2008-09-10 18:46:10 +0000 (Wed, 10 Sep 2008)
Log Message:
-----------
[ 2089958 ] Path simplification for vector output backends
Modified Paths:
--------------
trunk/matplotlib/CHANGELOG
trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
trunk/matplotlib/lib/matplotlib/config/mplconfig.py
trunk/matplotlib/lib/matplotlib/config/rcsetup.py
trunk/matplotlib/lib/matplotlib/path.py
trunk/matplotlib/lib/matplotlib/rcsetup.py
trunk/matplotlib/matplotlibrc.template
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/CHANGELOG 2008-09-10 18:46:10 UTC (rev 6080)
@@ -1,3 +1,10 @@
+2008-09-10 [ 2089958 ] Path simplification for vector output backends
+ Leverage the simplification code exposed through
+ path_to_polygons to simplify certain well-behaved paths in
+ the vector backends (PDF, PS and SVG). "path.simplify"
+ must be set to True in matplotlibrc for this to work. -
+ MGD
+
2008-09-10 Add "filled" kwarg to Path.intersects_path and
Path.intersects_bbox. - MGD
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -331,6 +331,10 @@
def __init__(self, width, height, dpi, filename):
self.width, self.height = width, height
self.dpi = dpi
+ if rcParams['path.simplify']:
+ self.simplify = (width * dpi, height * dpi)
+ else:
+ self.simplify = None
self.nextObject = 1 # next free object id
self.xrefTable = [ [0, 65535, 'the zero object'] ]
self.passed_in_file_object = False
@@ -1092,12 +1096,12 @@
self.endStream()
#@staticmethod
- def pathOperations(path, transform):
+ def pathOperations(path, transform, simplify=None):
tpath = transform.transform_path(path)
cmds = []
last_points = None
- for points, code in tpath.iter_segments():
+ for points, code in tpath.iter_segments(simplify):
if code == Path.MOVETO:
cmds.extend(points)
cmds.append(Op.moveto)
@@ -1118,7 +1122,8 @@
pathOperations = staticmethod(pathOperations)
def writePath(self, path, transform):
- cmds = self.pathOperations(path, transform)
+ cmds = self.pathOperations(
+ path, transform, self.simplify)
self.output(*cmds)
def reserveObject(self, name=''):
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -145,6 +145,10 @@
self.textcnt = 0
self.psfrag = []
self.imagedpi = imagedpi
+ if rcParams['path.simplify']:
+ self.simplify = (width * imagedpi, height * imagedpi)
+ else:
+ self.simplify = None
# current renderer state (None=uninitialised)
self.color = None
@@ -444,12 +448,12 @@
# unflip
im.flipud_out()
- def _convert_path(self, path, transform):
+ def _convert_path(self, path, transform, simplify=None):
path = transform.transform_path(path)
ps = []
last_points = None
- for points, code in path.iter_segments():
+ for points, code in path.iter_segments(simplify):
if code == Path.MOVETO:
ps.append("%g %g m" % tuple(points))
elif code == Path.LINETO:
@@ -463,7 +467,7 @@
elif code == Path.CLOSEPOLY:
ps.append("cl")
last_points = points
-
+
ps = "\n".join(ps)
return ps
@@ -482,7 +486,7 @@
"""
Draws a Path instance using the given affine transform.
"""
- ps = self._convert_path(path, transform)
+ ps = self._convert_path(path, transform, self.simplify)
self._draw_ps(ps, gc, rgbFace)
def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -42,6 +42,10 @@
self.width=width
self.height=height
self._svgwriter = svgwriter
+ if rcParams['path.simplify']:
+ self.simplify = (width, height)
+ else:
+ self.simplify = None
self._groupd = {}
if not rcParams['svg.image_inline']:
@@ -165,14 +169,14 @@
.scale(1.0, -1.0)
.translate(0.0, self.height))
- def _convert_path(self, path, transform):
+ def _convert_path(self, path, transform, simplify=None):
tpath = transform.transform_path(path)
path_data = []
appender = path_data.append
path_commands = self._path_commands
currpos = 0
- for points, code in tpath.iter_segments():
+ for points, code in tpath.iter_segments(simplify):
if code == Path.CLOSEPOLY:
segment = 'z'
else:
@@ -187,7 +191,7 @@
def draw_path(self, gc, path, transform, rgbFace=None):
trans_and_flip = self._make_flip_transform(transform)
- path_data = self._convert_path(path, trans_and_flip)
+ path_data = self._convert_path(path, trans_and_flip, self.simplify)
self._draw_svg_element('path', 'd="%s"' % path_data, gc, rgbFace)
def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
Modified: trunk/matplotlib/lib/matplotlib/config/mplconfig.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/config/mplconfig.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -117,6 +117,9 @@
markersize = T.Float(6)
antialiased = T.true
+ class path(TConfig):
+ simplify = T.false
+
class patch(TConfig):
linewidth = T.Float(1.0)
facecolor = T.Trait('blue', mplT.ColorHandler())
@@ -439,6 +442,8 @@
'svg.image_noscale' : (self.tconfig.backend.svg, 'image_noscale'),
'svg.embed_char_paths' : (self.tconfig.backend.svg, 'embed_char_paths'),
+ # Path properties
+ 'path.simplify' : (self.tconfig.path, 'simplify')
}
def __setitem__(self, key, val):
Modified: trunk/matplotlib/lib/matplotlib/config/rcsetup.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/config/rcsetup.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -476,6 +476,7 @@
'svg.embed_char_paths' : [True, validate_bool], # True to save all characters as paths in the SVG
'plugins.directory' : ['.matplotlib_plugins', str], # where plugin directory is locate
+ 'path.simplify' : [False, validate_bool]
}
if __name__ == '__main__':
Modified: trunk/matplotlib/lib/matplotlib/path.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/path.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/path.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -145,12 +145,24 @@
def __len__(self):
return len(self.vertices)
- def iter_segments(self):
+ def iter_segments(self, simplify=None):
"""
Iterates over all of the curve segments in the path. Each
iteration returns a 2-tuple (*vertices*, *code*), where
*vertices* is a sequence of 1 - 3 coordinate pairs, and *code* is
one of the :class:`Path` codes.
+
+ If *simplify* is provided, it must be a tuple (*width*,
+ *height*) defining the size of the figure, in native units
+ (e.g. pixels or points). Simplification implies both removing
+ adjacent line segments that are very close to parallel, and
+ removing line segments outside of the figure. The path will
+ be simplified *only* if :attr:`should_simplify` is True, which
+ is determined in the constructor by this criteria:
+
+ - No *codes* array
+ - No nonfinite values
+ - More than 128 vertices
"""
vertices = self.vertices
if not len(vertices):
@@ -166,7 +178,13 @@
CLOSEPOLY = self.CLOSEPOLY
STOP = self.STOP
- if codes is None:
+ if simplify is not None and self.should_simplify:
+ polygons = self.to_polygons(None, *simplify)
+ for vertices in polygons:
+ yield vertices[0], MOVETO
+ for v in vertices[1:]:
+ yield v, LINETO
+ elif codes is None:
next_code = MOVETO
for v in vertices:
if (~isfinite(v)).any():
Modified: trunk/matplotlib/lib/matplotlib/rcsetup.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/lib/matplotlib/rcsetup.py 2008-09-10 18:46:10 UTC (rev 6080)
@@ -487,6 +487,7 @@
'svg.embed_char_paths' : [True, validate_bool], # True to save all characters as paths in the SVG
'plugins.directory' : ['.matplotlib_plugins', str], # where plugin directory is locate
+ 'path.simplify' : [False, validate_bool]
}
if __name__ == '__main__':
Modified: trunk/matplotlib/matplotlibrc.template
===================================================================
--- trunk/matplotlib/matplotlibrc.template 2008-09-10 15:28:55 UTC (rev 6079)
+++ trunk/matplotlib/matplotlibrc.template 2008-09-10 18:46:10 UTC (rev 6080)
@@ -270,6 +270,8 @@
#contour.negative_linestyle : dashed # dashed | solid
### SAVING FIGURES
+#path.simplify : False # When True, simplify paths in vector backends, such as PDF, PS and SVG
+
# the default savefig params can be different for the GUI backends.
# Eg, you may want a higher resolution, or to make the figure
# background white
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|