14

I have a plot consisting of a blue surface (plotted via plot_surface) and a red sphere (plotted via scatter). The zorder of the surface is set to 0, and the zorder of the sphere is set to 1 (though not setting any zorder values yields the same results).

You can see that the red sphere is to the left of the surface: enter image description here

As I rotate the plot you can see the red sphere start to disappear behind the blue surface even though it's in front of it:

enter image description here

Until the red sphere completely disappears: enter image description here

What is strange is that for certain angles/views the red sphere re-appears and is visible again, such as this one: enter image description here

What's going on here? I've read some of the other plotting/zorder related issues but I haven't seen this type of behavior where one object is clearly behind/in-front of another and it isn't displayed correctly for most viewing angles.

If I make the blue surface transparent, you can see the red sphere behind the surface when it disappears in the plots below (so it seems like the plotting library actually thinks that it's behind the surface).

mattnedrich
  • 7,577
  • 9
  • 39
  • 45
  • 1
    https://stackoverflow.com/questions/14824893/how-to-draw-diagrams-like-this/14825951#14825951 <- may be relevant – tacaswell Apr 20 '14 at 23:31
  • @tcaswell Yea, I've looked at that, however, that post seems to deal with portions of shapes appearing in-front of or behind other shapes (e.g., it seems to be an all or nothing unless you split them up into the occluded vs non-occluded parts - am I understanding their scenario correctly?). Although, the third bullet "The 'proper' ordering of the surfaces also seems to be dependent on the view angle." does seem relevant to what I'm observing. Though, in my scenario I have two completely distinct shapes. – mattnedrich Apr 20 '14 at 23:46
  • This is a very closely related issue, the library draws artists a layer at a time. For what ever reason it has decided to draw the sphere first and then the blue curve. It does not matter what order they _should_ be in all that matters is what order they get rendered in. I am not familiar with the huristics that the library uses to sort out the draw order, but they are delicate (is _any_ part of your surface in front of the sphere?) – tacaswell Apr 20 '14 at 23:54
  • I've played around with my example a bit. If I move the red sphere sufficiently far away from the blue surface I observe the correct rendering. However, if it is nearby (even within 1-2 units) I get the behavior described above. At this point, I'm wondering if this is a known bug (and if it's documented somewhere). The post you pointed me to is over a year old. – mattnedrich Apr 21 '14 at 03:16
  • 1
    plot3D has not received much work recently. If you need 'real' 3D graphics you are much better off using mayavi (which wraps vtk) and is opengl based – tacaswell Apr 21 '14 at 13:01
  • @tcaswell I've attempted to install and use mayavi on both OSX and Windows. My experience with both was terrible. After 2+ days trying to setup and configure my environment I gave up. It's not even clear to me if you can obtain a free version of mayavi on OSX currently. It's unfortunate that plot3D has these issues :( – mattnedrich Jun 22 '14 at 19:46
  • 4
    I just ran into this issue as well. Even though it is 2018 now (well, more or less 2019...) this is still an issue. Will there be an update for this? – JE_Muc Dec 21 '18 at 09:26
  • I have the same problem and was wondering if it has been fixed since, I have matplotlib:3.3.4 and zorder still does not work. I need a specific azimuth angle to appreciate my visualization and it failed to order everything correctly. – Sophie.A Mar 25 '21 at 16:15
  • Matplotlib 3.4.2. The same issue still persists in 2021 :/ – biubiuty Jul 07 '21 at 18:42

2 Answers2

4

Since Matplotlib 3.5.0 there is a setting for axis3d which solves this problem. This setting is called computed_zorder.

Example:

ax = plt.axes(projection='3d',computed_zorder=False)
ax.plot_surface(X, Y, Z,zorder=1)
ax.plot_surface(U, V, W,zorder=2)

The element with the highest zorder will be displayed on top.

Some of the default zorder values are listed here:

Artist zorder
Images (AxesImage, FigureImage, BboxImage) 0
Patch, PatchCollection 1
Line2D, LineCollection (including minor ticks, grid lines) 2
Major ticks 2.01
Text (including axes labels and titles) 3
Legend 5
jri
  • 402
  • 1
  • 6
  • 15
2

This is still an issue in Matplotlib 1.5.3 (2016). The alternative that @tacaswell (who is a co-lead on Matplotlib dev) recommends is to handle 3D plotting using Mayavi which is relatively unique amongst Python plotting libraries in that it does not use Matplotlib as a backend like many other projects do (Pandas, Seaborn, ggplot).

I was able to install Mayavi on OSX with a minimum of fuss using Homebrew and pip.

#/bin/bash
# vtk is a mayavi requirement
brew install vtk
pip install mayavi
# Port your matplotlib code to mayavi
# Profit...