3#include <wmtk/utils/VectorUtils.h>
4#include <wmtk/AttributeCollection.hpp>
5#include <wmtk/Types.hpp>
6#include <wmtk/simplex/Simplex.hpp>
7#include <wmtk/simplex/SimplexCollection.hpp>
8#include <wmtk/threading/enumerable_thread_specific.hpp>
9#include <wmtk/threading/vertex_mutex.hpp>
10#include <wmtk/utils/Logger.hpp>
38 void update_hash(
const TriMesh& m);
71 inline size_t vid(
const TriMesh&)
const {
return m_vid; }
79 inline size_t fid(
const TriMesh&)
const {
return m_fid; }
153 friend bool operator<(
const Tuple& a,
const Tuple& t)
156 std::tie(a.m_vid, a.m_eid, a.m_fid, a.m_hash) <
157 std::tie(t.m_vid, t.m_eid, t.m_fid, t.m_hash));
172 const Tuple& tuple()
const {
return m_tuple; }
173 const TriMesh& mesh()
const {
return m_mesh; }
181 bool is_valid()
const {
return m_tuple.
is_valid(m_mesh); }
182 size_t vid()
const {
return m_tuple.
vid(m_mesh); }
183 size_t eid()
const {
return m_tuple.
eid(m_mesh); }
184 size_t fid()
const {
return m_tuple.
fid(m_mesh); }
187 std::optional<SmartTuple> switch_face()
const
189 const std::optional<Tuple> t = m_tuple.
switch_face(m_mesh);
191 return std::optional<SmartTuple>({m_mesh, t.value()});
216 inline size_t& operator[](
const size_t index)
222 inline size_t operator[](
const size_t index)
const
253 inline size_t& operator[](
size_t index)
259 inline size_t operator[](
size_t index)
const
269 inline int find(
size_t v_id)
const
271 for (
int j = 0; j < 3; j++) {
281 virtual ~TriMesh() {}
288 void init(
size_t n_vertices,
const std::vector<std::array<size_t, 3>>& tris);
295 void init(
const MatrixXi& F);
334 Tuple tuple_from_vids(
size_t vid0,
size_t vid1,
size_t vid2)
const;
336 simplex::Vertex simplex_from_vertex(
const Tuple& t)
const;
337 simplex::Edge simplex_from_edge(
const Tuple& t)
const;
338 simplex::Face simplex_from_face(
const Tuple& t)
const;
339 simplex::Face simplex_from_face(
const size_t fid)
const;
341 Tuple tuple_from_simplex(
const simplex::Face& s)
const;
344 simplex::SimplexCollection simplex_incident_triangles(
const simplex::Vertex& v)
const;
345 simplex::SimplexCollection simplex_incident_triangles(
const simplex::Edge& e)
const;
346 simplex::SimplexCollection simplex_link_vertices(
const simplex::Vertex& v)
const;
347 simplex::SimplexCollection simplex_link_vertices(
const simplex::Edge& e)
const;
348 simplex::SimplexCollection simplex_link_edges(
const simplex::Vertex& v)
const;
350 template <
typename T>
351 using vector = std::vector<T>;
354 AbstractAttributeContainer* p_vertex_attrs =
nullptr;
355 AbstractAttributeContainer* p_edge_attrs =
nullptr;
356 AbstractAttributeContainer* p_face_attrs =
nullptr;
368 if (factor >= 1.0) m_preallocation_factor = factor;
370 double preallocation_factor()
const {
return m_preallocation_factor; }
375 long request_tri_slots(
size_t n);
376 long request_vert_slots(
size_t n);
379 size_t reserved_capacity(
size_t live_count)
const
381 const size_t floor = 64;
382 double c = std::ceil(m_preallocation_factor *
static_cast<double>(live_count));
383 size_t capacity =
static_cast<size_t>(c);
384 if (capacity < live_count) capacity = live_count;
385 return capacity < floor ? floor : capacity;
388 vector<VertexConnectivity> m_vertex_connectivity;
389 vector<TriangleConnectivity> m_tri_connectivity;
390 std::atomic_long current_vert_size;
391 std::atomic_long current_tri_size;
392 double m_preallocation_factor = 6.0;
393 bool m_use_link_condition =
true;
410 std::vector<size_t>& component_of,
411 std::vector<size_t>& representatives)
const;
433 virtual bool invariants(
const std::vector<Tuple>&) {
return true; }
456 if (!m_use_link_condition) {
532 static constexpr int EDGES_PER_CELL = 3;
534 Tuple tuple_from_cell(
size_t cid)
const {
return tuple_from_tri(cid); }
552 for (
const size_t fid : fids) {
553 m_tri_connectivity[fid].m_is_removed =
true;
554 for (
int j = 0; j < 3; j++) {
555 vector_erase(m_vertex_connectivity[m_tri_connectivity[fid][j]].m_conn_tris, fid);
558 for (
auto& v : m_vertex_connectivity) {
559 if (v.m_is_removed)
continue;
560 if (v.m_conn_tris.empty()) v.m_is_removed =
true;
596 bool use_link_condition()
const {
return m_use_link_condition; }
657#ifdef WMTK_DEBUG_BRUTE_FORCE_OPS
673 std::string debug_canonical_form()
const;
676 std::string debug_reference_collapse(
size_t v_removed,
size_t v_kept)
const;
685 std::string debug_reference_swap(
size_t v0,
size_t v1,
size_t fa,
size_t fb)
const;
694 std::string debug_reference_split_face(
700 size_t tri_cap)
const;
709 std::string debug_reference_split(
size_t v0,
size_t v1,
size_t new_v,
size_t tri_cap)
const;
733 bool split_edge(
const Tuple& t, std::vector<Tuple>& new_t);
744 virtual bool collapse_edge(
const Tuple& t, std::vector<Tuple>& new_t);
751 std::vector<Tuple>& new_tris,
754 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
755 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
756 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
757 std::vector<size_t>& n12_intersect_fids);
765 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
766 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
767 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
768 std::vector<size_t>& n12_intersect_fids);
780 bool swap_edge(
const Tuple& t, std::vector<Tuple>& new_t);
799 bool split_face(
const Tuple& t, std::vector<Tuple>& new_t);
809 return m_vertex_connectivity[t.vid(*
this)].m_conn_tris.size();
821 return m_vertex_connectivity[vid].m_conn_tris.size();
831 const std::vector<size_t>& get_one_ring_fids_for_vertex(
const Tuple& t)
const;
832 const std::vector<size_t>& get_one_ring_fids_for_vertex(
const size_t vid)
const;
843 std::vector<size_t> get_incident_fids_for_edge(
const Tuple& t)
const;
844 std::vector<size_t> get_incident_fids_for_edge(
const size_t vid0,
const size_t vid1)
const;
875 std::array<Tuple, 2> get_edge_vertices(
const Tuple& t)
const;
876 std::array<size_t, 2> get_edge_vids(
const Tuple& t)
const;
887 if (fid >= m_tri_connectivity.size() || m_tri_connectivity[fid].m_is_removed)
889 auto vid = m_tri_connectivity[fid][0];
890 return Tuple(vid, 1, fid, *
this);
908 if (vid >= m_vertex_connectivity.size() || m_vertex_connectivity[vid].m_is_removed ||
909 m_vertex_connectivity[vid].m_conn_tris.empty()) {
912 auto fid = m_vertex_connectivity[vid][0];
913 auto eid = m_tri_connectivity[fid].find((
int)vid);
914 return Tuple(vid, (eid + 1) % 3, fid, *
this);
924 auto vid = m_tri_connectivity[fid][(local_eid + 1) % 3];
925 return Tuple(vid, local_eid, fid, *
this);
928 std::tuple<Tuple, size_t>
tuple_from_edge(
const std::array<size_t, 2>& vids)
const;
937 const std::array<size_t, 2>& vids)
const;
946 if (p_vertex_attrs) p_vertex_attrs->begin_protect();
947 if (p_edge_attrs) p_edge_attrs->begin_protect();
948 if (p_face_attrs) p_face_attrs->begin_protect();
956 if (p_vertex_attrs) p_vertex_attrs->end_protect();
957 if (p_edge_attrs) p_edge_attrs->end_protect();
958 if (p_face_attrs) p_face_attrs->end_protect();
966 if (p_vertex_attrs) p_vertex_attrs->rollback();
967 if (p_edge_attrs) p_edge_attrs->rollback();
968 if (p_face_attrs) p_face_attrs->rollback();
979 std::vector<VertexMutex> m_vertex_mutex;
981 bool try_set_vertex_mutex(
const Tuple& v,
int threadid)
983 bool got = m_vertex_mutex[v.
vid(*
this)].trylock();
984 if (got) m_vertex_mutex[v.
vid(*
this)].set_owner(threadid);
987 bool try_set_vertex_mutex(
size_t vid,
int threadid)
989 bool got = m_vertex_mutex[vid].trylock();
990 if (got) m_vertex_mutex[vid].set_owner(threadid);
994 void unlock_vertex_mutex(
const Tuple& v) { m_vertex_mutex[v.vid(*
this)].unlock(); }
995 void unlock_vertex_mutex(
size_t vid) { m_vertex_mutex[vid].unlock(); }
1005 std::vector<uint32_t> stamp;
1007 std::vector<size_t> frontier;
1008 std::vector<size_t> next;
1009 std::vector<size_t> one_ring;
1014 bool lock_vertex_ball(
const size_t* seeds,
size_t n_seeds,
int threadid,
int n,
size_t mark);
1017 void resize_mutex(
size_t v)
1019 if (m_vertex_mutex.size() < v) m_vertex_mutex.resize(v);
1025 int release_vertex_mutex_in_stack();
1116 void for_each_face(
const std::function<
void(
const Tuple&)>&);
1121 void for_each_edge(
const std::function<
void(
const Tuple&)>&);
1127 int NUM_THREADS = 0;
bool m_is_removed
is the triangle removed
Definition TriMesh.h:245
int find(size_t v_id) const
Definition TriMesh.h:269
size_t hash
the hash is changed every time there is an operation that influences the triangle
Definition TriMesh.h:251
std::array< size_t, 3 > m_indices
incident vertices of a given triangle
Definition TriMesh.h:240
size_t eid(const TriMesh &m) const
Definition TriMesh.cpp:95
size_t fid(const TriMesh &) const
Definition TriMesh.h:79
Tuple switch_vertex(const TriMesh &m) const
Definition TriMesh.cpp:158
bool is_valid(const TriMesh &m) const
check if a Tuple is valid
Definition TriMesh.cpp:296
std::vector< Tuple > switch_faces(const TriMesh &m) const
Definition TriMesh.cpp:250
Tuple switch_edge(const TriMesh &m) const
Definition TriMesh.cpp:187
std::array< Tuple, 3 > oriented_tri_vertices(const TriMesh &m) const
std::optional< Tuple > switch_face(const TriMesh &m) const
Definition TriMesh.cpp:214
size_t vid(const TriMesh &) const
Definition TriMesh.h:71
size_t local_eid(const TriMesh &m) const
Definition TriMesh.h:99
Tuple()
Definition TriMesh.h:56
std::vector< size_t > m_conn_tris
incident triangles of a given vertex
Definition TriMesh.h:209
bool m_is_removed
is the vertex removed
Definition TriMesh.h:214
virtual bool split_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge split.
Definition TriMesh.h:445
void set_preallocation_factor(double factor)
Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so op...
Definition TriMesh.h:366
std::array< size_t, 3 > oriented_tri_vids(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:2006
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.
Definition TriMesh.cpp:1857
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)
Definition TriMesh.cpp:1237
size_t edge_valence(const TriMesh::Tuple &t) const
Number of triangles incident to the edge the Tuple points at.
Definition TriMesh.cpp:435
void vertex_fan_components(size_t vid, std::vector< size_t > &component_of, std::vector< size_t > &representatives) const
Definition TriMesh.cpp:335
size_t get_order_of_vertex(const size_t vid) const
Get the order of a vertex.
Definition TriMesh.cpp:2883
void release_protect_attributes()
End the modification phase.
Definition TriMesh.h:954
size_t get_valence_for_vertex(const Tuple &t) const
Count the number of the one ring tris for a vertex.
Definition TriMesh.h:807
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.
Definition TriMesh.cpp:2556
std::vector< Tuple > get_vertices() const
Definition TriMesh.cpp:2130
size_t get_next_empty_slot_t()
Get the next avaiblie global index for the triangle.
Definition TriMesh.cpp:2411
size_t get_next_empty_slot_v()
Get the next avaiblie global index for the vertex.
Definition TriMesh.cpp:2417
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)
Definition TriMesh.cpp:1274
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....
Definition TriMesh.cpp:2423
bool try_set_face_mutex_one_ring(const Tuple &f, int threadid)
try lock the one-ring neighboring triangles' incident vertices.
Definition TriMesh.cpp:2771
void for_each_vertex(const std::function< void(const Tuple &)> &)
perform the given function for each vertex
Definition TriMesh.cpp:2821
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideras after an edge smooth.
Definition TriMesh.h:494
virtual bool invariants(const std::vector< Tuple > &)
User specified invariants that can't be violated.
Definition TriMesh.h:433
virtual bool edge_is_on_surface(const std::array< size_t, 2 > &vids) const
Is an edge part of the substructure.
Definition TriMesh.h:1144
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge collapse.
Definition TriMesh.h:466
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.
Definition TriMesh.cpp:724
Tuple tuple_from_edge(size_t fid, size_t local_eid) const
Definition TriMesh.h:922
Tuple switch_edge(const Tuple &t) const
a duplicate of Tuple::switch_edge funciton
Definition TriMesh.h:570
std::vector< Tuple > get_one_ring_tris_for_vertex(const Tuple &t) const
Get the one ring tris for a vertex.
Definition TriMesh.cpp:1891
virtual bool split_face_after(const Tuple &t)
User specified modifications and desideratas after a face split.
Definition TriMesh.h:507
bool split_face(const Tuple &t, std::vector< Tuple > &new_t)
Split a face in 3 faces.
Definition TriMesh.cpp:1641
int release_vertex_mutex_to(size_t mark)
Release the mutexes taken since the release stack held mark entries.
Definition TriMesh.cpp:2539
void rollback_protected_attributes()
rollback the attributes that are modified if any condition failed
Definition TriMesh.h:964
bool split_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:789
bool try_set_vertex_mutex_one_ring(const Tuple &v, int threadid)
Lock v and its one-ring. Complete, unlike the two-ring pair.
Definition TriMesh.cpp:2742
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideras after an edge swap.
Definition TriMesh.h:472
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.
Definition TriMesh.cpp:2659
bool swap_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:1508
Tuple tuple_from_tri(size_t fid) const
Definition TriMesh.h:885
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.
Definition TriMesh.cpp:2044
bool is_boundary_edge(const TriMesh::Tuple &t) const
Does exactly one triangle share this edge?
Definition TriMesh.cpp:445
void init(size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris)
Definition TriMesh.cpp:2086
size_t get_order_of_edge(const std::array< size_t, 2 > &vids) const
Compute the order of an edge.
Definition TriMesh.cpp:2878
size_t vert_capacity() const
get the current largest global vid
Definition TriMesh.h:521
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.
Definition TriMesh.h:550
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.
Definition TriMesh.cpp:1916
std::vector< Tuple > get_faces() const
Definition TriMesh.cpp:2167
bool check_mesh_connectivity_validity() const
verify the connectivity validity of the mesh
Definition TriMesh.cpp:752
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:2204
void consolidate_mesh()
removing the elements that are removed
Definition TriMesh.cpp:1788
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.
Definition TriMesh.cpp:2637
bool is_manifold_edge(const TriMesh::Tuple &t) const
Do exactly two triangles share this edge?
Definition TriMesh.cpp:460
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.
Definition TriMesh.cpp:2632
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.
Definition TriMesh.cpp:2684
virtual bool vertex_is_on_surface(const size_t vid) const
Is a vertex part of the substructure.
Definition TriMesh.h:1137
std::array< Tuple, 3 > oriented_tri_vertices(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1993
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for an edge smooth.
Definition TriMesh.h:488
size_t tri_capacity() const
get the current largest global fid
Definition TriMesh.h:515
size_t vertex_component_count(const size_t vid) const
Number of edge-connected components in the fan of a vertex.
Definition TriMesh.cpp:717
void start_protect_attributes()
Start the phase where the attributes that will be modified can be recorded.
Definition TriMesh.h:944
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split.
Definition TriMesh.h:501
bool substructure_link_condition(const Tuple &e_tuple) const
Link condition that also considers substructures.
Definition TriMesh.cpp:2904
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split.
Definition TriMesh.h:439
std::optional< Tuple > switch_face(const Tuple &t) const
a duplicate of Tuple::switch_face funciton
Definition TriMesh.h:575
simplex::SimplexCollection get_surface_edges_for_vertex(const size_t vid) const
Get all edges on the surface that are incident to vid.
Definition TriMesh.cpp:2854
size_t vertex_valence(const size_t vid) const
Number of triangles incident to a vertex, by id.
Definition TriMesh.h:819
void for_each_edge(const std::function< void(const Tuple &)> &)
perform the given function for each edge
Definition TriMesh.cpp:2801
Tuple tuple_from_vertex(size_t vid) const
Definition TriMesh.h:906
bool check_link_condition(const Tuple &t) const
prerequisite for collapse
Definition TriMesh.cpp:2442
void set_use_link_condition(bool use_it)
Should collapse_edge_before enforce the link condition?
Definition TriMesh.h:595
bool smooth_vertex(const Tuple &t)
Definition TriMesh.cpp:1607
std::vector< Tuple > get_edges() const
Definition TriMesh.cpp:2183
virtual bool collapse_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge collapse including the link check as collapse...
Definition TriMesh.h:454
Tuple switch_vertex(const Tuple &t) const
a duplicate of Tuple::switch_vertex funciton
Definition TriMesh.h:566
virtual bool collapse_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:1134
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
Definition TriMesh.h:717
bool check_edge_manifold() const
verify the edge manifoldness of the mesh
Definition TriMesh.cpp:781
void for_each_face(const std::function< void(const Tuple &)> &)
perform the given function for each face
Definition TriMesh.cpp:2837
Definition SimplexCollection.hpp:9
A per-vertex lock plus the id of the thread currently holding it.
Definition vertex_mutex.hpp:29
Definition enumerable_thread_specific.hpp:26
Per-thread buffers for the n-ring lock, so a lock acquisition allocates nothing.
Definition TriMesh.h:1004