MeshLib Documentation
Loading...
Searching...
No Matches
Filling Holes

Example of filling holes

  • C++
    #include <MRMesh/MRMesh.h>
    #include <MRMesh/MRMeshFillHole.h>
    #include <MRMesh/MRMeshLoad.h>
    #include <MRMesh/MRMeshSave.h>
    int main()
    {
    // Load mesh
    MR::Mesh mesh = *MR::MeshLoad::fromAnySupportedFormat( "mesh.stl" );
    // Find single edge for each hole in mesh
    std::vector<MR::EdgeId> holeEdges = mesh.topology.findHoleRepresentiveEdges();
    for ( MR::EdgeId e : holeEdges )
    {
    // Setup filling parameters
    MR::FillHoleParams params;
    params.metric = MR::getUniversalMetric( mesh );
    // Fill hole represented by `e`
    MR::fillHole( mesh, e, params );
    }
    // Save result
    auto saveRes = MR::MeshSave::toAnySupportedFormat( mesh, "filledMesh.stl" );
    }
    int main()
    Definition LaplacianDeformation.cpp:4
  • Python
    import meshlib.mrmeshpy as mrmeshpy
    # Load mesh
    mesh = mrmeshpy.loadMesh("mesh.stl")
    # Find single edge for each hole in mesh
    hole_edges = mesh.topology.findHoleRepresentiveEdges()
    for e in hole_edges:
    # Setup filling parameters
    params = mrmeshpy.FillHoleParams()
    params.metric = mrmeshpy.getUniversalMetric(mesh)
    # Fill hole represented by `e`
    mrmeshpy.fillHole(mesh, e, params)
    # Save result
    mrmeshpy.saveMesh(mesh, "filledMesh.stl")
  • C
    #include <MRCMesh/MRBitSet.h>
    #include <MRCMesh/MRMesh.h>
    #include <MRCMesh/MRMeshFillHole.h>
    #include <MRCMesh/MRMeshLoad.h>
    #include <MRCMesh/MRMeshMetrics.h>
    #include <MRCMesh/MRMeshSave.h>
    #include <MRCMesh/MRMeshTopology.h>
    #include <MRCMesh/MRString.h>
    #include <MRCMisc/expected_MR_Mesh_std_string.h>
    #include <MRCMisc/expected_void_std_string.h>
    #include <MRCMisc/std_string.h>
    #include <MRCMisc/std_vector_MR_EdgeId.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main( int argc, char* argv[] )
    {
    if ( argc != 2 && argc != 3 )
    {
    fprintf( stderr, "Usage: %s INPUT [OUTPUT]", argv[0] );
    return EXIT_FAILURE;
    }
    const char* input = argv[1];
    const char* output = ( argc == 2 ) ? argv[1] : argv[2];
    int rc = EXIT_FAILURE;
    // Load mesh.
    MR_expected_MR_Mesh_std_string* meshEx = MR_MeshLoad_fromAnySupportedFormat_2( input, NULL, NULL );
    MR_Mesh* mesh = MR_expected_MR_Mesh_std_string_value_mut( meshEx );
    // Handle failure to load mesh.
    if ( !mesh )
    {
    fprintf( stderr, "Failed to load mesh: %s\n", MR_std_string_data( MR_expected_MR_Mesh_std_string_error( meshEx ) ) );
    goto fail_mesh_loading;
    }
    // Get the list of the existing holes; each hole is represented by a single edge from the hole's border.
    MR_std_vector_MR_EdgeId* holes = MR_MeshTopology_findHoleRepresentiveEdges( MR_Mesh_Get_topology( mesh ), NULL );
    if ( MR_std_vector_MR_EdgeId_empty( holes ) )
    {
    printf( "Mesh doesn't have any holes" );
    goto fail_no_holes;
    }
    // You can set various parameters for the hole filling process; see the documentation for more info.
    MR_FillHoleParams* params = MR_FillHoleParams_DefaultConstruct();
    // The metric controls how exactly the hole is filled.
    // You can make a custom one, or choose from the predefined metrics defined in `<MRCMesh/MRMeshMetrics.h>`.
    MR_FillHoleMetric* metric = MR_getUniversalMetric( mesh );
    MR_FillHoleParams_Set_metric( params, MR_PassBy_Move, metric );
    MR_FillHoleMetric_Destroy( metric ); // `MR_PassBy_Move` is not destructive, the object still needs to be destroyed manually.
    // Optionally, receive the bitset of the created faces.
    MR_FaceBitSet* newFaces = MR_FaceBitSet_DefaultConstruct();
    MR_FillHoleParams_Set_outNewFaces( params, newFaces );
    // You can either fill all holes at once, or one by one.
    // In the latter case, don't forget to check the output fields of the parameters (e.g. `outNewFaces`) after every iteration.
    size_t newFaceCount = 0;
    #define FILL_ALL_HOLES 1
    #if FILL_ALL_HOLES
    MR_fillHoles( mesh, holes, params );
    newFaceCount = MR_BitSet_count( MR_FaceBitSet_UpcastTo_MR_BitSet( newFaces ) );
    #else
    const float minHoleArea = 100.f; // An arbitrary size threshold for holes, just as a demonstration.
    for ( size_t i = 0; i < MR_std_vector_MR_EdgeId_Size( holes ); i++ )
    {
    MR_EdgeId e = *MR_std_vector_MR_EdgeId_At( holes, i );
    MR_Vector3d holeDirArea = MR_Mesh_holeDirArea( mesh, e );
    if ( MR_Vector3d_lengthSq( &holeDirArea ) >= minHoleArea*minHoleArea )
    {
    MR_fillHole( mesh, e, params );
    newFaceCount += MR_BitSet_count( MR_FaceBitSet_UpcastTo_MR_BitSet( newFaces ) );
    }
    }
    #endif
    printf( "Added %zu new faces\n", newFaceCount );
    // Save result
    MR_expected_void_std_string* saveEx = MR_MeshSave_toAnySupportedFormat_3( mesh, output, NULL, NULL);
    if ( MR_expected_void_std_string_error( saveEx ) )
    {
    fprintf( stderr, "Failed to save mesh: %s\n", MR_std_string_data( MR_expected_void_std_string_error( saveEx ) ) );
    goto fail_save;
    }
    rc = EXIT_SUCCESS;
    fail_save:
    MR_FaceBitSet_Destroy( newFaces );
    fail_no_holes:
    MR_std_vector_MR_EdgeId_Destroy( holes );
    fail_mesh_loading:
    MR_expected_MR_Mesh_std_string_Destroy( meshEx );
    return rc;
    }
  • C#
    using System.Reflection;
    public static class MeshFillHoleExample
    {
    public static void Run(string[] args)
    {
    try
    {
    if (args.Length != 2 && args.Length != 3)
    {
    Console.WriteLine("Usage: {0} MeshFillHoleExample INPUT [OUTPUT]", Assembly.GetExecutingAssembly().GetName().Name);
    return;
    }
    string inputFile = args[1];
    string outputFile = args.Length == 3 ? args[2] : inputFile;
    var mesh = MR.MeshLoad.fromAnySupportedFormat(inputFile);
    MR.Std.Vector_MREdgeId holes = mesh.topology.findHoleRepresentiveEdges();
    MR.FillHoleParams fillHoleParams = new();
    fillHoleParams.metric.assign(MR.getUniversalMetric(mesh));
    MR.FaceBitSet outfaces = new();
    // TODO
    // fillHoleParams.OutNewFaces = ...
    MR.fillHoles(mesh, holes, fillHoleParams);
    // TODO
    // Console.WriteLine("Number of new faces: {0}", fillHoleParams.OutNewFaces.Count());
    MR.MeshSave.toAnySupportedFormat(mesh, outputFile);
    }
    catch (Exception e)
    {
    Console.WriteLine("Error: {0}", e.Message);
    }
    }
    }