Wildmeshing Toolkit
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Public Attributes | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
wmtk::TriMesh Class Reference
Inheritance diagram for wmtk::TriMesh:
wmtk::TriOptimizerMesh wmtk::components::c1_simplification::MMSurfaceMesh wmtk::components::c1_simplification::MMUVMesh wmtk::components::isotropic_remeshing::IsotropicRemeshing wmtk::components::qslim::QSlimMesh wmtk::components::shortest_edge_collapse::ShortestEdgeCollapse wmtk::components::simwild::tri::SimWildMeshTri wmtk::components::topological_offset::TopoOffsetTriMesh wmtk::components::triwild::TriWildMesh wmtk::components::manifold_extraction::ManExtractTriMesh

Classes

struct  RingLockScratch
 Per-thread buffers for the n-ring lock, so a lock acquisition allocates nothing. More...
 
class  SmartTuple
 
class  TriangleConnectivity
 
class  Tuple
 
class  VertexConnectivity
 

Public Types

template<typename T >
using vector = std::vector< T >
 
using VertexMutex = wmtk::threading::VertexMutex
 

Public Member Functions

void init (size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris)
 
void init (const MatrixXi &F)
 Generate the connectivity of the mesh from an IGL-style F matrix.
 
std::vector< Tupleget_vertices () const
 
std::vector< Tupleget_edges () const
 
std::vector< Tupleget_faces () const
 
Tuple tuple_from_edge (size_t vid1, size_t vid2, size_t fid) const
 
Tuple tuple_from_vids (size_t vid0, size_t vid1, size_t vid2) const
 
simplex::Vertex simplex_from_vertex (const Tuple &t) const
 
simplex::Edge simplex_from_edge (const Tuple &t) const
 
simplex::Face simplex_from_face (const Tuple &t) const
 
simplex::Face simplex_from_face (const size_t fid) const
 
Tuple tuple_from_simplex (const simplex::Face &s) const
 
simplex::SimplexCollection simplex_incident_triangles (const simplex::Vertex &v) const
 
simplex::SimplexCollection simplex_incident_triangles (const simplex::Edge &e) const
 
simplex::SimplexCollection simplex_link_vertices (const simplex::Vertex &v) const
 
simplex::SimplexCollection simplex_link_vertices (const simplex::Edge &e) const
 
simplex::SimplexCollection simplex_link_edges (const simplex::Vertex &v) const
 
void set_preallocation_factor (double factor)
 Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so operations can grab fresh slots without resizing the storage. When a pass exhausts the reserved capacity the affected operations fail (retried later after a consolidate). Values < 1 are clamped to 1.
 
double preallocation_factor () const
 
long request_tri_slots (size_t n)
 
long request_vert_slots (size_t n)
 
virtual bool invariants (const std::vector< Tuple > &)
 User specified invariants that can't be violated.
 
virtual bool split_edge_before (const Tuple &t)
 User specified preparations and desideratas for an edge split.
 
virtual bool split_edge_after (const Tuple &t)
 User specified modifications and desideratas after an edge split.
 
virtual bool collapse_edge_before (const Tuple &t)
 User specified preparations and desideratas for an edge collapse including the link check as collapse prerequisite.
 
virtual bool collapse_edge_after (const Tuple &t)
 User specified modifications and desideratas after an edge collapse.
 
virtual bool swap_edge_after (const Tuple &t)
 User specified modifications and desideras after an edge swap.
 
virtual bool swap_edge_before (const Tuple &t)
 User specified preparations and desideratas for an edge swap including 1.can't swap on boundary edge. 2. when swap edge between v1, v2, there can't exist edges between the two opposite vertices v3, v4.
 
virtual bool smooth_before (const Tuple &t)
 User specified preparations and desideratas for an edge smooth.
 
virtual bool smooth_after (const Tuple &t)
 User specified modifications and desideras after an edge smooth.
 
virtual bool split_face_before (const Tuple &t)
 User specified preparations and desideratas for a face split.
 
virtual bool split_face_after (const Tuple &t)
 User specified modifications and desideratas after a face split.
 
size_t tri_capacity () const
 get the current largest global fid
 
size_t vert_capacity () const
 get the current largest global vid
 
void consolidate_mesh ()
 removing the elements that are removed
 
void remove_tris_by_ids (const std::vector< size_t > &fids)
 Mark the given triangles, and any vertex left without an incident triangle, as removed.
 
Tuple switch_vertex (const Tuple &t) const
 a duplicate of Tuple::switch_vertex funciton
 
Tuple switch_edge (const Tuple &t) const
 a duplicate of Tuple::switch_edge funciton
 
