Wildmeshing Toolkit
Loading...
Searching...
No Matches
TetMesh.h
1#pragma once
2
3#include <wmtk/utils/VectorUtils.h>
4#include <wmtk/AttributeCollection.hpp>
5#include <wmtk/OperationDryRun.hpp>
6#include <wmtk/SlotPool.hpp>
7#include <wmtk/Types.hpp>
8#include <wmtk/simplex/Simplex.hpp>
9#include <wmtk/simplex/SimplexCollection.hpp>
10#include <wmtk/threading/enumerable_thread_specific.hpp>
11#include <wmtk/threading/vertex_mutex.hpp>
12#include <wmtk/utils/Logger.hpp>
13
14#include <Eigen/Core>
15
16#include <array>
17#include <atomic>
18#include <cassert>
19#include <cmath>
20#include <cstdint>
21#include <functional>
22#include <limits>
23#include <map>
24#include <memory>
25#include <optional>
26#include <vector>
27
28#include <wmtk/history/Fwd.hpp>
29
30namespace wmtk {
32{
33protected:
40 static constexpr std::array<std::array<int, 2>, 6> m_local_edges = {
41 {{{0, 1}}, {{1, 2}}, {{0, 2}}, {{0, 3}}, {{1, 3}}, {{2, 3}}}};
42
43private:
44 static constexpr std::array<int, 4> m_map_vertex2edge = {{0, 0, 1, 3}};
45 static constexpr std::array<int, 4> m_map_vertex2oppo_face = {{3, 1, 2, 0}};
46 static constexpr std::array<int, 6> m_map_edge2face = {{0, 0, 0, 1, 2, 1}};
47 static constexpr std::array<std::array<int, 3>, 4> m_local_faces = {
48 {{{0, 1, 2}}, {{0, 2, 3}}, {{0, 1, 3}}, {{1, 2, 3}}}}; // sorted local vids
49 static constexpr std::array<std::array<int, 3>, 4> m_local_edges_in_a_face = {
50 {{{0, 1, 2}}, {{2, 5, 3}}, {{3, 4, 0}}, {{5, 1, 4}}}};
51
52public:
53 // Cell Tuple Navigator
59 class Tuple
60 {
61 size_t m_global_vid = std::numeric_limits<size_t>::max();
62 size_t m_local_eid = std::numeric_limits<size_t>::max();
63 size_t m_local_fid = std::numeric_limits<size_t>::max();
64 size_t m_global_tid = std::numeric_limits<size_t>::max();
65
66 size_t m_hash = 0;
67
68 private:
78 Tuple(const TetMesh& m, size_t vid, size_t local_eid, size_t local_fid, size_t tid);
79
80 public:
81 Tuple() {}
82
83 friend TetMesh;
84
92 bool is_valid(const TetMesh& m) const;
95 bool is_valid_unlocked(const TetMesh& m) const { return is_valid(m); }
102 bool is_boundary_edge(const TetMesh& m) const;
109 bool is_boundary_face(const TetMesh& m) const;
110
115 void print_info() const;
116
122 void print_info(const TetMesh& m) const;
123
129 size_t vid(const TetMesh& m) const;
130
139 size_t eid(const TetMesh& m) const;
140
148 size_t fid(const TetMesh& m) const;
149
156 size_t tid(const TetMesh& m) const;
157
164 Tuple switch_vertex(const TetMesh& m) const;
171 Tuple switch_edge(const TetMesh& m) const;
178 Tuple switch_face(const TetMesh& m) const;
179
187 std::optional<Tuple> switch_tetrahedron(const TetMesh& m) const;
188 std::optional<Tuple> switch_tetrahedron_slow(const TetMesh& m) const;
189
190
192
195 void check_validity(const TetMesh& m) const;
196 friend bool operator==(const Tuple& a, const Tuple& t)
197 {
198 return (
199 std::tie(a.m_global_vid, a.m_local_eid, a.m_local_fid, a.m_global_tid, a.m_hash) ==
200 std::tie(t.m_global_vid, t.m_local_eid, t.m_local_fid, t.m_global_tid, t.m_hash));
201 }
202 friend bool operator<(const Tuple& a, const Tuple& t)
203 {
204 return (
205 std::tie(a.m_global_vid, a.m_local_eid, a.m_local_fid, a.m_global_tid, a.m_hash) <
206 std::tie(t.m_global_vid, t.m_local_eid, t.m_local_fid, t.m_global_tid, t.m_hash));
207 }
208 };
209
215 {
216 const TetMesh& m_mesh;
217 Tuple m_tuple;
218
219 public:
220 SmartTuple(const TetMesh& mesh, const Tuple& t)
221 : m_mesh(mesh)
222 , m_tuple(t)
223 {}
224
225 const Tuple& tuple() { return m_tuple; }
226 const TetMesh& mesh() { return m_mesh; }
227
228 SmartTuple& operator=(const SmartTuple& t)
229 {
230 m_tuple = t.m_tuple;
231 return *this;
232 }
233
234 bool is_valid() const { return m_tuple.is_valid(m_mesh); }
235 bool is_boundary_edge() const { return m_tuple.is_boundary_edge(m_mesh); }
236 bool is_boundary_face() const { return m_tuple.is_boundary_face(m_mesh); }
237 size_t vid() const { return m_tuple.vid(m_mesh); }
238 size_t eid() const { return m_tuple.eid(m_mesh); }
239 size_t fid() const { return m_tuple.fid(m_mesh); }
240 size_t tid() const { return m_tuple.tid(m_mesh); }
241 SmartTuple switch_vertex() const { return {m_mesh, m_tuple.switch_vertex(m_mesh)}; }
242 SmartTuple switch_edge() const { return {m_mesh, m_tuple.switch_edge(m_mesh)}; }
243 SmartTuple switch_face() const { return {m_mesh, m_tuple.switch_face(m_mesh)}; }
244 std::optional<SmartTuple> switch_tetrahedron() const
245 {
246 const std::optional<Tuple> t = m_tuple.switch_tetrahedron(m_mesh);
247 if (t) {
248 return std::optional<SmartTuple>({m_mesh, t.value()});
249 }
250 return {};
251 }
252 void check_validity() const { return m_tuple.check_validity(m_mesh); }
253 };
254
261 {
262 public:
263 std::vector<size_t> m_conn_tets; // todo: always keep it sorted
264 bool m_is_removed = false;
265
266 size_t& operator[](const size_t index)
267 {
268 assert(index < m_conn_tets.size());
269 return m_conn_tets[index];
270 }
271
272 size_t operator[](const size_t index) const
273 {
274 assert(index < m_conn_tets.size());
275 return m_conn_tets[index];
276 }
277
278 friend bool operator==(const VertexConnectivity& l, const VertexConnectivity& r)
279 {
280 return std::tie(l.m_conn_tets, l.m_is_removed) ==
281 std::tie(r.m_conn_tets, r.m_is_removed); // keep the same order
282 }
283
284 void print_info() {}
285 };
286
292 {
293 public:
294 std::array<size_t, 4> m_indices;
295 bool m_is_removed = false;
296
307 uint32_t hash = 0;
308
309 size_t& operator[](size_t index)
310 {
311 assert(index < 4);
312 return m_indices[index];
313 }
314
315 size_t operator[](size_t index) const
316 {
317 assert(index < 4);
318 return m_indices[index];
319 }
320
321 int find(size_t v_id) const
322 {
323 for (int j = 0; j < 4; j++) {
324 if (v_id == m_indices[j]) return j;
325 }
326 return -1;
327 }
328
329 int find_local_edge(size_t v1_id, size_t v2_id) const
330 {
331 std::array<int, 2> e;
332 for (int j = 0; j < 4; j++) {
333 if (v1_id == m_indices[j])
334 e[0] = j;
335 else if (v2_id == m_indices[j])
336 e[1] = j;
337 }
338 if (e[0] > e[1]) std::swap(e[0], e[1]);
339 int i =
340 std::find(m_local_edges.begin(), m_local_edges.end(), e) - m_local_edges.begin();
341 if (i >= m_local_edges.size()) return -1;
342 return i;
343 }
344
345 int find_local_face(size_t v1_id, size_t v2_id, size_t v3_id) const
346 {
347 std::array<int, 3> f;
348 for (int j = 0; j < 4; j++) {
349 if (v1_id == m_indices[j])
350 f[0] = j;
351 else if (v2_id == m_indices[j])
352 f[1] = j;
353 else if (v3_id == m_indices[j])
354 f[2] = j;
355 }
356 std::sort(f.begin(), f.end());
357 int i =
358 std::find(m_local_faces.begin(), m_local_faces.end(), f) - m_local_faces.begin();
359 if (i >= m_local_edges.size()) return -1;
360 return i;
361 }
362
363 friend bool operator==(const TetrahedronConnectivity& l, const TetrahedronConnectivity& r)
364 {
365 return std::tie(l.m_indices, l.m_is_removed, l.hash) ==
366 std::tie(r.m_indices, r.m_is_removed, r.hash); // keep the same order
367 }
368
369 void print_info() {}
370 };
371
372 TetMesh();
373 virtual ~TetMesh() = default;
379 size_t vert_capacity() const { return m_vertex_connectivity.live(); }
385 size_t tet_capacity() const { return m_tet_connectivity.live(); }
386
396 static constexpr int EDGES_PER_CELL = 6;
397 static constexpr int FACES_PER_CELL = 4;
398 size_t cell_capacity() const { return tet_capacity(); }
399 size_t cell_storage_capacity() const { return m_tet_connectivity.capacity(); }
400 Tuple tuple_from_cell(size_t cid) const { return tuple_from_tet(cid); }
407 size_t vertex_size() const
408 {
409 int cnt = 0;
410 for (auto i = 0; i < vert_capacity(); i++) {
411 if (!m_vertex_connectivity[i].m_is_removed) cnt++;
412 }
413 return cnt;
414 }
419 size_t tet_size() const
420 {
421 int cnt = 0;
422 for (auto i = 0; i < tet_capacity(); i++) {
423 if (!m_tet_connectivity[i].m_is_removed) cnt++;
424 }
425 return cnt;
426 }
436 void init(size_t n_vertices, const std::vector<std::array<size_t, 4>>& tets);
437 void init_with_isolated_vertices(
438 size_t n_vertices,
439 const std::vector<std::array<size_t, 4>>& tets);
440
446 void init(const MatrixXi& T);
447
455 bool split_edge(const Tuple& t, std::vector<Tuple>& new_tets);
463 virtual bool collapse_edge(const Tuple& t, std::vector<Tuple>& new_tets);
464
465 bool link_condition(const Tuple& t);
466
485 const Tuple& loc0,
486 size_t& v1_id,
487 Tuple& new_loc,
488 std::map<size_t, wmtk::TetMesh::VertexConnectivity>& rollback_vert_conn,
489 std::vector<size_t>& n1_t_ids_copy,
490 std::vector<size_t>& new_tet_id,
491 std::vector<TetrahedronConnectivity>& old_tets);
492
501 bool collapse_edge_check_topology(const std::vector<size_t>& new_tet_id);
502
516 size_t& v1_id,
517 std::map<size_t, wmtk::TetMesh::VertexConnectivity>& rollback_vert_conn,
518 std::vector<size_t>& n1_t_ids,
519 std::vector<size_t>& new_tet_id,
520 std::vector<TetrahedronConnectivity>& old_tets);
521
530 bool swap_edge_56(const Tuple& t, std::vector<Tuple>& new_tets);
539 bool swap_edge_44(const Tuple& t, std::vector<Tuple>& new_tets);
548 bool swap_edge(const Tuple& t, std::vector<Tuple>& new_tets);
555 bool swap_face(const Tuple& t, std::vector<Tuple>& new_tets);
563 bool smooth_vertex(const Tuple& t);
579
590 bool split_tet(const Tuple& t, std::vector<Tuple>& new_tets);
591
604 bool split_face(const Tuple& t, std::vector<Tuple>& new_tets);
605
614 const std::vector<Tuple>& intersected_tets,
615 const std::vector<Tuple>& intersected_edges,
616 std::vector<size_t>& new_edge_vids,
617 std::vector<size_t>& new_center_vids,
618 std::vector<std::array<size_t, 4>>& center_split_tets);
619
630 bool insert_point(const Tuple& t, std::vector<Tuple>& new_tets);
631 virtual bool insert_point_before(const Tuple& t) { return true; };
632 virtual bool insert_point_after(std::vector<Tuple>& new_tets) { return true; };
638 void consolidate_mesh();
639
652 std::shared_ptr<history::TrackedSurfaceRecorder> start_surface_history(
653 std::function<Eigen::Vector3d(size_t)> position);
659 size_t resync_surface_history();
667 std::shared_ptr<history::VolumeRecorder> start_volume_history(
668 std::function<Eigen::Vector3d(size_t)> position);
670 void stop_volume_history();
673 virtual std::vector<int64_t> tet_tags(size_t tid) const { return {}; }
675 std::vector<std::array<size_t, 3>> tracked_faces() const;
678 virtual bool is_tracked_face(size_t tid, int j) const { return false; }
682 virtual std::vector<std::array<size_t, 2>> tracked_feature_edges() const { return {}; }
687 virtual std::array<size_t, 3> orient_tracked_face(
688 const std::array<size_t, 3>& f,
689 const std::vector<size_t>& tets) const
690 {
691 return f;
692 }
694 std::array<size_t, 3> orient_tracked_face(const std::array<size_t, 3>& f) const
695 {
696 return orient_tracked_face(f, tets_of_face(f));
697 }
703 std::array<size_t, 3> face_out_of(size_t tid, const std::array<size_t, 3>& face) const;
704
705protected:
708 std::vector<std::array<size_t, 3>> tracked_faces_around(const std::vector<size_t>& vs, bool all)
709 const;
712 {
713 std::array<size_t, 3> face;
714 size_t fid;
715 std::vector<size_t> tets;
716 };
724 std::vector<VertexFace> faces_at_vertex(size_t v) const;
726 size_t face_id_in(const std::array<size_t, 3>& f, size_t tid) const;
727
739 virtual bool checks_tracked_surface() const { return false; }
740 virtual void tracked_surface_before(const std::vector<size_t>& vs, bool all) {}
741 virtual bool tracked_surface_after(const std::vector<size_t>& vs, bool all) { return true; }
742
743public:
745 std::vector<size_t> tets_of_face(const std::array<size_t, 3>& f) const;
746
752 std::vector<Tuple> get_edges() const;
758 std::vector<Tuple> get_faces() const;
764 std::vector<Tuple> get_vertices() const;
770 std::vector<Tuple> get_tets() const;
775 // virtual void for_each_edge(const std::function<void(const TetMesh::Tuple&)>&);
776
777 // TODO: make this concurrent
782 virtual void for_each_face(const std::function<void(const TetMesh::Tuple&)>&);
783 // /**
784 // * @brief looping through all the unique vertices and perform the given function
785 // *
786 // */
787 // virtual void for_each_vertex(const std::function<void(const TetMesh::Tuple&)>&);
788 // /**
789 // * @brief looping through all the unique tet and perform the given function
790 // *
791 // */
792 // virtual void for_each_tetra(const std::function<void(const TetMesh::Tuple&)>&);
793
794public:
795 template <typename T>
796 using vector = std::vector<T>;
797
798public:
799 AbstractAttributeContainer* p_vertex_attrs = nullptr;
800 AbstractAttributeContainer* p_edge_attrs = nullptr;
801 AbstractAttributeContainer* p_face_attrs = nullptr;
802 AbstractAttributeContainer* p_tet_attrs = nullptr;
803 // AbstractAttributeContainer vertex_attrs, edge_attrs, face_attrs, tet_attrs;
804
805
806public:
814 void set_preallocation_factor(double factor)
815 {
816 if (factor >= 1.0) m_preallocation_factor = factor;
817 }
818 double preallocation_factor() const { return m_preallocation_factor; }
819
820 // Atomically reserve `n` contiguous fresh tet/vertex slots. Returns the first
821 // index of the block, or -1 if that would exceed the preallocated capacity (the
822 // caller must then abort the operation before mutating any connectivity).
823
841 size_t tet_storage_capacity() const { return m_tet_connectivity.capacity(); }
842 size_t vert_storage_capacity() const { return m_vertex_connectivity.capacity(); }
845 bool slots_exhausted() const
846 {
847 return m_vertex_connectivity.refused() || m_tet_connectivity.refused();
848 }
849 void clear_slots_exhausted()
850 {
851 m_vertex_connectivity.clear_refused();
852 m_tet_connectivity.clear_refused();
853 }
854
855 size_t request_tet_slots(size_t n);
856 size_t request_vert_slots(size_t n);
857
879 size_t cell_slot_bound(const Tuple& t) const;
882 void reserve_free_slots(size_t cells, size_t verts);
885 virtual bool storage_grows_on_demand() const { return false; }
886
890 {
891 size_t cells = 0;
892 size_t verts = 0;
893 };
894 static SlotUsage slot_usage_of_this_thread()
895 {
896 return {
899 }
902protected:
905 virtual void on_slot_storage_grown() {}
906
907public:
908 // Construction/insertion helpers (single-threaded ONLY): guarantee at least
909 // `extra` free tet/vertex slots beyond the current used count, growing the
910 // storage geometrically if necessary. Unlike request_*_slots these never fail;
911 // they are used by the (legacy, non-concurrent) triangle-insertion path where
912 // the mesh is being built rather than edited by concurrent operations.
913 void ensure_free_tet_capacity(size_t extra)
914 {
915 const size_t need = m_tet_connectivity.live() + extra;
916 if (m_tet_connectivity.capacity() >= need) return;
917 const size_t newcap = std::max(need, m_tet_connectivity.capacity() * 2 + 1);
918 m_tet_connectivity.resize(newcap);
919 if (p_tet_attrs) p_tet_attrs->resize(newcap);
920 if (p_face_attrs) p_face_attrs->resize(4 * newcap);
921 if (p_edge_attrs) p_edge_attrs->resize(6 * newcap);
922 }
923 void ensure_free_vert_capacity(size_t extra)
924 {
925 const size_t need = m_vertex_connectivity.live() + extra;
926 if (m_vertex_connectivity.capacity() >= need) return;
927 const size_t newcap = std::max(need, m_vertex_connectivity.capacity() * 2 + 1);
928 m_vertex_connectivity.resize(newcap);
929 resize_vertex_mutex(newcap);
930 if (p_vertex_attrs) p_vertex_attrs->resize(newcap);
931 }
932
933private:
934 // capacity to reserve for a live element count
935 size_t reserved_capacity(size_t live_count) const
936 {
937 const size_t floor = 64;
938 // A mesh that grows on demand only needs room for the passes not to grow at once.
939 const double factor = storage_grows_on_demand() ? 1.25 : m_preallocation_factor;
940 double c = std::ceil(factor * static_cast<double>(live_count));
941 size_t capacity = static_cast<size_t>(c);
942 if (capacity < live_count) capacity = live_count;
943 return capacity < floor ? floor : capacity;
944 }
945
946 // Stores the connectivity of the mesh
947 SlotPool<VertexConnectivity> m_vertex_connectivity;
948 SlotPool<TetrahedronConnectivity> m_tet_connectivity;
949
950 double m_preallocation_factor = 6.0;
951
952 int m_t_empty_slot = 0;
953 int m_v_empty_slot = 0;
954 size_t get_next_empty_slot_t();
955 size_t get_next_empty_slot_v();
956
957 // TODO: subdivide_tets function should not be in the TetMesh API.
958 void subdivide_tets(
959 const std::vector<size_t> t_ids,
960 const std::vector<bool>& mark_surface,
961 const std::map<std::array<size_t, 2>, size_t>& map_edge2vid,
962 std::map<std::array<size_t, 3>, std::vector<std::array<size_t, 5>>>& new_face_vids,
963 const std::vector<size_t>& new_vids,
964 std::vector<size_t>& new_tids,
965 std::vector<size_t>& new_center_vids,
966 std::vector<std::array<size_t, 4>>& center_split_tets);
967 void subdivide_a_tet(
968 size_t t_id,
969 const std::array<int, 6>& new_v_ids,
970 bool mark_surface,
971 std::map<std::array<size_t, 3>, std::vector<std::array<size_t, 5>>>& new_face_vids,
972 std::vector<size_t>& new_tids,
973 std::vector<size_t>& new_center_vids,
974 std::vector<std::array<size_t, 4>>& center_split_tets);
975
976public:
977 virtual bool invariants(const std::vector<Tuple>&) { return true; }
978
979 // ---- OPERATION ACCOUNTING (counting only) ----
980 // Every call into split_edge, collapse_edge, swap_edge, swap_edge_44, swap_edge_56 and
981 // swap_face reports `attempt` on entry and exactly ONE other event on the way out: `committed`,
982 // or the place that refused it. The application's hooks are two of those places (before_hook,
983 // after_hook); why a hook said no is the hook's own to count. So for each kind, attempt equals
984 // the sum of the other events, and a subclass that counts can check both that identity and a
985 // hook's refusals against the reasons the hook counted. Added because the refusals made here,
986 // below every hook, were visible only as a difference: on the deliverable cube at
987 // target_distance_rel 1e-2 / front_conv_rel 1e-4, 521142 of the 542123 edge swaps that
988 // passed every before-hook in turn 5 were refused inside this class with no reason recorded.
989 //
990 // The default does nothing and no site reads a count: the mesh behaves identically with or
991 // without an override.
992 enum class OpKind : int { split, collapse, swap_32, swap_44, swap_56, swap_face, COUNT };
993 enum class OpEvent : int {
994 attempt,
995 before_hook, // the application's *_before said no
996 link_condition, // collapse: the classical link condition (m_collapse_check_link_condition)
997 no_return_tet, // collapse: both probes for the return tuple hit a boundary face
998 duplicate_tet, // a new tet repeats an existing one (collapse manifold check, 4-4, 5-6)
999 topology, // collapse: m_collapse_check_topology found a face missing
1000 valence, // edge swap: the edge does not have this swap's number of tets around it
1001 boundary, // edge swap: the edge's ring of tets is open; face swap: a boundary face
1002 exists, // 3-2: the new face already exists; face swap: the new edge already exists
1003 no_case_allowed, // 4-4 / 5-6: every candidate was vetoed by *_accept_case
1004 no_better_case, // 4-4 / 5-6: no allowed candidate scored below the current cells
1005 out_of_slots, // the preallocated vertex or tet slots ran out
1006 after_hook, // the application's *_after said no, so the operation was rolled back
1007 invariants, // invariants() said no after the after-hook passed; rolled back
1008 committed,
1009 screened, // a dry run passed every check that precedes the change (see dry_run())
1010 COUNT
1011 };
1012 virtual void op_event(OpKind, OpEvent) const {}
1014 bool op_refused(const OpKind k, const OpEvent e) const
1015 {
1016 op_event(k, e);
1017 return false;
1018 }
1019
1021 static bool dry_run() { return operation_dry_run(); }
1023 bool op_screened(const OpKind k) const
1024 {
1025 op_event(k, OpEvent::screened);
1026 return true;
1027 }
1028
1029protected:
1030 virtual bool triangle_insertion_before(const std::vector<Tuple>& faces) { return true; }
1031 virtual bool triangle_insertion_after(const std::vector<std::vector<Tuple>>&) { return true; }
1032
1034 // Checks if the split should be performed or not (user controlled)
1041 virtual bool split_edge_before(const Tuple& t) { return true; } // check edge condition
1042 // This function computes the attributes for the added simplices
1043 // if it returns false then the operation is undone
1050 virtual bool split_edge_after(const Tuple& t) { return true; } // check tet condition
1051
1053 // Checks if the collapse should be performed or not (user controlled)
1061 virtual bool collapse_edge_before(const Tuple& t) { return true; }
1062 // If it returns false then the operation is undone (the tuple indexes a vertex and tet that
1063 // survived)
1070 virtual bool collapse_edge_after(const Tuple& t) { return true; }
1078 virtual bool swap_edge_44_before(const Tuple& t) { return true; }
1089 virtual double swap_edge_44_energy(
1090 const std::vector<std::array<size_t, 4>>& tets,
1091 const int op_case)
1092 {
1093 return -op_case;
1094 }
1101 virtual bool swap_edge_44_after(const Tuple& t) { return true; }
1114 virtual bool swap_edge_44_accept_case(const std::array<size_t, 2>& new_edge) { return true; }
1122 virtual bool swap_edge_56_before(const Tuple& t) { return true; }
1133 virtual double swap_edge_56_energy(
1134 const std::vector<std::array<size_t, 4>>& tets,
1135 const int op_case)
1136 {
1137 return -op_case;
1138 }
1145 virtual bool swap_edge_56_after(const Tuple& t) { return true; }
1158 virtual bool swap_edge_56_accept_case(const std::array<size_t, 3>& new_face) { return true; }
1166 virtual bool swap_edge_before(const Tuple& t) { return true; }
1173 virtual bool swap_edge_after(const Tuple& t) { return true; }
1181 virtual bool swap_face_before(const Tuple& t) { return true; }
1188 virtual bool swap_face_after(const Tuple& t) { return true; }
1195 virtual bool smooth_before(const Tuple& t) { return true; }
1202 virtual bool smooth_after(const Tuple& t) { return true; }
1203
1210 virtual bool split_face_before(const Tuple& t) { return true; }
1211
1219 virtual bool split_face_after(const Tuple& t) { return true; }
1220
1227 virtual bool split_tet_before(const Tuple& t) { return true; }
1228
1236 virtual bool split_tet_after(const Tuple& t) { return true; }
1237
1238 // virtual void resize_vertex_mutex(size_t v) {}
1239
1240public:
1247 Tuple tuple_from_edge(size_t tid, int local_eid) const;
1253 Tuple tuple_from_edge(const std::array<size_t, 2>& vids) const;
1254
1261 Tuple tuple_from_face(size_t tid, int local_fid) const;
1262
1268 std::tuple<Tuple, size_t> tuple_from_face(const std::array<size_t, 3>& vids) const;
1276 std::optional<std::tuple<Tuple, size_t>> try_tuple_from_face(
1277 const std::array<size_t, 3>& vids) const;
1278
1285 size_t lowest_common_tet(size_t v0_id, size_t v1_id, size_t v2_id) const;
1286
1293 size_t vertex_valence(const size_t vid) const
1294 {
1295 return m_vertex_connectivity[vid].m_conn_tets.size();
1296 }
1297 std::tuple<Tuple, size_t> tuple_from_face(const simplex::Face& f) const;
1298
1304 Tuple tuple_from_vertex(size_t vid) const;
1305
1311 Tuple tuple_from_tet(size_t tid) const;
1312
1317 Tuple tuple_from_vids(size_t vid0, size_t vid1, size_t vid2, size_t vid3) const;
1318
1319 simplex::Tet simplex_from_tet(const Tuple& t) const;
1320 simplex::Tet simplex_from_tet(const size_t tid) const;
1321 simplex::Face simplex_from_face(const Tuple& t) const;
1322 simplex::Edge simplex_from_edge(const Tuple& t) const;
1323
1324
1328 Tuple switch_vertex(const Tuple& t) const
1329 {
1330 auto loc = t.switch_vertex(*this);
1332 return loc;
1333 }
1337 Tuple switch_edge(const Tuple& t) const
1338 {
1339 auto loc = t.switch_edge(*this);
1341 return loc;
1342 }
1346 Tuple switch_face(const Tuple& t) const
1347 {
1348 auto loc = t.switch_face(*this);
1350 return loc;
1351 }
1355 std::optional<Tuple> switch_tetrahedron(const Tuple& t) const
1356 {
1357 auto loc = t.switch_tetrahedron(*this);
1358 if (loc.has_value()) check_tuple_validity(loc.value());
1359 return loc;
1360 }
1361
1368 std::vector<Tuple> get_one_ring_tets_for_vertex(const Tuple& t) const;
1375 const std::vector<size_t>& get_one_ring_tids_for_vertex(const Tuple& t) const;
1376 const std::vector<size_t>& get_one_ring_tids_for_vertex(const size_t vid) const;
1377
1384 std::vector<Tuple> get_one_ring_vertices_for_vertex(const Tuple& t) const;
1392 std::vector<size_t> get_one_ring_vids_for_vertex(size_t vid, std::vector<size_t>& cache);
1399 std::vector<size_t> get_one_ring_vids_for_vertex(size_t vid) const;
1404 std::vector<size_t> get_one_ring_vids_for_vertex_adj(size_t vid) const;
1409 std::vector<size_t> get_one_ring_vids_for_vertex_adj(size_t vid, std::vector<size_t>& cache);
1410
1417 std::vector<Tuple> get_incident_tets_for_edge(const Tuple& t) const;
1418 std::vector<Tuple> get_incident_tets_for_edge(const size_t vid0, const size_t vid1) const;
1419
1420 std::vector<size_t> get_incident_tids_for_edge(const Tuple& t) const;
1421 std::vector<size_t> get_incident_tids_for_edge(const size_t vid0, const size_t vid1) const;
1422
1429 std::vector<Tuple> get_one_ring_tets_for_edge(const Tuple& t) const;
1430
1437 std::vector<std::array<size_t, 3>> vertex_adjacent_boundary_faces(const Tuple& t) const;
1442 std::array<Tuple, 4> oriented_tet_vertices(const Tuple& t) const;
1447 std::array<size_t, 4> oriented_tet_vids(const Tuple& t) const;
1448 std::array<size_t, 4> oriented_tet_vids(const size_t tid) const;
1455 std::array<Tuple, 3> get_face_vertices(const Tuple& t) const;
1456 std::array<size_t, 3> get_face_vids(const Tuple& t) const;
1457
1465 std::array<Tuple, 6> tet_edges(const Tuple& t) const;
1469 void check_tuple_validity(const Tuple& t) const { t.check_validity(*this); }
1482 void remove_tets_by_ids(const std::vector<size_t>& tids)
1483 {
1484 // A face or edge attribute lives at ONE canonical slot, (lowest incident tet) * 4
1485 // or 6 + local index. Deleting a tet that is a simplex's canonical owner silently
1486 // re-canonicalizes the simplex onto a surviving tet whose cell was never
1487 // maintained -- the operations only ever write the canonical slot -- so the
1488 // surviving cell holds stale garbage. Measured: after filtering, interior faces
1489 // read back m_is_surface_fs = true 0.12 (eps 0.09) from the real surface, and the
1490 // extracted "tracked surface" grows phantom triangles. Migrate every attribute
1491 // whose owner dies to the simplex's new owner BEFORE touching the connectivity.
1492 if (p_face_attrs != nullptr || p_edge_attrs != nullptr) {
1493 std::vector<bool> removed(tet_capacity(), false);
1494 for (const size_t tid : tids) {
1495 removed[tid] = true;
1496 }
1497 for (const size_t tid : tids) {
1498 const auto& tconn = m_tet_connectivity[tid];
1499 if (p_face_attrs != nullptr) {
1500 for (int lf = 0; lf < 4; ++lf) {
1501 std::array<size_t, 3> vids = {
1502 {tconn[m_local_faces[lf][0]],
1503 tconn[m_local_faces[lf][1]],
1504 tconn[m_local_faces[lf][2]]}};
1505 // The face's other incident tet, if any.
1506 auto common = set_intersection(
1507 m_vertex_connectivity[vids[0]].m_conn_tets,
1508 m_vertex_connectivity[vids[1]].m_conn_tets);
1509 common =
1510 set_intersection(common, m_vertex_connectivity[vids[2]].m_conn_tets);
1511 size_t other = std::numeric_limits<size_t>::max();
1512 for (const size_t t : common) {
1513 if (t != tid) {
1514 other = t;
1515 }
1516 }
1517 // Migrate only when this tet was the canonical owner (tid < other)
1518 // and the other side survives; other < tid means the attribute
1519 // already lives on the survivor.
1520 if (other == std::numeric_limits<size_t>::max() || removed[other] ||
1521 other < tid) {
1522 continue;
1523 }
1524 std::array<size_t, 3> sorted = vids;
1525 std::sort(sorted.begin(), sorted.end());
1526 for (int lo = 0; lo < 4; ++lo) {
1527 std::array<size_t, 3> ovids = {
1528 {m_tet_connectivity[other][m_local_faces[lo][0]],
1529 m_tet_connectivity[other][m_local_faces[lo][1]],
1530 m_tet_connectivity[other][m_local_faces[lo][2]]}};
1531 std::sort(ovids.begin(), ovids.end());
1532 if (ovids == sorted) {
1533 p_face_attrs->move(tid * 4 + lf, other * 4 + lo);
1534 break;
1535 }
1536 }
1537 }
1538 }
1539 if (p_edge_attrs != nullptr) {
1540 for (int le = 0; le < 6; ++le) {
1541 const size_t v0 = tconn[m_local_edges[le][0]];
1542 const size_t v1 = tconn[m_local_edges[le][1]];
1543 const auto fan = set_intersection(
1544 m_vertex_connectivity[v0].m_conn_tets,
1545 m_vertex_connectivity[v1].m_conn_tets);
1546 // Only the canonical owner migrates, once, to the lowest survivor.
1547 if (fan.empty() || fan.front() != tid) {
1548 continue;
1549 }
1550 size_t new_owner = std::numeric_limits<size_t>::max();
1551 for (const size_t t : fan) {
1552 if (!removed[t]) {
1553 new_owner = t; // fan is sorted ascending; first kept wins
1554 break;
1555 }
1556 }
1557 if (new_owner == std::numeric_limits<size_t>::max()) {
1558 continue; // the edge dies with its whole fan
1559 }
1560 for (int lo = 0; lo < 6; ++lo) {
1561 const size_t w0 = m_tet_connectivity[new_owner][m_local_edges[lo][0]];
1562 const size_t w1 = m_tet_connectivity[new_owner][m_local_edges[lo][1]];
1563 if ((w0 == v0 && w1 == v1) || (w0 == v1 && w1 == v0)) {
1564 p_edge_attrs->move(tid * 6 + le, new_owner * 6 + lo);
1565 break;
1566 }
1567 }
1568 }
1569 }
1570 }
1571 }
1572
1573 for (size_t tid : tids) {
1574 m_tet_connectivity[tid].m_is_removed = true;
1575 for (int j = 0; j < 4; j++)
1576 vector_erase(m_vertex_connectivity[m_tet_connectivity[tid][j]].m_conn_tets, tid);
1577 }
1578 for (auto& v : m_vertex_connectivity) {
1579 if (v.m_is_removed) continue;
1580 if (v.m_conn_tets.empty()) v.m_is_removed = true;
1581 }
1582 if (m_surface_history) resync_surface_history();
1583 }
1584 bool m_collapse_check_link_condition = true; // classical link condition
1585 bool m_collapse_check_topology = false; // sanity check
1586 bool m_collapse_check_manifold = true; // manifoldness check after collapse
1587
1588private:
1589 // `ok` is set to false if the operation ran out of preallocated tet slots; in
1590 // that case no connectivity is mutated and the caller must abort the operation.
1591 std::map<size_t, VertexConnectivity> operation_update_connectivity_impl(
1592 std::vector<size_t>& affected_tid,
1593 const std::vector<std::array<size_t, 4>>& new_tet_conn,
1594 bool& ok);
1595 void operation_failure_rollback_imp(
1596 std::map<size_t, VertexConnectivity>& rollback_vert_conn,
1597 const std::vector<size_t>& affected,
1598 const std::vector<size_t>& new_tet_id,
1599 const std::vector<TetrahedronConnectivity>& old_tets);
1600 std::map<size_t, VertexConnectivity> operation_update_connectivity_impl(
1601 const std::vector<size_t>& remove_id,
1602 const std::vector<std::array<size_t, 4>>& new_tet_conn,
1603 std::vector<size_t>& allocate_id,
1604 bool& ok);
1605 static std::vector<TetrahedronConnectivity> record_old_tet_connectivity(
1607 const std::vector<size_t>& tets)
1608 {
1609 std::vector<TetrahedronConnectivity> tet_conn;
1610 for (size_t i : tets) {
1611 tet_conn.push_back(conn[i]);
1612 }
1613 return tet_conn;
1614 }
1615
1616public:
1617 void start_protect_attributes()
1618 {
1619 if (p_vertex_attrs) {
1620 p_vertex_attrs->begin_protect();
1621 }
1622 if (p_edge_attrs) {
1623 p_edge_attrs->begin_protect();
1624 }
1625 if (p_face_attrs) {
1626 p_face_attrs->begin_protect();
1627 }
1628 if (p_tet_attrs) {
1629 p_tet_attrs->begin_protect();
1630 }
1631 }
1632
1633 void release_protect_attributes()
1634 {
1635 if (p_vertex_attrs) {
1636 p_vertex_attrs->end_protect();
1637 }
1638 if (p_edge_attrs) {
1639 p_edge_attrs->end_protect();
1640 }
1641 if (p_face_attrs) {
1642 p_face_attrs->end_protect();
1643 }
1644 if (p_tet_attrs) {
1645 p_tet_attrs->end_protect();
1646 }
1647 }
1648
1649 void rollback_protected_attributes()
1650 {
1651 if (p_vertex_attrs) {
1652 p_vertex_attrs->rollback();
1653 }
1654 if (p_edge_attrs) {
1655 p_edge_attrs->rollback();
1656 }
1657 if (p_face_attrs) {
1658 p_face_attrs->rollback();
1659 }
1660 if (p_tet_attrs) {
1661 p_tet_attrs->rollback();
1662 }
1663 }
1664
1665public:
1669
1670private:
1671 std::vector<VertexMutex> m_vertex_mutex;
1672
1673 bool try_set_vertex_mutex(const Tuple& v, int threadid)
1674 {
1675 bool got = m_vertex_mutex[v.vid(*this)].trylock();
1676 if (got) m_vertex_mutex[v.vid(*this)].set_owner(threadid);
1677 return got;
1678 }
1679 bool try_set_vertex_mutex(size_t vid, int threadid)
1680 {
1681 bool got = m_vertex_mutex[vid].trylock();
1682 if (got) m_vertex_mutex[vid].set_owner(threadid);
1683 return got;
1684 }
1685
1686 void unlock_vertex_mutex(const Tuple& v) { m_vertex_mutex[v.vid(*this)].unlock(); }
1687 void unlock_vertex_mutex(size_t vid) { m_vertex_mutex[vid].unlock(); }
1688
1696 {
1697 std::vector<uint32_t> stamp;
1698 uint32_t epoch = 0;
1699 std::vector<size_t> frontier;
1700 std::vector<size_t> next;
1701 std::vector<size_t> one_ring;
1702 };
1704
1705 std::shared_ptr<history::TrackedSurfaceRecorder> m_surface_history;
1711 void surface_history_before(const std::vector<size_t>& vs, bool all);
1712 std::array<size_t, 2> surface_history_commit(
1713 history::EditKind kind,
1714 std::vector<size_t> v,
1715 const std::vector<size_t>& vs_after,
1716 bool all);
1717
1720 struct VolumeRecording;
1721 std::shared_ptr<VolumeRecording> m_volume_history;
1723 history::VolumeCapture volume_capture(const std::vector<size_t>& vs) const;
1726 void volume_history_before(const std::vector<size_t>& vs);
1727 void volume_history_commit(
1729 std::array<size_t, 2> surface_edits,
1730 const std::vector<size_t>& op_vertices,
1731 const std::vector<size_t>& vs_after);
1733 std::vector<size_t> vertices_of_tets(const std::vector<size_t>& tids) const;
1734
1736 bool lock_vertex_ball(const size_t* seeds, size_t n_seeds, int threadid, int n, size_t mark);
1737
1739 void check_smoothing_stayed_in_star(size_t vid);
1740
1741protected:
1742 void resize_vertex_mutex(size_t v)
1743 {
1744 if (m_vertex_mutex.size() < v) m_vertex_mutex.resize(v);
1745 }
1746
1747public:
1750
1751 // void init(size_t n_vertices, const std::vector<std::array<size_t, 4>>& tets);
1752 int release_vertex_mutex_in_stack();
1760 int release_vertex_mutex_to(size_t mark);
1761
1778 bool try_set_vertex_mutex_n_ring(const Tuple& v, int threadid, int n);
1779 bool try_set_vertex_mutex_n_ring(size_t vid, int threadid, int n);
1783 bool try_set_edge_mutex_n_ring(const Tuple& e, int threadid, int n);
1787 bool try_set_face_mutex_n_ring(size_t v1, size_t v2, size_t v3, int threadid, int n);
1788
1829 bool try_set_vertex_mutex_two_ring(const Tuple& v, int threadid);
1831 bool try_set_vertex_mutex_two_ring_vid(const Tuple& v, int threadid);
1833 bool try_set_vertex_mutex_two_ring_vid(size_t v, int threadid);
1835 bool try_set_edge_mutex_two_ring(const Tuple& e, int threadid = 0);
1837 bool try_set_face_mutex_two_ring(const Tuple& f, int threadid = 0);
1840 const Tuple& v1,
1841 const Tuple& v2,
1842 const Tuple& v3,
1843 int threadid = 0);
1845 bool try_set_face_mutex_two_ring(size_t v1, size_t v2, size_t v3, int threadid = 0);
1847 bool try_set_vertex_mutex_one_ring(const Tuple& v, int threadid = 0);
1850public:
1855 void for_each_edge(const std::function<void(const TetMesh::Tuple&)>&);
1860 void for_each_vertex(const std::function<void(const TetMesh::Tuple&)>&);
1865 void for_each_tetra(const std::function<void(const TetMesh::Tuple&)>&);
1866 int NUM_THREADS = 0;
1867
1868public:
1869 // substructure functionality
1870
1876 virtual bool vertex_is_on_surface(const size_t vid) const { return false; }
1877
1883 virtual bool face_is_on_surface(const size_t fid) const { return false; }
1884
1891
1897 simplex::SimplexCollection get_surface_faces_for_edge(const std::array<size_t, 2>& vids) const;
1903 size_t get_num_surface_faces_for_edge(const std::array<size_t, 2>& vids) const;
1904
1905
1914 size_t compute_vertex_order(const size_t vid) const;
1915
1930 virtual size_t get_order_of_vertex(const size_t vid) const { return compute_vertex_order(vid); }
1931
1942 size_t get_order_of_edge(const std::array<size_t, 2>& vids) const;
1943
1953 virtual size_t substructure_order_of_edge(const std::array<size_t, 2>& vids) const
1954 {
1955 return get_order_of_edge(vids);
1956 }
1957 virtual size_t substructure_order_of_vertex(const size_t vid) const
1958 {
1959 return get_order_of_vertex(vid);
1960 }
1966 virtual void substructure_feature_neighbors(size_t, std::vector<size_t>&) const {}
1967
1981 bool substructure_link_condition(const Tuple& e_tuple) const;
1982};
1983
1984
1985} // namespace wmtk
Preallocated storage plus the atomic counter that hands slots out of it.
Definition SlotPool.hpp:38
static size_t taken_by_this_thread()
Slots this thread has been handed by pools of this type, over its lifetime.
Definition SlotPool.hpp:88
Definition TetMesh.h:215
uint32_t hash
Definition TetMesh.h:307
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:60
Tuple switch_face(const TetMesh &m) const
Definition TetMeshTuple.cpp:284
bool is_valid(const TetMesh &m) const
Definition TetMeshTuple.cpp:57
bool is_boundary_face(const TetMesh &m) const
Definition TetMeshTuple.cpp:17
void print_info() const
prints the tuple
Definition TetMeshTuple.cpp:68
std::optional< Tuple > switch_tetrahedron(const TetMesh &m) const
Definition TetMeshTuple.cpp:304
bool is_valid_unlocked(const TetMesh &m) const
Definition TetMesh.h:95
size_t eid(const TetMesh &m) const
Definition TetMeshTuple.cpp:111
Tuple switch_edge(const TetMesh &m) const
Definition TetMeshTuple.cpp:269
Tuple switch_vertex(const TetMesh &m) const
Definition TetMeshTuple.cpp:255
size_t tid(const TetMesh &m) const
Definition TetMeshTuple.cpp:250
size_t vid(const TetMesh &m) const
Definition TetMeshTuple.cpp:106
size_t fid(const TetMesh &m) const
Definition TetMeshTuple.cpp:184
bool is_boundary_edge(const TetMesh &m) const
Definition TetMeshTuple.cpp:34
void check_validity(const TetMesh &m) const
check Tuple validity and connectivity validity
Definition TetMeshTuple.cpp:389
Definition TetMesh.h:261
Definition TetMesh.h:32
size_t compute_vertex_order(const size_t vid) const
Compute the vertex order for a single vertex.
Definition TetMeshSubstructure.cpp:117
virtual bool swap_edge_44_after(const Tuple &t)
User specified modifications and desideratas for after a 4-4 edge swap.
Definition TetMesh.h:1101
std::vector< Tuple > get_one_ring_vertices_for_vertex(const Tuple &t) const
Get the one ring vertices for a vertex.
Definition TetMesh.cpp:862
size_t vertex_valence(const size_t vid) const
Number of tets incident to a vertex, in O(1).
Definition TetMesh.h:1293
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 (...
Definition TetMesh.h:1966
virtual bool swap_edge_44_before(const Tuple &t)
User specified preparations and desideratas for an 4-4 edge swap before changing the connectivity.
Definition TetMesh.h:1078
virtual bool split_tet_before(const Tuple &t)
User specified preparations and desideratas for a tet split before changing the connectivity.
Definition TetMesh.h:1227
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.
Definition TetMesh.cpp:482
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.
Definition TetMesh.cpp:1232
size_t tet_size() const
get the number of unremoved tets
Definition TetMesh.h:419
virtual size_t get_order_of_vertex(const size_t vid) const
Get the order of a vertex.
Definition TetMesh.h:1930
std::vector< Tuple > get_faces() const
Definition TetMesh.cpp:245
std::array< Tuple, 6 > tet_edges(const Tuple &t) const
get the 6 edges of a tet represented by Tuples
Definition TetMesh.cpp:825
virtual bool smooth_after(const Tuple &t)
User specified modifications and desideratas for after smoothing a vertex.
Definition TetMesh.h:1202
void consolidate_mesh()
cleans up the deleted vertices or tetrahedra, fixes the corresponding indices, and reset the version ...
Definition TetMesh.cpp:990
size_t vert_capacity() const
get the current largest global vid
Definition TetMesh.h:379
virtual bool collapse_edge_after(const Tuple &t)
User specified modifications and desideratas for after an edge collapse.
Definition TetMesh.h:1070
void set_preallocation_factor(double factor)
Preallocation factor: init/consolidate reserve capacity = max(floor, ceil(factor * live_count)) so op...
Definition TetMesh.h:814
virtual bool swap_edge_after(const Tuple &t)
User specified modifications and desideratas for after a 3-2 edge swap.
Definition TetMesh.h:1173
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.
Definition TetMeshSubstructure.cpp:82
bool smooth_vertex(const Tuple &t)
Definition TetMesh.cpp:373
void reserve_free_slots(size_t cells, size_t verts)
Definition TetMesh.cpp:48
std::vector< std::array< size_t, 3 > > tracked_faces() const
Every tracked face, oriented by orient_tracked_face().
Definition TetMesh.cpp:1712
virtual bool face_is_on_surface(const size_t fid) const
Is a face part of the substructure.
Definition TetMesh.h:1883
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....
Definition TetMeshTriangleInsertionConn.cpp:415
bool split_edge(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshEdgeSplittingConn.cpp:7
Tuple switch_face(const Tuple &t) const
wrapper function from Tuple::switch_face
Definition TetMesh.h:1346
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 subst...
Definition TetMesh.h:1953
std::array< Tuple, 4 > oriented_tet_vertices(const Tuple &t) const
Definition TetMesh.cpp:785
void for_each_vertex(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each vertex
Definition TetMesh.cpp:1649
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.
Definition TetMesh.cpp:1561
size_t resync_surface_history()
Definition TetMesh.cpp:1707
virtual bool checks_tracked_surface() const
Checks an application makes on what an operation does to the tracked surface.
Definition TetMesh.h:739
std::array< size_t, 4 > oriented_tet_vids(const Tuple &t) const
Definition TetMesh.cpp:797
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...
Definition TetMeshEdgeCollapsingConn.cpp:452
virtual bool storage_grows_on_demand() const
Definition TetMesh.h:885
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.
Definition TetMesh.cpp:1266
Tuple tuple_from_tet(size_t tid) const
get a Tuple from global tetra index
Definition TetMesh.cpp:715
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 > > &center_split_tets)
Definition TetMeshTriangleInsertionConn.cpp:142
void init(size_t n_vertices, const std::vector< std::array< size_t, 4 > > &tets)
Definition TetMesh.cpp:89
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.
Definition TetMesh.cpp:540
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 > > &center_split_tets)
Definition TetMeshTriangleInsertionConn.cpp:235
virtual bool swap_edge_56_before(const Tuple &t)
User specified preparations and desideratas for a 5-6 edge swap before changing the connectivity.
Definition TetMesh.h:1122
std::vector< Tuple > get_incident_tets_for_edge(const Tuple &t) const
Get the incident tets for edge.
Definition TetMesh.cpp:934
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.
Definition TetMesh.cpp:1894
virtual bool split_face_after(const Tuple &t)
Compute the attributes for the added simplices.
Definition TetMesh.h:1219
bool swap_edge_56(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshSwapMeshConnectivity.cpp:796
bool split_face(const Tuple &t, std::vector< Tuple > &new_tets)
Split a face in 3 faces.
Definition TetMeshFaceSplittingConn.cpp:6
bool link_condition(const Tuple &t)
Definition TetMeshEdgeCollapsingConn.cpp:343
std::vector< Tuple > get_one_ring_tets_for_edge(const Tuple &t) const
Get the one ring tets for edge.
Definition TetMesh.cpp:970
virtual bool split_face_before(const Tuple &t)
User specified preparations and desideratas for a face split before changing the connectivity.
Definition TetMesh.h:1210
std::array< size_t, 3 > orient_tracked_face(const std::array< size_t, 3 > &f) const
orient_tracked_face, finding the face's tets.
Definition TetMesh.h:694
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.
Definition TetMesh.h:1089
Tuple tuple_from_vertex(size_t vid) const
get a Tuple from global vertex index
Definition TetMesh.cpp:702
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.
Definition TetMesh.cpp:1854
simplex::SimplexCollection get_surface_faces_for_vertex(const size_t vid) const
Get all faces on the surface that are incident to vid.
Definition TetMeshSubstructure.cpp:7
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 TetMesh.cpp:1216
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 TetMesh.cpp:1126
virtual void for_each_face(const std::function< void(const TetMesh::Tuple &)> &)
looping through all the unique edges and perform the given function
Definition TetMesh.cpp:231
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.
Definition TetMesh.cpp:910
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.
Definition TetMesh.h:1023
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....
Definition TetMesh.cpp:1673
std::optional< Tuple > switch_tetrahedron(const Tuple &t) const
wrapper function from Tuple::switch_tetrahedron
Definition TetMesh.h:1355
bool op_refused(const OpKind k, const OpEvent e) const
op_event() for a refusal, returning false so a site reads return op_refused(...).
Definition TetMesh.h:1014
size_t get_order_of_edge(const std::array< size_t, 2 > &vids) const
Compute the order of an edge.
Definition TetMeshSubstructure.cpp:203
const std::vector< size_t > & get_one_ring_tids_for_vertex(const Tuple &t) const
Get the one ring tids for vertex.
Definition TetMesh.cpp:838
std::vector< Tuple > get_tets() const
Definition TetMesh.cpp:340
virtual bool smooth_before(const Tuple &t)
User specified preparations and desideratas for smoothing a vertex.
Definition TetMesh.h:1195
virtual bool split_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge split before changing the connectivity.
Definition TetMesh.h:1041
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.
Definition TetMesh.cpp:896
virtual bool swap_edge_before(const Tuple &t)
User specified preparations and desideratas for an 3-2 edge swap before changing the conenctivity.
Definition TetMesh.h:1166
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 > > &center_split_tets)
Insert a triangle into a tetmesh, with known intersection information.
Definition TetMeshTriangleInsertionConn.cpp:11
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)
Definition TetMeshSwapMeshConnectivity.cpp:45
virtual std::vector< std::array< size_t, 2 > > tracked_feature_edges() const
Definition TetMesh.h:682
void volume_history_before(const std::vector< size_t > &vs)
Definition TetMesh.cpp:1875
bool check_mesh_connectivity_validity() const
checks the validity of the connectivity of the mesh. Including the validity of each Tuple
Definition TetMesh.cpp:266
void stop_surface_history()
Stop recording. The recorder keeps what it has.
Definition TetMesh.cpp:1684
bool split_tet(const Tuple &t, std::vector< Tuple > &new_tets)
Split a tet in 4 tets.
Definition TetMeshTetSplittingConn.cpp:6
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).
Definition TetMesh.cpp:452
static bool dry_run()
Whether operations on this thread are dry runs (see wmtk/OperationDryRun.hpp).
Definition TetMesh.h:1021
size_t vertex_size() const
get the number of unremoved verticies
Definition TetMesh.h:407
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.
Definition TetMesh.cpp:1796
Tuple switch_vertex(const Tuple &t) const
wrapper function from Tuple::switch_vertex
Definition TetMesh.h:1328
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 ...
Definition TetMesh.cpp:1731
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.
Definition TetMeshSubstructure.cpp:42
bool substructure_link_condition(const Tuple &e_tuple) const
Link condition that also considers substructures.
Definition TetMeshSubstructure.cpp:218
virtual bool swap_face_before(const Tuple &t)
User specified preparations and desideratas for an 2-3 face swap befroe changing the geometry.
Definition TetMesh.h:1181
std::vector< VertexFace > faces_at_vertex(size_t v) const
The faces with v as a corner, found from v's tets alone.
Definition TetMesh.cpp:1806
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.
Definition TetMesh.cpp:1315
virtual bool vertex_is_on_surface(const size_t vid) const
Is a vertex part of the substructure.
Definition TetMesh.h:1876
bool swap_edge(const Tuple &t, std::vector< Tuple > &new_tets)
3-2 edge swap
Definition TetMeshSwapMeshConnectivity.cpp:137
Tuple switch_edge(const Tuple &t) const
wrapper function from Tuple::switch_edge
Definition TetMesh.h:1337
std::vector< Tuple > get_edges() const
Definition TetMesh.cpp:191
virtual bool split_tet_after(const Tuple &t)
Compute the attributes for the added simplices.
Definition TetMesh.h:1236
void for_each_edge(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each edge
Definition TetMesh.cpp:1590
size_t cell_slot_bound(const Tuple &t) const
Definition TetMesh.cpp:38
int release_vertex_mutex_to(size_t mark)
Release the mutexes taken since the release stack held mark entries.
Definition TetMesh.cpp:1109
void check_tuple_validity(const Tuple &t) const
Definition TetMesh.h:1469
std::vector< std::array< size_t, 3 > > tracked_faces_around(const std::vector< size_t > &vs, bool all) const
Definition TetMesh.cpp:1758
virtual std::vector< int64_t > tet_tags(size_t tid) const
Definition TetMesh.h:673
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.
Definition TetMesh.cpp:400
virtual std::array< size_t, 3 > orient_tracked_face(const std::array< size_t, 3 > &f, const std::vector< size_t > &tets) const
Definition TetMesh.h:687
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)
Definition TetMeshEdgeCollapsingConn.cpp:471
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 TetMesh.cpp:1244
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 TetMesh.cpp:1211
void stop_volume_history()
Stop recording the volume. The recorder keeps what it has.
Definition TetMesh.cpp:1702
virtual bool collapse_edge(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshEdgeCollapsingConn.cpp:265
virtual void on_slot_storage_grown()
Definition TetMesh.h:905
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.
Definition TetMesh.cpp:1361
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).
Definition TetMesh.cpp:462
bool m_check_smoothing_stays_in_star
While true, smooth_vertex() checks that the smooth recorded nothing outside the vertex's star – the v...
Definition TetMesh.h:578
virtual bool split_edge_after(const Tuple &t)
This function computes the attributes for the added simplices. User specified modifications and desid...
Definition TetMesh.h:1050
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.
Definition TetMesh.h:1708
static constexpr std::array< std::array< int, 2 >, 6 > m_local_edges
local edges within a tet
Definition TetMesh.h:40
std::array< Tuple, 3 > get_face_vertices(const Tuple &t) const
Get the 3 vertices of a face represented by Tuple.
Definition TetMesh.cpp:807
virtual bool swap_edge_56_after(const Tuple &t)
User specified modifications and desideratas for after a 5-6 edge swap.
Definition TetMesh.h:1145
virtual bool collapse_edge_before(const Tuple &t)
User specified preparations and desideratas for an edge collapse before changing the connectivity.
Definition TetMesh.h:1061
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 surfa...
Definition TetMesh.cpp:1690
std::vector< size_t > vertices_of_tets(const std::vector< size_t > &tids) const
The vertices of the tets tids, sorted.
Definition TetMesh.cpp:1903
std::vector< Tuple > get_vertices() const
Definition TetMesh.cpp:356
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)
Definition TetMeshEdgeCollapsingConn.cpp:482
size_t tet_capacity() const
get the current largest global tid
Definition TetMesh.h:385
std::vector< Tuple > get_one_ring_tets_for_vertex(const Tuple &t) const
Get the one ring tets for a vertex.
Definition TetMesh.cpp:851
void for_each_tetra(const std::function< void(const TetMesh::Tuple &)> &)
perform the given function for each tet
Definition TetMesh.cpp:1623
bool swap_edge_44(const Tuple &t, std::vector< Tuple > &new_tets)
Definition TetMeshSwapMeshConnectivity.cpp:539
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.
Definition TetMesh.h:1158
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.
Definition TetMesh.h:1114
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.
Definition TetMesh.h:1133
virtual bool is_tracked_face(size_t tid, int j) const
Definition TetMesh.h:678
bool swap_face(const Tuple &t, std::vector< Tuple > &new_tets)
2-3 face swap
Definition TetMeshSwapMeshConnectivity.cpp:272
void remove_tets_by_ids(const std::vector< size_t > &tids)
remove the tetrahedrons in the mesh that have given tet ids
Definition TetMesh.h:1482
void surface_history_before(const std::vector< size_t > &vs, bool all)
Definition TetMesh.cpp:1832
Tuple tuple_from_vids(size_t vid0, size_t vid1, size_t vid2, size_t vid3) const
Get a Tuple from global vertex IDs.
Definition TetMesh.cpp:726
std::vector< std::array< size_t, 3 > > vertex_adjacent_boundary_faces(const Tuple &t) const
Definition TetMesh.cpp:1084
virtual bool swap_face_after(const Tuple &t)
User specified modifications and desideratas for after a 2-3 face swap.
Definition TetMesh.h:1188
Definition Simplex.hpp:46
Definition Simplex.hpp:57
Definition SimplexCollection.hpp:9
Definition Simplex.hpp:71
A per-vertex lock plus the id of the thread currently holding it.
Definition vertex_mutex.hpp:29
Definition enumerable_thread_specific.hpp:37
std::optional< Tets > collapse(const Tets &T, const Vid a, const Vid b)
Definition volume_complex.cpp:185
std::optional< Faces > boundary(const Tets &T)
The faces of T on one tet only; nothing if a face is on more than two.
Definition volume_complex.cpp:48
EditKind
The kinds of edit a complex goes through.
Definition History.hpp:27
VolumeOp
The tet operations a volume history records.
Definition VolumeHistory.hpp:19
Per-thread buffers for the n-ring lock, so a lock acquisition allocates nothing.
Definition TetMesh.h:1696
Definition TetMesh.h:890
A face at a vertex: its corners sorted, its face id (Tuple::fid) and its tets, sorted.
Definition TetMesh.h:712
Definition TetMesh.cpp:16
Definition VolumeHistory.hpp:124