|
| 1 | +""" |
| 2 | +Style description information that is shared across unrelated classses. |
| 3 | +""" |
| 4 | + |
| 5 | +fromenumimportEnum,auto |
| 6 | +frommatplotlibimportcbook |
| 7 | + |
| 8 | + |
| 9 | +class_AutoStringNameEnum(Enum): |
| 10 | +"""Automate the ``name = 'name'`` part of making a (str, Enum).""" |
| 11 | +def_generate_next_value_(name,start,count,last_values): |
| 12 | +returnname |
| 13 | + |
| 14 | + |
| 15 | +def_deprecate_case_insensitive_join_cap(s): |
| 16 | +s_low=s.lower() |
| 17 | +ifs!=s_low: |
| 18 | +ifs_lowin ['miter','round','bevel']: |
| 19 | +cbook.warn_deprecated( |
| 20 | +"3.3",message="Case-insensitive capstyles are deprecated " |
| 21 | +"since %(since)s and support for them will be removed " |
| 22 | +"%(removal)s; please pass them in lowercase.") |
| 23 | +elifs_lowin ['butt','round','projecting']: |
| 24 | +cbook.warn_deprecated( |
| 25 | +"3.3",message="Case-insensitive joinstyles are deprecated " |
| 26 | +"since %(since)s and support for them will be removed " |
| 27 | +"%(removal)s; please pass them in lowercase.") |
| 28 | +# Else, error out at the check_in_list stage. |
| 29 | +returns_low |
| 30 | + |
| 31 | + |
| 32 | +classJoinStyle(str,_AutoStringNameEnum): |
| 33 | +""" |
| 34 | + Define how the connection between two line segments is drawn. |
| 35 | +
|
| 36 | + 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() |
| 44 | +
|
| 45 | + Lines in Matplotlib are typically defined by a 1D `~.path.Path` and a |
| 46 | + finite ``linewidth``, where the underlying 1D `~.path.Path` represents the |
| 47 | + center of the stroked line. |
| 48 | +
|
| 49 | + By default, `~.backend_bases.GraphicsContextBase` defines the boundaries of |
| 50 | + a stroked line to simply be every point within some radius, |
| 51 | + ``linewidth/2``, away from any point of the center line. However, this |
| 52 | + results in corners appearing "rounded", which may not be the desired |
| 53 | + behavior if you are drawing, for example, a polygon or pointed star. |
| 54 | +
|
| 55 | + Matplotlib provides three options for drawing the corners between adjacent |
| 56 | + segments. In short: |
| 57 | +
|
| 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. |
| 66 | +
|
| 67 | + .. note:: |
| 68 | +
|
| 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. |
| 77 | +
|
| 78 | + A more detailed description of the effect of a miter limit can be found |
| 79 | + in the `Mozilla Developer Docs |
| 80 | + <https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit>`_ |
| 81 | + """ |
| 82 | + |
| 83 | +miter=auto() |
| 84 | +round=auto() |
| 85 | +bevel=auto() |
| 86 | + |
| 87 | +def__init__(self,s): |
| 88 | +s=_deprecate_case_insensitive_join_cap(s) |
| 89 | +Enum.__init__(self) |
| 90 | + |
| 91 | +@staticmethod |
| 92 | +defdemo(): |
| 93 | +importnumpyasnp |
| 94 | +importmatplotlib.pyplotasplt |
| 95 | + |
| 96 | +defplot_angle(ax,x,y,angle,style): |
| 97 | +phi=np.radians(angle) |
| 98 | +xx= [x+.5,x,x+.5*np.cos(phi)] |
| 99 | +yy= [y,y,y+.5*np.sin(phi)] |
| 100 | +ax.plot(xx,yy,lw=12,color='tab:blue',solid_joinstyle=style) |
| 101 | +ax.plot(xx,yy,lw=1,color='black') |
| 102 | +ax.plot(xx[1],yy[1],'o',color='tab:red',markersize=3) |
| 103 | + |
| 104 | +fig,ax=plt.subplots(figsize=(8,6)) |
| 105 | +ax.set_title('Join style') |
| 106 | +forx,styleinenumerate(['miter','round','bevel']): |
| 107 | +ax.text(x,5,style) |
| 108 | +fory,angleinenumerate([20,45,60,90,120]): |
| 109 | +plot_angle(ax,x,y,angle,style) |
| 110 | +ifx==0: |
| 111 | +ax.text(-1.3,y,f'{angle} degrees') |
| 112 | +ax.set_xlim(-1.5,2.75) |
| 113 | +ax.set_ylim(-.5,5.5) |
| 114 | +ax.set_axis_off() |
| 115 | +fig.show() |
| 116 | + |
| 117 | + |
| 118 | +classCapStyle(str,_AutoStringNameEnum): |
| 119 | +r""" |
| 120 | + Define how the two endpoints (caps) of an unclosed line are drawn. |
| 121 | +
|
| 122 | + How to draw the start and end points of lines that represent a closed curve |
| 123 | + (i.e. that end in a `~.path.Path.CLOSEPOLY`) is controlled by the line's |
| 124 | + `JoinStyle`. For all other lines, how the start and end points are drawn is |
| 125 | + controlled by the *CapStyle*. |
| 126 | +
|
| 127 | + For a visual impression of each *CapStyle*, `view these docs online |
| 128 | + <CapStyle>` or run `CapStyle.demo`: |
| 129 | +
|
| 130 | + .. plot:: |
| 131 | + :alt: Demo of possible CapStyle's |
| 132 | +
|
| 133 | + from matplotlib._types import CapStyle |
| 134 | + CapStyle.demo() |
| 135 | +
|
| 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 | + """ |
| 144 | +butt='butt' |
| 145 | +projecting='projecting' |
| 146 | +round='round' |
| 147 | + |
| 148 | +def__init__(self,s): |
| 149 | +s=_deprecate_case_insensitive_join_cap(s) |
| 150 | +Enum.__init__(self) |
| 151 | + |
| 152 | +@staticmethod |
| 153 | +defdemo(): |
| 154 | +importmatplotlib.pyplotasplt |
| 155 | + |
| 156 | +fig,ax=plt.subplots(figsize=(8,2)) |
| 157 | +ax.set_title('Cap style') |
| 158 | + |
| 159 | +forx,styleinenumerate(['butt','round','projecting']): |
| 160 | +ax.text(x+0.25,1,style,ha='center') |
| 161 | +xx= [x,x+0.5] |
| 162 | +yy= [0,0] |
| 163 | +ax.plot(xx,yy,lw=12,color='tab:blue',solid_capstyle=style) |
| 164 | +ax.plot(xx,yy,lw=1,color='black') |
| 165 | +ax.plot(xx,yy,'o',color='tab:red',markersize=3) |
| 166 | +ax.text(2.25,0.7,'(default)',ha='center') |
| 167 | + |
| 168 | +ax.set_ylim(-.5,1.5) |
| 169 | +ax.set_axis_off() |
| 170 | +fig.show() |