0

このサンプルコードを開始コードとして使用しています

このコードは棒グラフを生成します。ユーザーが棒グラフの実際の棒をクリックすると、イベントがトリガーされ、個々の棒の境界ボックスの座標が表示されます。これはon_pick関数で発生します。

コードを変更したので、棒グラフの代わりにAxes3D折れ線グラフがあります。このXYZ座標系にいくつかの別々の線がプロットされています。必要なのは、どの行がクリックされたかを認識することです。バウンディングボックスは、棒グラフの場合のように3Dプロットでは機能しないようです。

pick_eventのドキュメントを調べましたが、解決策を見つけることができませんでした。クリックした位置のx、y座標を簡単に検出できますが、プロットは任意の角度で回転できるため、特に視点によっては重なる可能性があるため、実際にクリックされた線を検出するのは非常に難しいようです。

私はあなたの時間と助けに感謝します!

4

1 に答える 1

2

どの曲線がクリックされたかだけを知る必要がある場合は、それほど難しくありません。マウスの位置が曲線に十分近いかどうかを確認するには、line_picker() を作成する必要があります。

line_picker() は、点と線分の間の距離を計算する必要があります。これは少し難しいですが、曲線の線形補間を使用してこの問題を回避します。

コードは次のとおりです。曲線を 2000 ポイントで補間し、曲線に対するマウスの位置が 5 ピクセル未満の場合、曲線が選択されます。

import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt

def line_picker(line, me):
    if me.xdata is None: return False, dict()    
    x, y = me.x, me.y
    xdata, ydata = line.axes.transData.transform(np.array(line.get_data()).T).T
    index = np.arange(len(xdata))
    index2 = np.linspace(0, index[-1], 2000)
    xdata2 = np.interp(index2, index, xdata)
    ydata2 = np.interp(index2, index, ydata)
    d = np.sqrt((xdata2-x)**2. + (ydata2-y)**2.)
    if np.min(d) < 5:
        return True, {}
    else:
        return False, {}

mpl.rcParams['legend.fontsize'] = 10

fig = plt.figure()
ax = fig.gca(projection='3d')
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
line1 = ax.plot(x, y, z, label='parametric curve', picker=line_picker)[0]

t = np.linspace(-1, 1, 100) 
x = 4*np.sin(10*t)
y = 4*np.cos(10*t)
z = t**2*5-3

line2 = ax.plot(x, y, z, label="second", picker=line_picker)[0]

ax.legend()

def onpick(event):
    print [line1, line2].index(event.artist)

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()
于 2012-05-28T01:33:35.997 に答える