
PyVista 的 glyph() 方法不接受原始 NumPy 数组作为 orient 参数,而需先将矢量数据以字段名形式添加到 PolyData 对象中,再通过字符串指定该字段名来驱动朝向。
pyvista 的 `glyph()` 方法不接受原始 numpy 数组作为 `orient` 参数,而需先将矢量数据以字段名形式添加到 `polydata` 对象中,再通过字符串指定该字段名来驱动朝向。
在 PyVista 中为点云(如晶格顶点)添加带方向的箭头(例如自旋矢量),关键在于正确绑定矢量数据与几何体。常见错误是直接将归一化后的 NumPy 数组(如 normed_spins)传给 glyph(orient=...),这会触发 ValueError: The truth value of an array with more than one element is ambiguous —— 因为 PyVista 将 orient 参数视为布尔开关或字段名称,而非实际数据。
✅ 正确做法是:
- 将矢量数组以键值对形式赋给 PolyData 对象(即 lattice['vectors'] = normed_spins);
- 在 glyph() 中通过字符串 'vectors' 指定该字段用于朝向控制;
- 确保矢量数组形状为 (n_points, 3),且已归一化(避免因长度差异导致箭头缩放失真)。
以下是修正后的完整示例代码:
import numpy as np
import pyvista as pv
cols = 12
rows = 12
spacing = 10.0
# 构建六方晶格点坐标
points = []
for i in range(rows):
for j in range(cols):
x = j * spacing
y = i * (spacing * np.sqrt(3) / 2)
if i % 2 == 1:
x += spacing / 2
points.append([x, y, 0.0])
points = np.array(points)
# 随机生成单位长度自旋矢量(-1/+1 各分量,再归一化)
spins = np.random.choice([-1, 1], size=(len(points), 3))
normed_spins = spins / np.linalg.norm(spins, axis=1, keepdims=True) # ✅ 使用 keepdims=True 更清晰
# 创建 PolyData 并绑定矢量字段
lattice = pv.PolyData(points)
lattice['vectors'] = normed_spins # ✅ 关键:注册为 point-data 字段
# 调用 glyph:orient='vectors' 表示使用名为 'vectors' 的点数据定向箭头
arrows = lattice.glyph(
orient='vectors', # ✅ 字符串字段名,非数组
scale=True, # 启用缩放(默认按矢量模长,此处因已归一化,效果一致)
factor=0.5, # 整体缩放系数,控制箭头长度
geom=pv.Arrow(), # 显式指定箭头几何体(可选,默认亦为箭头)
)
# 可视化
plotter = pv.Plotter()
plotter.add_mesh(lattice, color="black", point_size=6, render_points_as_spheres=True, label="Lattice Points")
plotter.add_mesh(arrows, color="red", label="Spin Vectors")
plotter.show_bounds(grid="front", location="outer", all_edges=True)
plotter.add_legend()
plotter.show(title="Spin Vectors on Hexagonal Lattice")
⚠️ 注意事项:
- orient 和 scale 所依赖的数据必须同为 point data 或 cell data;本例中 lattice['vectors'] 自动成为点数据,符合要求;
- 若未显式调用 lattice.point_data.keys(),可通过 print(lattice) 查看已注册的字段;
- glyph() 默认使用 pv.Arrow() 作为几何模板,但也可传入自定义 geom(如 pv.Cone())实现不同图元;
- 若需按标量着色(如自旋 z 分量),可在 add_mesh() 中设置 scalars='vectors' 并配合 vector_mode='magnitude' 或 vector_mode='z'。
掌握这一数据绑定范式,即可稳定扩展至更复杂的矢量场可视化任务(如磁场、流速、应力方向等)。