std::optional< Tupleswitch_face (const Tuple &t) const
 a duplicate of Tuple::switch_face funciton
 
bool check_link_condition (const Tuple &t) const
 prerequisite for collapse
 
void set_use_link_condition (bool use_it)
 Should collapse_edge_before enforce the link condition?
 
bool use_link_condition () const
 
bool check_mesh_connectivity_validity () const
 verify the connectivity validity of the mesh
 
bool check_edge_manifold () const
 verify the edge manifoldness of the mesh
 
size_t edge_valence (const TriMesh::Tuple &t) const
 Number of triangles incident to the edge the Tuple points at.
 
bool is_boundary_edge (const TriMesh::Tuple &t) const
 Does exactly one triangle share this edge?
 
bool is_manifold_edge (const TriMesh::Tuple &t) const
 Do exactly two triangles share this edge?
 
size_t vertex_component_count (const size_t vid) const
 Number of edge-connected components in the fan of a vertex.
 
size_t vertex_component_count (const TriMesh::Tuple &t) const
 
bool is_manifold_vertex (const size_t vid) const
 
std::optional< Tupleswitch_component (const TriMesh::Tuple &t) const
 Jump to the next edge-connected component of the fan of the Tuple's vertex.
 
bool is_boundary_vertex (const TriMesh::Tuple &t) const
 check if the vertex that's represented by a Tuple is at the boundary of the mesh
 
bool split_edge (const Tuple &t, std::vector< Tuple > &new_t)
 
virtual bool collapse_edge (const Tuple &t, std::vector< Tuple > &new_t)
 
void collapse_edge_conn (const Tuple &loc0, std::vector< Tuple > &new_tris, Tuple &return_t, size_t &new_vid, std::vector< std::pair< size_t, TriangleConnectivity > > &old_tris, std::vector< std::pair< size_t, VertexConnectivity > > &old_vertices, std::vector< std::pair< size_t, size_t > > &same_edge_vid_fid, std::vector< size_t > &n12_intersect_fids)
 
void collapse_edge_rollback (size_t &new_vid, std::vector< std::pair< size_t, TriangleConnectivity > > &old_tris, std::vector< std::pair< size_t, VertexConnectivity > > &old_vertices, std::vector< std::pair< size_t, size_t > > &same_edge_vid_fid, std::vector< size_t > &n12_intersect_fids)
 
bool swap_edge (const Tuple &t, std::vector< Tuple > &new_t)
 
bool smooth_vertex (const Tuple &t)
 
bool split_face (const Tuple &t, std::vector< Tuple > &new_t)
 Split a face in 3 faces.
 
size_t get_valence_for_vertex (const Tuple &t) const
 Count the number of the one ring tris for a vertex.
 
size_t vertex_valence (const size_t vid) const
 Number of triangles incident to a vertex, by id.
 
std::vector< Tupleget_one_ring_tris_for_vertex (const Tuple &t) const
 Get the one ring tris for a vertex.
 
const std::vector< size_t > & get_one_ring_fids_for_vertex (const Tuple &t) const
 
const std::vector< size_t > & get_one_ring_fids_for_vertex (const size_t vid) const
 
std::vector< size_t > get_one_ring_vids_for_vertex_duplicate (const size_t &t) const
 Get the vids of the incident one ring tris for a vertex.
 
void get_one_ring_vids_for_vertex_duplicate (const size_t &t, std::vector< size_t > &one_ring) const
 
std::vector< size_t > get_incident_fids_for_edge (const Tuple &t) const
 
std::vector< size_t > get_incident_fids_for_edge (const size_t vid0, const size_t vid1) const
 
std::vector< Tupleget_one_ring_edges_for_vertex (const Tuple &t) const
 Get all edges that are incident to the vertex of Tuple t.
 
std::vector< Tupleget_one_ring_edges_for_vertex (const size_t vid) const
 
std::array< Tuple, 3 > oriented_tri_vertices (const Tuple &t) const
 Get the incident vertices for a triangle.
 
std::array< size_t, 3 > oriented_tri_vids (const Tuple &t) const
 Get the incident vertices for a triangle.
 
std::array< size_t, 3 > oriented_tri_vids (const size_t i) const
 
std::array< Tuple, 2 > get_edge_vertices (const Tuple &t) const
 
std::array< size_t, 2 > get_edge_vids (const Tuple &t) const
 
Tuple tuple_from_tri (size_t fid) const
 
Tuple tuple_from_vertex (size_t vid) const
 
Tuple tuple_from_edge (size_t fid, size_t local_eid) const
 
