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 simplex::Face simplex_from_face(const size_t fid) const;
330
331 Tuple tuple_from_simplex(const simplex::Face& s) const;
332 // Tuple tuple_from_simplex(const simplex::Edge& s) const;
333
334 simplex::RawSimplexCollection simplex_incident_triangles(const simplex::Vertex& v) const;
335 simplex::RawSimplexCollection simplex_incident_triangles(const simplex::Edge& e) const;
336 simplex::RawSimplexCollection simplex_link_vertices(const simplex::Vertex& v) const;
337 simplex::RawSimplexCollection simplex_link_vertices(const simplex::Edge& e) const;
338 simplex::RawSimplexCollection simplex_link_edges(const simplex::Vertex& v) const;
339
340 template <typename T>
341 using vector = tbb::concurrent_vector<T>;
342
343public:
344 AbstractAttributeContainer* p_vertex_attrs = nullptr;
345 AbstractAttributeContainer* p_edge_attrs = nullptr;
346 AbstractAttributeContainer* p_face_attrs = nullptr;
347
348private:
349 vector<VertexConnectivity> m_vertex_connectivity;
350 vector<TriangleConnectivity> m_tri_connectivity;
351 std::atomic_long current_vert_size;
352 std::atomic_long current_tri_size;
353 tbb::spin_mutex vertex_connectivity_lock;
354 tbb::spin_mutex tri_connectivity_lock;
355 bool vertex_connectivity_synchronizing_flag = false;
356 bool tri_connectivity_synchronizing_flag = false;
357 int MAX_THREADS = 128;
363 size_t get_next_empty_slot_t();
369 size_t get_next_empty_slot_v();
370
371public:
377 virtual bool invariants(const std::vector<Tuple>&) { return true; }
383 virtual bool split_edge_before(const Tuple& t) { return true; }
389 virtual bool split_edge_after(const Tuple& t) { return true; }
390
398 virtual bool collapse_edge_before(const Tuple& t)
399 {
400 if (check_link_condition(t)) return true;
401 return false;
402 }
408 virtual bool collapse_edge_after(const Tuple& t) { return true; }
414 virtual bool swap_edge_after(const Tuple& t) { return true; }
423 virtual bool swap_edge_before(const Tuple& t);
430 virtual bool smooth_before(const Tuple& t) { return true; }
436 virtual bool smooth_after(const Tuple& t) { return true; }
437
443 virtual bool split_face_before(const Tuple& t) { return true; }
449 virtual bool split_face_after(const Tuple& t) { return true; }
450
451public:
457 size_t tri_capacity() const { return current_tri_size; }
463 size_t vert_capacity() const { return current_vert_size; }
469 void consolidate_mesh();
473 Tuple switch_vertex(const Tuple& t) const { return t.switch_vertex(*this); }
477 Tuple switch_edge(const Tuple& t) const { return t.switch_edge(*this); }
482 std::optional<Tuple> switch_face(const Tuple& t) const { return t.switch_face(*this); }
483
489 bool check_link_condition(const Tuple& t) const;
498 bool check_edge_manifold() const;
499
505 bool is_boundary_edge(const TriMesh::Tuple& t) const { return t.switch_faces(*this).empty(); }
506
513 {
515 for (auto e : ve)
516 if (is_boundary_edge(e)) return true;
517 return false;
518 }
519
528 bool split_edge(const Tuple& t, std::vector<Tuple>& new_t);
529
539 virtual bool collapse_edge(const Tuple& t, std::vector<Tuple>& new_t);
540
545 const Tuple& loc0,
546 std::vector<Tuple>& new_tris,
547 Tuple& return_t,
548 size_t& new_vid,
549 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
550 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
551 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
552 std::vector<size_t>& n12_intersect_fids);
553
559 size_t& new_vid,
560 std::vector<std::pair<size_t, TriangleConnectivity>>& old_tris,
561 std::vector<std::pair<size_t, VertexConnectivity>>& old_vertices,
562 std::vector<std::pair<size_t, size_t>>& same_edge_vid_fid,
563 std::vector<size_t>& n12_intersect_fids);
564
565
575 bool swap_edge(const Tuple& t, std::vector<Tuple>& new_t);
576
584 bool smooth_vertex(const Tuple& t);
585
594 bool split_face(const Tuple& t, std::vector<Tuple>& new_t);
595
602 size_t get_valence_for_vertex(const Tuple& t) const
603 {
604 return m_vertex_connectivity[t.vid(*this)].m_conn_tris.size();
605 }
606
613 std::vector<Tuple> get_one_ring_tris_for_vertex(const Tuple& t) const;
614 const std::vector<size_t>& get_one_ring_fids_for_vertex(const Tuple& t) const;
615 const std::vector<size_t>& get_one_ring_fids_for_vertex(const size_t vid) const;
622 std::vector<size_t> get_one_ring_vids_for_vertex_duplicate(const size_t& t) const;
623
624 std::vector<size_t> get_incident_fids_for_edge(const Tuple& t) const;
625 std::vector<size_t> get_incident_fids_for_edge(const size_t vid0, const size_t vid1) const;
626
636 std::vector<Tuple> get_one_ring_edges_for_vertex(const Tuple& t) const;
637 std::vector<Tuple> get_one_ring_edges_for_vertex(const size_t vid) const;
638
645 std::array<Tuple, 3> oriented_tri_vertices(const Tuple& t) const;
646
653 std::array<size_t, 3> oriented_tri_vids(const Tuple& t) const;
654 std::array<size_t, 3> oriented_tri_vids(const size_t i) const;
655
656 std::array<Tuple, 2> get_edge_vertices(const Tuple& t) const;
657 std::array<size_t, 2> get_edge_vids(const Tuple& t) const;
658
666 Tuple tuple_from_tri(size_t fid) const
667 {
668 if (fid >= m_tri_connectivity.size() || m_tri_connectivity[fid].m_is_removed)
669 return Tuple();
670 auto vid = m_tri_connectivity[fid][0];
671 return Tuple(vid, 1, fid, *this);
672 }
678 Tuple tuple_from_vertex(size_t vid) const
679 {
680 auto fid = m_vertex_connectivity[vid][0];
681 auto eid = m_tri_connectivity[fid].find((int)vid);
682 return Tuple(vid, (eid + 1) % 3, fid, *this);
683 }
690 Tuple tuple_from_edge(size_t fid, size_t local_eid) const
691 {
692 auto vid = m_tri_connectivity[fid][(local_eid + 1) % 3];
693 return Tuple(vid, local_eid, fid, *this);
694 }
695
696 std::tuple<Tuple, size_t> tuple_from_edge(const std::array<size_t, 2>& vids) const;
697
698public:
704 {
705 if (p_vertex_attrs) p_vertex_attrs->begin_protect();
706 if (p_edge_attrs) p_edge_attrs->begin_protect();
707 if (p_face_attrs) p_face_attrs->begin_protect();
708 }
714 {
715 if (p_vertex_attrs) p_vertex_attrs->end_protect();
716 if (p_edge_attrs) p_edge_attrs->end_protect();
717 if (p_face_attrs) p_face_attrs->end_protect();
718 }
724 {
725 if (p_vertex_attrs) p_vertex_attrs->rollback();
726 if (p_edge_attrs) p_edge_attrs->rollback();
727 if (p_face_attrs) p_face_attrs->rollback();
728 }
729
730 // Moved code from concurrent TriMesh
731
732public:
734 {
735 tbb::spin_mutex mutex;
736 int owner = std::numeric_limits<int>::max();
737
738 public:
739 bool trylock() { return mutex.try_lock(); }
740
741 void unlock()
742 {
743 reset_owner();
744 mutex.unlock();
745 }
746
747 int get_owner() { return owner; }
748
749 void set_owner(int n) { owner = n; }
750
751 void reset_owner() { owner = std::numeric_limits<int>::max(); }
752 };
753
754private:
755 tbb::concurrent_vector<VertexMutex> m_vertex_mutex;
756
757 bool try_set_vertex_mutex(const Tuple& v, int threadid)
758 {
759 bool got = m_vertex_mutex[v.vid(*this)].trylock();
760 if (got) m_vertex_mutex[v.vid(*this)].set_owner(threadid);
761 return got;
762 }
763 bool try_set_vertex_mutex(size_t vid, int threadid)
764 {
765 bool got = m_vertex_mutex[vid].trylock();
766 if (got) m_vertex_mutex[vid].set_owner(threadid);
767 return got;
768 }
769
770 void unlock_vertex_mutex(const Tuple& v) { m_vertex_mutex[v.vid(*this)].unlock(); }
771 void unlock_vertex_mutex(size_t vid) { m_vertex_mutex[vid].unlock(); }
772
773protected:
774 void resize_mutex(size_t v) { m_vertex_mutex.grow_to_at_least(v); }
775
776public:
777 tbb::enumerable_thread_specific<std::vector<size_t>> mutex_release_stack;
778
779 int release_vertex_mutex_in_stack();
787 bool try_set_vertex_mutex_two_ring(const Tuple& v, int threadid);
796 bool try_set_edge_mutex_two_ring(const Tuple& e, int threadid);
804 bool try_set_vertex_mutex_one_ring(const Tuple& v, int threadid);
812 bool try_set_face_mutex_one_ring(const Tuple& f, int threadid);
813
818 void for_each_face(const std::function<void(const Tuple&)>&);
823 void for_each_edge(const std::function<void(const Tuple&)>&);
828 void for_each_vertex(const std::function<void(const Tuple&)>&);
829 int NUM_THREADS = 0;
830};
831
832} // 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:734
Definition TriMesh.h:28
virtual bool split_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge split.
Definition TriMesh.h:389
std::array< size_t, 3 > oriented_tri_vids(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1296
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:713
size_t get_valence_for_vertex(const Tuple &t) const
Count the number of the one ring tris for a vertex.
Definition TriMesh.h:602
std::vector< Tuple > get_vertices() const
Definition TriMesh.cpp:1399
size_t get_next_empty_slot_t()
Get the next avaiblie global index for the triangle.
Definition TriMesh.cpp:1608
size_t get_next_empty_slot_v()
Get the next avaiblie global index for the vertex.
Definition TriMesh.cpp:1635
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:1658
bool try_set_face_mutex_one_ring(const Tuple &f, int threadid)
try lock the one-ring neighboring triangles' incident vertices.
Definition TriMesh.cpp:1893
void for_each_vertex(const std::function< void(const Tuple &)> &)
perform the given function for each vertex
Definition TriMesh.cpp:1943
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideras after an edge smooth.
Definition TriMesh.h:436
virtual bool invariants(const std::vector< Tuple > &)
User specified invariants that can't be violated.
Definition TriMesh.h:377
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas after an edge collapse.
Definition TriMesh.h:408
Tuple tuple_from_edge(size_t fid, size_t local_eid) const
Definition TriMesh.h:690
Tuple switch_edge(const Tuple &t) const
a duplicate of Tuple::switch_edge funciton
Definition TriMesh.h:477
std::vector< Tuple > get_one_ring_tris_for_vertex(const Tuple &t) const
Get the one ring tris for a vertex.
Definition TriMesh.cpp:1186
virtual bool split_face_after(const Tuple &t)
User specified modifications and desideratas after a face split.
Definition TriMesh.h:449
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:723
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:1868
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideras after an edge swap.
Definition TriMesh.h:414
bool try_set_vertex_mutex_two_ring(const Tuple &v, int threadid)
try lock the two-ring neighboring triangles' incident vertices
Definition TriMesh.cpp:1785
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:666
void init(size_t n_vertices, const std::vector< std::array< size_t, 3 > > &tris)
Definition TriMesh.cpp:1359
size_t vert_capacity() const
get the current largest global vid
Definition TriMesh.h:463
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:1211
std::vector< Tuple > get_faces() const
Definition TriMesh.cpp:1431
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:1463
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:1810
std::array< Tuple, 3 > oriented_tri_vertices(const Tuple &t) const
Get the incident vertices for a triangle.
Definition TriMesh.cpp:1283
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for an edge smooth.
Definition TriMesh.h:430
size_t tri_capacity() const
get the current largest global fid
Definition TriMesh.h:457
void start_protect_attributes()
Start the phase where the attributes that will be modified can be recorded.
Definition TriMesh.h:703
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split.
Definition TriMesh.h:443
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split.
Definition TriMesh.h:383
std::optional< Tuple > switch_face(const Tuple &t) const
a duplicate of Tuple::switch_face funciton
Definition TriMesh.h:482
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:505
void for_each_edge(const std::function< void(const Tuple &)> &)
perform the given function for each edge
Definition TriMesh.cpp:1923
Tuple tuple_from_vertex(size_t vid) const
Definition TriMesh.h:678
bool check_link_condition(const Tuple &t) const
prerequisite for collapse
Definition TriMesh.cpp:1679
bool smooth_vertex(const Tuple &t)
Definition TriMesh.cpp:971
std::vector< Tuple > get_edges() const
Definition TriMesh.cpp:1447
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:398
Tuple switch_vertex(const Tuple &t) const
a duplicate of Tuple::switch_vertex funciton
Definition TriMesh.h:473
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:512
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:1959