MeshLib Documentation
Loading...
Searching...
No Matches
Mesh Offset

Example of mesh offset

See it live in the browser

  • C++
    #include <MRMesh/MRBox.h>
    #include <MRMesh/MRMesh.h>
    #include <MRMesh/MRCube.h>
    #include <MRMesh/MRMeshSave.h>
    #include <MRMesh/MRRegionBoundary.h>
    #include <MRVoxels/MROffset.h>
    #include <iostream>
    int main()
    {
    // Create mesh
    MR::Mesh mesh = MR::makeCube();
    // Setup parameters
    MR::GeneralOffsetParameters params;
    // calculate voxel size depending on desired accuracy and/or memory consumption
    params.voxelSize = suggestVoxelSize( mesh, 10000000.f );
    if ( !MR::findRightBoundary( mesh.topology ).empty() )
    params.signDetectionMode = MR::SignDetectionMode::HoleWindingRule; // use if you have holes in mesh
    // Make offset mesh
    float offset = mesh.computeBoundingBox().diagonal() * 0.1f;
    auto meshRes = MR::generalOffsetMesh( mesh, offset, params );
    if ( !meshRes.has_value() )
    {
    std::cerr << meshRes.error() << std::endl;
    return 1;
    }
    // Save result
    if ( auto saveRes = MR::MeshSave::toAnySupportedFormat( *meshRes, "mesh_offset.stl" ); !saveRes )
    {
    std::cerr << saveRes.error() << std::endl;
    return 1;
    }
    return 0;
    }
    int main()
    Definition LaplacianDeformation.cpp:4
    Source mesh
    After offset
  • Python
    import meshlib.mrmeshpy as mrmeshpy
    import sys
    # Load mesh
    mesh = mrmeshpy.loadMesh("mesh.stl")
    # Setup parameters
    params = mrmeshpy.OffsetParameters()
    params.voxelSize = mesh.computeBoundingBox().diagonal() * 5e-3 # offset grid precision (algorithm is voxel based)
    if mrmeshpy.findRightBoundary(mesh.topology).empty():
    params.signDetectionMode = mrmeshpy.SignDetectionMode.HoleWindingRule # use if you have holes in mesh
    # Make offset mesh
    offset = mesh.computeBoundingBox().diagonal() * 0.05
    try:
    result_mesh = mrmeshpy.offsetMesh(mesh, offset, params)
    except RuntimeError as e:
    print(e)
    sys.exit(1)
    # Save result
    mrmeshpy.saveMesh(result_mesh, "offsetMesh.stl")
    Source mesh
    After offset
  • C
    #include <MRCMesh/MRBox.h>
    #include <MRCMesh/MRCube.h>
    #include <MRCMesh/MRMesh.h>
    #include <MRCMesh/MRMeshPart.h>
    #include <MRCMesh/MRMeshSave.h>
    #include <MRCMesh/MRString.h>
    #include <MRCMesh/MRVector3.h>
    #include <MRCMisc/expected_MR_Mesh_std_string.h>
    #include <MRCMisc/expected_void_std_string.h>
    #include <MRCMisc/std_string.h>
    #include <MRCVoxels/MROffset.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main( void )
    {
    int rc = EXIT_FAILURE;
    // Create mesh
    MR_Vector3f size = MR_Vector3f_diagonal( 1.f );
    MR_Vector3f base = MR_Vector3f_diagonal( -0.5f );
    MR_Mesh* mesh = MR_makeCube( &size, &base );
    // offset functions can also be applied to separate mesh components rather than to the whole mesh
    // this is not our case, so the region is set to NULL
    MR_MeshPart* inputMeshPart = MR_MeshPart_Construct( mesh, NULL );
    // Setup parameters
    MR_GeneralOffsetParameters* params = MR_GeneralOffsetParameters_DefaultConstruct();
    // calculate voxel size depending on desired accuracy and/or memory consumption
    MR_GeneralOffsetParameters_Set_voxelSize( params, MR_suggestVoxelSize( inputMeshPart, 10000000.f ) );
    MR_Box3f bbox = MR_Mesh_computeBoundingBox_1( mesh, NULL );
    float offset = MR_Box3f_diagonal( &bbox ) * 0.1f;
    // Make offset mesh
    MR_expected_MR_Mesh_std_string* outputMeshEx = MR_generalOffsetMesh( inputMeshPart, offset, params );
    MR_MeshPart_Destroy( inputMeshPart );
    MR_GeneralOffsetParameters_Destroy( params );
    MR_Mesh* outputMesh = MR_expected_MR_Mesh_std_string_value_mut( outputMeshEx );
    if ( !outputMesh )
    {
    fprintf( stderr, "Failed to perform offset: %s", MR_std_string_data( MR_expected_MR_Mesh_std_string_error( outputMeshEx ) ) );
    goto fail_offset;
    }
    // Save result
    MR_expected_void_std_string* saveEx = MR_MeshSave_toAnySupportedFormat_3( outputMesh, "mesh_offset.stl", 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_expected_void_std_string_Destroy( saveEx );
    fail_offset:
    MR_expected_MR_Mesh_std_string_Destroy( outputMeshEx );
    MR_Mesh_Destroy( mesh );
    return rc;
    }
    Source mesh
    After offset
  • C#
    using System.Globalization;
    public class MeshOffsetExample
    {
    public static void Main(string[] args)
    {
    try
    {
    // Load the mesh given as the first argument, or make a sphere to offset if no path is given
    var mesh = args.Length > 0
    ? MR.MeshLoad.fromAnySupportedFormat(args[0])
    : MR.makeUVSphere(1.0f, 32, 32);
    // Offset value: the second argument if given, otherwise 5% of the bounding box diagonal
    float offsetValue = args.Length > 1
    ? float.Parse(args[1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture)
    : mesh.computeBoundingBox().diagonal() * 0.05f;
    MR.MeshPart mp = new(mesh);
    // Setup parameters
    MR.OffsetParameters op = new();
    op.voxelSize = MR.suggestVoxelSize(mp, 1e6f);
    // Make offset mesh
    var result = MR.offsetMesh(mp, offsetValue, op);
    // Save result
    MR.MeshSave.toAnySupportedFormat(result, "mesh_offset.stl");
    }
    catch (Exception e)
    {
    Console.WriteLine("Error: {0}", e.Message);
    }
    }
    }
    Source mesh
    After offset
  • JavaScript
    import createMeshLib from '@meshinspector/meshlib';
    const ml = await createMeshLib();
    // Create mesh
    using mesh = ml.makeCube();
    // Setup parameters
    using params = new ml.GeneralOffsetParameters();
    // calculate voxel size depending on desired accuracy and/or memory consumption
    params.voxelSize = ml.suggestVoxelSize(mesh, 10000000.0);
    using topology = mesh.topology;
    if (ml.findRightBoundary(topology).length > 0)
    params.signDetectionMode = ml.SignDetectionMode.HoleWindingRule; // use if you have holes in mesh
    // Make offset mesh
    using box = mesh.computeBoundingBox();
    const offset = box.diagonal() * 0.1;
    using result = ml.generalOffsetMesh(mesh, offset, params);
    // Save result
    ml.MeshSave.toAnySupportedFormat(result, 'mesh_offset.stl');
    Note
    The using declaration requires Node.js 24+ or a modern browser. On older runtimes, call .delete() on each object instead (see Memory Management in the JavaScript Setup Guide).
    Source mesh
    After offset