2015-10-15 73 views
3

我准备用matplotlib三维图,我有一个非常奇怪的行为与多个数据集。我有两个数据集,基本上描述了3d中的两个壳:一个内壳和一个外壳。要在3D中绘制它们,请执行以下操作:Pyplot三维散点:在前面的重叠点的点

fig = plt.figure() 

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

ax.scatter(outer_z[:n], outer_x[:n], outer_y[:n], c='black', marker='.', lw=0) 
ax.scatter(inner_z[:n], inner_x[:n], inner_y[:n], c='red', marker='.', lw=0) 

ax.set_xlabel("Z") 
ax.set_ylabel("X") 
ax.set_zlabel("Y") 

ax.set_xlim([-5,5]) 
ax.set_ylim([5,-5]) 
ax.set_zlim([-5,5]) 

(轴的顺序仅用于透视目的)。当我保存这个数字,但是,我没有得到两发炮弹:

enter image description hereenter image description here

我得到一个层上,另一方面也与该显然是出现在前面后面的点。你可以在图片上看到,应该在内壳后面的外壳的一些点被绘制在内壳的前面。这真的很烦人,因为它不追求“3D情节”的目的。有没有人有一个想法,为什么会发生这种情况,如何解决这个问题? 非常感谢!

+0

我是思考,如果你决定手动做,我有一个想法如何做到这一点。您必须选择一个点作为您的视角(相机所在的位置)和相机指向的方向。然后,从这里有一个公式可以确定点在这个方向上的距离(使用点到平面公式的距离),您可以将它用于zorder参数。让我知道你是否好奇追求这一点,我们可以尝试一下。但是如实地,您可能需要为这个项目寻找其他工具(带有真正的3D引擎)。 – breeden

回答

0

非常感谢您的解释:)我认为这可能确实是这样的。但是我忘记说在我的问题中,无论ax.scatter命令的顺序如何,都会发生同样的事情,这很奇怪。在阅读你的答案之前,我发现这不会发生在ax.plot命令中。因此,我代替:

ax.scatter(outer_z[:n], outer_x[:n], outer_y[:n], c='black', marker='.', lw=0) 
ax.scatter(inner_z[:n], inner_x[:n], inner_y[:n], c='red', marker='.', lw=0) 

通过

ax.plot(outer_z[:n], outer_x[:n], outer_y[:n], '.', markersize=1, color='black') 
ax.plot(inner_z[:n], inner_x[:n], inner_y[:n], '.', markersize=1, color='red') 

而且我得到了下面的图片:

enter image description here

这对我的作品。但是,我知道,如果我改变观点,我会让红色的外壳出现在黑色的外壳之上。后来发现的一个问题是.plot函数没有vmin和vmax参数(如.scatter之一),这使得难以将颜色定义为从vmin和vmax开始的渐变...

2

我知道这不是您的问题的解决方案,但也许是为什么它的行为方式的解释。

这与Matplotlib实际上没有3D引擎的事实有关。 Mplot3D获取你的点并将它们投影到它在2D图(对于每个对象)上的样子,然后Matplotlib每次绘制一个对象; Matplotlib是一个2D绘图框架,Mplot3D可以在不需要为Matplotlib编写完整的3D引擎的情况下获得一些3D功能。

这意味着您绘制不同图(在本例中为红色和黑色圆点)的顺序很重要,如果在红色圆点后绘制黑色圆点,它们将显示在红色圆点的前面,不管他们的位置。

让我用另一个例子来说明这一点。

theta = np.linspace(0, 2*np.pi, 100, endpoint=True) 

helix_x = np.cos(3*theta) 
helix_y = np.sin(3*theta) 
helix_z = theta 

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

line_x = np.zeros(100) 
line_y = np.zeros(100) 

ax.plot(line_x, line_y, theta, lw='3', color='r') 
ax.plot(helix_x, helix_y, helix_z, lw='2', color='k') 

ax.set_xlabel("Z") 
ax.set_ylabel("X") 
ax.set_zlabel("Y") 

ax.set_xlim([-1.5,1.5]) 
ax.set_ylim([-1.5,1.5]) 
ax.set_zlim([0,2*np.pi]) 

这给:enter image description here

但是从俯视图可以看出,该行是螺旋内:

enter image description here

但是,如果你交换的次序您阴谋这些行:

ax.plot(line_x, line_y, theta, lw='3', color='r') 
ax.plot(helix_x, helix_y, helix_z, lw='2', color='k') 

然后您会看到螺旋后绘制的线条:

enter image description here

最终,这意味着你必须手动确定哪个点会在其他点的前面。然后,您可以使用参数zorder来确定哪些对象位于其他对象的前面。但是您必须为每个视角(角度,高程)执行此操作。在这种情况下,您可能必须将内线分解为“infront_of_helix”和“behind_helix”部分,然后分别在螺旋前方和后方绘制它们。

虽然我希望有人对此事进行更详细的阐述,但我对这个话题感兴趣。我知道mplot3d有一些基本的方法可以确保首先显示前端点,我相信,当它使用着色算法时,我并不确定。