8000 Merge pull request #26788 from anntzer/avhlsi · matplotlib/matplotlib@870f479 · GitHub
[go: up one dir, main page]

Skip to content

Commit 870f479

Browse files
authored
Merge pull request #26788 from anntzer/avhlsi
Fix axh{line,span} on polar axes.
2 parents ae65c50 + b6694f4 commit 870f479

File tree

8 files changed

+63
-16
lines changed

8 files changed

+63
-16
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
``axvspan`` and ``axhspan`` now return ``Rectangle``\s, not ``Polygons``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
This change allows using `~.Axes.axhspan` to draw an annulus on polar axes.
4+
5+
This change also affects other elements built via `~.Axes.axvspan` and
6+
`~.Axes.axhspan`, such as ``Slider.poly``.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
``axhline`` and ``axhspan`` on polar axes
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
... now draw circles and circular arcs (`~.Axes.axhline`) or annuli and wedges
5+
(`~.Axes.axhspan`).

lib/matplotlib/axes/_axes.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
783783
trans = self.get_yaxis_transform(which='grid')
784784
l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
785785
self.add_line(l)
786+
l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
786787
if scaley:
787788
self._request_autoscale_view("y")
788789
return l
@@ -851,6 +852,7 @@ def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
851852
trans = self.get_xaxis_transform(which='grid')
852853
l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
853854
self.add_line(l)
855+
l.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
854856
if scalex:
855857
self._request_autoscale_view("x")
856858
return l
@@ -978,10 +980,17 @@ def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
978980
self._check_no_units([xmin, xmax], ['xmin', 'xmax'])
979981
(ymin, ymax), = self._process_unit_info([("y", [ymin, ymax])], kwargs)
980982

981-
verts = (xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)
982-
p = mpatches.Polygon(verts, **kwargs)
983+
p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs)
983984
p.set_transform(self.get_yaxis_transform(which="grid"))
985+
# For Rectangles and non-separable transforms, add_patch can be buggy
986+
# and update the x limits even though it shouldn't do so for an
987+
# yaxis_transformed patch, so undo that update.
988+
ix = self.dataLim.intervalx
989+
mx = self.dataLim.minposx
984990
self.add_patch(p)
991+
self.dataLim.intervalx = ix
992+
self.dataLim.minposx = mx
993+
p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
985994
self._request_autoscale_view("y")
986995
return p
987996

@@ -1034,11 +1043,17 @@ def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
10341043
self._check_no_units([ymin, ymax], ['ymin', 'ymax'])
10351044
(xmin, xmax), = self._process_unit_info([("x", [xmin, xmax])], kwargs)
10361045

1037-
verts = [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)]
1038-
p = mpatches.Polygon(verts, **kwargs)
1046+
p = mpatches.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin, **kwargs)
10391047
p.set_transform(self.get_xaxis_transform(which="grid"))
1040-
p.get_path()._interpolation_steps = 100
1048+
# For Rectangles and non-separable transforms, add_patch can be buggy
1049+
# and update the y limits even though it shouldn't do so for an
1050+
# xaxis_transformed patch, so undo that update.
1051+
iy = self.dataLim.intervaly.copy()
1052+
my = self.dataLim.minposy
10411053
self.add_patch(p)
1054+
self.dataLim.intervaly = iy
1055+
self.dataLim.minposy = my
1056+
p.get_path()._interpolation_steps = mpl.axis.GRIDLINE_INTERPOLATION_STEPS
10421057
self._request_autoscale_view("x")
10431058
return p
10441059

Loading

lib/matplotlib/tests/test_axes.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8849,3 +8849,15 @@ def test_xylim_changed_shared():
88498849
axs[1].callbacks.connect("ylim_changed", events.append)
88508850
axs[0].set(xlim=[1, 3], ylim=[2, 4])
88518851
assert events == [axs[1], axs[1]]
8852+
8853+
8854+
@image_comparison(["axhvlinespan_interpolation.png"], style="default")
8855+
def test_axhvlinespan_interpolation():
8856+
ax = plt.figure().add_subplot(projection="polar")
8857+
ax.set_axis_off()
8858+
ax.axvline(.1, c="C0")
8859+
ax.axvspan(.2, .3, fc="C1")
8860+
ax.axvspan(.4, .5, .1, .2, fc="C2")
8861+
ax.axhline(1, c="C0", alpha=.5)
8862+
ax.axhspan(.8, .9, fc="C1", alpha=.5)
8863+
ax.axhspan(.6, .7, .8, .9, fc="C2", alpha=.5)