std::tuple< Tuple, size_t > tuple_from_edge (const std::array< size_t, 2 > &vids) const
 
std::optional< std::tuple< Tuple, size_t > > try_tuple_from_edge (const std::array< size_t, 2 > &vids) const
 tuple_from_edge for callers where a missing edge is an answer, not a bug.
 
void start_protect_attributes ()
 Start the phase where the attributes that will be modified can be recorded.
 
void release_protect_attributes ()
 End the modification phase.
 
void rollback_protected_attributes ()
 rollback the attributes that are modified if any condition failed
 
int release_vertex_mutex_in_stack ()
 
int release_vertex_mutex_to (size_t mark)
 Release the mutexes taken since the release stack held mark entries.
 
bool try_set_vertex_mutex_n_ring (const Tuple &v, int threadid, int n)
 Lock every vertex within graph distance n of v, the seed included.
 
bool try_set_vertex_mutex_n_ring (size_t vid, int threadid, int n)
 
bool try_set_edge_mutex_n_ring (const Tuple &e, int threadid, int n)
 try_set_vertex_mutex_n_ring seeded from both ends of an edge.
 
bool try_set_face_mutex_one_ring (const Tuple &f, int threadid)
 try lock the one-ring neighboring triangles' incident vertices.
 
void for_each_face (const std::function< void(const Tuple &)> &)
 perform the given function for each face
 
void for_each_edge (const std::function< void(const Tuple &)> &)
 perform the given function for each edge
 
void for_each_vertex (const std::function< void(const Tuple &)> &)
 perform the given function for each vertex
 
virtual bool vertex_is_on_surface (const size_t vid) const
 Is a vertex part of the substructure.
 
virtual bool edge_is_on_surface (const std::array< size_t, 2 > &vids) const
 Is an edge part of the substructure.
 
simplex::SimplexCollection get_surface_edges_for_vertex (const size_t vid) const
 Get all edges on the surface that are incident to vid.
 
size_t get_order_of_edge (const std::array< size_t, 2 > &vids) const
 Compute the order of an edge.
 
size_t get_order_of_vertex (const size_t vid) const
 Get the order of a vertex.
 
bool substructure_link_condition (const Tuple &e_tuple) const
 Link condition that also considers substructures.
 
Ring lockers – NOT balls

The three helpers below are the ones every pass actually uses, and none of them claims the ball its name suggests. Each walks the ring with

if (m_vertex_mutex[w].get_owner() == threadid) continue;

and that continue skips the EXPANSION as well as the lock. So a vertex this thread already holds contributes none of its neighbours. In try_set_edge_mutex_two_ring the effect is systematic rather than incidental: v2 is locked up front, so walking v1's ring skips straight past it, and by the time v2's ring is walked almost everything in it is already owned from v1's expansion and is skipped in turn. What comes out is roughly 2-ring(v1) union N(v2) – the vertices at distance 2 from v2 and 3 from v1 are simply not claimed.

This is deliberate, and swapping in try_set_vertex_mutex_n_ring is a performance regression, not a cleanup. Measured: routing the passes through the complete ball cost +80% wall clock on the 14 challenging tetwild models at 16 threads (844s -> 1522s) and -0.4% on the 16 challenging triwild ones. 3D is where it hurts, because a tet vertex has ~30 neighbours and the honest 2-ring ball is enormous next to what these claim.

It is also a coverage-vs-name mismatch rather than a known race. What the operations rely on is that the whole ONE-ring of the seed simplex is held, and that they hold: the outer loops lock every unowned neighbour directly and only skip expanding through owned ones, so {v1, v2} u N(v1) u N(v2) is always claimed. That set is the operation's entire write set, and two operations interfere only if their one-rings meet – in which case they contend on the shared vertex and serialise. The second ring is defensive margin. No failing case is known for the part that is missing; if you find one, the fix is to widen the specific pass that needs it via try_set_vertex_mutex_n_ring, not to widen all of them.

A caller that genuinely needs a complete ball asks for one explicitly. The coarsening pass does: it re-smooths a k-ring, so it writes the k-ring and reads the (k+1)-ring, well past what a plain collapse claims.

bool try_set_vertex_mutex_two_ring (const Tuple &v, int threadid)
 Lock v's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_edge_mutex_two_ring (const Tuple &e, int threadid)
 Lock the edge's one-ring and, partially, its two-ring. See the note above.
 
bool try_set_vertex_mutex_one_ring (const Tuple &v, int threadid)
 Lock v and its one-ring. Complete, unlike the two-ring pair.
 

Public Attributes

AbstractAttributeContainerp_vertex_attrs = nullptr
 
