Wildmeshing Toolkit
Loading...
Searching...
No Matches
link_single_dimension.cpp
Go to the documentation of this file.
2
3#include <wmtk/TetMesh.hpp>
4#include <wmtk/TriMesh.hpp>
6
7#include "closed_star.hpp"
8#include "faces.hpp"
10
11namespace wmtk::simplex {
12
13namespace {
14void 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
61void 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
107void 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()) {
133 static_cast<const TriMesh&>(mesh),
134 simplex,
135 link_type,
136 sort_and_clean);
139 static_cast<const TetMesh&>(mesh),
140 simplex,
141 link_type,
142 sort_and_clean);
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;
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;
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:136
PrimitiveType top_simplex_type() const
Definition Mesh.hpp:982
Tuple switch_vertex(const Tuple &tuple) const
Definition TetMesh.hpp:113
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
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.
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 PE
constexpr PrimitiveType PV