Wildmeshing Toolkit
TriMeshSubstructureTopologyPreservingInvariant.cpp
Go to the documentation of this file.
2 #include <wmtk/Mesh.hpp>
3 
7 #include <wmtk/simplex/link.hpp>
9 
10 namespace 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 
27  const auto edge_tag_acc = mesh().create_const_accessor(m_substructure_edge_tag_handle);
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 :
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 =
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 :
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 =
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
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
SimplexCollection link(const Mesh &mesh, const simplex::Simplex &simplex, const bool sort_and_clean)
Definition: link.cpp:84
std::vector< Simplex > cofaces_single_dimension_simplices(const Mesh &mesh, const Simplex &simplex, PrimitiveType cofaces_type)
std::vector< Tuple > faces_single_dimension_tuples(const Mesh &mesh, const Simplex &simplex, const PrimitiveType face_type)