AbstractAttributeContainerp_edge_attrs = nullptr
 
AbstractAttributeContainerp_face_attrs = nullptr
 
wmtk::threading::enumerable_thread_specific< std::vector< size_t > > mutex_release_stack
 
int NUM_THREADS = 0
 

Protected Member Functions

void vertex_fan_components (size_t vid, std::vector< size_t > &component_of, std::vector< size_t > &representatives) const
 
void resize_mutex (size_t v)
 

Private Member Functions

size_t reserved_capacity (size_t live_count) const
 
size_t get_next_empty_slot_t ()
 Get the next avaiblie global index for the triangle.
 
size_t get_next_empty_slot_v ()
 Get the next avaiblie global index for the vertex.
 
bool try_set_vertex_mutex (const Tuple &v, int threadid)
 
bool try_set_vertex_mutex (size_t vid, int threadid)
 
void unlock_vertex_mutex (const Tuple &v)
 
void unlock_vertex_mutex (size_t vid)
 
bool lock_vertex_ball (const size_t *seeds, size_t n_seeds, int threadid, int n, size_t mark)
 The n-ring BFS. mark is the release-stack watermark to unwind to on failure.
 

Private Attributes

vector< VertexConnectivitym_vertex_connectivity
 
vector< TriangleConnectivitym_tri_connectivity
 
std::atomic_long current_vert_size
 
std::atomic_long current_tri_size
 
double m_preallocation_factor = 6.0
 
bool m_use_link_condition = true
 
std::vector< VertexMutexm_vertex_mutex
 
wmtk::threading::enumerable_thread_specific< RingLockScratchm_ring_lock_scratch
 

Dimension-generic cell accessors

A "cell" is the top-dimensional element: a triangle here, a tet in TetMesh. These three members plus EDGES_PER_CELL are the whole interface the dimension-generic helpers in wmtk/utils (ParallelCollect, SizingField) need, so the same helper works on both meshes without traits or overloads.

static constexpr int EDGES_PER_CELL = 3
 
size_t cell_capacity () const
 
Tuple tuple_from_cell (size_t cid) const
 

Member Typedef Documentation

◆ VertexMutex

See also
wmtk::threading::VertexMutex. Aliased rather than nested so TriMesh and TetMesh cannot drift apart again – they already had.

Member Function Documentation

◆ check_link_condition()

bool wmtk::TriMesh::check_link_condition ( const Tuple t) const

prerequisite for collapse

Parameters
tTuple referes to the edge to be collapsed
Returns
true is the link check is passed

◆ check_mesh_connectivity_validity()

bool wmtk::TriMesh::check_mesh_connectivity_validity ( ) const

verify the connectivity validity of the mesh

Note
a valid mesh can have triangles that are is_removed == true

◆ collapse_edge()

bool TriMesh::collapse_edge ( const Tuple t,
std::vector< Tuple > &  new_t 
)
virtual

Collapse an edge

Parameters
tInput Tuple for the edge to be collapsed.
[out]new_edgesa vector of Tuples refering to the triangles incident to the new vertex introduced
Note
collapse edge a,b and generate a new vertex c
Returns
if collapse succeed

◆ collapse_edge_after()

virtual bool wmtk::TriMesh::collapse_edge_after ( const Tuple t)
inlinevirtual

◆ collapse_edge_before()

virtual bool wmtk::TriMesh::collapse_edge_before ( const Tuple t)
inlinevirtual

User specified preparations and desideratas for an edge collapse including the link check as collapse prerequisite.

Parameters
theedge Tuple to be split
Returns
true if the preparation succeed

Reimplemented in wmtk::components::c1_simplification::MMUVMesh, wmtk::components::c1_simplification::MMSurfaceMesh, wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::qslim::QSlimMesh, wmtk::components::shortest_edge_collapse::ShortestEdgeCollapse, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ collapse_edge_conn()

void TriMesh::collapse_edge_conn ( const Tuple loc0,
std::vector< Tuple > &  new_tris,
Tuple return_t,
size_t &  new_vid,
std::vector< std::pair< size_t, TriangleConnectivity > > &  old_tris,
std::vector< std::pair< size_t, VertexConnectivity > > &  old_vertices,
std::vector< std::pair< size_t, size_t > > &  same_edge_vid_fid,
std::vector< size_t > &  n12_intersect_fids 
)

Collpase an edge connectivity part

◆ collapse_edge_rollback()

