Wildmeshing Toolkit
EdgeMeshOperationExecutor.cpp
Go to the documentation of this file.
1 
4 
5 namespace wmtk {
6 // constructor
8  EdgeMesh& m,
9  const Tuple& operating_tuple)
11  , ee_accessor(m.create_accessor<int64_t>(m.m_ee_handle))
12  , ev_accessor(m.create_accessor<int64_t>(m.m_ev_handle))
13  , ve_accessor(m.create_accessor<int64_t>(m.m_ve_handle))
14  , m_mesh(m)
15 {
16  m_operating_tuple = operating_tuple;
17  Tuple operating_tuple_switch_vertex = m_mesh.switch_vertex(operating_tuple);
18  // store ids of incident vertices
19  m_operating_edge_id = m_mesh.id_edge(m_operating_tuple);
20  m_spine_vids[0] = m_mesh.id_vertex(m_operating_tuple);
21  m_spine_vids[1] = m_mesh.id_vertex(operating_tuple_switch_vertex);
22 
23  // update hash on neighborhood
24  if (!m_mesh.is_boundary_vertex(m_operating_tuple)) {
25  m_neighbor_eids[0] = m_mesh.id_edge(m_mesh.switch_edge(m_operating_tuple));
26  }
27  if (!m_mesh.is_boundary_vertex(operating_tuple_switch_vertex)) {
28  m_neighbor_eids[1] = m_mesh.id_edge(m_mesh.switch_edge(operating_tuple_switch_vertex));
29  }
30 
31 
32  if (m_neighbor_eids[0] == m_neighbor_eids[1] && m_neighbor_eids[0] == m_operating_edge_id) {
33  m_is_self_loop = true;
34  }
35 }
36 
38 {
39  for (size_t d = 0; d < simplex_ids_to_delete.size(); ++d) {
40  for (const int64_t id : simplex_ids_to_delete[d]) {
41  flag_accessors[d].index_access().scalar_attribute(id) = 0;
42  }
43  }
44 }
45 
47 
48 const std::array<std::vector<int64_t>, 2>
50  const Tuple& tuple,
51  const EdgeMesh& m)
52 {
53  std::array<std::vector<int64_t>, 2> ids;
54  ids[1].emplace_back(m.id_edge(tuple));
55  return ids;
56 }
57 
58 const std::array<std::vector<int64_t>, 2>
60  const Tuple& tuple,
61  const EdgeMesh& m)
62 {
63  std::array<std::vector<int64_t>, 2> ids;
64  ids[0].emplace_back(m.id_vertex(tuple));
65  ids[1].emplace_back(m.id_edge(tuple));
66  if (m.is_free()) {
67  ids[0].emplace_back(m.id_vertex(m.switch_tuple(tuple, PrimitiveType::Vertex)));
68  }
69  return ids;
70 }
71 
72 
74 {
75  set_split();
76  m_output_tuple = split_edge_single_mesh();
77  // TODO: Implement for multi_mesh in the future
78 }
79 
81 {
82  simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh);
83 
84  // create new edges (facets)
85  // m_split_e[i] is connect to m_neighbor_eids[i] and m_spine_vids[i]
86  const auto& data = split_facet_data().add_facet(m_mesh, m_operating_tuple);
87  m_split_e = data.new_facet_indices;
88 
89  if (m_mesh.is_free()) {
90  const std::vector<int64_t> new_vids =
92  assert(new_vids.size() == 2);
93  std::copy(new_vids.begin(), new_vids.end(), m_free_split_v.begin());
94  const int64_t v_new = new_vids[0];
95  m_split_v = -1;
96  } else {
97  // create new vertex
98  const std::vector<int64_t> new_vids =
100  assert(new_vids.size() == 1);
101  const int64_t v_new = new_vids[0];
102  m_split_v = v_new;
103  }
104  const int64_t local_vid = m_mesh.is_ccw(m_operating_tuple) ? 0 : 1;
105 
106  // update ee
107  if (m_mesh.is_free()) {
108  } else {
109  // for 2 new edges
110  auto ee_new_0 = ee_accessor.index_access().vector_attribute(m_split_e[0]);
111  auto ee_new_1 = ee_accessor.index_access().vector_attribute(m_split_e[1]);
112  ee_new_0[local_vid ^ 1] = m_split_e[1];
113  ee_new_1[local_vid] = m_split_e[0];
114  if (m_is_self_loop) {
115  ee_new_0[local_vid] = m_split_e[1];
116  ee_new_1[local_vid ^ 1] = m_split_e[0];
117  } else {
118  ee_new_0[local_vid] = m_neighbor_eids[0];
119  ee_new_1[local_vid ^ 1] = m_neighbor_eids[1];
120  // for neighbor edges
121  for (int64_t i = 0; i < 2; i++) {
122  if (m_neighbor_eids[i] != -1) {
123  auto ee_neighbor =
124  ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]);
125  auto ev_neighbor =
126  ev_accessor.index_access().vector_attribute(m_neighbor_eids[i]);
127  for (int64_t j = 0; j < 2; j++) {
128  if (ee_neighbor[j] == m_operating_edge_id &&
129  ev_neighbor[j] == m_spine_vids[i]) {
130  ee_neighbor[j] = m_split_e[i];
131  break;
132  }
133  }
134  }
135  }
136  }
137  }
138 
139  // update ev
140  {
141  // for new edges
142  auto ev_new_0 = ev_accessor.index_access().vector_attribute(m_split_e[0]);
143  auto ev_new_1 = ev_accessor.index_access().vector_attribute(m_split_e[1]);
144  ev_new_0[local_vid] = m_spine_vids[0];
145  if (m_mesh.is_free()) {
146  ev_new_0[local_vid ^ 1] = m_free_split_v[0];
147  ev_new_1[local_vid] = m_free_split_v[1];
148  } else {
149  ev_new_0[local_vid ^ 1] = m_split_v;
150  ev_new_1[local_vid] = m_split_v;
151  }
152  ev_new_1[local_vid ^ 1] = m_spine_vids[1];
153  }
154 
155  // update ve
156  {
157  // for new vertex
158  if (m_mesh.is_free()) {
159  ve_accessor.index_access().scalar_attribute(m_free_split_v[0]) = m_split_e[0];
160  ve_accessor.index_access().scalar_attribute(m_free_split_v[1]) = m_split_e[1];
161  } else {
162  ve_accessor.index_access().scalar_attribute(m_split_v) = m_split_e[0];
163  }
164 
165  // for spine vertices
166  ve_accessor.index_access().scalar_attribute(m_spine_vids[0]) = m_split_e[0];
167  ve_accessor.index_access().scalar_attribute(m_spine_vids[1]) = m_split_e[1];
168  }
169  update_cell_hash();
170  delete_simplices();
171 
172  // prepare return Tuple
173  auto ret_edge = m_mesh.edge_tuple_from_id(m_split_e[1]);
174 
175  // if the mesh is free we don't care about which edge is returned
176  if (!m_mesh.is_free()) {
177  if (m_mesh.id_vertex(ret_edge) != m_split_v) {
178  ret_edge = m_mesh.switch_vertex(ret_edge);
179 
180  assert(m_mesh.id_edge(ret_edge) == m_split_e[1]);
181  assert(m_mesh.id_vertex(ret_edge) == m_split_v);
182  assert(m_mesh.id_vertex(m_mesh.switch_vertex(ret_edge)) == m_spine_vids[1]);
183  }
184  }
185 
186  return ret_edge;
187 }
188 
190 {
191  // TODO: Implement for multi_mesh in the future
192 }
193 
195 {
196  set_collapse();
197  m_output_tuple = collapse_edge_single_mesh();
198  // TODO: Implement for multi_mesh in the future
199 }
200 
201 
203 {
204  if (m_mesh.is_free()) {
205  simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh);
206  update_cell_hash();
207  delete_simplices();
208  return Tuple();
209  ;
210  }
211  // check if the collapse is valid
212  if (m_is_self_loop || (m_mesh.is_boundary_vertex(m_operating_tuple) &&
213  m_mesh.is_boundary_vertex(m_mesh.switch_vertex(m_operating_tuple)))) {
214  return Tuple();
215  }
216 
217  simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh);
218 
219  // update ee
220  {
221  // for neighbor edges
222  for (int64_t i = 0; i < 2; i++) {
223  if (m_neighbor_eids[i] != -1) {
224  auto ee_neighbor = ee_accessor.index_access().vector_attribute(m_neighbor_eids[i]);
225  for (int64_t j = 0; j < 2; j++) {
226  if (ee_neighbor[j] == m_operating_edge_id) {
227  ee_neighbor[j] = m_neighbor_eids[i ^ 1];
228  break;
229  }
230  }
231  }
232  }
233  }
234 
235  // update ev
236  {
237  if (m_neighbor_eids[0] != -1) {
238  auto ev_neighbor = ev_accessor.index_access().vector_attribute(m_neighbor_eids[0]);
239  for (int64_t j = 0; j < 2; j++) {
240  if (ev_neighbor[j] == m_spine_vids[0]) {
241  ev_neighbor[j] = m_spine_vids[1];
242  }
243  }
244  }
245  }
246 
247 
248  // update ve
249  {
250  ve_accessor.index_access().scalar_attribute(m_spine_vids[1]) =
251  (m_neighbor_eids[1] != -1) ? m_neighbor_eids[1] : m_neighbor_eids[0];
252  }
253 
254  update_cell_hash();
255  delete_simplices();
256 
257  const int64_t ret_eid = m_neighbor_eids[0] == -1 ? m_neighbor_eids[1] : m_neighbor_eids[0];
258  Tuple ret_tuple = m_mesh.edge_tuple_from_id(ret_eid);
259 
260  if (m_mesh.id_vertex(ret_tuple) != m_spine_vids[1]) {
261  ret_tuple = m_mesh.switch_vertex(ret_tuple);
262  }
263  return ret_tuple;
264 }
265 
267  const PrimitiveType type,
268  int64_t count)
269 {
270  m_mesh.guarantee_more_attributes(type, count);
271  return m_mesh.request_simplex_indices(type, count);
272 }
273 
274 } // namespace wmtk
EdgeMeshOperationExecutor(EdgeMesh &m, const Tuple &operating_tuple)
std::vector< int64_t > request_simplex_indices(const PrimitiveType type, int64_t count)
static const std::array< std::vector< int64_t >, 2 > get_split_simplices_to_delete(const Tuple &tuple, const EdgeMesh &m)
gather all simplices that are deleted in a split
std::array< attribute::Accessor< char >, 2 > flag_accessors
static const std::array< std::vector< int64_t >, 2 > get_collapse_simplices_to_delete(const Tuple &tuple, const EdgeMesh &m)
gather all simplices that are deleted in a collapse
int64_t id_edge(const Tuple &tuple) const
Definition: EdgeMesh.hpp:64
Tuple switch_tuple(const Tuple &tuple, PrimitiveType type) const override
switch the orientation of the Tuple of the given dimension
Definition: EdgeMesh.cpp:38
int64_t id_vertex(const Tuple &tuple) const
Definition: EdgeMesh.hpp:63
bool is_free() const
Definition: Mesh.hpp:987
std::vector< int64_t > request_simplex_indices(PrimitiveType type, int64_t count)
const attribute::Accessor< char > get_flag_accessor(PrimitiveType type) const
Definition: Mesh.cpp:158
std::array< std::vector< int64_t >, 2 > simplex_ids_to_delete
Definition: Accessor.hpp:6