Preface: I am aware that matplotlib cannot deal with 3D occlusion and that for that type of issue I should use Mayavi. This is a different situation.
What I'm trying to achieve is to plot a line on top of a surface. The line is only on "this" side of the surface so my expectation was that I could control what comes in front by adjusting the zorder. Unfortunately, it seems as if the zorder is not behaving as expected.
In my experiment below, the only thing that seems to be affected by the zorder is the line plot, which goes in front of the scatter if zorder>=3 (regardless of the zorder of the scatter points) and it goes in front of the surface if zorder>=4 (regardless of the zorder of the surface).
As far as I can tell, matplotlib is simply ignoring the zorder for the scatter and the surface, and setting them to fixed values.
Is there a way to force the zorder for the surface and the scatter?
Here is the result of the MWE below. The line is above the surface but the scatter points are below the surface.
EDIT: I just found out that we can use plot
and set no line to get points like scatter
. It is not ideal because we can't use the same features of scatter
, but it works as a workaround for plotting points that respect the zorder.
MWE
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
cos=np.cos
sin=np.sin
arccos=np.arccos
pi = np.pi
def getxyz(in_theta,in_phi,scale=1.0):
x = scale*sin(in_theta)*cos(in_phi)
y = scale*sin(in_theta)*sin(in_phi)
z = scale*cos(in_theta)
return x,y,z
# ============== SCRIPT ================
# Initialize Figure
fig = plt.figure(figsize=(8,8),dpi=100)
ax = fig.add_subplot(111, projection='3d')
ax.set_aspect("equal")
# Plot Sphere Surface-plot
NS=10
Sx,Sy,Sz = getxyz(*np.mgrid[0:pi/2:NS*2j, 0:pi/2:NS*2j])
ax.plot_surface(Sx,Sy,Sz,rstride=2,cstride=2, color=(0.5,0.5,0.5,0.7),zorder=100)
# Make a line on the sphere
Nl=20
Lx,Ly,Lz = getxyz(np.linspace(pi/3,pi/4,Nl),np.linspace(0,pi/3,Nl))
# Plot Scatter
ax.scatter(Lx,Ly,Lz,s=30,c='k',depthshade=False,zorder=500)
# Plot Line
ax.plot(Lx,Ly,Lz,'r-',zorder=4)
ax.view_init(30, 45)
# fig.savefig("test.png")
plt.show()