I’m trying to transform the points and normals of a polydata but part of the normals are negated after transformation. I transform the normals by multiplying them with the transposed and inverted transformation matrix

const transposedMatrix = mat4.create();
mat4.transpose(transposedMatrix, transformMatrix);
const normalsMatrix = mat4.create();
mat4.invert(normalsMatrix, transposedMatrix);
const pointData = polydata.getPoints().getData();
const normalsData = polydata.getCellData().getNormals().getData();
// modify point data
vtkMatrixBuilder
.buildFromDegree()
.setMatrix(transformMatrix)
.apply(pointData);
// modify normals
vtkMatrixBuilder
.buildFromDegree()
.setMatrix(normalsMatrix)
.apply(normalsData);
// explicitly set the point data again. This is needed because otherwise the bounds don't get updated
polydata.getPoints().setData(pointData);

This updates the points but about half of the normals are negated. I know this because when I manually negate all normals:

So you have inconsistency on the normal orientations in your input data.

Could you try using vtkPolyDataNormals on the output of the reader? This would compute the normals from scratch, and it should give orientation consistency. You can play with AutoOrientNormals and / or FlipNormals to get the result you want.

I’m using vtk-js and I believe that the vtkPolyDataNormals hasn’t been implemented yet (related issue). I maybe should have mentioned this already but without the transformation everything displays correctly. It’s only after the transformation that the normals are negated. Could it still be an issue with the input data?

If the normals are correct before you transform them, it doesn’t seem to be an issue with your input data… In what you are displaying, it almost looks like normals pointing in one direction (is it x, y or z?) get flipped. Can you share your transform matrix? (before transposition and inversion)

I use vtkLandmarkTransform to calculate the transformation matrix. So I have a bunch of points on the ios (structure you see in the picture and that should be transformed) and a structure I want to align it with.

Be careful, this rule is for normals that are expressed in homogeneous coordinates, but VTK stores its normals as (x,y,z). The math requires computing the w component prior to the matrix multiplication. For example, see VTK’s normal transformation code here.

In your case, it will work, but only because you are working with a rigid-body transformation (and note that for rigid-body transformations you can use the transformation matrix directly, you don’t have to take the transposed inverse).

My recommendation would be to use vtkTransformPolyDataFilter to transform the data.

Correction to my post above: even with a rigid-body transformation, it’s incorrect to multiply the (x,y,z) normal by the transposed inverse. The reason is that the normals are only to be transformed by the rotation part of the transform, while the translation part of the transform must have no effect.

However, for rigid-body transforms it is okay to simply set the ‘w’ component of the normal to zero before the multiplication: (x,y,z,0) as opposed to the (x,y,z,1) that is used for homogeneous point coordinates.