From e1241a3a08c14026e186922c352e57d0830e3491 Mon Sep 17 00:00:00 2001
From: Abitamim Bharmal <abitamimbharmal@hotmail.com>
Date: Thu, 15 Dec 2022 23:07:31 -0500
Subject: [PATCH 1/4] Make arrow annotation arrowhead adjustable

---
 lib/matplotlib/patches.py | 92 +++++++++++++++++++++++++++++++++++----
 1 file changed, 84 insertions(+), 8 deletions(-)

diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py
index d6a25dfc487c..edd669f9852b 100644
--- a/lib/matplotlib/patches.py
+++ b/lib/matplotlib/patches.py
@@ -2372,14 +2372,35 @@ def __call__(self, x0, y0, width, height, mutation_size):
     class LArrow:
         """A box in the shape of a left-pointing arrow."""
 
-        def __init__(self, pad=0.3):
+        def __init__(self, pad=0.3, head_width=1.5, head_angle=90.0):
             """
             Parameters
             ----------
             pad : float, default: 0.3
                 The amount of padding around the original box.
+            head_width : float, default: 1.5
+                The width of the arrow head versus the body. The minimum value
+                is 0.0 and the maximum value is 10.0. Any value smaller or
+                greater than this is contrained to the edge values.
+            head_angle : float, default: 90.0
+                The inside angle of the tip of the arrow. The minimum value is
+                10.0 and the maximum value is 179.0. Any value smaller or
+                greater than this is contrained to the edge values.
             """
             self.pad = pad
+            if head_width > 10:
+                self.head_width = 10
+            elif head_width < 0:
+                self.head_width = 0
+            else:
+                self.head_width = head_width
+
+            if head_angle >= 180:
+                self.head_angle = 179
+            elif head_angle < 10:
+                self.head_angle = 10
+            else:
+                self.head_angle = head_angle
 
         def __call__(self, x0, y0, width, height, mutation_size):
             # padding
@@ -2394,10 +2415,26 @@ def __call__(self, x0, y0, width, height, mutation_size):
             dxx = dx / 2
             x0 = x0 + pad / 1.4  # adjust by ~sqrt(2)
 
