66
77import pytest
88
9- from matplotlib .testing .decorators import image_comparison
9+ from matplotlib .testing .decorators import (
10+ check_figures_equal , image_comparison , remove_ticks_and_titles )
1011import matplotlib .pyplot as plt
1112
1213from matplotlib import patches , transforms
@@ -230,7 +231,7 @@ def test_sine_plus_noise():
230231 assert simplified .vertices .size == 25240
231232
232233
233- @image_comparison (['simplify_curve' ], remove_text = True )
234+ @image_comparison (['simplify_curve' ], remove_text = True , tol = 0.017 )
234235def test_simplify_curve ():
235236 pp1 = patches .PathPatch (
236237 Path ([(0 , 0 ), (1 , 0 ), (1 , 1 ), (np .nan , 1 ), (0 , 0 ), (2 , 0 ), (2 , 2 ),
@@ -245,6 +246,114 @@ def test_simplify_curve():
245246 ax .set_ylim ((0 , 2 ))
246247
247248
249+ @check_figures_equal ()
250+ def test_closed_path_nan_removal (fig_test , fig_ref ):
251+ ax_test = fig_test .subplots (2 , 2 ).flatten ()
252+ ax_ref = fig_ref .subplots (2 , 2 ).flatten ()
253+
254+ # NaN on the first point also removes the last point, because it's closed.
255+ path = Path (
256+ [[- 3 , np .nan ], [3 , - 3 ], [3 , 3 ], [- 3 , 3 ], [- 3 , - 3 ]],
257+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .CLOSEPOLY ])
258+ ax_test [0 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
259+ path = Path (
260+ [[- 3 , np .nan ], [3 , - 3 ], [3 , 3 ], [- 3 , 3 ], [- 3 , np .nan ]],
261+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .LINETO ])
262+ ax_ref [0 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
263+
264+ # NaN on second-last point should not re-close.
265+ path = Path (
266+ [[- 2 , - 2 ], [2 , - 2 ], [2 , 2 ], [- 2 , np .nan ], [- 2 , - 2 ]],
267+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .CLOSEPOLY ])
268+ ax_test [0 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
269+ path = Path (
270+ [[- 2 , - 2 ], [2 , - 2 ], [2 , 2 ], [- 2 , np .nan ], [- 2 , - 2 ]],
271+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .LINETO ])
272+ ax_ref [0 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
273+
274+ # Test multiple loops in a single path (with same paths as above).
275+ path = Path (
276+ [[- 3 , np .nan ], [3 , - 3 ], [3 , 3 ], [- 3 , 3 ], [- 3 , - 3 ],
277+ [- 2 , - 2 ], [2 , - 2 ], [2 , 2 ], [- 2 , np .nan ], [- 2 , - 2 ]],
278+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .CLOSEPOLY ,
279+ Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .CLOSEPOLY ])
280+ ax_test [1 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
281+ path = Path (
282+ [[- 3 , np .nan ], [3 , - 3 ], [3 , 3 ], [- 3 , 3 ], [- 3 , np .nan ],
283+ [- 2 , - 2 ], [2 , - 2 ], [2 , 2 ], [- 2 , np .nan ], [- 2 , - 2 ]],
284+ [Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .LINETO ,
285+ Path .MOVETO , Path .LINETO , Path .LINETO , Path .LINETO , Path .LINETO ])
286+ ax_ref [1 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
287+
288+ # NaN in first point of CURVE3 should not re-close, and hide entire curve.
289+ path = Path (
290+ [[- 1 , - 1 ], [1 , - 1 ], [1 , np .nan ], [0 , 1 ], [- 1 , 1 ], [- 1 , - 1 ]],
291+ [Path .MOVETO , Path .LINETO , Path .CURVE3 , Path .CURVE3 , Path .LINETO ,
292+ Path .CLOSEPOLY ])
293+ ax_test [2 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
294+ path = Path (
295+ [[- 1 , - 1 ], [1 , - 1 ], [1 , np .nan ], [0 , 1 ], [- 1 , 1 ], [- 1 , - 1 ]],
296+ [Path .MOVETO , Path .LINETO , Path .CURVE3 , Path .CURVE3 , Path .LINETO ,
297+ Path .CLOSEPOLY ])
298+ ax_ref [2 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
299+
300+ # NaN in second point of CURVE3 should not re-close, and hide entire curve
301+ # plus next line segment.
302+ path = Path (
303+ [[- 3 , - 3 ], [3 , - 3 ], [3 , 0 ], [0 , np .nan ], [- 3 , 3 ], [- 3 , - 3 ]],
304+ [Path .MOVETO , Path .LINETO , Path .CURVE3 , Path .CURVE3 , Path .LINETO ,
305+ Path .LINETO ])
306+ ax_test [2 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
307+ path = Path (
308+ [[- 3 , - 3 ], [3 , - 3 ], [3 , 0 ], [0 , np .nan ], [- 3 , 3 ], [- 3 , - 3 ]],
309+ [Path .MOVETO , Path .LINETO , Path .CURVE3 , Path .CURVE3 , Path .LINETO ,
310+ Path .LINETO ])
311+ ax_ref [2 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
312+
313+ # NaN in first point of CURVE4 should not re-close, and hide entire curve.
314+ path = Path (
315+ [[- 1 , - 1 ], [1 , - 1 ], [1 , np .nan ], [0 , 0 ], [0 , 1 ], [- 1 , 1 ], [- 1 , - 1 ]],
316+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
317+ Path .LINETO , Path .CLOSEPOLY ])
318+ ax_test [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
319+ path = Path (
320+ [[- 1 , - 1 ], [1 , - 1 ], [1 , np .nan ], [0 , 0 ], [0 , 1 ], [- 1 , 1 ], [- 1 , - 1 ]],
321+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
322+ Path .LINETO , Path .CLOSEPOLY ])
323+ ax_ref [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
324+
325+ # NaN in second point of CURVE4 should not re-close, and hide entire curve.
326+ path = Path (
327+ [[- 2 , - 2 ], [2 , - 2 ], [2 , 0 ], [0 , np .nan ], [0 , 2 ], [- 2 , 2 ], [- 2 , - 2 ]],
328+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
329+ Path .LINETO , Path .LINETO ])
330+ ax_test [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
331+ path = Path (
332+ [[- 2 , - 2 ], [2 , - 2 ], [2 , 0 ], [0 , np .nan ], [0 , 2 ], [- 2 , 2 ], [- 2 , - 2 ]],
333+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
334+ Path .LINETO , Path .LINETO ])
335+ ax_ref [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
336+
337+ # NaN in third point of CURVE4 should not re-close, and hide entire curve
338+ # plus next line segment.
339+ path = Path (
340+ [[- 3 , - 3 ], [3 , - 3 ], [3 , 0 ], [0 , 0 ], [0 , np .nan ], [- 3 , 3 ], [- 3 , - 3 ]],
341+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
342+ Path .LINETO , Path .LINETO ])
343+ ax_test [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
344+ path = Path (
345+ [[- 3 , - 3 ], [3 , - 3 ], [3 , 0 ], [0 , 0 ], [0 , np .nan ], [- 3 , 3 ], [- 3 , - 3 ]],
346+ [Path .MOVETO , Path .LINETO , Path .CURVE4 , Path .CURVE4 , Path .CURVE4 ,
347+ Path .LINETO , Path .LINETO ])
348+ ax_ref [3 ].add_patch (patches .PathPatch (path , facecolor = 'none' ))
349+
350+ # Keep everything clean.
351+ for ax in [* ax_test .flat , * ax_ref .flat ]:
352+ ax .set (xlim = (- 3.5 , 3.5 ), ylim = (- 3.5 , 3.5 ))
353+ remove_ticks_and_titles (fig_test )
354+ remove_ticks_and_titles (fig_ref )
355+
356+
248357@image_comparison (['hatch_simplify' ], remove_text = True )
249358def test_hatch ():
250359 fig , ax = plt .subplots ()
0 commit comments