MeshLib C++ Docs
Loading...
Searching...
No Matches
Fill/Stitch Holes overview

This chapter represents documentation about hole triangulations or stitching two holes. More...

Classes

struct  MR::FillHoleParams
 Parameters structure for MR::fillHole
Structure has some options to control MR::fillHole. More...
struct  MR::StitchHolesParams
 Parameters structure for MR::stitchHoles
Structure has some options to control MR::stitchHoles. More...
struct  MR::FillHoleItem
struct  MR::HoleFillPlan
 concise representation of proposed hole triangulation More...
struct  MR::MakeBridgeResult
struct  MR::FillHoleMetric
 Holds metrics for fillHole and stitchHoles triangulation
. More...

Typedefs

using MR::FillTriangleMetric = std::function<double( VertId a, VertId b, VertId c )>
 args: three vertices of candidate triangle
using MR::FillEdgeMetric = std::function<double( VertId a, VertId b, VertId l, VertId r )>
using MR::FillCombineMetric = std::function<double( double, double )>
 args: two metric weights to combine (usualy it is simple sum of them)

Functions

void MR::stitchHoles (Mesh &mesh, EdgeId a, EdgeId b, const StitchHolesParams &params={})
 Stitches two holes in Mesh
.
void MR::buildCylinderBetweenTwoHoles (Mesh &mesh, EdgeId a, EdgeId b, const StitchHolesParams &params={})
bool MR::stitchHoles (Mesh &mesh, const StitchHolesParams &params={})
 this version finds holes in the mesh by itself and returns false if they are not found
bool MR::buildCylinderBetweenTwoHoles (Mesh &mesh, const StitchHolesParams &params={})
void MR::fillHole (Mesh &mesh, EdgeId a, const FillHoleParams &params={})
 Fills hole in mesh
.
void MR::fillHoles (Mesh &mesh, const std::vector< EdgeId > &as, const FillHoleParams &params={})
 fill all holes given by their representative edges in
bool MR::isHoleBd (const MeshTopology &topology, const EdgeLoop &loop)
HoleFillPlan MR::getHoleFillPlan (const Mesh &mesh, EdgeId e, const FillHoleParams &params={})
std::vector< HoleFillPlanMR::getHoleFillPlans (const Mesh &mesh, const std::vector< EdgeId > &holeRepresentativeEdges, const FillHoleParams &params={})
HoleFillPlan MR::getPlanarHoleFillPlan (const Mesh &mesh, EdgeId e)
std::vector< HoleFillPlanMR::getPlanarHoleFillPlans (const Mesh &mesh, const std::vector< EdgeId > &holeRepresentativeEdges)
void MR::executeHoleFillPlan (Mesh &mesh, EdgeId a0, HoleFillPlan &plan, FaceBitSet *outNewFaces=nullptr)
 quickly triangulates the face or hole to the left of (e) given the plan (quickly compared to fillHole function)
VertId MR::fillHoleTrivially (Mesh &mesh, EdgeId a, FaceBitSet *outNewFaces=nullptr)
 Triangulates face of hole in mesh trivially
.
EdgeId MR::extendHole (Mesh &mesh, EdgeId a, const Plane3f &plane, FaceBitSet *outNewFaces=nullptr)
std::vector< EdgeId > MR::extendAllHoles (Mesh &mesh, const Plane3f &plane, FaceBitSet *outNewFaces=nullptr)
EdgeId MR::extendHole (Mesh &mesh, EdgeId a, std::function< Vector3f(const Vector3f &)> getVertPos, FaceBitSet *outNewFaces=nullptr)
EdgeId MR::buildBottom (Mesh &mesh, EdgeId a, Vector3f dir, float holeExtension, FaceBitSet *outNewFaces=nullptr)
EdgeId MR::makeDegenerateBandAroundHole (Mesh &mesh, EdgeId a, FaceBitSet *outNewFaces=nullptr)
MakeBridgeResult MR::makeQuadBridge (MeshTopology &topology, EdgeId a, EdgeId b, FaceBitSet *outNewFaces=nullptr)
MakeBridgeResult MR::makeBridge (MeshTopology &topology, EdgeId a, EdgeId b, FaceBitSet *outNewFaces=nullptr)
MakeBridgeResult MR::makeSmoothBridge (Mesh &mesh, EdgeId a, EdgeId b, float samplingStep, FaceBitSet *outNewFaces=nullptr)
EdgeId MR::makeBridgeEdge (MeshTopology &topology, EdgeId a, EdgeId b)
void MR::splitQuad (MeshTopology &topology, EdgeId a, FaceBitSet *outNewFaces=nullptr)
 given quadrangle face to the left of a, splits it in two triangles with new diagonal edge via dest(a)
