|
Wildmeshing Toolkit
|
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< Tuple > | get_vertices () const |
| std::vector< Tuple > | get_edges () const |
| std::vector< Tuple > | get_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< Tuple > | switch_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< Tuple > | switch_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< Tuple > | get_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< Tuple > | get_one_ring_edges_for_vertex (const Tuple &t) const |
Get all edges that are incident to the vertex of Tuple t. | |
| std::vector< Tuple > | get_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 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 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 | |
| AbstractAttributeContainer * | p_vertex_attrs = nullptr |
| AbstractAttributeContainer * | p_edge_attrs = nullptr |
| AbstractAttributeContainer * | p_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< VertexConnectivity > | m_vertex_connectivity |
| vector< TriangleConnectivity > | m_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< VertexMutex > | m_vertex_mutex |
| wmtk::threading::enumerable_thread_specific< RingLockScratch > | m_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 |
| bool wmtk::TriMesh::check_link_condition | ( | const Tuple & | t | ) | const |
prerequisite for collapse
| t | Tuple referes to the edge to be collapsed |
| bool wmtk::TriMesh::check_mesh_connectivity_validity | ( | ) | const |
verify the connectivity validity of the mesh
Collapse an edge
| t | Input Tuple for the edge to be collapsed. | |
| [out] | new_edges | a vector of Tuples refering to the triangles incident to the new vertex introduced |
|
inlinevirtual |
User specified modifications and desideratas after an edge collapse.
| the | edge Tuple to be collapsed |
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.
|
inlinevirtual |
User specified preparations and desideratas for an edge collapse including the link check as collapse prerequisite.
| the | edge Tuple to be split |
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.
| 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
| 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
| void TriMesh::consolidate_mesh | ( | ) |
removing the elements that are removed
| bnd_output | when turn on will write the boundary vertices to "bdn_table.dmat" |
|
inlinevirtual |
Is an edge part of the substructure.
| vids | The vertex IDs of the edge |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
| 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).
| std::vector< TriMesh::Tuple > TriMesh::get_edges | ( | ) | const |
Generate a vector of Tuples for each edge
| std::vector< TriMesh::Tuple > TriMesh::get_faces | ( | ) | const |
Generate a vector of Tuples from global face index
|
private |
Get the next avaiblie global index for the triangle.
|
private |
Get the next avaiblie global index for the 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()
| t | tuple pointing to a vertex |
The code below is a faster implementation but it did not give the exact same result for QSLIM. Leaving it commented out for now.
| std::vector< TriMesh::Tuple > TriMesh::get_one_ring_tris_for_vertex | ( | const Tuple & | t | ) | const |
Get the one ring tris for a vertex.
| t | tuple pointing to a vertex |
| 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.
| t | tuple pointing to a vertex |
| 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
| vids | The vertex IDs of the edge |
| 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
| vid | Vertex ID |
| simplex::SimplexCollection TriMesh::get_surface_edges_for_vertex | ( | const size_t | vid | ) | const |
Get all edges on the surface that are incident to vid.
| vid | Vertex ID |
|
inline |
Count the number of the one ring tris for a vertex.
| t | tuple pointing to a vertex |
| std::vector< TriMesh::Tuple > TriMesh::get_vertices | ( | ) | const |
Generate a vector of Tuples from global vertex index and local edge index
| void wmtk::TriMesh::init | ( | const MatrixXi & | F | ) |
Generate the connectivity of the mesh from an IGL-style F matrix.
| F | by 3 list of vertex indices. |
| void TriMesh::init | ( | size_t | n_vertices, |
| const std::vector< std::array< size_t, 3 > > & | tris | ||
| ) |
Generate the connectivity of the mesh
| n_vertices | Input number of vertices |
| tris | triangle connectivity |
|
inlinevirtual |
User specified invariants that can't be violated.
| std::vector<Tuple> | a vector of Tuples that are concerned in a given operation |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::qslim::QSlimMesh, wmtk::components::shortest_edge_collapse::ShortestEdgeCollapse, and wmtk::components::topological_offset::TopoOffsetTriMesh.
| bool TriMesh::is_boundary_edge | ( | const TriMesh::Tuple & | t | ) | const |
Does exactly one triangle share this edge?
| t | Tuple refering to an edge |
|
inline |
| 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.
| std::array< wmtk::TriMesh::Tuple, 3 > TriMesh::oriented_tri_vertices | ( | const Tuple & | t | ) | const |
Get the incident vertices for a triangle.
| t | tuple pointing to an face |
| std::array< size_t, 3 > TriMesh::oriented_tri_vids | ( | const Tuple & | t | ) | const |
Get the incident vertices for a triangle.
| t | tuple pointing to an face |
| 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.
|
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.
|
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.
|
inlinevirtual |
User specified modifications and desideras after an edge smooth.
| the | edge Tuple to be smoothed |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
|
inlinevirtual |
User specified preparations and desideratas for an edge smooth.
| the | edge Tuple to be smoothed |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
| bool TriMesh::smooth_vertex | ( | const Tuple & | t | ) |
Smooth a vertex
| t | Input Tuple for the vertex |
Split an edge
| t | Input Tuple for the edge to split. | |
| [out] | new_edges | a vector of Tuples refering to the triangles incident to the new vertex introduced |
|
inlinevirtual |
User specified modifications and desideratas after an edge split.
| the | edge Tuple to be split |
Reimplemented in wmtk::TriOptimizerMesh, wmtk::components::isotropic_remeshing::IsotropicRemeshing, and wmtk::components::topological_offset::TopoOffsetTriMesh.
|
inlinevirtual |
User specified preparations and desideratas for an edge split.
| the | edge Tuple to be split |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
Split a face in 3 faces.
| t | Input tuple for the face to split. | |
| [out] | new_t | A vector of Tuples refering to the triangles incident to the new vertex. introduced |
v2 /|\ / | \ / | \ /f1 ^ f0\
/ / \ \ // f2 \ v0 --------— v1
|
inlinevirtual |
User specified modifications and desideratas after a face split.
| the | face Tuple to be split |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh.
|
inlinevirtual |
User specified preparations and desideratas for a face split.
| the | face Tuple to be split |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh.
| 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 an edge
| t | Input Tuple for the edge to be swaped. | |
| [out] | new_edges | a vector of Tuples refering to the triangles incident to the new edge introduced |
|
inlinevirtual |
User specified modifications and desideras after an edge swap.
| the | edge Tuple to be swaped |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
|
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.
| the | edge Tuple to be swaped |
Reimplemented in wmtk::components::isotropic_remeshing::IsotropicRemeshing, wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
| 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.
a duplicate of Tuple::switch_face funciton
|
inline |
get the current largest global fid
| bool TriMesh::try_set_face_mutex_one_ring | ( | const Tuple & | f, |
| int | threadid | ||
| ) |
try lock the one-ring neighboring triangles' incident vertices.
| f | Tuple refers to the face |
| threadid |
| 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).
| 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.
|
inline |
Generate a edge Tuple using global fid and local eid
| fid | globale fid for the triangle |
| local_eid | local eid |
| 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
| vid1,vid2 | are local vids TODO: these are global vids |
| fid | globale fid for the triangle |
|
inline |
|
inline |
Generate avertex Tuple using local vid and global fid
| vid | globale vid for the triangle |
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.
|
inline |
get the current largest global vid
| 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.
|
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.
|
inlinevirtual |
Is a vertex part of the substructure.
| vid | Vertex ID |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTriMesh, and wmtk::TriOptimizerMesh.
|
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.