Skip to content

Commit 8357131

Browse files
committed
ENH: Add TransformedPatchPath for clipping.
By linking to the Patch instead of its Path, the clip path can automatically update whenever the underlying Patch changes.
1 parent e7e8bcb commit 8357131

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

lib/matplotlib/artist.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from matplotlib.cbook import mplDeprecation
1313
from matplotlib import docstring, rcParams
1414
from .transforms import (Bbox, IdentityTransform, TransformedBbox,
15-
TransformedPath, Transform)
15+
TransformedPatchPath, TransformedPath, Transform)
1616
from .path import Path
1717

1818
# Note, matplotlib artists use the doc strings for set and get
@@ -685,9 +685,7 @@ def set_clip_path(self, path, transform=None):
685685
self._clippath = None
686686
success = True
687687
elif isinstance(path, Patch):
688-
self._clippath = TransformedPath(
689-
path.get_path(),
690-
path.get_transform())
688+
self._clippath = TransformedPatchPath(path)
691689
success = True
692690
elif isinstance(path, tuple):
693691
path, transform = path
@@ -698,6 +696,9 @@ def set_clip_path(self, path, transform=None):
698696
elif isinstance(path, Path):
699697
self._clippath = TransformedPath(path, transform)
700698
success = True
699+
elif isinstance(path, TransformedPatchPath):
700+
self._clippath = path
701+
success = True
701702
elif isinstance(path, TransformedPath):
702703
self._clippath = path
703704
success = True

lib/matplotlib/transforms.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,6 +2715,46 @@ def get_affine(self):
27152715
return self._transform.get_affine()
27162716

27172717

2718+
class TransformedPatchPath(TransformedPath):
2719+
"""
2720+
A :class:`TransformedPatchPath` caches a non-affine transformed copy of
2721+
the :class:`~matplotlib.path.Patch`. This cached copy is automatically
2722+
updated when the non-affine part of the transform or the patch changes.
2723+
"""
2724+
def __init__(self, patch):
2725+
"""
2726+
Create a new :class:`TransformedPatchPath` from the given
2727+
:class:`~matplotlib.path.Patch`.
2728+
"""
2729+
TransformNode.__init__(self)
2730+
2731+
transform = patch.get_transform()
2732+
self._patch = patch
2733+
self._transform = transform
2734+
self.set_children(transform)
2735+
self._path = patch.get_path()
2736+
self._transformed_path = None
2737+
self._transformed_points = None
2738+
2739+
def _revalidate(self):
2740+
patch_path = self._patch.get_path()
2741+
# Only recompute if the invalidation includes the non_affine part of
2742+
# the transform, or the Patch's Path has changed.
2743+
if (self._transformed_path is None or self._path != patch_path or
2744+
(self._invalid & self.INVALID_NON_AFFINE ==
2745+
self.INVALID_NON_AFFINE)):
2746+
self._path = patch_path
2747+
self._transformed_path = \
2748+
self._transform.transform_path_non_affine(patch_path)
2749+
self._transformed_points = \
2750+
Path._fast_from_codes_and_verts(
2751+
self._transform.transform_non_affine(patch_path.vertices),
2752+
None,
2753+
{'interpolation_steps': patch_path._interpolation_steps,
2754+
'should_simplify': patch_path.should_simplify})
2755+
self._invalid = 0
2756+
2757+
27182758
def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
27192759
'''
27202760
Modify the endpoints of a range as needed to avoid singularities.

0 commit comments

Comments
 (0)