【问题标题】:Matplotlib like matlab's trisurfMatplotlib 类似于 matlab 的 trisurf
【发布时间】:2014-08-24 23:13:04
【问题描述】:

长话短说,我想在 python 中绘制一个通用的 3D 三角形网格。 Matplotlib 似乎是理想的候选者,但我会选择任何可以完成我将要描述的内容的 3D 渲染。

假设我有一个由 X、Y 和 Z 定义的三角形网格,点云的 3D 坐标,每个长度为 n 的向量,以及 UVW,一个 2D mx-3 矩阵,其中每一行是一个三元组索引到点云中。这个三元组代表一个单独的三角形。换句话说,我在 n 个点上有 m 个三角形。在 Matlab 中,要生成 3D 图,我只是这样做:

trisurf(UVW, X, Y, Z)

有人有这方面的经验吗?特别是,mplots trisurf 是否可以硬塞到工作中?

【问题讨论】:

  • Matplotlib 肯定不是 3D 绘图的最佳选择。你考虑过mayavi吗?它更适合 3D 事物。
  • mayavi 可能是要走的路,但我希望有一个更轻的解决方案。这些效果图可能是为期刊论文设计的。

标签: python matlab matplotlib 3d mesh


【解决方案1】:

根据您的性能需求,mayavi 可能最适合此 - 根据 Davis 的评论。

但是,matplotlib 带有plot_trisurf,您可以完美地将通用UVWXYZ 传递给您所描述的。

以环面网格为例:

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

R = 1.
r = 0.8
n = 50
m = 50

def torus_triangles(n, m):
    """ Returns triangles to mesh a (n, m) torus """
    tri = []
    for i in range(n):
        for j in range(m):
            a = i + j*(n)
            b = ((i+1) % n) + j*n
            d = i + ((j+1) % m) * n
            c = ((i+1) % n) + ((j+1) % m) * n
            tri += [[a, b, d], [b, c, d]]
    return np.array(tri, dtype=np.int32)

theta0 = np.linspace(0, (2*np.pi), n, endpoint=False)
phi0 = np.linspace(0, (2*np.pi), m, endpoint=False)
theta, phi = np.meshgrid(theta0, phi0)

x = (R + r * np.sin(phi)) * np.cos(theta)
y = (R + r * np.sin(phi)) * np.sin(theta)
z = r * np.cos(phi)

triangles = torus_triangles(n , m)
triang = mtri.Triangulation(x.ravel(), y.ravel(), triangles)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(triang, z.ravel(), lw=0.2, edgecolor="black", color="grey",
                alpha=0.5)

plt.show()

【讨论】:

  • 谢谢!这非常接近,但看起来它需要 X、Y 和 Z 存在于矩形网格上,而在我的情况下,它们不需要。
  • 不需要在矩形网格上,事实上,如果你查看网格,我必须将每个矩形分成 2 个三角形才能使用“plot_trisurf”。
【解决方案2】:

我也在寻找解决这个问题的方法,这次讨论帮助我成功了。以下是它的工作原理:

  1. GBy 的评论中已经给出了一个非常相似的问题的解决方案(见上文:Colouring the surface of a sphere with a set of scalar values in matplotlib

  2. 将知识转移到此处的问题会导致创建一个包含幅度的附加数组并将其分配给“通过set_array 方法的基础ScalarMappable”。对应的python代码如下:

    from mpl_toolkits.mplot3d import Axes3D
    from matplotlib import cm
    from matplotlib import pyplot as plt
    import numpy as np
    
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    colors = np.mean(CorticalImage[Face], axis=1)
    collec = ax.plot_trisurf(Xcoordinates, Ycoordinates, Zcoordinates, triangles=Face, cmap=cm.jet, linewidth=0.2)
    collec.set_array(colors)
    collec.autoscale()
    ax.view_init(30, 0)
    cbar = fig.colorbar(collec)
    

数组XcoordinatesYcoordinatesZcoordinates 包含网格节点的 X、Y 和 Z 坐标。当检查它们的形状时,例如Xcoordinates.shape 它应该看起来像这样 (750,),其中 750 是网格节点的数量。矩阵Face 与Larry 提出的原始问题中的矩阵UVW 相同。它是“一个 2D m-x-3 矩阵,其中每一行都是指向点云的索引的三元组”。如果您检查矩阵Face 的形状,它应该类似于(1496, 3),其中1496 是网格中的三角形数,3 是一个三角形中的节点数。最后,数组CorticalImage 包含网格中每个节点的振幅,这些是我们想要用于网格颜色的值(而不是 Z 值)。该数组的形状应该类似于坐标数组的形状,即(750,)

重要!!!可以看到节点数和三角形数不相等。几乎总是这样。此外,幅度通常是为节点而不是三角形给出的。因此,应该计算三角形的幅度,以便在图中获得正确的颜色。这是在colors = np.mean(CorticalImage[Face], axis=1) 行中完成的。

【讨论】:

    【解决方案3】:

    Plotly 有一个开源的 trisurf Python 实现,它更接近于 MATLAB 的 trisurf()。

    此处为 Python 代码和示例:

    https://plot.ly/python/tri-surf/

    【讨论】:

    • 虽然这在理论上可以回答问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
    【解决方案4】:

    为了完整起见,我将在此处添加一个 mayavi 示例,使用 GBy 答案中的网格。

    import numpy as np
    from mayavi import mlab 
    from tvtk.api import tvtk
    
    R = 1.
    r = 0.8
    n = 50
    m = 50
    
    def torus_triangles(n, m):
        """ Returns triangles to mesh a (n, m) torus """
        tri = []
        for i in range(n):
            for j in range(m):
                a = i + j*(n)
                b = ((i+1) % n) + j*n
                d = i + ((j+1) % m) * n
                c = ((i+1) % n) + ((j+1) % m) * n
                tri += [[a, b, d], [b, c, d]]
        return np.array(tri, dtype=np.int32)
    
    theta0 = np.linspace(0, (2*np.pi), n, endpoint=False)
    phi0 = np.linspace(0, (2*np.pi), m, endpoint=False)
    theta, phi = np.meshgrid(theta0, phi0)
    
    x = (R + r * np.sin(phi)) * np.cos(theta)
    y = (R + r * np.sin(phi)) * np.sin(theta)
    z = r * np.cos(phi)
    
    triangles = torus_triangles(n , m)
    
    mesh = mlab.triangular_mesh(x,y,z, triangles, representation='wireframe',color=(0,0,1) )
    
    mlab.show()
    

    产量:

    【讨论】:

      猜你喜欢
      • 2020-12-29
      • 2021-06-17
      • 2014-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多