You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 15:08:08