Cleanup: remove redundant doxygen \file argument
[blender.git] / source / blender / bmesh / intern / bmesh_delete.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file \ingroup bmesh
21  *
22  * BM remove functions.
23  */
24
25
26 #include "BLI_utildefines.h"
27
28 #include "bmesh.h"
29 #include "intern/bmesh_private.h"
30
31
32 /* -------------------------------------------------------------------- */
33 /* BMO functions */
34
35 /** \name BMesh Operator Delete Functions
36  * \{ */
37
38 /**
39  * Called by operators to remove elements that they have marked for
40  * removal.
41  */
42 static void bmo_remove_tagged_faces(BMesh *bm, const short oflag)
43 {
44         BMFace *f, *f_next;
45         BMIter iter;
46
47         BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
48                 if (BMO_face_flag_test(bm, f, oflag)) {
49                         BM_face_kill(bm, f);
50                 }
51         }
52 }
53
54 static void bmo_remove_tagged_edges(BMesh *bm, const short oflag)
55 {
56         BMEdge *e, *e_next;
57         BMIter iter;
58
59         BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
60                 if (BMO_edge_flag_test(bm, e, oflag)) {
61                         BM_edge_kill(bm, e);
62                 }
63         }
64 }
65
66 static void bmo_remove_tagged_verts(BMesh *bm, const short oflag)
67 {
68         BMVert *v, *v_next;
69         BMIter iter;
70
71         BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
72                 if (BMO_vert_flag_test(bm, v, oflag)) {
73                         BM_vert_kill(bm, v);
74                 }
75         }
76 }
77
78 static void bmo_remove_tagged_verts_loose(BMesh *bm, const short oflag)
79 {
80         BMVert *v, *v_next;
81         BMIter iter;
82
83         BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
84                 if (BMO_vert_flag_test(bm, v, oflag) && (v->e == NULL)) {
85                         BM_vert_kill(bm, v);
86                 }
87         }
88 }
89
90 void BMO_mesh_delete_oflag_tagged(BMesh *bm, const short oflag, const char htype)
91 {
92         if (htype & BM_FACE) {
93                 bmo_remove_tagged_faces(bm, oflag);
94         }
95         if (htype & BM_EDGE) {
96                 bmo_remove_tagged_edges(bm, oflag);
97         }
98         if (htype & BM_VERT) {
99                 bmo_remove_tagged_verts(bm, oflag);
100         }
101 }
102
103 /**
104  * \warning oflag applies to different types in some contexts,
105  * not just the type being removed.
106  */
107 void BMO_mesh_delete_oflag_context(BMesh *bm, const short oflag, const int type)
108 {
109         BMEdge *e;
110         BMFace *f;
111
112         BMIter eiter;
113         BMIter fiter;
114
115         switch (type) {
116                 case DEL_VERTS:
117                 {
118                         bmo_remove_tagged_verts(bm, oflag);
119
120                         break;
121                 }
122                 case DEL_EDGES:
123                 {
124                         /* flush down to vert */
125                         BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
126                                 if (BMO_edge_flag_test(bm, e, oflag)) {
127                                         BMO_vert_flag_enable(bm, e->v1, oflag);
128                                         BMO_vert_flag_enable(bm, e->v2, oflag);
129                                 }
130                         }
131                         bmo_remove_tagged_edges(bm, oflag);
132                         bmo_remove_tagged_verts_loose(bm, oflag);
133
134                         break;
135                 }
136                 case DEL_EDGESFACES:
137                 {
138                         bmo_remove_tagged_edges(bm, oflag);
139
140                         break;
141                 }
142                 case DEL_ONLYFACES:
143                 {
144                         bmo_remove_tagged_faces(bm, oflag);
145
146                         break;
147                 }
148                 case DEL_ONLYTAGGED:
149                 {
150                         BMO_mesh_delete_oflag_tagged(bm, oflag, BM_ALL_NOLOOP);
151
152                         break;
153                 }
154                 case DEL_FACES:
155                 case DEL_FACES_KEEP_BOUNDARY:
156                 {
157                         /* go through and mark all edges and all verts of all faces for delete */
158                         BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
159                                 if (BMO_face_flag_test(bm, f, oflag)) {
160                                         BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
161                                         BMLoop *l_iter;
162
163                                         l_iter = l_first;
164                                         do {
165                                                 BMO_vert_flag_enable(bm, l_iter->v, oflag);
166                                                 BMO_edge_flag_enable(bm, l_iter->e, oflag);
167                                         } while ((l_iter = l_iter->next) != l_first);
168                                 }
169                         }
170                         /* now go through and mark all remaining faces all edges for keeping */
171                         BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
172                                 if (!BMO_face_flag_test(bm, f, oflag)) {
173                                         BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
174                                         BMLoop *l_iter;
175
176                                         l_iter = l_first;
177                                         do {
178                                                 BMO_vert_flag_disable(bm, l_iter->v, oflag);
179                                                 BMO_edge_flag_disable(bm, l_iter->e, oflag);
180                                         } while ((l_iter = l_iter->next) != l_first);
181                                 }
182                         }
183                         /* also mark all the vertices of remaining edges for keeping */
184                         BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
185
186                                 /* Only exception to normal 'DEL_FACES' logic. */
187                                 if (type == DEL_FACES_KEEP_BOUNDARY) {
188                                         if (BM_edge_is_boundary(e)) {
189                                                 BMO_edge_flag_disable(bm, e, oflag);
190                                         }
191                                 }
192
193                                 if (!BMO_edge_flag_test(bm, e, oflag)) {
194                                         BMO_vert_flag_disable(bm, e->v1, oflag);
195                                         BMO_vert_flag_disable(bm, e->v2, oflag);
196                                 }
197                         }
198
199                         /* now delete marked face */
200                         bmo_remove_tagged_faces(bm, oflag);
201                         /* delete marked edge */
202                         bmo_remove_tagged_edges(bm, oflag);
203                         /* remove loose vertice */
204                         bmo_remove_tagged_verts(bm, oflag);
205
206                         break;
207                 }
208         }
209 }
210
211 /** \} */
212
213
214 /* -------------------------------------------------------------------- */
215 /* BM functions
216  *
217  * note! this is just a duplicate of the code above (bad!)
218  * but for now keep in sync, its less hassle then having to create bmesh operator flags,
219  * each time we need to remove some geometry.
220  */
221
222 /** \name BMesh Delete Functions (no oflags)
223  * \{ */
224
225 static void bm_remove_tagged_faces(BMesh *bm, const char hflag)
226 {
227         BMFace *f, *f_next;
228         BMIter iter;
229
230         BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) {
231                 if (BM_elem_flag_test(f, hflag)) {
232                         BM_face_kill(bm, f);
233                 }
234         }
235 }
236
237 static void bm_remove_tagged_edges(BMesh *bm, const char hflag)
238 {
239         BMEdge *e, *e_next;
240         BMIter iter;
241
242         BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) {
243                 if (BM_elem_flag_test(e, hflag)) {
244                         BM_edge_kill(bm, e);
245                 }
246         }
247 }
248
249 static void bm_remove_tagged_verts(BMesh *bm, const char hflag)
250 {
251         BMVert *v, *v_next;
252         BMIter iter;
253
254         BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
255                 if (BM_elem_flag_test(v, hflag)) {
256                         BM_vert_kill(bm, v);
257                 }
258         }
259 }
260
261 static void bm_remove_tagged_verts_loose(BMesh *bm, const char hflag)
262 {
263         BMVert *v, *v_next;
264         BMIter iter;
265
266         BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) {
267                 if (BM_elem_flag_test(v, hflag) && (v->e == NULL)) {
268                         BM_vert_kill(bm, v);
269                 }
270         }
271 }
272
273 void BM_mesh_delete_hflag_tagged(BMesh *bm, const char hflag, const char htype)
274 {
275         if (htype & BM_FACE) {
276                 bm_remove_tagged_faces(bm, hflag);
277         }
278         if (htype & BM_EDGE) {
279                 bm_remove_tagged_edges(bm, hflag);
280         }
281         if (htype & BM_VERT) {
282                 bm_remove_tagged_verts(bm, hflag);
283         }
284 }
285
286 /**
287  * \warning oflag applies to different types in some contexts,
288  * not just the type being removed.
289  */
290 void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
291 {
292         BMEdge *e;
293         BMFace *f;
294
295         BMIter eiter;
296         BMIter fiter;
297
298         switch (type) {
299                 case DEL_VERTS:
300                 {
301                         bm_remove_tagged_verts(bm, hflag);
302
303                         break;
304                 }
305                 case DEL_EDGES:
306                 {
307                         /* flush down to vert */
308                         BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
309                                 if (BM_elem_flag_test(e, hflag)) {
310                                         BM_elem_flag_enable(e->v1, hflag);
311                                         BM_elem_flag_enable(e->v2, hflag);
312                                 }
313                         }
314                         bm_remove_tagged_edges(bm, hflag);
315                         bm_remove_tagged_verts_loose(bm, hflag);
316
317                         break;
318                 }
319                 case DEL_EDGESFACES:
320                 {
321                         bm_remove_tagged_edges(bm, hflag);
322
323                         break;
324                 }
325                 case DEL_ONLYFACES:
326                 {
327                         bm_remove_tagged_faces(bm, hflag);
328
329                         break;
330                 }
331                 case DEL_ONLYTAGGED:
332                 {
333                         BM_mesh_delete_hflag_tagged(bm, hflag, BM_ALL_NOLOOP);
334
335                         break;
336                 }
337                 case DEL_FACES:
338                 {
339                         /* go through and mark all edges and all verts of all faces for delete */
340                         BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
341                                 if (BM_elem_flag_test(f, hflag)) {
342                                         BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
343                                         BMLoop *l_iter;
344
345                                         l_iter = l_first;
346                                         do {
347                                                 BM_elem_flag_enable(l_iter->v, hflag);
348                                                 BM_elem_flag_enable(l_iter->e, hflag);
349                                         } while ((l_iter = l_iter->next) != l_first);
350                                 }
351                         }
352                         /* now go through and mark all remaining faces all edges for keeping */
353                         BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
354                                 if (!BM_elem_flag_test(f, hflag)) {
355                                         BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
356                                         BMLoop *l_iter;
357
358                                         l_iter = l_first;
359                                         do {
360                                                 BM_elem_flag_disable(l_iter->v, hflag);
361                                                 BM_elem_flag_disable(l_iter->e, hflag);
362                                         } while ((l_iter = l_iter->next) != l_first);
363                                 }
364                         }
365                         /* also mark all the vertices of remaining edges for keeping */
366                         BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
367                                 if (!BM_elem_flag_test(e, hflag)) {
368                                         BM_elem_flag_disable(e->v1, hflag);
369                                         BM_elem_flag_disable(e->v2, hflag);
370                                 }
371                         }
372                         /* now delete marked face */
373                         bm_remove_tagged_faces(bm, hflag);
374                         /* delete marked edge */
375                         bm_remove_tagged_edges(bm, hflag);
376                         /* remove loose vertice */
377                         bm_remove_tagged_verts(bm, hflag);
378
379                         break;
380                 }
381         }
382 }
383
384 /** \} */