lib/matplotlib/tests/test_path.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ def test_nonlinear_containment():
142142
ax.set(xscale="log", ylim=(0, 1))
143143
polygon = ax.axvspan(1 F438 , 10)
144144
assert polygon.get_path().contains_point(
145-
ax.transData.transform((5, .5)), ax.transData)
145+
ax.transData.transform((5, .5)), polygon.get_transform())
146146
assert not polygon.get_path().contains_point(
147-
ax.transData.transform((.5, .5)), ax.transData)
147+
ax.transData.transform((.5, .5)), polygon.get_transform())
148148
assert not polygon.get_path().contains_point(
149-
ax.transData.transform((50, .5)), ax.transData)
149+
ax.transData.transform((50, .5)), polygon.get_transform())
150150

151151

152152
@image_comparison(['arrow_contains_point.png'],

lib/matplotlib/transforms.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ def intersection(bbox1, bbox2):
671671
y1 = np.minimum(bbox1.ymax, bbox2.ymax)
672672
return Bbox([[x0, y0], [x1, y1]]) if x0 <= x1 and y0 <= y1 else None
673673

674+
674675
_default_minpos = np.array([np.inf, np.inf])
675676

676677

@@ -1011,6 +1012,10 @@ def minpos(self):
10111012
"""
10121013
return self._minpos
10131014

1015+
@minpos.setter
1016+
def minpos(self, val):
1017+
self._minpos[:] = val
1018+
10141019
@property
10151020
def minposx(self):
10161021
"""
@@ -1022,6 +1027,10 @@ def minposx(self):
10221027
"""
10231028
return self._minpos[0]
10241029

1030+
@minposx.setter
1031+
def minposx(self, val):
1032+
self._minpos[0] = val
1033+
10251034
@property
10261035
def minposy(self):
10271036
"""
@@ -1033,6 +1042,10 @@ def minposy(self):
10331042
"""
10341043
return self._minpos[1]
10351044

1045+
@minposy.setter
1046+
def minposy(self, val):
1047+
self._minpos[1] = val
1048+
10361049
def get_points(self):
10371050
"""
10381051
Get the points of the bounding box as an array of the form

lib/matplotlib/widgets.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ def __init__(self, ax, label, valmin, valmax, *, valinit=0.5, valfmt=None,
432432
Notes
433433
-----
434434
Additional kwargs are passed on to ``self.poly`` which is the
435-
`~matplotlib.patches.Polygon` that draws the slider knob. See the
436-
`.Polygon` documentation for valid property names (``facecolor``,
435+
`~matplotlib.patches.Rectangle` that draws the slider knob. See the
436+
`.Rectangle` documentation for valid property names (``facecolor``,
437437
``edgecolor``, ``alpha``, etc.).
438438
"""
439439
super().__init__(ax, orientation, closedmin, closedmax,
@@ -576,16 +576,12 @@ def set_val(self, val):
576576
----------
577577
val : float
578578
"""
579-
xy = self.poly.xy
580579
if self.orientation == 'vertical':
581-
xy[1] = .25, val
582-
xy[2] = .75, val
580+
self.poly.set_height(val - self.poly.get_y())
583581
self._handle.set_ydata([val])
584582
else:
585-
xy[2] = val, .75
586-
xy[3] = val, .25
583+
self.poly.set_width(val - self.poly.get_x())
587584
self._handle.set_xdata([val])
588-
self.poly.xy = xy
589585
self.valtext.set_text(self._format(val))
590586
if self.drawon:
591587
self.ax.figure.canvas.draw_idle()

0 commit comments

Comments
 (0)
0