double MR::calcCombinedFillMetric (const Mesh &mesh, const FaceBitSet &filledRegion, const FillHoleMetric &metric)
 Computes combined metric after filling a hole.
FillHoleMetric MR::getCircumscribedMetric (const Mesh &mesh)
FillHoleMetric MR::getPlaneFillMetric (const Mesh &mesh, EdgeId e)
FillHoleMetric MR::getPlaneNormalizedFillMetric (const Mesh &mesh, EdgeId e)
FillHoleMetric MR::getComplexStitchMetric (const Mesh &mesh)
FillHoleMetric MR::getEdgeLengthFillMetric (const Mesh &mesh)
 Simple metric minimizing the sum of all edge lengths.
FillHoleMetric MR::getEdgeLengthStitchMetric (const Mesh &mesh)
FillHoleMetric MR::getVerticalStitchMetric (const Mesh &mesh, const Vector3f &upDir)
FillHoleMetric MR::getVerticalStitchMetricEdgeBased (const Mesh &mesh, const Vector3f &upDir)
FillHoleMetric MR::getComplexFillMetric (const Mesh &mesh, EdgeId e)
FillHoleMetric MR::getParallelPlaneFillMetric (const Mesh &mesh, EdgeId e, const Plane3f *plane=nullptr)
 This metric minimizes summary projection of new edges to plane normal, (try do produce edges parallel to plane)
FillHoleMetric MR::getMaxDihedralAngleMetric (const Mesh &mesh)
FillHoleMetric MR::getUniversalMetric (const Mesh &mesh)
FillHoleMetric MR::getMinTriAngleMetric (const Mesh &mesh)
 This metric maximizes the minimal angle among all faces in the triangulation.
FillHoleMetric MR::getMinAreaMetric (const Mesh &mesh)

Variables

const double MR::BadTriangulationMetric

Detailed Description

This chapter represents documentation about hole triangulations or stitching two holes.

Typedef Documentation

◆ FillCombineMetric

using MR::FillCombineMetric = std::function<double( double, double )>

#include <MRMesh/MRMeshMetrics.h>

args: two metric weights to combine (usualy it is simple sum of them)

◆ FillEdgeMetric

using MR::FillEdgeMetric = std::function<double( VertId a, VertId b, VertId l, VertId r )>

#include <MRMesh/MRMeshMetrics.h>

args: a->b: candidate edge l: next(a->b) note that they are not connected in topology untill triangulation process ends r: prev(a->b) note that they are not connected in topology untill triangulation process ends

◆ FillTriangleMetric

using MR::FillTriangleMetric = std::function<double( VertId a, VertId b, VertId c )>

#include <MRMesh/MRMeshMetrics.h>

args: three vertices of candidate triangle

Function Documentation

◆ buildBottom()

