|
| 1 | + |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +import matplotlib.pyplot as plt |
| 5 | +from matplotlib.image import BboxImage |
| 6 | +import numpy as np |
| 7 | +from matplotlib.transforms import IdentityTransform |
| 8 | + |
| 9 | +import matplotlib.patches as mpatches |
| 10 | + |
| 11 | +from matplotlib.offsetbox import AnnotationBbox,\ |
| 12 | + AnchoredOffsetbox, AuxTransformBox |
| 13 | + |
| 14 | +from matplotlib.cbook import get_sample_data |
| 15 | + |
| 16 | +from matplotlib.text import TextPath |
| 17 | + |
| 18 | + |
| 19 | +class PathClippedImagePatch(mpatches.PathPatch): |
| 20 | + """ |
| 21 | + The given image is used to draw the face of the patch. Internally, |
| 22 | + it uses BboxImage whose clippath set to the path of the patch. |
| 23 | +
|
| 24 | + FIXME : The result is currently dpi dependent. |
| 25 | + """ |
| 26 | + |
| 27 | + def __init__(self, path, bbox_image, **kwargs): |
| 28 | + mpatches.PathPatch.__init__(self, path, **kwargs) |
| 29 | + self._init_bbox_image(bbox_image) |
| 30 | + |
| 31 | + def set_facecolor(self, color): |
| 32 | + """simply ignore facecolor""" |
| 33 | + mpatches.PathPatch.set_facecolor(self, "none") |
| 34 | + |
| 35 | + def _init_bbox_image(self, im): |
| 36 | + |
| 37 | + bbox_image = BboxImage(self.get_window_extent, |
| 38 | + norm=None, |
| 39 | + origin=None, |
| 40 | + ) |
| 41 | + bbox_image.set_transform(IdentityTransform()) |
| 42 | + |
| 43 | + bbox_image.set_data(im) |
| 44 | + self.bbox_image = bbox_image |
| 45 | + |
| 46 | + def draw(self, renderer=None): |
| 47 | + |
| 48 | + # the clip path must be updated every draw. any solution? -JJ |
| 49 | + self.bbox_image.set_clip_path(self._path, self.get_transform()) |
| 50 | + self.bbox_image.draw(renderer) |
| 51 | + |
| 52 | + mpatches.PathPatch.draw(self, renderer) |
| 53 | + |
| 54 | + |
| 55 | +if 1: |
| 56 | + |
| 57 | + usetex = plt.rcParams["text.usetex"] |
| 58 | + |
| 59 | + fig = plt.figure(1) |
| 60 | + |
| 61 | + # EXAMPLE 1 |
| 62 | + |
| 63 | + ax = plt.subplot(211) |
| 64 | + |
| 65 | + from matplotlib._png import read_png |
| 66 | + fn = get_sample_data("grace_hopper.png", asfileobj=False) |
| 67 | + arr = read_png(fn) |
| 68 | + |
| 69 | + text_path = TextPath((0, 0), "!?", size=150) |
| 70 | + p = PathClippedImagePatch(text_path, arr, ec="k", |
| 71 | + transform=IdentityTransform()) |
| 72 | + |
| 73 | + #p.set_clip_on(False) |
| 74 | + |
| 75 | + # make offset box |
| 76 | + offsetbox = AuxTransformBox(IdentityTransform()) |
| 77 | + offsetbox.add_artist(p) |
| 78 | + |
| 79 | + # make anchored offset box |
| 80 | + ao = AnchoredOffsetbox(loc=2, child=offsetbox, frameon=True, borderpad=0.2) |
| 81 | + ax.add_artist(ao) |
| 82 | + |
| 83 | + # another text |
| 84 | + from matplotlib.patches import PathPatch |
| 85 | + if usetex: |
| 86 | + r = r"\mbox{textpath supports mathtext \& \TeX}" |
| 87 | + else: |
| 88 | + r = r"textpath supports mathtext & TeX" |
| 89 | + |
| 90 | + text_path = TextPath((0, 0), r, |
| 91 | + size=20, usetex=usetex) |
| 92 | + |
| 93 | + p1 = PathPatch(text_path, ec="w", lw=3, fc="w", alpha=0.9, |
| 94 | + transform=IdentityTransform()) |
| 95 | + p2 = PathPatch(text_path, ec="none", fc="k", |
| 96 | + transform=IdentityTransform()) |
| 97 | + |
| 98 | + offsetbox2 = AuxTransformBox(IdentityTransform()) |
| 99 | + offsetbox2.add_artist(p1) |
| 100 | + offsetbox2.add_artist(p2) |
| 101 | + |
| 102 | + ab = AnnotationBbox(offsetbox2, (0.95, 0.05), |
| 103 | + xycoords='axes fraction', |
| 104 | + boxcoords="offset points", |
| 105 | + box_alignment=(1., 0.), |
| 106 | + frameon=False |
| 107 | + ) |
| 108 | + ax.add_artist(ab) |
| 109 | + |
| 110 | + ax.imshow([[0, 1, 2], [1, 2, 3]], cmap=plt.cm.gist_gray_r, |
| 111 | + interpolation="bilinear", |
| 112 | + aspect="auto") |
| 113 | + |
| 114 | + # EXAMPLE 2 |
| 115 | + |
| 116 | + ax = plt.subplot(212) |
| 117 | + |
| 118 | + arr = np.arange(256).reshape(1, 256)/256. |
| 119 | + |
| 120 | + if usetex: |
| 121 | + s = r"$\displaystyle\left[\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}\right]$!" |
| 122 | + else: |
| 123 | + s = r"$\left[\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}\right]$!" |
| 124 | + text_path = TextPath((0, 0), s, size=40, usetex=usetex) |
| 125 | + text_patch = PathClippedImagePatch(text_path, arr, ec="none", |
| 126 | + transform=IdentityTransform()) |
| 127 | + |
| 128 | + shadow1 = mpatches.Shadow(text_patch, 1, -1, props=dict(fc="none", ec="0.6", lw=3)) |
| 129 | + shadow2 = mpatches.Shadow(text_patch, 1, -1, props=dict(fc="0.3", ec="none")) |
| 130 | + |
| 131 | + # make offset box |
| 132 | + offsetbox = AuxTransformBox(IdentityTransform()) |
| 133 | + offsetbox.add_artist(shadow1) |
| 134 | + offsetbox.add_artist(shadow2) |
| 135 | + offsetbox.add_artist(text_patch) |
| 136 | + |
| 137 | + # place the anchored offset box using AnnotationBbox |
| 138 | + ab = AnnotationBbox(offsetbox, (0.5, 0.5), |
| 139 | + xycoords='data', |
| 140 | + boxcoords="offset points", |
| 141 | + box_alignment=(0.5, 0.5), |
| 142 | + ) |
| 143 | + #text_path.set_size(10) |
| 144 | + |
| 145 | + ax.add_artist(ab) |
| 146 | + |
| 147 | + ax.set_xlim(0, 1) |
| 148 | + ax.set_ylim(0, 1) |
| 149 | + |
| 150 | + plt.draw() |
| 151 | + plt.show() |
0 commit comments