14 #include <VolumeRemesher/embed.h>
19 #include <polysolve/Utils.hpp>
24 std::tuple<std::shared_ptr<wmtk::TetMesh>, std::vector<std::array<bool, 4>>>
31 polysolve::StopWatch timer(
"tri insertion",
logger());
35 std::vector<double> tri_vrt_coords(V.rows() * 3);
36 std::vector<uint32_t> triangle_indices(F.rows() * 3);
37 std::vector<double> tet_vrt_coords(background_V.rows() * 3);
38 std::vector<uint32_t> tet_indices(background_TV.rows() * 4);
40 for (int64_t i = 0; i < V.rows(); ++i) {
41 tri_vrt_coords[i * 3 + 0] = V(i, 0);
42 tri_vrt_coords[i * 3 + 1] = V(i, 1);
43 tri_vrt_coords[i * 3 + 2] = V(i, 2);
46 for (int64_t i = 0; i < F.rows(); ++i) {
47 triangle_indices[i * 3 + 0] = F(i, 0);
48 triangle_indices[i * 3 + 1] = F(i, 1);
49 triangle_indices[i * 3 + 2] = F(i, 2);
52 for (int64_t i = 0; i < background_V.rows(); ++i) {
53 tet_vrt_coords[i * 3 + 0] = background_V(i, 0);
54 tet_vrt_coords[i * 3 + 1] = background_V(i, 1);
55 tet_vrt_coords[i * 3 + 2] = background_V(i, 2);
58 for (int64_t i = 0; i < background_TV.rows(); ++i) {
59 tet_indices[i * 4 + 0] = background_TV(i, 0);
60 tet_indices[i * 4 + 1] = background_TV(i, 1);
61 tet_indices[i * 4 + 2] = background_TV(i, 2);
62 tet_indices[i * 4 + 3] = background_TV(i, 3);
66 std::vector<vol_rem::bigrational> embedded_vertices;
67 std::vector<uint32_t> embedded_facets;
68 std::vector<uint32_t> embedded_cells;
69 std::vector<uint32_t> embedded_facets_on_input;
70 std::vector<std::array<uint32_t, 4>> tets_final;
71 std::vector<uint32_t> final_tets_parent;
72 std::vector<bool> cells_with_faces_on_input;
73 std::vector<std::vector<uint32_t>> final_tets_parent_faces;
76 vol_rem::embed_tri_in_poly_mesh(
86 embedded_facets_on_input,
87 cells_with_faces_on_input,
88 final_tets_parent_faces,
91 assert(tets_final.size() == final_tets_parent.size());
94 "volume remesher finished {}s, polycell mesh generated, #vertices: {}, #cells: {}, #tets "
96 timer.getElapsedTimeInSec(),
97 embedded_vertices.size() / 3,
98 embedded_cells.size(),
102 std::vector<Vector3r> v_coords;
103 std::vector<std::array<int64_t, 3>> polygon_faces;
104 std::vector<bool> polygon_faces_on_input;
105 std::vector<std::array<bool, 4>> tet_face_on_input_surface;
109 int64_t round_cnt = 0;
110 for (int64_t i = 0; i < embedded_vertices.size() / 3; ++i) {
111 #ifdef USE_GNU_GMP_CLASSES
112 v_coords.emplace_back();
113 v_coords.back()[0].init(embedded_vertices[3 * i + 0].get_mpq_t());
114 v_coords.back()[1].init(embedded_vertices[3 * i + 1].get_mpq_t());
115 v_coords.back()[2].init(embedded_vertices[3 * i + 2].get_mpq_t());
117 v_coords.emplace_back();
118 v_coords.back()[0].init_from_binary(embedded_vertices[3 * i + 0].get_str());
119 v_coords.back()[1].init_from_binary(embedded_vertices[3 * i + 1].get_str());
120 v_coords.back()[2].init_from_binary(embedded_vertices[3 * i + 2].get_str());
125 for (int64_t j = 0; j < 3; ++j) {
126 if (!v_coords.back()[j].can_be_rounded()) {
134 for (int64_t j = 0; j < 3; ++j) v_coords.back()[j].round();
137 wmtk::logger().info(
"done, {} rounded vertices over {}", round_cnt, v_coords.size());
140 for (int64_t i = 0; i < embedded_facets.size(); ++i) {
141 int64_t polysize = embedded_facets[i];
142 assert(polysize == 3);
143 std::array<int64_t, 3> polygon;
144 for (int64_t j = i + 1; j <= i + polysize; ++j) {
145 polygon[j - (i + 1)] = embedded_facets[j];
147 polygon_faces.push_back(polygon);
153 polygon_faces_on_input.resize(polygon_faces.size(),
false);
154 for (int64_t i = 0; i < embedded_facets_on_input.size(); ++i) {
155 polygon_faces_on_input[embedded_facets_on_input[i]] =
true;
162 assert(final_tets_parent_faces.size() == tets_final.size());
163 for (int64_t i = 0; i < tets_final.size(); ++i) {
164 const auto& tetra = tets_final[i];
165 const uint32_t tetra_parent = final_tets_parent[i];
167 if (!cells_with_faces_on_input[tetra_parent]) {
168 tet_face_on_input_surface.push_back({{
false,
false,
false,
false}});
173 std::array<int64_t, 3> local_f0{{tetra[1], tetra[2], tetra[3]}};
174 std::sort(local_f0.begin(), local_f0.end());
175 std::array<int64_t, 3> local_f1{{tetra[0], tetra[2], tetra[3]}};
176 std::sort(local_f1.begin(), local_f1.end());
177 std::array<int64_t, 3> local_f2{{tetra[0], tetra[1], tetra[3]}};
178 std::sort(local_f2.begin(), local_f2.end());
179 std::array<int64_t, 3> local_f3{{tetra[0], tetra[1], tetra[2]}};
180 std::sort(local_f3.begin(), local_f3.end());
183 std::array<bool, 4> tet_face_on_input{{
false,
false,
false,
false}};
184 for (
auto f : final_tets_parent_faces[i]) {
185 assert(polygon_faces[f].size() == 3);
187 auto f_vs = polygon_faces[f];
188 std::sort(f_vs.begin(), f_vs.end());
190 int64_t local_f_idx = -1;
194 if (f_vs == local_f0) {
196 }
else if (f_vs == local_f1) {
198 }
else if (f_vs == local_f2) {
203 assert(local_f_idx >= 0);
205 tet_face_on_input[local_f_idx] = polygon_faces_on_input[f];
208 tet_face_on_input_surface.push_back(tet_face_on_input);
211 wmtk::logger().info(
"took: {}", timer.getElapsedTimeInSec());
213 wmtk::logger().info(
"removing unreferenced vertices...");
215 std::vector<bool> v_is_used_in_tet(v_coords.size(),
false);
216 for (
const auto& t : tets_final) {
217 for (
const auto& v : t) {
218 v_is_used_in_tet[v] =
true;
221 std::vector<int64_t> v_map(v_coords.size(), -1);
222 std::vector<Vector3r> v_coords_final;
224 for (int64_t i = 0; i < v_coords.size(); ++i) {
225 if (v_is_used_in_tet[i]) {
226 v_map[i] = v_coords_final.size();
227 v_coords_final.emplace_back(v_coords[i]);
230 for (
auto& t : tets_final) {
231 for (
int i = 0; i < 4; ++i) {
232 assert(v_map[t[i]] >= 0);
237 wmtk::logger().info(
"took: {}", timer.getElapsedTimeInSec());
268 RowVectors3r V_final_rational(v_coords_final.size(), 3);
271 for (int64_t i = 0; i < v_coords_final.size(); ++i) {
272 V_final_rational.row(i) = v_coords_final[i];
275 for (int64_t i = 0; i < tets_final.size(); ++i) {
276 assert(tets_final[i][0] < V_final_rational.rows());
277 assert(tets_final[i][1] < V_final_rational.rows());
278 assert(tets_final[i][2] < V_final_rational.rows());
279 assert(tets_final[i][3] < V_final_rational.rows());
281 assert(tets_final[i][0] != tets_final[i][1]);
282 assert(tets_final[i][0] != tets_final[i][2]);
283 assert(tets_final[i][0] != tets_final[i][3]);
285 assert(tets_final[i][1] != tets_final[i][2]);
286 assert(tets_final[i][1] != tets_final[i][3]);
288 assert(tets_final[i][2] != tets_final[i][3]);
290 TV_final.row(i) << tets_final[i][0], tets_final[i][1], tets_final[i][2], tets_final[i][3];
296 std::shared_ptr<wmtk::TetMesh> m = std::make_shared<wmtk::TetMesh>();
297 m->initialize(TV_final);
303 if (!m->is_connectivity_valid()) {
304 wmtk::logger().error(
"invalid tetmesh connectivity after insertion");
305 throw std::runtime_error(
"invalid tetmesh connectivity by insertion");
307 return std::make_tuple(m, tet_face_on_input_surface);
attribute::MeshAttributeHandle set_matrix_attribute(const Mat &data, const std::string &name, const PrimitiveType &type, Mesh &mesh)
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...
RowVectors< int64_t, 3 > RowVectors3l
RowVectors< int64_t, 4 > RowVectors4l
spdlog::logger & logger()
Retrieves the current logger.
RowVectors< double, 3 > RowVectors3d
RowVectors< Rational, 3 > RowVectors3r