Wildmeshing Toolkit
Loading...
Searching...
No Matches
TriMeshSubstructureTopologyPreservingInvariant.cpp
Go to the documentation of this file.
2#include <wmtk/Mesh.hpp>
3
9
10namespace wmtk::invariants {
12 const Mesh& m,
13 const TypedAttributeHandle<int64_t>& substructure_edge_tag_handle,
14 const int64_t substructure_tag_value)
15 : Invariant(m, true, false, false)
16 , m_substructure_edge_tag_handle(substructure_edge_tag_handle)
17 , m_substructure_tag_value(substructure_tag_value)
18{}
19
21 const simplex::Simplex& input_simplex) const
22{
23 assert(input_simplex.primitive_type() == PrimitiveType::Edge);
24
25 using namespace simplex;
26
28
29 // edge e = (u,v)
30
31 const simplex::Simplex edge_e = input_simplex;
32 const simplex::Simplex vertex_u(mesh(), PrimitiveType::Vertex, input_simplex.tuple());
33 const simplex::Simplex vertex_v(
34 mesh(),
36 mesh().switch_tuple(input_simplex.tuple(), PrimitiveType::Vertex));
37
38 RawSimplexCollection lk_u_0(link(mesh(), vertex_u));
39 RawSimplexCollection lk_u_1;
40 RawSimplexCollection lk_u_2;
41
42 int64_t u_incident_subset_edges = 0;
43
44 for (const simplex::Simplex& e_u :
45 cofaces_single_dimension_simplices(mesh(), vertex_u, PrimitiveType::Edge)) {
46 if (edge_tag_acc.const_scalar_attribute(e_u.tuple()) == m_substructure_tag_value) {
47 ++u_incident_subset_edges;
48
49 std::vector<Tuple> vertices_dummy_tri =
50 faces_single_dimension_tuples(mesh(), e_u, PrimitiveType::Vertex);
51 vertices_dummy_tri.emplace_back(Tuple()); // add dummy vertex
52
53 RawSimplex dummy_tri(mesh(), vertices_dummy_tri);
54 RawSimplex opp_dummy_edge = dummy_tri.opposite_face(mesh(), vertex_u.tuple());
55 lk_u_0.add(opp_dummy_edge);
56 lk_u_0.add(opp_dummy_edge.faces());
57
58 lk_u_1.add(opp_dummy_edge);
59 lk_u_1.add(opp_dummy_edge.faces());
60
61 RawSimplex raw_e_u(mesh(), e_u);
62 lk_u_2.add(raw_e_u.opposite_face(mesh(), vertex_u.tuple()));
63 }
64 }
65
66 // if u is an order 2 vertex
67 if (u_incident_subset_edges != 0 && u_incident_subset_edges != 2) {
68 lk_u_2.add(RawSimplex({-1})); // add dummy vertex
69 }
70
71 lk_u_0.sort_and_clean();
72 lk_u_1.sort_and_clean();
73 lk_u_2.sort_and_clean();
74
75 // same code for vertex v
76
77 RawSimplexCollection lk_v_0(link(mesh(), vertex_v));
78 RawSimplexCollection lk_v_1;
79 RawSimplexCollection lk_v_2;
80
81 int64_t v_incident_subset_edges = 0;
82
83 for (const simplex::Simplex& e_v :
84 cofaces_single_dimension_simplices(mesh(), vertex_v, PrimitiveType::Edge)) {
85 if (edge_tag_acc.const_scalar_attribute(e_v.tuple()) == m_substructure_tag_value) {
86 ++v_incident_subset_edges;
87
88 std::vector<Tuple> vertices_dummy_tri =
89 faces_single_dimension_tuples(mesh(), e_v, PrimitiveType::Vertex);
90 vertices_dummy_tri.emplace_back(Tuple()); // add dummy vertex
91
92 RawSimplex dummy_tri(mesh(), vertices_dummy_tri);
93 RawSimplex opp_dummy_edge = dummy_tri.opposite_face(mesh(), vertex_v.tuple());
94 lk_v_0.add(opp_dummy_edge);
95 lk_v_0.add(opp_dummy_edge.faces());
96
97 lk_v_1.add(opp_dummy_edge);
98 lk_v_1.add(opp_dummy_edge.faces());
99
100 RawSimplex raw_e_v(mesh(), e_v);
101 lk_v_2.add(raw_e_v.opposite_face(mesh(), vertex_v.tuple()));
102 }
103 }
104
105 // if v is an order 2 vertex
106 if (v_incident_subset_edges != 0 && v_incident_subset_edges != 2) {
107 lk_v_2.add(RawSimplex({-1})); // add dummy vertex
108 }
109
110 lk_v_0.sort_and_clean();
111 lk_v_1.sort_and_clean();
112 lk_v_2.sort_and_clean();
113
114 if (!RawSimplexCollection::get_intersection(lk_u_2, lk_v_2).simplex_vector().empty()) {
115 return false;
116 }
117
118 // lk_e
119 RawSimplexCollection lk_e_0(link(mesh(), edge_e));
120 RawSimplexCollection lk_e_1;
121
122 RawSimplex raw_edge_e(mesh(), edge_e);
123
124 if (edge_tag_acc.const_scalar_attribute(edge_e.tuple()) == m_substructure_tag_value) {
125 RawSimplex dummy_vertex({-1});
126 lk_e_0.add(dummy_vertex);
127 lk_e_1.add(dummy_vertex);
128 }
129
130 lk_e_0.sort_and_clean();
131 lk_e_1.sort_and_clean();
132
133 RawSimplexCollection intersection_u_v_0 =
134 RawSimplexCollection::get_intersection(lk_u_0, lk_v_0);
135 if (!RawSimplexCollection::are_simplex_collections_equal(intersection_u_v_0, lk_e_0)) {
136 return false;
137 }
138 RawSimplexCollection intersection_u_v_1 =
139 RawSimplexCollection::get_intersection(lk_u_1, lk_v_1);
140 if (!RawSimplexCollection::are_simplex_collections_equal(intersection_u_v_1, lk_e_1)) {
141 return false;
142 }
143
144 return true;
145}
146
147} // namespace wmtk::invariants
const attribute::Accessor< T, Mesh, D > create_const_accessor(const attribute::MeshAttributeHandle &handle) const
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
Handle that represents attributes for some mesh.
const Mesh & mesh() const
Definition Invariant.cpp:35
TriMeshSubstructureTopologyPreservingInvariant(const Mesh &m, const TypedAttributeHandle< int64_t > &substructure_edge_tag_handle, const int64_t substructure_tag_value)
const Tuple & tuple() const
Definition Simplex.hpp:53
PrimitiveType primitive_type() const
Definition Simplex.hpp:51