[Python-modules-commits] [python-mplexporter] 25/135: add path rendering
Wolfgang Borgert
debacle at moszumanska.debian.org
Tue Sep 23 21:19:00 UTC 2014
This is an automated email from the git hooks/post-receive script.
debacle pushed a commit to branch master
in repository python-mplexporter.
commit 6880903d200ceaf982a43366406b070f58114654
Author: Jake Vanderplas <vanderplas at astro.washington.edu>
Date: Thu Feb 20 13:59:11 2014 -0800
add path rendering
---
mplexporter/exporter.py | 15 ++++++++-
mplexporter/renderers/base.py | 14 +++++++--
mplexporter/tests/test_utils.py | 11 +++++++
mplexporter/utils.py | 67 ++++++++++++++++++++++++++++++++++-------
4 files changed, 92 insertions(+), 15 deletions(-)
diff --git a/mplexporter/exporter.py b/mplexporter/exporter.py
index 4586d4b..dcb0cf5 100644
--- a/mplexporter/exporter.py
+++ b/mplexporter/exporter.py
@@ -68,7 +68,7 @@ class Exporter(object):
if data is not None:
return code, transform.transform(data)
else:
- return code
+ return code
def _crawl_fig(self, fig):
properties = {'figwidth': fig.get_figwidth(),
@@ -92,6 +92,7 @@ class Exporter(object):
'dynamic': ax.get_navigate()}
with self.renderer.draw_axes(ax, properties):
self._extract_lines(ax)
+ self._extract_patches(ax)
self._extract_texts(ax)
def _extract_lines(self, ax):
@@ -127,3 +128,15 @@ class Exporter(object):
position)
style = utils.get_text_style(text)
self.renderer.draw_text(content, position, code, style)
+
+ def _extract_patches(self, ax):
+ for patch in ax.patches:
+ vertices, pathcodes = utils.SVG_path(patch.get_path())
+ transform = patch.get_transform()
+ coordinates, vertices = self._process_transform(transform,
+ ax, vertices)
+ linestyle = utils.get_path_style(patch)
+ self.renderer.draw_path(vertices,
+ coordinates=coordinates,
+ pathcodes=pathcodes,
+ style=linestyle)
diff --git a/mplexporter/renderers/base.py b/mplexporter/renderers/base.py
index eef8b68..1c7d637 100644
--- a/mplexporter/renderers/base.py
+++ b/mplexporter/renderers/base.py
@@ -71,12 +71,20 @@ class Renderer(object):
def close_axes(self, ax):
pass
- def draw_line(self, data, coordinates, style):
- raise NotImplementedError()
-
def draw_markers(self, data, coordinates, style):
raise NotImplementedError()
def draw_text(self, text, position, coordinates, style):
raise NotImplementedError()
+ def draw_path(self, data, coordinates, pathcodes, style):
+ raise NotImplementedError()
+
+ def draw_line(self, data, coordinates, style):
+ # by default, draw the line via the draw_path() command. Some renderers
+ # might wish to override this and provide more fine-grained behavior.
+ pathcodes = ['M'] + (data.shape[0] - 1) * ['L']
+ pathstyle = dict(facecolor='none', **style)
+ pathstyle['edgecolor'] = pathstyle.pop('color')
+ pathstyle['edgewidth'] = pathstyle.pop('linewidth')
+ self.draw_path(data, coordinates, pathcodes, pathstyle)
diff --git a/mplexporter/tests/test_utils.py b/mplexporter/tests/test_utils.py
new file mode 100644
index 0000000..ac22b86
--- /dev/null
+++ b/mplexporter/tests/test_utils.py
@@ -0,0 +1,11 @@
+from numpy.testing import assert_allclose, assert_equal
+import matplotlib.pyplot as plt
+from .. import utils
+
+
+def test_path_data():
+ circle = plt.Circle((0, 0), 1)
+ vertices, codes = utils.SVG_path(circle.get_path())
+
+ assert_allclose(vertices.shape, (26, 2))
+ assert_equal(codes, ['M', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'Z'])
diff --git a/mplexporter/utils.py b/mplexporter/utils.py
index f332b8f..8c6cc7a 100644
--- a/mplexporter/utils.py
+++ b/mplexporter/utils.py
@@ -2,6 +2,10 @@
Utility Routines for Working with Matplotlib Objects
====================================================
"""
+import itertools
+
+import numpy as np
+
from matplotlib.colors import colorConverter
from matplotlib.path import Path
from matplotlib.markers import MarkerStyle
@@ -14,7 +18,6 @@ def color_to_hex(color):
return '#{0:02X}{1:02X}{2:02X}'.format(*(int(255 * c) for c in rgb))
-
def many_to_one(input_dict):
"""Convert a many-to-one mapping to a one-to-one mapping"""
return dict((key, val)
@@ -47,23 +50,64 @@ def get_dasharray(obj, i=None):
PATH_DICT = {Path.LINETO: 'L',
Path.MOVETO: 'M',
- Path.STOP: 'STOP',
Path.CURVE3: 'S',
Path.CURVE4: 'C',
Path.CLOSEPOLY: 'Z'}
-def SVG_path(path, transform=None):
- """Return a list of SVG path tuples of a (transformed) path"""
+def SVG_path(path, transform=None, simplify=False):
+ """Construct the vertices and SVG codes for the path
+
+ Parameters
+ ----------
+ path : matplotlib.Path object
+
+ transform : matplotlib transform (optional)
+ if specified, the path will be transformed before computing the output.
+
+ Returns
+ -------
+ vertices : array
+ The shape (M, 2) array of vertices of the Path. Note that some Path
+ codes require multiple vertices, so the length of these vertices may
+ be longer than the list of path codes.
+ path_codes : list
+ A length N list of single-character path codes, N <= M. Each code is
+ a single character, in ['L','M','S','C','Z']. See the standard SVG
+ path specification for a description of these.
+ """
if transform is not None:
path = path.transformed(transform)
- return [(PATH_DICT[path_code], vertices.tolist())
- for vertices, path_code in path.iter_segments(simplify=False)]
-
+ vc_tuples = [(vertices if path_code != Path.CLOSEPOLY else [],
+ PATH_DICT[path_code])
+ for (vertices, path_code)
+ in path.iter_segments(simplify=simplify)]
+
+ if not vc_tuples:
+ # empty path is a special case
+ return np.zeros((0, 2)), []
+ else:
+ vertices, codes = zip(*vc_tuples)
+ vertices = np.array(list(itertools.chain(*vertices))).reshape(-1, 2)
+ return vertices, list(codes)
+
+
+def get_path_style(path):
+ """Get the style dictionary for matplotlib path objects"""
+ style = {}
+ style['alpha'] = path.get_alpha()
+ if style['alpha'] is None:
+ style['alpha'] = 1
+ style['edgecolor'] = color_to_hex(path.get_edgecolor())
+ style['facecolor'] = color_to_hex(path.get_facecolor())
+ style['edgewidth'] = path.get_linewidth()
+ style['dasharray'] = get_dasharray(path)
+ return style
+
def get_line_style(line):
- """Return the line style dict for the line"""
+ """Get the style dictionary for matplotlib line objects"""
style = {}
style['alpha'] = line.get_alpha()
if style['alpha'] is None:
@@ -75,7 +119,7 @@ def get_line_style(line):
def get_marker_style(line):
- """Return the marker style dict for the line"""
+ """Get the style dictionary for matplotlib marker objects"""
style = {}
style['alpha'] = line.get_alpha()
if style['alpha'] is None:
@@ -94,6 +138,7 @@ def get_marker_style(line):
markertransform)
return style
+
def get_text_style(text):
"""Return the text style dict for a text instance"""
style = {}
@@ -102,7 +147,7 @@ def get_text_style(text):
style['alpha'] = 1
style['fontsize'] = text.get_size()
style['color'] = color_to_hex(text.get_color())
- style['halign'] = text.get_horizontalalignment() # left, center, right
- style['valign'] = text.get_verticalalignment() # baseline, center, top
+ style['halign'] = text.get_horizontalalignment() # left, center, right
+ style['valign'] = text.get_verticalalignment() # baseline, center, top
style['rotation'] = text.get_rotation()
return style
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mplexporter.git
More information about the Python-modules-commits
mailing list