From 1d7f0945689342d16c4a370b3e355a46090fd6b7 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 13 Sep 2023 18:17:44 -0400 Subject: [PATCH] Trim Gouraud triangles that contain NaN Agg enters an infinite loop if you give it points that are NaN, due to converting the values to fixed-point integers, and then oscillating between the large values that result from that conversion. NaN values may be introduced after transforming the input, so we need to trim those after transformation. This matches what is done in normal paths. --- lib/matplotlib/tests/test_transforms.py | 19 +++++++++++++++++++ src/_backend_agg.h | 3 +++ 2 files changed, 22 insertions(+) diff --git a/lib/matplotlib/tests/test_transforms.py b/lib/matplotlib/tests/test_transforms.py index ee6754cb8da8..a9a92d33cff3 100644 --- a/lib/matplotlib/tests/test_transforms.py +++ b/lib/matplotlib/tests/test_transforms.py @@ -142,6 +142,25 @@ def test_pcolormesh_pre_transform_limits(): assert_almost_equal(expected, ax.dataLim.get_points()) +def test_pcolormesh_gouraud_nans(): + np.random.seed(19680801) + + values = np.linspace(0, 180, 3) + radii = np.linspace(100, 1000, 10) + z, y = np.meshgrid(values, radii) + x = np.radians(np.random.rand(*z.shape) * 100) + + fig = plt.figure() + ax = fig.add_subplot(111, projection="polar") + # Setting the limit to cause clipping of the r values causes NaN to be + # introduced; these should not crash but be ignored as in other path + # operations. + ax.set_rlim(101, 1000) + ax.pcolormesh(x, y, z, shading="gouraud") + + fig.canvas.draw() + + def test_Affine2D_from_values(): points = np.array([[0, 0], [10, 20], diff --git a/src/_backend_agg.h b/src/_backend_agg.h index f15fa05dd5fd..61c24232a866 100644 --- a/src/_backend_agg.h +++ b/src/_backend_agg.h @@ -1193,6 +1193,9 @@ inline void RendererAgg::_draw_gouraud_triangle(PointArray &points, tpoints[i][j] = points(i, j); } trans.transform(&tpoints[i][0], &tpoints[i][1]); + if(std::isnan(tpoints[i][0]) || std::isnan(tpoints[i][1])) { + return; + } } span_alloc_t span_alloc;