Description
Bug report
Bug summary
The edges of some half-filled markers either produce spikes or are missing parts.
Code for reproduction
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(2.2, 1.4))
ax.set_xlim(-0.5, 5)
ax.set_axis_off()
sty = dict(marker='D', fillstyle='right', markerfacecoloralt='r',
markerfacecolor='g', markeredgecolor='#00000088')
plt.plot([0], [0], **sty)
plt.plot([1], [0], markeredgewidth=10, **sty)
plt.plot([3], [0], markeredgewidth=10, markersize=30, **sty)
This code produces the following image
Expected output
The outer marker edges should build a rectangle like for fully filled markers. The spikes and missing parts of the edge are not as noticeable for the default marker size (left), but they can still be visible when printed from a vector image (e.g. pdf). (The transparency of the edges is just to more clearly show the two paths the marker edge is composed of.)
When looking into the matplotlib.markers.MarkerStyle._set_diamond
method, there are three issues generating this output:
- The marker paths are not closed. This causes the asymmetry of the edge at the top and bottom of the marker.
- The join-style of the edge is set to
'miter'
, which causes the spikes at the top since the corner has a very sharp 45° angle. - The cap-style of the edge defaults to
'butt'
. At the marker bottom the edge path starts and ends and does not complete the corner.
The same issue appears for the other half-filled styles 'left'
, 'top'
and 'bottom'
(since they only rotate the marker differently). Other markers have similar issues (e.g. 's'
, '^'
, 'd'
, 'h'
).
My current solution is to set the join-style and cap-style to 'rounded'
at the end of the MarkerStyle._set_diamond
method
self._joinstyle = 'round'
self._capstyle = 'round'
This produces the output
The corners are now round instead of pointy, but the spikes and missing parts are gone and the marker is symmetric.
A more general solution would be better, though. This would maybe require using custom paths for the edges instead of reusing the paths of the marker faces. But I'm not sure whether this can be easily implemented.
Matplotlib version
- Operating system: Windows 10
- Matplotlib version: 3.0.3
- Matplotlib backend: Qt5Agg & inline
- Python version: 3.7 & 3.6