python 后面的3d散射点与前面的点重叠

hof1towb  于 2023-05-27  发布在  Python
关注(0)|答案(2)|浏览(114)

我正在用matplotlib准备3d图,我对多个数据集有一个非常奇怪的行为。我有两个数据集,基本上描述了3D中的两个壳:一个内壳和一个 shell 。在3D中绘制它们:

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])

(the轴的顺序仅用于透视目的)。但是,当我保存图形时,我不会得到两个壳:

我得到一层在另一层之上,明显在后面的点出现在前面。你可以在图片上看到, shell 的一些点应该在内壳的后面,但却绘制在内壳的前面。这真的很烦人,因为它不追求“3d中的情节”的目的。有没有人知道为什么会发生这种情况,以及如何解决?

oxiaedzo

oxiaedzo1#

我知道这不能解决你的问题,但也许能解释为什么它会这样。
这与Matplotlib实际上没有3D引擎有关。Mplot 3D获取您的点并将其投影到2D图上(对于每个对象),然后Matplotlib一次绘制一个对象; Matplotlib是一个2D绘图框架,Mplot 3D是一种小技巧,可以让一些3D功能工作,而无需为Matplotlib编写一个完整的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])

这给出:x1c 0d1x
但从俯视图中你可以看到这条线在螺旋线内部:

但是,如果交换绘制这些线的顺序:

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

然后,您会看到在螺旋线之后绘制的直线:

最终,这意味着您必须手动确定哪些点将位于其他点的前面。然后,您可以使用zorder参数来确定哪些对象将位于其他对象的前面。但是你必须为每个透视图(Angular ,高度)做这件事。在这种情况下,您可能必须将内部线分解为“infront_of_helix”和“behind_helix”部分,然后分别在螺旋的前面和后面绘制它们。
我希望有人沿着对这件事做更多的阐述,因为我自己对这个主题很感兴趣。我知道mplot 3d有一些基本的方法来确保前面的点首先显示,我相信,当它使用着色算法时,但我不完全确定。

epfja78i

epfja78i2#

非常感谢你的解释:)我想它确实可能是这样的。但是我忘了在我的问题中说,无论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')

我得到了下面的图片:

这对我很有效然而,我知道,如果我改变视角,我会让红色 shell 出现在黑色 shell 的顶部。我后来发现的一个问题是.plot函数没有vmin和vmax参数(和.scatter一样),这使得它更难将颜色定义为从vmin和vmax开始的渐变。

相关问题