void TriMesh::collapse_edge_rollback ( size_t &  new_vid,
std::vector< std::pair< size_t, TriangleConnectivity > > &  old_tris,
std::vector< std::pair< size_t, VertexConnectivity > > &  old_vertices,
std::vector< std::pair< size_t, size_t > > &  same_edge_vid_fid,
std::vector< size_t > &  n12_intersect_fids 
)

collapse edge rollback

◆ consolidate_mesh()

void TriMesh::consolidate_mesh ( )

removing the elements that are removed

Parameters
bnd_outputwhen turn on will write the boundary vertices to "bdn_table.dmat"

◆ edge_is_on_surface()

virtual bool wmtk::TriMesh::edge_is_on_surface ( const std::array< size_t, 2 > &  vids) const
inlinevirtual

Is an edge part of the substructure.

Parameters
vidsThe vertex IDs of the edge

Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ edge_valence()

size_t TriMesh::edge_valence ( const TriMesh::Tuple t) const

Number of triangles incident to the edge the Tuple points at.

1 on the boundary, 2 when manifold, more when not. O(valence).

◆ get_edges()

std::vector< TriMesh::Tuple > TriMesh::get_edges ( ) const

Generate a vector of Tuples for each edge

Note
ensures the fid assigned is the smallest between faces adjacent to the edge
Returns
vector of Tuples refering to unique edges

◆ get_faces()

std::vector< TriMesh::Tuple > TriMesh::get_faces ( ) const

Generate a vector of Tuples from global face index

Note
Local vid is the first of the m_idices Local eid assigned counter clockwise as in the ilustrated example
Returns
vector of Tuples refering to each face

◆ get_next_empty_slot_t()

size_t TriMesh::get_next_empty_slot_t ( )
private

Get the next avaiblie global index for the triangle.

Returns
size_t

◆ get_next_empty_slot_v()

size_t TriMesh::get_next_empty_slot_v ( )
private

Get the next avaiblie global index for the vertex.

Returns
size_t

◆ get_one_ring_edges_for_vertex()

std::vector< wmtk::TriMesh::Tuple > TriMesh::get_one_ring_edges_for_vertex ( const Tuple t) const

Get all edges that are incident to the vertex of Tuple t.

The return tuples contain the edge and the adjacent vertex: return_tuple.switch_vertex().vid == t.vid()

Parameters
ttuple pointing to a vertex
Returns
one-ring

The code below is a faster implementation but it did not give the exact same result for QSLIM. Leaving it commented out for now.

◆ get_one_ring_tris_for_vertex()

std::vector< TriMesh::Tuple > TriMesh::get_one_ring_tris_for_vertex ( const Tuple t) const

Get the one ring tris for a vertex.

Parameters
ttuple pointing to a vertex
Returns
a vector of Tuples refering to one-ring tris

◆ get_one_ring_vids_for_vertex_duplicate()

std::vector< size_t > TriMesh::get_one_ring_vids_for_vertex_duplicate ( const size_t &  t) const

Get the vids of the incident one ring tris for a vertex.

Parameters
ttuple pointing to a vertex
Returns
a vector of vids that can have duplicates

◆ get_order_of_edge()

size_t TriMesh::get_order_of_edge ( const std::array< size_t, 2 > &  vids) const

Compute the order of an edge.

The order of an edge in a TriMesh is as follows: 0: the edge is not on the surface 1: the edge is on the surface

Parameters
vidsThe vertex IDs of the edge

◆ get_order_of_vertex()

size_t TriMesh::get_order_of_vertex ( const size_t  vid) const

Get the order of a vertex.

The order of a vertex in a TriMesh is as follows: 0: vertex is not on the surface 1: vertex is on the surface 2: vertex is a non-manifold vertex in the substructure

Parameters
vidVertex ID

◆ get_surface_edges_for_vertex()

simplex::SimplexCollection TriMesh::get_surface_edges_for_vertex ( const size_t  vid) const

Get all edges on the surface that are incident to vid.

Parameters
vidVertex ID

◆ get_valence_for_vertex()

size_t wmtk::TriMesh::get_valence_for_vertex ( const Tuple t) const
inline

Count the number of the one ring tris for a vertex.

Parameters
ttuple pointing to a vertex
Returns
one-ring tris number

◆ get_vertices()

std::vector< TriMesh::Tuple > TriMesh::get_vertices ( ) const

Generate a vector of Tuples from global vertex index and local edge index

Note
Each vertex generate Tuple that has the smallest fid to be among incident triangles'. Local vid to be in the same order as thier indices in the m_conn_tris. Local eid assigned counter clockwise as in the ilustrated example
Returns
vector of Tuples refering to each vertex

◆ init() [1/2]

void wmtk::TriMesh::init ( const MatrixXi &  F)

