diff --git a/doc/api/next_api_changes/behavior/19214-DS.rst b/doc/api/next_api_changes/behavior/19214-DS.rst new file mode 100644 index 000000000000..cffd0b8ffd6f --- /dev/null +++ b/doc/api/next_api_changes/behavior/19214-DS.rst @@ -0,0 +1,5 @@ +Improved autoscaling for bezier curves +-------------------------------------- +Bezier curves are now autoscaled to their extents - previously they were +autoscaled to their ends and control points, which in some cases led to +unnecessarily large limits. diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 37a3d39ed77f..007c45045835 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -22,7 +22,6 @@ import matplotlib.image as mimage import matplotlib.lines as mlines import matplotlib.patches as mpatches -import matplotlib.path as mpath from matplotlib.rcsetup import cycler, validate_axisbelow import matplotlib.spines as mspines import matplotlib.table as mtable @@ -2375,10 +2374,18 @@ def _update_patch_limits(self, patch): ((not patch.get_width()) and (not patch.get_height()))): return p = patch.get_path() - vertices = p.vertices if p.codes is None else p.vertices[np.isin( - p.codes, (mpath.Path.CLOSEPOLY, mpath.Path.STOP), invert=True)] - if not vertices.size: - return + # Get all vertices on the path + # Loop through each sement to get extrema for Bezier curve sections + vertices = [] + for curve, code in p.iter_bezier(): + # Get distance along the curve of any extrema + _, dzeros = curve.axis_aligned_extrema() + # Calculate vertcies of start, end and any extrema in between + vertices.append(curve([0, *dzeros, 1])) + + if len(vertices): + vertices = np.row_stack(vertices) + patch_trf = patch.get_transform() updatex, updatey = patch_trf.contains_branch_seperately(self.transData) if not (updatex or updatey): diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png index 8af5f62b5526..c5236a34b9e1 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_ccw_true.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_center_radius.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_center_radius.png index f7b7108ce79b..64b2244711f9 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_center_radius.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_center_radius.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_default.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_default.png index 1c0c6c2c0577..f3935a9e159a 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_default.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_default.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_frame_grid.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_frame_grid.png index 4eea9fb7c157..4e4edbeed0ed 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_frame_grid.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_frame_grid.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_0.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_0.png index 18acc069100e..e814e061205a 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_0.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_0.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_2.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_2.png index 68fc84a4d596..e12d743fbc45 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_2.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_linewidth_2.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_no_label.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_no_label.png index d2d651e421dc..c6fd5262acce 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_no_label.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_no_label.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_axes/pie_rotatelabels_true.png b/lib/matplotlib/tests/baseline_images/test_axes/pie_rotatelabels_true.png index 91664207dee7..d5875752c3cd 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/pie_rotatelabels_true.png and b/lib/matplotlib/tests/baseline_images/test_axes/pie_rotatelabels_true.png differ diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 5da2df1455db..d971debc1486 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -24,6 +24,7 @@ import matplotlib.font_manager as mfont_manager import matplotlib.markers as mmarkers import matplotlib.patches as mpatches +import matplotlib.path as mpath import matplotlib.pyplot as plt import matplotlib.ticker as mticker import matplotlib.transforms as mtransforms @@ -5042,7 +5043,7 @@ def test_pie_default(): @image_comparison(['pie_linewidth_0', 'pie_linewidth_0', 'pie_linewidth_0'], - extensions=['png']) + extensions=['png'], style='mpl20') def test_pie_linewidth_0(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -5074,7 +5075,7 @@ def test_pie_linewidth_0(): plt.axis('equal') -@image_comparison(['pie_center_radius.png']) +@image_comparison(['pie_center_radius.png'], style='mpl20') def test_pie_center_radius(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -5094,7 +5095,7 @@ def test_pie_center_radius(): plt.axis('equal') -@image_comparison(['pie_linewidth_2.png']) +@image_comparison(['pie_linewidth_2.png'], style='mpl20') def test_pie_linewidth_2(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -5109,7 +5110,7 @@ def test_pie_linewidth_2(): plt.axis('equal') -@image_comparison(['pie_ccw_true.png']) +@image_comparison(['pie_ccw_true.png'], style='mpl20') def test_pie_ccw_true(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -5124,7 +5125,7 @@ def test_pie_ccw_true(): plt.axis('equal') -@image_comparison(['pie_frame_grid.png']) +@image_comparison(['pie_frame_grid.png'], style='mpl20') def test_pie_frame_grid(): # The slices will be ordered and plotted counter-clockwise. labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' @@ -5151,7 +5152,7 @@ def test_pie_frame_grid(): plt.axis('equal') -@image_comparison(['pie_rotatelabels_true.png']) +@image_comparison(['pie_rotatelabels_true.png'], style='mpl20') def test_pie_rotatelabels_true(): # The slices will be ordered and plotted counter-clockwise. labels = 'Hogwarts', 'Frogs', 'Dogs', 'Logs' @@ -7340,3 +7341,24 @@ def test_clim(): clim = (7, 8) norm = plot_method(clim=clim).norm assert (norm.vmin, norm.vmax) == clim + + +def test_bezier_autoscale(): + # Check that bezier curves autoscale to their curves, and not their + # control points + verts = [[-1, 0], + [0, -1], + [1, 0], + [1, 0]] + codes = [mpath.Path.MOVETO, + mpath.Path.CURVE3, + mpath.Path.CURVE3, + mpath.Path.CLOSEPOLY] + p = mpath.Path(verts, codes) + + fig, ax = plt.subplots() + ax.add_patch(mpatches.PathPatch(p)) + ax.autoscale() + # Bottom ylim should be at the edge of the curve (-0.5), and not include + # the control point (at -1) + assert ax.get_ylim()[0] == -0.5 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy