Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c19ffdf

Browse filesBrowse files
authored
Merge pull request #23208 from rcomer/stripey-lines
ENH: enable stripey lines
2 parents 6e5a541 + 83240b0 commit c19ffdf
Copy full SHA for c19ffdf

File tree

Expand file treeCollapse file tree

5 files changed

+106
-8
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+106
-8
lines changed
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Striped lines (experimental)
2+
----------------------------
3+
4+
New *gapcolor* parameter enables the creation of striped lines.
5+
6+
.. plot::
7+
:include-source: true
8+
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
12+
x = np.linspace(1., 3., 10)
13+
y = x**3
14+
15+
fig, ax = plt.subplots()
16+
ax.plot(x, y, linestyle='--', color='orange', gapcolor='blue',
17+
linewidth=3, label='a striped line')
18+
ax.legend()
19+
plt.show()

‎examples/lines_bars_and_markers/line_demo_dash_control.py

Copy file name to clipboardExpand all lines: examples/lines_bars_and_markers/line_demo_dash_control.py
+17-5Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,33 @@
1717
:doc:`property_cycle </tutorials/intermediate/color_cycle>`
1818
by passing a list of dash sequences using the keyword *dashes* to the
1919
cycler. This is not shown within this example.
20+
21+
Other attributes of the dash may also be set either with the relevant method
22+
(`~.Line2D.set_dash_capstyle`, `~.Line2D.set_dash_joinstyle`,
23+
`~.Line2D.set_gapcolor`) or by passing the property through a plotting
24+
function.
2025
"""
2126
import numpy as np
2227
import matplotlib.pyplot as plt
2328

2429
x = np.linspace(0, 10, 500)
2530
y = np.sin(x)
2631

32+
plt.rc('lines', linewidth=2.5)
2733
fig, ax = plt.subplots()
2834

29-
# Using set_dashes() to modify dashing of an existing line
30-
line1, = ax.plot(x, y, label='Using set_dashes()')
31-
line1.set_dashes([2, 2, 10, 2]) # 2pt line, 2pt break, 10pt line, 2pt break
35+
# Using set_dashes() and set_capstyle() to modify dashing of an existing line.
36+
line1, = ax.plot(x, y, label='Using set_dashes() and set_dash_capstyle()')
37+
line1.set_dashes([2, 2, 10, 2]) # 2pt line, 2pt break, 10pt line, 2pt break.
38+
line1.set_dash_capstyle('round')
3239

33-
# Using plot(..., dashes=...) to set the dashing when creating a line
40+
# Using plot(..., dashes=...) to set the dashing when creating a line.
3441
line2, = ax.plot(x, y - 0.2, dashes=[6, 2], label='Using the dashes parameter')
3542

36-
ax.legend()
43+
# Using plot(..., dashes=..., gapcolor=...) to set the dashing and
44+
# alternating color when creating a line.
45+
line3, = ax.plot(x, y - 0.4, dashes=[4, 4], gapcolor='tab:pink',
46+
label='Using the dashes and gapcolor parameters')
47+
48+
ax.legend(handlelength=4)
3749
plt.show()

‎lib/matplotlib/lines.py

Copy file name to clipboardExpand all lines: lib/matplotlib/lines.py
+59-3Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ def __init__(self, xdata, ydata,
273273
linewidth=None, # all Nones default to rc
274274
linestyle=None,
275275
color=None,
276+
gapcolor=None,
276277
marker=None,
277278
markersize=None,
278279
markeredgewidth=None,
@@ -365,6 +366,9 @@ def __init__(self, xdata, ydata,
365366
else:
366367
self._marker = marker
367368

369+
self._gapcolor = None
370+
self.set_gapcolor(gapcolor)
371+
368372
self._markevery = None
369373
self._markersize = None
370374
self._antialiased = None
@@ -755,9 +759,6 @@ def draw(self, renderer):
755759
self._set_gc_clip(gc)
756760
gc.set_url(self.get_url())
757761

758-
lc_rgba = mcolors.to_rgba(self._color, self._alpha)
759-
gc.set_foreground(lc_rgba, isRGBA=True)
760-
761762
gc.set_antialiased(self._antialiased)
762763
gc.set_linewidth(self._linewidth)
763764

@@ -773,6 +774,26 @@ def draw(self, renderer):
773774
if self.get_sketch_params() is not None:
774775
gc.set_sketch_params(*self.get_sketch_params())
775776

777+
# We first draw a path within the gaps if needed.
778+
if self.is_dashed() and self._gapcolor is not None:
779+
lc_rgba = mcolors.to_rgba(self._gapcolor, self._alpha)
780+
gc.set_foreground(lc_rgba, isRGBA=True)
781+
782+
# Define the inverse pattern by moving the last gap to the
783+
# start of the sequence.
784+
dashes = self._dash_pattern[1]
785+
gaps = dashes[-1:] + dashes[:-1]
786+
# Set the offset so that this new first segment is skipped
787+
# (see backend_bases.GraphicsContextBase.set_dashes for
788+
# offset definition).
789+
offset_gaps = self._dash_pattern[0] + dashes[-1]
790+
791+
gc.set_dashes(offset_gaps, gaps)
792+
renderer.draw_path(gc, tpath, affine.frozen())
793+
794+
lc_rgba = mcolors.to_rgba(self._color, self._alpha)
795+
gc.set_foreground(lc_rgba, isRGBA=True)
796+
776797
gc.set_dashes(*self._dash_pattern)
777798
renderer.draw_path(gc, tpath, affine.frozen())
778799
gc.restore()
@@ -877,6 +898,14 @@ def get_drawstyle(self):
877898
"""
878899
return self._drawstyle
879900

901+
def get_gapcolor(self):
902+
"""
903+
Return the line gapcolor.
904+
905+
See also `~.Line2D.set_gapcolor`.
906+
"""
907+
return self._gapcolor
908+
880909
def get_linestyle(self):
881910
"""
882911
Return the linestyle.
@@ -1067,6 +1096,29 @@ def set_drawstyle(self, drawstyle):
10671096
self._invalidx = True
10681097
self._drawstyle = drawstyle
10691098

1099+
def set_gapcolor(self, gapcolor):
1100+
"""
1101+
Set a color to fill the gaps in the dashed line style.
1102+
1103+
.. note::
1104+
1105+
Striped lines are created by drawing two interleaved dashed lines.
1106+
There can be overlaps between those two, which may result in
1107+
artifacts when using transparency.
1108+
1109+
This functionality is experimental and may change.
1110+
1111+
Parameters
1112+
----------
1113+
gapcolor : color or None
1114+
The color with which to fill the gaps. If None, the gaps are
1115+
unfilled.
1116+
"""
1117+
if gapcolor is not None:
1118+
mcolors._check_color_like(color=gapcolor)
1119+
self._gapcolor = gapcolor
1120+
self.stale = True
1121+
10701122
def set_linewidth(self, w):
10711123
"""
10721124
Set the line width in points.
@@ -1248,6 +1300,9 @@ def set_dashes(self, seq):
12481300
For example, (5, 2, 1, 2) describes a sequence of 5 point and 1 point
12491301
dashes separated by 2 point spaces.
12501302
1303+
See also `~.Line2D.set_gapcolor`, which allows those spaces to be
1304+
filled with a color.
1305+
12511306
Parameters
12521307
----------
12531308
seq : sequence of floats (on/off ink in points) or (None, None)
@@ -1265,6 +1320,7 @@ def update_from(self, other):
12651320
self._linestyle = other._linestyle
12661321
self._linewidth = other._linewidth
12671322
self._color = other._color
1323+
self._gapcolor = other._gapcolor
12681324
self._markersize = other._markersize
12691325
self._markerfacecolor = other._markerfacecolor
12701326
self._markerfacecoloralt = other._markerfacecoloralt
Loading

‎lib/matplotlib/tests/test_lines.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_lines.py
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,17 @@ def test_marker_as_markerstyle():
304304
assert_array_equal(line3.get_marker().vertices, triangle1.vertices)
305305

306306

307+
@image_comparison(['striped_line.png'], remove_text=True, style='mpl20')
308+
def test_striped_lines():
309+
rng = np.random.default_rng(19680801)
310+
_, ax = plt.subplots()
311+
ax.plot(rng.uniform(size=12), color='orange', gapcolor='blue',
312+
linestyle='--', lw=5, label=' ')
313+
ax.plot(rng.uniform(size=12), color='red', gapcolor='black',
314+
linestyle=(0, (2, 5, 4, 2)), lw=5, label=' ', alpha=0.5)
315+
ax.legend(handlelength=5)
316+
317+
307318
@check_figures_equal()
308319
def test_odd_dashes(fig_test, fig_ref):
309320
fig_test.add_subplot().plot([1, 2], dashes=[1, 2, 3])

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.