Generate the connectivity of the mesh from an IGL-style F matrix.

Parameters
Fby 3 list of vertex indices.

◆ init() [2/2]

void TriMesh::init ( size_t  n_vertices,
const std::vector< std::array< size_t, 3 > > &  tris 
)

Generate the connectivity of the mesh

Parameters
n_verticesInput number of vertices
tristriangle connectivity

◆ invariants()

virtual bool wmtk::TriMesh::invariants ( const std::vector< Tuple > &  )
inlinevirtual

User specified invariants that can't be violated.

Parameters
std::vector<Tuple>a vector of Tuples that are concerned in a given operation
Returns
true if the invairnats are not violated

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::qslim::QSlimMesh, wmtk::components::shortest_edge_collapse::ShortestEdgeCollapse, and wmtk::components::topological_offset::TopoOffsetTriMesh.

◆ is_boundary_edge()

bool TriMesh::is_boundary_edge ( const TriMesh::Tuple t) const

Does exactly one triangle share this edge?

Parameters
tTuple refering to an edge

◆ is_boundary_vertex()

bool wmtk::TriMesh::is_boundary_vertex ( const TriMesh::Tuple t) const
inline

check if the vertex that's represented by a Tuple is at the boundary of the mesh

Parameters
tTuple refering to an edge

◆ is_manifold_edge()

bool TriMesh::is_manifold_edge ( const TriMesh::Tuple t) const

Do exactly two triangles share this edge?

Note that a boundary edge is not manifold by this definition; callers that need "manifold or boundary" should test is_manifold_edge(t) || is_boundary_edge(t).

Stops counting at three, so a pole with a large fan costs no more than a normal edge. swap_edge_before() asks this of every candidate edge.

◆ oriented_tri_vertices()

std::array< wmtk::TriMesh::Tuple, 3 > TriMesh::oriented_tri_vertices ( const Tuple t) const

Get the incident vertices for a triangle.

Parameters
ttuple pointing to an face
Returns
tuples of incident vertices

◆ oriented_tri_vids()

std::array< size_t, 3 > TriMesh::oriented_tri_vids ( const Tuple t) const

Get the incident vertices for a triangle.

Parameters
ttuple pointing to an face
Returns
global vids of incident vertices

◆ release_vertex_mutex_to()

int TriMesh::release_vertex_mutex_to ( size_t  mark)

Release the mutexes taken since the release stack held mark entries.

Unwinding to a watermark rather than clearing the whole stack is what lets one lock acquisition be composed out of several, and what lets a failed acquisition leave the caller's own locks alone. release_vertex_mutex_in_stack() is this with mark = 0.

◆ remove_tris_by_ids()

void wmtk::TriMesh::remove_tris_by_ids ( const std::vector< size_t > &  fids)
inline

Mark the given triangles, and any vertex left without an incident triangle, as removed.

The 2D counterpart of TetMesh::remove_tets_by_ids, used by the output filters to drop the region outside the input. Call consolidate_mesh() afterwards to compact.

◆ set_use_link_condition()

void wmtk::TriMesh::set_use_link_condition ( bool  use_it)
inline

Should collapse_edge_before enforce the link condition?

The link condition guarantees a collapse preserves the homotopy type and keeps the mesh a simplicial complex. Turning it off allows collapses that change topology and that create non-manifold edges and vertices, which the data structure now represents; the collapse itself still merges any duplicate triangles it produces so the result stays a simplicial complex.

Defaults to true, which is the historical behaviour of every caller.

◆ smooth_after()

virtual bool wmtk::TriMesh::smooth_after ( const Tuple t)
inlinevirtual

User specified modifications and desideras after an edge smooth.

Parameters
theedge Tuple to be smoothed
Returns
true if the modifications succeed

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ smooth_before()

virtual bool wmtk::TriMesh::smooth_before ( const Tuple t)
inlinevirtual

User specified preparations and desideratas for an edge smooth.

Parameters
theedge Tuple to be smoothed
Returns
true if the preparation succeed

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ smooth_vertex()

bool TriMesh::smooth_vertex ( const Tuple t)

Smooth a vertex

Parameters
tInput Tuple for the vertex
Note
no geometry changed here
Returns
if smooth succeed

◆ split_edge()

bool TriMesh::split_edge ( const Tuple t,
std::vector< Tuple > &  new_t 
)

Split an edge

Parameters
tInput Tuple for the edge to split.
[out]new_edgesa vector of Tuples refering to the triangles incident to the new vertex introduced
Returns
if split succeed

◆ split_edge_after()

virtual bool wmtk::TriMesh::split_edge_after ( const Tuple t)
inlinevirtual

