Wildmeshing Toolkit
Loading...
Searching...
No Matches
link_condition.cpp
Go to the documentation of this file.
1#include "link_condition.hpp"
6#include "link.hpp"
7#include "link_iterable.hpp"
8#include "open_star.hpp"
10
11namespace wmtk::simplex {
12bool link_condition_closed_trimesh(const TriMesh& mesh, const Tuple& edge)
13{
14 const Simplex v_a = Simplex::vertex(mesh, edge);
15 const Simplex v_b = Simplex::vertex(mesh, mesh.switch_tuple(edge, PrimitiveType::Vertex));
16 const Simplex e_ab = Simplex::edge(mesh, edge);
17
18 IdSimplexCollection link_a(mesh);
19 link_a.reserve(24);
20 for (const IdSimplex& s : link_iterable(mesh, v_a)) {
21 link_a.add(s);
22 }
23 link_a.sort_and_clean();
24 IdSimplexCollection link_b(mesh);
25 link_b.reserve(24);
26 for (const IdSimplex& s : link_iterable(mesh, v_b)) {
27 link_b.add(s);
28 }
29 link_b.sort_and_clean();
30 IdSimplexCollection link_ab(mesh);
31 link_ab.reserve(2);
32 for (const IdSimplex& s : link_iterable(mesh, e_ab)) {
33 link_ab.add(s);
34 }
35 link_ab.sort_and_clean();
36
37 const IdSimplexCollection link_a_link_b_intersection =
39
40 return IdSimplexCollection::are_simplex_collections_equal(link_a_link_b_intersection, link_ab);
41}
42
43bool link_condition(const EdgeMesh& mesh, const Tuple& edge)
44{
45 const Tuple edge_switch_v = mesh.switch_tuple(edge, PrimitiveType::Vertex);
46 if (mesh.is_boundary_vertex(edge) && mesh.is_boundary_vertex(edge_switch_v)) {
47 return false;
48 }
50 mesh,
51 edge,
53 edge_switch_v,
55 return false;
56 }
57 return true;
58}
59
60bool link_condition(const TriMesh& mesh, const Tuple& edge)
61{
62 // step1 check link condition for closed case
63 if (!link_condition_closed_trimesh(mesh, edge)) {
64 return false;
65 }
66 // for the trimesh with boudanry cases, we add a dummy vertex w to the mesh, and connected it to
67 // all the boundary edges, then the mesh becomes a closed manifold mesh for all vertices but w.
68
69 // check if dummy vertex w is included in the lhs
70 auto get_boundary_edges = [&mesh](const Tuple& _v) {
71 const Simplex input_v(mesh, PrimitiveType::Vertex, _v);
72 std::vector<Tuple> ret;
73 // get incident_edges from open_star
74 // incident_edges = cofaces_single_dimension_tuples(mesh, input_v,
75 // PrimitiveType::Edge);
76 auto incident_edges = cofaces_single_dimension_iterable(mesh, input_v, PrimitiveType::Edge);
77 for (const Tuple& _e : incident_edges) {
78 if (mesh.is_boundary(PrimitiveType::Edge, _e)) {
79 ret.push_back(mesh.switch_tuple(_e, PrimitiveType::Vertex));
80 }
81 }
82 return ret;
83 };
84
85 // case 1: edge ab is a boundary edge, in this case dummy vertex w is in lnk(ab), need to check
86 // if there are any common edges connected with w in lnk_w^0(a)∩lnk_w^0(b)
87 const auto boundary_neighbors_a = get_boundary_edges(edge);
88 const auto boundary_neighbors_b =
89 get_boundary_edges(mesh.switch_tuple(edge, PrimitiveType::Vertex));
90 if (mesh.is_boundary_edge(edge)) {
91 assert(boundary_neighbors_a.size() == 2); // if guarantee 2-manifold
92 assert(boundary_neighbors_b.size() == 2); // if guarantee 2-manifold
93 for (auto e_a : boundary_neighbors_a) {
94 for (auto e_b : boundary_neighbors_b) {
96 mesh,
98 Simplex(mesh, PrimitiveType::Vertex, e_b))) {
99 // find common edge, link condition fails
100 return false;
101 }
102 }
103 }
104 } else {
105 if (boundary_neighbors_a.size() == 0 || boundary_neighbors_b.size() == 0) {
106 // in this case, lnk_w^0(a) ∩ lnk_w^0(b) == lnk(a) ∩ lnk(b) == lnk(ab) == lnk_w^0(ab)
107 return true;
108 } else {
109 // in this case w \in lhs but not \in rhs
110 return false;
111 }
112 }
113
114 return true;
115}
116
117bool link_condition_closed_tetmesh(const TetMesh& mesh, const Tuple& edge)
118{
119 // for closed mesh, if link(a) \intersect link(b) == link(ab)
120 const Simplex v_a = Simplex::vertex(mesh, edge);
121 const Simplex v_b = Simplex::vertex(mesh, mesh.switch_vertex(edge));
122 const Simplex e_ab = Simplex::edge(mesh, edge);
123
124 IdSimplexCollection link_a(mesh);
125 link_a.reserve(128);
126 for (const IdSimplex& s : link_iterable(mesh, v_a)) {
127 link_a.add(s);
128 }
129 link_a.sort_and_clean();
130 IdSimplexCollection link_b(mesh);
131 link_b.reserve(128);
132 for (const IdSimplex& s : link_iterable(mesh, v_b)) {
133 link_b.add(s);
134 }
135 link_b.sort_and_clean();
136 IdSimplexCollection link_ab(mesh);
137 link_ab.reserve(32);
138 for (const IdSimplex& s : link_iterable(mesh, e_ab)) {
139 link_ab.add(s);
140 }
141 link_ab.sort_and_clean();
142
143 const IdSimplexCollection link_a_link_b_intersection =
145
146 return IdSimplexCollection::are_simplex_collections_equal(link_a_link_b_intersection, link_ab);
147}
148
149bool link_condition(const TetMesh& mesh, const Tuple& edge)
150{
151 // close mesh check
152 if (!link_condition_closed_tetmesh(mesh, edge)) {
153 return false;
154 }
155
162 auto get_boundary_vertex_link = [&mesh](const Tuple& _v) {
163 const Simplex input_v(mesh, PrimitiveType::Vertex, _v);
164 // std::vector<Tuple> ret;
165 IdSimplexCollection ret(mesh);
166 // auto incident_faces =
167 // cofaces_single_dimension_tuples(mesh, input_v, PrimitiveType::Triangle);
168 auto incident_faces =
170 for (const Tuple& _f : incident_faces) {
171 if (mesh.is_boundary(PrimitiveType::Triangle, _f)) {
172 // assuming cofaces_single_dimension always return the tuple point to the input
173 // vertex
174 // ret.push_back(mesh.switch_tuples(_f, {PrimitiveType::Vertex,
175 // PrimitiveType::Edge})); ret.push_back(mesh.switch_edge(mesh.switch_vertex(_f)));
176 Tuple link_tuple =
178 ret.add(PrimitiveType::Edge, link_tuple);
179 ret.add(PrimitiveType::Vertex, link_tuple);
180 ret.add(
182 mesh.switch_tuple(link_tuple, PrimitiveType::Vertex));
183 }
184 }
185 return ret;
186 };
187
188 auto get_boundary_edge_link = [&mesh](const Tuple& _v) {
189 const Simplex input_e(mesh, PrimitiveType::Edge, _v);
190 IdSimplexCollection ret(mesh);
191 auto incident_faces =
193 for (const Tuple& _f : incident_faces) {
194 if (mesh.is_boundary(PrimitiveType::Triangle, _f)) {
195 Tuple link_tuple =
197 ret.add(PrimitiveType::Vertex, link_tuple);
198 }
199 }
200 return ret;
201 };
202
203 const Tuple& a_tuple = edge;
204 const Tuple b_tuple = mesh.switch_tuple(edge, PrimitiveType::Vertex);
205
206 if (mesh.is_boundary_edge(edge)) {
207 IdSimplexCollection boundary_link_a = get_boundary_vertex_link(a_tuple);
208 boundary_link_a.sort_and_clean();
209 IdSimplexCollection boundary_link_b = get_boundary_vertex_link(b_tuple);
210 boundary_link_b.sort_and_clean();
211
212 IdSimplexCollection boundary_link_ab = get_boundary_edge_link(edge);
213 boundary_link_ab.sort_and_clean();
214
215 IdSimplexCollection boundary_link_a_link_b_intersection =
216 IdSimplexCollection::get_intersection(boundary_link_a, boundary_link_b);
217
219 boundary_link_a_link_b_intersection,
220 boundary_link_ab);
221
222 } else if (mesh.is_boundary_vertex(a_tuple) && mesh.is_boundary_vertex(b_tuple)) {
223 return false;
224 }
225
226 return true;
227}
228
229bool link_condition(const Mesh& mesh, const Tuple& edge)
230{
231 return std::visit(
232 [&edge](auto&& m) noexcept {
233 using MType = std::decay_t<decltype(m.get())>;
234 if constexpr (std::is_same_v<MType, Mesh>) {
235 throw std::runtime_error("Link condition called on an unknown type of mesh - could "
236 "only cast it to Mesh");
237 } else if constexpr (std::is_same_v<MType, PointMesh>) {
238 return true;
239 } else {
240 return link_condition(m.get(), edge);
241 }
242 },
244}
245} // namespace wmtk::simplex
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const override
switch the orientation of the Tuple of the given dimension
Definition EdgeMesh.cpp:38
bool is_boundary_vertex(const Tuple &tuple) const
Definition EdgeMesh.cpp:31
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
bool is_boundary_vertex(const Tuple &tuple) const
Definition TetMesh.cpp:386
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const final override
switch the orientation of the Tuple of the given dimension
Definition TetMesh.cpp:250
bool is_boundary_edge(const Tuple &tuple) const
Definition TetMesh.cpp:374
Tuple switch_vertex(const Tuple &tuple) const
Definition TetMesh.hpp:113
bool is_boundary(PrimitiveType pt, const Tuple &tuple) const final override
returns if a simplex is on the boundary of hte mesh. For anything but dimension - 1 this checks if th...
Definition TetMesh.cpp:353
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const final override
switch the orientation of the Tuple of the given dimension
Definition TriMesh.cpp:99
bool is_boundary(PrimitiveType pt, const Tuple &tuple) const final override
returns if a simplex is on the boundary of hte mesh. For anything but dimension - 1 this checks if th...
Definition TriMesh.cpp:58
bool is_boundary_edge(const Tuple &tuple) const
Definition TriMesh.cpp:72
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
void sort_and_clean()
Sort simplex vector and remove duplicates.
static IdSimplexCollection get_intersection(const IdSimplexCollection &collection_a, const IdSimplexCollection &collection_b)
Get intersection of two simplex collections.
void add(const IdSimplex &simplex)
Add simplex to the collection.
static bool are_simplex_collections_equal(const IdSimplexCollection &collection_a, const IdSimplexCollection &collection_b)
Check if the two simplex collections are equal.
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
static bool equal(const Mesh &m, const Simplex &s0, const Simplex &s1)
bool link_condition(const EdgeMesh &mesh, const Tuple &edge)
Check if the edge to collapse satisfying the link condition.
bool link_condition_closed_trimesh(const TriMesh &mesh, const Tuple &edge)
bool link_condition_closed_tetmesh(const TetMesh &mesh, const Tuple &edge)
LinkIterable link_iterable(const Mesh &mesh, const Simplex &simplex)
CofacesSingleDimensionIterable cofaces_single_dimension_iterable(const Mesh &mesh, const Simplex &simplex, const PrimitiveType cofaces_type)
ConstMeshVariantType as_const_mesh_variant(const Mesh &mesh)