3D convex hull of a point cloud

I need to build a three-dimensional cloud of points (number of points: N), then a convex hull (actually a polyhedron with N vertices) from points. I made a script in python with scipy.spatial ConvexHull for a graph of 8 points and built a cube, the graph of the point cloud is fine, but the cube is not suitable, because the code places two lines passing through the diagonal face of the cube in addition to the boundary lines. I don’t understand why the plot lines cross the faces.

script:

import numpy as np from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from scipy.spatial import ConvexHull fig = plt.figure() ax = fig.add_subplot(111, projection='3d') points= np.array([[0,0,0], [4,0,0], [4,4,0], [0,4,0], [0,0,4], [4,0,4], [4,4,4], [0,4,4]]) hull=ConvexHull(points) edges= zip(*points) for i in hull.simplices: plt.plot(points[i,0], points[i,1], points[i,2], 'r-') ax.plot(edges[0],edges[1],edges[2],'bo') ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') ax.set_xlim3d(-5,5) ax.set_ylim3d(-5,5) ax.set_zlim3d(-5,5) plt.show() 

The result of the script:

enter image description here

+8
source share
1 answer

I know this is old, but I came here from Google, so I think others can too.

The only problem is the printing method you are using. One simplex is an nD-triangular nick, defined by 3 points. But the plotting function should return to the last point, otherwise only 2 out of 3 simplex edges are drawn.

 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.spatial import ConvexHull # 8 points defining the cube corners pts = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1], ]) hull = ConvexHull(pts) fig = plt.figure() ax = fig.add_subplot(111, projection="3d") # Plot defining corner points ax.plot(pts.T[0], pts.T[1], pts.T[2], "ko") # 12 = 2 * 6 faces are the simplices (2 simplices per square face) for s in hull.simplices: s = np.append(s, s[0]) # Here we cycle back to the first coordinate ax.plot(pts[s, 0], pts[s, 1], pts[s, 2], "r-") # Make axis label for i in ["x", "y", "z"]: eval("ax.set_{:s}label('{:s}')".format(i, i)) plt.show() 

image

+8
source

Source: https://habr.com/ru/post/979043/


All Articles