split dissolve_disk into dissolve_vert dissolve_disk as agreed. also made dissolve...
[blender.git] / source / blender / bmesh / operators / dissolveops.c
1 #include "MEM_guardedalloc.h"
2
3 #include "BKE_utildefines.h"
4
5 #include "bmesh.h"
6 #include "mesh_intern.h"
7 #include "bmesh_private.h"
8 #include "BLI_arithb.h"
9
10 #include <stdio.h>
11
12 #define FACE_MARK       1
13
14 #define VERT_MARK       1
15
16 void dissolvefaces_exec(BMesh *bm, BMOperator *op)
17 {
18         BMOIter iter;
19         BMIter liter;
20         BMLoop *l;
21         BMFace *f, *f2, *nf = NULL;
22
23         //BMO_Flag_Buffer(bm, op, BMOP_DISFACES_FACEIN, FACE_MARK);
24
25         /*TODO: need to discuss with Briggs how best to implement this, seems this would be
26           a great time to use the walker api, get it up to snuff.  perhaps have a walker
27           that goes over inner vertices of a contiguously-flagged region?  then you
28           could just use dissolve disk on them.*/
29         if (BMO_GetSlot(op, BMOP_DISFACES_FACEIN)->len != 2) return;
30
31         /*HACK: for debugging purposes, handle cases of two adjacent faces*/
32         f = BMO_IterNew(&iter, bm, op, BMOP_DISFACES_FACEIN);
33         f2 = BMO_IterStep(&iter);
34
35         for (l=BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);l;l=BMIter_Step(&liter)) {
36                 if (!l->radial.next) continue;
37                 if (((BMLoop*)l->radial.next->data)->f == f2) {
38                         nf = BM_Join_Faces(bm, f, f2, l->e, 1, 0);
39                         break;
40                 }
41         }
42
43         if (nf) {
44                 BMO_SetFlag(bm, nf, 1);
45                 BMO_Flag_To_Slot(bm, op, BMOP_DISFACES_REGIONOUT, 1, BM_FACE);
46         }
47
48 }
49
50 /*returns 1 if any faces were dissolved*/
51 int BM_DissolveFaces(EditMesh *em, int flag) {
52         BMesh *bm = editmesh_to_bmesh(em);
53         EditMesh *em2;
54         BMOperator op;
55
56         BMO_Init_Op(&op, BMOP_DISSOLVE_FACES);
57         BMO_HeaderFlag_To_Slot(bm, &op, BMOP_DISFACES_FACEIN, flag, BM_FACE);
58         BMO_Exec_Op(bm, &op);
59         BMO_Finish_Op(bm, &op);
60         
61         em2 = bmesh_to_editmesh(bm);
62         set_editMesh(em, em2);
63         MEM_freeN(em2);
64
65         return BMO_GetSlot(&op, BMOP_DISFACES_REGIONOUT)->len > 0;
66 }
67
68 void dissolveverts_exec(BMesh *bm, BMOperator *op)
69 {
70         BMOpSlot *vinput;
71         BMIter iter, liter, fiter;
72         BMVert *v;
73         BMFace *f, *f2;
74         BMEdge *fe;
75         BMLoop *l;
76         int found, found2, found3, len, oldlen=0;
77         
78         vinput = BMO_GetSlot(op, BMOP_DISVERTS_VERTIN);
79
80         BMO_Flag_Buffer(bm, op, BMOP_DISVERTS_VERTIN, VERT_MARK);
81         
82         found = 1;
83         while (found) {
84                 found = 0;
85                 len = 0;
86                 for (v=BMIter_New(&iter, bm, BM_VERTS, NULL); v; v=BMIter_Step(&iter)) {
87                         if (BMO_TestFlag(bm, v, VERT_MARK)) {
88                                 if (!BM_Dissolve_Vert(bm, v)) {
89                                         BMO_RaiseError(bm, op,
90                                               BMERR_DISSOLVEDISK_FAILED, NULL);
91                                         return;
92                                 }
93                                 found = 1;
94                                 len++;
95                         }
96                 }
97
98
99                 /*clean up two-edged faces*/
100                 /*basic idea is to keep joining 2-edged faces until their
101                   gone.  this however relies on joining two 2-edged faces
102                   together to work, which doesn't.*/
103                 found3 = 1;
104                 while (found3) {
105                         found3 = 0;
106                         for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)){
107                                 if (BM_Validate_Face(bm, f, stderr)) {
108                                         printf("error.\n");
109                                 }
110
111                                 if (f->len == 2) {
112                                         //this design relies on join faces working
113                                         //with two-edged faces properly.
114                                         //commenting this line disables the
115                                         //outermost loop.
116                                         //found3 = 1;
117                                         found2 = 0;
118                                         l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
119                                         fe = l->e;
120                                         for (; l; l=BMIter_Step(&liter)) {
121                                                 f2 = BMIter_New(&fiter, bm,
122                                                                 BM_FACES_OF_EDGE, l->e);
123                                                 for (; f2; f2=BMIter_Step(&fiter)) {
124                                                         if (f2 != f) {
125                                                                 BM_Join_Faces(bm, f, f2, l->e, 
126                                                                               1, 0);
127                                                                 found2 = 1;
128                                                                 break;
129                                                         }
130                                                 }
131                                                 if (found2) break;
132                                         }
133
134                                         if (!found2) {
135                                                 bmesh_kf(bm, f);
136                                                 bmesh_ke(bm, fe);
137                                         }
138                                 } /*else if (f->len == 3) {
139                                         BMEdge *ed[3];
140                                         BMVert *vt[3];
141                                         BMLoop *lp[3];
142                                         int i=0;
143
144                                         //check for duplicate edges
145                                         l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
146                                         for (; l; l=BMIter_Step(&liter)) {
147                                                 ed[i] = l->e;   
148                                                 lp[i] = l;
149                                                 vt[i++] = l->v;
150                                         }
151                                         if (vt[0] == vt[1] || vt[0] == vt[2]) {
152                                                 i += 1;
153                                         }
154                                 }*/
155                         }
156                 }
157                 if (oldlen == len) break;
158                 oldlen = len;
159         }
160
161 }