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

使用Axes3D.voxels绘制三维整数点列表时遇维度错误的解决方案咨询

Axes3D.voxels绘制三维整数点列表时遇维度错误的解决方案咨询

我明白你遇到的问题了——Axes3D.voxels() 确实不接受直接传入三维点列表,它需要的是一个三维布尔数组来标记每个体素位置是否被填充。下面我来帮你分析错误原因,并给出两种可行的解决方案:

错误原因解析

你传入的cap和body是二维的点列表(每个元素是[x,y,z]坐标),但voxels()要求第一个参数必须是形状为(x_dim, y_dim, z_dim)的三维数组,用来表示空间中每个体素的填充状态,这就是为什么会抛出ValueError: Argument filled must be 3-dimensional的原因。另外你代码里的点筛选逻辑也有语法错误,比如cap = [lambda p : p[2] == roof - 1, crust]这种写法无法正确筛选点,需要调整。

解决方案一:将点列表转换为三维布尔数组

既然你的点范围是(-15,-15,0)到(15,15,9),我们可以先把这些坐标转换为非负的数组索引,再创建对应大小的三维布尔数组,标记出存在体素的位置。具体步骤如下:

  1. 先修正点筛选的逻辑:
# 正确筛选顶部和主体的点
roof = 8
cap_points = [p for p in crust if p[2] == roof - 1]
body_points = [p for p in crust if p[2] < roof - 1] if level > 1 else None
  1. 将点列表转换为三维布尔数组:
import numpy as np

# 把所有点转为numpy数组方便处理
all_points = np.array(crust)

# 计算偏移量,让所有坐标转为非负(数组索引不能为负)
x_offset = -np.min(all_points[:, 0])
y_offset = -np.min(all_points[:, 1])
z_offset = -np.min(all_points[:, 2])

# 计算每个维度的总大小
x_size = np.max(all_points[:, 0]) + x_offset + 1
y_size = np.max(all_points[:, 1]) + y_offset + 1
z_size = np.max(all_points[:, 2]) + z_offset + 1

# 创建全False的三维布尔数组
filled = np.zeros((x_size, y_size, z_size), dtype=bool)

# 标记所有存在体素的位置
for x, y, z in all_points:
    filled[x + x_offset, y + y_offset, z + z_offset] = True

# 拆分顶部和主体的体素数组
cap_filled = filled.copy()
target_z_idx = (roof - 1) + z_offset
# 只保留顶部层的体素
cap_filled[:, :, :target_z_idx] = False
cap_filled[:, :, target_z_idx+1:] = False

body_filled = filled.copy() if body_points else None
if body_filled is not None:
    # 只保留主体层的体素
    body_filled[:, :, target_z_idx:] = False
  1. 用转换后的数组绘制体素:
# 绘制顶部体素
ax.voxels(cap_filled, facecolors=colors[0], edgecolors=colors[1])
# 绘制主体体素(如果存在)
if body_filled is not None:
    ax.voxels(body_filled, facecolors=colors[1], edgecolors=colors[0])
screen.draw()

解决方案二:直接绘制单个立方体(替代voxels)

如果你不想创建庞大的三维数组,也可以手动为每个点绘制对应的立方体。Matplotlib的mpl_toolkits.mplot3d.art3d模块提供了Cube3D类,可以用来创建单个立方体:

from mpl_toolkits.mplot3d.art3d import Cube3D

def draw_cube(ax, x, y, z, face_color, edge_color):
    # 以整数坐标为中心,绘制边长为1的立方体
    cube = Cube3D([x-0.5, y-0.5, z-0.5], 1, 1, 1)
    cube.set_facecolor(face_color)
    cube.set_edgecolor(edge_color)
    ax.add_artist(cube)

# 绘制顶部点的立方体
for x, y, z in cap_points:
    draw_cube(ax, x, y, z, colors[0], colors[1])

# 绘制主体点的立方体
if body_points:
    for x, y, z in body_points:
        draw_cube(ax, x, y, z, colors[1], colors[0])

# 调整坐标轴范围适配立方体
ax.set_xlim(-15.5, 15.5)
ax.set_ylim(-15.5, 15.5)
ax.set_zlim(-0.5, 9.5)
screen.draw()

补充说明

  • 方案一适合体素分布比较密集的情况,绘制效率更高;方案二更适合点数量较少的场景,节省内存。
  • 你代码中原来的map变量名建议修改,因为map是Python内置函数,避免命名冲突。

备注:内容来源于stack exchange,提问作者David Wallace

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:45:29