Matplotlib scatter 3D button_press_event 根据子图上的散点轴位置给出错误的索引

问题描述

我在 3D 散点图上显示了一些点,我想突出显示被点击的点。但是 ind["ind"][0] 根据图表上 x 轴(顶部或底部)或 y 轴(左侧或右侧)的位置给出了所选点的错误索引。因此,突出显示的不是我点击的那个。

问候,

马特

import matplotlib.pyplot as plt
import numpy as np

Lx = 0.8
Ly = 0.5
n = 10
Nx = 8
Ny = 5
x = np.linspace(0,Lx,Nx)
y = np.linspace(0,Ly,Ny)

X,Y = np.meshgrid(x,y)

#visualisaiton 3D
fig = plt.figure('Visualisation 3D')
ax2 = plt.subplot(1,1,projection='3d')

ac_x,ac_y = 1,1

sc = ax2.scatter(X.ravel(),Y.ravel(),np.zeros(Nx * Ny),picker=True)
ac = ax2.scatter(x[ac_x],y[ac_y],'r',s=50)

def click(event,ind):
    i = ind["ind"][0]
    xx,yy,zz = sc._offsets3d

    def find_nearest(array,value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return idx

    ac_x = np.where(x == xx[i])[0]
    ac_y = np.where(y == yy[i])[0]

    print('xx[i],yy[i]: (%.2f,%.2f)' % (xx[i],yy[i]))

    print('Click at: (%.2f,yy[i]))
    print('%s click: button=%d,x=%d,y=%d,xdata=%f,ydata=%f' %
          ('double' if event.dblclick else 'single',event.button,event.x,event.y,event.xdata,event.ydata))

    ac_act = ax2.scatter(x[ac_x],s=50)

    print('index (%d,%d) position: (%.2f,%.2f)' % (ac_x,ac_y,x[ac_x],y[ac_y]))

def on_click(event):
    if event.inaxes == ax2:
        cont2,ind2 = sc.contains(event)
        if cont2:
            click(event,ind2)
            fig.canvas.draw_idle()

fig.canvas.mpl_connect('button_press_event',on_click)


plt.show()

工作示例:

enter image description here

不工作:

enter image description here

解决方法

我在从 Path3DCollection 获取正确索引时也遇到了一些麻烦。经过一番挖掘,我发现数据数组是根据 z 坐标重新排序的。要获取原始索引,您需要访问成员_z_markers_idx,不幸的是该成员受到保护。

在文件中:

mpl_toolkits\mplot3d\art3d.py

我向 Path3DCollection 类添加了以下 getter:

def get_z_markers_idx(self):
    return self._z_markers_idx

然后您就可以通过以下方式获取正确的索引:

def click(event,ind):
    i = sc.get_z_markers_idx()[ind["ind"][0]]