This page contains some examples of using MeshLib
Basing your application on MeshLib
First of all you should make main
function like this
int main( int argc, char** argv )
{
launchParams.name = "Your app name";
}
Definition MRSetupViewer.h:10
virtual MRVIEWER_API void setupBasePlugins(Viewer *) const
static MRVIEWER_API void parseLaunchParams(LaunchParams ¶ms)
static Viewer * instance()
Definition MRViewer.h:102
MRMESH_API void setupLoggerByDefault()
MRVIEWER_API int launchDefaultViewer(const Viewer::LaunchParams ¶ms, const ViewerSetup &setup)
int argc
Definition MRViewer.h:67
Then you should make your plugins, to find how have a look at State Plugins overview page
C++ Basic Examples
You can find example project in MeshLib/source/meshconv
Following code presents example of loading and saving mesh file
#include <iostream>
int main()
{
std::filesystem::path inFilePath = "mesh.stl";
if ( loadRes.has_value() )
{
std::filesystem::path outFilePath = "mesh.ply";
if ( !saveRes.has_value() )
std::cerr << saveRes.error() << "\n";
}
else
std::cerr << loadRes.error() << "\n";
return 0;
}
MRMESH_API Expected< Mesh, std::string > fromAnySupportedFormat(const std::filesystem::path &file, const MeshLoadSettings &settings={})
detects the format from file extension and loads mesh from it
MRMESH_API VoidOrErrStr toAnySupportedFormat(const Mesh &mesh, const std::filesystem::path &file, const SaveSettings &settings={})
detects the format from file extension and save mesh to it
Further examples won't check return values for sake of clarity
- See also
- MR::MeshLoad
-
MR::MeshSave
Some examples of mesh modification are presented here
int main()
{
return 0;
}
MRMESH_API bool relax(Mesh &mesh, const MeshRelaxParams ¶ms={}, ProgressCallback cb={})
MRMESH_API int subdivideMesh(Mesh &mesh, const SubdivideSettings &settings={})
Definition MRAffineXf.h:10
static constexpr AffineXf linear(const M &A) noexcept
creates linear-only transformation (without translation)
Definition MRAffineXf.h:24
static constexpr Matrix3 rotation(const Vector3< float > &axis, float angle) noexcept
creates matrix representing rotation around given axis on given angle
MRMESH_API void transform(const AffineXf3f &xf, const VertBitSet *region=nullptr)
Definition MRMeshSubdivide.h:17
float maxDeviationAfterFlip
Improves local mesh triangulation by doing edge flips if it does not make too big surface deviation.
Definition MRMeshSubdivide.h:23
static constexpr Vector3 plusZ() noexcept
Definition MRVector3.h:31
Export example of points and triangles from mesh (e.g. for rendering)
int main()
{
const std::vector<MR::Vector3f> & points = mesh.
points.
vec_;
const int * vertexTripples = reinterpret_cast<const int*>( triangles.data() );
return 0;
}
MRMESH_API std::vector< ThreeVertIds > getAllTriVerts() const
returns three vertex ids for valid triangles, invalid triangles are skipped
std::vector< T > vec_
the user can directly manipulate the vector, anyway she cannot break anything
Definition MRVector.h:135
MRMESH_API Mesh makeCube(const Vector3f &size=Vector3f::diagonal(1.0f), const Vector3f &base=Vector3f::diagonal(-0.5f))
MeshTopology topology
Definition MRMesh.h:24
VertCoords points
Definition MRMesh.h:25
Example of mesh decimate
int main()
{
}
MRMESH_API DecimateResult decimateMesh(Mesh &mesh, const DecimateSettings &settings={})
Collapse edges in mesh region according to the settings.
Parameters structure for MR::decimateMesh.
Definition MRMeshDecimate.h:32
float maxError
Definition MRMeshDecimate.h:38
Example of Boolean operation
#include <iostream>
int main()
{
sphere2.transform( xf );
if ( !result.valid() )
std::cerr << result.errorString << "\n";
return 0;
}
MRMESH_API BooleanResult boolean(const Mesh &meshA, const Mesh &meshB, BooleanOperation operation, const AffineXf3f *rigidB2A, BooleanResultMapper *mapper=nullptr, ProgressCallback cb={})
Performs CSG operation on two meshes.
MRMESH_API Mesh makeUVSphere(float radius=1.0, int horisontalResolution=16, int verticalResolution=16)
creates a mesh of sphere with regular triangulation (parallels and meridians)
static constexpr AffineXf translation(const V &b) noexcept
creates translation-only transformation (with identity linear component)
Definition MRAffineXf.h:22
Structure contain boolean result.
Definition MRMeshBoolean.h:27
Example of mesh offset
int main()
{
if ( !meshRes.has_value() )
{
return 1;
}
return 0;
}
@ HoleWindingRule
computes winding number generalization with support of holes in mesh, slower than WindingRule
MRMESH_API std::vector< EdgeLoop > findRightBoundary(const MeshTopology &topology, const FaceBitSet *region=nullptr)
MRMESH_API Expected< Mesh > generalOffsetMesh(const MeshPart &mp, float offset, const GeneralOffsetParameters ¶ms)
Offsets mesh by converting it to voxels and back using one of three modes specified in the parameters...
float voxelSize
Definition MROffset.h:17
allows the user to select in the parameters which offset algorithm to call
Definition MROffset.h:87
MRMESH_API Box3f computeBoundingBox(const AffineXf3f *toWorld=nullptr) const
SignDetectionMode signDetectionMode
determines the method to compute distance sign
Definition MROffset.h:29
Example of mesh ICP (finding transformation to match objects)
#include <iostream>
int main()
{
float diagonal = meshFixed.getBoundingBox().diagonal();
float icpSamplingVoxelSize = diagonal * 0.01f;
icpParams.exitVal = diagonal * 0.003f;
icpSamplingVoxelSize );
meshFloating.transform( xf );
std::string info = icp.getLastICPInfo();
std::cerr << info << "\n";
}
void setParams(const ICPProperties &prop)
tune algorithm params before run calculateTransformation()
Definition MRICP.h:196
Definition MRMeshOrPoints.h:17
constexpr T sqr(T x) noexcept
Definition MRMeshFwd.h:519
AffineXf3< float > AffineXf3f
Definition MRMeshFwd.h:178
float distThresholdSq
Points pair will be counted only if squared distance between points is lower than.
Definition MRICP.h:129
Definition MRMeshPart.h:11
Example of filling holes
int main()
{
{
}
}
MRMESH_API std::vector< EdgeId > findHoleRepresentiveEdges() const
returns one edge with no valid left face for every boundary in the mesh
MRMESH_API FillHoleMetric getUniversalMetric(const Mesh &mesh)
MRMESH_API void fillHole(Mesh &mesh, EdgeId a, const FillHoleParams ¶ms={})
Fills hole in mesh .
Parameters structure for MR::fillHole Structure has some options to control MR::fillHole.
Definition MRMeshFillHole.h:25
FillHoleMetric metric
Definition MRMeshFillHole.h:30
Example of stitching holes (connect two holes with a cylinder)
int main()
{
MR::Mesh mesh = std::move( meshARes.value() );
if ( edges.size() != 2 )
return 1;
return 0;
}
MRMESH_API void buildCylinderBetweenTwoHoles(Mesh &mesh, EdgeId a, EdgeId b, const StitchHolesParams ¶ms={})
Stitches two holes in Mesh .
MRMESH_API void addPart(const Mesh &from, FaceMap *outFmap=nullptr, VertMap *outVmap=nullptr, WholeEdgeMap *outEmap=nullptr, bool rearrangeTriangles=false)
appends mesh (from) in addition to this mesh: creates new edges, faces, verts and points
Parameters structure for MR::buildCylinderBetweenTwoHoles Structure has some options to control MR::b...
Definition MRMeshFillHole.h:74
FillHoleMetric metric
Definition MRMeshFillHole.h:79
Example of extrude faces on mesh
int main()
{
{
} );
}
void autoResizeSet(IndexType pos, size_type len, bool val=true)
Definition MRBitSet.h:129
auto BitSetParallelFor(const BS &bs, F f, Cb &&... cb)
Definition MRBitSetParallelFor.h:202
MRMESH_API void makeDegenerateBandAroundRegion(Mesh &mesh, const FaceBitSet ®ion, const MakeDegenerateBandAroundRegionParams ¶ms={})
Create a band of degenerate faces along the border of the specified region and the rest of the mesh.
MRMESH_API VertBitSet getIncidentVerts(const MeshTopology &topology, const FaceBitSet &faces)
MRMESH_API void invalidateCaches(bool pointsChanged=true)
Python Basic Examples
In this section we provide the same examples but with python code
Load and save example:
import meshlib.mrmeshpy as mrmeshpy
try:
mesh = mrmeshpy.loadMesh("mesh.stl")
except ValueError as e:
print(e)
mrmeshpy.saveMesh(mesh, "mesh.ply")
Using numpy to create mesh and get back its primitives
import meshlib.mrmeshpy as mrmeshpy
import meshlib.mrmeshnumpy as mrmeshnumpy
import numpy as np
faces = np.ndarray(shape=(2, 3), dtype=np.int32, buffer=np.array([[0, 1, 2], [2, 3, 0]], dtype=np.int32))
# mrmesh uses float32 for vertex coordinates
# however, you could also use float64
verts = np.ndarray(shape=(4, 3), dtype=np.float32, buffer=np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0]], dtype=np.float32))
mesh = mrmeshnumpy.meshFromFacesVerts(faces, verts)
# some mesh manipulations
out_verts = mrmeshnumpy.getNumpyVerts(mesh)
out_faces = mrmeshnumpy.getNumpyFaces(mesh.topology)
Mesh modification examples
import meshlib.mrmeshpy as mrmeshpy
mesh = mrmeshpy.loadMesh("mesh.stl")
relax_params = mrmeshpy.MeshRelaxParams()
relax_params.iterations = 5
mrmeshpy.relax(mesh, relax_params)
props = mrmeshpy.SubdivideSettings()
props.maxDeviationAfterFlip = 0.5
mrmeshpy.subdivideMesh(mesh,props)
plus_z = mrmeshpy.Vector3f()
plus_z.z = 1.0
rotation_xf = mrmeshpy.AffineXf3f.linear(mrmeshpy.Matrix3f.rotation(plus_z, 3.1415 * 0.5))
Simple triangulation
from meshlib import mrmeshpy as mm
from meshlib import mrmeshnumpy as mn
import numpy as np
u, v = np.mgrid[0:2 * np.pi:100j, 0:np.pi:100j]
x = np.cos(u) * np.sin(v)
y = np.sin(u) * np.sin(v)
z = np.cos(v)
# Prepare for MeshLib PointCloud
verts = np.stack((x.flatten(), y.flatten(), z.flatten()), axis=-1).reshape(-1, 3)
# Create MeshLib PointCloud from np ndarray
pc = mn.pointCloudFromPoints(verts)
# Remove duplicate points
pc.validPoints = mm.pointUniformSampling(pc, 1e-3)
pc.invalidateCaches()
# Triangulate it
triangulated_pc = mm.triangulatePointCloud(pc)
# Fix possible issues
triangulated_pc = mm.offsetMesh(triangulated_pc, 0.0)
Triangulation of regular numpy grid
from meshlib import mrmeshpy as mm
from meshlib import mrmeshnumpy as mn
import numpy as np
u, v = np.mgrid[0:2 * np.pi:50j, 0:np.pi:100j]
x = np.cos(u) * np.sin(v)
y = np.sin(u) * np.sin(v)
z = np.cos(v)
mesh = mn.meshFromUVPoints(x,y,z)
Using plotly to visualize mesh
from meshlib import mrmeshpy as mm
from meshlib import mrmeshnumpy as mn
import numpy as np
import plotly.graph_objects as go
# load mesh
mesh = mm.loadMesh("mesh.stl")
# extract numpy arrays
verts = mn.getNumpyVerts(mesh)
# prepare data for plotly
verts_t = np.transpose(verts)
faces_t = np.transpose(faces)
# draw
fig = go.Figure(data=[
go.Mesh3d(
x=verts_t[0],
y=verts_t[1],
z=verts_t[2],
i=faces_t[0],
j=faces_t[1],
k=faces_t[2]
)
])
fig.show()
Plotly visualization
Example of mesh decimate
import meshlib.mrmeshpy as mrmeshpy
# Load mesh
mesh = mrmeshpy.loadMesh("mesh.stl")
# Setup decimate parameters
settings = mrmeshpy.DecimateSettings()
settings.maxError = 0.05
# Decimate mesh
mrmeshpy.decimateMesh(mesh, settings)
# Save result
mrmeshpy.saveMesh(mesh, "decimatedMesh.stl")
Example of Boolean operation
import meshlib.mrmeshpy as mrmeshpy
# create first sphere with radius of 1 unit
sphere1 = mrmeshpy.makeUVSphere(1.0, 64, 64)
# create second sphere by cloning the first sphere and moving it in X direction
sphere2 = mrmeshpy.copyMesh(sphere1)
xf = mrmeshpy.AffineXf3f.translation(mrmeshpy.Vector3f(0.7, 0.0, 0.0))
sphere2.transform(xf)
# perform boolean operation
result = mrmeshpy.boolean(sphere1, sphere2, mrmeshpy.BooleanOperation.Intersection)
result_mesh = result.mesh
if not result.valid():
print(result.errorString)
# save result to STL file
mrmeshpy.saveMesh(result_mesh, "out_boolean.stl")
Example of mesh offset
import meshlib.mrmeshpy as mrmeshpy
# Load mesh
mesh = mrmeshpy.loadMesh("mesh.stl")
# Setup parameters
params = mrmeshpy.OffsetParameters()
if mrmeshpy.findRightBoundary(mesh.
topology).empty():
params.
signDetectionMode = mrmeshpy.SignDetectionMode.HoleWindingRule # use
if you have holes in mesh
# Make offset mesh
result_mesh = mrmeshpy.offsetMesh(mesh, offset, params)
# Save result
mrmeshpy.saveMesh(result_mesh, "offsetMesh.stl")
Example of mesh ICP
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,
mrmeshpy.AffineXf3f(), mrmeshpy.AffineXf3f(),
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")
std::optional< T > distance(const Plane3< T > &plane1, const Plane3< T > &plane2, T errorLimit=std::numeric_limits< T >::epsilon() *T(20))
Definition MRIntersection.h:104
Example of filling holes
import meshlib.mrmeshpy as mrmeshpy
# Load mesh
mesh = mrmeshpy.loadMesh("mesh.stl")
# Find single edge for each hole in mesh
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")
Example of stitch holes
import meshlib.mrmeshpy as mrmeshpy
# Load meshes
mesh_a = mrmeshpy.loadMesh("meshAwithHole.stl")
mesh_b = mrmeshpy.loadMesh("meshBwithHole.stl")
# Unite meshes
mesh = mrmeshpy.mergeMeshes([mesh_a, mesh_b])
# Find holes
# Connect two holes
params = mrmeshpy.StitchHolesParams()
params.metric = mrmeshpy.getUniversalMetric(mesh)
mrmeshpy.buildCylinderBetweenTwoHoles(mesh, edges[0], edges[1], params)
# Save result
mrmeshpy.saveMesh(mesh, "stitchedMesh.stl")
Example of extrude faces on mesh
import meshlib.mrmeshpy as mrmeshpy
# Load mesh
mesh = mrmeshpy.loadMesh("mesh.stl")
# Prepare region to extrude
faces_to_extrude = mrmeshpy.FaceBitSet()
faces_to_extrude.resize(3, False)
faces_to_extrude.set(mrmeshpy.FaceId(1), True)
faces_to_extrude.set(mrmeshpy.FaceId(2), True)
# Create duplicated verts on region boundary
mrmeshpy.makeDegenerateBandAroundRegion(mesh, faces_to_extrude)
# Find vertices that will be moved
verts_for_move = mrmeshpy.getIncidentVerts(mesh.
topology, faces_to_extrude)
# Move each vertex
for v in range(verts_for_move.size()):
if verts_for_move.test(mrmeshpy.
VertId(v)):
mesh.points.vec[v] += mrmeshpy.
Vector3f(0.0, 0.0, 1.0)
# Invalidate internal caches after manual changing
mesh.invalidateCaches()
# Save mesh
mrmeshpy.saveMesh(mesh, "extrudedMesh.stl")
Vector3< float > Vector3f
Definition MRMeshFwd.h:120
Id< VertTag > VertId
Definition MRMeshFwd.h:69
- See also
- Python overview