
PyVista中点集采样失败(vtkValidPointMask=0)通常由默认单元定位器(cell locator)精度不足导致;通过显式指定locator='static_cell'可显著提升几何包含性判断的鲁棒性,确保所有位于网格内部或边界上的点均被正确插值。
pyvista中点集采样失败(`vtkvalidpointmask=0`)通常由默认单元定位器(cell locator)精度不足导致;通过显式指定`locator='static_cell'`可显著提升几何包含性判断的鲁棒性,确保所有位于网格内部或边界上的点均被正确插值。
在使用 pointset.sample(mesh) 对非结构化网格(如含矩形棱柱的 .vtk 文件)进行点采样时,部分点虽明显位于网格几何包围体内,却仍返回 vtkValidPointMask = 0 —— 这并非数据本身错误,而是 PyVista ≤ 0.44.2 版本中默认使用的动态单元定位器(vtkStaticCellLocator 的替代实现或未启用优化路径)在处理复杂/非均匀/薄层网格时存在数值容差与搜索策略缺陷,导致点-单元包含关系误判。
根本解决方法是显式指定高可靠性定位器:
pointset_sample = pointset.sample(mesh, locator='static_cell')
locator='static_cell' 启用 VTK 底层的 vtkStaticCellLocator,它预先构建空间划分加速结构(如BSP树),大幅提升点是否位于某单元内的判定精度与稳定性,尤其适用于:
- 非共形(nonconforming)或局部加密的网格;
- 具有细长、扁平或高纵横比单元的模型;
- 坐标尺度跨度大(如本例中 x/y 达 ±2500,z 范围仅 -400~1600)的场景。
✅ 正确示例(修复后):
import pyvista as pv
import numpy as np
from points import points
mesh = pv.read("mesh.vtk")
mesh.set_active_scalars('Resistivity[Ohm-m]')
pointset = pv.PointSet(points)
# 关键修复:强制使用 static_cell locator
pointset_sample = pointset.sample(mesh, locator='static_cell')
# 验证全部有效
mask = pointset_sample.point_data['vtkValidPointMask']
print(f"Valid points: {mask.sum()}/{len(mask)}") # 输出:128/128
print(f"All valid? {mask.all()}") # True
# 可视化(无红色无效点)
plot = pv.Plotter()
plot.add_mesh(pointset_sample, scalars='Resistivity[Ohm-m]',
cmap='turbo_r', render_points_as_spheres=True,
point_size=15, log_scale=True, clim=[5e0, 5e2])
plot.add_mesh(mesh, scalars='Resistivity[Ohm-m]',
opacity=0.3, show_edges=True, edge_opacity=0.7)
plot.show()
⚠️ 注意事项:
-
locator='static_cell'是当前最推荐方案,但会略微增加首次采样前的预处理时间(构建空间索引); - 若升级至 PyVista ≥ 0.45.0,该定位器已设为默认,无需手动指定;
- 避免使用
locator='cell'(旧版默认,不稳定)或locator=None(可能回退至低效策略); - 对于极端情况(如点恰好落在单元缝隙或浮点精度临界面),可结合
tolerance参数微调(需 PyVista ≥ 0.43.0):pointset.sample(mesh, locator='static_cell', tolerance=1e-6)
总结:采样失效本质是几何查询精度问题,而非数据或逻辑错误。主动指定 locator='static_cell' 是兼容性强、效果立竿见影的标准实践,应作为处理非结构化网格点采样的默认配置。










