|
Wildmeshing Toolkit
|
Classes | |
| struct | RingLockScratch |
| Per-thread buffers for the n-ring lock, so a lock acquisition allocates nothing. More... | |
| struct | SlotUsage |
| class | SmartTuple |
| class | TetrahedronConnectivity |
| class | Tuple |
| a Tuple refers to a global vid and a global tet id, and a local edge id and local face id More... | |
| class | VertexConnectivity |
| struct | VertexFace |
| A face at a vertex: its corners sorted, its face id (Tuple::fid) and its tets, sorted. More... | |
| struct | VolumeRecording |
Public Types | |
| enum class | OpKind : int { split , collapse , swap_32 , swap_44 , swap_56 , swap_face , COUNT } |
| enum class | OpEvent : int { attempt , before_hook , link_condition , no_return_tet , duplicate_tet , topology , valence , boundary , exists , no_case_allowed , no_better_case , out_of_slots , after_hook , invariants , committed , screened , COUNT } |
| template<typename T > | |
| using | vector = std::vector< T > |
| using | VertexMutex = wmtk::threading::VertexMutex |
Public Member Functions | |
| size_t | vert_capacity () const |
| get the current largest global vid | |
| size_t | tet_capacity () const |
| get the current largest global tid | |
| size_t | vertex_size () const |
| get the number of unremoved verticies | |
| size_t | tet_size () const |
| get the number of unremoved tets | |
| void | init (size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets) |
| void | init_with_isolated_vertices (size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets) |
| void | init (const MatrixXi &T) |
| Generate the connectivity of the mesh from an IGL-style T matrix. | |
| bool | split_edge (const Tuple &t, std::vector< Tuple > &new_tets) |
| virtual bool | collapse_edge (const Tuple &t, std::vector< Tuple > &new_tets) |
| bool | link_condition (const Tuple &t) |
| bool | collapse_edge_conn (const Tuple &loc0, size_t &v1_id, Tuple &new_loc, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids_copy, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets) |
| bool | collapse_edge_check_topology (const std::vector< size_t > &new_tet_id) |
| Check topology after collapse connectivity change. This is a sanity check and should not be necessary. | |
| void | collapse_edge_rollback (size_t &v1_id, std::map< size_t, wmtk::TetMesh::VertexConnectivity > &rollback_vert_conn, std::vector< size_t > &n1_t_ids, std::vector< size_t > &new_tet_id, std::vector< TetrahedronConnectivity > &old_tets) |
| bool | swap_edge_56 (const Tuple &t, std::vector< Tuple > &new_tets) |
| bool | swap_edge_44 (const Tuple &t, std::vector< Tuple > &new_tets) |
| bool | swap_edge (const Tuple &t, std::vector< Tuple > &new_tets) |
| 3-2 edge swap | |
| bool | swap_face (const Tuple &t, std::vector< Tuple > &new_tets) |
| 2-3 face swap | |
| bool | smooth_vertex (const Tuple &t) |
| bool | split_tet (const Tuple &t, std::vector< Tuple > &new_tets) |
| Split a tet in 4 tets. | |
| bool | split_face (const Tuple &t, std::vector< Tuple > &new_tets) |
| Split a face in 3 faces. | |
| void | triangle_insertion (const std::vector< Tuple > &intersected_tets, const std::vector< Tuple > &intersected_edges, std::vector< size_t > &new_edge_vids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > ¢er_split_tets) |
| Insert a triangle into a tetmesh, with known intersection information. | |
| bool | insert_point (const Tuple &t, std::vector< Tuple > &new_tets) |
| Insert a point into a tetmesh inside a tet. In general position, this split a tet into 4. In face position, split two tets. In edge position, In point position, do nothing. It has no surface history hooks, and throws while a surface history is recording. | |
| virtual bool | insert_point_before (const Tuple &t) |
| virtual bool | insert_point_after (std::vector< Tuple > &new_tets) |
| void | consolidate_mesh () |
| cleans up the deleted vertices or tetrahedra, fixes the corresponding indices, and reset the version number. WARNING: it invalidates all tuples! | |
| std::shared_ptr< history::TrackedSurfaceRecorder > | start_surface_history (std::function< Eigen::Vector3d(size_t)> position) |
| Record every change to the tracked surface from now on (see wmtk/history/TrackedRecorder.hpp). | |
| void | stop_surface_history () |
| Stop recording. The recorder keeps what it has. | |
| size_t | resync_surface_history () |
| std::shared_ptr< history::VolumeRecorder > | start_volume_history (std::function< Eigen::Vector3d(size_t)> position) |
Record, alongside the surface history, the tets around every operation that changes the tracked surface (wmtk/history/VolumeHistory.hpp): what a map of the volume needs. The surface history must be recording; a volume history is its own choice, since it takes far more room. position(v) is called as start_surface_history()'s is; a tet's region is its tet_tags(). | |
| void | stop_volume_history () |
| Stop recording the volume. The recorder keeps what it has. | |
| virtual std::vector< int64_t > | tet_tags (size_t tid) const |
| std::vector< std::array< size_t, 3 > > | tracked_faces () const |
| Every tracked face, oriented by orient_tracked_face(). | |
| virtual bool | is_tracked_face (size_t tid, int j) const |
| virtual std::vector< std::array< size_t, 2 > > | tracked_feature_edges () const |
| virtual std::array< size_t, 3 > | orient_tracked_face (const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const |
| std::array< size_t, 3 > | orient_tracked_face (const std::array< size_t, 3 > &f) const |
| orient_tracked_face, finding the face's tets. | |
| std::array< size_t, 3 > | face_out_of (size_t tid, const std::array< size_t, 3 > &face) const |
The corners of face, a face of tet tid, ordered so that its normal points out of the tet – for a tet the right way round as TetOptimizerMesh has them, with its fourth vertex on the side of the first three's normal (orient3d negative). | |
| std::vector< size_t > | tets_of_face (const std::array< size_t, 3 > &f) const |
The tets with the face f, sorted: one on the boundary, two inside. | |
| std::vector< Tuple > | get_edges () const |
| std::vector< Tuple > | get_faces () const |
| std::vector< Tuple > | get_vertices () const |
| std::vector< Tuple > | get_tets () const |
| virtual void | for_each_face (const std::function< void(const TetMesh::Tuple &)> &) |
| looping through all the unique edges and perform the given function | |
| 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 (and are retried later after a consolidate). Tune per application (e.g. from JSON); values < 1 are clamped to 1. | |
| double | preallocation_factor () const |
| bool | slots_exhausted () const |
| void | clear_slots_exhausted () |
| size_t | request_tet_slots (size_t n) |
| size_t | request_vert_slots (size_t n) |
| void | ensure_free_tet_capacity (size_t extra) |
| void | ensure_free_vert_capacity (size_t extra) |
| virtual bool | invariants (const std::vector< Tuple > &) |
| virtual void | op_event (OpKind, OpEvent) const |
| bool | op_refused (const OpKind k, const OpEvent e) const |
op_event() for a refusal, returning false so a site reads return op_refused(...). | |
| bool | op_screened (const OpKind k) const |
| The end of a dry run that would have gone on to change the mesh: true, and counted. | |
| Tuple | tuple_from_edge (size_t tid, int local_eid) const |
| get a Tuple from global tetra index and local edge index (from 0-5). | |
| Tuple | tuple_from_edge (const std::array< size_t, 2 > &vids) const |
| get a Tuple from global vids of the 2 end of an edge | |
| Tuple | tuple_from_face (size_t tid, int local_fid) const |
| get a Tuple from global tetra index and local face index (from 0-3). | |
| std::tuple< Tuple, size_t > | tuple_from_face (const std::array< size_t, 3 > &vids) const |
| get a Tuple and the global face index from global vertex index of the face. | |
| std::optional< std::tuple< Tuple, size_t > > | try_tuple_from_face (const std::array< size_t, 3 > &vids) const |
| tuple_from_face for callers where a missing face is an answer, not a bug. | |
| size_t | lowest_common_tet (size_t v0_id, size_t v1_id, size_t v2_id) const |
| Lowest tet id incident to all three vertices, or size_t(-1) if there is none. | |
| size_t | vertex_valence (const size_t vid) const |
| Number of tets incident to a vertex, in O(1). | |
| std::tuple< Tuple, size_t > | tuple_from_face (const simplex::Face &f) const |
| Tuple | tuple_from_vertex (size_t vid) const |
| get a Tuple from global vertex index | |
| Tuple | tuple_from_tet (size_t tid) const |
| get a Tuple from global tetra index | |
| Tuple | tuple_from_vids (size_t vid0, size_t vid1, size_t vid2, size_t vid3) const |
| Get a Tuple from global vertex IDs. | |
| simplex::Tet | simplex_from_tet (const Tuple &t) const |
| simplex::Tet | simplex_from_tet (const size_t tid) const |
| simplex::Face | simplex_from_face (const Tuple &t) const |
| simplex::Edge | simplex_from_edge (const Tuple &t) const |
| Tuple | switch_vertex (const Tuple &t) const |
| wrapper function from Tuple::switch_vertex | |
| Tuple | switch_edge (const Tuple &t) const |
| wrapper function from Tuple::switch_edge | |
| Tuple | switch_face (const Tuple &t) const |
| wrapper function from Tuple::switch_face | |
| std::optional< Tuple > | switch_tetrahedron (const Tuple &t) const |
| wrapper function from Tuple::switch_tetrahedron | |
| std::vector< Tuple > | get_one_ring_tets_for_vertex (const Tuple &t) const |
| Get the one ring tets for a vertex. | |
| const std::vector< size_t > & | get_one_ring_tids_for_vertex (const Tuple &t) const |
| Get the one ring tids for vertex. | |
| const std::vector< size_t > & | get_one_ring_tids_for_vertex (const size_t vid) const |
| std::vector< Tuple > | get_one_ring_vertices_for_vertex (const Tuple &t) const |
| Get the one ring vertices for a vertex. | |
| std::vector< size_t > | get_one_ring_vids_for_vertex (size_t vid, std::vector< size_t > &cache) |
| Get the one ring vids for vertex. | |
| std::vector< size_t > | get_one_ring_vids_for_vertex (size_t vid) const |
| Get the one ring vids for vertex. | |
| std::vector< size_t > | get_one_ring_vids_for_vertex_adj (size_t vid) const |
| Duplicate of the function TetMesh::get_one_ring_vids_for_vertex. | |
| std::vector< size_t > | get_one_ring_vids_for_vertex_adj (size_t vid, std::vector< size_t > &cache) |
| Duplicate of the function TetMesh::get_one_ring_vids_for_vertex. | |
| std::vector< Tuple > | get_incident_tets_for_edge (const Tuple &t) const |
| Get the incident tets for edge. | |
| std::vector< Tuple > | get_incident_tets_for_edge (const size_t vid0, const size_t vid1) const |
| std::vector< size_t > | get_incident_tids_for_edge (const Tuple &t) const |
| std::vector< size_t > | get_incident_tids_for_edge (const size_t vid0, const size_t vid1) const |
| std::vector< Tuple > | get_one_ring_tets_for_edge (const Tuple &t) const |
| Get the one ring tets for edge. | |
| std::vector< std::array< size_t, 3 > > | vertex_adjacent_boundary_faces (const Tuple &t) const |
| std::array< Tuple, 4 > | oriented_tet_vertices (const Tuple &t) const |
| std::array< size_t, 4 > | oriented_tet_vids (const Tuple &t) const |
| std::array< size_t, 4 > | oriented_tet_vids (const size_t tid) const |
| std::array< Tuple, 3 > | get_face_vertices (const Tuple &t) const |
| Get the 3 vertices of a face represented by Tuple. | |
| std::array< size_t, 3 > | get_face_vids (const Tuple &t) const |
| std::array< Tuple, 6 > | tet_edges (const Tuple &t) const |
| get the 6 edges of a tet represented by Tuples | |
| void | check_tuple_validity (const Tuple &t) const |
| bool | check_mesh_connectivity_validity () const |
| checks the validity of the connectivity of the mesh. Including the validity of each Tuple | |
| void | remove_tets_by_ids (const std::vector< size_t > &tids) |
| remove the tetrahedrons in the mesh that have given tet ids | |
| void | start_protect_attributes () |
| void | release_protect_attributes () |
| void | rollback_protected_attributes () |
| 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_n_ring (size_t v1, size_t v2, size_t v3, int threadid, int n) |
| try_set_vertex_mutex_n_ring seeded from the three vertices of a face. | |
| void | for_each_edge (const std::function< void(const TetMesh::Tuple &)> &) |
| perform the given function for each edge | |
| void | for_each_vertex (const std::function< void(const TetMesh::Tuple &)> &) |
| perform the given function for each vertex | |
| void | for_each_tetra (const std::function< void(const TetMesh::Tuple &)> &) |
| perform the given function for each tet | |
| virtual bool | vertex_is_on_surface (const size_t vid) const |
| Is a vertex part of the substructure. | |
| virtual bool | face_is_on_surface (const size_t fid) const |
| Is a face part of the substructure. | |
| simplex::SimplexCollection | get_surface_faces_for_vertex (const size_t vid) const |
| Get all faces on the surface that are incident to vid. | |
| simplex::SimplexCollection | get_surface_faces_for_edge (const std::array< size_t, 2 > &vids) const |
| Get all faces on the surface that are incident to the edge. | |
| size_t | get_num_surface_faces_for_edge (const std::array< size_t, 2 > &vids) const |
| Get the number of surface faces incident to the edge. | |
| size_t | compute_vertex_order (const size_t vid) const |
| Compute the vertex order for a single vertex. | |
| virtual size_t | get_order_of_vertex (const size_t vid) const |
| Get the order of a vertex. | |
| size_t | get_order_of_edge (const std::array< size_t, 2 > &vids) const |
| Compute the order of an edge. | |
| virtual size_t | substructure_order_of_edge (const std::array< size_t, 2 > &vids) const |
| The orders substructure_link_condition consults, overridable so an application can widen the 1D substructure beyond what the surface complex derives. | |
| virtual size_t | substructure_order_of_vertex (const size_t vid) const |
| virtual void | substructure_feature_neighbors (size_t, std::vector< size_t > &) const |
One-ring vertices x of vid where (vid, x) is 1D substructure NOT derivable from the surface complex (feature edges through the interior, for instance). The link condition's order-2 edge collection walks surface faces and would never see them. | |
| bool | substructure_link_condition (const Tuple &e_tuple) const |
| Link condition that also considers substructures. | |
Storage capacity | |
True if any slot request has been refused since the last clear. The pass boundary uses this to decide whether to consolidate: a refusal means an operation was abandoned for want of storage, and consolidating reclaims the slots that removed elements still hold (the counter only ever advances during a pass) and re-derives the capacity from the real element count. How many slots the storage holds, as opposed to tet_capacity()/vert_capacity(), which report the LIVE count – the end of the handed-out region. Exhaustion is | |
| size_t | tet_storage_capacity () const |
| size_t | vert_storage_capacity () const |
Ring lockers – NOT balls | |
The helpers below are the ones every pass actually uses, and none of the two-ring ones 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), against -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 do 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, as the 2D 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_vertex_mutex_two_ring_vid (const Tuple &v, int threadid) |
| try_set_vertex_mutex_two_ring reached through vids rather than Tuples. | |
| bool | try_set_vertex_mutex_two_ring_vid (size_t v, int threadid) |
| try_set_vertex_mutex_two_ring reached through vids rather than Tuples. | |
| bool | try_set_edge_mutex_two_ring (const Tuple &e, int threadid=0) |
| Lock the edge's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_face_mutex_two_ring (const Tuple &f, int threadid=0) |
| Lock the face's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_face_mutex_two_ring (const Tuple &v1, const Tuple &v2, const Tuple &v3, int threadid=0) |
| Lock the face's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_face_mutex_two_ring (size_t v1, size_t v2, size_t v3, int threadid=0) |
| Lock the face's one-ring and, partially, its two-ring. See the note above. | |
| bool | try_set_vertex_mutex_one_ring (const Tuple &v, int threadid=0) |
| Lock v and its one-ring. Complete, unlike the two-ring family. | |
Static Public Member Functions | |
| static bool | dry_run () |
| Whether operations on this thread are dry runs (see wmtk/OperationDryRun.hpp). | |
Public Attributes | |
| bool | m_check_smoothing_stays_in_star = false |
| While true, smooth_vertex() checks that the smooth recorded nothing outside the vertex's star – the vertex itself and the edges, faces and cells incident to it – and throws if it did. | |
| AbstractAttributeContainer * | p_vertex_attrs = nullptr |
| AbstractAttributeContainer * | p_edge_attrs = nullptr |
| AbstractAttributeContainer * | p_face_attrs = nullptr |
| AbstractAttributeContainer * | p_tet_attrs = nullptr |
| bool | m_collapse_check_link_condition = true |
| bool | m_collapse_check_topology = false |
| bool | m_collapse_check_manifold = true |
| wmtk::threading::enumerable_thread_specific< std::vector< size_t > > | mutex_release_stack |
| wmtk::threading::enumerable_thread_specific< std::vector< size_t > > | get_one_ring_cache |
| int | NUM_THREADS = 0 |
Protected Member Functions | |
| std::vector< std::array< size_t, 3 > > | tracked_faces_around (const std::vector< size_t > &vs, bool all) const |
| std::vector< VertexFace > | faces_at_vertex (size_t v) const |
| The faces with v as a corner, found from v's tets alone. | |
| size_t | face_id_in (const std::array< size_t, 3 > &f, size_t tid) const |
| The face id (Tuple::fid) of f, a face of tet tid, its lowest; from tid alone. | |
| virtual bool | checks_tracked_surface () const |
| Checks an application makes on what an operation does to the tracked surface. | |
| virtual void | tracked_surface_before (const std::vector< size_t > &vs, bool all) |
| virtual bool | tracked_surface_after (const std::vector< size_t > &vs, bool all) |
| virtual void | on_slot_storage_grown () |
| virtual bool | triangle_insertion_before (const std::vector< Tuple > &faces) |
| virtual bool | triangle_insertion_after (const std::vector< std::vector< Tuple > > &) |
| virtual bool | split_edge_before (const Tuple &t) |
| User specified preparations and desideratas for an edge split before changing the connectivity. | |
| virtual bool | split_edge_after (const Tuple &t) |
| This function computes the attributes for the added simplices. User specified modifications and desideratas for after an edge split. | |
| virtual bool | collapse_edge_before (const Tuple &t) |
| User specified preparations and desideratas for an edge collapse before changing the connectivity. | |
| virtual bool | collapse_edge_after (const Tuple &t) |
| User specified modifications and desideratas for after an edge collapse. | |
| virtual bool | swap_edge_44_before (const Tuple &t) |
| User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity. | |
| virtual double | swap_edge_44_energy (const std::vector< std::array< size_t, 4 > > &tets, const int op_case) |
| User specified energy to decide which of the 4 possible orientations should be chosen. | |
| virtual bool | swap_edge_44_after (const Tuple &t) |
| User specified modifications and desideratas for after a 4-4 edge swap. | |
| virtual bool | swap_edge_44_accept_case (const std::array< size_t, 2 > &new_edge) |
| Filter which of the 4-4 orientations may be chosen. | |
| virtual bool | swap_edge_56_before (const Tuple &t) |
| User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity. | |
| virtual double | swap_edge_56_energy (const std::vector< std::array< size_t, 4 > > &tets, const int op_case) |
| User specified energy to decide which of the 5 possible orientations should be chosen. | |
| virtual bool | swap_edge_56_after (const Tuple &t) |
| User specified modifications and desideratas for after a 5-6 edge swap. | |
| virtual bool | swap_edge_56_accept_case (const std::array< size_t, 3 > &new_face) |
| Filter which of the 5-6 orientations may be chosen. | |
| virtual bool | swap_edge_before (const Tuple &t) |
| User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity. | |
| virtual bool | swap_edge_after (const Tuple &t) |
| User specified modifications and desideratas for after a 3-2 edge swap. | |
| virtual bool | swap_face_before (const Tuple &t) |
| User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry. | |
| virtual bool | swap_face_after (const Tuple &t) |
| User specified modifications and desideratas for after a 2-3 face swap. | |
| virtual bool | smooth_before (const Tuple &t) |
| User specified preparations and desideratas for smoothing a vertex. | |
| virtual bool | smooth_after (const Tuple &t) |
| User specified modifications and desideratas for after smoothing a vertex. | |
| virtual bool | split_face_before (const Tuple &t) |
| User specified preparations and desideratas for a face split before changing the connectivity. | |
| virtual bool | split_face_after (const Tuple &t) |
| Compute the attributes for the added simplices. | |
| virtual bool | split_tet_before (const Tuple &t) |
| User specified preparations and desideratas for a tet split before changing the connectivity. | |
| virtual bool | split_tet_after (const Tuple &t) |
| Compute the attributes for the added simplices. | |
| void | resize_vertex_mutex (size_t v) |
Static Protected Attributes | |
| static constexpr std::array< std::array< int, 2 >, 6 > | m_local_edges |
| local edges within a tet | |
Private Member Functions | |
| size_t | reserved_capacity (size_t live_count) const |
| size_t | get_next_empty_slot_t () |
| size_t | get_next_empty_slot_v () |
| void | subdivide_tets (const std::vector< size_t > t_ids, const std::vector< bool > &mark_surface, const std::map< std::array< size_t, 2 >, size_t > &map_edge2vid, std::map< std::array< size_t, 3 >, std::vector< std::array< size_t, 5 > > > &new_face_vids, const std::vector< size_t > &new_vids, std::vector< size_t > &new_tids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > ¢er_split_tets) |
| void | subdivide_a_tet (size_t t_id, const std::array< int, 6 > &new_v_ids, bool mark_surface, std::map< std::array< size_t, 3 >, std::vector< std::array< size_t, 5 > > > &new_face_vids, std::vector< size_t > &new_tids, std::vector< size_t > &new_center_vids, std::vector< std::array< size_t, 4 > > ¢er_split_tets) |
| std::map< size_t, VertexConnectivity > | operation_update_connectivity_impl (std::vector< size_t > &affected_tid, const std::vector< std::array< size_t, 4 > > &new_tet_conn, bool &ok) |
| void | operation_failure_rollback_imp (std::map< size_t, VertexConnectivity > &rollback_vert_conn, const std::vector< size_t > &affected, const std::vector< size_t > &new_tet_id, const std::vector< TetrahedronConnectivity > &old_tets) |
| std::map< size_t, VertexConnectivity > | operation_update_connectivity_impl (const std::vector< size_t > &remove_id, const std::vector< std::array< size_t, 4 > > &new_tet_conn, std::vector< size_t > &allocate_id, bool &ok) |
| 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) |
| void | surface_history_before (const std::vector< size_t > &vs, bool all) |
| std::array< size_t, 2 > | surface_history_commit (history::EditKind kind, std::vector< size_t > v, const std::vector< size_t > &vs_after, bool all) |
| history::VolumeCapture | volume_capture (const std::vector< size_t > &vs) const |
The tets at the vertices vs, with what a volume history keeps of them. | |
| void | volume_history_before (const std::vector< size_t > &vs) |
| void | volume_history_commit (history::VolumeOp op, std::array< size_t, 2 > surface_edits, const std::vector< size_t > &op_vertices, const std::vector< size_t > &vs_after) |
| std::vector< size_t > | vertices_of_tets (const std::vector< size_t > &tids) const |
The vertices of the tets tids, sorted. | |
| 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. | |
| void | check_smoothing_stayed_in_star (size_t vid) |
| See m_check_smoothing_stays_in_star; throws, after dropping the record, if the check fails. | |
Static Private Member Functions | |
| static std::vector< TetrahedronConnectivity > | record_old_tet_connectivity (const SlotPool< TetrahedronConnectivity > &conn, const std::vector< size_t > &tets) |
Private Attributes | |
| SlotPool< VertexConnectivity > | m_vertex_connectivity |
| SlotPool< TetrahedronConnectivity > | m_tet_connectivity |
| double | m_preallocation_factor = 6.0 |
| int | m_t_empty_slot = 0 |
| int | m_v_empty_slot = 0 |
| std::vector< VertexMutex > | m_vertex_mutex |
| wmtk::threading::enumerable_thread_specific< RingLockScratch > | m_ring_lock_scratch |
| std::shared_ptr< history::TrackedSurfaceRecorder > | m_surface_history |
| wmtk::threading::enumerable_thread_specific< std::vector< std::array< size_t, 3 > > > | m_surface_history_before |
| The tracked faces around the operation this thread is in, as they were before it. | |
| std::shared_ptr< VolumeRecording > | m_volume_history |
Static Private Attributes | |
| static constexpr std::array< int, 4 > | m_map_vertex2edge = {{0, 0, 1, 3}} |
| static constexpr std::array< int, 4 > | m_map_vertex2oppo_face = {{3, 1, 2, 0}} |
| static constexpr std::array< int, 6 > | m_map_edge2face = {{0, 0, 0, 1, 2, 1}} |
| static constexpr std::array< std::array< int, 3 >, 4 > | m_local_faces |
| static constexpr std::array< std::array< int, 3 >, 4 > | m_local_edges_in_a_face |
Dimension-generic cell accessors | |
A "cell" is the top-dimensional element: a tet here, a triangle in TriMesh. 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 = 6 |
| static constexpr int | FACES_PER_CELL = 4 |
| size_t | cell_capacity () const |
| size_t | cell_storage_capacity () const |
| Tuple | tuple_from_cell (size_t cid) const |
Growing the storage at serial points | |
The storage cannot grow while operations run in parallel – growing reallocates it out from under concurrent readers – which is why it is preallocated. A serial pass has no concurrent readers, and between two of its operations nothing holds a reference into the storage either: so it can grow there, and only there, with no synchronisation at all. The scheduler does exactly that: before each operation of a serial pass it reserves cell_slot_bound() cells and one vertex. Every local operation creates its cells inside the stars of the vertices of its tuple's cell and adds at most one vertex, so the reservation covers whatever the operation requests, and a serial pass never refuses an operation for want of slots. The ids handed out are unchanged – the same counter, in the same order – so the result is the one an unbounded preallocation would give. With that in place a serial mesh only needs a small slack at init/consolidate, instead of the preallocation factor (see storage_grows_on_demand()). | |
| size_t | cell_slot_bound (const Tuple &t) const |
| void | reserve_free_slots (size_t cells, size_t verts) |
| virtual bool | storage_grows_on_demand () const |
| static SlotUsage | slot_usage_of_this_thread () |
| size_t wmtk::TetMesh::cell_slot_bound | ( | const Tuple & | t | ) | const |
Upper bound on the fresh cell slots one local operation on t can take: the sum of the star sizes of the vertices of t's cell. t must be valid.
| bool wmtk::TetMesh::check_mesh_connectivity_validity | ( | ) | const |
checks the validity of the connectivity of the mesh. Including the validity of each Tuple
|
inline |
wrapper function for Tuple::check_validity
|
inlineprotectedvirtual |
Checks an application makes on what an operation does to the tracked surface.
When checks_tracked_surface() says so, every operation that can change the tracked surface – a collapse, a swap, a smoothing – calls tracked_surface_before() once its before-hook and screening have passed, with the vertices around which the tracked faces may change (faces with a corner among them, or with all three when all), and then tracked_surface_after(), with those after it, once its after-hook and invariants have passed; false there refuses it, as a failed after-hook does. Both run while the operation holds its locks. A split moves nothing and is not checked.
Reimplemented in wmtk::TetOptimizerMesh.
Collapse an edge
| t | Input Tuple for the edge to collapse. | |
| [out] | new_tets | a vector of Tuples for all the newly introduced tetra. |
|
inlineprotectedvirtual |
User specified modifications and desideratas for after an edge collapse.
| t | edge Tuple that's collapsed |
Reimplemented in wmtk::components::c1_simplification::MMTetMesh, wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for an edge collapse before changing the connectivity.
| t | edge Tuple to be collapsed |
Reimplemented in wmtk::components::c1_simplification::MMTetMesh, wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
| bool wmtk::TetMesh::collapse_edge_check_topology | ( | const std::vector< size_t > & | new_tet_id | ) |
Check topology after collapse connectivity change. This is a sanity check and should not be necessary.
| new_tet_id | new tet ids added to v2 |
| bool wmtk::TetMesh::collapse_edge_conn | ( | const Tuple & | loc0, |
| size_t & | v1_id, | ||
| Tuple & | new_loc, | ||
| std::map< size_t, wmtk::TetMesh::VertexConnectivity > & | rollback_vert_conn, | ||
| std::vector< size_t > & | n1_t_ids_copy, | ||
| std::vector< size_t > & | new_tet_id, | ||
| std::vector< TetrahedronConnectivity > & | old_tets | ||
| ) |
Collapse edge connectivity change part. Constains a link condition check and the connecticity update
| loc0 | Input Tuple for the edge to collapse | |
| [out] | new_tets | a vector of Tuples for all the newly introduced tetra. |
| [out] | v1_id | vertex id of the input tuple |
| [out] | new_loc | result vertex tuple |
| [out] | rollback_vert_conn | vertex connectivity got changed and will be involed in rollback |
| [out] | n1_t_ids_copy | origninal (before collape) one ring tet ids connected to the input vertex |
| [out] | new_tet_id | new tet ids added to v2 |
| [out] | old_tets | tets tv connectivities in n1_t_ids_copy |
backup of everything
| void wmtk::TetMesh::collapse_edge_rollback | ( | size_t & | v1_id, |
| std::map< size_t, wmtk::TetMesh::VertexConnectivity > & | rollback_vert_conn, | ||
| std::vector< size_t > & | n1_t_ids, | ||
| std::vector< size_t > & | new_tet_id, | ||
| std::vector< TetrahedronConnectivity > & | old_tets | ||
| ) |
rollback function for collapse edges
| [out] | v1_id | vertex id of the input tuple |
| [out] | rollback_vert_conn | vertex connectivity got changed and will be involed in rollback |
| [out] | n1_t_ids | origninal (before collape) one ring tet ids connected to the input vertex |
| [out] | new_tet_id | new tet ids added to v2 |
| [out] | old_tets | tets tv connectivities in n1_t_ids |
| size_t wmtk::TetMesh::compute_vertex_order | ( | const size_t | vid | ) | const |
Compute the vertex order for a single vertex.
This is expensive. It is recommended to store the vertex order as vertex attribute and only compute it once.
| vid | Vertex ID |
The vertex is either on a boundary or on a non-manifold edge and has two edges incident that are of the same type.
The vertex is either at the end of a non-manifold edge or the number of incident faces is different for the incident edges. In both cases, the vertex must be order 3.
Check if vertex is non-manifold: All faces must be reachable by iterating through edges, starting from one face.
|
inlinevirtual |
Is a face part of the substructure.
| fid | Face ID |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
protected |
The faces with v as a corner, found from v's tets alone.
Those are all the tets of each face, so nothing is read of the other corners. An operation that holds v but not them must not read their tets: a thread changing those need not hold v. tuple_from_face, Tuple::fid and tets_of_face read all three corners'.
|
virtual |
looping through all the unique edges and perform the given function
looping through all the unique faces and perform the given function
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_edges | ( | ) | const |
Get all unique undirected edges in the mesh.
| std::array< TetMesh::Tuple, 3 > wmtk::TetMesh::get_face_vertices | ( | const Tuple & | t | ) | const |
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_faces | ( | ) | const |
Get all unique faces in the mesh.
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_incident_tets_for_edge | ( | const Tuple & | t | ) | const |
Get the incident tets for edge.
| t | tuple pointing to an edge |
| size_t wmtk::TetMesh::get_num_surface_faces_for_edge | ( | const std::array< size_t, 2 > & | vids | ) | const |
Get the number of surface faces incident to the edge.
| vids | The vertex IDs of the edge |
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_one_ring_tets_for_edge | ( | const Tuple & | t | ) | const |
Get the one ring tets for edge.
| t | tuple pointing to an edge |
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_one_ring_tets_for_vertex | ( | const Tuple & | t | ) | const |
Get the one ring tets for a vertex.
| t | tuple pointing to a vertex |
| const std::vector< size_t > & wmtk::TetMesh::get_one_ring_tids_for_vertex | ( | const Tuple & | t | ) | const |
Get the one ring tids for vertex.
| t | a Tuple that refers to a vertex |
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_one_ring_vertices_for_vertex | ( | const Tuple & | t | ) | const |
Get the one ring vertices for a vertex.
| t | tuple pointing to a vertex |
| std::vector< size_t > wmtk::TetMesh::get_one_ring_vids_for_vertex | ( | size_t | vid | ) | const |
Get the one ring vids for vertex.
| vid | size_t type vertex id |
| std::vector< size_t > wmtk::TetMesh::get_one_ring_vids_for_vertex | ( | size_t | vid, |
| std::vector< size_t > & | cache | ||
| ) |
Get the one ring vids for vertex.
| vid | size_t type vertex id |
| [output] | cache stores a verctor of vids with duplicate |
| size_t wmtk::TetMesh::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 TetMesh is as follows: 0: the edge is not on the surface 1: the edge is on the surface 2: the edge is on the surface boundary or non-manifold
| vids | The vertex IDs of the edge |
|
inlinevirtual |
Get the order of a vertex.
The order of a vertex in a TetMesh is as follows: 0: vertex is not on the surface 1: vertex is on the surface 2: vertex is on the surface boundary or a non-manifold edge 3: vertex is at the boundary of a non-manifold edge or a non-manifold vertex
Computing the vertex order is expensive. It is recommended to store the vertex order as a vertex attribute and override this method.
| vid | Vertex ID |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
| simplex::SimplexCollection wmtk::TetMesh::get_surface_faces_for_edge | ( | const std::array< size_t, 2 > & | vids | ) | const |
Get all faces on the surface that are incident to the edge.
| vids | The vertex IDs of the edge |
| simplex::SimplexCollection wmtk::TetMesh::get_surface_faces_for_vertex | ( | const size_t | vid | ) | const |
Get all faces on the surface that are incident to vid.
| vid | Vertex ID |
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_tets | ( | ) | const |
Get all unique tet in the mesh.
| std::vector< TetMesh::Tuple > wmtk::TetMesh::get_vertices | ( | ) | const |
Get all unique vertices in the mesh.
| void wmtk::TetMesh::init | ( | const MatrixXi & | T | ) |
Generate the connectivity of the mesh from an IGL-style T matrix.
| T | by 4 list of vertex indices. |
| void wmtk::TetMesh::init | ( | size_t | n_vertices, |
| const std::vector< std::array< size_t, 4 > > & | tets | ||
| ) |
Initialize TetMesh data structure
| n_vertices | number of vertices |
| tets | vector of array. Each element represents one tet, which is defined by four vertices. |
tets should not exceed n_vertices Insert a point into a tetmesh inside a tet. In general position, this split a tet into 4. In face position, split two tets. In edge position, In point position, do nothing. It has no surface history hooks, and throws while a surface history is recording.
|
inlinevirtual |
Whether local face j of tet tid is tracked surface, for a surface history. None is, unless an application says so.
Reimplemented in wmtk::TetOptimizerMesh.
| bool wmtk::TetMesh::link_condition | ( | const Tuple & | t | ) |
Compute the link of a given simplex Return a tuple of sets for 1. vertices, 2. edges, and 3. faces.
| size_t wmtk::TetMesh::lowest_common_tet | ( | size_t | v0_id, |
| size_t | v1_id, | ||
| size_t | v2_id | ||
| ) | const |
Lowest tet id incident to all three vertices, or size_t(-1) if there is none.
Costs O(smallest incident-tet fan) rather than O(largest), which matters when the fans are skewed – see the implementation for the case that motivated it.
|
inlineprotectedvirtual |
Called after reserve_free_slots() grew the storage, for derived classes that keep per-slot side arrays.
Reimplemented in wmtk::TetOptimizerMesh.
|
private |
| tet_conn | |
| vert_conn | |
| remove_id | this will be modified as new_tet_id, useful for rollback etc. |
| new_tet_conn |
|
inlinevirtual |
A tracked face's corners in the order that orients it, for a surface history, given the face's tets (tets_of_face). As given, unless an application says otherwise. The tets are passed in so that a caller holding one corner can find them from its tets alone (faces_at_vertex).
Reimplemented in wmtk::components::simwild::SimWildMesh, wmtk::TetOptimizerMesh, wmtk::components::simwild::SimWildMesh, wmtk::components::simwild::SimWildMesh, and wmtk::TetOptimizerMesh.
| std::array< TetMesh::Tuple, 4 > wmtk::TetMesh::oriented_tet_vertices | ( | const Tuple & | t | ) | const |
Positively oriented 4 vertices (represented by Tuples) in a tetra.
| std::array< size_t, 4 > wmtk::TetMesh::oriented_tet_vids | ( | const Tuple & | t | ) | const |
Positively oriented 4 vertices ids in a tetra.
| int wmtk::TetMesh::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 |
remove the tetrahedrons in the mesh that have given tet ids
| tids |
| void wmtk::TetMesh::reserve_free_slots | ( | size_t | cells, |
| size_t | verts | ||
| ) |
Serial points only: make cells fresh cell slots and verts fresh vertex slots available, growing the storage (connectivity and attributes) by at least half if not.
| size_t wmtk::TetMesh::resync_surface_history | ( | ) |
Brings the recorded surface in line with the tracked faces after a change outside the operations (tags re-derived, say). Returns how many faces it removed and added: 0 when nothing changed, or when not recording.
|
inlineprotectedvirtual |
User specified modifications and desideratas for after smoothing a vertex.
| t | Tuple refering to a vertex |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for smoothing a vertex.
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
| bool wmtk::TetMesh::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_tets | a vector of Tuples for all the newly introduced tetra. |
update connectivity
|
inlineprotectedvirtual |
This function computes the attributes for the added simplices. User specified modifications and desideratas for after an edge split.
| the | edge Tuple to be split |
Reimplemented in wmtk::TetOptimizerMesh, and wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for an edge split before changing the connectivity.
| the | edge Tuple to be split |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
Split a face in 3 faces.
The TetMesh is assumed to be face manifold, i.e., a face has at most two incident tets.
| t | Input tuple for the face to split. | |
| [out] | new_t | A vector of Tuples refering to the tets incident to the new vertex. introduced |
It has no surface history hooks, and throws while a surface history is recording.
v2 /|\ / | \ / | \ /t1 ^ t0\
/ / \ \ // t2 \ v0 --------— v1
|
inlineprotectedvirtual |
Compute the attributes for the added simplices.
User specified modifications and desideratas for after a face split
| t | The face tuple to be split. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for a face split before changing the connectivity.
| t | The face tuple to be split. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
Split a tet in 4 tets.
| t | Input tuple for the tet to split. | |
| [out] | new_t | A vector of Tuples refering to the tets incident to the new vertex. introduced |
It has no surface history hooks, and throws while a surface history is recording.
v2
/|\
/ | \
/ | \
/t1 X t0\
/ /(t3)\ \
// t2 \ v0 --------— v1
New tet vertex connectivity: t0: (X,1,2,3) <- modified old tet t1: (0,X,2,3) t2: (0,1,X,3) t3: (0,1,2,X)
|
inlineprotectedvirtual |
Compute the attributes for the added simplices.
User specified modifications and desideratas for after a tet split
| t | The tet tuple to be split. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for a tet split before changing the connectivity.
| t | The tet tuple to be split. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh.
| std::shared_ptr< history::TrackedSurfaceRecorder > wmtk::TetMesh::start_surface_history | ( | std::function< Eigen::Vector3d(size_t)> | position | ) |
Record every change to the tracked surface from now on (see wmtk/history/TrackedRecorder.hpp).
The tracked surface is the faces is_tracked_face() names, oriented by orient_tracked_face(). Snapshots it and returns the recorder. Every operation then reports the tracked faces around it at its commit point, a consolidation renumbers the recorder's vertices, and remove_tets_by_ids() resyncs it. position(v) gives vertex v's position: it is called at the snapshot, and then from inside an operation while its locks are held, so it must read through const attribute access. Recording changes nothing the operations do.
|
inlinevirtual |
Whether this mesh's passes run serially and so grow the storage on demand; if so, init/consolidate reserve a small slack instead of the preallocation factor.
Reimplemented in wmtk::TetOptimizerMesh.
|
private |
track surface
|
private |
insert new vertices
record infos
insert new tets
update conn_tets
|
inlinevirtual |
One-ring vertices x of vid where (vid, x) is 1D substructure NOT derivable from the surface complex (feature edges through the interior, for instance). The link condition's order-2 edge collection walks surface faces and would never see them.
Reimplemented in wmtk::TetOptimizerMesh.
| bool wmtk::TetMesh::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.
|
inlinevirtual |
The orders substructure_link_condition consults, overridable so an application can widen the 1D substructure beyond what the surface complex derives.
The paper's condition is written in terms of simplex orders; TetOptimizerMesh overrides these so an input FEATURE edge counts as order 2 (and its endpoints accordingly) without touching the meaning of get_order_of_* anywhere else – the feature tags are deliberately not part of the order classification.
Reimplemented in wmtk::TetOptimizerMesh.
|
private |
An operation's tracked faces before it changes the mesh, and at its commit point, which returns the range of surface edits it made.
3-2 edge swap
| t | Input Tuple for the edge to swap. |
| new_tets | a vector of Tuples for all the newly introduced tetra. |
Perform 4-4 swap between 2 tets
| t | Input Tuple for the edge to swap. | |
| [out] | new_tets | a vector of Tuples for all the newly introduced tetra. |
|
inlineprotectedvirtual |
Filter which of the 4-4 orientations may be chosen.
Called for every candidate 4-4 case (identified by its new edge) BEFORE the energy-based selection; a candidate whose new edge is rejected here is not considered. The default accepts everything, so interior edges keep the pure min-energy behavior. A derived mesh can override this to force a specific retetrahedralization (e.g. tetwild forces the case that realizes a surface diagonal flip).
| new_edge | The two vertices of the candidate's new edge. The ordering is implementation-defined (currently new_edge[0] is the case-selector vertex). |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified modifications and desideratas for after a 4-4 edge swap.
| t | edge Tuple that's swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.
| t | edge Tuple to be swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified energy to decide which of the 4 possible orientations should be chosen.
Accepts the last shown orientation if not overridden.
| tets | New tets after performing a 4-4 swap. |
| op_case | The operation case, where 0 are the tets before swap. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
Perform 5-6 swap
| t | Input Tuple for the edge to swap. | |
| [out] | new_tets | a vector of Tuples for all the newly introduced tetra. |
|
inlineprotectedvirtual |
Filter which of the 5-6 orientations may be chosen.
Called for every candidate 5-6 case (identified by its new fan face) BEFORE the energy-based selection; a candidate whose new face is rejected here is not considered. The default accepts everything, so interior edges keep the pure min-energy behavior. new_face[0] is the fan apex. A derived mesh can override this to force a specific retetrahedralization (e.g. tetwild forces the fan that realizes a surface diagonal flip).
| new_face | The candidate's new fan face; new_face[0] is the fan apex. |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified modifications and desideratas for after a 5-6 edge swap.
| t | edge Tuple that's swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.
| t | edge Tuple to be swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified energy to decide which of the 5 possible orientations should be chosen.
Accepts the last shown orientation if not overridden.
| tets | New tets after performing a 5-6 swap. |
| op_case | The operation case, where 0 are the tets before swap. |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified modifications and desideratas for after a 3-2 edge swap.
| t | edge Tuple that's swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.
| t | edge Tuple to be swaped |
Reimplemented in wmtk::TetOptimizerMesh.
2-3 face swap
| t | Input Tuple for the edge to swap. |
| new_tets | a vector of Tuples for all the newly introduced tetra. |
|
inlineprotectedvirtual |
User specified modifications and desideratas for after a 2-3 face swap.
| t | edge Tuple that's swaped |
Reimplemented in wmtk::TetOptimizerMesh.
|
inlineprotectedvirtual |
User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.
| t | edge Tuple to be swaped |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
inline |
get the current largest global tid
| std::array< TetMesh::Tuple, 6 > wmtk::TetMesh::tet_edges | ( | const Tuple & | t | ) | const |
get the 6 edges of a tet represented by Tuples
| t |
|
inlinevirtual |
The tags of tet tid, for a volume history: tets with the same tags form a region, which the volume map keeps. None, unless an application says otherwise.
Reimplemented in wmtk::components::simwild::SimWildMesh.
|
protected |
The tracked faces of the tets at the vertices vs that have a corner among them – or, with all, all three – as sorted vertex triples.
|
inlinevirtual |
The feature curves on the tracked surface, for a surface history: edges of tracked faces the operations keep by the history's rules (a split halves one, a collapse renames the removed end's, a swap never takes one). None, unless an application says otherwise.
Reimplemented in wmtk::TetOptimizerMesh.
| void wmtk::TetMesh::triangle_insertion | ( | const std::vector< Tuple > & | intersected_tets, |
| const std::vector< Tuple > & | intersected_edges, | ||
| std::vector< size_t > & | new_edge_vids, | ||
| std::vector< size_t > & | new_center_vids, | ||
| std::vector< std::array< size_t, 4 > > & | center_split_tets | ||
| ) |
Insert a triangle into a tetmesh, with known intersection information.
| intersected_tets | the tet to split |
| intersected_edges | the edges where new points are assigned to |
| new_edge_vids | new vertices correspond to each cut-edge |
get all tets
track surface before
subdivide
track surface after
| bool wmtk::TetMesh::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 cells).
| std::optional< std::tuple< TetMesh::Tuple, size_t > > wmtk::TetMesh::try_tuple_from_face | ( | const std::array< size_t, 3 > & | vids | ) | const |
tuple_from_face for callers where a missing face is an answer, not a bug.
The asserting form is right for the many callers that ask for a face they know exists. collapse_edge_after is not one of them: it asks for a face across the merged vertex that the collapse may have just removed, and it already has a branch for that case.
| TetMesh::Tuple wmtk::TetMesh::tuple_from_edge | ( | const std::array< size_t, 2 > & | vids | ) | const |
get a Tuple from global vids of the 2 end of an edge
| vids | an array of the 2 vertex id of the edge |
| TetMesh::Tuple wmtk::TetMesh::tuple_from_edge | ( | size_t | tid, |
| int | local_eid | ||
| ) | const |
get a Tuple from global tetra index and local edge index (from 0-5).
| tid | Global tetra index |
| local_eid | local edge index |
| std::tuple< TetMesh::Tuple, size_t > wmtk::TetMesh::tuple_from_face | ( | const std::array< size_t, 3 > & | vids | ) | const |
get a Tuple and the global face index from global vertex index of the face.
| vids | Global vertex index of the face |
| TetMesh::Tuple wmtk::TetMesh::tuple_from_face | ( | size_t | tid, |
| int | local_fid | ||
| ) | const |
get a Tuple from global tetra index and local face index (from 0-3).
| tid | Global tetra index |
| local_fid | local face index |
| TetMesh::Tuple wmtk::TetMesh::tuple_from_tet | ( | size_t | tid | ) | const |
get a Tuple from global tetra index
| tid | Global tetra index |
| TetMesh::Tuple wmtk::TetMesh::tuple_from_vertex | ( | size_t | vid | ) | const |
get a Tuple from global vertex index
| vid | Global vertex index |
|
inline |
get the current largest global vid
| std::vector< std::array< size_t, 3 > > wmtk::TetMesh::vertex_adjacent_boundary_faces | ( | const Tuple & | t | ) | const |
| m |
|
inlinevirtual |
Is a vertex part of the substructure.
| vid | Vertex ID |
Reimplemented in wmtk::components::topological_offset::TopoOffsetTetMesh, and wmtk::TetOptimizerMesh.
|
inline |
Number of tets incident to a vertex, in O(1).
Around 20-30 on a well-shaped mesh. Worth checking before anything that walks the one ring, since a degenerate mesh can push it into the thousands.
|
private |
An operation's tets before it changes the mesh, and at its commit point, given the surface edits it made: recorded if it made any.
| bool wmtk::TetMesh::m_check_smoothing_stays_in_star = false |
While true, smooth_vertex() checks that the smooth recorded nothing outside the vertex's star – the vertex itself and the edges, faces and cells incident to it – and throws if it did.
Set by a pass that smooths several vertices at once without locks (colored smoothing, see TetOptimizerMesh::smooth_vertices_colored). Two vertices it runs together share no simplex of their stars, but they can share a neighbour. A smoothing hook that reaches an attribute entry through non-const access records it, and a rejected smooth writes every recorded entry back – so an entry outside the star, such as a neighbour read as m_vertex_attribute[u] instead of through a const view, would be written by two threads at once. Hooks must read everything outside the star through const access; this turns a hook that does not into an error on its first such read, instead of a rare race.
|
staticconstexprprotected |
local edges within a tet
Protected rather than private: TetOptimizerMesh's feature-edge tracker enumerates a tet's six edges by local id.
|
staticconstexprprivate |
|
staticconstexprprivate |