Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hatching "style" class for GSOD #19077

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 18 additions & 3 deletions doc/_static/mpl.css
Expand Up @@ -89,7 +89,7 @@ table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}

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


/* function and class description */
.descclassname {
color: #aaa;
Expand Down Expand Up @@ -806,6 +805,22 @@ dl.class > dd {
font-size: 14px;
}

/* custom tables for lists of allowed values in "mpl._types" */
dl.value-list {
display: grid;
}

dl.value-list dt {
grid-column: 1;
margin: 4px 0;
}

dl.value-list dd {
grid-column: 2;
margin: 4px 0 4px 20px;
padding: 0;
}

/* parameter section table */
table.docutils.field-list {
width: 100%;
Expand Down Expand Up @@ -1257,4 +1272,4 @@ div.bullet-box li {

div#gallery.section .sphx-glr-clear:first-of-type, div#tutorials.section .sphx-glr-clear:first-of-type{
display: none;
}
}
15 changes: 15 additions & 0 deletions doc/api/_types.rst
@@ -0,0 +1,15 @@
**********************
``matplotlib._types``
**********************

.. automodule:: matplotlib._types
:no-members:

.. autoclass:: JoinStyle
:members: demo
:exclude-members: bevel, miter, round, input_description

.. autoclass:: CapStyle
:members: demo
:exclude-members: butt, round, projecting, input_description

9 changes: 9 additions & 0 deletions doc/api/hatch_api.rst
@@ -0,0 +1,9 @@
*********************
``matplotlib.hatch``
*********************

.. automodule:: matplotlib.hatch
:members:
:undoc-members:
:show-inheritance:

2 changes: 2 additions & 0 deletions doc/api/index.rst
Expand Up @@ -93,6 +93,7 @@ Matplotlib consists of the following submodules:
font_manager_api.rst
fontconfig_pattern_api.rst
gridspec_api.rst
hatch_api.rst
image_api.rst
legend_api.rst
legend_handler_api.rst
Expand Down Expand Up @@ -124,6 +125,7 @@ Matplotlib consists of the following submodules:
transformations.rst
tri_api.rst
type1font.rst
_types.rst
units_api.rst
widgets_api.rst
_api_api.rst
Expand Down
90 changes: 0 additions & 90 deletions examples/lines_bars_and_markers/joinstyle.py

This file was deleted.

204 changes: 204 additions & 0 deletions lib/matplotlib/_types.py
@@ -0,0 +1,204 @@
"""
Concepts used by the matplotlib API that do not yet have a dedicated class.

Matplotlib often uses simple data types like strings or tuples to define a
concept; e.g. the line capstyle can be specified as one of 'butt', 'round',
or 'projecting'. The classes in this module are used internally and document
these concepts formally.

As an end-user you will not use these classes directly, but only the values
they define.
"""

from enum import Enum, auto
from matplotlib import cbook, docstring


class _AutoStringNameEnum(Enum):
"""Automate the ``name = 'name'`` part of making a (str, Enum)."""
def _generate_next_value_(name, start, count, last_values):
return name


def _deprecate_case_insensitive_join_cap(s):
s_low = s.lower()
if s != s_low:
if s_low in ['miter', 'round', 'bevel']:
cbook.warn_deprecated(
"3.3", message="Case-insensitive capstyles are deprecated "
"since %(since)s and support for them will be removed "
"%(removal)s; please pass them in lowercase.")
elif s_low in ['butt', 'round', 'projecting']:
cbook.warn_deprecated(
"3.3", message="Case-insensitive joinstyles are deprecated "
"since %(since)s and support for them will be removed "
"%(removal)s; please pass them in lowercase.")
# Else, error out at the check_in_list stage.
return s_low


class JoinStyle(str, _AutoStringNameEnum):
"""
Define how the connection between two line segments is drawn.

For a visual impression of each *JoinStyle*, `view these docs online
<JoinStyle>`, or run `JoinStyle.demo`.

Lines in Matplotlib are typically defined by a 1D `~.path.Path` and a
finite ``linewidth``, where the underlying 1D `~.path.Path` represents the
center of the stroked line.

By default, `~.backend_bases.GraphicsContextBase` defines the boundaries of
a stroked line to simply be every point within some radius,
``linewidth/2``, away from any point of the center line. However, this
results in corners appearing "rounded", which may not be the desired
behavior if you are drawing, for example, a polygon or pointed star.

**Supported values:**

.. rst-class:: value-list

'miter'
the "arrow-tip" style. Each boundary of the filled-in area will
extend in a straight line parallel to the tangent vector of the
centerline at the point it meets the corner, until they meet in a
sharp point.
'round'
stokes every point within a radius of ``linewidth/2`` of the center
lines.
'bevel'
the "squared-off" style. It can be thought of as a rounded corner
where the "circular" part of the corner has been cut off.

.. note::

Very long miter tips are cut off (to form a *bevel*) after a
backend-dependent limit called the "miter limit", which specifies the
maximum allowed ratio of miter length to line width. For example, the
PDF backend uses the default value of 10 specified by the PDF standard,
while the SVG backend does not even specify the miter limit, resulting
in a default value of 4 per the SVG specification. Matplotlib does not
currently allow the user to adjust this parameter.

A more detailed description of the effect of a miter limit can be found
in the `Mozilla Developer Docs
<https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit>`_

.. plot::
:alt: Demo of possible JoinStyle's

from matplotlib._types import JoinStyle
JoinStyle.demo()

"""

miter = auto()
round = auto()
bevel = auto()

def __init__(self, s):
s = _deprecate_case_insensitive_join_cap(s)
Enum.__init__(self)

@staticmethod
def demo():
"""Demonstrate how each JoinStyle looks for various join angles."""
import numpy as np
import matplotlib.pyplot as plt

def plot_angle(ax, x, y, angle, style):
phi = np.radians(angle)
xx = [x + .5, x, x + .5*np.cos(phi)]
yy = [y, y, y + .5*np.sin(phi)]
ax.plot(xx, yy, lw=12, color='tab:blue', solid_joinstyle=style)
ax.plot(xx, yy, lw=1, color='black')
ax.plot(xx[1], yy[1], 'o', color='tab:red', markersize=3)

fig, ax = plt.subplots(figsize=(5, 4), constrained_layout=True)
ax.set_title('Join style')
for x, style in enumerate(['miter', 'round', 'bevel']):
ax.text(x, 5, style)
for y, angle in enumerate([20, 45, 60, 90, 120]):
plot_angle(ax, x, y, angle, style)
if x == 0:
ax.text(-1.3, y, f'{angle} degrees')
ax.set_xlim(-1.5, 2.75)
ax.set_ylim(-.5, 5.5)
ax.set_axis_off()
fig.show()


JoinStyle.input_description = "{" \
+ ", ".join([f"'{js.name}'" for js in JoinStyle]) \
+ "}"


class CapStyle(str, _AutoStringNameEnum):
r"""
Define how the two endpoints (caps) of an unclosed line are drawn.

How to draw the start and end points of lines that represent a closed curve
(i.e. that end in a `~.path.Path.CLOSEPOLY`) is controlled by the line's
`JoinStyle`. For all other lines, how the start and end points are drawn is
controlled by the *CapStyle*.

For a visual impression of each *CapStyle*, `view these docs online
<CapStyle>` or run `CapStyle.demo`.

**Supported values:**

.. rst-class:: value-list

'butt'
the line is squared off at its endpoint.
'projecting'
the line is squared off as in *butt*, but the filled in area
extends beyond the endpoint a distance of ``linewidth/2``.
'round'
like *butt*, but a semicircular cap is added to the end of the
line, of radius ``linewidth/2``.

.. plot::
:alt: Demo of possible CapStyle's

from matplotlib._types import CapStyle
CapStyle.demo()

"""
butt = 'butt'
projecting = 'projecting'
round = 'round'

def __init__(self, s):
s = _deprecate_case_insensitive_join_cap(s)
Enum.__init__(self)

@staticmethod
def demo():
"""Demonstrate how each CapStyle looks for a thick line segment."""
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 1.2))
ax = fig.add_axes([0, 0, 1, 0.8])
ax.set_title('Cap style')

for x, style in enumerate(['butt', 'round', 'projecting']):
ax.text(x+0.25, 0.85, style, ha='center')
xx = [x, x+0.5]
yy = [0, 0]
ax.plot(xx, yy, lw=12, color='tab:blue', solid_capstyle=style)
ax.plot(xx, yy, lw=1, color='black')
ax.plot(xx, yy, 'o', color='tab:red', markersize=3)
ax.text(2.25, 0.55, '(default)', ha='center')

ax.set_ylim(-.5, 1.5)
ax.set_axis_off()
fig.show()


CapStyle.input_description = "{" \
+ ", ".join([f"'{cs.name}'" for cs in CapStyle]) \
+ "}"

docstring.interpd.update({'JoinStyle': JoinStyle.input_description,
'CapStyle': CapStyle.input_description})