如何用Python绘制XYZ轴对应RGB色彩的球面曲面图?
问题原因
你用go.Surface的surfacecolor传入了三维RGB数组,但Plotly的Surface组件的surfacecolor参数只接受二维标量数组,它会把输入的数组当作数值型数据,自动映射到默认的颜色条,所以无法呈现你想要的RGB着色效果。
解决方案
要实现按顶点XYZ坐标直接映射RGB颜色的球面,有两种可行方法:
方法1:改用Mesh3d组件(推荐)
go.Mesh3d的vertexcolor参数支持直接传入顶点的RGB数组(值范围0-1),完美匹配你的需求:
import plotly.graph_objects as go import numpy as np # 创建theta和phi网格 theta = np.linspace(0, 2 * np.pi, 100) phi = np.linspace(0, np.pi, 100) theta, phi = np.meshgrid(theta, phi) r = 1 # 球坐标转笛卡尔坐标 x = r * np.sin(phi) * np.cos(theta) y = r * np.sin(phi) * np.sin(theta) z = r * np.cos(phi) # 将XYZ坐标转为RGB值(取绝对值,确保在0-1区间) rgb = np.stack([np.abs(x), np.abs(y), np.abs(z)], axis=-1).reshape(-1, 3) # 将网格转为顶点和面数据(四边形面拆分为两个三角形) vertices = np.stack([x.flatten(), y.flatten(), z.flatten()], axis=1) i, j = np.meshgrid(np.arange(99), np.arange(99)) triangles1 = np.stack([i.flatten(), i.flatten()+1, j.flatten()*100 + i.flatten()], axis=1) triangles2 = np.stack([i.flatten()+1, j.flatten()*100 + i.flatten()+1, j.flatten()*100 + i.flatten()], axis=1) faces = np.vstack([triangles1, triangles2]) # 创建Mesh3d图 fig = go.Figure(data=[go.Mesh3d( x=vertices[:,0], y=vertices[:,1], z=vertices[:,2], i=faces[:,0], j=faces[:,1], k=faces[:,2], vertexcolor=rgb, # 直接传入顶点RGB数组 flatshading=True # 开启平面着色,让颜色过渡更自然 )]) # 设置场景比例 fig.update_layout(scene=dict(aspectmode="data")) fig.show()
方法2:用Surface组件+十六进制颜色字符串
如果坚持使用Surface,可以将RGB值转为十六进制颜色字符串,再传入surfacecolor:
import plotly.graph_objects as go import numpy as np theta = np.linspace(0, 2 * np.pi, 100) phi = np.linspace(0, np.pi, 100) theta, phi = np.meshgrid(theta, phi) r = 1 x = r * np.sin(phi) * np.cos(theta) y = r * np.sin(phi) * np.sin(theta) z = r * np.cos(phi) # 将0-1范围的RGB值转为十六进制字符串 def rgb_to_hex(rgb): r, g, b = (rgb * 255).astype(int) return f"#{r:02x}{g:02x}{b:02x}" # 生成二维颜色数组 color_array = np.vectorize(rgb_to_hex)(np.stack([np.abs(x), np.abs(y), np.abs(z)], axis=-1)) fig = go.Figure(data=[go.Surface( x=x, y=y, z=z, surfacecolor=color_array, # 传入十六进制颜色数组 colorscale=[[0, "#000000"], [1, "#ffffff"]], # 占位颜色条 showscale=False # 隐藏多余的颜色条 )]) fig.update_layout(scene=dict(aspectmode="data")) fig.show()
内容的提问来源于stack exchange,提问作者riddermarkdown
相关产品推荐
相关产品推荐