User specified modifications and desideratas after an edge split.

Parameters
theedge Tuple to be split
Returns
true if the modifications succeed

Reimplemented in wmtk::TriOptimizerMesh, wmtk::components::isotropic_remeshing::IsotropicRemeshing, and wmtk::components::topological_offset::TopoOffsetTriMesh.

◆ split_edge_before()

virtual bool wmtk::TriMesh::split_edge_before ( const Tuple t)
inlinevirtual

User specified preparations and desideratas for an edge split.

Parameters
theedge Tuple to be split
Returns
true if the preparation succeed

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ split_face()

bool TriMesh::split_face ( const Tuple t,
std::vector< Tuple > &  new_t 
)

Split a face in 3 faces.

Parameters
tInput tuple for the face to split.
[out]new_tA vector of Tuples refering to the triangles incident to the new vertex. introduced
Returns
true, if split succeed
   v2
   /|\
  / | \
 /  |  \
/f1 ^ f0\

/ / \ \ // f2 \ v0 --------— v1

◆ split_face_after()

virtual bool wmtk::TriMesh::split_face_after ( const Tuple t)
inlinevirtual

User specified modifications and desideratas after a face split.

Parameters
theface Tuple to be split
Returns
true if the modifications succeed

Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh.

◆ split_face_before()

virtual bool wmtk::TriMesh::split_face_before ( const Tuple t)
inlinevirtual

User specified preparations and desideratas for a face split.

Parameters
theface Tuple to be split
Returns
true if the preparation succeed

Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh.

◆ substructure_link_condition()

bool TriMesh::substructure_link_condition ( const Tuple e_tuple) const

Link condition that also considers substructures.

Implementation based on the pseudo code from the paper: Vivodtzev et. al. - Substructure Topology Preserving Simplification of Tetrahedral Meshes

The math and the pseudo code in the paper contain errors! The theory itself is correct.

The link condition must be evaluated for the mesh and all substructures (surfaces, lines, points). If there is a substructure simplex in the star, the simplex is extended with a dummy vertex (e.g., an edge becomes a face) and this extended simplex must also be considered for the link.

◆ swap_edge()

bool TriMesh::swap_edge ( const Tuple t,
std::vector< Tuple > &  new_t 
)

Swap an edge

Parameters
tInput Tuple for the edge to be swaped.
[out]new_edgesa vector of Tuples refering to the triangles incident to the new edge introduced
Note
swap edge a,b to edge c,d
Returns
if swap succeed

◆ swap_edge_after()

virtual bool wmtk::TriMesh::swap_edge_after ( const Tuple t)
inlinevirtual

User specified modifications and desideras after an edge swap.

Parameters
theedge Tuple to be swaped
Returns
true if the modifications succeed

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ swap_edge_before()

bool TriMesh::swap_edge_before ( const Tuple t)
virtual

User specified preparations and desideratas for an edge swap including 1.can't swap on boundary edge. 2. when swap edge between v1, v2, there can't exist edges between the two opposite vertices v3, v4.

Parameters
theedge Tuple to be swaped
Returns
true if the preparation succeed

Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ switch_component()

std::optional< TriMesh::Tuple > TriMesh::switch_component ( const TriMesh::Tuple t) const

Jump to the next edge-connected component of the fan of the Tuple's vertex.

The returned Tuple points at the same vertex but at a face that no sequence of switch_edge/switch_face can reach from t. Applying it once per component returns to the starting component. Returns nullopt when the vertex is manifold, i.e. when there is no other component to jump to.

◆ switch_face()

std::optional< Tuple > wmtk::TriMesh::switch_face ( const Tuple t) const
inline

a duplicate of Tuple::switch_face funciton

Note
Returns nullptr if current Tuple referes to a boundary triangle

◆ tri_capacity()

size_t wmtk::TriMesh::tri_capacity ( ) const
inline

get the current largest global fid

Returns
size_t

◆ try_set_face_mutex_one_ring()

bool TriMesh::try_set_face_mutex_one_ring ( const Tuple f,
int  threadid 
)

try lock the one-ring neighboring triangles' incident vertices.

Parameters
fTuple refers to the face
threadid
Returns
true if all locked successfully

◆ try_set_vertex_mutex_n_ring()

bool TriMesh::try_set_vertex_mutex_n_ring ( const Tuple v,
int  threadid,
int  n 
)

Lock every vertex within graph distance n of v, the seed included.

A true breadth-first ball, expanded only through vertices this thread holds, so every connectivity read is made under a lock. On failure it releases exactly what it took and returns false; the caller must not assume anything about the mesh afterwards.

