6464
6565Keyword arguments:
6666
67- *units*: ['width' | 'height' | 'dots' | 'inches' | 'x' | 'y' ]
67+ *units*: ['width' | 'height' | 'dots' | 'inches' | 'x' | 'y' | 'xy' ]
6868 arrow units; the arrow dimensions *except for length* are in
6969 multiples of this unit.
7070
@@ -518,17 +518,33 @@ def _set_transform(self):
518518 self .set_transform (trans )
519519 return trans
520520
521- def _angles (self , U , V , eps = 0.001 ):
521+ def _angles_lengths (self , U , V , eps = 1 ):
522522 xy = self .ax .transData .transform (self .XY )
523523 uv = np .hstack ((U [:,np .newaxis ], V [:,np .newaxis ]))
524524 xyp = self .ax .transData .transform (self .XY + eps * uv )
525525 dxy = xyp - xy
526- ang = np .arctan2 (dxy [:,1 ], dxy [:,0 ])
527- return ang
526+ angles = np .arctan2 (dxy [:,1 ], dxy [:,0 ])
527+ lengths = np .absolute (dxy [:,0 ] + dxy [:,1 ]* 1j ) / eps
528+ return angles , lengths
529+
530+
528531
529532 def _make_verts (self , U , V ):
530533 uv = (U + V * 1j )
531- a = np .absolute (uv )
534+ if self .angles == 'xy' and self .scale_units == 'xy' :
535+ # Here eps is 1 so that if we get U, V by diffing
536+ # the X, Y arrays, the vectors will connect the
537+ # points, regardless of the axis scaling (including log).
538+ angles , lengths = self ._angles_lengths (U , V , eps = 1 )
539+ elif self .angles == 'xy' or self .scale_units == 'xy' :
540+ # We could refine this by calculating eps based on
541+ # the magnitude of U, V relative to that of X, Y,
542+ # to ensure we are always making small shifts in X, Y.
543+ angles , lengths = self ._angles_lengths (U , V , eps = 0.001 )
544+ if self .scale_units == 'xy' :
545+ a = lengths
546+ else :
547+ a = np .absolute (uv )
532548 if self .scale is None :
533549 sn = max (10 , math .sqrt (self .N ))
534550 if self .Umask is not ma .nomask :
@@ -543,14 +559,17 @@ def _make_verts(self, U, V):
543559 self .scale = scale
544560 widthu_per_lenu = 1.0
545561 else :
546- dx = self ._dots_per_unit (self .scale_units )
562+ if self .scale_units == 'xy' :
563+ dx = 1
564+ else :
565+ dx = self ._dots_per_unit (self .scale_units )
547566 widthu_per_lenu = dx / self ._trans_scale
548567 if self .scale is None :
549568 self .scale = scale * widthu_per_lenu
550569 length = a * (widthu_per_lenu / (self .scale * self .width ))
551570 X , Y = self ._h_arrows (length )
552571 if self .angles == 'xy' :
553- theta = self . _angles ( U , V )
572+ theta = angles
554573 elif self .angles == 'uv' :
555574 theta = np .angle (uv )
556575 else :
0 commit comments