Skip to content

Commit a94b137

Browse files
committed
Use Path(..., closed=True) more.
I'm not sure repeating `LINETO` so many times really help legibility, especially when we already have the closed=True helper implemented (it exactly sets the codes to [MOVETO, LINETO, ..., LINETO, CLOSEPOLY]).
1 parent 70d59ae commit a94b137

File tree

8 files changed

+72
-171
lines changed

8 files changed

+72
-171
lines changed

lib/matplotlib/axes/_axes.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3957,17 +3957,11 @@ def line_props_with_rcdefaults(subkey, explicit, zdelta=0,
39573957
if meanprops is None or removed_prop not in meanprops:
39583958
final_meanprops[removed_prop] = ''
39593959

3960-
def to_vc(xs, ys):
3961-
# convert arguments to verts and codes, append (0, 0) (ignored).
3962-
verts = np.append(np.column_stack([xs, ys]), [(0, 0)], 0)
3963-
codes = ([mpath.Path.MOVETO]
3964-
+ [mpath.Path.LINETO] * (len(verts) - 2)
3965-
+ [mpath.Path.CLOSEPOLY])
3966-
return verts, codes
3967-
39683960
def patch_list(xs, ys, **kwargs):
3969-
verts, codes = to_vc(xs, ys)
3970-
path = mpath.Path(verts, codes)
3961+
path = mpath.Path(
3962+
# Last vertex will have a CLOSEPOLY code and thus be ignored.
3963+
np.append(np.column_stack([xs, ys]), [(0, 0)], 0),
3964+
closed=True)
39713965
patch = mpatches.PathPatch(path, **kwargs)
39723966
self.add_artist(patch)
39733967
return [patch]

lib/matplotlib/collections.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,15 +1098,10 @@ def set_verts(self, verts, closed=True):
10981098
for xy in verts:
10991099
if len(xy):
11001100
if isinstance(xy, np.ma.MaskedArray):
1101-
xy = np.ma.concatenate([xy, xy[0:1]])
1101+
xy = np.ma.concatenate([xy, xy[:1]])
11021102
else:
1103-
xy = np.asarray(xy)
1104-
xy = np.concatenate([xy, xy[0:1]])
1105-
codes = np.empty(xy.shape[0], dtype=mpath.Path.code_type)
1106-
codes[:] = mpath.Path.LINETO
1107-
codes[0] = mpath.Path.MOVETO
1108-
codes[-1] = mpath.Path.CLOSEPOLY
1109-
self._paths.append(mpath.Path(xy, codes))
1103+
xy = np.concatenate([xy, xy[:1]])
1104+
self._paths.append(mpath.Path(xy, closed=True))
11101105
else:
11111106
self._paths.append(mpath.Path(xy))
11121107
else:

lib/matplotlib/markers.py

Lines changed: 23 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -410,23 +410,15 @@ def _set_pixel(self):
410410
def _set_point(self):
411411
self._set_circle(reduction=self._point_size_reduction)
412412

413-
_triangle_path = Path(
414-
[[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0], [0.0, 1.0]],
415-
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
413+
_triangle_path = Path([[0, 1], [-1, -1], [1, -1], [0, 1]], closed=True)
416414
# Going down halfway looks to small. Golden ratio is too far.
417-
_triangle_path_u = Path(
418-
[[0.0, 1.0], [-3 / 5., -1 / 5.], [3 / 5., -1 / 5.], [0.0, 1.0]],
419-
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
415+
_triangle_path_u = Path([[0, 1], [-3/5, -1/5], [3/5, -1/5], [0, 1]],
416+
closed=True)
420417
_triangle_path_d = Path(
421-
[[-3 / 5., -1 / 5.], [3 / 5., -1 / 5.], [1.0, -1.0], [-1.0, -1.0],
422-
[-3 / 5., -1 / 5.]],
423-
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
424-
_triangle_path_l = Path(
425-
[[0.0, 1.0], [0.0, -1.0], [-1.0, -1.0], [0.0, 1.0]],
426-
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
427-
_triangle_path_r = Path(
428-
[[0.0, 1.0], [0.0, -1.0], [1.0, -1.0], [0.0, 1.0]],
429-
[Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY])
418+
[[-3/5, -1/5], [3/5, -1/5], [1, -1], [-1, -1], [-3/5, -1/5]],
419+
closed=True)
420+
_triangle_path_l = Path([[0, 1], [0, -1], [-1, -1], [0, 1]], closed=True)
421+
_triangle_path_r = Path([[0, 1], [0, -1], [1, -1], [0, 1]], closed=True)
430422

431423
def _set_triangle(self, rot, skip):
432424
self._transform = Affine2D().scale(0.5).rotate_deg(rot)
@@ -505,10 +497,8 @@ def _set_diamond(self):
505497
if not self._half_fill():
506498
self._path = Path.unit_rectangle()
507499
else:
508-
self._path = Path([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]])
509-
self._alt_path = Path([[0.0, 0.0], [0.0, 1.0],
510-
[1.0, 1.0], [0.0, 0.0]])
511-
500+
self._path = Path([[0, 0], [1, 0], [1, 1], [0, 0]])
501+
self._alt_path = Path([[0, 0], [0, 1], [1, 1], [0, 0]])
512502
if fs == 'bottom':
513503
rotate = 270.
514504
elif fs == 'top':
@@ -517,10 +507,8 @@ def _set_diamond(self):
517507
rotate = 180.
518508
else:
519509
rotate = 0.
520-
521510
self._transform.rotate_deg(rotate)
522511
self._alt_transform = self._transform
523-
524512
self._joinstyle = 'miter'
525513

526514
def _set_thin_diamond(self):
@@ -815,24 +803,13 @@ def _set_x(self):
815803
self._filled = False
816804
self._path = self._x_path
817805

818-
_plus_filled_path = Path([(1/3, 0), (2/3, 0), (2/3, 1/3),
819-
(1, 1/3), (1, 2/3), (2/3, 2/3),
820-
(2/3, 1), (1/3, 1), (1/3, 2/3),
821-
(0, 2/3), (0, 1/3), (1/3, 1/3),
822-
(1/3, 0)],
823-
[Path.MOVETO, Path.LINETO, Path.LINETO,
824-
Path.LINETO, Path.LINETO, Path.LINETO,
825-
Path.LINETO, Path.LINETO, Path.LINETO,
826-
Path.LINETO, Path.LINETO, Path.LINETO,
827-
Path.CLOSEPOLY])
828-
829-
_plus_filled_path_t = Path([(1, 1/2), (1, 2/3), (2/3, 2/3),
830-
(2/3, 1), (1/3, 1), (1/3, 2/3),
831-
(0, 2/3), (0, 1/2), (1, 1/2)],
832-
[Path.MOVETO, Path.LINETO, Path.LINETO,
833-
Path.LINETO, Path.LINETO, Path.LINETO,
834-
Path.LINETO, Path.LINETO,
835-
Path.CLOSEPOLY])
806+
_plus_filled_path = Path(
807+
[(1/3, 0), (2/3, 0), (2/3, 1/3), (1, 1/3), (1, 2/3), (2/3, 2/3),
808+
(2/3, 1), (1/3, 1), (1/3, 2/3), (0, 2/3), (0, 1/3), (1/3, 1/3),
809+
(1/3, 0)], closed=True)
810+
_plus_filled_path_t = Path(
811+
[(1, 1/2), (1, 2/3), (2/3, 2/3), (2/3, 1), (1/3, 1), (1/3, 2/3),
812+
(0, 2/3), (0, 1/2), (1, 1/2)], closed=True)
836813

837814
def _set_plus_filled(self):
838815
self._transform = Affine2D().translate(-0.5, -0.5)
@@ -858,22 +835,13 @@ def _set_plus_filled(self):
858835
self._transform.rotate_deg(rotate)
859836
self._alt_transform.rotate_deg(rotate_alt)
860837

861-
_x_filled_path = Path([(0.25, 0), (0.5, 0.25), (0.75, 0), (1, 0.25),
862-
(0.75, 0.5), (1, 0.75), (0.75, 1), (0.5, 0.75),
863-
(0.25, 1), (0, 0.75), (0.25, 0.5), (0, 0.25),
864-
(0.25, 0)],
865-
[Path.MOVETO, Path.LINETO, Path.LINETO,
866-
Path.LINETO, Path.LINETO, Path.LINETO,
867-
Path.LINETO, Path.LINETO, Path.LINETO,
868-
Path.LINETO, Path.LINETO, Path.LINETO,
869-
Path.CLOSEPOLY])
870-
871-
_x_filled_path_t = Path([(0.75, 0.5), (1, 0.75), (0.75, 1),
872-
(0.5, 0.75), (0.25, 1), (0, 0.75),
873-
(0.25, 0.5), (0.75, 0.5)],
874-
[Path.MOVETO, Path.LINETO, Path.LINETO,
875-
Path.LINETO, Path.LINETO, Path.LINETO,
876-
Path.LINETO, Path.CLOSEPOLY])
838+
_x_filled_path = Path(
839+
[(0.25, 0), (0.5, 0.25), (0.75, 0), (1, 0.25), (0.75, 0.5), (1, 0.75),
840+
(0.75, 1), (0.5, 0.75), (0.25, 1), (0, 0.75), (0.25, 0.5), (0, 0.25),
841+
(0.25, 0)], closed=True)
842+
_x_filled_path_t = Path(
843+
[(0.75, 0.5), (1, 0.75), (0.75, 1), (0.5, 0.75), (0.25, 1), (0, 0.75),
844+
(0.25, 0.5), (0.75, 0.5)], closed=True)
877845

878846
def _set_x_filled(self):
879847
self._transform = Affine2D().translate(-0.5, -0.5)

lib/matplotlib/patches.py

Lines changed: 25 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,17 +1991,14 @@ def __init__(self, pad=0.3):
19911991

19921992
def transmute(self, x0, y0, width, height, mutation_size):
19931993
pad = mutation_size * self.pad
1994-
19951994
# width and height with padding added.
1996-
width, height = width + 2*pad, height + 2*pad
1997-
1995+
width = width + 2 * pad
1996+
height = height + 2 * pad
19981997
# boundary of the padded box
1999-
x0, y0 = x0 - pad, y0 - pad,
1998+
x0, y0 = x0 - pad, y0 - pad
20001999
x1, y1 = x0 + width, y0 + height
2001-
2002-
vertices = [(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)]
2003-
codes = [Path.MOVETO] + [Path.LINETO] * 3 + [Path.CLOSEPOLY]
2004-
return Path(vertices, codes)
2000+
return Path([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y0)],
2001+
closed=True)
20052002

20062003
@_register_style(_style_list)
20072004
class Circle(_Base):
@@ -2020,9 +2017,8 @@ def __init__(self, pad=0.3):
20202017
def transmute(self, x0, y0, width, height, mutation_size):
20212018
pad = mutation_size * self.pad
20222019
width, height = width + 2 * pad, height + 2 * pad
2023-
20242020
# boundary of the padded box
2025-
x0, y0 = x0 - pad, y0 - pad,
2021+
x0, y0 = x0 - pad, y0 - pad
20262022
return Path.circle((x0 + width / 2, y0 + height / 2),
20272023
max(width, height) / 2)
20282024

@@ -2043,31 +2039,21 @@ def __init__(self, pad=0.3):
20432039
def transmute(self, x0, y0, width, height, mutation_size):
20442040
# padding
20452041
pad = mutation_size * self.pad
2046-
20472042
# width and height with padding added.
20482043
width, height = width + 2. * pad, height + 2. * pad
2049-
20502044
# boundary of the padded box
20512045
x0, y0 = x0 - pad, y0 - pad,
20522046
x1, y1 = x0 + width, y0 + height
20532047

2054-
dx = (y1 - y0) / 2.
2055-
dxx = dx * .5
2056-
# adjust x0. 1.4 <- sqrt(2)
2057-
x0 = x0 + pad / 1.4
2058-
2059-
cp = [(x0 + dxx, y0), (x1, y0), (x1, y1), (x0 + dxx, y1),
2060-
(x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
2061-
(x0 + dxx, y0 - dxx), # arrow
2062-
(x0 + dxx, y0), (x0 + dxx, y0)]
2063-
2064-
com = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO,
2065-
Path.LINETO, Path.LINETO, Path.LINETO,
2066-
Path.LINETO, Path.CLOSEPOLY]
2067-
2068-
path = Path(cp, com)
2048+
dx = (y1 - y0) / 2
2049+
dxx = dx / 2
2050+
x0 = x0 + pad / 1.4 # adjust by ~sqrt(2)
20692051

2070-
return path
2052+
return Path([(x0 + dxx, y0), (x1, y0), (x1, y1), (x0 + dxx, y1),
2053+
(x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
2054+
(x0 + dxx, y0 - dxx), # arrow
2055+
(x0 + dxx, y0), (x0 + dxx, y0)],
2056+
closed=True)
20712057

20722058
@_register_style(_style_list)
20732059
class RArrow(LArrow):
@@ -2106,42 +2092,27 @@ def __init__(self, pad=0.3):
21062092
super().__init__()
21072093

21082094
def transmute(self, x0, y0, width, height, mutation_size):
2109-
21102095
# padding
21112096
pad = mutation_size * self.pad
2112-
21132097
# width and height with padding added.
21142098
# The width is padded by the arrows, so we don't need to pad it.
21152099
height = height + 2. * pad
2116-
21172100
# boundary of the padded box
21182101
x0, y0 = x0 - pad, y0 - pad
21192102
x1, y1 = x0 + width, y0 + height
21202103

21212104
dx = (y1 - y0) / 2
2122-
dxx = dx * .5
2123-
# adjust x0. 1.4 <- sqrt(2)
2124-
x0 = x0 + pad / 1.4
2125-
2126-
cp = [(x0 + dxx, y0), (x1, y0), # bot-segment
2127-
(x1, y0 - dxx), (x1 + dx + dxx, y0 + dx),
2128-
(x1, y1 + dxx), # right-arrow
2129-
(x1, y1), (x0 + dxx, y1), # top-segment
2130-
(x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
2131-
(x0 + dxx, y0 - dxx), # left-arrow
2132-
(x0 + dxx, y0), (x0 + dxx, y0)] # close-poly
2133-
2134-
com = [Path.MOVETO, Path.LINETO,
2135-
Path.LINETO, Path.LINETO,
2136-
Path.LINETO,
2137-
Path.LINETO, Path.LINETO,
2138-
Path.LINETO, Path.LINETO,
2139-
Path.LINETO,
2140-
Path.LINETO, Path.CLOSEPOLY]
2141-
2142-
path = Path(cp, com)
2143-
2144-
return path
2105+
dxx = dx / 2
2106+
x0 = x0 + pad / 1.4 # adjust by ~sqrt(2)
2107+
2108+
return Path([(x0 + dxx, y0), (x1, y0), # bot-segment
2109+
(x1, y0 - dxx), (x1 + dx + dxx, y0 + dx),
2110+
(x1, y1 + dxx), # right-arrow
2111+
(x1, y1), (x0 + dxx, y1), # top-segment
2112+
(x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
2113+
(x0 + dxx, y0 - dxx), # left-arrow
2114+
(x0 + dxx, y0), (x0 + dxx, y0)], # close-poly
2115+
closed=True)
21452116

21462117
@_register_style(_style_list)
21472118
class Round(_Base):

lib/matplotlib/path.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ def __init__(self, vertices, codes=None, _interpolation_steps=1,
120120
intended for public use.
121121
closed : bool, optional
122122
If *codes* is None and closed is True, vertices will be treated as
123-
line segments of a closed polygon.
123+
line segments of a closed polygon. Note that the last vertex will
124+
then be ignored (as the corresponding code will be set to
125+
CLOSEPOLY).
124126
readonly : bool, optional
125127
Makes the path behave in an immutable way and sets the vertices
126128
and codes as read-only arrays.
@@ -635,12 +637,8 @@ def unit_rectangle(cls):
635637
Return a `Path` instance of the unit rectangle from (0, 0) to (1, 1).
636638
"""
637639
if cls._unit_rectangle is None:
638-
cls._unit_rectangle = \
639-
cls([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0],
640-
[0.0, 0.0]],
641-
[cls.MOVETO, cls.LINETO, cls.LINETO, cls.LINETO,
642-
cls.CLOSEPOLY],
643-
readonly=True)
640+
cls._unit_rectangle = cls([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]],
641+
closed=True, readonly=True)
644642
return cls._unit_rectangle
645643

646644
_unit_regular_polygons = WeakValueDictionary()
@@ -661,11 +659,7 @@ def unit_regular_polygon(cls, numVertices):
661659
# "points-up".
662660
+ np.pi / 2)
663661
verts = np.column_stack((np.cos(theta), np.sin(theta)))
664-
codes = np.empty(numVertices + 1)
665-
codes[0] = cls.MOVETO
666-
codes[1:-1] = cls.LINETO
667-
codes[-1] = cls.CLOSEPOLY
668-
path = cls(verts, codes, readonly=True)
662+
path = cls(verts, closed=True, readonly=True)
669663
if numVertices <= 16:
670664
cls._unit_regular_polygons[numVertices] = path
671665
return path
@@ -690,12 +684,8 @@ def unit_regular_star(cls, numVertices, innerCircle=0.5):
690684
theta += np.pi / 2.0
691685
r = np.ones(ns2 + 1)
692686
r[1::2] = innerCircle
693-
verts = (r * np.vstack((np.cos(theta), np.sin(theta)))).T
694-
codes = np.empty(ns2 + 1)
695-
codes[0] = cls.MOVETO
696-
codes[1:-1] = cls.LINETO
697-
codes[-1] = cls.CLOSEPOLY
698-
path = cls(verts, codes, readonly=True)
687+
verts = r * np.column_stack((np.cos(theta), np.sin(theta)))
688+
path = cls(verts, closed=True, readonly=True)
699689
if numVertices <= 16:
700690
cls._unit_regular_stars[(numVertices, innerCircle)] = path
701691
return path

lib/matplotlib/tests/test_patches.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,16 +319,15 @@ def test_patch_str():
319319
assert str(p) == "FancyBboxPatch((1, 2), width=3, height=4)"
320320

321321
# Further nice __str__ which cannot be `eval`uated:
322-
path_data = [([1, 2], mpath.Path.MOVETO), ([2, 2], mpath.Path.LINETO),
323-
([1, 2], mpath.Path.CLOSEPOLY)]
324-
p = mpatches.PathPatch(mpath.Path(*zip(*path_data)))
322+
path = mpath.Path([(1, 2), (2, 2), (1, 2)], closed=True)
323+
p = mpatches.PathPatch(path)
325324
assert str(p) == "PathPatch3((1, 2) ...)"
326325

327326
data = [[1, 2], [2, 2], [1, 2]]
328327
p = mpatches.Polygon(data)
329328
assert str(p) == "Polygon3((1, 2) ...)"
330329

331-
p = mpatches.FancyArrowPatch(path=mpath.Path(*zip(*path_data)))
330+
p = mpatches.FancyArrowPatch(path=path)
332331
assert str(p)[:27] == "FancyArrowPatch(Path(array("
333332

334333
p = mpatches.FancyArrowPatch((1, 2), (3, 4))

lib/matplotlib/tests/test_transforms.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,17 @@ def test_affine_inverted_invalidated():
189189

190190
def test_clipping_of_log():
191191
# issue 804
192-
M, L, C = Path.MOVETO, Path.LINETO, Path.CLOSEPOLY
193-
points = [(0.2, -99), (0.4, -99), (0.4, 20), (0.2, 20), (0.2, -99)]
194-
codes = [M, L, L, L, C]
195-
path = Path(points, codes)
196-
192+
path = Path([(0.2, -99), (0.4, -99), (0.4, 20), (0.2, 20), (0.2, -99)],
193+
closed=True)
197194
# something like this happens in plotting logarithmic histograms
198195
trans = mtransforms.BlendedGenericTransform(
199196
mtransforms.Affine2D(), scale.LogTransform(10, 'clip'))
200197
tpath = trans.transform_path_non_affine(path)
201198
result = tpath.iter_segments(trans.get_affine(),
202199
clip=(0, 0, 100, 100),
203200
simplify=False)
204-
205201
tpoints, tcodes = zip(*result)
206-
assert_allclose(tcodes, [M, L, L, L, C])
202+
assert_allclose(tcodes, path.codes)
207203

208204

209205
class NonAffineForTest(mtransforms.Transform):
@@ -627,8 +623,7 @@ def test_invalid_arguments():
627623

628624
def test_transformed_path():
629625
points = [(0, 0), (1, 0), (1, 1), (0, 1)]
630-
codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]
631-
path = Path(points, codes)
626+
path = Path(points, closed=True)
632627

633628
trans = mtransforms.Affine2D()
634629
trans_path = mtransforms.TransformedPath(path, trans)

0 commit comments

Comments
 (0)