Wildmeshing Toolkit
Loading...
Searching...
No Matches
tetmesh_topology_initialization.cpp
Go to the documentation of this file.
2#include <algorithm>
3#include <fstream>
4#include <iostream>
5#include <vector>
7
8namespace wmtk {
9
10std::tuple<RowVectors6l, RowVectors4l, RowVectors4l, VectorXl, VectorXl, VectorXl>
11tetmesh_topology_initialization(Eigen::Ref<const RowVectors4l> T)
12{
13 RowVectors6l TE;
14 RowVectors4l TF;
15 RowVectors4l TT;
16 VectorXl FT;
17 VectorXl ET;
18 VectorXl VT;
19
20 // First pass is identifying faces, and filling VT
21 std::vector<std::vector<int64_t>> TTT;
22
23 char iv0 = 0;
24 char iv1 = 1;
25 char iv2 = 2;
26 char it = 3;
27 char ii = 4;
28
29
30 int64_t vertex_count = T.maxCoeff() + 1;
31
32 // Build a table for finding Faces and populate the corresponding
33 // topology relations
34 {
35 TTT.resize(T.rows() * 4);
36 for (int64_t t = 0; t < T.rows(); ++t) {
37 for (int64_t i = 0; i < 4; ++i) {
38 // v1 v2 v3 f ei
39 int64_t x = T(t, static_cast<int64_t>(autogen::tet_mesh::auto_3d_faces[i][0]));
40 int64_t y = T(t, static_cast<int64_t>(autogen::tet_mesh::auto_3d_faces[i][1]));
41 int64_t z = T(t, static_cast<int64_t>(autogen::tet_mesh::auto_3d_faces[i][2]));
42 if (x > y) std::swap(x, y);
43 if (y > z) std::swap(y, z);
44 if (x > y) std::swap(x, y);
45
46 std::vector<int64_t> r(5);
47 r[iv0] = x;
48 r[iv1] = y;
49 r[iv2] = z;
50 r[it] = t;
51 r[ii] = i;
52 TTT[t * 4 + i] = r;
53 }
54 }
55 std::sort(TTT.begin(), TTT.end());
56
57 // std::ofstream file("TTT_F_debug.txt");
58 // for (const auto& row : TTT) {
59 // for (const auto& element : row) {
60 // file << element << " ";
61 // }
62 // file << std::endl;
63 // }
64 // file.close();
65
66 // VT
67 VT.resize(vertex_count, 1);
68 for (int64_t i = 0; i < T.rows(); ++i) {
69 for (int64_t j = 0; j < T.cols(); ++j) {
70 VT[T(i, j)] = i;
71 }
72 }
73
74 // Compute TF, TT, and FT
75 TF.resize(T.rows(), 4);
76 TT.resize(T.rows(), 4);
77 std::vector<int64_t> FT_temp;
78
79 // iterate over TTT to find faces
80 // for every entry check if the next is the same, and update the connectivity accordingly
81
82 for (int64_t i = 0; i < TTT.size(); ++i) {
83 if ((i == TTT.size() - 1) || (TTT[i][0] != TTT[i + 1][0]) ||
84 (TTT[i][1] != TTT[i + 1][1]) || (TTT[i][2] != TTT[i + 1][2])) {
85 // If the next tuple is empty, then this is a boundary face
86 FT_temp.push_back(TTT[i][it]);
87
88 TT(TTT[i][it], TTT[i][ii]) = -1;
89 TF(TTT[i][it], TTT[i][ii]) = FT_temp.size() - 1;
90 } else {
91 // this is an internal face, update both sides
92 // If the next tuple is empty, then this is a boundary face
93
94 FT_temp.push_back(TTT[i][it]);
95
96 TT(TTT[i][it], TTT[i][ii]) = TTT[i + 1][it];
97 TF(TTT[i][it], TTT[i][ii]) = FT_temp.size() - 1;
98
99 TT(TTT[i + 1][it], TTT[i + 1][ii]) = TTT[i][it];
100 TF(TTT[i + 1][it], TTT[i + 1][ii]) = FT_temp.size() - 1;
101
102 ++i; // skip the other entry
103 }
104 }
105
106 // copy FT
107 FT.resize(FT_temp.size());
108 for (int64_t i = 0; i < FT_temp.size(); ++i) FT(i) = FT_temp[i];
109 }
110
111 // Build a table for finding edges and populate the corresponding
112 // topology relations
113 {
114 TTT.resize(T.rows() * 6);
115 for (int64_t t = 0; t < T.rows(); ++t) {
116 for (int64_t i = 0; i < 6; ++i) {
117 // v1 v2 f ei
118 int64_t x = T(t, static_cast<int64_t>(autogen::tet_mesh::auto_3d_edges[i][0]));
119 int64_t y = T(t, static_cast<int64_t>(autogen::tet_mesh::auto_3d_edges[i][1]));
120 if (x > y) std::swap(x, y);
121
122 std::vector<int64_t> r(5);
123 r[iv0] = x;
124 r[iv1] = y;
125 r[iv2] = 0; // unused
126 r[it] = t;
127 r[ii] = i;
128 TTT[t * 6 + i] = r;
129 }
130 }
131 std::sort(TTT.begin(), TTT.end());
132
133 // std::ofstream file("TTT_E_debug.txt");
134 // for (const auto& row : TTT) {
135 // for (const auto& element : row) {
136 // file << element << " ";
137 // }
138 // file << std::endl;
139 // }
140 // file.close();
141
142
143 // Compute TE, ET
144 TE.resize(T.rows(), 6);
145 std::vector<int64_t> ET_temp;
146
147
148 // iterate over TTT to find edges
149 // for every entry check if the next is the same, and update the connectivity accordingly
150 for (int64_t i = 0; i < TTT.size(); ++i) {
151 if ((i == TTT.size() - 1) || (TTT[i][0] != TTT[i + 1][0]) ||
152 (TTT[i][1] != TTT[i + 1][1])) {
153 // new edge found
154 ET_temp.push_back(TTT[i][it]);
155
156 // update first copy
157 TE(TTT[i][it], TTT[i][ii]) = ET_temp.size() - 1;
158 } else {
159 // new edge found
160 ET_temp.push_back(TTT[i][it]);
161
162 // update first copy
163 TE(TTT[i][it], TTT[i][ii]) = ET_temp.size() - 1;
164
165 // loop over all the copies
166 int64_t j = 1;
167 while ((i + j < TTT.size()) && (TTT[i][0] == TTT[i + j][0]) &&
168 (TTT[i][1] == TTT[i + j][1])) {
169 TE(TTT[i + j][it], TTT[i + j][ii]) = ET_temp.size() - 1;
170 ++j;
171 }
172 assert(j >= 2);
173
174 i = i + j - 1; // skip the visited entries
175 }
176 }
177
178 // copy ET
179 ET.resize(ET_temp.size());
180 for (int64_t i = 0; i < ET_temp.size(); ++i) ET(i) = ET_temp[i];
181 }
182
183 return {TE, TF, TT, VT, ET, FT};
184}
185
186} // namespace wmtk
const int64_t auto_3d_edges[6][2]
const int64_t auto_3d_faces[4][3]
RowVectors< int64_t, 6 > RowVectors6l
Definition Types.hpp:49
RowVectors< int64_t, 4 > RowVectors4l
Definition Types.hpp:48
VectorX< int64_t > VectorXl
Definition Types.hpp:33
std::tuple< RowVectors6l, RowVectors4l, RowVectors4l, VectorXl, VectorXl, VectorXl > tetmesh_topology_initialization(Eigen::Ref< const RowVectors4l > T)
Given the mesh connectivity in matrix format, finds unique edges and faces and their relations.