Reputation: 25550
I'd like to plot a sine wave on a circle: that is, the circle is in the x,y-plane and the sine wave wraps around it perpendicular to that plane (sticking up the z-axis). I can do this, but when I try to fill the areas between the circle and the sine wave with a polygon (ie paint on the surface of the imaginary cylinder on which my sine wave lives), I can't get it quite right - matplotlib seems to XOR the regions that overlap in a view of the plot instead of giving me a view in which the ones in front occlude those behind. Here's the relevant bit of my code:
fig = plt.figure()
ax = fig.gca(projection='3d')
ax._axis3don = False
theta = np.linspace(0., 2 * np.pi, 1000)
r = 1.
x = r * np.sin(theta)
y = r * np.cos(theta)
sinez = N * np.sin(theta * m)
ax.plot(x, y, sinez, color='r')
xv = np.append(x, x[::-1])
yv = np.append(y, y[::-1])
zv = np.append(sinez, np.zeros(n))
verts = [zip(xv,yv,zrev),]
poly = Poly3DCollection(verts, facecolors = [cc('r'), cc('b')],
edgecolor='None')
poly.set_alpha(0.7)
ax.add_collection3d(poly)
Here's what it looks like:
Upvotes: 2
Views: 1111
Reputation: 87536
matplotlib
's main reason for existence is 2D plotting, the 3D stuff is just some clever transforms and can be buggy/hacky. One of the inherent limitations is that matplotlib
draws in layers, so it has no notion of 'in front' or 'behind', it only knows the order in which in draws the curves to the canvas (which is confusingly called z-order).
If you want to get this to look right with out re-writing the 3D code, split the sine wave up into pieces and make sure you set the z-order right by hand (see How to draw intersecting planes? for a simpler version of this), but you won't be able to rotate the image.
If you need real 3D, I would suggest looking into mayavi
from enthought which is OpenGL based.
Upvotes: 2
Reputation: 20373
In the docs, the devs claim that Poly3DCollection
does a bit of magic with the _facecolors and _edgecolors properties.
which I believe is the XOR effect that you can see here, and looking at the code it's the function do_3d_projection
that seems to be doing the magic.
As I see it, you could either subclass Poly3DCollection
and rewrite do_3d_projection
to get what you want, or maybe think of another way to plot this (perhaps treating the sinusoid and circle as separate objects somehow).
Upvotes: 1