# Remove faces in contact with non-manifold edges

**URL:** https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116
**Category:** Support
**Created:** [September 1, 2020, 1:23am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116 "2020-09-01T01:23:19Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![Lucas\_A](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/l/c5a1d2/32.png) [@Lucas\_A](https://discourse.vtk.org/u/Lucas_A)
#### Post date: [September 1, 2020, 1:23am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/1 "2020-09-01T01:23:19Z")

</div>

Hi,  
I have as input a (triangular) mesh that has some holes. I’m trying to execute the vtkFillHolesFilter to close all the holes. It works well for most of the holes, but some of them are not being closed. I discovered that these roles that are not being closed by the fill holes filter are surrounded by some non-manifold edges. Then I made some test on Meshlab, I selected all the non-manifold edges, deleted all faces that share these edges and executed the fill holes, and it closed everything perfectly. But now I want to execute this process with VTK.

I need to remove from my mesh (a vtkPolyData), all the faces that are in contact with non-manifold edges.

I was able to identify all the non-manifold edges with the vtkFeatureEdges filter, but I’m not sure how to proceed to delete the faces that share these edges.

The resulting mesh should be the original mesh without any non-manifold edge.

Right now I have this:

| vtkSmartPointer featureEdges = | vtkSmartPointer::New(); |
| --- | --- |
| | featureEdges-\>SetInputData(meshPolydata); |
| | featureEdges-\>BoundaryEdgesOff(); |
| | featureEdges-\>FeatureEdgesOff(); |
| | featureEdges-\>ManifoldEdgesOff(); |
| | featureEdges-\>NonManifoldEdgesOn(); |
| | featureEdges-\>Update(); |

But I’m not sure how to use the featureEdges-\>GetOutput() to delete the faces around the edges from my meshPolydata.

I would appreciate some help.

\*I also accept other possible solutions to remove all non-manifold edges from the mesh.

A picture from the process in Meshlab…

 ![123](https://discourse.vtk.org/uploads/default/original/2X/b/bccdfb61e8d1a720296ad2f256fd77bdf78c31ae.png)

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [March 10, 2021, 10:34pm UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/2 "2021-03-10T22:34:52Z")

</div>

We would like to do exactly the same (remove non-manifold edges and fill small holes). Can somebody give advice?

I remember that somebody mentioned that Kitware is working on a mesh cleanup filter. Is there any news about that?

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [March 11, 2021, 11:03am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/3 "2021-03-11T11:03:48Z")

</div>

For reasonably simple cases this shouldn’t be too hard (e.g., smaller holes, small non-manifold wings). But in general it can be quite hard (large holes, Klein bottles). Do you have sample data that you can post? We can add it to the list…

---

<div class="post-metadata">

### Author: ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)
#### Post date: [March 11, 2021, 3:22pm UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/4 "2021-03-11T15:22:55Z")

</div>

There is a [Manifold checker](https://topology-tool-kit.github.io/doc/html/classttk_1_1ManifoldCheck.html) in [TTK](https://topology-tool-kit.github.io/). Used with a threshold, you should be able to do something similar, without having to develop a new filter.

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [March 19, 2021, 7:34pm UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/5 "2021-03-19T19:34:23Z")

</div>

Interesting.

For a start…

Either use Manifold Checker (see @Charles_Gueunet’s reply) and threshold with link number. You’ll have to experiment in ParaView for this. Then carry on from step 1.

Or if you’d like to use VTK through and through,

Begin with an input triangulation(likely has some awful non-manifold edges) and two outputs of different feature edge filters. One of them `nmEdges` with only non-manifold edges and another `bndryEdges1` with only boundary edges.

1. Append global point Ids to input. Helps in later steps.

2. Insert all lines from `bndryEdges1` into a container. Importantly, we’d like to know if an edge is a boundary. Either create a vector-of-bool `isBoundary` for all edges of the input mesh or keep boundary edges in a map or set. Ex: `std::unordered_map<std::pair<vtkIdtype, vtkIdType>>`.

3. With help of line segments from `nmEdges`, locate triangles around those edges. No need to use cell locators, [`::GetPointCells()`](https://vtk.org/doc/nightly/html/classvtkPolyData.html#adf9caaa01f72972d9a986ba997af0ac7) should be fine. For the pointId arg, use the ids I appended to point-data in the previous step.

4. [`vtkPolyData::DeleteCell()`](https://vtk.org/doc/nightly/html/classvtkPolyData.html#a8500b4ee075729703e4c2d3570aec892)

5. [`vtkPolyData::RemoveDeletedCells()`](https://vtk.org/doc/nightly/html/classvtkPolyData.html#ac9cd46d47285b3f685eae193db9a4836)

6. I’ll call this `holeyMesh` cuz this has holes. Apply feature edges again, this time with _boundary edges:_ **on** and _non-manifold:_ **off**. I’ll call the output `bndryEdges2`.

7. Insert all line segments in `bndryEdges2` into a [`vtkMutableUndirectedGraph`](https://vtk.org/doc/nightly/html/classvtkMutableUndirectedGraph.html).

8. Now, remove line segments that make up the real boundary, i.e, edges from `bndryEdges1`. `isBoundary` from step 2 will help me here.

9. Reconstruct manifold polygons. I’ll keep these polys in `fillerPolys` since they’re supposed to fill holes. Maybe do it by hand or use [`vtkBoostConnectedComponents`](https://vtk.org/doc/nightly/html/classvtkBoostConnectedComponents.html) for that purpose. If I were using python up to now, I’d use [scipy.sparse.csgraph](https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.csgraph.connected_components.html#scipy.sparse.csgraph.connected_components) to identify connected components since vtk on PyPi does not enable boost at build time. You’ve been warned.

10. Insert each cell from `fillerPolys` into `holeyMesh` to cover the holes.

The mesh should hopefully be free from awful non-manifolds.

I might’ve made a certain choice of features from C++ STL and VTK to describe the algorithm. But, there could be other better alternatives.

I did a similar process by hand a lot of times in Blender. If you dig deep enough, someone might’ve written a python plugin to automate this procedure using Blender’s wonderful BMesh API 🙂

[BMesh-devdoc](https://wiki.blender.org/wiki/Source/Modeling/BMesh/Design), [BMesh-userdoc](https://docs.blender.org/api/current/bmesh.html)

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 8, 2022, 1:23am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/6 "2022-06-08T01:23:37Z")

</div>

Jaswant, I need to remove non-manifold edges from my model, which was generated from appending couple of models. I am trying to understand your steps outlined above and didn’t quiet get from step 6 onwards. Can you please take a look at the following code and help with the next steps.

def DeleteNonManifoldEdgs(polyData):

```
boundaryEdges = vtk.vtkFeatureEdges()
boundaryEdges.BoundaryEdgesOn()
boundaryEdges.FeatureEdgesOff()
boundaryEdges.NonManifoldEdgesOff()
boundaryEdges.ManifoldEdgesOff()
boundaryEdges.SetInputData(polyData)
boundaryEdges.Update()
bePolyData = boundaryEdges.GetOutput()

nmEdges = vtk.vtkFeatureEdges()
nmEdges.BoundaryEdgesOff()
nmEdges.FeatureEdgesOff()
nmEdges.NonManifoldEdgesOn()
nmEdges.ManifoldEdgesOff()
nmEdges.SetInputData(polyData)
nmEdges.Update()
nmePolyData = nmEdges.GetOutput()

#Mark the points on the polyData that needs to be deleted    
toDelete = vtk.vtkFloatArray()
toDelete.SetNumberOfComponents(1)
toDelete.SetNumberOfValues(polyData.GetNumberOfPoints())

for i in range(polyData.GetNumberOfPoints()):
    toDelete.SetValue(i, 0)

for ptId in range(nmePolyData.GetNumberOfPoints()):
    nmePnt = nmePolyData.GetPoint(ptId)
    vertId = polyData.FindPoint(nmePnt)
    toDelete.SetValue(vertId, 1)

cellIdList = vtk.vtkIdList()

#Delete the celles connected to nmEdges
for ptId in range(polyData.GetNumberOfPoints()):
    if toDelete.GetValue(ptId) == 0:continue
    polyData.GetPointCells (ptId, cellIdList) 
    
    for i in range(cellIdList.GetNumberOfIds()):
        polyData.DeleteCell(cellIdList.GetId(i))
    
polyData.RemoveDeletedCells()

boundaryEdges2 = vtk.vtkFeatureEdges()
boundaryEdges2.BoundaryEdgesOn()
boundaryEdges2.FeatureEdgesOff()
boundaryEdges2.NonManifoldEdgesOff()
boundaryEdges2.ManifoldEdgesOff()
boundaryEdges2.SetInputData(polyData)
boundaryEdges2.Update()
be2PolyData = boundaryEdges2.GetOutput()

```

Please suggest next steps.

Thank you

---

<div class="post-metadata">

### Author: ![jaswantp](https://discourse.vtk.org/user_avatar/discourse.vtk.org/jaswantp/32/10046_2.png) [@jaswantp](https://discourse.vtk.org/u/jaswantp)
#### Post date: [June 8, 2022, 1:49am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/7 "2022-06-08T01:49:32Z")

</div>

Hi @kruvva

Before moving on with step 6, did you try using `vtkHolesFilter()` after step 5? In your code, it would be

```python
fillHoles = vtk.vtkFillHolesFilter();
fillHoles.SetInputData(polyData)
fillHoles.Update()

```

If the output of `fillHoles` looks good, you do not have to go through the remaining steps.

---

<div class="post-metadata">

### Author: ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)
#### Post date: [June 8, 2022, 6:29pm UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/8 "2022-06-08T18:29:54Z")

</div>

I don’t kno if it helps but here is some code I developed for cleaning small holes while removing non manifold edges

> <https://github.com/SlicerIGT/SlicerBoneReconstructionPlanner/issues/35#issuecomment-796962159>
>
> vtkbool fails (returns empty mesh or meshes with errors) for some Boolean mesh o…perations. We work together with vtkbool developer to identify and fix the issues.
> 
> It seems that vtkbool expects input meshes to not have any non-manifold edges (which is completely reasonable). We need to test if we detect non-manifold edges using vtkCleanPolyData and vtkFeatureEdges and then maybe stitch the holes using vtkFillHolesFilter solves the problem - see https://github.com/zippy84/vtkbool/issues/40#issuecomment-795420589.

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 9, 2022, 1:46am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/9 "2022-06-09T01:46:09Z")

</div>

Thank you Mauro. I tried your code and found interesting things about my model. Following is the total number of facets, manifold edges, non-manifold edges and boundary edges at different steps of the code.

| | Facets | Manifold Edges | Non-manifold Edges | Boundary Edges |
| --- | --- | --- | --- | --- |
| Original | 388040 | 538460 | 0 | 87200 |
| After geometryFilter | 388040 | 538460 | 0 | 87200 |
| After filler | 420924 | 608186 | 6242 | 21432 |
| After cleanFilter | 420924 | 226084 | 174987 | 0 |

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 9, 2022, 1:50am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/10 "2022-06-09T01:50:07Z")

</div>

Thank you Jaswant. Interestingly, my model don’t have non-manifold edges. It is built from appending several models, as union using boolean filter didn’t work.

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [June 9, 2022, 3:53am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/11 "2022-06-09T03:53:25Z")

</div>

VTK’s built-in Boolean filters do not work: they may provide invalid output for valid input. If you want to combine multiple meshes you must not append them (that may introduce mesh errors that might not possible to fix automatically). Instead, you can use [vtkbool package](https://github.com/zippy84/vtkbool).

---

<div class="post-metadata">

### Author: ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)
#### Post date: [June 9, 2022, 6:40am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/12 "2022-06-09T06:40:20Z")

</div>

If you can comply with the CGAL License (GPLv3) we have the [VESPA](https://gitlab.kitware.com/vtk-cgal/vespa) module. It bring some of the CGAL functionalities into VTK, including boolean operations. In my experience, it is much more robust.  
This project is young and should be presented soon to the community.

---

<div class="post-metadata">

### Author: ![kruvva](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/k/a4c791/32.png) [@kruvva](https://discourse.vtk.org/u/kruvva)
#### Post date: [June 12, 2022, 7:12pm UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/13 "2022-06-12T19:12:39Z")

</div>

Thanks Andras. I don’t build vtk, rather I use pip install. Can I still build vtkbool on top of what I have. How do I set VTK\_DIR for cmake.

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [June 13, 2022, 4:08am UTC](https://discourse.vtk.org/t/remove-faces-in-contact-with-non-manifold-edges/4116/14 "2022-06-13T04:08:00Z")

</div>

I don’t think vtkbool is accesible via pip.

If you don’t want to build VTK then one option is to use VTK in the virtual Python environment that [3D Slicer](https://www.slicer.org/) provides. vtkbool is built as part of the Sandbox extension, so after installing 3D Slicer, [install the Sandbox extension](https://slicer.readthedocs.io/en/latest/user_guide/extensions_manager.html#install-extensions). You can get started with vtkbool using the convenient GUI of [“Combine models” module](https://github.com/PerkLab/SlicerSandbox/blob/master/CombineModels/CombineModels.py).
