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