Wildmeshing Toolkit
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
wmtk::BoundaryEnvelope Class Reference

A tube around the open boundary of a triangle mesh, for operations allowed to move it. More...

#include <BoundaryEnvelope.hpp>

Public Member Functions

template<typename VertexAttributes >
bool init (const TriMesh &m, VertexAttributes &vertex_attrs, double eps, bool use_exact)
 Build the tube around the boundary edges of m and flag their vertices.
 
bool initialized () const
 Whether init() found a boundary to build the tube around.
 
void set_use_exact (bool use_exact)
 
template<typename VertexAttributes >
bool boundary_edges_inside (const TriMesh &m, const VertexAttributes &vertex_attrs, const std::vector< TriMesh::Tuple > &tris) const
 Every boundary edge of tris that touches an input_boundary vertex lies in the tube.
 

Static Public Member Functions

template<typename VertexAttributes >
static bool on_input_boundary (const TriMesh &m, const VertexAttributes &vertex_attrs, const TriMesh::Tuple &v)
 v is an input_boundary vertex that is still on the boundary.
 

Private Member Functions

void build (const std::vector< Eigen::Vector3d > &V, const std::vector< Eigen::Vector2i > &E, double eps, bool use_exact)
 

Private Attributes

Envelope m_envelope
 
bool m_initialized = false
 

Detailed Description

A tube around the open boundary of a triangle mesh, for operations allowed to move it.

The alternative to freezing the boundary. Freezing keeps the outline exactly, and with it everything enclosed by boundary loops packed too tightly to leave a free vertex between them. The tube lets the outline coarsen and move instead, as long as every boundary edge that descends from the input's boundary stays within eps of the input's boundary edges. Holes and slits narrower than the tube can then close.

"Descends from" is a per-vertex lineage flag, input_boundary, kept in the mesh's own vertex attributes so that it is rolled back and consolidated with them. The operations maintain it:

A boundary edge derived from the input's outline then always touches a flagged vertex, and boundary_edges_inside() judges exactly those. Boundary that an operation opens elsewhere – a collapse with the link condition off tearing a dense closed patch, say – is not judged, as it was not judged under a frozen boundary either: such tears are transient while a patch simplifies, and refusing them leaves it stuck (Thingi10K 55928; see ShortestEdgeCollapse::create_mesh).

The vertex attributes are duck-typed: anything indexed by vertex id whose elements have an Eigen::Vector3d pos and a bool input_boundary – in practice a component's AttributeCollection<VertexAttributes>.

Member Function Documentation

◆ boundary_edges_inside()

template<typename VertexAttributes >
bool wmtk::BoundaryEnvelope::boundary_edges_inside ( const TriMesh &  m,
const VertexAttributes &  vertex_attrs,
const std::vector< TriMesh::Tuple > &  tris 
) const
inline

Every boundary edge of tris that touches an input_boundary vertex lies in the tube.

Meant for TriMesh::invariants(), with the triangles an operation produced: they include every edge whose position or boundary status the operation changed. Edges touching no flagged vertex are skipped before the boundary test, so a mesh far from its boundary pays one flag lookup per edge.

◆ init()

template<typename VertexAttributes >
bool wmtk::BoundaryEnvelope::init ( const TriMesh &  m,
VertexAttributes &  vertex_attrs,
double  eps,
bool  use_exact 
)
inline

Build the tube around the boundary edges of m and flag their vertices.

Call right after TriMesh::init, before any operation.

Parameters
epstube radius
use_exactwhether queries use the exact predicate. An edge envelope builds its exact structure only when this is set here, so set it to whatever the surface envelope uses; set_use_exact() can switch to the sampled predicate later, but not back.
Returns
whether there is a boundary. A closed mesh builds nothing and flags nothing, so there is nothing to judge either, and initialized() stays false.

◆ on_input_boundary()

template<typename VertexAttributes >
static bool wmtk::BoundaryEnvelope::on_input_boundary ( const TriMesh &  m,
const VertexAttributes &  vertex_attrs,
const TriMesh::Tuple &  v 
)
inlinestatic

v is an input_boundary vertex that is still on the boundary.

For placement: an operation that moves such a vertex off the boundary pulls the outline into the surface, which the tube then refuses, so the operation is better off keeping it where it is. Only flagged vertices pay for the ring walk.

The ring walk reads the connectivity of v's neighbours, so in a parallel pass ask it only where those are locked – of an endpoint of the edge an operation is about to change, say, not of the edges it hands back for re-queueing.

◆ set_use_exact()

void wmtk::BoundaryEnvelope::set_use_exact ( bool  use_exact)
inline

Answer queries with the exact predicate or the sampled one, to follow a surface envelope whose flag the caller flips after init() (tetwild does, around its simplification). The exact structure exists only if use_exact was on at init().


The documentation for this class was generated from the following files: