Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[ENH]: Having more customization options for the FancyArrow class (specifically different tails) #22344

Open
@mapfiable

Description

Problem

Following my recent erroneous bug report, I think it would be great to have more customization options for the FancyArrow class. More specifically, it would be nice to be able to change the shape of the tail via a simple kwarg, similar to capstyle e.g.

I was also surprised to find that you have much more customization options for the annotation arrow than for a class called FancyArrow. It would be great to also have these options for the FancyArrow class, and e.g. introduce a similar notation like .-|> to get a round tail.

Proposed solution

As suggested by @jklymak, I tried to use a custom Polygon to simulate the effect. Here is my attempt of modifying the FandyArrow class:

class FancierArrow(FancyArrow):
 """
 Like FancyArrow, but lets you choose a round butt.
 """
 def __str__(self):
 return "FancierArrow()"
 def __init__(
 self, x, y, dx, dy, width=0.001, length_includes_head=False,
 head_width=None, head_length=None, shape='full', overhang=0,
 head_starts_at_zero=False, round_tail=False, **kwargs
 ):
 self._round_tail = round_tail
 super().__init__(
 x, y, dx, dy, width=width,
 length_includes_head=length_includes_head,
 head_width=head_width, head_length=head_length, shape=shape,
 overhang=overhang, head_starts_at_zero=head_starts_at_zero,
 **kwargs
 )
 def set_data(
 self, *, x=None, y=None, dx=None, dy=None, width=None,
 head_width=None, head_length=None, round_tail=None,
 ):
 if round_tail is not None:
 self._round_tail = round_tail
 super().__init__(
 x=x, y=y, dx=dx, dy=dy, width=width, head_width=head_width,
 head_length=head_length
 )
 def _make_verts(self):
 super()._make_verts()
 if self._round_tail:
 self._make_tail_round()
 def _make_tail_round(self):
 nvert = 25
 add_rot = np.pi/2
 radius = width/2
 x, y = self._x, self._y
 dx, dy = self._dx, self._dy
 if self._head_starts_at_zero:
 x, y = (self.verts[4] + self.verts[3])/2
 dx, dy = (self.verts[4] - self.verts[3])/2
 add_rot += np.pi/2
 if self._shape in ['left', 'right']:
 radius /= 2
 x, y = (self.verts[4] + self.verts[3])/2
 dx, dy = (self.verts[4] - self.verts[3])/2
 if self._shape == 'left' and not self._head_starts_at_zero:
 add_rot += np.pi/2
 elif self._shape == 'right':
 if self._head_starts_at_zero:
 add_rot += np.pi
 else:
 add_rot -= np.pi/2
 angle = np.arctan2(dx, dy) + add_rot
 circ_segs = np.linspace(0, np.pi, nvert+1) + angle
 tail_verts = np.zeros((nvert, 2), float)
 tail_verts[:, 0] = np.sin(circ_segs)[:-1]*radius + x
 tail_verts[:, 1] = np.cos(circ_segs)[:-1]*radius + y
 if self._shape == 'right':
 tail_verts = tail_verts[::-1]
 self.verts = np.array([*self.verts[:4], *tail_verts, *self.verts[4:]])
fig, ax = plt.subplots(dpi=300)
fig.tight_layout()
width = 0.3
xs = np.sin(np.linspace(0, 2*np.pi, 9))[:-1]
ys = np.cos(np.linspace(0, 2*np.pi, 9))[:-1]
for x, y in zip(xs, ys):
 polygon = FancierArrow(
 x, y, x, y, width=width, edgecolor='black',
 round_tail=True,
 head_starts_at_zero=True,
 shape='left'
 )
 ax.add_patch(polygon)
ax.relim()
ax.autoscale_view()
fig.show()

grafik

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

        AltStyle によって変換されたページ (->オリジナル) /