Wildmeshing Toolkit
Loading...
Searching...
No Matches
TopoOffsetTetMesh.h
1#pragma once
2
3#include <igl/Timer.h>
4#include <wmtk/TetMesh.h>
5#include <wmtk/simplex/Simplex.hpp>
6#include "Parameters.h"
7#include "SimplicialComplexBVH.hpp"
8
9// clang-format off
10#include <wmtk/utils/DisableWarnings.hpp>
11#include <wmtk/utils/EnableWarnings.hpp>
12// clang-format on
13
14using CellTag = std::set<int64_t>;
15
16
17namespace wmtk::components::topological_offset {
18
19
20const int64_t TEMP_OFFSET_TET_TAG = -1;
21const CellTag TEMP_OFFSET_TET_TAG_SET{TEMP_OFFSET_TET_TAG};
22
23
24// for all attributes:
25// label: 0=default, 1=input, 2=offset
27{
28public:
29 Vector3d m_posf;
30 int label = 0;
31 size_t component_id = 0;
32
34 VertexAttributes(const Vector3d& p);
35};
36
37
39{
40public:
41 int label = 0;
42};
43
44
46{
47public:
48 int label = 0;
49};
50
51
53{
54public:
55 int label = 0;
56 CellTag tag;
57};
58
59
61{
62public: // mode for splitting in marching tets
63 enum class EdgeSplitMode {
64 Midpoint = 0,
65 BinarySearch = 1, // requires that every edge being split has one vertex labelled 0 and the
66 // other 1 or 2
67 Initial = 2 // requires that every edge being split has one vertex labelled 0 and the other
68 // 1 or 2. This is really hacky. This initializes the offset using the minimum
69 // of half the target distance and half the edge length. Basically we want to
70 // initialize the offset with as high of quality as possible
71 };
72
73public:
74 int m_vtu_counter = 0;
75 std::array<size_t, 4> m_init_counts = {{0, 0, 0, 0}};
76 size_t m_tags_count;
77 SimplicialComplexBVH m_input_complex_bvh;
78 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
79
80 // tag map stuff
81 std::map<std::string, int64_t> m_tag_name_to_id;
82 std::map<int64_t, std::string> m_tag_id_to_name;
83 // std::vector<CellTag> m_offset_tags_ids;
84 CellTag m_offset_output_tag_ids;
85
86 // if in 'singlebody' mode
87 bool m_singlebody = false;
88 int64_t m_single_tag;
89
90 // dont actually use, just for retaining in output
91 bool m_has_envelope;
92 MatrixXd m_V_envelope;
93 MatrixXi m_F_envelope;
94
95 Parameters& m_params;
96
101 VertAttCol m_vertex_attribute;
102 EdgeAttCol m_edge_attribute;
103 FaceAttCol m_face_attribute;
104 TetAttCol m_tet_attribute;
105
106 TopoOffsetTetMesh(Parameters& _m_params, int _num_threads = 0)
107 : m_params(_m_params)
108 {
109 NUM_THREADS = _num_threads;
110 p_vertex_attrs = &m_vertex_attribute;
111 p_edge_attrs = &m_edge_attribute;
112 p_face_attrs = &m_face_attribute;
113 p_tet_attrs = &m_tet_attribute;
114 }
115
117
126 void init_from_image(
127 const MatrixXd& V,
128 const MatrixXi& T,
129 const MatrixSi& T_tags,
130 const MatrixXd& V_env,
131 const MatrixXi F_env,
132 const std::vector<std::string>& tag_names);
133
137 void label_input_complex();
138
143 bool empty_input_complex();
144
149
155 void edge_split_binary_search(const size_t v1, const size_t v2, Vector3d& p_new) const;
156
160 size_t flood_fill();
161
163 bool split_edge_before(const Tuple& t) override;
164 bool split_edge_after(const Tuple& t) override;
165 bool split_face_before(const Tuple& t) override;
166 bool split_face_after(const Tuple& t) override;
167 bool split_tet_before(const Tuple& t) override;
168 bool split_tet_after(const Tuple& t) override;
169 bool invariants(const std::vector<Tuple>& tets) override;
171
178 void marching_tets();
179
180
182
186 bool is_simplicially_embedded() const;
187
192 bool tet_is_simp_emb(const Tuple& t) const;
193
199
201
204 bool tag_tet_consistent_topology(size_t t_id, int64_t tag) const;
205
210 bool offset_tet_consistent_topology(const size_t t_id) const;
211
216 bool tet_is_in_offset_conservative(const size_t t_id, const double threshold_r) const;
217
224
229 void set_offset_tet_tags();
230
237 bool offset_is_manifold();
238
240 void write_input_complex(const std::string& path); // write components labeled to be offset
241 void write_vtu(const std::string& path);
242 // void write_msh(const std::string& file);
243 void write_msh_groups(const std::string& file);
245
246private:
253 {
254 size_t v1_id;
255 size_t v2_id;
256 VertexAttributes new_v;
257
258 // cache edge attributes
259 EdgeAttributes split_e;
260 std::map<size_t, EdgeAttributes> internal_e;
261 std::map<simplex::Edge, EdgeAttributes> external_e; // edge is boundary edge (not link)
262 std::map<simplex::Edge, EdgeAttributes> link_e;
263
264 // cache face attributes
265 std::map<size_t, FaceAttributes> split_f;
266 std::map<simplex::Edge, FaceAttributes> internal_f;
267 std::map<std::pair<simplex::Edge, size_t>, FaceAttributes> external_f;
268
269 // cache tet attributes
270 std::map<simplex::Edge, TetAttributes> tets;
271 };
272 tbb::enumerable_thread_specific<EdgeSplitCache> edge_split_cache;
273
275 {
276 size_t v1_id;
277 size_t v2_id;
278 size_t v3_id;
279
280 // cache edge attributes
281 std::map<simplex::Edge, EdgeAttributes> existing_e;
282
283 // cache face attributes
284 std::map<simplex::Face, FaceAttributes> existing_f;
285 int splitf_label;
286
287 // cache tet attributes
288 std::map<size_t, TetAttributes> tets;
289 };
290 tbb::enumerable_thread_specific<FaceSplitCache> face_split_cache;
291
293 {
294 std::array<size_t, 4> v_ids;
295
296 // cache retained edge attributes
297 std::map<simplex::Edge, EdgeAttributes> existing_e;
298
299 // cache retained face attributes
300 std::map<simplex::Face, FaceAttributes> existing_f;
301
302 // cache tet attribute
303 TetAttributes tet;
304 };
305 tbb::enumerable_thread_specific<TetSplitCache> tet_split_cache;
306
307private: // helpers
313 bool any_tag_present(const CellTag& tag1, const CellTag& tag2)
314 {
315 if (tag2.empty()) {
316 return tag1.empty();
317 }
318 if (tag1.empty()) { // tag1 is ambient, tag2 is not
319 return false;
320 }
321
322 for (const int64_t& i : tag1) {
323 if (tag2.find(i) != tag2.end()) {
324 return true;
325 }
326 }
327 return false;
328 }
329
333 void sort_edges_by_length(std::vector<simplex::Edge>& edges)
334 {
335 std::sort(
336 edges.begin(),
337 edges.end(),
338 [this](const simplex::Edge& e1, const simplex::Edge& e2) {
339 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
340 m_vertex_attribute[e1.vertices()[1]].m_posf)
341 .norm();
342 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
343 m_vertex_attribute[e2.vertices()[1]].m_posf)
344 .norm();
345 return len1 > len2;
346 });
347 }
348
349public: // helpers
353 std::vector<Tuple> get_face_adjacent_tets(const Tuple& t) const
354 {
355 std::vector<Tuple> adj_tets;
356 auto tet_1 = t.switch_tetrahedron(*this);
357 if (tet_1) {
358 adj_tets.push_back(tet_1.value());
359 }
360 auto tet_2 = t.switch_face(*this).switch_tetrahedron(*this);
361 if (tet_2) {
362 adj_tets.push_back(tet_2.value());
363 }
364 auto tet_3 = t.switch_edge(*this).switch_face(*this).switch_tetrahedron(*this);
365 if (tet_3) {
366 adj_tets.push_back(tet_3.value());
367 }
368 auto tet_4 =
369 t.switch_vertex(*this).switch_edge(*this).switch_face(*this).switch_tetrahedron(*this);
370 if (tet_4) {
371 adj_tets.push_back(tet_4.value());
372 }
373 return adj_tets;
374 }
375
379 std::vector<size_t> connected_components_helper(const size_t& v_id)
380 {
381 auto onering_v_ids = get_one_ring_vids_for_vertex(v_id);
382 std::vector<size_t> ret_v_ids;
383 for (const size_t& other_v_id : onering_v_ids) {
384 size_t e_id = tuple_from_edge({{v_id, other_v_id}}).eid(*this);
385 if (m_edge_attribute[e_id].label != 0) { // edge labelled 1 or 2
386 ret_v_ids.push_back(other_v_id);
387 }
388 }
389 return ret_v_ids;
390 }
391
396 {
397 auto verts = get_vertices();
398 for (const Tuple& v : verts) {
399 size_t v_id = v.vid(*this);
400 m_vertex_attribute[v_id].component_id = 0;
401 }
402 }
403};
404
405
406} // namespace wmtk::components::topological_offset
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:48
Definition TetMesh.h:23
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:764
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:353
std::vector< Tuple > get_vertices() const
Definition TetMesh.cpp:323
std::vector< Tuple > get_face_adjacent_tets(const Tuple &t) const
get tets (as Tuples) that are face-adjacent to the given tet (as Tuple)
Definition TopoOffsetTetMesh.h:353
bool split_edge_after(const Tuple &t) override
This function computes the attributes for the added simplices. User specified modifications and desid...
Definition ComponentSplitting.cpp:154
void sort_edges_by_length(std::vector< simplex::Edge > &edges)
sort edge simplices in place by decreasing edge length
Definition TopoOffsetTetMesh.h:333
bool tet_is_in_offset_conservative(const size_t t_id, const double threshold_r) const
check if a tet is inside the offset (implicitly defined via BVH distance field to input complex) via ...
Definition Spatial.cpp:13
void reset_connected_components()
reset connected component assignments.
Definition TopoOffsetTetMesh.h:395
void edge_split_binary_search(const size_t v1, const size_t v2, Vector3d &p_new) const
split edge at point by minimizing m_params.target_distance - d() (where d() is distance to input comp...
Definition ComponentSplitting.cpp:12
size_t flood_fill()
label connected simplicial complex components (simplices labelled 1 or 2)
Definition TopoOffsetTetMesh.cpp:638
void init_from_image(const MatrixXd &V, const MatrixXi &T, const MatrixSi &T_tags, const MatrixXd &V_env, const MatrixXi F_env, const std::vector< std::string > &tag_names)
initialize TetMesh from vertex, tet, and tag data
Definition TopoOffsetTetMesh.cpp:32
void marching_tets()
execute simplistic marching tets. All edges with one vertex labelled 0 and the other 1/2 are split....
Definition TopoOffsetTetMesh.cpp:823
bool split_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge split before changing the connectivity.
Definition ComponentSplitting.cpp:34
void set_offset_tet_tags()
update 'tags' data for tets in the offset region (tets labelled 2) based on the given offset tag valu...
Definition TopoOffsetTetMesh.cpp:961
bool split_tet_after(const Tuple &t) override
Compute the attributes for the added simplices.
Definition ComponentSplitting.cpp:416
void grow_offset_conservative()
grow offset region conservatively using conservative checks while ensuring consistent topology
Definition TopoOffsetTetMesh.cpp:896
bool split_face_before(const Tuple &t) override
User specified preparations and desideratas for a face split before changing the connectivity.
Definition ComponentSplitting.cpp:224
bool offset_is_manifold()
verify that the closed offset region (simplices labelled 1 or 2) form a manifold region....
Definition TopoOffsetTetMesh.cpp:996
bool tag_tet_consistent_topology(size_t t_id, int64_t tag) const
check if removing the tet would change the topology of any label
Definition Spatial.cpp:133
bool is_simplicially_embedded() const
check if the input complex (simplices labelled 1) are simplicially embedded w.r.t....
Definition TopoOffsetTetMesh.cpp:683
bool any_tag_present(const CellTag &tag1, const CellTag &tag2)
determine if any tag from tag1 is also present in tag2.
Definition TopoOffsetTetMesh.h:313
std::vector< size_t > connected_components_helper(const size_t &v_id)
get all one-ring vertices through input simplices (labelled 1)
Definition TopoOffsetTetMesh.h:379
void simplicial_embedding()
make mesh a simplicial embedding of the input complex (simplices labelled 1)
Definition TopoOffsetTetMesh.cpp:728
void init_input_complex_bvh()
initialize BVH for input complex. Must be called after init_from_image(...)
Definition TopoOffsetTetMesh.cpp:484
void label_input_complex()
label input simplicial complex simplices, as defined in m_params.offset_selection
Definition TopoOffsetTetMesh.cpp:112
bool tet_is_simp_emb(const Tuple &t) const
check if a tet satisfies simpicial embedding criteria w.r.t. input complex (simplices labelled 1)
Definition TopoOffsetTetMesh.cpp:700
bool offset_tet_consistent_topology(const size_t t_id) const
check if adding a tet to the offset region does not change the topology of the offset....
Definition Spatial.cpp:54
bool split_tet_before(const Tuple &t) override
User specified preparations and desideratas for a tet split before changing the connectivity.
Definition ComponentSplitting.cpp:379
bool empty_input_complex()
check if the input complex is empty. Only valid after calling init_from_image(...)....
Definition TopoOffsetTetMesh.cpp:471
bool split_face_after(const Tuple &t) override
Compute the attributes for the added simplices.
Definition ComponentSplitting.cpp:298
Definition Simplex.hpp:46