Length is in arrow width units.
(self, length)
| 719 | return XY |
| 720 | |
| 721 | def _h_arrows(self, length): |
| 722 | """Length is in arrow width units.""" |
| 723 | # It might be possible to streamline the code |
| 724 | # and speed it up a bit by using complex (x, y) |
| 725 | # instead of separate arrays; but any gain would be slight. |
| 726 | minsh = self.minshaft * self.headlength |
| 727 | N = len(length) |
| 728 | length = length.reshape(N, 1) |
| 729 | # This number is chosen based on when pixel values overflow in Agg |
| 730 | # causing rendering errors |
| 731 | # length = np.minimum(length, 2 ** 16) |
| 732 | np.clip(length, 0, 2 ** 16, out=length) |
| 733 | # x, y: normal horizontal arrow |
| 734 | x = np.array([0, -self.headaxislength, |
| 735 | -self.headlength, 0], |
| 736 | np.float64) |
| 737 | x = x + np.array([0, 1, 1, 1]) * length |
| 738 | y = 0.5 * np.array([1, 1, self.headwidth, 0], np.float64) |
| 739 | y = np.repeat(y[np.newaxis, :], N, axis=0) |
| 740 | # x0, y0: arrow without shaft, for short vectors |
| 741 | x0 = np.array([0, minsh - self.headaxislength, |
| 742 | minsh - self.headlength, minsh], np.float64) |
| 743 | y0 = 0.5 * np.array([1, 1, self.headwidth, 0], np.float64) |
| 744 | ii = [0, 1, 2, 3, 2, 1, 0, 0] |
| 745 | X = x[:, ii] |
| 746 | Y = y[:, ii] |
| 747 | Y[:, 3:-1] *= -1 |
| 748 | X0 = x0[ii] |
| 749 | Y0 = y0[ii] |
| 750 | Y0[3:-1] *= -1 |
| 751 | shrink = length / minsh if minsh != 0. else 0. |
| 752 | X0 = shrink * X0[np.newaxis, :] |
| 753 | Y0 = shrink * Y0[np.newaxis, :] |
| 754 | short = np.repeat(length < minsh, 8, axis=1) |
| 755 | # Now select X0, Y0 if short, otherwise X, Y |
| 756 | np.copyto(X, X0, where=short) |
| 757 | np.copyto(Y, Y0, where=short) |
| 758 | if self.pivot == 'middle': |
| 759 | X -= 0.5 * X[:, 3, np.newaxis] |
| 760 | elif self.pivot == 'tip': |
| 761 | # numpy bug? using -= does not work here unless we multiply by a |
| 762 | # float first, as with 'mid'. |
| 763 | X = X - X[:, 3, np.newaxis] |
| 764 | elif self.pivot != 'tail': |
| 765 | _api.check_in_list(["middle", "tip", "tail"], pivot=self.pivot) |
| 766 | |
| 767 | tooshort = length < self.minlength |
| 768 | if tooshort.any(): |
| 769 | # Use a heptagonal dot: |
| 770 | th = np.arange(0, 8, 1, np.float64) * (np.pi / 3.0) |
| 771 | x1 = np.cos(th) * self.minlength * 0.5 |
| 772 | y1 = np.sin(th) * self.minlength * 0.5 |
| 773 | X1 = np.repeat(x1[np.newaxis, :], N, axis=0) |
| 774 | Y1 = np.repeat(y1[np.newaxis, :], N, axis=0) |
| 775 | tooshort = np.repeat(tooshort, 8, 1) |
| 776 | np.copyto(X, X1, where=tooshort) |
| 777 | np.copyto(Y, Y1, where=tooshort) |
| 778 | # Mask handling is deferred to the caller, _make_verts. |