3#include <wmtk/utils/VectorUtils.h>
4#include <wmtk/AttributeCollection.hpp>
5#include <wmtk/SlotPool.hpp>
6#include <wmtk/Types.hpp>
7#include <wmtk/simplex/Simplex.hpp>
8#include <wmtk/simplex/SimplexCollection.hpp>
9#include <wmtk/threading/enumerable_thread_specific.hpp>
10#include <wmtk/threading/vertex_mutex.hpp>
11#include <wmtk/utils/Logger.hpp>
39 void update_hash(
const TriMesh& m);
72 inline size_t vid(
const TriMesh&)
const {
return m_vid; }
80 inline size_t fid(
const TriMesh&)
const {
return m_fid; }
154 friend bool operator<(
const Tuple& a,
const Tuple& t)
157 std::tie(a.m_vid, a.m_eid, a.m_fid, a.m_hash) <
158 std::tie(t.m_vid, t.m_eid, t.m_fid, t.m_hash));
173 const Tuple& tuple()
const {
return m_tuple; }
174 const TriMesh& mesh()
const {
return m_mesh; }
182 bool is_valid()
const {
return m_tuple.
is_valid(m_mesh); }
183 size_t vid()
const {
return m_tuple.
vid(m_mesh); }
184 size_t eid()
const {
return m_tuple.
eid(m_mesh); }
185 size_t fid()
const {
return m_tuple.
fid(m_mesh); }
188 std::optional<SmartTuple> switch_face()
const
190 const std::optional<Tuple> t = m_tuple.
switch_face(m_mesh);
192 return std::optional<SmartTuple>({m_mesh, t.value()});
217 inline size_t& operator[](
const size_t index)
223 inline size_t operator[](
const size_t index)
const
254 inline size_t& operator[](
size_t index)
260 inline size_t operator[](
size_t index)
const
270 inline int find(
size_t v_id)
const
272 for (
int j = 0; j < 3; j++) {
282 virtual ~TriMesh() {}
289 void init(
size_t n_vertices,
const std::vector<std::array<size_t, 3>>& tris);
296 void init(
const MatrixXi& F);
335 Tuple tuple_from_vids(
size_t vid0,
size_t vid1,
size_t vid2)
const;
337 simplex::Vertex simplex_from_vertex(
const Tuple& t)
const;
338 simplex::Edge simplex_from_edge(
const Tuple& t)
const;
339 simplex::Face simplex_from_face(
const Tuple& t)
const;
340 simplex::Face simplex_from_face(
const size_t fid)
const;
342 Tuple tuple_from_simplex(
const simplex::Face& s)
const;
345 simplex::SimplexCollection simplex_incident_triangles(
const simplex::Vertex& v)
const;
346 simplex::SimplexCollection simplex_incident_triangles(
const simplex::Edge& e)
const;
347 simplex::SimplexCollection simplex_link_vertices(
const simplex::Vertex& v)
const;
348 simplex::SimplexCollection simplex_link_vertices(
const simplex::Edge& e)
const;
349 simplex::SimplexCollection simplex_link_edges(
const simplex::Vertex& v)
const;
351 template <
typename T>
352 using vector = std::vector<T>;
355 AbstractAttributeContainer* p_vertex_attrs =
nullptr;
356 AbstractAttributeContainer* p_edge_attrs =
nullptr;
357 AbstractAttributeContainer* p_face_attrs =
nullptr;
369 if (factor >= 1.0) m_preallocation_factor = factor;
371 double preallocation_factor()
const {
return m_preallocation_factor; }
394 size_t tri_storage_capacity()
const {
return m_tri_connectivity.capacity(); }
395 size_t vert_storage_capacity()
const {
return m_vertex_connectivity.capacity(); }
398 bool slots_exhausted()
const
400 return m_vertex_connectivity.refused() || m_tri_connectivity.refused();
402 void clear_slots_exhausted()
404 m_vertex_connectivity.clear_refused();
405 m_tri_connectivity.clear_refused();
408 size_t request_tri_slots(
size_t n);
409 size_t request_vert_slots(
size_t n);
412 size_t reserved_capacity(
size_t live_count)
const
414 const size_t floor = 64;
415 double c = std::ceil(m_preallocation_factor *
static_cast<double>(live_count));
416 size_t capacity =
static_cast<size_t>(c);
417 if (capacity < live_count) capacity = live_count;
418 return capacity < floor ? floor : capacity;
421 SlotPool<VertexConnectivity> m_vertex_connectivity;
422 SlotPool<TriangleConnectivity> m_tri_connectivity;
423 double m_preallocation_factor = 6.0;
424 bool m_use_link_condition =
true;
441 std::vector<size_t>& component_of,
442 std::vector<size_t>& representatives)
const;
464 virtual bool invariants(
const std::vector<Tuple>&) {
return true; }
487 if (!m_use_link_condition) {
563 static constexpr int EDGES_PER_CELL = 3;
565 Tuple tuple_from_cell(
size_t cid)
const {
return tuple_from_tri(cid); }
583 for (
const size_t fid : fids) {
584 m_tri_connectivity[fid].m_is_removed =
true;
585 for (
int j = 0; j < 3; j++) {
586 vector_erase(m_vertex_connectivity[m_tri_connectivity[fid][j]].m_conn_tris, fid);
589 for (
auto& v : m_vertex_connectivity) {
590 if (v.m_is_removed)
continue;
591 if (v.m_conn_tris.empty()) v.m_is_removed =
true;
627 bool use_link_condition()
const {
return m_use_link_condition; }
688#ifdef WMTK_DEBUG_BRUTE_FORCE_OPS
704 std::string debug_canonical_form()
const;
707 std::string debug_reference_collapse(
size_t v_removed,
size_t v_kept)
const;
716 std::string debug_reference_swap(
size_t v0,
size_t v1,
size_t fa,
size_t fb)
const;
725 std::string debug_reference_split_face(
731 size_t tri_cap)
const;
740 std::string debug_reference_split(
size_t v0,
size_t v1,
size_t new_v,
size_t tri_cap)
const;
764 bool split_edge(
const Tuple& t, std::vector<Tuple>& new_t);
775 virtual bool collapse_edge(
const Tuple& t, std::vector<Tuple>& new_t);
782 std::vector<Tuple>& new_tris,
785 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
786 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
787 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
788 std::vector<size_t>& n12_intersect_fids);
796 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
797 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
798 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
799 std::vector<size_t>& n12_intersect_fids);
811 bool swap_edge(
const Tuple& t, std::vector<Tuple>& new_t);
830 bool split_face(
const Tuple& t, std::vector<Tuple>& new_t);
840 return m_vertex_connectivity[t.vid(*
this)].m_conn_tris.size();
852 return m_vertex_connectivity[vid].m_conn_tris.size();
862 const std::vector<size_t>& get_one_ring_fids_for_vertex(
const Tuple& t)
const;
863 const std::vector<size_t>& get_one_ring_fids_for_vertex(
const size_t vid)
const;
874 std::vector<size_t> get_incident_fids_for_edge(
const Tuple& t)
const;
875 std::vector<size_t> get_incident_fids_for_edge(
const size_t vid0,
const size_t vid1)
const;
906 std::array<Tuple, 2> get_edge_vertices(
const Tuple& t)
const;
907 std::array<size_t, 2> get_edge_vids(
const Tuple& t)
const;
918 if (fid >= m_tri_connectivity.capacity() || m_tri_connectivity[fid].m_is_removed)
920 auto vid = m_tri_connectivity[fid][0];
921 return Tuple(vid, 1, fid, *
this);
939 if (vid >= m_vertex_connectivity.capacity() || m_vertex_connectivity[vid].m_is_removed ||
940 m_vertex_connectivity[vid].m_conn_tris.empty()) {
943 auto fid = m_vertex_connectivity[vid][0];
944 auto eid = m_tri_connectivity[fid].find((
int)vid);
945 return Tuple(vid, (eid + 1) % 3, fid, *
this);
955 auto vid = m_tri_connectivity[fid][(local_eid + 1) % 3];
956 return Tuple(vid, local_eid, fid, *
this);
959 std::tuple<Tuple, size_t>
tuple_from_edge(
const std::array<size_t, 2>& vids)
const;
968 const std::array<size_t, 2>& vids)
const;
977 if (p_vertex_attrs) p_vertex_attrs->begin_protect();
978 if (p_edge_attrs) p_edge_attrs->begin_protect();
979 if (p_face_attrs) p_face_attrs->begin_protect();
987 if (p_vertex_attrs) p_vertex_attrs->end_protect();
988 if (p_edge_attrs) p_edge_attrs->end_protect();
989 if (p_face_attrs) p_face_attrs->end_protect();
997 if (p_vertex_attrs) p_vertex_attrs->rollback();
998 if (p_edge_attrs) p_edge_attrs->rollback();
999 if (p_face_attrs) p_face_attrs->rollback();
1010 std::vector<VertexMutex> m_vertex_mutex;
1012 bool try_set_vertex_mutex(
const Tuple& v,
int threadid)
1014 bool got = m_vertex_mutex[v.
vid(*
this)].trylock();
1015 if (got) m_vertex_mutex[v.
vid(*
this)].set_owner(threadid);
1018 bool try_set_vertex_mutex(
size_t vid,
int threadid)
1020 bool got = m_vertex_mutex[vid].trylock();
1021 if (got) m_vertex_mutex[vid].set_owner(threadid);
1025 void unlock_vertex_mutex(
const Tuple& v) { m_vertex_mutex[v.vid(*
this)].unlock(); }
1026 void unlock_vertex_mutex(
size_t vid) { m_vertex_mutex[vid].unlock(); }
1036 std::vector<uint32_t> stamp;
1038 std::vector<size_t> frontier;
1039 std::vector<size_t> next;
1040 std::vector<size_t> one_ring;
1045 bool lock_vertex_ball(
const size_t* seeds,
size_t n_seeds,
int threadid,
int n,
size_t mark);
1048 void resize_mutex(
size_t v)
1050 if (m_vertex_mutex.size() < v) m_vertex_mutex.resize(v);
1056 int release_vertex_mutex_in_stack();
1147 void for_each_face(
const std::function<
void(
const Tuple&)>&);
1152 void for_each_edge(
const std::function<
void(
const Tuple&)>&);
1158 int NUM_THREADS = 0;
bool m_is_removed
is the triangle removed
Definition TriMesh.h:246
int find(size_t v_id) const
Definition TriMesh.h:270
size_t hash
the hash is changed every time there is an operation that influences the triangle
Definition TriMesh.h:252
std::array< size_t, 3 > m_indices
incident vertices of a given triangle
Definition TriMesh.h:241
size_t eid(const TriMesh &m) const
Definition TriMesh.cpp:95
size_t fid(const TriMesh &) const
Definition TriMesh.h:80
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:72
size_t local_eid(const TriMesh &m) const
Definition TriMesh.h:100
Tuple()
Definition TriMesh.h:57
std::vector< size_t > m_conn_tris
incident triangles of a given vertex
Definition TriMesh.h:210
bool m_is_removed
is the vertex removed
Definition TriMesh.h:215
virtual bool split_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge split.
Definition TriMesh.h:476
void set_preallocation_factor(double factor)
Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so op...
Definition TriMesh.h:367
std::array< size_t, 3 > oriented_tri_vids(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:2004
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:1855
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:1236
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:2848
void release_protect_attributes()
End the modification phase.
Definition TriMesh.h:985
size_t get_valence_for_vertex(const Tuple &t) const
Count the number of the one ring tris for a vertex.
Definition TriMesh.h:838
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:2521
std::vector< Tuple > get_vertices() const
Definition TriMesh.cpp:2128
size_t get_next_empty_slot_t()
Get the next avaiblie global index for the triangle.
Definition TriMesh.cpp:2378
size_t get_next_empty_slot_v()
Get the next avaiblie global index for the vertex.
Definition TriMesh.cpp:2383
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:1273
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:2388
bool try_set_face_mutex_one_ring(const Tuple &f, int threadid)
try lock the one-ring neighboring triangles' incident vertices.
Definition TriMesh.cpp:2736
void for_each_vertex(const std::function< void(const Tuple &)> &)
perform the given function for each vertex
Definition TriMesh.cpp:2786
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideras after an edge smooth.
Definition TriMesh.h:525
virtual bool invariants(const std::vector< Tuple > &)
User specified invariants that can't be violated.
Definition TriMesh.h:464
virtual bool edge_is_on_surface(const std::array< size_t, 2 > &vids) const
Is an edge part of the substructure.
Definition TriMesh.h:1175
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge collapse.
Definition TriMesh.h:497
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:953
Tuple switch_edge(const Tuple &t) const
a duplicate of Tuple::switch_edge funciton
Definition TriMesh.h:601
std::vector< Tuple > get_one_ring_tris_for_vertex(const Tuple &t) const
Get the one ring tris for a vertex.
Definition TriMesh.cpp:1889
virtual bool split_face_after(const Tuple &t)
User specified modifications and desideratas after a face split.
Definition TriMesh.h:538
bool split_face(const Tuple &t, std::vector< Tuple > &new_t)
Split a face in 3 faces.
Definition TriMesh.cpp:1640
int release_vertex_mutex_to(size_t mark)
Release the mutexes taken since the release stack held mark entries.
Definition TriMesh.cpp:2504
void rollback_protected_attributes()
rollback the attributes that are modified if any condition failed
Definition TriMesh.h:995
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:2707
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideras after an edge swap.
Definition TriMesh.h:503
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:2624
bool swap_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:1507
Tuple tuple_from_tri(size_t fid) const
Definition TriMesh.h:916
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:2042
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:2084
size_t get_order_of_edge(const std::array< size_t, 2 > &vids) const
Compute the order of an edge.
Definition TriMesh.cpp:2843
size_t vert_capacity() const
get the current largest global vid
Definition TriMesh.h:552
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:581
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:1914
std::vector< Tuple > get_faces() const
Definition TriMesh.cpp:2165
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:2202
void consolidate_mesh()
removing the elements that are removed
Definition TriMesh.cpp:1786
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:2602
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:2597
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:2649
virtual bool vertex_is_on_surface(const size_t vid) const
Is a vertex part of the substructure.
Definition TriMesh.h:1168
std::array< Tuple, 3 > oriented_tri_vertices(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1991
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for an edge smooth.
Definition TriMesh.h:519
size_t tri_capacity() const
get the current largest global fid
Definition TriMesh.h:546
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:975
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split.
Definition TriMesh.h:532
bool substructure_link_condition(const Tuple &e_tuple) const
Link condition that also considers substructures.
Definition TriMesh.cpp:2869
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split.
Definition TriMesh.h:470
std::optional< Tuple > switch_face(const Tuple &t) const
a duplicate of Tuple::switch_face funciton
Definition TriMesh.h:606
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:2819
size_t vertex_valence(const size_t vid) const
Number of triangles incident to a vertex, by id.
Definition TriMesh.h:850
void for_each_edge(const std::function< void(const Tuple &)> &)
perform the given function for each edge
Definition TriMesh.cpp:2766
Tuple tuple_from_vertex(size_t vid) const
Definition TriMesh.h:937
bool check_link_condition(const Tuple &t) const
prerequisite for collapse
Definition TriMesh.cpp:2407
void set_use_link_condition(bool use_it)
Should collapse_edge_before enforce the link condition?
Definition TriMesh.h:626
bool smooth_vertex(const Tuple &t)
Definition TriMesh.cpp:1606
std::vector< Tuple > get_edges() const
Definition TriMesh.cpp:2181
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:485
Tuple switch_vertex(const Tuple &t) const
a duplicate of Tuple::switch_vertex funciton
Definition TriMesh.h:597
virtual bool collapse_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:1133
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:748
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:2802
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:1035