|
12 | 12 | from matplotlib._path import point_in_path, get_path_extents, \ |
13 | 13 | point_in_path_collection, get_path_collection_extents, \ |
14 | 14 | path_in_path, path_intersects_path, convert_path_to_polygons, \ |
15 | | - cleanup_path, points_in_path |
| 15 | + cleanup_path, points_in_path, clip_path_to_rect |
16 | 16 | from matplotlib.cbook import simple_linear_interpolation, maxdict |
17 | 17 | from matplotlib import rcParams |
18 | 18 |
|
@@ -171,22 +171,23 @@ def make_compound_path_from_polys(cls, XY): |
171 | 171 | def make_compound_path(cls, *args): |
172 | 172 | """ |
173 | 173 | (staticmethod) Make a compound path from a list of Path |
174 | | - objects. Only polygons (not curves) are supported. |
| 174 | + objects. |
175 | 175 | """ |
176 | | - for p in args: |
177 | | - assert p.codes is None |
178 | | - |
179 | 176 | lengths = [len(x) for x in args] |
180 | 177 | total_length = sum(lengths) |
181 | 178 |
|
182 | 179 | vertices = np.vstack([x.vertices for x in args]) |
183 | 180 | vertices.reshape((total_length, 2)) |
184 | 181 |
|
185 | | - codes = cls.LINETO * np.ones(total_length) |
| 182 | + codes = np.empty(total_length, dtype=cls.code_type) |
186 | 183 | i = 0 |
187 | | - for length in lengths: |
188 | | - codes[i] = cls.MOVETO |
189 | | - i += length |
| 184 | + for path in args: |
| 185 | + if path.codes is None: |
| 186 | + codes[i] = cls.MOVETO |
| 187 | + codes[i + 1:i + len(path.vertices)] = cls.LINETO |
| 188 | + else: |
| 189 | + codes[i:i + len(path.codes)] = path.codes |
| 190 | + i += len(path.vertices) |
190 | 191 |
|
191 | 192 | return cls(vertices, codes) |
192 | 193 |
|
@@ -709,6 +710,22 @@ def hatch(cls, hatchpattern, density=6): |
709 | 710 | cls._hatch_dict[(hatchpattern, density)] = hatch_path |
710 | 711 | return hatch_path |
711 | 712 |
|
| 713 | + def clip_to_bbox(self, bbox, inside=True): |
| 714 | + """ |
| 715 | + Clip the path to the given bounding box. |
| 716 | +
|
| 717 | + The path must be made up of one or more closed polygons. This |
| 718 | + algorithm will not behave correctly for unclosed paths. |
| 719 | +
|
| 720 | + If *inside* is `True`, clip to the inside of the box, otherwise |
| 721 | + to the outside of the box. |
| 722 | + """ |
| 723 | + # Use make_compound_path_from_polys |
| 724 | + verts = clip_path_to_rect(self, bbox, inside) |
| 725 | + paths = [Path(poly) for poly in verts] |
| 726 | + return self.make_compound_path(*paths) |
| 727 | + |
| 728 | + |
712 | 729 | _get_path_collection_extents = get_path_collection_extents |
713 | 730 | def get_path_collection_extents( |
714 | 731 | master_transform, paths, transforms, offsets, offset_transform): |
|
0 commit comments