wxPython matplotlib - 检测在3D线图上单击了哪条线

时间:2012-05-27 21:14:17

标签: wxpython matplotlib

我使用this example code作为我的起始代码

此代码生成条形图。当用户单击条形图上的实际条形时,将触发事件并显示单个条形的边界框坐标。这发生在on_pick函数中。

我修改了代码而不是条形图,我有一个Axes3D line plot。我在这个XYZ坐标系上绘制了几条单独的线。我需要的是识别点击了哪一行。看起来边界框不适用于3D绘图,就像使用条形图一样。

我已经查看了pick_event文档,但未能找到解决方案。我可以简单地检测点击位置的x,y坐标,但由于绘图可以以任何角度旋转,因此检测实际点击哪条线似乎很困难,特别是因为它们可以根据视点重叠。

感谢您的时间和帮助!

1 个答案:

答案 0 :(得分: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()