Skip to content

Commit 48a465e

Browse files
CharlieThornton33anntzer
authored andcommitted
Make arrow annotation arrowhead adjustable (tests, whatsnew).
[Only part of the patch was kept by the PR committer.]
1 parent 59331be commit 48a465e

File tree

5 files changed

+89
-2
lines changed

5 files changed

+89
-2
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Arrow-style sub-classes of ``BoxStyle`` support arrow head resizing
2+
-------------------------------------------------------------------
3+
4+
The new *head_width* and *head_angle* parameters to
5+
`.BoxStyle.LArrow`, `.BoxStyle.RArrow` and `.BoxStyle.DArrow` allow for adjustment
6+
of the size and aspect ratio of the arrow heads used.
7+
8+
To give a consistent appearance across all parameter values, the
9+
default head position (where the head starts relative to text) is
10+
slightly changed compared to the previous hard-coded position.
11+
12+
By using negative angles (or corresponding reflex angles) for *head_angle*, arrows
13+
with 'backwards' heads may be created.
14+
15+
.. plot::
16+
:include-source: true
17+
:alt:
18+
Six arrow-shaped text boxes. The arrows on the left have the shaft on
19+
their left; the arrows on the right have the shaft on the right; the
20+
arrows in the middle have shafts on both sides.
21+
22+
import matplotlib.pyplot as plt
23+
24+
plt.text(0.2, 0.8, "LArrow", ha='center', size=16,
25+
bbox=dict(boxstyle="larrow, pad=0.3, head_angle=150"))
26+
plt.text(0.2, 0.2, "LArrow", ha='center', size=16,
27+
bbox=dict(boxstyle="larrow, pad=0.3, head_width=0.5"))
28+
plt.text(0.5, 0.8, "DArrow", ha='center', size=16,
29+
bbox=dict(boxstyle="darrow, pad=0.3, head_width=3"))
30+
plt.text(0.5, 0.2, "DArrow", ha='center', size=16,
31+
bbox=dict(boxstyle="darrow, pad=0.3, head_width=1, head_angle=60"))
32+
plt.text(0.8, 0.8, "RArrow", ha='center', size=16,
33+
bbox=dict(boxstyle="rarrow, pad=0.3, head_angle=30"))
34+
plt.text(0.8, 0.2, "RArrow", ha='center', size=16,
35+
bbox=dict(boxstyle="rarrow, pad=0.3, head_width=2, head_angle=-90"))
36+
37+
plt.show()

lib/matplotlib/patches.pyi

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,11 @@ class BoxStyle(_Style):
381381

382382
class RArrow(BoxStyle):
383383
pad: float
384-
def __init__(self, pad: float = ...) -> None: ...
384+
head_width: float
385+
head_angle: float
386+
def __init__(
387+
self, pad: float = ..., head_width: float = ..., head_angle: float = ...
388+
) -> None: ...
385389
def __call__(
386390
self,
387391
x0: float,
@@ -403,7 +407,11 @@ class BoxStyle(_Style):
403407

404408
class DArrow(RArrow):
405409
pad: float
406-
def __init__(self, pad: float = ...) -> None: ...
410+
head_width: float
411+
head_angle: float
412+
def __init__(
413+
self, pad: float = ..., head_width: float = ..., head_angle: float = ...
414+
) -> None: ...
407415
def __call__(
408416
self,
409417
x0: float,
47.3 KB
Loading
-7.35 KB
Loading

lib/matplotlib/tests/test_arrow_patches.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,48 @@ def test_boxarrow():
4949
bbox=dict(boxstyle=stylename, fc="w", ec="k"))
5050

5151

52+
@image_comparison(['boxarrow_adjustment_test_image.png'], style='mpl20')
53+
def test_boxarrow_adjustment():
54+
55+
styles = ['larrow', 'rarrow', 'darrow']
56+
57+
# Cases [head_width, head_angle] to test for each arrow style
58+
cases = [
59+
[1.5, 90],
60+
[1.5, 170], # Test dynamic padding
61+
[0.75, 30],
62+
[0.5, -10], # Should just give a rectangle
63+
[2, -90],
64+
[2, -15] # None of arrow body is outside of head
65+
]
66+
67+
# Horizontal and vertical spacings of arrow centres
68+
spacing_horizontal = 3.75
69+
spacing_vertical = 1.6
70+
71+
# Numbers of styles and cases
72+
m = len(styles)
73+
n = len(cases)
74+
75+
figwidth = (m * spacing_horizontal)
76+
figheight = (n * spacing_vertical) + .5
77+
78+
fig = plt.figure(figsize=(figwidth / 1.5, figheight / 1.5))
79+
80+
fontsize = 0.3 * 72
81+
82+
for i, stylename in enumerate(styles):
83+
for j, case in enumerate(cases):
84+
# Draw arrow
85+
fig.text(
86+
((m - i) * spacing_horizontal - 1.5) / figwidth,
87+
((n - j) * spacing_vertical - 0.5) / figheight,
88+
stylename, ha='center', va='center',
89+
size=fontsize, transform=fig.transFigure,
90+
bbox=dict(boxstyle=f"{stylename}, head_width={case[0]}, \
91+
head_angle={case[1]}", fc="w", ec="k"))
92+
93+
5294
def __prepare_fancyarrow_dpi_cor_test():
5395
"""
5496
Convenience function that prepares and returns a FancyArrowPatch. It aims

0 commit comments

Comments
 (0)