merge with/from trunk at r35190
[blender.git] / source / blender / bmesh / operators / removedoubles.c
index b19b409b93dad4e74b2be1ec542a1416cdeb6836..f806fd33a6b6596c32e1e1ec029abe56ca04a6e9 100644 (file)
@@ -7,9 +7,11 @@
 
 #include "BKE_utildefines.h"
 
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_ghash.h"
 #include "BLI_blenlib.h"
+#include "BLI_array.h"
+#include "BLI_utildefines.h"
 
 #include "bmesh.h"
 #include "mesh_intern.h"
@@ -32,8 +34,8 @@ void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op)
                v2 = BMO_Get_MapPointer(bm, op, "targetmap", l->v);
                /*ok: if v2 is NULL (e.g. not in the map) then it's
                      a target vert, otherwise it's a double*/
-               if (v2 && BM_Vert_In_Face(f, v2) && v2 != BL(l->head.prev)->v 
-                   && v2 != BL(l->head.next)->v)
+               if (v2 && BM_Vert_In_Face(f, v2) && v2 != BL(l->prev)->v 
+                   && v2 != BL(l->next)->v)
                {
                        doub = l->v;
                        split = 1;
@@ -85,9 +87,9 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
        BMIter iter, liter;
        BMVert *v, *v2;
        BMEdge *e, *e2, **edges = NULL;
-       V_DECLARE(edges);
+       BLI_array_declare(edges);
        BMLoop *l, *l2, **loops = NULL;
-       V_DECLARE(loops);
+       BLI_array_declare(loops);
        BMFace *f, *f2;
        int a, b;
 
@@ -136,12 +138,12 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
                        continue;
                }
 
-               V_RESET(edges);
-               V_RESET(loops);
+               BLI_array_empty(edges);
+               BLI_array_empty(loops);
                a = 0;
                BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
                        v = l->v;
-                       v2 = BL(l->head.next)->v;
+                       v2 = BL(l->next)->v;
                        if (BMO_TestFlag(bm, v, ELE_DEL)) 
                                v = BMO_Get_MapPointer(bm, op, "targetmap", v);
                        if (BMO_TestFlag(bm, v2, ELE_DEL)) 
@@ -156,8 +158,8 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
                                if (b != a)
                                        continue;
 
-                               V_GROW(edges);
-                               V_GROW(loops);
+                               BLI_array_growone(edges);
+                               BLI_array_growone(loops);
 
                                edges[a] = e2;
                                loops[a] = l;
@@ -166,6 +168,9 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
                        }
                }
                
+               if (BLI_array_count(loops) < 3)
+                       continue;
+
                v = loops[0]->v;
                v2 = loops[1]->v;
 
@@ -174,7 +179,7 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
                if (BMO_TestFlag(bm, v2, ELE_DEL)) 
                        v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
                
-               f2 = BM_Make_Ngon(bm, v, v2, edges, a, 0);
+               f2 = BM_Make_Ngon(bm, v2, v, edges, a, 0);
                if (f2) {
                        BM_Copy_Attributes(bm, bm, f, f2);
 
@@ -190,8 +195,8 @@ void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
 
        BMO_CallOpf(bm, "del geom=%fvef context=%i", ELE_DEL, DEL_ONLYTAGGED);
 
-       V_FREE(edges);
-       V_FREE(loops);
+       BLI_array_free(edges);
+       BLI_array_free(loops);
 }
 
 static int vergaverco(const void *e1, const void *e2)
@@ -210,6 +215,7 @@ static int vergaverco(const void *e1, const void *e2)
 #define VERT_TARGET    4
 #define VERT_KEEP      8
 #define VERT_MARK      16
+#define VERT_IN                32
 
 #define EDGE_MARK      1
 
@@ -312,7 +318,7 @@ void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
        BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
                if (!snapv) {
                        snapv = v;
-                       VECCOPY(snapv->co, vec);
+                       copy_v3_v3(snapv->co, vec);
                } else {
                        BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
                }               
@@ -328,7 +334,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
        BMWalker walker;
        BMIter iter;
        BMEdge *e, **edges = NULL;
-       V_DECLARE(edges);
+       BLI_array_declare(edges);
        float min[3], max[3];
        int i, tot;
        
@@ -343,19 +349,19 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
                        continue;
 
                e = BMW_Begin(&walker, e->v1);
-               V_RESET(edges);
+               BLI_array_empty(edges);
 
                INIT_MINMAX(min, max);
                for (tot=0; e; tot++, e=BMW_Step(&walker)) {
-                       V_GROW(edges);
+                       BLI_array_growone(edges);
                        edges[tot] = e;
 
                        DO_MINMAX(e->v1->co, min, max);
                        DO_MINMAX(e->v2->co, min, max);
                }
 
-               VECADD(min, min, max);
-               VECMUL(min, 0.5f);
+               add_v3_v3v3(min, min, max);
+               mul_v3_fl(min, 0.5f);
 
                /*snap edges to a point.  for initial testing purposes anyway.*/
                for (i=0; i<tot; i++) {
@@ -373,7 +379,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
        BMO_Finish_Op(bm, &weldop);
 
        BMW_End(&walker);
-       V_FREE(edges);
+       BLI_array_free(edges);
 }
 
 /*uv collapse function*/
@@ -384,7 +390,7 @@ void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
        BMLoop *l, *l2;
        BMWalker walker;
        void **blocks = NULL;
-       V_DECLARE(blocks);
+       BLI_array_declare(blocks);
        CDBlockBytes min, max;
        int i, tot, type = bm->ldata.layers[layer].type;
 
