2012-05-27 21 views
0

哪一行我使用this example code作爲我的起始代碼wxPython的matplotlib - 檢測被點擊的3D線圖

此代碼生成的柱狀圖。當用戶點擊條形圖上的實際條形時,將觸發事件並顯示單個條形的邊框座標。這發生在on_pick函數中。

我修改了代碼,以代替條形圖,我有一個Axes3D line plot。我在這個XYZ座標系上繪製了幾條單獨的線。我需要的是識別哪一行被點擊。看起來,邊界框不適用於三維繪圖,因爲它與條形圖一樣。

我已經查看了pick_event文檔,但一直未能找到解決方案。我可以簡單地檢測點擊位置的x,y座標,但是因爲可以以任意角度旋轉繪圖,所以檢測哪條線實際被點擊是非常困難的,尤其是因爲它們可以根據視點重疊。

我感謝您的時間和幫助!

回答

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() 
+0

非常感謝你,這就是我所需要的。 您可以解釋每個繪圖命令後的[0]是什麼嗎?我對Python很陌生,所以請原諒,如果這很明顯。謝謝! –

+0

plot()返回Line2D對象的列表,直接獲取Line2D對象,我使用[0]。 – HYRY