2016-12-22 2 views
1

my previous question У меня есть координаты поля текстовой метки в координатах фракции фигуры и вы пытались получить координаты патча стрелки таким же образом.Получение координат стрелки в аннотации Matplotlib

Но координаты, которые я получаю, не соответствуют стрелке, потому что, когда я сюжет линию над тем же координатам она не лежит на нем:

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') 

enter image description here

Как может Я получаю ((x0,y0), (x1,y1)) координаты стрелки аннотации в единицах фракции фигур и что пошло не так в моей попытке здесь?

+0

Я думаю, что он делает именно то, что вы говорите, чтобы сделать: построение линии сверху вниз вправо справа от рамки стрелки. Если вы хотите, чтобы строка была выровнена со стрелкой, вы можете просто поместить '[:: - 1]', чтобы отменить либо xdata, либо ydata. Это те координаты, которые вы искали? Где вы хотите, чтобы линия была построена? – whrrgarbl

+0

Хм - Я думаю, ты прав. Я действительно хочу, чтобы координаты хвоста и головы самой стрелки. – xnx

ответ

1

Самый простой способ в этом очень конкретном случае просто рисовать координаты х в обратном

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) 

Это будет работать для любого направления стрелки (направленного вверх или вниз, на восток или на запад), но относится к аргументам arrowpropsarrowstyle='->' и . Использование разных стилей стрелок или соединений потребует установки index для разных значений, которые можно найти, путем выбора соответствующих индексов из массива, хранящегося в verts.


В самом общем случае можно также посмотреть на следующее:

box = ann.arrow_patch._posA_posB 
tbox = fig.transFigure.inverted().transform(leader_line_box) 
print tbox 
line = Line2D(tbox.T[0], tbox.T[1],transform=fig.transFigure) 

Однако это поможет вам линию между аннотированный точкой и самого текста. В общем, эта строка может отличаться от фактической стрелки, в зависимости от используемого стиля стрелки.

1

Вы почти находитесь там, у вас есть координаты ограничивающей рамки стрелки, которая представляет собой коробку, нарисованную стрелкой как диагональ. Отсюда мы можем найти координаты головы/хвоста.

Координаты ограничительной рамки даны в порядке [[left, bottom], [right, top]]. Здесь стрелка находится в верхнем левом углу, а хвост - внизу справа. Таким образом, мы можем нарисовать две строки, чтобы визуально отметить их. Замена этой секции в коде с этим:

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) 

результаты в следующем сюжете:

plot with arrow head and tail marked

Смежные вопросы