从my previous question开始,我在图形分数坐标中有文本标签框的坐标,并尝试以相同的方式获取箭头补丁的坐标。
但是我得到的坐标与箭头不对应,因为当我在同一坐标上绘制一条线时,它不会位于它上面:
import numpy as np
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
def f(x):
return 10 * np.sin(3*x)**4
x = np.linspace(0, 2*np.pi, 100)
y = f(x)
fig, ax = plt.subplots()
ax.plot(x,y)
xpt = 1.75
ypt = f(xpt)
xy = ax.transData.transform([xpt, ypt])
xy = fig.transFigure.inverted().transform(xy)
xytext = xy + [0.1, -0.1]
rdx, rdy = 0, 1
ann = ax.annotate('A point', xy=xy, xycoords='figure fraction',
xytext=xytext, textcoords='figure fraction',
arrowprops=dict(arrowstyle='->', connectionstyle="arc3",
relpos=(rdx, rdy)),
bbox=dict(fc='gray', edgecolor='k', alpha=0.5),
ha='left', va='top'
)
fig.canvas.draw()
leader_line_box = ann.arrow_patch.get_extents()
print(leader_line_box)
leader_line_box = fig.transFigure.inverted().transform(leader_line_box)
print(leader_line_box)
from matplotlib.lines import Line2D
line = Line2D(leader_line_box.T[0], leader_line_box.T[1],transform=fig.transFigure, lw=2, color='m')
ax.add_line(line)
plt.savefig('test.png')
如何以图形分数单位获取注释箭头的((x0,y0), (x1,y1))
坐标以及我在此处尝试出错的地方?
答案 0 :(得分:2)
在这种非常具体的情况下,最简单的方法就是反向绘制x坐标
[warn] Foo
[warn] Runner.Foo
I am Bar
I am Runner.Foo
[warn] Foo2
I am Bar
I am Foo2
如果您需要更通用的解决方案,
line = Line2D(leader_line_box.T[0][::-1], leader_line_box.T[1],transform=fig.transFigure, lw=2, color='m')
这适用于任何箭头方向(向上或向下,向东或向西),但特定于verts = ann.arrow_patch.get_path()._vertices
tverts= fig.transFigure.inverted().transform(verts)
index = [0,2]
line = Line2D([tverts[index[0],0],tverts[index[1],0]], [tverts[index[0],1],tverts[index[1],1]],
transform=fig.transFigure, lw=2, color='m')
ax.add_line(line)
参数arrowprops
和arrowstyle='->'
。使用不同的箭头样式或连接样式需要将connectionstyle="arc3"
设置为不同的值,这些值可以通过从index
中存储的数组中选择适当的索引来找到。
<小时/> 在一般情况下,您还可以查看以下内容:
verts
然而,这将使您获得注释点和文本本身之间的界限。通常,此行可能与实际箭头不同,具体取决于使用的箭头样式。
答案 1 :(得分:1)
You're almost there, you have the coordinates of the bounding box of the arrow, which is the box drawn using the arrow as the diagonal. From that, we can find the head / tail coordinates.
The bounding box coordinates are given in the order [[left, bottom], [right, top]]
. Here, the arrow head is at the top left, and tail is bottom right. So we can draw two lines to visually mark these. Replacing that section in your code with this:
from matplotlib.lines import Line2D
dl = 0.01 # some arbitrary length for the marker line
head = [leader_line_box.T[0][0], leader_line_box.T[1][1]]
line_head = Line2D([head[0],head[0]+dl], [head[1],head[1]+dl],
transform=fig.transFigure, lw=2, color='r') # mark head with red
ax.add_line(line_head)
tail = [leader_line_box.T[0][1], leader_line_box.T[1][0]]
line_tail = Line2D([tail[0],tail[0]+dl], [tail[1],tail[1]+dl],
transform=fig.transFigure, lw=2, color='g') # mark tail with green
ax.add_line(line_tail)
results in the following plot:
时出错