From 7b9547eb4dc3da956701f8915a6f6300bb36fed9 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Sat, 18 Feb 2023 21:22:04 +0100 Subject: [PATCH] Support make_compound_path concatenating only empty paths. Previously `codes[i]` would fail if codes (i.e. the concatenated path) had length zero. --- lib/matplotlib/path.py | 26 +++++++++++--------------- lib/matplotlib/tests/test_path.py | 10 ++++++++-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/matplotlib/path.py b/lib/matplotlib/path.py index 0b10d93b8b8a..d8a411ebf0f1 100644 --- a/lib/matplotlib/path.py +++ b/lib/matplotlib/path.py @@ -318,29 +318,25 @@ def make_compound_path_from_polys(cls, XY): @classmethod def make_compound_path(cls, *args): + r""" + Concatenate a list of `Path`\s into a single `.Path`, removing all `.STOP`\s. """ - Make a compound path from a list of `Path` objects. Blindly removes - all `Path.STOP` control points. - """ - # Handle an empty list in args (i.e. no args). if not args: return Path(np.empty([0, 2], dtype=np.float32)) - vertices = np.concatenate([x.vertices for x in args]) + vertices = np.concatenate([path.vertices for path in args]) codes = np.empty(len(vertices), dtype=cls.code_type) i = 0 for path in args: + size = len(path.vertices) if path.codes is None: - codes[i] = cls.MOVETO - codes[i + 1:i + len(path.vertices)] = cls.LINETO + if size: + codes[i] = cls.MOVETO + codes[i+1:i+size] = cls.LINETO else: - codes[i:i + len(path.codes)] = path.codes - i += len(path.vertices) - # remove STOP's, since internal STOPs are a bug - not_stop_mask = codes != cls.STOP - vertices = vertices[not_stop_mask, :] - codes = codes[not_stop_mask] - - return cls(vertices, codes) + codes[i:i+size] = path.codes + i += size + not_stop_mask = codes != cls.STOP # Remove STOPs, as internal STOPs are a bug. + return cls(vertices[not_stop_mask], codes[not_stop_mask]) def __repr__(self): return f"Path({self.vertices!r}, {self.codes!r})" diff --git a/lib/matplotlib/tests/test_path.py b/lib/matplotlib/tests/test_path.py index 8cc4905287e9..34a450847c01 100644 --- a/lib/matplotlib/tests/test_path.py +++ b/lib/matplotlib/tests/test_path.py @@ -203,8 +203,14 @@ def test_log_transform_with_zero(): def test_make_compound_path_empty(): # We should be able to make a compound path with no arguments. # This makes it easier to write generic path based code. - r = Path.make_compound_path() - assert r.vertices.shape == (0, 2) + empty = Path.make_compound_path() + assert empty.vertices.shape == (0, 2) + r2 = Path.make_compound_path(empty, empty) + assert r2.vertices.shape == (0, 2) + assert r2.codes.shape == (0,) + r3 = Path.make_compound_path(Path([(0, 0)]), empty) + assert r3.vertices.shape == (1, 2) + assert r3.codes.shape == (1,) def test_make_compound_path_stops():