Python 在三维numpy矩阵中绘制给定值的曲面轮廓

Python 在三维numpy矩阵中绘制给定值的曲面轮廓,python,numpy,matplotlib,Python,Numpy,Matplotlib,我有三个3D网格矩阵(X,Y,Z)对应于xyz坐标空间 我还有一个3D Numpy矩阵a,其中a[I,j,k]包含一个与点(x,y,z)关联的浮点,其中x=x[I,j,k],y=y[I,j,k],和z=z[I,j,k]。浮动值在A内是连续的(即A相邻元素之间的值变化通常很小) 是否有一种方法可以使用Matplotlib或任何其他基于Python的图形包绘制与a中给定浮点值对应的曲面?例如,如果给定一个值2.34,我感兴趣的是在显示2.34(加上或减去一些公差)的地方获得矩阵a的绘制轮廓曲面 到目

我有三个3D网格矩阵(
X
Y
Z
)对应于xyz坐标空间

我还有一个3D Numpy矩阵
a
,其中
a[I,j,k]
包含一个与点
(x,y,z)
关联的浮点,其中
x=x[I,j,k]
y=y[I,j,k]
,和
z=z[I,j,k]
。浮动值在
A
内是连续的(即
A
相邻元素之间的值变化通常很小)

是否有一种方法可以使用Matplotlib或任何其他基于Python的图形包绘制与
a
中给定浮点值对应的曲面?例如,如果给定一个值
2.34
,我感兴趣的是在显示
2.34
(加上或减去一些公差)的地方获得矩阵
a
的绘制轮廓曲面

到目前为止,我已经能够恢复
A
中目标值公差范围内的所有值的xyz坐标,然后使用(下面的代码)绘制三维散点图。也许还有一种从这些点绘制曲面的方法

def clean (A, t, dt):
    # function for making A binary for t+-dt
    # t is the target value I want in the matrix A with tolerance dt
    new_A = np.copy(A)
    new_A[np.logical_and(new_A > t-dt, new_A < t+dt)] = -1
    new_A[new_A != -1] = 0
    new_A[new_A == -1] = 1
    return (new_A)

def get_surface (X, Y, Z, new_A):
    x_vals = []
    y_vals = []
    z_vals = []

    # Retrieve (x,y,z) coordinates of surface
    for i in range(new_A.shape[0]):
        for j in range(new_A.shape[1]):
            for k in range(new_A.shape[2]):
                if new_A[i,j,k] == 1.0:
                    x_vals.append(X[i,j,k])
                    y_vals.append(Y[i,j,k])
                    z_vals.append(Z[i,j,k])

    return (np.array(x_vals), np.array(y_vals), np.array(z_vals))

cleaned_A = clean (A, t=2.5, dt=0.001)
x_f, y_f, z_f = get_surface (X, Y, Z, cleaned_A )

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', aspect='equal')
ax.scatter(x_f, y_f, z_f, color='g', s=1)
def清洁(A、t、dt):
#为t+-dt生成二进制的函数
#t是我想要的矩阵A中的目标值,公差为dt
新的A=np.副本(A)
new_A[np.logical_and(new_A>t-dt,new_A
我也试过
ax.plot\u trisurf(x\u f,y\u f,z\u f)
,但这给了我一个连接不良的绘图。我猜数组中的值顺序可能会影响这一点,在这种情况下,是否有一个包可以使用点的随机顺序(例如,通过最小化表面积或类似的方式)进行某种3D插值曲面打印


我感兴趣的物体大致是球形的(即每(x,y)两个z)。我似乎找不到任何在封闭的3D曲面上进行三角剖分的有效示例,但可能我找的地方不对。

经过大量的挖掘,我想我已经找到了一个可行的解决方案(至少对于球体来说——在我尝试球体变形时会更新我的答案)。非常感谢那些帮助我思考正确道路的评论。我基本上使用了一个
ConvexHull
scipy.spatial
进行三角测量:

from matplotlib.tri import Triangulation
from scipy.spatial import ConvexHull

def clean (A, t, dt):
    # function for making A binary for t+-dt
    # t is the target value I want in the matrix A with tolerance dt
    new_A = np.copy(A)
    new_A[np.logical_and(new_A > t-dt, new_A < t+dt)] = -1
    new_A[new_A != -1] = 0
    new_A[new_A == -1] = 1
    return (new_A)

def get_surface (X, Y, Z, new_A):
    x_vals = []
    y_vals = []
    z_vals = []

    # Retrieve (x,y,z) coordinates of surface
    for i in range(new_A.shape[0]):
        for j in range(new_A.shape[1]):
            for k in range(new_A.shape[2]):
                if new_A[i,j,k] == 1.0:
                    x_vals.append(X[i,j,k])
                    y_vals.append(Y[i,j,k])
                    z_vals.append(Z[i,j,k])

    return (np.array(x_vals), np.array(y_vals), np.array(z_vals))

cleaned_A = clean (A, t=2.5, dt=0.001)
x_f, y_f, z_f = get_surface (X, Y, Z, cleaned_A )

Xs = np.vstack((x_f, y_f, z_f)).T
hull = ConvexHull(Xs)
x, y, z = Xs.T

tri = Triangulation(x, y, triangles=hull.simplices)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', aspect='equal')
ax.plot_trisurf(tri, z, color='g', alpha=0.1)
从matplotlib.tri导入三角剖分
从scipy.spatial导入convxhull
def清洁(A、t、dt):
#为t+-dt生成二进制的函数
#t是我想要的矩阵A中的目标值,公差为dt
新的A=np.副本(A)
new_A[np.logical_and(new_A>t-dt,new_A
您对绘图的形状了解多少?例如,有多少个z值对应于相同的x,y对?我认为
plot\u trisurf
是正确的方法。但是,正如您所注意到的,如果选定的点没有形成一个漂亮、平滑的曲面,则该操作将失败。作为第一步,我将使用
scipy.spatial.Delaunay
计算点云周围的外壳,然后绘制该三角剖分的点。@xg.plt.py该图将大致为一个球体,可能存在变形,但每个(x,y)对始终有两个z值。有没有办法将这些信息应用到绘图中?@PaulBrodersen谢谢你的提示。我对如何/为什么在
plot\u trisurf
之前实现Delaunay有点困惑(Delaunay不是
plot\u trisurf
中的默认训练规则,还是我遗漏了什么?)Matplotlib的
plot\u trisurf
确实默认使用Delaunay三角剖分,Delaunay三角剖分只考虑要进行三角剖分的x和y值。因此,如果同一个x,y对有多个可能的值,它最终会绘制垂直或接近垂直的三角形。因此,结果不是图形的表面,而是一堆三角形穿过图形。