简体   繁体   English

在选择事件上注释 3D scatter plot

[英]Annotate 3D scatter plot on pick event

I want to show annotations on a 3D scatter plot when the user clicks on a point.当用户单击一个点时,我想在 3D 分散 plot 上显示注释。

The code I have shows the annotation once I move the plot after I click on a point.在我单击一个点后移动 plot后,我的代码会显示注释。

from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')

x = [1, 2, 3]
y = [1, 2, 3]
z = [1, 2, 3]

scatter = ax.scatter(x,y,z,picker=True)

def annotate_onclick(event):

    point_index = int(event.ind)
    print(point_index)

    proj = ax.get_proj()

    x_p, y_p, _ = proj3d.proj_transform(x[point_index], y[point_index], z[point_index], proj)

    plt.annotate(str(point_index), xy=(x_p, y_p))


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

plt.show()

How can I make the annotation appear as soon as the user clicks on a point, without having to move the plot?如何在用户单击某个点时立即显示注释,而无需移动 plot?

Add fig.canvas.draw_idle() at the end of your callback function to force the re-drawing of the new annotation.在回调 function 的末尾添加fig.canvas.draw_idle()以强制重新绘制新注释。

Hmm when using Matplotlib 3.4 the index flips depending on the orientation of the 3dgraph on the screen, and it throws this whole thing off.嗯,当使用 Matplotlib 3.4 时,索引会根据屏幕上 3dgraph 的方向翻转,它会抛出这一切。 Run the code rotate graph by 180 degrees and click on the points.运行代码将图形旋转 180 度并单击点。 It's awful.太可怕了。

#!/usr/bin/env python3

from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt


import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')

x = [0, 2, 0,0]
y = [0, 2, 0,2]
z = [0, 2, 2,0]

scatter = ax.scatter(x,y,z,picker=True)

def chaos_onclick(event):

    point_index = int(event.ind)
    print(point_index)

    #proj = ax.get_proj()
    #x_p, y_p, _ = proj3d.proj_transform(x[point_index], y[point_index], z[point_index], proj)
    #plt.annotate(str(point_index), xy=(x_p, y_p))
    
    print("X=",x[point_index], " Y=",y[point_index], " Z=",z[point_index], " PointIdx=", point_index)


fig.canvas.mpl_connect('pick_event', chaos_onclick)
plt.show()

OK here's a workaround with info gathered from Matplotlib: Annotating a 3D scatter plot .好的,这是使用从Matplotlib 收集的信息的解决方法: Annotating a 3D scatter plot

#!/usr/bin/env python3

from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt
import numpy as np

import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))

fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')

x = [0, 2, 0,0]
y = [0, 2, 0,2]
z = [0, 2, 2,0]

scatter = ax.scatter(x,y,z,picker=True)

ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')


def onMouseMotion(event):
  print(event)

def chaos_onclick(event):

    print(dir(event.mouseevent))
    xx=event.mouseevent.x
    yy=event.mouseevent.y
    
    #magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot
    x2, y2, z2=proj3d.proj_transform(x[0], y[0], z[0], plt.gca().get_proj())
    x3, y3 = ax.transData.transform((x2, y2))
    #the distance
    d=np.sqrt ((x3 - xx)**2 + (y3 - yy)**2)
    
    print ("distance=",d)
    
    
    #find the closest by searching for min distance.
    #All glory to https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot
    imin=0
    dmin=10000000
    for i in range(len(x)):
      #magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot
      x2, y2, z2=proj3d.proj_transform(x[i], y[i], z[i], plt.gca().get_proj())
      x3, y3 = ax.transData.transform((x2, y2))
      #the distance magic from https://stackoverflow.com/questions/10374930/matplotlib-annotating-a-3d-scatter-plot
      d=np.sqrt ((x3 - xx)**2 + (y3 - yy)**2)
      #We find the distance and also the index for the closest datapoint
      if d< dmin:
        dmin=d
        imin=i
        
      #print ("i=",i," d=",d, " imin=",imin, " dmin=",dmin)
    
    # gives the incorrect data point index
    point_index = int(event.ind)

    print("Xfixed=",x[imin], " Yfixed=",y[imin], " Zfixed=",z[imin], " PointIdxFixed=", imin)
    print("Xbroke=",x[point_index], " Ybroke=",y[point_index], " Zbroke=",z[point_index], " PointIdx=", point_index)

fig.canvas.mpl_connect('pick_event', chaos_onclick)
#fig.canvas.mpl_connect('motion_notify_event', onMouseMotion)  # on mouse motion


plt.show()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM