You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
mplot3d failed to clip bar charts if zlim is set. #8902
# Adapter from http://matplotlib.org/2.0.2/examples/mplot3d/bars3d_demo.htmlfrommpl_toolkits.mplot3dimportAxes3Dimportmatplotlib.pyplotaspltimportnumpyasnpfig=plt.figure()
ax=fig.add_subplot(111, projection='3d')
forc, zinzip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
xs=np.arange(20)
ys=np.random.rand(20)
# You can provide either a single color or an array. To demonstrate this,# the first bar of each set will be colored cyan.cs= [c] *len(xs)
cs[0] ='c'ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Set zlim3dax.set_zlim3d(bottom=0.2, top=1)
plt.show()
Actual outcome
Expected outcome
The z-axis would be clipped according to the zlim_3d parameters properly
To my understanding we do not compute any sort of 3D intersections or have a proper z-buffer (either of which could be used to implement this) and both of which would be pretty major efforts to implement.
@tacaswell instead of implementing code to compute 3D intersections or z-buffer, could zlim_3d clip the data properly just like the workaround below?
# Adapted from http://matplotlib.org/2.0.2/examples/mplot3d/bars3d_demo.htmlfrommpl_toolkits.mplot3dimportAxes3Dimportmatplotlib.tickerastickerimportmatplotlib.pyplotaspltimportnumpyasnp# Funcformatter to simulate zlim_3ddefmajor_formatter(x, pos):
return"{:.1f}".format(x+0.2)
fig=plt.figure()
ax=fig.add_subplot(111, projection='3d')
forc, zinzip(['r', 'g', 'b', 'y'], [30, 20, 10, 0]):
xs=np.arange(20)
ys=np.random.rand(20)
# Simulate zlim_3d by subtracting the min limitys-=0.2ys[ys<0] =0# You can provide either a single color or an array. To demonstrate this,# the first bar of each set will be colored cyan.cs= [c] *len(xs)
cs[0] ='c'ax.bar(xs, ys, zs=z, zdir='y', color=cs, alpha=0.8)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Shift the tick labels up by 0.2ax.zaxis.set_major_formatter(ticker.FuncFormatter(major_formatter))
plt.show()
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
There is some discussion about this desired behavior in #25804
#27349 will implement option B from the graphic below, but option C is really the thrust of the original question here.
Unfortunately, implementing that would require a huge rewrite of the 3D renderer to do proper culling with a z-buffer or 3D intersections, as @tacaswell mentioned in his comment. I don't think there's anyone able to do that right now, though if someone wants to take it on as a project it'd be awesome.
Activity
tacaswell commentedon Jul 17, 2017
To my understanding we do not compute any sort of 3D intersections or have a proper z-buffer (either of which could be used to implement this) and both of which would be pretty major efforts to implement.
@a113n are you interested in working on this?
a113n commentedon Jul 18, 2017
@tacaswell instead of implementing code to compute 3D intersections or z-buffer, could zlim_3d clip the data properly just like the workaround below?
Result:

tacaswell commentedon Jul 20, 2017
That works for this case where you know the shift and use it to both adjust the data and the tick labels. However I don't see how to generalize it.
It would also be odd if it only worked in the z-direction, not x and y.
QuLogic commentedon Jun 23, 2018
The code passes
zdir='y'which is why the layering is in the y direction instead of z.github-actions commentedon Oct 9, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
scottshambaugh commentedon Nov 28, 2023
There is some discussion about this desired behavior in #25804
#27349 will implement option B from the graphic below, but option C is really the thrust of the original question here.

Unfortunately, implementing that would require a huge rewrite of the 3D renderer to do proper culling with a z-buffer or 3D intersections, as @tacaswell mentioned in his comment. I don't think there's anyone able to do that right now, though if someone wants to take it on as a project it'd be awesome.