EdgeId MR::buildBottom ( Mesh & mesh,
EdgeId a,
Vector3f dir,
float holeExtension,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

adds cylindrical extension of given hole represented by one of its edges (having no valid left face) by adding new vertices located in lowest point of the hole -dir*holeExtension and 2 * number_of_hole_edge triangles;

Returns
the edge of new hole opposite to input edge (a)

◆ buildCylinderBetweenTwoHoles() [1/2]

bool MR::buildCylinderBetweenTwoHoles ( Mesh & mesh,
const StitchHolesParams & params = {} )

◆ buildCylinderBetweenTwoHoles() [2/2]

void MR::buildCylinderBetweenTwoHoles ( Mesh & mesh,
EdgeId a,
EdgeId b,
const StitchHolesParams & params = {} )

◆ calcCombinedFillMetric()

double MR::calcCombinedFillMetric ( const Mesh & mesh,
const FaceBitSet & filledRegion,
const FillHoleMetric & metric )

#include <MRMesh/MRMeshMetrics.h>

Computes combined metric after filling a hole.

◆ executeHoleFillPlan()

void MR::executeHoleFillPlan ( Mesh & mesh,
EdgeId a0,
HoleFillPlan & plan,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

quickly triangulates the face or hole to the left of (e) given the plan (quickly compared to fillHole function)

◆ extendAllHoles()

std::vector< EdgeId > MR::extendAllHoles ( Mesh & mesh,
const Plane3f & plane,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

adds cylindrical extension of too all holes of the mesh by calling extendHole(...);

Returns
representative edges of one per every hole after extension

◆ extendHole() [1/2]

EdgeId MR::extendHole ( Mesh & mesh,
EdgeId a,
const Plane3f & plane,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

adds cylindrical extension of given hole represented by one of its edges (having no valid left face) by adding new vertices located in given plane and 2 * number_of_hole_edge triangles;

Returns
the edge of new hole opposite to input edge (a)

◆ extendHole() [2/2]

EdgeId MR::extendHole ( Mesh & mesh,
EdgeId a,
std::function< Vector3f(const Vector3f &)> getVertPos,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

adds extension of given hole represented by one of its edges (having no valid left face) by adding new vertices located at getVertPos( existing vertex position );

Returns
the edge of new hole opposite to input edge (a)

◆ fillHole()

void MR::fillHole ( Mesh & mesh,
EdgeId a,
const FillHoleParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

Fills hole in mesh
.

Fills given hole represented by one of its edges (having no valid left face),
uses fillHoleTrivially if cannot fill hole without multiple edges,
default metric: CircumscribedFillMetric

Before
After

Next picture show, how newly generated faces can be smoothed MR::positionVertsSmoothly MR::subdivideMesh

Fill with smooth
Parameters
meshmesh with hole
aEdgeId which represents hole (should not have valid left FaceId)
paramsparameters of hole filling
See also
stitchHoles
fillHoleTrivially
FillHoleParams

◆ fillHoles()

void MR::fillHoles ( Mesh & mesh,
const std::vector< EdgeId > & as,
const FillHoleParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

fill all holes given by their representative edges in

Parameters
as

◆ fillHoleTrivially()

VertId MR::fillHoleTrivially ( Mesh & mesh,
EdgeId a,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

Triangulates face of hole in mesh trivially
.

Fills given hole represented by one of its edges (having no valid left face)
by creating one new vertex in the centroid of boundary vertices and connecting new vertex with all boundary vertices.

Before
After

Next picture show, how newly generated faces can be smoothed MR::positionVertsSmoothly MR::subdivideMesh

Trivial fill with smooth
Parameters
meshmesh with hole
aEdgeId points on the face or hole to the left that will be triangulated
outNewFacesoptional output newly generated faces
Returns
new vertex
See also
fillHole

◆ getCircumscribedMetric()

FillHoleMetric MR::getCircumscribedMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric minimizes the sum of circumcircle radii for all triangles in the triangulation. It is rather fast to calculate, and it results in typically good triangulations.

◆ getComplexFillMetric()

FillHoleMetric MR::getComplexFillMetric ( const Mesh & mesh,
EdgeId e )

#include <MRMesh/MRMeshMetrics.h>

This metric minimizes the sum of triangleMetric for all triangles in the triangulation plus the sum edgeMetric for all edges inside and on the boundary of the triangulation.
Where
triangleMetric is proportional to weighted triangle area and triangle aspect ratio
edgeMetric grows with angle between triangles as ( ( 1 - cos( x ) ) / ( 1 + cos( x ) ) ) ^ 4.

◆ getComplexStitchMetric()

FillHoleMetric MR::getComplexStitchMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric minimizes the sum of triangleMetric for all triangles in the triangulation plus the sum edgeMetric for all edges inside and on the boundary of the triangulation.
Where
triangleMetric is proportional to triangle aspect ratio
edgeMetric is proportional to ( 1 - dihedralAngleCos )

◆ getEdgeLengthFillMetric()

FillHoleMetric MR::getEdgeLengthFillMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

Simple metric minimizing the sum of all edge lengths.

◆ getEdgeLengthStitchMetric()

FillHoleMetric MR::getEdgeLengthStitchMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

Forbids connecting vertices from the same hole
Simple metric minimizing edge length

◆ getHoleFillPlan()

HoleFillPlan MR::getHoleFillPlan ( const Mesh & mesh,
EdgeId e,
const FillHoleParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

prepares the plan how to triangulate the face or hole to the left of (e) (not filling it immediately), several getHoleFillPlan can work in parallel

◆ getHoleFillPlans()

std::vector< HoleFillPlan > MR::getHoleFillPlans ( const Mesh & mesh,
const std::vector< EdgeId > & holeRepresentativeEdges,
const FillHoleParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

prepares the plans how to triangulate the faces or holes, each given by a boundary edge (with filling target to the left), the plans are prepared in parallel with minimal memory allocation compared to manual calling of several getHoleFillPlan(), but it can inefficient when some holes are very complex

◆ getMaxDihedralAngleMetric()

FillHoleMetric MR::getMaxDihedralAngleMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric minimizes the maximal dihedral angle between the faces in the triangulation and on its boundary

◆ getMinAreaMetric()

FillHoleMetric MR::getMinAreaMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric is for triangulation construction with minimal summed area of triangles. Warning: this metric can produce degenerated triangles

◆ getMinTriAngleMetric()

FillHoleMetric MR::getMinTriAngleMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric maximizes the minimal angle among all faces in the triangulation.

◆ getParallelPlaneFillMetric()

FillHoleMetric MR::getParallelPlaneFillMetric ( const Mesh & mesh,
EdgeId e,
const Plane3f * plane = nullptr )

#include <MRMesh/MRMeshMetrics.h>

This metric minimizes summary projection of new edges to plane normal, (try do produce edges parallel to plane)

◆ getPlanarHoleFillPlan()

HoleFillPlan MR::getPlanarHoleFillPlan ( const Mesh & mesh,
EdgeId e )

#include <MRMesh/MRMeshFillHole.h>

prepares the plan how to triangulate the planar face or planar hole to the left of (e) (not filling it immediately), several getPlanarHoleFillPlan can work in parallel

◆ getPlanarHoleFillPlans()

std::vector< HoleFillPlan > MR::getPlanarHoleFillPlans ( const Mesh & mesh,
const std::vector< EdgeId > & holeRepresentativeEdges )

#include <MRMesh/MRMeshFillHole.h>

prepares the plans how to triangulate the planar faces or holes, each given by a boundary edge (with filling target to the left), the plans are prepared in parallel with minimal memory allocation compared to manual calling of several getPlanarHoleFillPlan(), but it can inefficient when some holes are very complex

◆ getPlaneFillMetric()

FillHoleMetric MR::getPlaneFillMetric ( const Mesh & mesh,
EdgeId e )

#include <MRMesh/MRMeshMetrics.h>

Same as getCircumscribedFillMetric, but with extra penalty for the triangles having normals looking in the opposite side of plane containing left of (e).

◆ getPlaneNormalizedFillMetric()

FillHoleMetric MR::getPlaneNormalizedFillMetric ( const Mesh & mesh,
EdgeId e )

#include <MRMesh/MRMeshMetrics.h>

Similar to getPlaneFillMetric with extra penalty for the triangles having normals looking in the opposite side of plane containing left of (e), but the metric minimizes the sum of circumcircle radius times aspect ratio for all triangles in the triangulation.

◆ getUniversalMetric()

FillHoleMetric MR::getUniversalMetric ( const Mesh & mesh)

#include <MRMesh/MRMeshMetrics.h>

This metric consists of two parts 1) for each triangle: it is the circumcircle diameter, this avoids the appearance of degenerate triangles; 2) for each edge: square root of double total area of triangles to its left and right times the factor depending extensionally on absolute dihedral angle between left and right triangles, this makes visually triangulated surface as smooth as possible. For planar holes it is the same as getCircumscribedMetric.

◆ getVerticalStitchMetric()

FillHoleMetric MR::getVerticalStitchMetric ( const Mesh & mesh,
const Vector3f & upDir )

#include <MRMesh/MRMeshMetrics.h>

Forbids connecting vertices from the same hole
penalize for large area and face normal deviation from upDir
All new faces should be parallel to given direction

◆ getVerticalStitchMetricEdgeBased()

FillHoleMetric MR::getVerticalStitchMetricEdgeBased ( const Mesh & mesh,
const Vector3f & upDir )

#include <MRMesh/MRMeshMetrics.h>

Forbids connecting vertices from the same hole
penalize for long edges and its deviation from upDir
All new faces should be parallel to given direction

◆ isHoleBd()

bool MR::isHoleBd ( const MeshTopology & topology,
const EdgeLoop & loop )
nodiscard

#include <MRMesh/MRMeshFillHole.h>

returns true if given loop is a boundary of one hole in given mesh topology:

  • every edge in the loop does not have left face,
  • next/prev edges in the loop are related as follows: next = topology.prev( prev.sym() ) if the function returns true, then any edge from the loop passed to fillHole will fill the same hole

◆ makeBridge()

MakeBridgeResult MR::makeBridge ( MeshTopology & topology,
EdgeId a,
EdgeId b,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

creates a bridge between two boundary edges a and b (both having no valid left face); bridge consists of two triangles in general or of one triangle if a and b are neighboring edges on the boundary;

Returns
MakeBridgeResult evaluating to false if bridge cannot be created because otherwise multiple edges appear

◆ makeBridgeEdge()

EdgeId MR::makeBridgeEdge ( MeshTopology & topology,
EdgeId a,
EdgeId b )

#include <MRMesh/MRMeshFillHole.h>

creates a new bridge edge between origins of two boundary edges a and b (both having no valid left face);

Returns
invalid id if bridge cannot be created because otherwise multiple edges appear

◆ makeDegenerateBandAroundHole()

EdgeId MR::makeDegenerateBandAroundHole ( Mesh & mesh,
EdgeId a,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

creates a band of degenerate triangles around given hole;

Returns
the edge of new hole opposite to input edge (a)

◆ makeQuadBridge()

MakeBridgeResult MR::makeQuadBridge ( MeshTopology & topology,
EdgeId a,
EdgeId b,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

creates a bridge between two boundary edges a and b (both having no valid left face); bridge consists of one quadrangle in general (beware that it cannot be rendered) or of one triangle if a and b are neighboring edges on the boundary;

Returns
false if bridge cannot be created because otherwise multiple edges appear

◆ makeSmoothBridge()

MakeBridgeResult MR::makeSmoothBridge ( Mesh & mesh,
EdgeId a,
EdgeId b,
float samplingStep,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

creates a bridge between two boundary edges a and b (both having no valid left face); bridge consists of strip of quadrangles (each consisting of two triangles) in general or of some triangles if a and b are neighboring edges on the boundary; the bridge is made as smooth as possible with small angles in between its links and on the boundary with existed triangles;

Parameters
samplingStepboundaries of the bridge will be subdivided until the distance between neighbor points becomes less than this distance
Returns
MakeBridgeResult evaluating to false if bridge cannot be created because otherwise multiple edges appear

◆ splitQuad()

void MR::splitQuad ( MeshTopology & topology,
EdgeId a,
FaceBitSet * outNewFaces = nullptr )

#include <MRMesh/MRMeshFillHole.h>

given quadrangle face to the left of a, splits it in two triangles with new diagonal edge via dest(a)

◆ stitchHoles() [1/2]

bool MR::stitchHoles ( Mesh & mesh,
const StitchHolesParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

this version finds holes in the mesh by itself and returns false if they are not found

◆ stitchHoles() [2/2]

void MR::stitchHoles ( Mesh & mesh,
EdgeId a,
EdgeId b,
const StitchHolesParams & params = {} )

#include <MRMesh/MRMeshFillHole.h>

Stitches two holes in Mesh
.

Build cylindrical patch to fill space between two holes represented by one of their edges each,
default metric: ComplexStitchMetric

Before
After

Next picture show, how newly generated faces can be smoothed MR::positionVertsSmoothly MR::subdivideMesh

Stitch with smooth
Parameters
meshmesh with hole
aEdgeId which represents 1st hole (should not have valid left FaceId)
bEdgeId which represents 2nd hole (should not have valid left FaceId)
paramsparameters of holes stitching
See also
fillHole
StitchHolesParams

Variable Documentation

◆ BadTriangulationMetric

const double MR::BadTriangulationMetric
extern

#include <MRMesh/MRMeshMetrics.h>

Big value, but less then DBL_MAX, to be able to pass some bad triangulations instead of breaking it e10 - real metrics to have weight in triangulation, if it would be more than e15+ some metrics will be less than double precision