+            # The width adjustment is the value that must be added or
+            # subtracted from y_0 and y_1 for the ends of the head.
+            # The body width is 2dx.
+            # Subtracting 1 from the head_width gives what percentage of the
+            # body width is in the head, and there is .5x of that on each side.
+            # The .5 cancels out the 2dx for the body width.
+            width_adjustment = (self.head_width - 1) * dx
+
+            # The angle adjustment is the value that must be subtracted/added
+            # from x_0 or x_1 for the position of the tip.
+            # each half of the arrow head is a right angle triangle. Therefore,
+            # each half of the arrow head has the equation tan(head_angle/2)=
+            # (dx+width_adjustment)/(dxx+angle_adjustment).
+            angle_adjustment = ((dx + width_adjustment) / math.tan((self.
+                                head_angle/2) * (math.pi/180))) - dxx
+
             return Path._create_closed(
                 [(x0 + dxx, y0), (x1, y0), (x1, y1), (x0 + dxx, y1),
-                 (x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
-                 (x0 + dxx, y0 - dxx),  # arrow
+                 (x0 + dxx, y1 + width_adjustment), (x0 - angle_adjustment, y0
+                 + dx), (x0 + dxx, y0 - width_adjustment),  # arrow
                  (x0 + dxx, y0)])
 
     @_register_style(_style_list)
@@ -2415,14 +2452,35 @@ class DArrow:
         """A box in the shape of a two-way arrow."""
         # Modified from LArrow to add a right arrow to the bbox.
 
-        def __init__(self, pad=0.3):
+        def __init__(self, pad=0.3, head_width=1.5, head_angle=90.0):
             """
             Parameters
             ----------
             pad : float, default: 0.3
                 The amount of padding around the original box.
+            head_width : float, default: 1.5
+                The width of the arrow head versus the body. The minimum value
+                is 0.0 and the maximum value is 10.0. Any value smaller or
+                greater than this is contrained to the edge values.
+            head_angle : float, default: 90.0
+                The inside angle of the tip of the arrow. The minimum value is
+                10.0 and the maximum value is 179.0. Any value smaller or
+                greater than this is contrained to the edge values.
             """
             self.pad = pad
+            if head_width > 10:
+                self.head_width = 10
+            elif head_width < 0:
+                self.head_width = 0
+            else:
+                self.head_width = head_width
+
+            if head_angle >= 180:
+                self.head_angle = 179
+            elif head_angle < 10:
+                self.head_angle = 10
+            else:
+                self.head_angle = head_angle
 
         def __call__(self, x0, y0, width, height, mutation_size):
             # padding
@@ -2438,13 +2496,31 @@ def __call__(self, x0, y0, width, height, mutation_size):
             dxx = dx / 2
             x0 = x0 + pad / 1.4  # adjust by ~sqrt(2)
 
+            # The width adjustment is the value that must be added or
+            # subtracted from y_0 and y_1 for the ends of the head.
+            # The body width is 2dx.
+            # Subtracting 1 from the head_width gives what percentage of the
+            # body width is in the head, and there is .5x of that on each side.
+            # The .5 cancels out the 2dx for the body width.
+            width_adjustment = (self.head_width - 1) * dx
+
+            # The angle adjustment is the value that must be subtracted/added
+            # from x_0 or x_1 for the position of the tip.
+            # each half of the arrow head is a right angle triangle. Therefore,
+            # each half of the arrow head has the equation tan(head_angle/2)=
+            # (dx+width_adjustment)/(dxx+angle_adjustment).
+            angle_adjustment = ((dx + width_adjustment) / math.tan((self.
+                                head_angle/2) * (math.pi/180))) - dxx
+
             return Path._create_closed([
                 (x0 + dxx, y0), (x1, y0),  # bot-segment
-                (x1, y0 - dxx), (x1 + dx + dxx, y0 + dx),
-                (x1, y1 + dxx),  # right-arrow
+                (x1, y0 - width_adjustment),
+                (x1 + angle_adjustment + dxx, y0 + dx),
+                (x1, y1 + width_adjustment),  # right-arrow
                 (x1, y1), (x0 + dxx, y1),  # top-segment
-                (x0 + dxx, y1 + dxx), (x0 - dx, y0 + dx),
-                (x0 + dxx, y0 - dxx),  # left-arrow
+                (x0 + dxx, y1 + width_adjustment),
+                (x0 - angle_adjustment, y0 + dx),
+                (x0 + dxx, y0 - width_adjustment),  # left-arrow
                 (x0 + dxx, y0)])
 
     @_register_style(_style_list)

From 792c229aca59b655c7c4e46126ae8179bc5de79b Mon Sep 17 00:00:00 2001
From: Abitamim Bharmal <abitamimbharmal@hotmail.com>
Date: Thu, 15 Dec 2022 23:07:42 -0500
Subject: [PATCH 2/4] Add test - not sure if correct

---
 .../roadsign_test_image.png                   | Bin 0 -> 10660 bytes
 lib/matplotlib/tests/test_arrow_patches.py    |  21 ++++++++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 lib/matplotlib/tests/baseline_images/test_arrow_patches/roadsign_test_image.png

diff --git a/lib/matplotlib/tests/baseline_images/test_arrow_patches/roadsign_test_image.png b/lib/matplotlib/tests/baseline_images/test_arrow_patches/roadsign_test_image.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9cf3646b5857078f0df436313c15f3bd78a81fe
GIT binary patch
literal 10660
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
B6f^(;

literal 0
HcmV?d00001

diff --git a/lib/matplotlib/tests/test_arrow_patches.py b/lib/matplotlib/tests/test_arrow_patches.py
index 8d573b4adb1b..9d38111b19ff 100644
--- a/lib/matplotlib/tests/test_arrow_patches.py
+++ b/lib/matplotlib/tests/test_arrow_patches.py
@@ -47,6 +47,27 @@ def test_boxarrow():
                  transform=fig.transFigure,
                  bbox=dict(boxstyle=stylename, fc="w", ec="k"))
 
+@image_comparison(['roadsign_test_image.png'])
+def temp_test_boxarrow():
+
+    styles = mpatches.BoxStyle.get_styles()
+
+    n = len(styles)
+    spacing = 1.2
+
+    figheight = (n * spacing + .5)
+    fig = plt.figure(figsize=(4 / 1.5, figheight / 1.5))
+
+    fontsize = 0.3 * 72
+
+    for i, stylename in enumerate(sorted(styles)):
+        if stylename in ("larrow", "rarrow", "darrow"):
+            fig.text(0.5, ((n - i) * spacing - 0.5)/figheight, stylename,
+                    ha="center",
+                    size=fontsize,
+                    transform=fig.transFigure,
+                    bbox=dict(boxstyle=stylename+",head_width=1", fc="w", ec="k"))
+
 
 def __prepare_fancyarrow_dpi_cor_test():
     """

From 0e890ece5cdf638b2cad1554fb9f16d97968f7bd Mon Sep 17 00:00:00 2001
From: Abitamim Bharmal <abitamimbharmal@hotmail.com>
Date: Thu, 15 Dec 2022 23:14:49 -0500
Subject: [PATCH 3/4] Update tutorial

---
 tutorials/text/annotations.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tutorials/text/annotations.py b/tutorials/text/annotations.py
index bee2e244238d..8cb1239e56c8 100644
--- a/tutorials/text/annotations.py
+++ b/tutorials/text/annotations.py
@@ -192,10 +192,10 @@
 #   Class        Name             Attrs
 #   ==========   ==============   ==========================
 #   Circle       ``circle``       pad=0.3
-#   DArrow       ``darrow``       pad=0.3
+#   DArrow       ``darrow``       pad=0.3,head_width=1.5,head_angle=90
 #   Ellipse      ``ellipse``      pad=0.3
-#   LArrow       ``larrow``       pad=0.3
-#   RArrow       ``rarrow``       pad=0.3
+#   LArrow       ``larrow``       pad=0.3,head_width=1.5,head_angle=90
+#   RArrow       ``rarrow``       pad=0.3,head_width=1.5,head_angle=90
 #   Round        ``round``        pad=0.3,rounding_size=None
 #   Round4       ``round4``       pad=0.3,rounding_size=None
 #   Roundtooth   ``roundtooth``   pad=0.3,tooth_size=None
@@ -254,8 +254,8 @@ def custom_box_style(x0, y0, width, height, mutation_size):
     x0, y0 = x0 - pad, y0 - pad
     x1, y1 = x0 + width, y0 + height
     # return the new path
-    return Path([(x0, y0), (x1, y0), (x1, y1), (x0, y1),
-                 (x0-pad, (y0+y1)/2), (x0, y0), (x0, y0)],
+    return Path([(x0, y0), (x1, y0), (x1, y1), (x0, y1), (x0, y1-pad),
+                 (x0-pad, (y0+y1)/2), (x0, y0+pad), (x0, y0), (x0, y0)],
                 closed=True)
 
 fig, ax = plt.subplots(figsize=(3, 3))

From 94907fe2dd17a5e2dd8c0d04efd60816653dc63f Mon Sep 17 00:00:00 2001
From: Abitamim Bharmal <abitamimbharmal@hotmail.com>
Date: Thu, 15 Dec 2022 23:44:37 -0500
Subject: [PATCH 4/4] Fixed linting

---
 lib/matplotlib/tests/test_arrow_patches.py | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/matplotlib/tests/test_arrow_patches.py b/lib/matplotlib/tests/test_arrow_patches.py
index 9d38111b19ff..bf71bc4a674c 100644
--- a/lib/matplotlib/tests/test_arrow_patches.py
+++ b/lib/matplotlib/tests/test_arrow_patches.py
@@ -47,6 +47,7 @@ def test_boxarrow():
                  transform=fig.transFigure,
                  bbox=dict(boxstyle=stylename, fc="w", ec="k"))
 
+
 @image_comparison(['roadsign_test_image.png'])
 def temp_test_boxarrow():
 
@@ -63,10 +64,11 @@ def temp_test_boxarrow():
     for i, stylename in enumerate(sorted(styles)):
         if stylename in ("larrow", "rarrow", "darrow"):
             fig.text(0.5, ((n - i) * spacing - 0.5)/figheight, stylename,
-                    ha="center",
-                    size=fontsize,
-                    transform=fig.transFigure,
-                    bbox=dict(boxstyle=stylename+",head_width=1", fc="w", ec="k"))
+                        ha="center",
+                        size=fontsize,
+                        transform=fig.transFigure,
+                        bbox=dict(boxstyle=stylename+",head_width=1", fc="w",
+                                    ec="k"))
 
 
 def __prepare_fancyarrow_dpi_cor_test():