4

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.

Result of the MWE

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()
MrWonderful
  • 2,530
  • 1
  • 16
  • 22
Miguel
  • 1,293
  • 1
  • 13
  • 30
  • I don't know what `zorder` is, but in my experience with 2D plots the things you draw are just stacked on top of each other in the same order you called the drawing functions. – Guimoute May 06 '19 at 19:11
  • That is true, and zorder usually allows the user to specify a different order to draw. However, it seems that for the 3D plots something strange is happening because I think also the order in which you call the plotting functions doesn't affect the result. – Miguel May 07 '19 at 08:58
  • I would also link to your ticket: https://github.com/matplotlib/matplotlib/issues/14148 – Ciro Santilli OurBigBook.com Dec 07 '20 at 09:04

0 Answers0