如何用体素填充三维图形?

2024-05-23 13:54:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用体素填充一个四面体来生成3D数据。我已经能够使用4个不同的点来生成四面体。我不确定如何使用NumPy或任何其他Python框架用体素填充四面体内部的区域。以下是生成四面体3D绘图的代码:

# Tetrahedron

from scipy.spatial import Delaunay
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
points= np.array([[1,2,2],[1,3,4],[4,1,4],[5,3,2]])
tri = Delaunay(points)
tr = tri.simplices[0]  # indices of first tetrahedron
pts = points[tr, :]  # pts is a 4x3 array of the tetrahedron coordinates
fig = plt.figure()
ax = fig.gca(projection= '3d')

# plotting the six edges of the tetrahedron
for ij in [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]:
    ax.plot3D(pts[ij, 0], pts[ij, 1], pts[ij, 2])
plt.show()

Tetrahedron Plot

下面是一个我试图实现的示例图像。此示例以已填充体素的球体为特征:


Tags: oftheimportmatplotlibasnppltarray
1条回答
网友
1楼 · 发布于 2024-05-23 13:54:26

那么你在找这样的东西

Voxeled Simplex

我采用这个https://matplotlib.org/stable/gallery/mplot3d/voxels_rgb.html来获得你的单纯形

import itertools
import functools
import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (18,9)
points = np.array([[1,2,2],[1,3,4],[4,1,4],[5,3,2]])
center = np.mean(points, axis=0)

def surface_normal_form(a,b,c):
    v = b-a
    w = c-b
    n = np.cross(v,w)
    #normal needs to point out
    if (center-a)@n > 0:
         n *= -1
    return a, n

def midpoints(x):
    sl = ()
    for i in range(x.ndim):
        x = (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
        sl += np.index_exp[:]
    return x

x, y, z = (np.indices((60, 60, 60))-np.array([20,25,25]).reshape(-1,1,1,1))/8
mx = midpoints(x)
my = midpoints(y)
mz = midpoints(z)

conditions = []
for p1,p2,p3 in itertools.combinations(points, 3):
    a, n = surface_normal_form(p1,p2,p3)
    conditions.append((mx-a[0])*n[0]+(my-a[1])*n[1]+(mz-a[2])*n[2] <= 0)

simplex = conditions[0] & conditions[1] & conditions[2] & conditions[3]

ax = plt.figure().add_subplot(projection='3d')
ax.voxels(x, y, z, simplex, linewidth=0.5)
ax.set(xlabel='x', ylabel='y', zlabel='z')
ax.set_xlim(1.0,5.0)
ax.set_ylim(1.0,3.0)
ax.set_zlim(2.0,4.0)

你能解释一下你在曲面法向函数中做了什么吗

当然,在3d中,你可以通过平面的一个点和与平面正交的向量来描述平面。这非常有用,因为这样很容易判断点是在平面的一侧还是另一侧。然后,如果取包含单纯形侧面的平面,则通过取紧密配合在一起的体素立方体,并为每个平面移除错误侧面的体素,得到单纯形体素。这就是我正在做的

另外,你能解释一下中点的功能吗

首先是一个小小的免责声明,我自己没有写过。正如我所说,它来自matplotlib示例。但如果你想计算一维数组的中点,你可以这样做

(x[:-1]+x[1:])/2

首先x[:-1]给出所有值,但最后一个值除外,x[1:]给出所有值,但第一个值除外,因此相邻的值将求和并除以2,即得到中点。请注意,如果原始阵列大于1d(在本例中为三维),则它将采用(在本例中为2d)子阵列的“中点”。在第二步中,我们正在做的是(x[:,:-1]+x[:,1:])/2。 由于[:]给出了所有的值,midpoint函数对每个维度都这样做

相关问题 更多 >