|
| 1 | +""" |
| 2 | +=================================== |
| 3 | +Angle annotations on bracket arrows |
| 4 | +=================================== |
| 5 | +
|
| 6 | +This example shows how to add angle annotations to bracket arrow styles |
| 7 | +created using `.FancyArrowPatch`. *angleA* and *angleB* are measured from a |
| 8 | +vertical line as positive (to the left) or negative (to the right). Blue |
| 9 | +`.FancyArrowPatch` arrows indicate the directions of *angleA* and *angleB* |
| 10 | +from the vertical and axes text annotate the angle sizes. |
| 11 | +""" |
| 12 | + |
| 13 | +import matplotlib.pyplot as plt |
| 14 | +import numpy as np |
| 15 | +from matplotlib.patches import FancyArrowPatch |
| 16 | + |
| 17 | + |
| 18 | +def get_point_of_rotated_vertical(origin, line_length, degrees): |
| 19 | + """Return xy coordinates of the vertical line end rotated by degrees.""" |
| 20 | + rad = np.deg2rad(-degrees) |
| 21 | + return [origin[0] + line_length * np.sin(rad), |
| 22 | + origin[1] + line_length * np.cos(rad)] |
| 23 | + |
| 24 | + |
| 25 | +fig, ax = plt.subplots(figsize=(8, 7)) |
| 26 | +ax.set(xlim=(0, 6), ylim=(-1, 4)) |
| 27 | +ax.set_title("Orientation of the bracket arrows relative to angleA and angleB") |
| 28 | + |
| 29 | +for i, style in enumerate(["]-[", "|-|"]): |
| 30 | + for j, angle in enumerate([-40, 60]): |
| 31 | + y = 2*i + j |
| 32 | + arrow_centers = ((1, y), (5, y)) |
| 33 | + vlines = ((1, y + 0.5), (5, y + 0.5)) |
| 34 | + anglesAB = (angle, -angle) |
| 35 | + bracketstyle = f"{style}, angleA={anglesAB[0]}, angleB={anglesAB[1]}" |
| 36 | + bracket = FancyArrowPatch(*arrow_centers, arrowstyle=bracketstyle, |
| 37 | + mutation_scale=42) |
| 38 | + ax.add_patch(bracket) |
| 39 | + ax.text(3, y + 0.05, bracketstyle, ha="center", va="bottom") |
| 40 | + ax.vlines([i[0] for i in vlines], [y, y], [i[1] for i in vlines], |
| 41 | + linestyles="--", color="C0") |
| 42 | + # Get the top coordinates for the drawn patches at A and B |
| 43 | + patch_tops = [get_point_of_rotated_vertical(center, 0.5, angle) |
| 44 | + for center, angle in zip(arrow_centers, anglesAB)] |
| 45 | + # Define the connection directions for the annotation arrows |
| 46 | + connection_dirs = (1, -1) if angle > 0 else (-1, 1) |
| 47 | + # Add arrows and annotation text |
| 48 | + arrowstyle = "Simple, tail_width=0.5, head_width=4, head_length=8" |
| 49 | + for vline, dir, patch_top, angle in zip(vlines, connection_dirs, |
| 50 | + patch_tops, anglesAB): |
| 51 | + kw = dict(connectionstyle=f"arc3,rad={dir * 0.5}", |
| 52 | + arrowstyle=arrowstyle, color="C0") |
| 53 | + ax.add_patch(FancyArrowPatch(vline, patch_top, **kw)) |
| 54 | + ax.text(vline[0] - dir * 0.15, y + 0.3, f'{angle}°', ha="center", |
| 55 | + va="center") |
| 56 | + |
| 57 | +############################################################################# |
| 58 | +# |
| 59 | +# .. admonition:: References |
| 60 | +# |
| 61 | +# The use of the following functions, methods, classes and modules is shown |
| 62 | +# in this example: |
| 63 | +# |
| 64 | +# - `matplotlib.patches.ArrowStyle` |
0 commit comments