从点云生成3D凸壳

18

我需要绘制一个3D点云(点数:N),然后从这些点生成一个凸包(实际上是一个具有N个顶点的多面体)。我用Python和Scipy库中的ConvexHull编写了一个脚本,可以绘制8个点和一个立方体。点云的绘图效果很好,但是立方体的绘图效果不好,因为代码除了边线外还在对角面上放置了两条线。我不明白为什么要绘制在面上的线。

脚本:

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()

脚本的结果:

在此输入图片描述

2个回答

25

我知道这已经过时了,但我从谷歌搜索中来到这里,所以我认为其他人也可能会来。

问题仅存在于您使用的绘图方法中。 一个单纯形是由3个点定义的nD三角形。 但是绘图函数必须回到最后一个点,否则只会绘制3个简单形边缘中的2个。

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


3

据我理解,您只想要边缘(所以我不理解Thorben的答案)。

要获得凸包及其边缘,请使用pycddlib(即cdd库):

# -*- coding: utf-8 -*-
import numpy as np
import cdd as pcdd
import matplotlib.pyplot as plt

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]
])

# to get the convex hull with cdd, one has to prepend a column of ones
vertices = np.hstack((np.ones((8,1)), points))

# do the polyhedron
mat = pcdd.Matrix(vertices, linear=False, number_type="fraction") 
mat.rep_type = pcdd.RepType.GENERATOR
poly = pcdd.Polyhedron(mat)

# get the adjacent vertices of each vertex
adjacencies = [list(x) for x in poly.get_input_adjacency()]

# store the edges in a matrix (giving the indices of the points)
edges = [None]*(8-1)
for i,indices in enumerate(adjacencies[:-1]):
    indices = list(filter(lambda x: x>i, indices))
    l = len(indices)
    col1 = np.full((l, 1), i)
    indices = np.reshape(indices, (l, 1))
    edges[i] = np.hstack((col1, indices))
Edges = np.vstack(tuple(edges))

# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")

start = points[Edges[:,0]]
end = points[Edges[:,1]]

for i in range(12):
    ax.plot(
        [start[i,0], end[i,0]], 
        [start[i,1], end[i,1]], 
        [start[i,2], end[i,2]],
        "blue"
    )

ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")

ax.set_xlim3d(-1,5)
ax.set_ylim3d(-1,5)
ax.set_zlim3d(-1,5)

plt.show()

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接