Wildmeshing Toolkit
Loading...
Searching...
No Matches
TopoOffsetTriMesh.h
1#pragma once
2#include <wmtk/TriMesh.h>
3#include <algorithm>
4#include <set>
5#include "Parameters.h"
6#include "SimplicialComplexBVH.hpp"
7
8using CellTag = std::set<int64_t>;
9
10
11namespace wmtk::components::topological_offset {
12
13
14const int64_t TEMP_OFFSET_TRI_TAG = -1;
15const CellTag TEMP_OFFSET_TRI_TAG_SET{TEMP_OFFSET_TRI_TAG};
16
17
19{
20public:
21 Vector2d m_posf;
22 int label = 0;
23
25 VertexAttributes2d(const Vector2d& p);
26};
27
28
30{
31public:
32 int label = 0;
33};
34
35
37{
38public:
39 int label = 0;
40 CellTag tag;
41};
42
43
45{
46public: // mode for splitting in marching tets
47 enum class EdgeSplitMode {
48 Midpoint = 0,
49 BinarySearch = 1, // requires that every edge being split has one vertex labelled 0 and the
50 // other 1 or 2
51 Initial = 2 // requires that every edge being split has one vertex labelled 0 and the other
52 // 1 or 2. This is really hacky. This initializes the offset using the minimum
53 // of half the target distance and half the edge length. Basically we want to
54 // initialize the offset with as high of quality as possible
55 };
56
57public:
58 int m_vtu_counter = 0;
59 std::array<size_t, 3> m_init_counts = {{0, 0, 0}};
60 size_t m_tags_count;
61 SimplicialComplexBVH m_input_complex_bvh;
62 EdgeSplitMode m_edge_split_mode = EdgeSplitMode::Midpoint;
63
64 // tag name maps
65 std::map<std::string, int64_t> m_tag_name_to_id;
66 std::map<int64_t, std::string> m_tag_id_to_name;
67 // std::vector<CellTag> m_offset_tags_ids;
68 CellTag m_offset_output_tag_ids;
69
70 // if in 'singlebody' mode
71 bool m_singlebody = false;
72 int64_t m_single_tag;
73
74 // just for retaining in output. dont actually use
75 bool m_has_envelope = false;
76 MatrixXd m_V_envelope;
77 MatrixXi m_F_envelope;
78
79 Parameters& m_params;
80
84 VertAttCol m_vertex_attribute;
85 EdgeAttCol m_edge_attribute;
86 FaceAttCol m_face_attribute;
87
88 TopoOffsetTriMesh(Parameters& _m_params, int _num_threads = 0)
89 : m_params(_m_params)
90 {
91 NUM_THREADS = _num_threads;
92 p_vertex_attrs = &m_vertex_attribute;
93 p_edge_attrs = &m_edge_attribute;
94 p_face_attrs = &m_face_attribute;
95 }
96
98
107 void init_from_image(
108 const MatrixXd& V,
109 const MatrixXi& F,
110 const MatrixSi& F_tags,
111 const MatrixXd& V_env,
112 const MatrixXi& F_env,
113 const std::vector<std::string>& tag_names);
114
118 void label_input_complex();
119
124 bool empty_input_complex();
125
130
136 void edge_split_binary_search(const size_t v1, const size_t v2, Vector2d& p_new) const;
137
139 bool split_edge_before(const Tuple& t) override;
140 bool split_edge_after(const Tuple& t) override;
141 bool split_face_before(const Tuple& t) override;
142 bool split_face_after(const Tuple& t) override;
143 bool invariants(const std::vector<Tuple>& tris) override;
145
146
153 void marching_tris();
154
155
157
161 bool is_simplicially_embedded() const;
162
167 bool tri_is_simp_emb(const Tuple& t) const;
168
174
175 // variable offset stuff
176
180 bool tag_tri_consistent_topology(size_t f_id, int64_t tag) const;
181
186 bool offset_tri_consistent_topology(const size_t f_id) const;
187
192 bool tri_is_in_offset_conservative(const size_t f_id, const double threshold_r) const;
193
200
205 void set_offset_tri_tags();
206
211 bool offset_is_manifold();
212
214 void write_input_complex(const std::string& path);
215 void write_vtu(const std::string& path);
216 // void write_msh(const std::string& file);
217 void write_msh_groups(const std::string& file);
219
220private:
227 {
228 size_t v1_id;
229 size_t v2_id;
230 VertexAttributes2d new_v;
231
232 // cache edge attributes
233 EdgeAttributes2d split_eattr;
234 std::map<simplex::Edge, EdgeAttributes2d> existing_eattr;
235
236 // cache face attributes
237 std::map<size_t, FaceAttributes2d> opp_v_fattr;
238 };
239 tbb::enumerable_thread_specific<EdgeSplitCache> edge_split_cache;
240
242 {
243 size_t v1_id;
244 size_t v2_id;
245 size_t v3_id;
246 VertexAttributes2d new_v;
247
248 std::map<simplex::Edge, EdgeAttributes2d> existing_eattr; // 3 orig edges
249 FaceAttributes2d split_fattr; // split face attributes
250 };
251 tbb::enumerable_thread_specific<FaceSplitCache> face_split_cache;
252
253private: // helpers
257 bool any_tag_present(const CellTag& tag1, const CellTag& tag2) const
258 {
259 for (const int64_t& i : tag1) {
260 if (tag2.find(i) != tag2.end()) {
261 return true;
262 }
263 }
264 return false;
265
266 // if (tag2.empty()) {
267 // return tag1.empty();
268 // }
269 // if (tag1.empty()) { // tag1 is ambient and tag2 is not
270 // return false;
271 // }
272
273 // for (const int64_t& i : tag1) {
274 // if (tag2.find(i) != tag2.end()) {
275 // return true;
276 // }
277 // }
278 // return false;
279 }
280
284 void sort_edges_by_length(std::vector<simplex::Edge>& edges)
285 {
286 std::sort(
287 edges.begin(),
288 edges.end(),
289 [this](const simplex::Edge& e1, const simplex::Edge& e2) {
290 double len1 = (m_vertex_attribute[e1.vertices()[0]].m_posf -
291 m_vertex_attribute[e1.vertices()[1]].m_posf)
292 .squaredNorm();
293 double len2 = (m_vertex_attribute[e2.vertices()[0]].m_posf -
294 m_vertex_attribute[e2.vertices()[1]].m_posf)
295 .squaredNorm();
296 return len1 > len2;
297 });
298 }
299
300public: // helpers
304 size_t edge_id_from_simplex(const simplex::Edge& e) const
305 {
306 const auto& verts = e.vertices();
307 const auto incident = simplex_incident_triangles(e);
308 const auto& faces = incident.faces();
309
310 assert(!faces.empty()); // throw error here otherwise
311
312 const size_t f_id = tuple_from_simplex(faces.front()).fid(*this);
313 const Tuple t_edge = tuple_from_edge(verts[0], verts[1], f_id);
314 return t_edge.eid(*this);
315 }
316
321 {
322 const auto& v = e.vertices();
323 const auto faces = simplex_incident_triangles(e).faces();
324 assert(!faces.empty());
325 const size_t fid = tuple_from_simplex(faces.front()).fid(*this);
326 return tuple_from_edge(v[0], v[1], fid);
327 }
328
332 std::vector<Tuple> get_edge_adjacent_faces(const Tuple& f) const
333 {
334 std::vector<Tuple> adj_tris;
335 auto tri_1 = f.switch_face(*this);
336 if (tri_1) {
337 adj_tris.push_back(tri_1.value());
338 }
339 auto tri_2 = f.switch_edge(*this).switch_face(*this);
340 if (tri_2) {
341 adj_tris.push_back(tri_2.value());
342 }
343 auto tri_3 = f.switch_vertex(*this).switch_edge(*this).switch_face(*this);
344 if (tri_3) {
345 adj_tris.push_back(tri_3.value());
346 }
347 return adj_tris;
348 }
349};
350
351
352} // namespace wmtk::components::topological_offset
Definition TriMesh.h:32
size_t fid(const TriMesh &) const
Definition TriMesh.h:80
Definition TriMesh.h:28
Tuple tuple_from_edge(size_t vid1, size_t vid2, size_t fid) const
Definition TriMesh.cpp:1479
void label_input_complex()
label input complex simplices as per boolean expression (or single body mode)
Definition TopoOffsetTriMesh.cpp:103
void init_from_image(const MatrixXd &V, const MatrixXi &F, const MatrixSi &F_tags, const MatrixXd &V_env, const MatrixXi &F_env, const std::vector< std::string > &tag_names)
initialize TriMesh from vertex, face, tag data
Definition TopoOffsetTriMesh.cpp:19
bool split_face_before(const Tuple &t) override
User specified preparations and desideratas for a face split.
Definition ComponentSplitting.cpp:637
void set_offset_tri_tags()
update 'tags' data for triangles in the offset region (tris labelled 2) based on the given offset tag...
Definition TopoOffsetTriMesh.cpp:713
bool offset_is_manifold()
verify that the closed offset region (simplices labelled 1 or 2) form a manifold region....
Definition TopoOffsetTriMesh.cpp:748
bool tag_tri_consistent_topology(size_t f_id, int64_t tag) const
check if removing the given face from the given tag set would retain its topology
Definition Spatial.cpp:327
void grow_offset_conservative()
grow offset region conservatively using conservative checks while ensuring consistent topology
Definition TopoOffsetTriMesh.cpp:654
bool empty_input_complex()
check if the input complex is empty. Only valid after calling init_from_image(...)....
Definition TopoOffsetTriMesh.cpp:359
void init_input_complex_bvh()
initialize BVH for input complex. Must be called after init_from_image(...)
Definition TopoOffsetTriMesh.cpp:372
size_t edge_id_from_simplex(const simplex::Edge &e) const
get global id of edge from simplex::Edge object
Definition TopoOffsetTriMesh.h:304
Tuple get_tuple_from_edge(const simplex::Edge &e) const
get Tuple simplex::Edge object
Definition TopoOffsetTriMesh.h:320
void marching_tris()
execute simplistic marching tets. All edges with one vertex labelled 0 and the other 1/2 are split....
Definition TopoOffsetTriMesh.cpp:588
void sort_edges_by_length(std::vector< simplex::Edge > &edges)
sort vector of edge simplices in place by decreasing length
Definition TopoOffsetTriMesh.h:284
bool split_edge_after(const Tuple &t) override
User specified modifications and desideratas after an edge split.
Definition ComponentSplitting.cpp:584
bool invariants(const std::vector< Tuple > &tris) override
User specified invariants that can't be violated.
Definition TopoOffsetTriMesh.cpp:796
bool split_edge_before(const Tuple &t) override
User specified preparations and desideratas for an edge split.
Definition ComponentSplitting.cpp:497
bool split_face_after(const Tuple &t) override
User specified modifications and desideratas after a face split.
Definition ComponentSplitting.cpp:668
bool any_tag_present(const CellTag &tag1, const CellTag &tag2) const
determine if any tag from tag1 is also present in tag2.
Definition TopoOffsetTriMesh.h:257
bool offset_tri_consistent_topology(const size_t f_id) const
check if adding a triangle to the offset region does not change the topology of the offset....
Definition Spatial.cpp:274
bool tri_is_in_offset_conservative(const size_t f_id, const double threshold_r) const
check if a triangle is inside the offset (implicitly defined via BVH distance field to input complex)...
Definition Spatial.cpp:233
void edge_split_binary_search(const size_t v1, const size_t v2, Vector2d &p_new) const
split edge at point by minimizing m_params.target_distance - d() (where d() is distance to input comp...
Definition ComponentSplitting.cpp:475
void simplicial_embedding()
make mesh a simplicial embedding of the input complex (simplices labelled 1)
Definition TopoOffsetTriMesh.cpp:525
std::vector< Tuple > get_edge_adjacent_faces(const Tuple &f) const
get faces (as Tuples) that are edge-adjacent to the given face (as Tuple)
Definition TopoOffsetTriMesh.h:332
bool is_simplicially_embedded() const
check if the input complex (simplices labelled 1) are simplicially embedded w.r.t....
Definition TopoOffsetTriMesh.cpp:480
bool tri_is_simp_emb(const Tuple &t) const
check if a triangle satisfies simpicial embedding criteria w.r.t. input complex (simplices labelled 1...
Definition TopoOffsetTriMesh.cpp:499
Definition Simplex.hpp:46