n == 0 locks the seed alone; n == 1 the seed and its one-ring, and so on. Sizing the ball is the caller's job: an operation must claim every vertex it READS as well as every vertex it writes, which for an operation that also re-smooths a k-ring means k+1 (smoothing a vertex reads its one-ring and writes the quality of its incident faces).

Warning
This is NOT a drop-in replacement for the *_two_ring / *_one_ring helpers below, which claim a strictly smaller set. Read the note on them before "simplifying" one into the other – it has a large, measured cost.

◆ try_tuple_from_edge()

std::optional< std::tuple< TriMesh::Tuple, size_t > > TriMesh::try_tuple_from_edge ( const std::array< size_t, 2 > &  vids) const

tuple_from_edge for callers where a missing edge is an answer, not a bug.

The asserting form is right for the many callers that ask for an edge they know exists. collapse_edge_after is not one of them: it asks for an edge across the merged vertex that the collapse may have just removed, and it already has a branch for that case.

◆ tuple_from_edge() [1/2]

Tuple wmtk::TriMesh::tuple_from_edge ( size_t  fid,
size_t  local_eid 
) const
inline

Generate a edge Tuple using global fid and local eid

Parameters
fidglobale fid for the triangle
local_eidlocal eid
Returns
tuple refers to the edge

◆ tuple_from_edge() [2/2]

TriMesh::Tuple TriMesh::tuple_from_edge ( size_t  vid1,
size_t  vid2,
size_t  fid 
) const

Generate a tuple using local vid and global fid

Parameters
vid1,vid2are local vids TODO: these are global vids
fidglobale fid for the triangle
Note
tuple refers to vid1
Returns
vector of Tuples

◆ tuple_from_tri()

Tuple wmtk::TriMesh::tuple_from_tri ( size_t  fid) const
inline

Generate a face Tuple using global fid

Parameters
fidglobal fid for the triangle
Note
Use the local vid of the first vertex among the incident vertices in the connectivity of the triangle
Returns
a face Tuple

◆ tuple_from_vertex()

Tuple wmtk::TriMesh::tuple_from_vertex ( size_t  vid) const
inline

Generate avertex Tuple using local vid and global fid

Parameters
vidglobale vid for the triangle
Note
tuple refers to vid
Returns
an invalid Tuple when vid is out of range, removed, or incident to no triangle – the same contract tuple_from_tri has always had.

The guard is not decoration. Without it this read m_vertex_connectivity[vid][0] unconditionally, and VertexConnectivity::operator[] only asserts, so in Release a removed or isolated vertex indexed an EMPTY vector: nullptr[0], i.e. a segfault. for_each_vertex builds a Tuple for every slot in [0, vert_capacity()) and only then asks is_valid, so any caller that ran it on an unconsolidated mesh crashed – 22 of 30 identical runs on Thingi-2D 193539, and 12 models into a 2333-model sweep.

◆ vert_capacity()

size_t wmtk::TriMesh::vert_capacity ( ) const
inline

get the current largest global vid

Returns
size_t

◆ vertex_component_count()

size_t TriMesh::vertex_component_count ( const size_t  vid) const

Number of edge-connected components in the fan of a vertex.

1 for a manifold vertex (and for a vertex on a non-manifold edge, whose faces are still joined through that edge), more for a pinch point. 0 for an isolated vertex.

◆ vertex_fan_components()

void TriMesh::vertex_fan_components ( size_t  vid,
std::vector< size_t > &  component_of,
std::vector< size_t > &  representatives 
) const
protected

Edge-connected components of the fan of vid, as positions into that fan.

component_of[i] is the index into representatives of the component containing m_vertex_connectivity[vid].m_conn_tris[i], and representatives holds each component's smallest fid in increasing order. Two faces are in the same component when they share an edge containing vid.

Both outputs are sized by the fan rather than by the mesh, and nothing is cached: the fan is already the whole input, so recomputing costs the same as reading a stored answer would, minus the obligation to keep it current.

◆ vertex_is_on_surface()

virtual bool wmtk::TriMesh::vertex_is_on_surface ( const size_t  vid) const
inlinevirtual

Is a vertex part of the substructure.

Parameters
vidVertex ID

Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.

◆ vertex_valence()

size_t wmtk::TriMesh::vertex_valence ( const size_t  vid) const
inline

Number of triangles incident to a vertex, by id.

The same count as get_valence_for_vertex, for callers that hold a vid rather than a Tuple. Around 6 on a well-shaped mesh; worth checking before anything that walks the one ring, since a degenerate mesh can push it much higher.


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