Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Holes generation in flat geometries #39

Open
AliE89 opened this issue Jul 29, 2024 · 4 comments
Open

Holes generation in flat geometries #39

AliE89 opened this issue Jul 29, 2024 · 4 comments

Comments

@AliE89
Copy link

AliE89 commented Jul 29, 2024

Hello guys,

Thanks for this tool, quite interesting. Today, I was playing around and I noticed that fast_simplification produces holes in the geometry if operating on flat surfaces 2D surfaces. Does this ring a bell?

Commnad I ma using is simply:
points_out, faces_out = fast_simplification.simplify(points, faces, 0.5)

Maybe I can add more flags to prevent this.

Many thanks.

@AliE89
Copy link
Author

AliE89 commented Jul 29, 2024

image

@Louis-Pujol
Copy link
Collaborator

Hi !

Is it possible for you to share the input data ? It seems to me that if input does not have holes the algorithm should not create ones, it would be interesting to have a closer look at your example to figure out what's going wrong here.

@AliE89
Copy link
Author

AliE89 commented Aug 5, 2024

Hello Louis,

sure, please find attached one stl you can play with.
test.zip

It's likely I am mistaking something... sorry about that.

Cheers,

@Louis-Pujol
Copy link
Collaborator

Hi @AliE89,

Sorry for the late answer. I've written a script to understand what happened here. I wrote a count_holes function that counts the number of holes in a triangular structure using the topological data analysis library gudhi. Then I compare the result of decimation using fast-simplification and the decimate method of PyVista:

import pyvista as pv
import gudhi
import fast_simplification

def count_holes(triangles):
    """Count the number of holes in a triangle mesh"""

    st = gudhi.SimplexTree()
    for t in triangles:
        st.insert(t)

    st.compute_persistence()

    # The first Betti number is the number of connected components
    # The second Betti number is the number of holes
    return st.betti_numbers()[1]



# Load the data
mesh = pv.read("test0.stl")
points, faces = mesh.points, mesh.regular_faces

# Decimate with fast-simplification
points_out, faces_out = fast_simplification.simplify(points, faces, 0.5)
mesh_decimated_fast_simplification = pv.PolyData.from_regular_faces(
    points_out,
    faces=faces_out
    )

# Decimate with PyVista
mesh_decimated_pyvista = mesh.decimate(0.5)
points_out_pyvista, faces_out_pyvista = mesh_decimated_pyvista.points, mesh_decimated_pyvista.regular_faces

plotter = pv.Plotter(shape=(1, 3))
plotter.subplot(0, 0)
plotter.add_mesh(mesh)
plotter.add_text(f"Input: {count_holes(faces)} holes")
plotter.subplot(0, 1)
plotter.add_mesh(mesh_decimated_fast_simplification)
plotter.add_text(f"Fast-simplification: {count_holes(faces_out)} holes")
plotter.subplot(0, 2)
plotter.add_mesh(mesh_decimated_pyvista)
plotter.add_text(f"PyVista: {count_holes(faces_out_pyvista)} holes")
plotter.show()

And there is the result I obtain:

image

There, even if they are imperceptible, your input geometry has some holes, and the number of holes decreases after decimation. I am almost sure that there cannot be more holes after decimation than before. The operation of edge contraction described in this paper can fill holes but never create new ones.

The decimation algorithm of fast-simplification is a fast version of vtk QuadricDecimation (this is the method wrapped by pyvista). You can read more about the fast algorithm on the associated GitHub, where it is stated that: "It uses a threshold to determine which triangles to delete, which avoids sorting but might lead to lesser quality"

For your problem, you can use the slower decimation from pyvista that seems visually better or try filling the imperceptible holes in the mesh before decimation. You can try pymeshfix; I never use it so I cannot tell if it will work on your example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants