diff --git a/doc/users/whats_new/filled_plus_and_x_markers.rst b/doc/users/whats_new/filled_plus_and_x_markers.rst new file mode 100644 index 000000000000..f73dcec3b575 --- /dev/null +++ b/doc/users/whats_new/filled_plus_and_x_markers.rst @@ -0,0 +1,7 @@ +Filled ``+`` and ``x`` markers +------------------------------ + +New fillable *plus* and *x* markers have been added. See +the :mod:`~matplotlib.markers` module and +:ref:`marker reference ` +examples. diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py index b0ee5c51f077..ba43041174d3 100644 --- a/lib/matplotlib/markers.py +++ b/lib/matplotlib/markers.py @@ -31,6 +31,8 @@ "d" thin_diamond "|" vline "_" hline +"P" plus (filled) +"X" x (filled) TICKLEFT tickleft TICKRIGHT tickright TICKUP tickup @@ -126,6 +128,8 @@ class MarkerStyle(object): 'd': 'thin_diamond', '|': 'vline', '_': 'hline', + 'P': 'plus_filled', + 'X': 'x_filled', TICKLEFT: 'tickleft', TICKRIGHT: 'tickright', TICKUP: 'tickup', @@ -147,7 +151,8 @@ class MarkerStyle(object): # Just used for informational purposes. is_filled() # is calculated in the _set_* functions. filled_markers = ( - 'o', 'v', '^', '<', '>', '8', 's', 'p', '*', 'h', 'H', 'D', 'd') + 'o', 'v', '^', '<', '>', '8', 's', 'p', '*', 'h', 'H', 'D', 'd', + 'P', 'X') fillstyles = ('full', 'left', 'right', 'bottom', 'top', 'none') _half_fillstyles = ('left', 'right', 'bottom', 'top') @@ -828,3 +833,87 @@ def _set_x(self): self._snap_threshold = 3.0 self._filled = False self._path = self._x_path + + _plus_filled_path = Path([(1/3, 0), (2/3, 0), (2/3, 1/3), + (1, 1/3), (1, 2/3), (2/3, 2/3), + (2/3, 1), (1/3, 1), (1/3, 2/3), + (0, 2/3), (0, 1/3), (1/3, 1/3), + (1/3, 0)], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.CLOSEPOLY]) + + _plus_filled_path_t = Path([(1, 1/2), (1, 2/3), (2/3, 2/3), + (2/3, 1), (1/3, 1), (1/3, 2/3), + (0, 2/3), (0, 1/2), (1, 1/2)], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, + Path.CLOSEPOLY]) + + def _set_plus_filled(self): + self._transform = Affine2D().translate(-0.5, -0.5) + self._snap_threshold = 5.0 + self._joinstyle = 'miter' + fs = self.get_fillstyle() + if not self._half_fill(): + self._path = self._plus_filled_path + else: + # Rotate top half path to support all partitions + if fs == 'top': + rotate, rotate_alt = 0, 180 + elif fs == 'bottom': + rotate, rotate_alt = 180, 0 + elif fs == 'left': + rotate, rotate_alt = 90, 270 + else: + rotate, rotate_alt = 270, 90 + + self._path = self._plus_filled_path_t + self._alt_path = self._plus_filled_path_t + self._alt_transform = Affine2D().translate(-0.5, -0.5) + self._transform.rotate_deg(rotate) + self._alt_transform.rotate_deg(rotate_alt) + + _x_filled_path = Path([(0.25, 0), (0.5, 0.25), (0.75, 0), (1, 0.25), + (0.75, 0.5), (1, 0.75), (0.75, 1), (0.5, 0.75), + (0.25, 1), (0, 0.75), (0.25, 0.5), (0, 0.25), + (0.25, 0)], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.CLOSEPOLY]) + + _x_filled_path_t = Path([(0.75, 0.5), (1, 0.75), (0.75, 1), + (0.5, 0.75), (0.25, 1), (0, 0.75), + (0.25, 0.5), (0.75, 0.5)], + [Path.MOVETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.LINETO, Path.LINETO, + Path.LINETO, Path.CLOSEPOLY]) + + def _set_x_filled(self): + self._transform = Affine2D().translate(-0.5, -0.5) + self._snap_threshold = 5.0 + self._joinstyle = 'miter' + fs = self.get_fillstyle() + if not self._half_fill(): + self._path = self._x_filled_path + else: + # Rotate top half path to support all partitions + if fs == 'top': + rotate, rotate_alt = 0, 180 + elif fs == 'bottom': + rotate, rotate_alt = 180, 0 + elif fs == 'left': + rotate, rotate_alt = 90, 270 + else: + rotate, rotate_alt = 270, 90 + + self._path = self._x_filled_path_t + self._alt_path = self._x_filled_path_t + self._alt_transform = Affine2D().translate(-0.5, -0.5) + self._transform.rotate_deg(rotate) + self._alt_transform.rotate_deg(rotate_alt) diff --git a/lib/matplotlib/tests/baseline_images/test_axes/marker_styles.png b/lib/matplotlib/tests/baseline_images/test_axes/marker_styles.png index e8be480e4ca7..0bb2791b7207 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_axes/marker_styles.png and b/lib/matplotlib/tests/baseline_images/test_axes/marker_styles.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_lines/marker_fill_styles.png b/lib/matplotlib/tests/baseline_images/test_lines/marker_fill_styles.png index 547599f93d2e..fc251c4cadbe 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_lines/marker_fill_styles.png and b/lib/matplotlib/tests/baseline_images/test_lines/marker_fill_styles.png differ diff --git a/lib/matplotlib/tests/test_lines.py b/lib/matplotlib/tests/test_lines.py index 194777cce5a6..2038706c30f3 100644 --- a/lib/matplotlib/tests/test_lines.py +++ b/lib/matplotlib/tests/test_lines.py @@ -180,7 +180,7 @@ def test_marker_fill_styles(): markeredgewidth=2) ax.set_ylim([0, 7.5]) - ax.set_xlim([-5, 135]) + ax.set_xlim([-5, 155]) @image_comparison(baseline_images=['scaled_lines'], style='default') pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy