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

Skip to content

Commit 651c293

Browse files
authored
Merge pull request #18544 from brunobeltran/join_cap_styles
REORG: JoinStyle and CapStyle classes
2 parents 1233840 + 4894099 commit 651c293

File tree

13 files changed

+391
-225
lines changed

13 files changed

+391
-225
lines changed

doc/_static/mpl.css

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ table.highlighttable td {
8989
padding: 0 0.5em 0 0.5em;
9090
}
9191

92-
cite, code, tt {
92+
cite, code, tt, dl.value-list dt {
9393
font-family: 'Consolas', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
9494
font-size: 0.95em;
9595
letter-spacing: 0.01em;
@@ -730,7 +730,6 @@ td.field-body table.property-table tr:last-of-type td {
730730
border-bottom-color: #888;
731731
}
732732

733-
734733
/* function and class description */
735734
.descclassname {
736735
color: #aaa;
@@ -806,6 +805,22 @@ dl.class > dd {
806805
font-size: 14px;
807806
}
808807

808+
/* custom tables for lists of allowed values in "mpl._types" */
809+
dl.value-list {
810+
display: grid;
811+
}
812+
813+
dl.value-list dt {
814+
grid-column: 1;
815+
margin: 4px 0;
816+
}
817+
818+
dl.value-list dd {
819+
grid-column: 2;
820+
margin: 4px 0 4px 20px;
821+
padding: 0;
822+
}
823+
809824
/* parameter section table */
810825
table.docutils.field-list {
811826
width: 100%;
@@ -1257,4 +1272,4 @@ div.bullet-box li {
12571272

12581273
div#gallery.section .sphx-glr-clear:first-of-type, div#tutorials.section .sphx-glr-clear:first-of-type{
12591274
display: none;
1260-
}
1275+
}

doc/api/_enums.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
**********************
2+
``matplotlib._enums``
3+
**********************
4+
5+
.. automodule:: matplotlib._enums
6+
:no-members:
7+
8+
.. autoclass:: JoinStyle
9+
:members: demo
10+
:exclude-members: bevel, miter, round, input_description
11+
12+
.. autoclass:: CapStyle
13+
:members: demo
14+
:exclude-members: butt, round, projecting, input_description
15+

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Matplotlib consists of the following submodules:
8989
dates_api.rst
9090
docstring_api.rst
9191
dviread.rst
92+
_enums.rst
9293
figure_api.rst
9394
font_manager_api.rst
9495
fontconfig_pattern_api.rst
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
=========
3+
CapStyle
4+
=========
5+
6+
The `matplotlib._enums.CapStyle` controls how Matplotlib draws the corners
7+
where two different line segments meet. For more details, see the
8+
`~matplotlib._enums.CapStyle` docs.
9+
"""
10+
11+
import matplotlib.pyplot as plt
12+
from matplotlib._enums import CapStyle
13+
14+
CapStyle.demo()
15+
plt.show()
Lines changed: 8 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,15 @@
11
"""
2-
==========================
3-
Join styles and cap styles
4-
==========================
2+
=========
3+
JoinStyle
4+
=========
55
6-
This example demonstrates the available join styles and cap styles.
7-
8-
Both are used in `.Line2D` and various ``Collections`` from
9-
`matplotlib.collections` as well as some functions that create these, e.g.
10-
`~matplotlib.pyplot.plot`.
11-
12-
13-
Join styles
14-
===========
15-
16-
Join styles define how the connection between two line segments is drawn.
17-
18-
See the respective ``solid_joinstyle``, ``dash_joinstyle`` or ``joinstyle``
19-
parameters.
6+
The `matplotlib._enums.JoinStyle` controls how Matplotlib draws the corners
7+
where two different line segments meet. For more details, see the
8+
`~matplotlib._enums.JoinStyle` docs.
209
"""
2110

22-
import numpy as np
2311
import matplotlib.pyplot as plt
12+
from matplotlib._enums import JoinStyle
2413

25-
26-
def plot_angle(ax, x, y, angle, style):
27-
phi = np.radians(angle)
28-
xx = [x + .5, x, x + .5*np.cos(phi)]
29-
yy = [y, y, y + .5*np.sin(phi)]
30-
ax.plot(xx, yy, lw=12, color='tab:blue', solid_joinstyle=style)
31-
ax.plot(xx, yy, lw=1, color='black')
32-
ax.plot(xx[1], yy[1], 'o', color='tab:red', markersize=3)
33-
34-
35-
fig, ax = plt.subplots(figsize=(8, 6))
36-
ax.set_title('Join style')
37-
38-
for x, style in enumerate(['miter', 'round', 'bevel']):
39-
ax.text(x, 5, style)
40-
for y, angle in enumerate([20, 45, 60, 90, 120]):
41-
plot_angle(ax, x, y, angle, style)
42-
if x == 0:
43-
ax.text(-1.3, y, f'{angle} degrees')
44-
ax.text(1, 4.7, '(default)')
45-
46-
ax.set_xlim(-1.5, 2.75)
47-
ax.set_ylim(-.5, 5.5)
48-
ax.set_axis_off()
14+
JoinStyle.demo()
4915
plt.show()
50-
51-
52-
#############################################################################
53-
#
54-
# Cap styles
55-
# ==========
56-
#
57-
# Cap styles define how the the end of a line is drawn.
58-
#
59-
# See the respective ``solid_capstyle``, ``dash_capstyle`` or ``capstyle``
60-
# parameters.
61-
62-
fig, ax = plt.subplots(figsize=(8, 2))
63-
ax.set_title('Cap style')
64-
65-
for x, style in enumerate(['butt', 'round', 'projecting']):
66-
ax.text(x+0.25, 1, style, ha='center')
67-
xx = [x, x+0.5]
68-
yy = [0, 0]
69-
ax.plot(xx, yy, lw=12, color='tab:blue', solid_capstyle=style)
70-
ax.plot(xx, yy, lw=1, color='black')
71-
ax.plot(xx, yy, 'o', color='tab:red', markersize=3)
72-
ax.text(2.25, 0.7, '(default)', ha='center')
73-
74-
ax.set_ylim(-.5, 1.5)
75-
ax.set_axis_off()
76-
77-
78-
#############################################################################
79-
#
80-
# ------------
81-
#
82-
# References
83-
# """"""""""
84-
#
85-
# The use of the following functions, methods, classes and modules is shown
86-
# in this example:
87-
88-
import matplotlib
89-
matplotlib.axes.Axes.plot
90-
matplotlib.pyplot.plot

lib/matplotlib/_enums.py

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
"""
2+
Enums representing sets of strings that Matplotlib uses as input parameters.
3+
4+
Matplotlib often uses simple data types like strings or tuples to define a
5+
concept; e.g. the line capstyle can be specified as one of 'butt', 'round',
6+
or 'projecting'. The classes in this module are used internally and serve to
7+
document these concepts formally.
8+
9+
As an end-user you will not use these classes directly, but only the values
10+
they define.
11+
"""
12+
13+
from enum import Enum, auto
14+
from matplotlib import cbook, docstring
15+
16+
17+
class _AutoStringNameEnum(Enum):
18+
"""Automate the ``name = 'name'`` part of making a (str, Enum)."""
19+
20+
def _generate_next_value_(name, start, count, last_values):
21+
return name
22+
23+
def __hash__(self):
24+
return str(self).__hash__()
25+
26+
27+
def _deprecate_case_insensitive_join_cap(s):
28+
s_low = s.lower()
29+
if s != s_low:
30+
if s_low in ['miter', 'round', 'bevel']:
31+
cbook.warn_deprecated(
32+
"3.3", message="Case-insensitive capstyles are deprecated "
33+
"since %(since)s and support for them will be removed "
34+
"%(removal)s; please pass them in lowercase.")
35+
elif s_low in ['butt', 'round', 'projecting']:
36+
cbook.warn_deprecated(
37+
"3.3", message="Case-insensitive joinstyles are deprecated "
38+
"since %(since)s and support for them will be removed "
39+
"%(removal)s; please pass them in lowercase.")
40+
# Else, error out at the check_in_list stage.
41+
return s_low
42+
43+
44+
class JoinStyle(str, _AutoStringNameEnum):
45+
"""
46+
Define how the connection between two line segments is drawn.
47+
48+
For a visual impression of each *JoinStyle*, `view these docs online
49+
<JoinStyle>`, or run `JoinStyle.demo`.
50+
51+
Lines in Matplotlib are typically defined by a 1D `~.path.Path` and a
52+
finite ``linewidth``, where the underlying 1D `~.path.Path` represents the
53+
center of the stroked line.
54+
55+
By default, `~.backend_bases.GraphicsContextBase` defines the boundaries of
56+
a stroked line to simply be every point within some radius,
57+
``linewidth/2``, away from any point of the center line. However, this
58+
results in corners appearing "rounded", which may not be the desired
59+
behavior if you are drawing, for example, a polygon or pointed star.
60+
61+
**Supported values:**
62+
63+
.. rst-class:: value-list
64+
65+
'miter'
66+
the "arrow-tip" style. Each boundary of the filled-in area will
67+
extend in a straight line parallel to the tangent vector of the
68+
centerline at the point it meets the corner, until they meet in a
69+
sharp point.
70+
'round'
71+
stokes every point within a radius of ``linewidth/2`` of the center
72+
lines.
73+
'bevel'
74+
the "squared-off" style. It can be thought of as a rounded corner
75+
where the "circular" part of the corner has been cut off.
76+
77+
.. note::
78+
79+
Very long miter tips are cut off (to form a *bevel*) after a
80+
backend-dependent limit called the "miter limit", which specifies the
81+
maximum allowed ratio of miter length to line width. For example, the
82+
PDF backend uses the default value of 10 specified by the PDF standard,
83+
while the SVG backend does not even specify the miter limit, resulting
84+
in a default value of 4 per the SVG specification. Matplotlib does not
85+
currently allow the user to adjust this parameter.
86+
87+
A more detailed description of the effect of a miter limit can be found
88+
in the `Mozilla Developer Docs
89+
<https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit>`_
90+
91+
.. plot::
92+
:alt: Demo of possible JoinStyle's
93+
94+
from matplotlib._enums import JoinStyle
95+
JoinStyle.demo()
96+
97+
"""
98+
99+
miter = auto()
100+
round = auto()
101+
bevel = auto()
102+
103+
def __init__(self, s):
104+
s = _deprecate_case_insensitive_join_cap(s)
105+
Enum.__init__(self)
106+
107+
@staticmethod
108+
def demo():
109+
"""Demonstrate how each JoinStyle looks for various join angles."""
110+
import numpy as np
111+
import matplotlib.pyplot as plt
112+
113+
def plot_angle(ax, x, y, angle, style):
114+
phi = np.radians(angle)
115+
xx = [x + .5, x, x + .5*np.cos(phi)]
116+
yy = [y, y, y + .5*np.sin(phi)]
117+
ax.plot(xx, yy, lw=12, color='tab:blue', solid_joinstyle=style)
118+
ax.plot(xx, yy, lw=1, color='black')
119+
ax.plot(xx[1], yy[1], 'o', color='tab:red', markersize=3)
120+
121+
fig, ax = plt.subplots(figsize=(5, 4), constrained_layout=True)
122+
ax.set_title('Join style')
123+
for x, style in enumerate(['miter', 'round', 'bevel']):
124+
ax.text(x, 5, style)
125+
for y, angle in enumerate([20, 45, 60, 90, 120]):
126+
plot_angle(ax, x, y, angle, style)
127+
if x == 0:
128+
ax.text(-1.3, y, f'{angle} degrees')
129+
ax.set_xlim(-1.5, 2.75)
130+
ax.set_ylim(-.5, 5.5)
131+
ax.set_axis_off()
132+
fig.show()
133+
134+
135+
JoinStyle.input_description = "{" \
136+
+ ", ".join([f"'{js.name}'" for js in JoinStyle]) \
137+
+ "}"
138+
139+
140+
class CapStyle(str, _AutoStringNameEnum):
141+
r"""
142+
Define how the two endpoints (caps) of an unclosed line are drawn.
143+
144+
How to draw the start and end points of lines that represent a closed curve
145+
(i.e. that end in a `~.path.Path.CLOSEPOLY`) is controlled by the line's
146+
`JoinStyle`. For all other lines, how the start and end points are drawn is
147+
controlled by the *CapStyle*.
148+
149+
For a visual impression of each *CapStyle*, `view these docs online
150+
<CapStyle>` or run `CapStyle.demo`.
151+
152+
**Supported values:**
153+
154+
.. rst-class:: value-list
155+
156+
'butt'
157+
the line is squared off at its endpoint.
158+
'projecting'
159+
the line is squared off as in *butt*, but the filled in area
160+
extends beyond the endpoint a distance of ``linewidth/2``.
161+
'round'
162+
like *butt*, but a semicircular cap is added to the end of the
163+
line, of radius ``linewidth/2``.
164+
165+
.. plot::
166+
:alt: Demo of possible CapStyle's
167+
168+
from matplotlib._enums import CapStyle
169+
CapStyle.demo()
170+
171+
"""
172+
butt = 'butt'
173+
projecting = 'projecting'
174+
round = 'round'
175+
176+
def __init__(self, s):
177+
s = _deprecate_case_insensitive_join_cap(s)
178+
Enum.__init__(self)
179+
180+
@staticmethod
181+
def demo():
182+
"""Demonstrate how each CapStyle looks for a thick line segment."""
183+
import matplotlib.pyplot as plt
184+
185+
fig = plt.figure(figsize=(4, 1.2))
186+
ax = fig.add_axes([0, 0, 1, 0.8])
187+
ax.set_title('Cap style')
188+
189+
for x, style in enumerate(['butt', 'round', 'projecting']):
190+
ax.text(x+0.25, 0.85, style, ha='center')
191+
xx = [x, x+0.5]
192+
yy = [0, 0]
193+
ax.plot(xx, yy, lw=12, color='tab:blue', solid_capstyle=style)
194+
ax.plot(xx, yy, lw=1, color='black')
195+
ax.plot(xx, yy, 'o', color='tab:red', markersize=3)
196+
ax.text(2.25, 0.55, '(default)', ha='center')
197+
198+
ax.set_ylim(-.5, 1.5)
199+
ax.set_axis_off()
200+
fig.show()
201+
202+
203+
CapStyle.input_description = "{" \
204+
+ ", ".join([f"'{cs.name}'" for cs in CapStyle]) \
205+
+ "}"
206+
207+
docstring.interpd.update({'JoinStyle': JoinStyle.input_description,
208+
'CapStyle': CapStyle.input_description})

0 commit comments

Comments
 (0)