Wildmeshing Toolkit
Loading...
Searching...
No Matches
triangle_insertion.cpp
Go to the documentation of this file.
2
3
8
10
11#include <wmtk/Mesh.hpp>
12#include <wmtk/Scheduler.hpp>
13#include <wmtk/TetMesh.hpp>
14#include <wmtk/TriMesh.hpp>
17#include <wmtk/utils/Logger.hpp>
19
20
21// this should change! make a util?
23
24
26
27std::tuple<std::shared_ptr<wmtk::TetMesh>, ChildMeshes> triangle_insertion(
28 const TetMesh& bg_mesh,
29 const std::string& bg_position,
30 const TriMesh& mesh_in,
31 const std::string& in_position,
32 std::vector<attribute::MeshAttributeHandle>& pass_through,
33 bool round,
34 bool track_submeshes,
35 bool make_child_free)
36{
38 mesh_in.serialize(writer);
39
41 bg_mesh.serialize(writer_bg);
42
43 Eigen::MatrixXd V;
44 writer.get_double_matrix(in_position, PrimitiveType::Vertex, V);
45
46 Eigen::MatrixX<int64_t> F;
47 writer.get_FV_matrix(F);
48
49 Eigen::MatrixXd Vbg;
50 writer_bg.get_double_matrix(bg_position, PrimitiveType::Vertex, Vbg);
51
52 Eigen::MatrixX<int64_t> Fbg;
53 writer_bg.get_TV_matrix(Fbg);
54
55
56 /* new code for nonmanifold substructure and open boundaries*/
57
58 constexpr static PrimitiveType PV = PrimitiveType::Vertex;
59 constexpr static PrimitiveType PE = PrimitiveType::Edge;
60 constexpr static PrimitiveType PF = PrimitiveType::Triangle;
62
63 auto [tetmesh, tet_face_on_input_surface] =
65
66 /* -------------rounding------------ */
67
68 if (round) {
69 auto rounding_pt_attribute =
70 tetmesh->get_attribute_handle_typed<Rational>(in_position, PrimitiveType::Vertex);
71
72 std::shared_ptr<Mesh> m_ptr = tetmesh;
73
74 auto rounding = std::make_shared<wmtk::operations::Rounding>(*m_ptr, rounding_pt_attribute);
75 rounding->add_invariant(
76 std::make_shared<SimplexInversionInvariant<Rational>>(*m_ptr, rounding_pt_attribute));
77
78 Scheduler scheduler;
79 auto stats = scheduler.run_operation_on_all(*rounding);
80
81 logger().info(
82 "Executed rounding, {} ops (S/F) {}/{}. Time: collecting: {}, sorting: {}, "
83 "executing: {}",
84 stats.number_of_performed_operations(),
85 stats.number_of_successful_operations(),
86 stats.number_of_failed_operations(),
87 stats.collecting_time,
88 stats.sorting_time,
89 stats.executing_time);
90 }
91
92 ChildMeshes child_meshes;
93
94 if (track_submeshes) {
95 /* -----------input surface--------- */
96
97 logger().trace("Registering input surface from tag surface");
98 auto surface_handle =
99 tetmesh->register_attribute<int64_t>("surface", PrimitiveType::Triangle, 1);
100 auto surface_accessor = tetmesh->create_accessor<int64_t>(surface_handle);
101
102 // register surface tag
103
104 const auto& tets = tetmesh->get_all(PrimitiveType::Tetrahedron);
105 assert(tets.size() == tet_face_on_input_surface.size());
106
107 logger().info("Assigning surface tags");
108 for (int64_t i = 0; i < tets.size(); ++i) {
109 const auto& t = tets[i]; // local face 2
110 std::array<Tuple, 4> fs = {
111 {tetmesh->switch_tuples(t, {PV, PE, PF}),
112 tetmesh->switch_tuples(t, {PE, PF}),
113 t,
114 tetmesh->switch_tuples(t, {PF})}};
115
116 for (int64_t k = 0; k < 4; ++k) {
117 if (tet_face_on_input_surface[i][k]) {
118 surface_accessor.scalar_attribute(fs[k]) = 1;
119 } else {
120 surface_accessor.scalar_attribute(fs[k]) = 0;
121 }
122 }
123 }
124
125 pass_through.push_back(surface_handle);
126
127
128 // get multimesh from tag
129
130 if (make_child_free) {
131 logger().info("Making free child surface mesh");
132 child_meshes.surface_mesh =
134 *tetmesh,
135 surface_handle.as<int64_t>(),
136 1,
137 /*free = */ true);
138
139 } else {
140 logger().info("Making child surface mesh");
141 internal::MultiMeshFromTag SurfaceMeshFromTag(*tetmesh, surface_handle, 1);
142 SurfaceMeshFromTag.compute_substructure_mesh();
143
144 child_meshes.surface_mesh = tetmesh->get_child_meshes().back();
145
146 SurfaceMeshFromTag.remove_soup();
147 }
148
149 /* -----------open boundary and nonmanifold edges in input surface--------- */
150
151 logger().info("Going through open/nonmanifold stuff");
152 auto open_boundary_handle =
153 tetmesh->register_attribute<int64_t>("open_boundary", PrimitiveType::Edge, 1);
154 auto open_boundary_accessor = tetmesh->create_accessor<int64_t>(open_boundary_handle);
155
156 auto nonmanifold_edge_handle =
157 tetmesh->register_attribute<int64_t>("nonmanifold_edge", PrimitiveType::Edge, 1);
158 auto nonmanifold_edge_accessor = tetmesh->create_accessor<int64_t>(nonmanifold_edge_handle);
159
160 pass_through.push_back(open_boundary_handle);
161 pass_through.push_back(nonmanifold_edge_handle);
162
163 // register edge tags
164 bool has_openboundary = false;
165 bool has_nonmanifold_edge = false;
166
167 logger().info("Looping edges for open/nonmanifold ones");
168 for (const auto& e : child_meshes.surface_mesh->get_all(PrimitiveType::Edge)) {
169 const auto surface_edge = simplex::Simplex::edge(*child_meshes.surface_mesh, e);
170 if (!child_meshes.surface_mesh->is_boundary(surface_edge)) continue;
171
172 const auto& parent_e = child_meshes.surface_mesh->map_to_parent(surface_edge);
173 const auto& child_e =
174 tetmesh->map_to_child_tuples(*child_meshes.surface_mesh, parent_e);
175
176 assert(child_e.size() > 0);
177
178 if (child_e.size() == 1) {
179 // if edge is a boundary on the surface mesh and only appears once,
180 // then it is an open boundary
181 open_boundary_accessor.scalar_attribute(parent_e.tuple()) = 1;
182 has_openboundary = true;
183 } else {
184 // else it is a nonmanifold edge in the input surface
185 nonmanifold_edge_accessor.scalar_attribute(parent_e.tuple()) = 1;
186 has_nonmanifold_edge = true;
187 }
188 }
189
190 const bool process_nonmanifold_edges = !make_child_free && has_nonmanifold_edge;
191
192 // get multimeshes from tag
193
194 if (has_openboundary) {
195 if (make_child_free) {
196 logger().error("Creating free open boundary child mesh");
197 child_meshes.open_boundary_mesh =
199 *tetmesh,
200 open_boundary_handle.as<int64_t>(),
201 1,
202 /*free = */ true);
203
204 } else {
205 logger().error("Creating open boundary child mesh");
206 internal::MultiMeshFromTag OpenBoundaryFromTag(*tetmesh, open_boundary_handle, 1);
207 OpenBoundaryFromTag.compute_substructure_mesh();
208
209 child_meshes.open_boundary_mesh = tetmesh->get_child_meshes().back();
210 OpenBoundaryFromTag.remove_soup();
211 }
212 }
213
214 if (process_nonmanifold_edges) {
215 logger().info("Creating nonmanifold edge mesh");
216 internal::MultiMeshFromTag NonmanifoldEdgeFromTag(*tetmesh, nonmanifold_edge_handle, 1);
217 NonmanifoldEdgeFromTag.compute_substructure_mesh();
218
219 child_meshes.nonmanifold_edge_mesh = tetmesh->get_child_meshes().back();
220 NonmanifoldEdgeFromTag.remove_soup();
221 }
222
223 /* ---------------------bounding box-------------------------*/
224 auto bbox_handle = tetmesh->register_attribute<int64_t>("bbox", PrimitiveType::Triangle, 1);
225 auto bbox_accessor = tetmesh->create_accessor<int64_t>(bbox_handle);
226
227 pass_through.push_back(bbox_handle);
228
229 logger().info("Annotating bounding box boundary");
230 for (const auto& f : tetmesh->get_all(PrimitiveType::Triangle)) {
231 bbox_accessor.scalar_attribute(f) =
232 tetmesh->is_boundary(PrimitiveType::Triangle, f) ? 1 : 0;
233 }
234
235 internal::MultiMeshFromTag NonmanifoldEdgeFromTag(*tetmesh, bbox_handle, 1);
236 NonmanifoldEdgeFromTag.compute_substructure_mesh();
237
238 child_meshes.bbox_mesh = tetmesh->get_child_meshes().back();
239 NonmanifoldEdgeFromTag.remove_soup();
240
241
242 /* -----------nonmanifold vertices in input surface--------- */
243
244 logger().info("Nonmanifold vertices");
245 auto nonmanifold_vertex_handle =
246 tetmesh->register_attribute<int64_t>("nonmanifold_vertex", PrimitiveType::Vertex, 1);
247 auto nonmanifold_vertex_accessor =
248 tetmesh->create_accessor<int64_t>(nonmanifold_vertex_handle);
249
250 pass_through.push_back(nonmanifold_vertex_handle);
251
252 for (const auto& v : tetmesh->get_all(PrimitiveType::Vertex)) {
253 int64_t on_open_boundary_cnt = 0;
254 int64_t on_nonmanifold_edge_cnt = 0;
255
256 if (has_openboundary) {
257 on_open_boundary_cnt = tetmesh
258 ->map_to_child(
259 *child_meshes.open_boundary_mesh,
260 simplex::Simplex::vertex(*tetmesh, v))
261 .size();
262 }
263 if (process_nonmanifold_edges) {
264 on_nonmanifold_edge_cnt = tetmesh
265 ->map_to_child(
266 *child_meshes.nonmanifold_edge_mesh,
267 simplex::Simplex::vertex(*tetmesh, v))
268 .size();
269 }
270
271 if (on_open_boundary_cnt + on_open_boundary_cnt > 1) {
272 // if on the edgemeshes and more than 1 copy
273 nonmanifold_vertex_accessor.scalar_attribute(v) = 1;
274 } else if (
275 // not on the edgemeshes and more than 1 copy on the surface mesh
276 on_open_boundary_cnt + on_nonmanifold_edge_cnt == 0 &&
277 tetmesh->map_to_child(
278 *child_meshes.surface_mesh,
279 simplex::Simplex::vertex(*tetmesh, v))
280 .size() > 1) {
281 nonmanifold_vertex_accessor.scalar_attribute(v) = 1;
282 }
283 }
284
285 // TODO: register as child mesh
286
287 // remove all soups
288 // NonmanifoldEdgeFromTag.remove_soup();
289 // OpenBoundaryFromTag.remove_soup();
290 // SurfaceMeshFromTag.remove_soup();
291
292
293 /* ------------------ post processing -------------------*/
294
295 logger().info("Propagating position to child meshes");
296 // propagate position to all child meshes
297 auto pt_attribute =
298 tetmesh->get_attribute_handle<Rational>(in_position, PrimitiveType::Vertex);
299
300 for (auto child : tetmesh->get_child_meshes()) {
301 auto child_position_handle = child->register_attribute<Rational>(
302 in_position,
304 tetmesh->get_attribute_dimension(pt_attribute.as<Rational>()));
305
306 auto propagate_to_child_position =
307 [](const Eigen::MatrixX<Rational>& P) -> Eigen::VectorX<Rational> { return P; };
308 auto update_child_positon = std::make_shared<
310 child_position_handle,
311 pt_attribute,
312 propagate_to_child_position);
313 update_child_positon->run_on_all();
314 }
315
316 // send to cache
317
318 logger().info(
319 "TetMesh created: {} tets, {} faces, {} edges, {} vertices",
320 tetmesh->capacity(PrimitiveType::Tetrahedron),
321 tetmesh->capacity(PrimitiveType::Triangle),
322 tetmesh->capacity(PrimitiveType::Edge),
323 tetmesh->capacity(PrimitiveType::Vertex));
324
325 logger().info("Surface child TriMesh registered");
326
327 if (has_openboundary) {
328 logger().info("Open boundary child EdgeMesh registered");
329 }
330 if (process_nonmanifold_edges) {
331 logger().info("Nonmanifold edge child EdgeMesh registered");
332 }
333
334 logger().info("Bbox child TriMesh registered");
335 }
336
337 return std::make_tuple(tetmesh, child_meshes);
338}
339
340} // namespace wmtk::components::triangle_insertion
void serialize(MeshWriter &writer, const Mesh *local_root=nullptr) const
Definition Mesh.cpp:93
SchedulerStats run_operation_on_all(operations::Operation &op)
Definition Scheduler.cpp:33
This class generates a multi-mesh from a mesh where the substructure is represented by a tag.
void remove_soup()
Remove the substructure soup from the multimesh.
void compute_substructure_mesh()
Create a manifold mesh from the substructure.
static Simplex edge(const Mesh &m, const Tuple &t)
Definition Simplex.hpp:61
static Simplex vertex(const Mesh &m, const Tuple &t)
Definition Simplex.hpp:56
void get_TV_matrix(MatrixX< int64_t > &matrix)
void get_FV_matrix(MatrixX< int64_t > &matrix)
void get_double_matrix(const std::string &name, const PrimitiveType type, MatrixX< double > &matrix)
constexpr wmtk::PrimitiveType PT
constexpr wmtk::PrimitiveType PF
std::tuple< std::shared_ptr< wmtk::TetMesh >, ChildMeshes > triangle_insertion(const TetMesh &bg_mesh, const std::string &bg_position, const TriMesh &mesh_in, const std::string &in_position, std::vector< attribute::MeshAttributeHandle > &pass_through, bool round, bool track_submeshes, bool make_child_free)
std::shared_ptr< Mesh > extract_and_register_child_mesh_from_tag_handle(Mesh &m, const wmtk::attribute::TypedAttributeHandle< int64_t > &tag_handle, const int64_t tag_value, bool child_is_free)
extract a child mesh based on the tag handle and the tag value, and register it to the input (parent)...
std::tuple< std::shared_ptr< wmtk::TetMesh >, std::vector< std::array< bool, 4 > > > generate_raw_tetmesh_from_input_surface(const RowVectors3d &V, const RowVectors3l &F, const RowVectors3d &background_V, const RowVectors4l &background_TV)
input a triangle surface mesh, embed it into a background tet mesh, track the input surfaces on the t...
constexpr PrimitiveType PE
spdlog::logger & logger()
Retrieves the current logger.
Definition Logger.cpp:58
constexpr PrimitiveType PV