@@ -397,13 +403,13 @@ void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
                BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
                        if (BMO_TestFlag(bm, l->e, EDGE_MARK)) {
                                /*walk*/
-                               V_RESET(blocks);
+                               BLI_array_empty(blocks);
                                tot = 0;
                                l2 = BMW_Begin(&walker, l);
 
                                CustomData_data_initminmax(type, &min, &max);
                                for (tot=0; l2; tot++, l2=BMW_Step(&walker)) {
-                                       V_GROW(blocks);
+                                       BLI_array_growone(blocks);
                                        blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer);
                                        CustomData_data_dominmax(type, blocks[tot], &min, &max);
                                }
@@ -423,7 +429,7 @@ void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
        }
 
        BMW_End(&walker);
-       V_FREE(blocks);
+       BLI_array_free(blocks);
 }
 
 void bmesh_collapsecon_exec(BMesh *bm, BMOperator *op)
@@ -442,7 +448,7 @@ void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
        BMOIter oiter;
        BMVert *v, *v2;
        BMVert **verts=NULL;
-       V_DECLARE(verts);
+       BLI_array_declare(verts);
        float dist, distsqr;
        int i, j, len;
 
@@ -453,14 +459,14 @@ void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
        
        i = 0;
        BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
-               V_GROW(verts);
+               BLI_array_growone(verts);
                verts[i++] = v;
        }
 
        /*sort by vertex coordinates added together*/
-       qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
+       qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
        
-       len = V_COUNT(verts);
+       len = BLI_array_count(verts);
        for (i=0; i<len; i++) {
                v = verts[i];
                if (BMO_TestFlag(bm, v, VERT_TESTED)) continue;
@@ -470,8 +476,10 @@ void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
                        float vec[3];
                        
                        v2 = verts[j];
-                       if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
-                            > distsqr) break;
+                       //if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+                       //     > distsqr) break;
+                       if ((v2->co[0]-v->co[0]) + (v2->co[1]-v->co[1]) + (v2->co[2]-v->co[2]) > distsqr*4.0f)
+                               break;
 
                        vec[0] = v->co[0] - v2->co[0];
                        vec[1] = v->co[1] - v2->co[1];
@@ -487,7 +495,7 @@ void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
                }
        }
 
-       V_FREE(verts);
+       BLI_array_free(verts);
 
        BMO_Exec_Op(bm, &weldop);
        BMO_Finish_Op(bm, &weldop);
@@ -499,7 +507,7 @@ void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
        BMOIter oiter;
        BMVert *v, *v2;
        BMVert **verts=NULL;
-       V_DECLARE(verts);
+       BLI_array_declare(verts);
        float dist, distsqr;
        int i, j, len, keepvert;
 
@@ -508,18 +516,18 @@ void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
 
        i = 0;
        BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
-               V_GROW(verts);
+               BLI_array_growone(verts);
                verts[i++] = v;
        }
 
        keepvert = BMO_IterNew(&oiter, bm, op, "keepverts", BM_VERT) != NULL;
 
        /*sort by vertex coordinates added together*/
-       qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
+       qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
        
        BMO_Flag_Buffer(bm, op, "keepverts", VERT_KEEP, BM_VERT);
 
-       len = V_COUNT(verts);
+       len = BLI_array_count(verts);
        for (i=0; i<len; i++) {
                v = verts[i];
                if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
@@ -534,7 +542,7 @@ void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
                                        continue;
                        }
 
-                       if (VecLenCompare(v->co, v2->co, dist)) {
+                       if (compare_len_v3v3(v->co, v2->co, dist)) {
                                BMO_SetFlag(bm, v2, VERT_DOUBLE);
                                BMO_SetFlag(bm, v, VERT_TARGET);
                        
@@ -543,5 +551,60 @@ void bmesh_finddoubles_exec(BMesh *bm, BMOperator *op)
                }
        }
 
-       V_FREE(verts);
+       BLI_array_free(verts);
+}
+
+void bmesh_automerge_exec(BMesh *bm, BMOperator *op)
+{
+       BMOIter oiter;
+       BMOperator weldop;
+       BMVert *v, *v2;
+       BMVert **verts=NULL;
+       BLI_array_declare(verts);
+       float dist, distsqr;
+       int i, j, len, keepvert;
+
+       dist = BMO_Get_Float(op, "dist");
+       distsqr = dist*dist;
+
+       i = 0;
+       BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+               BLI_array_growone(verts);
+               verts[i++] = v;
+       }
+
+       BMO_Init_Op(&weldop, "weldverts");
+
+       /*sort by vertex coordinates added together*/
+       qsort(verts, BLI_array_count(verts), sizeof(void*), vergaverco);
+       
+       BMO_Flag_Buffer(bm, op, "verts", VERT_KEEP, BM_VERT);
+
+       len = BLI_array_count(verts);
+       for (i=0; i<len; i++) {
+               v = verts[i];
+               if (BMO_TestFlag(bm, v, VERT_DOUBLE)) continue;
+               
+               for (j=i+1; j<len; j++) {
+                       v2 = verts[j];
+                       if ((v2->co[0]+v2->co[1]+v2->co[2]) - (v->co[0]+v->co[1]+v->co[2])
+                            > distsqr) break;
+                       
+                       /* only allow unselected -> selected */
+                       if (BMO_TestFlag(bm, v2, VERT_IN))
+                               continue;
+
+                       if (compare_len_v3v3(v->co, v2->co, dist)) {
+                               BMO_SetFlag(bm, v2, VERT_DOUBLE);
+                               BMO_SetFlag(bm, v, VERT_TARGET);
+                       
+                               BMO_Insert_MapPointer(bm, &weldop, "targetmap", v2, v);
+                       }
+               }
+       }
+
+       BMO_Exec_Op(bm, &weldop);
+       BMO_Finish_Op(bm, &weldop);
+
+       BLI_array_free(verts);
 }