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
    // Find single edge for each hole in mesh
    std::vector<MR::EdgeId> holeEdges = mesh.topology.findHoleRepresentiveEdges();
    for ( MR::EdgeId e : holeEdges )
    {
    // Setup filling parameters
    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" );
    }
    MRMESH_API std::vector< EdgeId > findHoleRepresentiveEdges(const FaceBitSet *region=nullptr) const
    MRMESH_API FillHoleMetric getUniversalMetric(const Mesh &mesh)
    MRMESH_API void fillHole(Mesh &mesh, EdgeId a, const FillHoleParams &params={})
    MRMESH_API Expected< Mesh > fromAnySupportedFormat(const std::filesystem::path &file, const MeshLoadSettings &settings={})
    MRMESH_API Expected< void > toAnySupportedFormat(const Mesh &mesh, const std::filesystem::path &file, const SaveSettings &settings={})
    FillHoleMetric metric
    MeshTopology topology
  • 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.metric = mrmeshpy.getUniversalMetric(mesh)
    # Fill hole represented by `e`
    mrmeshpy.fillHole(mesh, e, params)
    # Save result
    mrmeshpy.saveMesh(mesh, "filledMesh.stl")
    None saveMesh(Mesh mesh, os.PathLike|str|bytes file, SaveSettings settings='{}')
    None fillHole(Mesh mesh, Id_EdgeTag a, FillHoleParams params='{}')
    FillHoleMetric getUniversalMetric(Mesh mesh)
    Mesh loadMesh(os.PathLike|str|bytes file, MeshLoadSettings settings='{}')
  • C
    #include <MRMeshC/MRBitSet.h>
    #include <MRMeshC/MRMesh.h>
    #include <MRMeshC/MRMeshFillHole.h>
    #include <MRMeshC/MRMeshLoad.h>
    #include <MRMeshC/MRMeshSave.h>
    #include <MRMeshC/MRMeshTopology.h>
    #include <MRMeshC/MRString.h>
    #include <stdio.h>
    #include <stdlib.h>
    #define MIN_HOLE_AREA 100.f
    int main( int argc, char* argv[] )
    {
    int rc = EXIT_FAILURE;
    if ( argc != 2 && argc != 3 )
    {
    fprintf( stderr, "Usage: %s INPUT [OUTPUT]", argv[0] );
    goto out;
    }
    const char* input = argv[1];
    const char* output = ( argc == 2 ) ? argv[1] : argv[2];
    // error messages will be stored here
    MRString* errorString = NULL;
    MRMesh* mesh = mrMeshLoadFromAnySupportedFormat( input, &errorString );
    if ( errorString )
    {
    fprintf( stderr, "Failed to load mesh: %s", mrStringData( errorString ) );
    mrStringFree( errorString );
    goto out;
    }
    // get list of existing holes; each hole is represented by a single edge lying on the hole's border
    MREdgePath* holes = mrMeshFindHoleRepresentiveEdges( mesh );
    if ( holes->size == 0 )
    {
    printf( "Mesh doesn't have any holes" );
    goto out_holes;
    }
    // you can set various parameters for the fill hole process; see the documentation for more info
    // think of a metric as a method to fill holes in a preferred way
    // you can define one or choose from one of predefined metrics from MRMeshMetrics.h
    params.metric = metric;
    // optionally get the bitset of created faces
    MRFaceBitSet* newFaces = mrFaceBitSetNew( 0, false );
    params.outNewFaces = newFaces;
    // you can either fill all holes at once or one by one
    // in the second case don't forget to check the output fields of params (e.g. outNewFaces) after every iteration
    size_t newFaceCount = 0;
    #define FILL_ALL_HOLES 1
    #if FILL_ALL_HOLES
    mrFillHoles( mesh, holes->data, holes->size, &params );
    newFaceCount = mrBitSetCount( (const MRBitSet*)newFaces );
    #else
    for ( int i = 0; i < mrEdgePathSize( holes ); i++ )
    {
    MREdgeId e = mrEdgePathData( holes )[i];
    if ( mrVector3Length( &holeDirArea ) >= MIN_HOLE_AREA )
    {
    mrFillHole( mesh, e, &params );
    newFaceCount += mrBitSetCount( newFaces );
    }
    }
    #endif
    printf( "Added new %zu faces", newFaceCount );
    mrMeshSaveToAnySupportedFormat( mesh, output, &saveSettings, &errorString);
    if ( errorString )
    {
    fprintf( stderr, "Failed to save mesh: %s", mrStringData( errorString ) );
    mrStringFree( errorString );
    goto out_newFaces;
    }
    rc = EXIT_SUCCESS;
    out_newFaces:
    mrFaceBitSetFree( newFaces );
    out_metric:
    out_holes:
    mrEdgePathFree( holes );
    out_mesh:
    mrMeshFree( mesh );
    out:
    return rc;
    }
    MRMESHC_API size_t mrBitSetCount(const MRBitSet *bs)
    MRMESHC_API void mrFaceBitSetFree(MRFaceBitSet *fbs)
    MRMESHC_API MRFaceBitSet * mrFaceBitSetNew(size_t numBits, bool fillValue)
    MRMESHC_API void mrFillHole(MRMesh *mesh, MREdgeId a, const MRFillHoleParams *params)
    MRMESHC_API void mrFillHoles(MRMesh *mesh, const MREdgeId *as, size_t asNum, const MRFillHoleParams *params)
    MRMESHC_API MRFillHoleParams mrFillHoleParamsNew(void)
    struct MRMesh MRMesh
    struct MRFaceBitSet MRFaceBitSet
    typedefMR_EXTERN_C_BEGIN struct MRString MRString
    struct MRBitSet MRBitSet
    MR_EXTERN_C_BEGIN MRMESHC_API MRMesh * mrMeshLoadFromAnySupportedFormat(const char *file, MRString **errorStr)
    MRMESHC_API MRFillHoleMetric * mrGetUniversalMetric(const MRMesh *mesh)
    MRMESHC_API void mrFillHoleMetricFree(MRFillHoleMetric *metric)
    MR_EXTERN_C_BEGIN MRMESHC_API void mrMeshSaveToAnySupportedFormat(const MRMesh *mesh, const char *file, const MRSaveSettings *settings, MRString **errorStr)
    MRMESHC_API MRVector3f mrMeshHoleDirArea(const MRMesh *mesh, MREdgeId e)
    MRMESHC_API MREdgePath * mrMeshFindHoleRepresentiveEdges(const MRMesh *mesh)
    MRMESHC_API void mrMeshFree(MRMesh *mesh)
    MRMESHC_API MRSaveSettings mrSaveSettingsNew(void)
    MRMESHC_API void mrStringFree(MRString *str)
    MR_EXTERN_C_BEGIN MRMESHC_API const char * mrStringData(const MRString *str)
    Vector3d holeDirArea(MeshTopology topology, VertCoords points, Id_EdgeTag e)
    MRFaceBitSet * outNewFaces
    const MRFillHoleMetric * metric
  • C#
    using System.Reflection;
    using static MR.DotNet;
    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 = MeshLoad.FromAnySupportedFormat(inputFile);
    var holes = mesh.HoleRepresentiveEdges;
    var fillHoleParams = new FillHoleParams();
    fillHoleParams.Metric = FillHoleMetric.GetUniversalMetric( mesh );
    fillHoleParams.OutNewFaces = new FaceBitSet();
    FillHoles(ref mesh, holes.ToList(), fillHoleParams);
    Console.WriteLine("Number of new faces: {0}", fillHoleParams.OutNewFaces.Count());
    MeshSave.ToAnySupportedFormat(mesh, outputFile);
    }
    catch (Exception e)
    {
    Console.WriteLine("Error: {0}", e.Message);
    }
    }
    }