如何在Matplotlib 3D中填充选中的网格单元?
3D网格中高效绘制填充单元的解决方案
我需要在Ngrid×Ngrid×Ngrid的3D网格中填充Ncell个单元。目前用散点图绘制每个单元的中心,但想替换为给每个单元填充颜色。实际网格规模为1000³,Ncell量级为10^5,需要高效的代码。
针对大规模场景,以下两种方法均采用向量化/批量操作,避免低效循环,可轻松处理1e5量级的单元:
方法1:使用voxels(最优选择,性能最高)
voxels是matplotlib原生的3D网格绘制函数,底层基于numpy向量化实现,处理大规模数据效率极高。
import numpy as np import matplotlib.pyplot as plt Ngrid, Ncell = 100, 150 # 随机选中单元的网格索引(对应单元的起始角点) xx = np.random.choice(Ngrid, Ncell) yy = np.random.choice(Ngrid, Ncell) zz = np.random.choice(Ngrid, Ncell) %matplotlib widget fig = plt.figure(figsize=(10, 7)) ax = plt.axes(projection="3d") # 创建网格掩码:标记需要填充的单元 mask = np.zeros((Ngrid, Ngrid, Ngrid), dtype=bool) mask[xx, yy, zz] = True # 绘制填充单元,自定义颜色和边框样式 ax.voxels(mask, facecolors='cornflowerblue', edgecolors='lightgray', alpha=0.5) # 设置坐标轴范围匹配网格尺寸 ax.set_xlim(0, Ngrid) ax.set_ylim(0, Ngrid) ax.set_zlim(0, Ngrid) plt.show()
自定义颜色扩展
如果需要给不同单元设置不同颜色,可将facecolors替换为与mask同形状的颜色数组:
# 生成随机RGB颜色数组 colors = np.random.rand(Ngrid, Ngrid, Ngrid, 3) ax.voxels(mask, facecolors=colors, edgecolors='lightgray', alpha=0.5)
方法2:批量生成立方体顶点,用Poly3DCollection绘制
如果需要更灵活的立方体样式(比如自定义边长、顶点位置),可通过numpy批量生成所有立方体的顶点,一次性添加到集合中,避免逐个绘制的低效操作。
import numpy as np from mpl_toolkits.mplot3d.art3d import Poly3DCollection import matplotlib.pyplot as plt Ngrid, Ncell = 100, 150 xx = np.random.choice(Ngrid, Ncell) yy = np.random.choice(Ngrid, Ncell) zz = np.random.choice(Ngrid, Ncell) %matplotlib widget fig = plt.figure(figsize=(10, 7)) ax = plt.axes(projection="3d") # 定义边长为1的立方体顶点模板(以原点为起始角点) cube_template = np.array([ [0,0,0], [1,0,0], [1,1,0], [0,1,0], # 底面 [0,0,1], [1,0,1], [1,1,1], [0,1,1] # 顶面 ]) # 批量生成所有选中单元的立方体顶点:给模板加上每个单元的偏移量 all_cubes = cube_template[None, ...] + np.stack([xx, yy, zz], axis=1)[:, None, :] # 定义立方体的6个面(每个面由4个顶点的索引组成) cube_faces = [ [0,1,2,3], [4,5,6,7], # 底面、顶面 [0,1,5,4], [1,2,6,5], [2,3,7,6], [3,0,4,7] # 四个侧面 ] # 批量展开所有面的顶点数据 all_faces = all_cubes[:, cube_faces].reshape(-1, 4, 3) # 创建3D多边形集合并添加到坐标轴 cube_collection = Poly3DCollection(all_faces, facecolors='coral', edgecolors='gray', alpha=0.5) ax.add_collection3d(cube_collection) # 设置坐标轴范围 ax.set_xlim(0, Ngrid) ax.set_ylim(0, Ngrid) ax.set_zlim(0, Ngrid) plt.show()
自定义颜色扩展
如果需要给每个立方体单独设置颜色,可给facecolors传入长度为Ncell*6的颜色列表(每个立方体6个面):
# 每个立方体的6个面使用同一种随机颜色 cube_colors = np.repeat(np.random.rand(Ncell, 3), 6, axis=0) cube_collection = Poly3DCollection(all_faces, facecolors=cube_colors, edgecolors='gray', alpha=0.5)
内容的提问来源于stack exchange,提问作者deltasata
相关产品推荐
相关产品推荐

