8000 Merge pull request #19214 from dstansby/bezier-autoscale · matplotlib/matplotlib@bbc50e4 · GitHub
[go: up one dir, main page]

Skip to content

Commit bbc50e4

Browse files
authored
Merge pull request #19214 from dstansby/bezier-autoscale
Improve autoscaling for high order Bezier curves
2 parents dc11ded + 7036d2d commit bbc50e4

File tree

11 files changed

+45
-11
lines changed

11 files changed

+45
-11
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Improved autoscaling for bezier curves
2+
--------------------------------------
3+
Bezier curves are now autoscaled to their extents - previously they were
4+
autoscaled to their ends and control points, which in some cases led to
5+
unnecessarily large limits.

lib/matplotlib/axes/_base.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import matplotlib.image as mimage
2323
import matplotlib.lines as mlines
2424
import matplotlib.patches as mpatches
25-
import matplotlib.path as mpath
2625
from matplotlib.rcsetup import cycler, validate_axisbelow
2726
import matplotlib.spines as mspines
2827
import matplotlib.table as mtable
@@ -2382,10 +2381,18 @@ def _update_patch_limits(self, patch):
23822381
((not patch.get_width()) and (not patch.get_height()))):
23832382
return
23842383
p = patch.get_path()
2385-
vertices = p.vertices if p.codes is None else p.vertices[np.isin(
2386-
p.codes, (mpath.Path.CLOSEPOLY, mpath.Path.STOP), invert=True)]
2387-
if not vertices.size:
2388-
return
2384+
# Get all vertices on the path
2385+
# Loop through each sement to get extrema for Bezier curve sections
2386+
vertices = []
2387+
for curve, code in p.iter_bezier():
2388+
# Get distance along the curve of any extrema
2389+
_, dzeros = curve.axis_aligned_extrema()
2390+
# Calculate vertcies of start, end and any extrema in between
2391+
vertices.append(curve([0, *dzeros, 1]))
2392+
2393+
if len(vertices):
2394+
vertices = np.row_stack(vertices)
2395+
23892396
patch_trf = patch.get_transform()
23902397
updatex, updatey = patch_trf.contains_branch_seperately(self.transData)
23912398
if not (updatex or updatey):
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

lib/matplotlib/tests/test_axes.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import matplotlib.font_manager as mfont_manager
2525
import matplotlib.markers as mmarkers
2626
import matplotlib.patches as mpatches
27+
import matplotlib.path as mpath
2728
import matplotlib.pyplot as plt
2829
import matplotlib.ticker as mticker
2930
import matplotlib.transforms as mtransforms
@@ -5119,7 +5120,7 @@ def test_pie_default():
51195120

51205121

51215122
@image_comparison(['pie_linewidth_0', 'pie_linewidth_0', 'pie_linewidth_0'],
5122-
extensions=['png'])
5123+
extensions=['png'], style='mpl20')
51235124
def test_pie_linewidth_0():
51245125
# The slices will be ordered and plotted counter-clockwise.
51255126
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
@@ -5151,7 +5152,7 @@ def test_pie_linewidth_0():
51515152
plt.axis('equal')
51525153

51535154

5154-
@image_comparison(['pie_center_radius.png'])
5155+
@image_comparison(['pie_center_radius.png'], style='mpl20')
51555156
def test_pie_center_radius():
51565157
# The slices will be ordered and plotted counter-clockwise.
51575158
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
@@ -5171,7 +5172,7 @@ def test_pie_center_radius():
51715172
plt.axis('equal')
51725173

51735174

5174-
@image_comparison(['pie_linewidth_2.png'])
5175+
@image_comparison(['pie_linewidth_2.png'], style='mpl20')
51755176
def test_pie_linewidth_2():
51765177
# The slices will be ordered and plotted counter-clockwise.
51775178
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
@@ -5186,7 +5187,7 @@ def test_pie_linewidth_2():
51865187
plt.axis('equal')
51875188

51885189

5189-
@image_comparison(['pie_ccw_true.png'])
5190+
@image_comparison(['pie_ccw_true.png'], style='mpl20')
51905191
def test_pie_ccw_true():
51915192
# The slices will be ordered and plotted counter-clockwise.
51925193
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
@@ -5201,7 +5202,7 @@ def test_pie_ccw_true():
52015202
plt.axis('equal')
52025203

52035204

5204-
@image_comparison(['pie_frame_grid.png'])
5205+
@image_comparison(['pie_frame_grid.png'], style='mpl20')
52055206
def test_pie_frame_grid():
52065207
# The slices will be ordered and plotted counter-clockwise.
52075208
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
@@ -5228,7 +5229,7 @@ def test_pie_frame_grid():
52285229
plt.axis('equal')
52295230

52305231

5231-
@image_comparison(['pie_rotatelabels_true.png'])
5232+
@image_comparison(['pie_rotatelabels_true.png'], style='mpl20')
52325233
def test_pie_rotatelabels_true():
52335234
# The slices will be ordered and plotted counter-clockwise.
52345235
labels = 'Hogwarts', 'Frogs', 'Dogs', 'Logs'
@@ -7539,3 +7540,24 @@ def test_clim():
75397540
clim = (7, 8)
75407541
norm = plot_method(clim=clim).norm
75417542
assert (norm.vmin, norm.vmax) == clim
7543+
7544+
7545+
def test_bezier_autoscale():
7546+
# Check that bezier curves autoscale to their curves, and not their
7547+
# control points
7548+
verts = [[-1, 0],
7549+
[0, -1],
7550+
[1, 0],
7551+
[1, 0]]
7552+
codes = [mpath.Path.MOVETO,
7553+
mpath.Path.CURVE3,
7554+
mpath.Path.CURVE3,
7555+
mpath.Path.CLOSEPOLY]
7556+
p = mpath.Path(verts, codes)
7557+
7558+
fig, ax = plt.subplots()
7559+
ax.add_patch(mpatches.PathPatch(p))
7560+
ax.autoscale()
7561+
# Bottom ylim should be at the edge of the curve (-0.5), and not include
7562+
# the control point (at -1)
7563+
assert ax.get_ylim()[0] == -0.5

0 commit comments

Comments
 (0)
0