1

I search for the correct implementation for this a long time now.

I have a 3D delaunay triangulation and want to plot this in 2D. In 3D i manage to do so: Complex 3D delauny triangulation. Half of the triangles hidden.

I need a 2D plot though. What i get using matplotlib.tripcolor method or the matplotlib.collections.PolyCollection is:

Complex 3D delauny triangulation mapped to 2D. Some triangles from the back of the structure are plotted

How do i plot this in 2D without the top and back triangles all mixed up? With all methods tried so far, some triangles are hidden by triangles that should be in the back of the structure.

I see, that the methods just do not have the information necessary to plot in the correct order, since i have to provide 2D arrays already. The depth information is lost.

Does anybody know how to do this? Thanks a lot!

  • Maybe one of the answers to [this question](https://stackoverflow.com/questions/33084853/set-matplotlib-view-to-be-normal-to-the-x-y-plane-in-python) will do what you want – user3419537 Jul 04 '17 at 10:39
  • Not quite. The angle is already set properly in the top picture. The problem is, that i want to plot other stuff in 2D above. So i really want 2D – Daniel Böckenhoff Jul 04 '17 at 12:38
  • 1
    Matplotlib is not a 3D engine per se. As so the rendering is faulty. You can use tripcolor only with the front triangles. But that probably implies that you need to check which triangles have vertices with an `x` greater than something, and plot all others. This might work better or worse depending on the "shape" of your volume but assume that there is no proper pixel by pixel depth check. If the shape is too complex you might need to build your own small rendering algorithm (perhaps using imshow or similar). – armatita Jul 04 '17 at 13:05
  • I fear so! That is why i am asking. Before doing that, often there is a better solution one has never stumbled upon. But maybe your are rigth. – Daniel Böckenhoff Jul 04 '17 at 13:17

1 Answers1

1

You can mimic a 2D plot with Axes3d by setting an orthographic projection, initialising the view to face the desired plane, and removing unwanted plot elements along the axis orthogonal to the chosen plane of view. In addition, you can plot 2D elements using the zdir keyword argument.

Here's one of the matplotlib 3D plot examples I modified to demonstrate

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np

# Enable orthographic projection
# https://stackoverflow.com/questions/23840756/how-to-disable-perspective-in-mplot3d
from mpl_toolkits.mplot3d import proj3d
def orthogonal_proj(zfront, zback):
    a = (zfront+zback)/(zfront-zback)
    b = -2*(zfront*zback)/(zfront-zback)
    return np.array([[1,0,0,0],
                        [0,1,0,0],
                        [0,0,a,b],
                        [0,0,-0.000001,zback]])
proj3d.persp_transformation = orthogonal_proj

fig = plt.figure()
ax = fig.gca(projection='3d')

# Init view to YZ plane
ax.view_init(azim=0, elev=0)

# Hide the X axis
ax.w_xaxis.line.set_lw(0.)
ax.set_xticks([])

# Change YZ plane colour to white
ax.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 1.0))

# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
ax.set_zlim(-1.1, 1.1)
ax.set_ylabel('y')
ax.set_zlabel('z')

# Plot 2D elements with zdir argument
# https://stackoverflow.com/questions/29549905/pylab-3d-scatter-plots-with-2d-projections-of-plotted-data
stepsize = 0.1
t = np.arange(-4, 4+stepsize, step=stepsize)
ax.plot(t, 0.5*np.sin(t), 'k', zdir='x', linewidth=1.0)
ax.text(0, 0, 1, 'Text', zdir='y', ha='center', va='top')

plt.show()

enter image description here

user3419537
  • 4,740
  • 2
  • 24
  • 42