3

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

洞穴扫描的搅拌机法线

然后将网格导出为 STL 文件。

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

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

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

pyvista 的屏幕截图显示法线矢量图,其中一堆指向内

OC_wellsliced.stlSTL 文件在这里

4

1 回答 1

2

您的案例的便利功能似乎有点方便了。

引擎盖下的作用是plot_normals()它访问cave.point_normals,而后者又调用cave.compute_normals(). include的默认参数compute_normals()consistent_normals=True,根据文档确实

执行一致的多边形排序。

还有一些其他参数暗示运行此过滤器时可能会发生黑魔法(例如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 屏幕截图中看到法线,所以我无法解决这个问题。点法线(与面法线相反)可能在两者之间的计算方式不同。对于平面多边形单元格,单元格法线应该明确定义。

于 2022-01-26T19:59:15.847 回答