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
46
47const std::array<std::vector<int64_t>, 2>
49 const Tuple& tuple,
50 const EdgeMesh& m)
51{
52 std::array<std::vector<int64_t>, 2> ids;
53 ids[1].emplace_back(m.id_edge(tuple));
54 return ids;
55}
56
57const std::array<std::vector<int64_t>, 2>
59 const Tuple& tuple,
60 const EdgeMesh& m)
61{
62 std::array<std::vector<int64_t>, 2> ids;
63 ids[0].emplace_back(m.id_vertex(tuple));
64 ids[1].emplace_back(m.id_edge(tuple));
65 if (m.is_free()) {
66 ids[0].emplace_back(m.id_vertex(m.switch_tuple(tuple, PrimitiveType::Vertex)));
67 }
68 return ids;
69}
70
71
73{
74 set_split();
75 m_output_tuple = split_edge_single_mesh();
76 // TODO: Implement for multi_mesh in the future
77}
78
80{
81 simplex_ids_to_delete = get_split_simplices_to_delete(m_operating_tuple, m_mesh);
82
83 // create new edges (facets)
84 // m_split_e[i] is connect to m_neighbor_eids[i] and m_spine_vids[i]
85 const auto& data = split_facet_data().add_facet(m_mesh, m_operating_tuple);
86 m_split_e = data.new_facet_indices;
87
88 if (m_mesh.is_free()) {
89 const std::vector<int64_t> new_vids =
91 assert(new_vids.size() == 2);
92 std::copy(new_vids.begin(), new_vids.end(), m_free_split_v.begin());
93 const int64_t v_new = new_vids[0];
94 m_split_v = -1;
95 } else {
96 // create new vertex
97 const std::vector<int64_t> new_vids =
99 assert(new_vids.size() == 1);
100 const int64_t v_new = new_vids[0];
101 m_split_v = v_new;
102 }
103 const int64_t local_vid = m_mesh.is_ccw(m_operating_tuple) ? 0 : 1;
104
105 // update ee
106 if (m_mesh.is_free()) {
107 } else {
108 // for 2 new edges
109 auto ee_new_0 = ee_accessor.vector_attribute(m_split_e[0]);
110 auto ee_new_1 = ee_accessor.vector_attribute(m_split_e[1]);
111 ee_new_0[local_vid ^ 1] = m_split_e[1];
112 ee_new_1[local_vid] = m_split_e[0];
113 if (m_is_self_loop) {
114 ee_new_0[local_vid] = m_split_e[1];
115 ee_new_1[local_vid ^ 1] = m_split_e[0];
116 } else {
117 ee_new_0[local_vid] = m_neighbor_eids[0];
118 ee_new_1[local_vid ^ 1] = m_neighbor_eids[1];
119 // for neighbor edges
120 for (int64_t i = 0; i < 2; i++) {
121 if (m_neighbor_eids[i] != -1) {
122 auto ee_neighbor = ee_accessor.vector_attribute(m_neighbor_eids[i]);
123 auto ev_neighbor = ev_accessor.vector_attribute(m_neighbor_eids[i]);
124 for (int64_t j = 0; j < 2; j++) {
125 if (ee_neighbor[j] == m_operating_edge_id &&
126 ev_neighbor[j] == m_spine_vids[i]) {
127 ee_neighbor[j] = m_split_e[i];
128 break;
129 }
130 }
131 }
132 }
133 }
134 }
135
136 // update ev
137 {
138 // for new edges
139 auto ev_new_0 = ev_accessor.vector_attribute(m_split_e[0]);
140 auto ev_new_1 = ev_accessor.vector_attribute(m_split_e[1]);
141 ev_new_0[local_vid] = m_spine_vids[0];
142 if (m_mesh.is_free()) {
143 ev_new_0[local_vid ^ 1] = m_free_split_v[0];
144 ev_new_1[local_vid] = m_free_split_v[1];
145 } else {
146 ev_new_0[local_vid ^ 1] = m_split_v;
147 ev_new_1[local_vid] = m_split_v;
148 }
149 ev_new_1[local_vid ^ 1] = m_spine_vids[1];
150 }
151
152 // update ve
153 {
154 // for new vertex
155 if (m_mesh.is_free()) {
156 ve_accessor.scalar_attribute(m_free_split_v[0]) = m_split_e[0];
157 ve_accessor.scalar_attribute(m_free_split_v[1]) = m_split_e[1];
158 } else {
159 ve_accessor.scalar_attribute(m_split_v) = m_split_e[0];
160 }
161
162 // for spine vertices
163 ve_accessor.scalar_attribute(m_spine_vids[0]) = m_split_e[0];
164 ve_accessor.scalar_attribute(m_spine_vids[1]) = m_split_e[1];
165 }
166 delete_simplices();
167
168 // prepare return Tuple
169 auto ret_edge = m_mesh.edge_tuple_from_id(m_split_e[1]);
170
171 // if the mesh is free we don't care about which edge is returned
172 if (!m_mesh.is_free()) {
173 if (m_mesh.id_vertex(ret_edge) != m_split_v) {
174 ret_edge = m_mesh.switch_vertex(ret_edge);
175
176 assert(m_mesh.id_edge(ret_edge) == m_split_e[1]);
177 assert(m_mesh.id_vertex(ret_edge) == m_split_v);
178 assert(m_mesh.id_vertex(m_mesh.switch_vertex(ret_edge)) == m_spine_vids[1]);
179 }
180 }
181
182 return ret_edge;
183}
184
185
187{
188 set_collapse();
189 m_output_tuple = collapse_edge_single_mesh();
190 // TODO: Implement for multi_mesh in the future
191}
192
193
195{
196 if (m_mesh.is_free()) {
197 simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh);
198 delete_simplices();
199 return Tuple();
200 ;
201 }
202 // check if the collapse is valid
203 if (m_is_self_loop || (m_mesh.is_boundary_vertex(m_operating_tuple) &&
204 m_mesh.is_boundary_vertex(m_mesh.switch_vertex(m_operating_tuple)))) {
205 return Tuple();
206 }
207
208 simplex_ids_to_delete = get_collapse_simplices_to_delete(m_operating_tuple, m_mesh);
209
210 // update ee
211 {
212 // for neighbor edges
213 for (int64_t i = 0; i < 2; i++) {
214 if (m_neighbor_eids[i] != -1) {
215 auto ee_neighbor = ee_accessor.vector_attribute(m_neighbor_eids[i]);
216 for (int64_t j = 0; j < 2; j++) {
217 if (ee_neighbor[j] == m_operating_edge_id) {
218 ee_neighbor[j] = m_neighbor_eids[i ^ 1];
219 break;
220 }
221 }
222 }
223 }
224 }
225
226 // update ev
227 {
228 if (m_neighbor_eids[0] != -1) {
229 auto ev_neighbor = ev_accessor.vector_attribute(m_neighbor_eids[0]);
230 for (int64_t j = 0; j < 2; j++) {
231 if (ev_neighbor[j] == m_spine_vids[0]) {
232 ev_neighbor[j] = m_spine_vids[1];
233 }
234 }
235 }
236 }
237
238
239 // update ve
240 {
241 ve_accessor.scalar_attribute(m_spine_vids[1]) =
242 (m_neighbor_eids[1] != -1) ? m_neighbor_eids[1] : m_neighbor_eids[0];
243 }
244
245 delete_simplices();
246
247 const int64_t ret_eid = m_neighbor_eids[0] == -1 ? m_neighbor_eids[1] : m_neighbor_eids[0];
248 Tuple ret_tuple = m_mesh.edge_tuple_from_id(ret_eid);
249
250 if (m_mesh.id_vertex(ret_tuple) != m_spine_vids[1]) {
251 ret_tuple = m_mesh.switch_vertex(ret_tuple);
252 }
253 return ret_tuple;
254}
255
257 const PrimitiveType type,
258 int64_t count)
259{
260 m_mesh.guarantee_more_attributes(type, count);
261 return m_mesh.request_simplex_indices(type, count);
262}
263
264} // 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:971
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:166
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