Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 235bf97

Browse files
authored
Fix nan-handling within PathSimplifier for closepoly
PathSimplifier should ignore vertices corresponding to Path.CLOSEPOLY, and rather replace them with the most recent Path.MOVETO vertex.
1 parent 5eccf94 commit 235bf97

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

lib/matplotlib/tests/test_simplification.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,54 @@ def test_clipping_full():
518518
simplified = list(p.iter_segments(clip=[0, 0, 100, 100]))
519519
assert ([(list(x), y) for x, y in simplified] ==
520520
[([50, 40], 1)])
521+
522+
523+
def test_simplify_closepoly():
524+
# The values of the vertices in a CLOSEPOLY should always be ignored,
525+
# in favor of the most recent MOVETO's vertex values
526+
paths = [Path([(1, 1), (2, 1), (2, 2), (np.nan, np.nan)],
527+
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]),
528+
Path([(1, 1), (2, 1), (2, 2), (40, 50)],
529+
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])]
530+
expected_path = Path([(1, 1), (2, 1), (2, 2), (1, 1), (1, 1), (0, 0)],
531+
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
532+
Path.LINETO, Path.STOP])
533+
534+
for path in paths:
535+
simplified_path = path.cleaned(simplify=True)
536+
assert_array_equal(expected_path.vertices, simplified_path.vertices)
537+
assert_array_equal(expected_path.codes, simplified_path.codes)
538+
539+
# test that a compound path also works
540+
path = Path([(1, 1), (2, 1), (2, 2), (np.nan, np.nan),
541+
(-1, 0), (-2, 0), (-2, 1), (np.nan, np.nan)],
542+
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY,
543+
Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
544+
expected_path = Path([(1, 1), (2, 1), (2, 2), (1, 1),
545+
(-1, 0), (-2, 0), (-2, 1), (-1, 0), (-1, 0), (0, 0)],
546+
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
547+
Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
548+
Path.LINETO, Path.STOP])
549+
550+
simplified_path = path.cleaned(simplify=True)
551+
assert_array_equal(expected_path.vertices, simplified_path.vertices)
552+
assert_array_equal(expected_path.codes, simplified_path.codes)
553+
554+
# test for a path with an invalid MOVETO
555+
# CLOSEPOLY with an invalid MOVETO should be ignored
556+
path = Path([(1, 0), (1, -1), (2, -1),
557+
(np.nan, np.nan), (-1, -1), (-2, 1), (-1, 1),
558+
(2, 2), (0, -1)],
559+
[Path.MOVETO, Path.LINETO, Path.LINETO,
560+
Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
561+
Path.CLOSEPOLY, Path.LINETO])
562+
expected_path = Path([(1, 0), (1, -1), (2, -1),
563+
(np.nan, np.nan), (-1, -1), (-2, 1), (-1, 1),
564+
(0, -1), (0, -1), (0, 0)],
565+
[Path.MOVETO, Path.LINETO, Path.LINETO,
566+
Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
567+
Path.LINETO, Path.LINETO, Path.STOP])
568+
569+
simplified_path = path.cleaned(simplify=True)
570+
assert_array_equal(expected_path.vertices, simplified_path.vertices)
571+
assert_array_equal(expected_path.codes, simplified_path.codes)

src/path_converters.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,13 @@ class PathSimplifier : protected EmbeddedQueue<9>
665665
m_after_moveto(false),
666666
m_clipped(false),
667667

668+
// whether the most recent MOVETO vertex is valid
669+
m_has_init(false),
670+
671+
// the most recent MOVETO vertex
672+
m_initX(0.0),
673+
m_initY(0.0),
674+
668675
// the x, y values from last iteration
669676
m_lastx(0.0),
670677
m_lasty(0.0),
@@ -775,6 +782,15 @@ class PathSimplifier : protected EmbeddedQueue<9>
775782
_push(x, y);
776783
}
777784
m_after_moveto = true;
785+
786+
if (std::isfinite(*x) && std::isfinite(*y)) {
787+
m_has_init = true;
788+
m_initX = *x;
789+
m_initY = *y;
790+
} else {
791+
m_has_init = false;
792+
}
793+
778794
m_lastx = *x;
779795
m_lasty = *y;
780796
m_moveto = false;
@@ -789,6 +805,19 @@ class PathSimplifier : protected EmbeddedQueue<9>
789805
}
790806
m_after_moveto = false;
791807

808+
if(agg::is_close(cmd)) {
809+
if (m_has_init) {
810+
/* If we have a valid initial vertex, then
811+
replace the current vertex with the initial vertex */
812+
*x = m_initX;
813+
*y = m_initY;
814+
} else {
815+
/* If we don't have a valid initial vertex, then
816+
we can't close the path, so we skip the vertex */
817+
continue;
818+
}
819+
}
820+
792821
/* NOTE: We used to skip this very short segments, but if
793822
you have a lot of them cumulatively, you can miss
794823
maxima or minima in the data. */
@@ -940,6 +969,8 @@ class PathSimplifier : protected EmbeddedQueue<9>
940969
bool m_moveto;
941970
bool m_after_moveto;
942971
bool m_clipped;
972+
bool m_has_init;
973+
double m_initX, m_initY;
943974
double m_lastx, m_lasty;
944975

945976
double m_origdx;

0 commit comments

Comments
 (0)