顶点法线在 PyVista 和 Blender 中看起来不同

Vertex normals look different in PyVista and Blender

我正在处理一个洞穴的网格,并使用 Blender(编辑模式 -> 选择面 -> 翻转法线)手动将所有面法线设置为 'correct'(所有面朝外) ).我还在 Blender 中可视化了顶点法线,它们在整个表面都指向外:

网格随后导出为 STL 文件。

然而,现在,当我使用以下代码在 Pyvista 中可视化相同的东西时:

import pyvista as pv
cave = pv.read("data/OC_wellsliced.stl")
cave.plot_normals()

法线指向非常不同的方向(下方),有时甚至是相反的方向。如果能帮助理解这种差异,我们将不胜感激!

OC_wellsliced.stl STL 文件是 here

你的案例的便利功能似乎方便了。

plot_normals() 在幕后所做的是它访问 cave.point_normals,后者又调用 cave.compute_normals()The default arguments to compute_normals() 包括 consistent_normals=True,根据文档

Enforcement of consistent polygon ordering.

当 运行 这个过滤器(例如 auto_orient_normalsnon_manifold_ordering,即使默认值看起来安全)时,还有一些其他参数暗示潜在的黑魔法。

所以似乎发生的是你的网格(非流形,即它有开放的边缘)打破了 compute_normals 试图用默认的“强制多边形排序”做的魔法。由于您已经在 Blender 中执行了正确的顺序,您可以告诉 pyvista(好吧,VTK)不要理会您的多边形,只按原样计算法线。这无法通过 plot_normals(),因此您需要做更多的工作:

import pyvista as pv

# read data
cave = pv.read("OC_wellsliced.stl")

# compute normals
# cave = cave.compute_normals()  # default (wrong) behaviour
cave = cave.compute_normals(consistent_normals=False)  # correct behaviour

# plot the normals manually; plot_normals() won't work
plotter = pv.Plotter()
plotter.add_mesh(cave, color='silver')
plotter.add_mesh(cave.glyph(geom=pv.Arrow(), orient='Normals'), color='black')
plotter.view_vector([-1, -1, 1])
plotter.show()

您可以取消注释对 compute_normals() 的默认调用以重现 plot_normals() 的原始行为。更重要的是,您现在在网格上拥有名为 'Normals' 的点和元胞数组,可用于任何类型的后处理。而且这些保证是正常的,因为它们正是我们在上图中绘制的。


我现在注意到你也说了“在非常不同的 [...] 方向上”;我专注于标志翻转。不幸的是,很难在您的 Blender 屏幕截图中看到法线,所以我无法解决这个问题。点法线(与面法线相反)在两者之间的计算方式可能不同。对于扁平的多边形单元格,单元格法线应该是 well-defined。