为什么 vtk 中网格上的法线根据网格颜色不同?

Why normals on a mesh in vtk are different acording to mesh color?

我正在尝试为每个顶点计算 vtk 中网格的法线。 当我显示它们时,绿色顶点的法线顶点似乎比白色顶点的长度更小。 我不明白为什么会得到这个结果。

为了给网格着色,我使用了这个函数:

def update_colors(self,couleurs=None,Vertex_correspondance=None):
    Colors = vtk.vtkUnsignedCharArray()
    Colors.SetNumberOfComponents(3)
    Colors.SetName("Colors")
    for i in range(self.points.shape[0]):
        if not i in Vertex_correspondance :
            Colors.InsertNextTuple3(255,255,255)
        else:
            Colors.InsertNextTuple3(couleurs[0] ,  couleurs[1] , couleurs[2])
    self.GetOutput.GetPointData().SetScalars(Colors)
    self.GetOutput.Modified()

所以我为网格的某些顶点(30 个顶点)指定了绿色。

为了计算法线,我使用:

        poly_data = self.actor.GetMapper().GetInput()

        normalsCalc = vtk.vtkPolyDataNormals()

        normalsCalc.SetInputData(poly_data)
        normalsCalc.ComputePointNormalsOn()
        normalsCalc.ComputeCellNormalsOff()
        normalsCalc.SplittingOff()
        normalsCalc.FlipNormalsOff()
        normalsCalc.ConsistencyOn()
        normalsCalc.AutoOrientNormalsOn()
        normalsCalc.Update()

        arrowSource = vtk.vtkArrowSource()

        glyph3D = vtk.vtkGlyph3D()
        glyph3D.SetSourceConnection(arrowSource.GetOutputPort())
        glyph3D.SetVectorModeToUseNormal()
        glyph3D.SetInputData(normalsCalc.GetOutput())
        glyph3D.SetScaleFactor(0.02)
        glyph3D.OrientOn()
        glyph3D.Update()

        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputConnection(glyph3D.GetOutputPort())

        self.glyphActor = vtk.vtkActor()
        self.glyphActor.SetMapper(mapper)
        self.glyphActor.GetProperty().SetColor([0, 0, 1])

这是我得到的显示

此外,如果我在

之后计算法线长度
    normals = []
    array = normalsCalc.GetOutput().GetPointData().GetNormals()
    for i in range(array.GetNumberOfTuples()):
        normals.append(array.GetTuple(i))
    self.Normals = np.array(normals)
    np.linalg.norm(self.Normals,axis=1)

我的数字非常接近 1。 所以法线似乎计算得很好...

也许你需要使用 SetScaleModeToDataScalingOff(),这似乎有效:

from vedo import Ellipsoid, show
import vtk

s = Ellipsoid().computeNormals()
arr = s.points()[:,2]
s.cmap('jet_r', arr)

arrowSource = vtk.vtkArrowSource()
glyph3D = vtk.vtkGlyph3D()
glyph3D.SetSourceConnection(arrowSource.GetOutputPort())
glyph3D.SetVectorModeToUseNormal()
glyph3D.SetInputData(s.polydata())
glyph3D.SetScaleFactor(0.2)
glyph3D.OrientOn()
glyph3D.SetScaleModeToDataScalingOff() ###### <--
glyph3D.Update()

show(s, glyph3D, axes=1)