Wildmeshing Toolkit
Loading...
Searching...
No Matches
TriMesh.h
1#pragma once
2
3#include <wmtk/utils/VectorUtils.h>
4#include <wmtk/AttributeCollection.hpp>
5#include <wmtk/Types.hpp>
6#include <wmtk/simplex/RawSimplex.hpp>
7#include <wmtk/simplex/RawSimplexCollection.hpp>
8#include <wmtk/utils/Logger.hpp>
9
10// clang-format off
11#include <wmtk/utils/DisableWarnings.hpp>
12#include <tbb/concurrent_vector.h>
13#include <tbb/spin_mutex.h>
14#include <wmtk/utils/EnableWarnings.hpp>
15// clang-format on
16
17#include <algorithm>
18#include <array>
19#include <cassert>
20#include <map>
21#include <memory>
22#include <optional>
23#include <vector>
24
25namespace wmtk {
26
28{
29public:
30 // Cell Tuple Navigator
31 class Tuple
32 {
33 private:
34 size_t m_vid = -1;
35 size_t m_eid = -1;
36 size_t m_fid = -1;
37 size_t m_hash = -1;
38
39 void update_hash(const TriMesh& m);
40
41 public:
42 void print_info();
43
44 // v2 /
45 // / \ /
46 // e1 / \ e0 /
47 // v0 - - - v1 /
48 // e2 /
57 Tuple() {}
58 Tuple(size_t vid, size_t eid, size_t fid, const TriMesh& m)
59 : m_vid(vid)
60 , m_eid(eid)
61 , m_fid(fid)
62 {
63 update_hash(m);
64 }
65
66
72 inline size_t vid(const TriMesh&) const { return m_vid; }
73
80 inline size_t fid(const TriMesh&) const { return m_fid; }
81
82
91 size_t eid(const TriMesh& m) const;
92
100 size_t local_eid(const TriMesh& m) const { return m_eid; };
107 Tuple switch_vertex(const TriMesh& m) const;
113 Tuple switch_edge(const TriMesh& m) const;
123 std::optional<Tuple> switch_face(const TriMesh& m) const;
124
125 std::vector<Tuple> switch_faces(const TriMesh& m) const;
126
136 bool is_valid(const TriMesh& m) const;
137
142 std::array<Tuple, 3> oriented_tri_vertices(const TriMesh& m) const;
143 friend bool operator<(const Tuple& a, const Tuple& t)
144 {
145 return (
146 std::tie(a.m_vid, a.m_eid, a.m_fid, a.m_hash) <
147 std::tie(t.m_vid, t.m_eid, t.m_fid, t.m_hash));
148 }
149 };
150
152 {
153 Tuple m_tuple;
154 const TriMesh& m_mesh;
155
156 public:
157 SmartTuple(const TriMesh& mesh, const Tuple& t)
158 : m_mesh(mesh)
159 , m_tuple(t)
160 {}
161
162 const Tuple& tuple() const { return m_tuple; }
163 const TriMesh& mesh() const { return m_mesh; }
164
165 SmartTuple& operator=(const SmartTuple& t)
166 {
167 m_tuple = t.m_tuple;
168 return *this;
169 }
170
171 bool is_valid() const { return m_tuple.is_valid(m_mesh); }
172 size_t vid() const { return m_tuple.vid(m_mesh); }
173 size_t eid() const { return m_tuple.eid(m_mesh); }
174 size_t fid() const { return m_tuple.fid(m_mesh); }
175 SmartTuple switch_vertex() const { return {m_mesh, m_tuple.switch_vertex(m_mesh)}; }
176 SmartTuple switch_edge() const { return {m_mesh, m_tuple.switch_edge(m_mesh)}; }
177 std::optional<SmartTuple> switch_face() const
178 {
179 const std::optional<Tuple> t = m_tuple.switch_face(m_mesh);
180 if (t) {
181 return std::optional<SmartTuple>({m_mesh, t.value()});
182 }
183 return {};
184 }
185 };
186
193 {
194 public:
199 std::vector<size_t> m_conn_tris;
204 bool m_is_removed = false;
205
206 inline size_t& operator[](const size_t index)
207 {
208 assert(index < m_conn_tris.size());
209 return m_conn_tris[index];
210 }
211
212 inline size_t operator[](const size_t index) const
213 {
214 assert(index < m_conn_tris.size());
215 return m_conn_tris[index];
216 }
217 };
218
224 {
225 public:
230 std::array<size_t, 3> m_indices;
235 bool m_is_removed = false;
241 size_t hash = 0;
242
243 inline size_t& operator[](size_t index)
244 {
245 assert(index < 3);
246 return m_indices[index];
247 }
248
249 inline size_t operator[](size_t index) const
250 {
251 assert(index < 3);
252 return m_indices[index];
253 }
259 inline int find(size_t v_id) const
260 {
261 for (int j = 0; j < 3; j++) {
262 if (v_id == m_indices[j]) {
263 return j;
264 }
265 }
266 return -1;
267 }
268 };
269
270 TriMesh() {}
271 virtual ~TriMesh() {}
272
278 void init(size_t n_vertices, const std::vector<std::array<size_t, 3>>& tris);
279
285 void init(const MatrixXi& F);
286
297 std::vector<Tuple> get_vertices() const;
298
305 std::vector<Tuple> get_edges() const;
306
313 std::vector<Tuple> get_faces() const;
314
322 Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const;
323
324 Tuple tuple_from_vids(size_t vid0, size_t vid1, size_t vid2) const;
325
326 simplex::Vertex simplex_from_vertex(const Tuple& t) const;
327 simplex::Edge simplex_from_edge(const Tuple& t) const;
328 simplex::Face simplex_from_face(const Tuple& t) const;
329
330 Tuple tuple_from_simplex(const simplex::Face& s) const;
331 // Tuple tuple_from_simplex(const simplex::Edge& s) const;
332
333 simplex::RawSimplexCollection simplex_incident_triangles(const simplex::Vertex& v) const;
334 simplex::RawSimplexCollection simplex_incident_triangles(const simplex::Edge& e) const;
335 simplex::RawSimplexCollection simplex_link_vertices(const simplex::Vertex& v) const;
336 simplex::RawSimplexCollection simplex_link_vertices(const simplex::Edge& e) const;
337 simplex::RawSimplexCollection simplex_link_edges(const simplex::Vertex& v) const;
338
339 template <typename T>
340 using vector = tbb::concurrent_vector<T>;
341
342public:
343 AbstractAttributeContainer* p_vertex_attrs = nullptr;
344 AbstractAttributeContainer* p_edge_attrs = nullptr;
345 AbstractAttributeContainer* p_face_attrs = nullptr;
346
347private:
348 vector<VertexConnectivity> m_vertex_connectivity;
349 vector<TriangleConnectivity> m_tri_connectivity;
350 std::atomic_long current_vert_size;
351 std::atomic_long current_tri_size;
352 tbb::spin_mutex vertex_connectivity_lock;
353 tbb::spin_mutex tri_connectivity_lock;
354 bool vertex_connectivity_synchronizing_flag = false;
355 bool tri_connectivity_synchronizing_flag = false;
356 int MAX_THREADS = 128;
362 size_t get_next_empty_slot_t();
368 size_t get_next_empty_slot_v();
369
370public:
376 virtual bool invariants(const std::vector<Tuple>&) { return true; }
382 virtual bool split_edge_before(const Tuple& t) { return true; }
388 virtual bool split_edge_after(const Tuple& t) { return true; }
389
397 virtual bool collapse_edge_before(const Tuple& t)
398 {
399 if (check_link_condition(t)) return true;
400 return false;
401 }
407 virtual bool collapse_edge_after(const Tuple& t) { return true; }
413 virtual bool swap_edge_after(const Tuple& t) { return true; }
422 virtual bool swap_edge_before(const Tuple& t);
429 virtual bool smooth_before(const Tuple& t) { return true; }
435 virtual bool smooth_after(const Tuple& t) { return true; }
436
442 virtual bool split_face_before(const Tuple& t) { return true; }
448 virtual bool split_face_after(const Tuple& t) { return true; }
449
450public:
456 size_t tri_capacity() const { return current_tri_size; }
462 size_t vert_capacity() const { return current_vert_size; }
468 void consolidate_mesh();
472 Tuple switch_vertex(const Tuple& t) const { return t.switch_vertex(*this); }
476 Tuple switch_edge(const Tuple& t) const { return t.switch_edge(*this); }
481 std::optional<Tuple> switch_face(const Tuple& t) const { return t.switch_face(*this); }
482
488 bool check_link_condition(const Tuple& t) const;
497 bool check_edge_manifold() const;
498
504 bool is_boundary_edge(const TriMesh::Tuple& t) const { return t.switch_faces(*this).empty(); }
505
512 {
514 for (auto e : ve)
515 if (is_boundary_edge(e)) return true;
516 return false;
517 }
518
527 bool split_edge(const Tuple& t, std::vector<Tuple>& new_t);
528
538 virtual bool collapse_edge(const Tuple& t, std::vector<Tuple>& new_t);
539
544 const Tuple& loc0,
545 std::vector<Tuple>& new_tris,
546 Tuple& return_t,
547 size_t& new_vid,
548 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
549 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
550 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
551 std::vector<size_t>& n12_intersect_fids);
552
558 size_t& new_vid,
559 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
560 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
561 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
562 std::vector<size_t>& n12_intersect_fids);
563
564
574 bool swap_edge(const Tuple& t, std::vector<Tuple>& new_t);
575
583 bool smooth_vertex(const Tuple& t);
584
593 bool split_face(const Tuple& t, std::vector<Tuple>& new_t);
594
601 size_t get_valence_for_vertex(const Tuple& t) const
602 {
603 return m_vertex_connectivity[t.vid(*this)].m_conn_tris.size();
604 }
605
612 std::vector<Tuple> get_one_ring_tris_for_vertex(const Tuple& t) const;
619 std::vector<size_t> get_one_ring_vids_for_vertex_duplicate(const size_t& t) const;
620
630 std::vector<Tuple> get_one_ring_edges_for_vertex(const Tuple& t) const;
631
638 std::array<Tuple, 3> oriented_tri_vertices(const Tuple& t) const;
639
646 std::array<size_t, 3> oriented_tri_vids(const Tuple& t) const;
647 std::array<size_t, 3> oriented_tri_vids(const size_t i) const;
648
656 Tuple tuple_from_tri(size_t fid) const
657 {
658 if (fid >= m_tri_connectivity.size() || m_tri_connectivity[fid].m_is_removed)
659 return Tuple();
660 auto vid = m_tri_connectivity[fid][0];
661 return Tuple(vid, 1, fid, *this);
662 }
668 Tuple tuple_from_vertex(size_t vid) const
669 {
670 auto fid = m_vertex_connectivity[vid][0];
671 auto eid = m_tri_connectivity[fid].find((int)vid);
672 return Tuple(vid, (eid + 1) % 3, fid, *this);
673 }
680 Tuple tuple_from_edge(size_t fid, size_t local_eid) const
681 {
682 auto vid = m_tri_connectivity[fid][(local_eid + 1) % 3];
683 return Tuple(vid, local_eid, fid, *this);
684 }
685
686public:
692 {
693 if (p_vertex_attrs) p_vertex_attrs->begin_protect();
694 if (p_edge_attrs) p_edge_attrs->begin_protect();
695 if (p_face_attrs) p_face_attrs->begin_protect();
696 }
702 {
703 if (p_vertex_attrs) p_vertex_attrs->end_protect();
704 if (p_edge_attrs) p_edge_attrs->end_protect();
705 if (p_face_attrs) p_face_attrs->end_protect();
706 }
712 {
713 if (p_vertex_attrs) p_vertex_attrs->rollback();
714 if (p_edge_attrs) p_edge_attrs->rollback();
715 if (p_face_attrs) p_face_attrs->rollback();
716 }
717
718 // Moved code from concurrent TriMesh
719
720public:
722 {
723 tbb::spin_mutex mutex;
724 int owner = std::numeric_limits<int>::max();
725
726 public:
727 bool trylock() { return mutex.try_lock(); }
728
729 void unlock()
730 {
731 reset_owner();
732 mutex.unlock();
733 }
734
735 int get_owner() { return owner; }
736
737 void set_owner(int n) { owner = n; }
738
739 void reset_owner() { owner = std::numeric_limits<int>::max(); }
740 };
741
742private:
743 tbb::concurrent_vector<VertexMutex> m_vertex_mutex;
744
745 bool try_set_vertex_mutex(const Tuple& v, int threadid)
746 {
747 bool got = m_vertex_mutex[v.vid(*this)].trylock();
748 if (got) m_vertex_mutex[v.vid(*this)].set_owner(threadid);
749 return got;
750 }
751 bool try_set_vertex_mutex(size_t vid, int threadid)
752 {
753 bool got = m_vertex_mutex[vid].trylock();
754 if (got) m_vertex_mutex[vid].set_owner(threadid);
755 return got;
756 }
757
758 void unlock_vertex_mutex(const Tuple& v) { m_vertex_mutex[v.vid(*this)].unlock(); }
759 void unlock_vertex_mutex(size_t vid) { m_vertex_mutex[vid].unlock(); }
760
761protected:
762 void resize_mutex(size_t v) { m_vertex_mutex.grow_to_at_least(v); }
763
764public:
765 tbb::enumerable_thread_specific<std::vector<size_t>> mutex_release_stack;
766
767 int release_vertex_mutex_in_stack();
775 bool try_set_vertex_mutex_two_ring(const Tuple& v, int threadid);
784 bool try_set_edge_mutex_two_ring(const Tuple& e, int threadid);
792 bool try_set_vertex_mutex_one_ring(const Tuple& v, int threadid);
800 bool try_set_face_mutex_one_ring(const Tuple& f, int threadid);
801
806 void for_each_face(const std::function<void(const Tuple&)>&);
811 void for_each_edge(const std::function<void(const Tuple&)>&);
816 void for_each_vertex(const std::function<void(const Tuple&)>&);
817 int NUM_THREADS = 0;
818};
819
820} // namespace wmtk
Definition TriMesh.h:152
Definition TriMesh.h:224
bool m_is_removed
is the triangle removed
Definition TriMesh.h:235
int find(size_t v_id) const
Definition TriMesh.h:259
size_t hash
the hash is changed every time there is an operation that influences the triangle
Definition TriMesh.h:241
std::array< size_t, 3 > m_indices
incident vertices of a given triangle
Definition TriMesh.h:230
Definition TriMesh.h:32
size_t eid(const TriMesh &m) const
Definition TriMesh.cpp:27
size_t fid(const TriMesh &) const
Definition TriMesh.h:80
Tuple switch_vertex(const TriMesh &m) const
Definition TriMesh.cpp:78
bool is_valid(const TriMesh &m) const
check if a Tuple is valid
Definition TriMesh.cpp:233
Tuple switch_edge(const TriMesh &m) const
Definition TriMesh.cpp:107
std::array< Tuple, 3 > oriented_tri_vertices(const TriMesh &m) const
std::optional< Tuple > switch_face(const TriMesh &m) const
Definition TriMesh.cpp:134
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
Definition TriMesh.h:193
std::vector< size_t > m_conn_tris
incident triangles of a given vertex
Definition TriMesh.h:199
bool m_is_removed
is the vertex removed
Definition TriMesh.h:204
Definition TriMesh.h:722
Definition TriMesh.h:28
virtual bool split_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge split.
Definition TriMesh.h:388
std::array< size_t, 3 > oriented_tri_vids(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1268
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:1159
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:684
void release_protect_attributes()
End the modification phase.
Definition TriMesh.h:701
size_t get_valence_for_vertex(const Tuple &t) const
Count the number of the one ring tris for a vertex.
Definition TriMesh.h:601
std::vector< Tuple > get_vertices() const
Definition TriMesh.cpp:1326
size_t get_next_empty_slot_t()
Get the next avaiblie global index for the triangle.
Definition TriMesh.cpp:1530
size_t get_next_empty_slot_v()
Get the next avaiblie global index for the vertex.
Definition TriMesh.cpp:1553
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:721
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:1576
bool try_set_face_mutex_one_ring(const Tuple &f, int threadid)
try lock the one-ring neighboring triangles' incident vertices.
Definition TriMesh.cpp:1811
void for_each_vertex(const std::function< void(const Tuple &)> &)
perform the given function for each vertex
Definition TriMesh.cpp:1861
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideras after an edge smooth.
Definition TriMesh.h:435
virtual bool invariants(const std::vector< Tuple > &)
User specified invariants that can't be violated.
Definition TriMesh.h:376
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge collapse.
Definition TriMesh.h:407
Tuple tuple_from_edge(size_t fid, size_t local_eid) const
Definition TriMesh.h:680
Tuple switch_edge(const Tuple &t) const
a duplicate of Tuple::switch_edge funciton
Definition TriMesh.h:476
virtual bool split_face_after(const Tuple &t)
User specified modifications and desideratas after a face split.
Definition TriMesh.h:448
bool split_face(const Tuple &t, std::vector< Tuple > &new_t)
Split a face in 3 faces.
Definition TriMesh.cpp:983
void rollback_protected_attributes()
rollback the attributes that are modified if any condition failed
Definition TriMesh.h:711
bool split_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:312
bool try_set_vertex_mutex_one_ring(const Tuple &v, int threadid)
get the lock for one ring neighboring triangles' incident vertices
Definition TriMesh.cpp:1786
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideras after an edge swap.
Definition TriMesh.h:413
bool try_set_vertex_mutex_two_ring(const Tuple &v, int threadid)
try lock the two-ring neighboring triangles' incident vertices
Definition TriMesh.cpp:1703
bool swap_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:891
Tuple tuple_from_tri(size_t fid) const
Definition TriMesh.h:656
void init(size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris)
Definition TriMesh.cpp:1286
size_t vert_capacity() const
get the current largest global vid
Definition TriMesh.h:462
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:1190
std::vector< Tuple > get_faces() const
Definition TriMesh.cpp:1358
bool check_mesh_connectivity_validity() const
verify the connectivity validity of the mesh
Definition TriMesh.cpp:271
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:1390
void consolidate_mesh()
removing the elements that are removed
Definition TriMesh.cpp:1094
bool try_set_edge_mutex_two_ring(const Tuple &e, int threadid)
try lock the two-ring neighboring triangles' incident vertices for the two ends of an edge
Definition TriMesh.cpp:1728
std::array< Tuple, 3 > oriented_tri_vertices(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1255
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for an edge smooth.
Definition TriMesh.h:429
size_t tri_capacity() const
get the current largest global fid
Definition TriMesh.h:456
void start_protect_attributes()
Start the phase where the attributes that will be modified can be recorded.
Definition TriMesh.h:691
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split.
Definition TriMesh.h:442
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split.
Definition TriMesh.h:382
std::optional< Tuple > switch_face(const Tuple &t) const
a duplicate of Tuple::switch_face funciton
Definition TriMesh.h:481
bool is_boundary_edge(const TriMesh::Tuple &t) const
check if edge that's represented by a Tuple is at the boundary of the mesh
Definition TriMesh.h:504
void for_each_edge(const std::function< void(const Tuple &)> &)
perform the given function for each edge
Definition TriMesh.cpp:1841
Tuple tuple_from_vertex(size_t vid) const
Definition TriMesh.h:668
bool check_link_condition(const Tuple &t) const
prerequisite for collapse
Definition TriMesh.cpp:1597
bool smooth_vertex(const Tuple &t)
Definition TriMesh.cpp:971
std::vector< Tuple > get_edges() const
Definition TriMesh.cpp:1374
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:397
Tuple switch_vertex(const Tuple &t) const
a duplicate of Tuple::switch_vertex funciton
Definition TriMesh.h:472
virtual bool collapse_edge(const Tuple &t, std::vector< Tuple > &new_t)
Definition TriMesh.cpp:618
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:511
std::vector< Tuple > get_one_ring_tris_for_vertex(const Tuple &t) const
Get the one ring tris for a vertex.
Definition TriMesh.cpp:1174
bool check_edge_manifold() const
verify the edge manifoldness of the mesh
Definition TriMesh.cpp:293
void for_each_face(const std::function< void(const Tuple &)> &)
perform the given function for each face
Definition TriMesh.cpp:1877