Wildmeshing Toolkit
link_single_dimension.cpp
Go to the documentation of this file.
2 
3 #include <wmtk/TetMesh.hpp>
4 #include <wmtk/TriMesh.hpp>
5 #include <wmtk/utils/Logger.hpp>
6 
7 #include "closed_star.hpp"
8 #include "faces.hpp"
10 
11 namespace wmtk::simplex {
12 
13 namespace {
14 void link_vertex_vertex(
15  const TriMesh& mesh,
16  const simplex::Simplex& simplex,
17  std::vector<Simplex>& collection)
18 {
22 
23  assert(mesh.is_valid(simplex.tuple()));
24  const Tuple t_in = simplex.tuple();
25  Tuple t = t_in;
26 
27  do {
28  const Tuple t_collect = mesh.switch_tuples(t, {PV, PE});
29  collection.emplace_back(simplex::Simplex(mesh, PV, t_collect));
30 
31  if (mesh.is_boundary_edge(t)) {
32  break;
33  }
34  t = mesh.switch_tuples(t, {PF, PE});
35  } while (t != t_in);
36 
37 
38  if (t == t_in && !mesh.is_boundary_edge(t)) {
39  return;
40  }
41 
42  t = mesh.switch_edge(t_in);
43 
44  collection.emplace_back(simplex::Simplex(mesh, PV, mesh.switch_tuple(t, PV)));
45  if (mesh.is_boundary_edge(t)) {
46  return;
47  }
48  t = mesh.switch_tuples(t, {PF, PE});
49 
50  do {
51  const Tuple t_collect = mesh.switch_tuples(t, {PV, PE});
52  collection.emplace_back(simplex::Simplex(mesh, PV, t_collect));
53 
54  if (mesh.is_boundary_edge(t)) {
55  break;
56  }
57  t = mesh.switch_tuples(t, {PF, PE});
58  } while (true);
59 }
60 
61 void link_vertex_edge(
62  const TriMesh& mesh,
63  const simplex::Simplex& simplex,
64  std::vector<Simplex>& collection)
65 {
69 
70  assert(mesh.is_valid(simplex.tuple()));
71  const Tuple t_in = simplex.tuple();
72  Tuple t = t_in;
73 
74  do {
75  const Tuple t_collect = mesh.switch_tuples(t, {PV, PE});
76  collection.emplace_back(simplex::Simplex(mesh, PE, t_collect));
77 
78  if (mesh.is_boundary_edge(t)) {
79  break;
80  }
81  t = mesh.switch_tuples(t, {PF, PE});
82  } while (t != t_in);
83 
84 
85  if (t == t_in && !mesh.is_boundary_edge(t)) {
86  return;
87  }
88 
89  t = mesh.switch_edge(t_in);
90 
91  if (mesh.is_boundary_edge(t)) {
92  return;
93  }
94  t = mesh.switch_tuples(t, {PF, PE});
95 
96  do {
97  const Tuple t_collect = mesh.switch_tuples(t, {PV, PE});
98  collection.emplace_back(simplex::Simplex(mesh, PE, t_collect));
99 
100  if (mesh.is_boundary_edge(t)) {
101  break;
102  }
103  t = mesh.switch_tuples(t, {PF, PE});
104  } while (true);
105 }
106 
107 void link_edge(
108  const TriMesh& mesh,
109  const simplex::Simplex& simplex,
110  std::vector<Simplex>& collection)
111 {
115  const Tuple& t = simplex.tuple();
116 
117  collection.emplace_back(simplex::Simplex(mesh, PV, mesh.switch_tuples(t, {PE, PV})));
118  if (!mesh.is_boundary_edge(t)) {
119  collection.emplace_back(simplex::Simplex(mesh, PV, mesh.switch_tuples(t, {PF, PE, PV})));
120  }
121 }
122 } // namespace
123 
125  const Mesh& mesh,
126  const simplex::Simplex& simplex,
127  const PrimitiveType link_type,
128  const bool sort_and_clean)
129 {
130  switch (mesh.top_simplex_type()) {
132  return link_single_dimension(
133  static_cast<const TriMesh&>(mesh),
134  simplex,
135  link_type,
136  sort_and_clean);
138  return link_single_dimension(
139  static_cast<const TetMesh&>(mesh),
140  simplex,
141  link_type,
142  sort_and_clean);
144  case PrimitiveType::Edge:
145  default: return link_single_dimension_slow(mesh, simplex, link_type, sort_and_clean); break;
146  }
147 }
148 
150  const TriMesh& mesh,
151  const simplex::Simplex& simplex,
152  const PrimitiveType link_type,
153  const bool sort_and_clean)
154 {
155  std::vector<Simplex> link_simplices;
156  switch (simplex.primitive_type()) {
158  if (link_type == PrimitiveType::Vertex) {
159  link_vertex_vertex(mesh, simplex, link_simplices);
160  } else if (link_type == PrimitiveType::Edge) {
161  link_vertex_edge(mesh, simplex, link_simplices);
162  }
163  break;
164  case PrimitiveType::Edge:
165  if (link_type == PrimitiveType::Vertex) {
166  link_edge(mesh, simplex, link_simplices);
167  }
168  break;
169  case PrimitiveType::Triangle: break;
171  default: log_and_throw_error("Unknown primitive type in link_single_dimension."); break;
172  }
173 
174  SimplexCollection collection(mesh, std::move(link_simplices));
175 
176  if (sort_and_clean) {
177  collection.sort();
178  }
179 
180  return collection;
181 }
182 
184  const TetMesh& mesh,
185  const simplex::Simplex& simplex,
186  const PrimitiveType link_type,
187  const bool sort_and_clean)
188 {
189  // make use of the fact that the top dimension coface tuples always contain the simplex itself
190  const std::vector<Tuple> cell_tuples = top_dimension_cofaces_tuples(mesh, simplex);
191 
196 
197  std::vector<Simplex> all_cofaces;
198  switch (simplex.primitive_type()) {
200  if (link_type == PrimitiveType::Vertex) {
201  all_cofaces.reserve(cell_tuples.size() * 3);
202  for (Tuple t : cell_tuples) {
203  t = mesh.switch_tuples(t, {PV, PE, PF});
204  all_cofaces.emplace_back(Simplex::vertex(mesh, t));
205  t = mesh.switch_tuples(t, {PV, PE});
206  all_cofaces.emplace_back(Simplex::vertex(mesh, t));
207  t = mesh.switch_tuples(t, {PV, PE});
208  all_cofaces.emplace_back(Simplex::vertex(mesh, t));
209  }
210  } else if (link_type == PrimitiveType::Edge) {
211  all_cofaces.reserve(cell_tuples.size() * 3);
212  for (Tuple t : cell_tuples) {
213  t = mesh.switch_tuples(t, {PV, PE, PF});
214  all_cofaces.emplace_back(Simplex::edge(mesh, t));
215  t = mesh.switch_tuples(t, {PV, PE});
216  all_cofaces.emplace_back(Simplex::edge(mesh, t));
217  t = mesh.switch_tuples(t, {PV, PE});
218  all_cofaces.emplace_back(Simplex::edge(mesh, t));
219  }
220  }
221  if (link_type == PrimitiveType::Triangle) {
222  all_cofaces.reserve(cell_tuples.size());
223  for (Tuple t : cell_tuples) {
224  t = mesh.switch_tuples(t, {PV, PE, PF});
225  all_cofaces.emplace_back(Simplex::face(mesh, t));
226  }
227  }
228  break;
229  case PrimitiveType::Edge:
230  if (link_type == PrimitiveType::Vertex) {
231  all_cofaces.reserve(cell_tuples.size() * 2);
232  for (Tuple t : cell_tuples) {
233  t = mesh.switch_tuples(t, {PE, PV, PF, PE});
234  all_cofaces.emplace_back(Simplex::vertex(mesh, t));
235  all_cofaces.emplace_back(Simplex::vertex(mesh, mesh.switch_vertex(t)));
236  }
237  }
238  if (link_type == PrimitiveType::Edge) {
239  all_cofaces.reserve(cell_tuples.size());
240  for (Tuple t : cell_tuples) {
241  t = mesh.switch_tuples(t, {PE, PV, PF, PE});
242  all_cofaces.emplace_back(Simplex::edge(mesh, t));
243  }
244  }
245  break;
247  if (link_type == PrimitiveType::Vertex) {
248  all_cofaces.reserve(cell_tuples.size());
249  for (Tuple t : cell_tuples) {
250  t = mesh.switch_tuples(t, {PE, PF, PE, PV});
251  all_cofaces.emplace_back(Simplex::vertex(mesh, t));
252  }
253  }
254  break;
255  case PrimitiveType::Tetrahedron: break;
256  default: log_and_throw_error("Unknown primitive type in link_single_dimension."); break;
257  }
258 
259  SimplexCollection collection(mesh, std::move(all_cofaces));
260 
261  if (sort_and_clean) {
262  collection.sort_and_clean();
263  }
264 
265  return collection;
266 }
267 
269  const Mesh& mesh,
270  const simplex::Simplex& simplex,
271  const PrimitiveType link_type,
272  const bool sort_and_clean)
273 {
274  SimplexCollection collection(mesh);
275 
276  SimplexCollection cs = closed_star(mesh, simplex, sort_and_clean);
277 
278  SimplexCollection simplex_w_bd = faces(mesh, simplex, false);
279  simplex_w_bd.add(simplex);
280  simplex_w_bd.sort_and_clean();
281 
282  for (const Simplex& s : cs.simplex_vector()) {
283  SimplexCollection bd = faces(mesh, s, false);
284  bd.add(s);
285  bd.sort_and_clean();
286  SimplexCollection intersection = SimplexCollection::get_intersection(simplex_w_bd, bd);
287  if (intersection.simplex_vector().empty()) {
288  collection.add(s);
289  }
290  }
291 
292  return SimplexCollection(mesh, collection.simplex_vector(link_type));
293 }
294 
295 } // namespace wmtk::simplex
Tuple switch_tuples(const Tuple &tuple, const ContainerType &op_sequence) const
Performs a sequence of switch_tuple operations in the order specified in op_sequence.
Definition: MeshCRTP.hpp:135
PrimitiveType top_simplex_type() const
Definition: Mesh.hpp:997
Tuple switch_vertex(const Tuple &tuple) const
Definition: TetMesh.hpp:113
void add(const Simplex &simplex)
Add simplex to the collection.
const std::vector< Simplex > & simplex_vector() const
Return const reference to the simplex vector.
static SimplexCollection get_intersection(const SimplexCollection &collection_a, const SimplexCollection &collection_b)
Get intersection of two simplex collections.
void sort_and_clean()
Sort simplex vector and remove duplicates.
static Simplex face(const Mesh &m, const Tuple &t)
Definition: Simplex.hpp:63
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
PrimitiveType primitive_type() const
Definition: Simplex.hpp:51
constexpr wmtk::PrimitiveType PT
constexpr wmtk::PrimitiveType PF
void top_dimension_cofaces_tuples(const PointMesh &mesh, const Simplex &simplex, SimplexCollection &collection)
SimplexCollection closed_star(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
The closed star contains the input simplex, all its top dimension cofaces, and their faces.
Definition: closed_star.cpp:13
SimplexCollection link_single_dimension(const Mesh &mesh, const simplex::Simplex &simplex, const PrimitiveType link_type, const bool sort_and_clean)
SimplexCollection link_single_dimension_slow(const Mesh &mesh, const simplex::Simplex &simplex, const PrimitiveType link_type, const bool sort_and_clean)
SimplexCollection faces(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
Returns all faces of a simplex.
Definition: faces.cpp:10
void log_and_throw_error(const std::string &msg)
Definition: Logger.cpp:101
constexpr PrimitiveType PV
constexpr PrimitiveType PE