Extra or missing triangle with vmtksurfaceendclipper script

Dear all,

I am using the vmtksurfaceendclipper script to clip the extremities of a segmentation and the output surface often contains either an extra or missing triangle part:

vmtksurfaceendclipper -ifile "C:/temp/debug-clip-3/input.vtk" -ofile "C:/temp/debug-clip-3/output.vtk"

vmtk1

I tried to process the script step by step and it seems that the extra/missing part is always connected to the (closest) point on the input surface provided via the SetClosestPoint method to the seamFilter. The issue is then visible on the vtkClipPolyData output:

# vmtkSurfaceEndClipper.py line 311

seamFilter = vtkvmtk.vtkvmtkTopologicalSeamFilter()
seamFilter.SetInputData(clippedSurface)
seamFilter.SetClosestPoint(seedPoint)
seamFilter.SetSeamScalarsArrayName(“SeamScalars”)
seamFilter.SetSeamFunction(plane)

clipper = vtk.vtkClipPolyData()
clipper.SetInputConnection(seamFilter.GetOutputPort())
clipper.GenerateClipScalarsOff()
clipper.GenerateClippedOutputOn()

vmtk2

Is there any modification I could make to the seamFilter or the Clipper to fix this issue ? Or any post processing of the surface I could try ?
I found this issue on VMTK Github (vmtksurfaceendclipper does not work consistently · Issue #169 · vmtk/vmtk · GitHub) that seems related to this problem.

Thanks a lot for any suggestion,
Antoine

Dear all,

After more investigations I think I found the cause of the issue.

I tried to clip a cylinder (vtk.vtkCylinderSource()) providing an input point on the surface and a normal vector along the cylinder axis. These 2 inputs then define the cutting plane (displayed below as the red line) and provided as input to the seamFilter (vtkvmtkTopologicalSeamFilter).

vmtk3

I had a look at the scalar output of the seamFilter (vtkvmtkTopologicalSeamFilter) for each points around the desired cropping plane:

vmtk4

Here I was surprised to find out that the SeamScalars value of closest point from my input was actually at 0.
I believe this is the reason why the clipper filter (vtk.vtkClipPolyData) called right after considers this point as part of the area to clip since it uses the SeamScalars array to clip the surface:

vmtk5

Looking into the seamFilter filter’s code (vtkvmtkTopologicalSeamFilter.cxx) I realized that this point will be defined as the closest point to the implicit plane and then be the starting point of the global analysis (first point in the seamQueue).

However it seems to me that the seamArray value is never filed for the specific point compared to all of its neighbors (no seamArray->SetValue(…) for this point) making the final value the same as the initialization 0. Maybe adding something like seamArray->SetValue(point0Id,point0Value); line 175 would help ?

To bypass the issue I manually set the seamValue of this specific point (after the seamFilter execution) to the distance between the point and the plane plane.FunctionValue(pointPosition) and then recall the clipper filter which here provide me the desired output:

vmtk6

I hope this can be useful, tell me if you have any comments or suggestions.

Thank you,
Antoine

1 Like

It would be awesome if you could submit a pull request with a proposed fix.

No problem, I’ll be happy to contribute. I will prepare a pull request soon.

1 Like