Wildmeshing Toolkit
Loading...
Searching...
No Matches
EdgeMeshOperationExecutor.cpp
Go to the documentation of this file.
1
4
5namespace 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().deactivate(id) ;
42 }
43 }
44}
45
47
48const 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
58const 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
std::array< attribute::FlagAccessor< EdgeMesh >, 2 > flag_accessors
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
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:63
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:62
bool is_free() const
Definition Mesh.hpp:973
std::vector< int64_t > request_simplex_indices(PrimitiveType type, int64_t count)
const attribute::FlagAccessor< Mesh > get_flag_accessor(PrimitiveType type) const
Definition Mesh.cpp:159
The Tuple is the basic navigation tool in our mesh data structure.
Definition Tuple.hpp:19
std::array< std::vector< int64_t >, 2 > simplex_ids_to_delete