私は自分に合ったものを思いつきました。灰色の破線に注意してください。

回転は手動で設定する必要がありますが、これはdraw()
レイアウト後に行う必要があります。したがって、私の解決策は、行を注釈に関連付けてから、それらを繰り返し処理してこれを行うことです:
- 行のデータ変換を取得します (つまり、データ座標から表示座標に移動します)
- 線に沿って 2 点を変換して座標を表示する
- 表示された直線の傾きを求める
- この勾配に一致するようにテキストの回転を設定します
回転されたテキストの matplotlib の処理がすべて間違っているため、これは完璧ではありません。テキストのベースラインではなく、境界ボックスによって整列されます。
テキストのレンダリングに興味がある場合のフォントの基本: http://docs.oracle.com/javase/tutorial/2d/text/fontconcepts.html
この例は、matplotlib の機能を示しています: http://matplotlib.org/examples/pylab_examples/text_rotation.html
行の横にラベルを適切に配置する唯一の方法は、垂直方向と水平方向の両方で中央に揃えることです。次に、ラベルが重ならないように左に 10 ポイントずらします。私のアプリケーションには十分です。
これが私のコードです。必要に応じて線を描画し、注釈を描画してから、ヘルパー関数でそれらをバインドします。
line, = fig.plot(xdata, ydata, '--', color=color)
# x,y appear on the midpoint of the line
t = fig.annotate("text", xy=(x, y), xytext=(-10, 0), textcoords='offset points', horizontalalignment='left', verticalalignment='bottom', color=color)
text_slope_match_line(t, x, y, line)
次に、レイアウトの後、前に別のヘルパー関数を呼び出します(インタラクティブな画像の場合、描画イベントに登録してハンドラーsavefig
を呼び出す必要があると思います)update_text_slopes
plt.tight_layout()
update_text_slopes()
ヘルパー:
rotated_labels = []
def text_slope_match_line(text, x, y, line):
global rotated_labels
# find the slope
xdata, ydata = line.get_data()
x1 = xdata[0]
x2 = xdata[-1]
y1 = ydata[0]
y2 = ydata[-1]
rotated_labels.append({"text":text, "line":line, "p1":numpy.array((x1, y1)), "p2":numpy.array((x2, y2))})
def update_text_slopes():
global rotated_labels
for label in rotated_labels:
# slope_degrees is in data coordinates, the text() and annotate() functions need it in screen coordinates
text, line = label["text"], label["line"]
p1, p2 = label["p1"], label["p2"]
# get the line's data transform
ax = line.get_axes()
sp1 = ax.transData.transform_point(p1)
sp2 = ax.transData.transform_point(p2)
rise = (sp2[1] - sp1[1])
run = (sp2[0] - sp1[0])
slope_degrees = math.degrees(math.atan(rise/run))
text.set_rotation(slope_degrees)