Wildmeshing Toolkit
tetmesh_topology_initialization.cpp
Go to the documentation of this file.
2 #include <algorithm>
3 #include <fstream>
4 #include <iostream>
5 #include <vector>
7 
8 namespace wmtk {
9 
10 std::tuple<RowVectors6l, RowVectors4l, RowVectors4l, VectorXl, VectorXl, VectorXl>
11 tetmesh_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]
Definition: Accessor.hpp:6
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.