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

Example of mesh ICP (finding transformation to match objects)

  • C++
    #include <MRMesh/MRBox.h>
    #include <MRMesh/MRICP.h>
    #include <MRMesh/MRMesh.h>
    #include <MRMesh/MRMeshLoad.h>
    #include <MRMesh/MRMeshSave.h>
    #include <iostream>
    int main()
    {
    // Load meshes
    auto meshFloatingRes = MR::MeshLoad::fromAnySupportedFormat( "meshA.stl" );
    if ( !meshFloatingRes.has_value() )
    {
    std::cerr << meshFloatingRes.error() << std::endl;
    return 1;
    }
    MR::Mesh& meshFloating = *meshFloatingRes;
    auto meshFixedRes = MR::MeshLoad::fromAnySupportedFormat( "meshB.stl" );
    if ( !meshFixedRes.has_value() )
    {
    std::cerr << meshFixedRes.error() << std::endl;
    return 1;
    }
    MR::Mesh& meshFixed = *meshFixedRes;
    // Prepare ICP parameters
    float diagonal = meshFixed.getBoundingBox().diagonal();
    float icpSamplingVoxelSize = diagonal * 0.01f; // To sample points from object
    MR::ICPProperties icpParams;
    icpParams.distThresholdSq = MR::sqr( diagonal * 0.1f ); // Use points pairs with maximum distance specified
    icpParams.exitVal = diagonal * 0.003f; // Stop when distance reached
    // Calculate transformation
    MR::ICP icp(
    MR::MeshOrPoints{ MR::MeshPart{ meshFloating } },
    MR::MeshOrPoints{ MR::MeshPart{ meshFixed } },
    MR::AffineXf3f(), MR::AffineXf3f(),
    icpSamplingVoxelSize );
    icp.setParams( icpParams );
    MR::AffineXf3f xf = icp.calculateTransformation();
    // Transform floating mesh
    meshFloating.transform( xf );
    // Output information string
    std::string info = icp.getStatusInfo();
    std::cerr << info << std::endl;
    // Save result
    if ( auto saveRes = MR::MeshSave::toAnySupportedFormat( meshFloating, "meshA_icp.stl" ); !saveRes )
    {
    std::cerr << saveRes.error() << std::endl;
    return 1;
    }
    }
    int main()
    Definition LaplacianDeformation.cpp:4
    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={})
    constexpr T sqr(T x) noexcept
  • Python
    import meshlib.mrmeshpy as mrmeshpy
    # Load meshes
    meshFloating = mrmeshpy.loadMesh("meshA.stl")
    meshFixed = mrmeshpy.loadMesh("meshB.stl")
    # Prepare ICP parameters
    diagonal = meshFixed.getBoundingBox().diagonal()
    icp_sampling_voxel_size = diagonal * 0.01 # To sample points from object
    icp_params = mrmeshpy.ICPProperties()
    icp_params.distThresholdSq = (diagonal * 0.1) ** 2 # Use points pairs with maximum distance specified
    icp_params.exitVal = diagonal * 0.003 # Stop when this distance reached
    # Calculate transformation
    icp = mrmeshpy.ICP(meshFloating, meshFixed,
    icp_sampling_voxel_size)
    icp.setParams(icp_params)
    xf = icp.calculateTransformation()
    # Transform floating mesh
    meshFloating.transform(xf)
    # Output information string
    print(icp.getLastICPInfo())
    # Save result
    mrmeshpy.saveMesh(meshFloating, "meshA_icp.stl")
    None saveMesh(Mesh mesh, os.PathLike|str|bytes file, SaveSettings settings='{}')
    Mesh loadMesh(os.PathLike|str|bytes file, MeshLoadSettings settings='{}')
  • C
    #include <MRMeshC/MRICP.h>
    #include <MRMeshC/MRMesh.h>
    #include <MRMeshC/MRMeshLoad.h>
    #include <MRMeshC/MRMeshSave.h>
    #include <MRMeshC/MRString.h>
    #include <stdio.h>
    #include <stdlib.h>
    int main( int argc, char* argv[] )
    {
    // Load meshes
    MRMesh* meshFloating = mrMeshLoadFromAnySupportedFormat( "meshA.stl", NULL );
    MRMesh* meshFixed = mrMeshLoadFromAnySupportedFormat( "meshB.stl", NULL );
    // Prepare ICP parameters
    MRBox3f bbox = mrMeshComputeBoundingBox( meshFixed, NULL );
    float diagonal = mrBox3fDiagonal( &bbox );
    float icpSamplingVoxelSize = diagonal * 0.01f; // To sample points from object
    icpParams.distThresholdSq = diagonal * diagonal * 0.01f; // Use points pairs with maximum distance specified
    icpParams.exitVal = diagonal * 0.003f; // Stop when distance reached
    // Calculate transformation
    MRMeshOrPointsXf* flt = mrMeshOrPointsXfFromMesh( meshFloating, NULL );
    MRMeshOrPointsXf* ref = mrMeshOrPointsXfFromMesh( meshFixed, NULL );
    MRICP* icp = mrICPNew( flt, ref, icpSamplingVoxelSize );
    mrICPSetParams( icp, &icpParams );
    // Transform floating mesh
    mrMeshTransform( meshFloating, &xf, NULL );
    // Output information string
    MRString* info = mrICPGetStatusInfo( icp );
    printf( "%s\n", mrStringData( info ) );
    // Save result
    mrMeshSaveToAnySupportedFormat( meshFloating, "meshA_icp.stl", NULL, NULL );
    mrStringFree( info );
    mrICPFree( icp );
    mrMeshFree( meshFixed );
    mrMeshFree( meshFloating );
    return EXIT_SUCCESS;
    }
    MRMESHC_API float mrBox3fDiagonal(const MRBox3f *box)
    struct MRICP MRICP
    MRMESHC_API void mrICPSetParams(MRICP *icp, const MRICPProperties *prop)
    MRMESHC_API MRAffineXf3f mrICPCalculateTransformation(MRICP *icp)
    MRMESHC_API void mrICPFree(MRICP *icp)
    MRMESHC_API MRString * mrICPGetStatusInfo(const MRICP *icp)
    MRMESHC_API MRICPProperties mrICPPropertiesNew(void)
    MRMESHC_API MRICP * mrICPNew(const MRMeshOrPointsXf *flt, const MRMeshOrPointsXf *ref, float samplingVoxelSize)
    struct MRMesh MRMesh
    typedefMR_EXTERN_C_BEGIN struct MRString MRString
    MR_EXTERN_C_BEGIN MRMESHC_API MRMesh * mrMeshLoadFromAnySupportedFormat(const char *file, MRString **errorStr)
    struct MRMeshOrPointsXf MRMeshOrPointsXf
    MRMESHC_API MRMeshOrPointsXf * mrMeshOrPointsXfFromMesh(const MRMesh *mesh, const MRAffineXf3f *xf)
    MRMESHC_API void mrMeshOrPointsXfFree(MRMeshOrPointsXf *mp)
    MR_EXTERN_C_BEGIN MRMESHC_API void mrMeshSaveToAnySupportedFormat(const MRMesh *mesh, const char *file, const MRSaveSettings *settings, MRString **errorStr)
    MRMESHC_API void mrMeshTransform(MRMesh *mesh, const MRAffineXf3f *xf, const MRVertBitSet *region)
    MRMESHC_API MRBox3f mrMeshComputeBoundingBox(const MRMesh *mesh, const MRAffineXf3f *toWorld)
    MRMESHC_API void mrMeshFree(MRMesh *mesh)
    MRMESHC_API void mrStringFree(MRString *str)
    MR_EXTERN_C_BEGIN MRMESHC_API const char * mrStringData(const MRString *str)
  • C#
    using System.Reflection;
    using static MR.DotNet;
    public class MeshICPExample
    {
    public static void Run()
    {
    try
    {
    // Load meshes
    Mesh meshFloating = MeshLoad.FromAnySupportedFormat("meshA.stl");
    MeshOrPointsXf meshXfFloating = new MeshOrPointsXf(meshFloating, new AffineXf3f());
    MeshOrPointsXf meshXfFixed = new MeshOrPointsXf(MeshLoad.FromAnySupportedFormat("meshB.stl"), new AffineXf3f());
    // Prepare ICP parameters
    float diagonal = meshXfFixed.obj.BoundingBox.Diagonal();
    float icpSamplingVoxelSize = diagonal * 0.01f; // To sample points from object
    ICPProperties icpParams = new ICPProperties();
    icpParams.distThresholdSq = diagonal * diagonal * 0.01f; // Use points pairs with maximum distance specified
    icpParams.exitVal = diagonal * 0.003f; // Stop when distance reached
    // Calculate transformation
    ICP icp = new ICP(meshXfFloating, meshXfFixed, icpSamplingVoxelSize);
    icp.SetParams( icpParams );
    AffineXf3f xf = icp.CalculateTransformation();
    // Transform floating mesh
    meshFloating.Transform(xf);
    // Output information string
    Console.WriteLine("info {0}", icp.GetStatusInfo());
    // Save result
    MeshSave.ToAnySupportedFormat( meshFloating, "meshA_icp.stl");
    }
    catch (Exception e)
    {
    Console.WriteLine("Error: {0}", e.Message);
    }
    }
    }