Non-manifold caused by marching cube

I have a structured points data that I have prepared in such a way that my actual simulation data is in the middle surrounded by boundary points that all have the value of 0. My idea is that once I applied marching cube on it, I will get a mesh that is closed. The idea kind of work, and I indeed get a mesh that is closed around the boundary as expected. However, there seems to be a problem with manifold, with some triangle intersect with others. An image showing the orientation of faces is shown below (blue is outside and red is inside which is incorrect).
Screenshot from 2024-03-11 22-05-40

I have no idea how could this happen. From my understanding it should be impossible for marching cube algorithm to generate defective mesh. The code I use is very straightforward.

mc = vtkMarchingCubes()
reader = vtkStructuredPointsReader()
reader.SetFileName(Input_name + ".vtk")
mc.SetValue(0, threshold)

readerMC = mc.GetOutput()

stlWriter = vtkSTLWriter()
stlWriter.SetFileName(Output_name + ".stl")

I have tried vtkFlyingEdges3D and vtkCleanPolyData with not much luck. I also tried clipping these parts out and hopefully fix them with vtkClipClosedSurface which to my surprise, still have this non-manifold problem. The code I use is something along this line,

TinyVal = 0.01
BoundarySize = 255.0
plane1 = vtk.vtkPlane()
plane1.SetNormal(1, 0, 0)
plane1.SetOrigin(TinyVal, TinyVal, TinyVal)
plane2 = vtk.vtkPlane()
plane2.SetNormal(0, 1, 0)
plane2.SetOrigin(TinyVal, TinyVal, TinyVal)
plane3 = vtk.vtkPlane()
plane3.SetNormal(0, 0, 1)
plane3.SetOrigin(TinyVal, TinyVal, TinyVal)
plane4 = vtk.vtkPlane()
plane4.SetNormal(-1, 0, 0)
plane4.SetOrigin(BoundarySize - TinyVal, BoundarySize - TinyVal, BoundarySize - TinyVal)
plane5 = vtk.vtkPlane()
plane5.SetNormal(0, -1, 0)
plane5.SetOrigin(BoundarySize - TinyVal, BoundarySize - TinyVal, BoundarySize - TinyVal)
plane6 = vtk.vtkPlane()
plane6.SetNormal(0, 0, -1)
plane6.SetOrigin(BoundarySize - TinyVal, BoundarySize - TinyVal, BoundarySize - TinyVal)

coll = vtk.vtkPlaneCollection()
clip = vtk.vtkClipClosedSurface()

I should also add that until now I haven’t “pad” my simulation results with 0 and left the mesh open, in such cases marching cube works like a charm, but for my current situation I really need it to close so here we are. I am completely new to vtk so this is probably a very beginner question, but I would really appreciate any helps that you can provide.

To my eye this looks like the simulation data is bleeding through the isosurface. This could be due to resolution issues, but I’m not sure without more information. Please could you sketch a picture or otherwise depict what you are trying to do?

@will.schroeder Thanks you so much for the reply! Sure, this is our original simulation data (or at least isosurface of it).

As you can see, the surface is open around the simulation boundary (which is correct). However, for our current goal, we need the 3D model to be closed, so we want these surface to close when it touch the boundary (which corresponds to 6 planes I used in the original question). Due to our lack of experience in vtk, we thought that by simply adding one more layer of 0 enveloping the whole simulation data, marching cube will detect the change in value and close these open areas for us. It indeed does so but with the problem of manifold that I am trying to solve now.

I am sorry but I am not sure what you meant simulation data bleeding, all we did was add one more layer of 0 to the simulation result before we output vtk file. Can you guild me on how to check for any additional information that you may need ? I will be very happy to check and add more information here as soon as I can.

This is a result I made by ClipClosedSurface this open surfaces (I know this is not ideal), however the same result also appear when I use marching cube like the original question.

They are very small but you can see that around the edge between the isosurface and the plane, there are mysterious small edges that seems to goes inside other triangles (one of them is highlighted in white color).

I’m afraid that without seeing the actual data I can’t tell what’s happening.