如何在Plotly中使用非方形X、Y、Z数组绘制3D网格曲面?
如何在Plotly中使用非方形X、Y、Z数组绘制3D网格曲面?
这个问题我之前也碰到过!其实核心原因是Plotly的Surface组件依赖二维网格结构,而Mesh3d如果只传顶点坐标的话,它不知道怎么把这些点连接成面。下面给你两种可行的解决方案,看哪种更适合你的场景:
方法一:保留原二维网格,直接遮罩无效点
这是最省心的方案——不用把数组扁平化,直接在生成的(100,100)二维数组上,把z>0.8的位置设为np.nan,Plotly的Surface会自动跳过这些NaN值,完美保留曲面的规整网格结构。
import numpy as np import plotly.graph_objs as go from plotly.offline import plot r = 1000 u, v = np.mgrid[0:2 * np.pi:100j, 0:np.pi:100j] x = np.cos(u) * np.sin(v) y = np.sin(u) * np.sin(v) z = np.cos(v) # 直接遮罩z>0.8的点,设为NaN即可 z[z > 0.8] = np.nan # 沿用你原来的布局设置 titlecolor = 'white' bgcolor = 'black' noaxis = dict(showbackground=False, showgrid=False, showline=False, showticklabels=False, ticks='', title='', zeroline=False) layout = go.Layout(autosize=True, titlefont=dict(family='Courier New', color=titlecolor), showlegend=False, scene=dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis, aspectmode='auto'), paper_bgcolor=bgcolor, plot_bgcolor=bgcolor) fig = go.Figure(data=go.Surface(x=x, y=y, z=z, opacity=0.2), layout=layout) plot(fig, validate=False, auto_open=True)
方法二:对一维散点进行三角剖分,用Mesh3d渲染
如果你已经处理完得到了一维的(x,y,z)数组(比如形状为(7900,1)),那可以通过三角剖分告诉Plotly如何连接这些点。我们可以用scipy.spatial.Delaunay生成面的索引,再传给Mesh3d的i、j、k参数:
import numpy as np import plotly.graph_objs as go from plotly.offline import plot from scipy.spatial import Delaunay # 假设你已经得到了处理后的一维数组x,y,z(形状(7900,1)) # 先转换成一维扁平数组 x = x.flatten() y = y.flatten() z = z.flatten() # 基于xy平面投影做Delaunay三角剖分,生成面的索引 points = np.column_stack((x, y)) tri = Delaunay(points) i, j, k = tri.simplices.T # 沿用你原来的布局设置 titlecolor = 'white' bgcolor = 'black' noaxis = dict(showbackground=False, showgrid=False, showline=False, showticklabels=False, ticks='', title='', zeroline=False) layout = go.Layout(autosize=True, titlefont=dict(family='Courier New', color=titlecolor), showlegend=False, scene=dict(xaxis=noaxis, yaxis=noaxis, zaxis=noaxis, aspectmode='auto'), paper_bgcolor=bgcolor, plot_bgcolor=bgcolor) # 传入顶点坐标和面索引,用Mesh3d渲染 fig = go.Figure(data=go.Mesh3d(x=x, y=y, z=z, i=i, j=j, k=k, opacity=0.2), layout=layout) plot(fig, validate=False, auto_open=True)
如果你觉得手动写剖分代码麻烦,也可以用Plotly封装好的create_trisurf工具,它会自动处理三角剖分:
from plotly.figure_factory import create_trisurf # 基于一维点集生成三角曲面 fig = create_trisurf(x=x, y=y, z=z, opacity=0.2) # 应用你原来的布局 fig.update_layout(layout) plot(fig, validate=False, auto_open=True)
小结
- 优先选方法一,它保留了原有的网格结构,渲染出的曲面更规整,代码也更简单;
- 如果必须处理一维点集,再用方法二的三角剖分方案,适合更灵活的点集场景。
备注:内容来源于stack exchange,提问作者AaronJPung
相关产品推荐
相关产品推荐

