3#include "wmtk/TetMesh.h"
4#include "wmtk/utils/GeoUtils.h"
7#include <wmtk/utils/DisableWarnings.hpp>
8#include <tbb/concurrent_map.h>
9#include <wmtk/utils/EnableWarnings.hpp>
15#include <wmtk/Types.hpp>
25void match_tet_faces_to_triangles(
27 const std::vector<std::array<size_t, 3>>& faces,
28 tbb::concurrent_vector<bool>& is_matched,
29 tbb::concurrent_map<std::array<size_t, 3>, std::vector<int>>& tet_face_tags);
31bool remove_duplicates(
32 std::vector<Vector3d>& vertices,
33 std::vector<std::array<size_t, 3>>& faces,
34 const double epsilon);
36template <
typename rational>
37auto triangle_insert_prepare_info(
39 const std::array<size_t, 3>& face_v,
40 std::vector<std::array<size_t, 3>>& marking_tet_faces,
41 const std::function<
bool(
const std::array<size_t, 3>&)>& try_acquire_triangle,
42 const std::function<
bool(
const std::vector<wmtk::TetMesh::Tuple>&)>& try_acquire_tetra,
43 const std::function<Eigen::Matrix<rational, 3, 1>(
size_t)>& vertex_pos_r)
45 using Vector3r = Eigen::Matrix<rational, 3, 1>;
46 using Vector2r = Eigen::Matrix<rational, 2, 1>;
48 constexpr int EMPTY_INTERSECTION = 0;
49 constexpr int TRI_INTERSECTION = 1;
50 constexpr int PLN_INTERSECTION = 2;
52 static constexpr std::array<std::array<int, 2>, 6> map_leid2lfids = {
53 {{{0, 2}}, {{0, 3}}, {{0, 1}}, {{1, 2}}, {{2, 3}}, {{1, 3}}}};
54 static constexpr std::array<std::array<int, 3>, 4> local_faces = {
55 {{{0, 1, 2}}, {{0, 2, 3}}, {{0, 1, 3}}, {{1, 2, 3}}}};
56 static constexpr std::array<std::array<int, 2>, 6> local_edges = {
57 {{{0, 1}}, {{1, 2}}, {{0, 2}}, {{0, 3}}, {{1, 3}}, {{2, 3}}}};
59 bool success_flag =
false;
60 std::set<size_t> visited;
62 std::array<Vector3r, 3> tri = {
63 vertex_pos_r(face_v[0]),
64 vertex_pos_r(face_v[1]),
65 vertex_pos_r(face_v[2])};
67 Vector3r tri_normal = (tri[1] - tri[0]).cross(tri[2] - tri[0]);
69 std::array<Vector2r, 3> tri2;
70 int squeeze_to_2d_dir = wmtk::project_triangle_to_2d(tri, tri2);
72 std::vector<Tuple> intersected_tets;
73 std::map<std::array<size_t, 2>, std::tuple<int, Vector3r, size_t, int>> map_edge2point;
74 std::map<std::array<size_t, 3>,
bool> map_face2intersected;
77 std::set<std::array<size_t, 2>> intersected_tet_edges;
79 std::queue<Tuple> tet_queue;
81 if (!try_acquire_triangle(face_v)) {
86 std::vector<Vector3r>());
89 for (
int j = 0; j < 3; j++) {
92 for (
const auto& t : conn_tets) {
93 if (visited.find(t.tid(m)) != visited.end())
continue;
95 visited.insert(t.tid(m));
99 constexpr auto is_seg_cut_tri_2 = [](
const std::array<Vector2r, 2>& seg2d,
100 const std::array<Vector2r, 3>& tri2d) {
102 bool is_inside = wmtk::is_point_inside_triangle(seg2d[0], tri2d) ||
103 wmtk::is_point_inside_triangle(seg2d[1], tri2d);
107 for (
int j = 0; j < 3; j++) {
108 std::array<Vector2r, 2> tri_seg2 = {{tri2d[j], tri2d[(j + 1) % 3]}};
110 bool is_intersected =
111 wmtk::open_segment_open_segment_intersection_2d(seg2d, tri_seg2, _);
112 if (is_intersected) {
121 while (!tet_queue.empty()) {
122 auto tet = tet_queue.front();
125 std::array<bool, 4> is_tet_face_intersected = {{
false,
false,
false,
false}};
130 std::map<size_t, int> vertex_sides;
131 std::vector<int> coplanar_f_lvids;
135 auto retry_flag = !try_acquire_tetra(std::vector<Tuple>{{tet}});
139 std::vector<Tuple>(),
140 std::vector<Tuple>(),
141 std::vector<Vector3r>());
144 std::array<size_t, 4> vertex_vids;
145 for (
int j = 0; j < 4; j++) {
146 vertex_vids[j] = vs[j].vid(m);
147 Vector3r dir = vertex_pos_r(vertex_vids[j]) - tri[0];
148 auto side = dir.dot(tri_normal);
151 vertex_sides[vertex_vids[j]] = 1;
152 }
else if (side < 0) {
154 vertex_sides[vertex_vids[j]] = -1;
156 coplanar_f_lvids.push_back(j);
157 vertex_sides[vertex_vids[j]] = 0;
161 if (coplanar_f_lvids.size() == 1) {
162 int lvid = coplanar_f_lvids[0];
163 size_t vid = vertex_vids[lvid];
164 auto p = wmtk::project_point_to_2d(vertex_pos_r(vid), squeeze_to_2d_dir);
165 bool is_inside = wmtk::is_point_inside_triangle(p, tri2);
169 for (
auto& t : conn_tets) {
170 if (visited.find(t.tid(m)) != visited.end())
continue;
171 visited.insert(t.tid(m));
175 }
else if (coplanar_f_lvids.size() == 2) {
176 std::array<Vector2r, 2> seg2;
177 seg2[0] = wmtk::project_point_to_2d(
178 vertex_pos_r(vertex_vids[coplanar_f_lvids[0]]),
180 seg2[1] = wmtk::project_point_to_2d(
181 vertex_pos_r(vertex_vids[coplanar_f_lvids[1]]),
183 if (is_seg_cut_tri_2(seg2, tri2)) {
184 std::array<int, 2> le = {{coplanar_f_lvids[0], coplanar_f_lvids[1]}};
185 if (le[0] > le[1]) std::swap(le[0], le[1]);
187 std::find(local_edges.begin(), local_edges.end(), le) - local_edges.begin();
188 is_tet_face_intersected[map_leid2lfids[leid][0]] =
true;
189 is_tet_face_intersected[map_leid2lfids[leid][1]] =
true;
191 for (
int j = 0; j < 2; j++) {
193 for (
auto& t : conn_tets) {
194 if (visited.find(t.tid(m)) != visited.end())
continue;
195 visited.insert(t.tid(m));
201 }
else if (coplanar_f_lvids.size() == 3) {
203 for (
int i = 0; i < 3; i++) {
204 std::array<Vector2r, 2> seg2;
205 seg2[0] = wmtk::project_point_to_2d(
206 vertex_pos_r(vertex_vids[coplanar_f_lvids[i]]),
208 seg2[1] = wmtk::project_point_to_2d(
209 vertex_pos_r(vertex_vids[coplanar_f_lvids[(i + 1) % 3]]),
211 if (is_seg_cut_tri_2(seg2, tri2)) {
217 std::array<size_t, 3> f = {
218 {vertex_vids[coplanar_f_lvids[0]],
219 vertex_vids[coplanar_f_lvids[1]],
220 vertex_vids[coplanar_f_lvids[2]]}};
221 std::sort(f.begin(), f.end());
222 marking_tet_faces.push_back(f);
225 for (
int j = 0; j < 3; j++) {
227 for (
auto& t : conn_tets) {
228 if (visited.find(t.tid(m)) != visited.end())
continue;
229 visited.insert(t.tid(m));
237 if (cnt_pos == 0 || cnt_neg == 0) {
242 std::array<Tuple, 6> edges = m.
tet_edges(tet);
244 std::vector<std::array<size_t, 2>> edge_vids;
245 for (
auto& loc : edges) {
246 size_t v1_id = loc.vid(m);
248 size_t v2_id = tmp.
vid(m);
249 std::array<size_t, 2> e = {{v1_id, v2_id}};
250 if (e[0] > e[1]) std::swap(e[0], e[1]);
251 edge_vids.push_back(e);
255 bool need_subdivision =
false;
256 for (
int l_eid = 0; l_eid < edges.size(); l_eid++) {
257 const std::array<size_t, 2>& e = edge_vids[l_eid];
258 if (vertex_sides[e[0]] * vertex_sides[e[1]] >= 0)
continue;
260 if (map_edge2point.find(e) != map_edge2point.end()) {
261 if (std::get<0>(map_edge2point[e]) == TRI_INTERSECTION) {
262 for (
int k = 0; k < 2; k++)
263 is_tet_face_intersected[map_leid2lfids[l_eid][k]] =
true;
264 need_subdivision =
true;
269 std::array<Vector3r, 2> seg = {{vertex_pos_r(e[0]), vertex_pos_r(e[1])}};
271 int intersection_status = EMPTY_INTERSECTION;
272 bool is_inside_tri =
false;
273 bool is_intersected_plane =
274 wmtk::open_segment_plane_intersection_3d(seg, tri, p, is_inside_tri);
275 if (is_intersected_plane && is_inside_tri) {
276 intersection_status = TRI_INTERSECTION;
277 }
else if (is_intersected_plane) {
278 intersection_status = PLN_INTERSECTION;
281 map_edge2point[e] = std::make_tuple(intersection_status, p, tet.tid(m), l_eid);
282 if (intersection_status == EMPTY_INTERSECTION) {
284 }
else if (intersection_status == TRI_INTERSECTION) {
285 for (
int k = 0; k < 2; k++)
286 is_tet_face_intersected[map_leid2lfids[l_eid][k]] =
true;
287 need_subdivision =
true;
291 if (need_subdivision) {
293 for (
const auto& t : incident_tets) {
294 size_t tid = t.tid(m);
295 if (visited.find(tid) != visited.end()) {
306 for (
int j = 0; j < 4; j++) {
307 if (is_tet_face_intersected[j])
continue;
308 std::array<size_t, 3> f = {
309 {vs[local_faces[j][0]].vid(m),
310 vs[local_faces[j][1]].vid(m),
311 vs[local_faces[j][2]].vid(m)}};
312 std::sort(f.begin(), f.end());
313 auto it = map_face2intersected.find(f);
314 if (it != map_face2intersected.end()) {
315 if (it->second) need_subdivision =
true;
322 for (
int k = 0; k < 3; k++) {
323 if (vertex_sides[f[k]] > 0)
325 else if (vertex_sides[f[k]] < 0)
328 if (cnt_pos1 == 0 || cnt_neg1 == 0)
continue;
331 std::array<Vector3r, 3> tet_tri = {
332 {vertex_pos_r(f[0]), vertex_pos_r(f[1]), vertex_pos_r(f[2])}};
334 std::array<int, 3> tet_tri_v_sides;
335 Vector3r tet_tri_normal = (tet_tri[1] - tet_tri[0]).cross(tet_tri[2] - tet_tri[0]);
336 for (
int k = 0; k < 3; k++) {
337 Vector3r dir = tri[k] - tet_tri[0];
338 auto side = dir.dot(tet_tri_normal);
340 tet_tri_v_sides[k] = 0;
342 tet_tri_v_sides[k] = 1;
344 tet_tri_v_sides[k] = -1;
347 bool is_intersected =
false;
348 for (
int k = 0; k < 3; k++) {
349 if ((tet_tri_v_sides[k] >= 0 && tet_tri_v_sides[(k + 1) % 3] >= 0) ||
350 (tet_tri_v_sides[k] <= 0 && tet_tri_v_sides[(k + 1) % 3] <= 0))
353 is_intersected = wmtk::open_segment_triangle_intersection_3d(
354 {{tri[k], tri[(k + 1) % 3]}},
357 if (is_intersected) {
358 need_subdivision =
true;
362 map_face2intersected[f] = is_intersected;
364 if (is_intersected) {
366 if (res.has_value()) {
367 auto n_tet = res.value();
368 size_t tid = n_tet.tid(m);
369 if (visited.find(tid) != visited.end()) {
373 tet_queue.push(n_tet);
381 if (need_subdivision) {
382 intersected_tets.push_back(tet);
384 for (
auto& e : edge_vids) {
385 intersected_tet_edges.insert(e);
392 for (
auto it = map_edge2point.begin(), ite = map_edge2point.end(); it != ite;) {
393 if (std::get<0>(it->second) == EMPTY_INTERSECTION ||
394 intersected_tet_edges.find(it->first) == intersected_tet_edges.end())
395 it = map_edge2point.erase(it);
400 std::vector<TetMesh::Tuple> intersected_edges;
401 std::vector<Vector3r> intersected_pos;
402 for (
auto& info : map_edge2point) {
403 auto& [_, p, tid, l_eid] = info.second;
405 intersected_pos.push_back(p);
407 return std::tuple(success_flag, intersected_tets, intersected_edges, intersected_pos);
a Tuple refers to a global vid and a global tet id, and a local edge id and local face id
Definition TetMesh.h:49
size_t vid(const TetMesh &m) const
Definition TetMeshTuple.cpp:106
std::array< Tuple, 6 > tet_edges(const Tuple &t) const
get the 6 edges of a tet represented by Tuples
Definition TetMesh.cpp:677
std::array< Tuple, 4 > oriented_tet_vertices(const Tuple &t) const
Definition TetMesh.cpp:637
std::vector< Tuple > get_incident_tets_for_edge(const Tuple &t) const
Get the incident tets for edge.
Definition TetMesh.cpp:781
Tuple tuple_from_vertex(size_t vid) const
get a Tuple from global vertex index
Definition TetMesh.cpp:567
std::optional< Tuple > switch_tetrahedron(const Tuple &t) const
wrapper function from Tuple::switch_tetrahedron
Definition TetMesh.h:948
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
Tuple switch_vertex(const Tuple &t) const
wrapper function from Tuple::switch_vertex
Definition TetMesh.h:921
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:363
std::vector< Tuple > get_one_ring_tets_for_vertex(const Tuple &t) const
Get the one ring tets for a vertex.
Definition TetMesh.cpp:701