I am plotting families of orbits in python using matplotlib and the add_subplots()
routine:
fig=plt.figure()
ax=fig.add_subplots(projection='3d')
I then loop through my list of [X,Y,Z] series and plot them on my ax:
x1, y1, z1 = np.array([...]), np.array([...]), np.array([...])
x2, y2, z2 = np.array([...]), np.array([...]), np.array([...])
...
xn, yn, zn = np.array([...]), np.array([...]), np.array([...])
xs, ys, zs = [x1, x2, ..., xn], [y1, y2, ..., yn], [z1, z2, ..., zn]
for i in range(n):
ax.plot(xs[i], ys[i], zs[i])
plt.show()
The issue is that the lines appear on top of or below each other not based on where they are in 3D space, but on the order they were drawn in. This makes for weird optical effects when trying to examine the plots where they kind of look like those impossible Escher drawings with lines overlaying ones where they physically can't. This effect is even worse when interacting with the plot and rotating around.
I feel like there is something simple I am missing here, and I can see how especially for 2D plots drawing order is important, but I also feel like by default, 3D line plots should follow the idea of putting certain parts of lines in front of others based on where they are in 3D space, otherwise whats the point of a 3D plot?
Anyway, if anyone has any ideas, I'm open to them. The actual plotting routine is obviously more complex than the above, which I've almost pseduocoded for simplicity, but I'm not going to put my whole OOP family of plotting classes up - not least because its overkill to answer this question.
Matplotlib is always plotting objects according to the order they were drawn in, not their actual position in space.
This is discussed in their FAQ, where they recommend an alternative, that is MayaVi2 (which you can find documentation for here). It has very similar approach to Matplotlib, so you don't get too confused when switching.
You can find more information in this question, that I don't want to paraphrase just for the sake of a longer answer.
In your case, the new code could look like that:
from mayavi import mlab
x1, y1, z1 = np.array([...]), np.array([...]), np.array([...])
x2, y2, z2 = np.array([...]), np.array([...]), np.array([...])
# ...
xn, yn, zn = np.array([...]), np.array([...]), np.array([...])
xs, ys, zs = [x1, x2, ..., xn], [y1, y2, ..., yn], [z1, z2, ..., zn]
for i in range(n):
mlab.plot3d(xs[i], ys[i], zs[i])
mlab.show()