title: Draw rounded fancyarrowpatch with midpoint arrow in matplotlib
body: <p>I've been trying to push the boundaries of matplotlib's patches and instruct it to draw a rounded <code>FancyArrowPatch</code> with a directional arrow on its midpoint. This would prove incredibly useful in a network representation I am trying to create. </p>
  
  <p>My coding hours with python are not yet in the double digit, so I can't say I have a clear understanding of matplotlib's patches.py, but I have narrowed down the solution to two possible strategies:</p>
  
  <ol>
  <li>the smart, possibly pythonic way: create a custom <code>arrowstyle</code> class which further requires a modification of the <code>_get_arrow_wedge()</code> function to include a midpoint coordinates. This may be beyond my possibilities for now, or</li>
  <li>the lazy way: extract the midpoint coordinates from an elicited FancyArrowPatch and draw the desired <code>arrowstyle</code> on such coordinates.</li>
  </ol>
  
  <p>Of course, so far I've chosen the lazy way. I did some early experimenting with extracting the midpoint coordinates of a curved <code>FancyArrowPatch</code> using <code>get_path()</code> and <code>get_path_in_displaycoord()</code>, but I can't seem to predict the precise midpoint coordinates. Some help would be very appreciated.</p>
  
  <p>My fiddling so far:</p>
  
  <pre><code>import matplotlib.pyplot as plt
  from matplotlib.patches import FancyArrowPatch
  
  n1 = (2,3)
  n2 = (4,6)
  
  
  # Try with multiple arc radius sizes, draw a separate plot each time
  for rad in range(20):
      #setup figure
      figure = plt.figure()
      ax = plt.subplot(111)
      plt.annotate('rad:' + str(rad/25.),xy=(2,5))
  
      # create rounded fancyarrowpatch   
      t = FancyArrowPatch(posA=n1,posB=n2,
                          connectionstyle='arc3,rad=%s'%float(rad/25.),
                          arrowstyle='-&gt;',
                          shrinkA=0,
                          shrinkB=0,
                          mutation_scale=0.5)
  
      # extract vertices from get_path: points P#
      path = t.get_path().vertices.tolist()
      lab, px, py = ['P{0}'.format(i) for i in range(len(path))], [u[0] for u in path],[u[1] for u in path]
      for i in range(len(path)):
          plt.annotate(lab[i],xy=(px[i],py[i]))
  
      # extract vertices from get_path_in_displaycoord (but they are useless) : points G#
      newpath = t.get_path_in_displaycoord()
      a,b = newpath[0][0].vertices.tolist(), newpath[0][1].vertices.tolist()
      a.extend(b)
      glab, gx, gy = ['G{0}'.format(i) for i in range(len(a))], [u[0] for u in a],[u[1] for u in a]
      for i in range(len(a)):
          plt.annotate(glab[i],xy=(gx[i],gy[i]))    
  
      #point A: start
      x1, y1 = n1
      plt.annotate('A',xy=(x1,y1))    
  
      #point B:end
      x2, y2 = n2
      plt.annotate('B',xy=(x2,y2))
  
      #point M: the 'midpoint' as defined by class Arc3, specifically its connect() function
      x12, y12 = (x1 + x2) / 2., (y1 + y2) / 2.
      dx, dy = x2 - x1, y2 - y1
      cx, cy = x12 + (rad/100.) * dy, y12 - (rad/100.) * dx    
      plt.annotate('M',xy=(cx,cy))
  
      #point O : midpoint between M and P1, the second vertex from get_path   
      mx,my = (cx + px[1])/2., (cy + py[1])/2.
      plt.annotate('O',xy=(mx,my))
  
      ax.add_patch(t)
      plt.scatter([x1,cx,x2,mx,gx].extend(px),[y1,cy,y2,my,gy].extend(py))
  
  
  plt.show()
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/61hcc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/61hcc.png" alt="objective"></a></p>
  
  <p>EDIT: taking onboard @cphlewis suggestions: I tried to reconstruct the Bezier curve:</p>
  
  <pre><code>def bezcurv(start,control,end,tau):
      ans = []
      for t in tau:
          B = [(1-t)**2 * start[i] + 2*(1-t)*t*end[i] + (t**2)*control[i] for i in range(len(start))]
          ans.append(tuple(B))
      return ans
  </code></pre>
  
  <p>I thus add the generated line to the original plot:</p>
  
  <pre><code>tau = [time/100. for time in range(101)]
  bezsim = bezcurv(n1,n2,(cx,cy),tau)
  simx,simy = [b[0] for b in bezsim], [b[1] for b in bezsim]
  </code></pre>
  
  <p>The green line below is (should be?) the reconstructed bezier curve, though it's clearly not.
  <a href="https://i.stack.imgur.com/61wnc.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/61wnc.png" alt="attempt at bezier curve reconstruction"></a></p>