1
1
"""
2
- Style description information that is shared across unrelated classses.
2
+ Matplotlib API concepts that would not otherwise merit a dedicated class.
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.
3
11
"""
4
12
5
13
from enum import Enum , auto
6
- from matplotlib import cbook
14
+ from matplotlib import cbook , docstring
7
15
8
16
9
17
class _AutoStringNameEnum (Enum ):
10
18
"""Automate the ``name = 'name'`` part of making a (str, Enum)."""
19
+
11
20
def _generate_next_value_ (name , start , count , last_values ):
12
21
return name
13
22
23
+ def __hash__ (self ):
24
+ return str (self ).__hash__ ()
25
+
14
26
15
27
def _deprecate_case_insensitive_join_cap (s ):
16
28
s_low = s .lower ()
@@ -34,13 +46,7 @@ class JoinStyle(str, _AutoStringNameEnum):
34
46
Define how the connection between two line segments is drawn.
35
47
36
48
For a visual impression of each *JoinStyle*, `view these docs online
37
- <JoinStyle>`, or run `JoinStyle.demo`:
38
-
39
- .. plot::
40
- :alt: Demo of possible JoinStyle's
41
-
42
- from matplotlib._types import JoinStyle
43
- JoinStyle.demo()
49
+ <JoinStyle>`, or run `JoinStyle.demo`.
44
50
45
51
Lines in Matplotlib are typically defined by a 1D `~.path.Path` and a
46
52
finite ``linewidth``, where the underlying 1D `~.path.Path` represents the
@@ -52,32 +58,42 @@ class JoinStyle(str, _AutoStringNameEnum):
52
58
results in corners appearing "rounded", which may not be the desired
53
59
behavior if you are drawing, for example, a polygon or pointed star.
54
60
55
- Matplotlib provides three options for drawing the corners between adjacent
56
- segments. In short:
61
+ **Supported values:**
62
+
63
+ .. rst-class:: value-list
57
64
58
- - *miter* is the "arrow-tip" style. Each boundary of the filled-in area
59
- will extend in a straight line parallel to the tangent vector of the
60
- centerline at the point it meets the corner, until they meet in a
61
- sharp point.
62
- - *round* stokes every point within a radius of ``linewidth/2`` of the
63
- center lines.
64
- - *bevel* is the "squared-off" style. It can be thought of as a rounded
65
- corner where the "circular" part of the corner has been cut off.
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.
66
76
67
77
.. note::
68
78
69
- The *miter* option can be controlled further by specifying a "miter
70
- limit", which specifies how long a miter tip can get before it is
71
- automatically "bevel"ed off. Matplotlib does not currently expose a
72
- ``miterlimit`` parameter to the user, and most backends simply use the
73
- upstream default value. For example, the PDF backend assumes the
74
- default value of 10 specified by the PDF standard, while the SVG
75
- backend does not even specify the miter limit, resulting in a default
76
- value of 4 per the SVG specification.
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.
77
86
78
87
A more detailed description of the effect of a miter limit can be found
79
88
in the `Mozilla Developer Docs
80
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._types import JoinStyle
95
+ JoinStyle.demo()
96
+
81
97
"""
82
98
83
99
miter = auto ()
@@ -90,6 +106,7 @@ def __init__(self, s):
90
106
91
107
@staticmethod
92
108
def demo ():
109
+ """Demonstrate how each JoinStyle looks for various join angles."""
93
110
import numpy as np
94
111
import matplotlib .pyplot as plt
95
112
@@ -101,7 +118,7 @@ def plot_angle(ax, x, y, angle, style):
101
118
ax .plot (xx , yy , lw = 1 , color = 'black' )
102
119
ax .plot (xx [1 ], yy [1 ], 'o' , color = 'tab:red' , markersize = 3 )
103
120
104
- fig , ax = plt .subplots (figsize = (8 , 6 ) )
121
+ fig , ax = plt .subplots (figsize = (5 , 4 ), constrained_layout = True )
105
122
ax .set_title ('Join style' )
106
123
for x , style in enumerate (['miter' , 'round' , 'bevel' ]):
107
124
ax .text (x , 5 , style )
@@ -115,6 +132,11 @@ def plot_angle(ax, x, y, angle, style):
115
132
fig .show ()
116
133
117
134
135
+ JoinStyle .input_description = "{" \
136
+ + ", " .join ([f"'{ js .name } '" for js in JoinStyle ]) \
137
+ + "}"
138
+
139
+
118
140
class CapStyle (str , _AutoStringNameEnum ):
119
141
r"""
120
142
Define how the two endpoints (caps) of an unclosed line are drawn.
@@ -125,21 +147,27 @@ class CapStyle(str, _AutoStringNameEnum):
125
147
controlled by the *CapStyle*.
126
148
127
149
For a visual impression of each *CapStyle*, `view these docs online
128
- <CapStyle>` or run `CapStyle.demo`:
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``.
129
164
130
165
.. plot::
131
166
:alt: Demo of possible CapStyle's
132
167
133
168
from matplotlib._types import CapStyle
134
169
CapStyle.demo()
135
170
136
- Available options:
137
-
138
- - *butt*: the line is squared off at its endpoint.
139
- - *projecting*: the line is squared off as in *butt*, but the filled in
140
- area extends beyond the endpoint a distance of ``linewidth/2``.
141
- - *round*: like *butt*, but a semicircular cap is added to the end of
142
- the line, of radius ``linewidth/2``.
143
171
"""
144
172
butt = 'butt'
145
173
projecting = 'projecting'
@@ -151,20 +179,30 @@ def __init__(self, s):
151
179
152
180
@staticmethod
153
181
def demo ():
182
+ """Demonstrate how each CapStyle looks for a thick line segment."""
154
183
import matplotlib .pyplot as plt
155
184
156
- fig , ax = plt .subplots (figsize = (8 , 2 ))
185
+ fig = plt .figure (figsize = (4 , 1.2 ))
186
+ ax = fig .add_axes ([0 , 0 , 1 , 0.8 ])
157
187
ax .set_title ('Cap style' )
158
188
159
189
for x , style in enumerate (['butt' , 'round' , 'projecting' ]):
160
- ax .text (x + 0.25 , 1 , style , ha = 'center' )
190
+ ax .text (x + 0.25 , 0.85 , style , ha = 'center' )
161
191
xx = [x , x + 0.5 ]
162
192
yy = [0 , 0 ]
163
193
ax .plot (xx , yy , lw = 12 , color = 'tab:blue' , solid_capstyle = style )
164
194
ax .plot (xx , yy , lw = 1 , color = 'black' )
165
195
ax .plot (xx , yy , 'o' , color = 'tab:red' , markersize = 3 )
166
- ax .text (2.25 , 0.7 , '(default)' , ha = 'center' )
196
+ ax .text (2.25 , 0.55 , '(default)' , ha = 'center' )
167
197
168
198
ax .set_ylim (- .5 , 1.5 )
169
199
ax .set_axis_off ()
170
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