forgot to add this file.
authorJoseph Eagar <joeedh@gmail.com>
Tue, 23 Jun 2009 06:37:12 +0000 (06:37 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Tue, 23 Jun 2009 06:37:12 +0000 (06:37 +0000)
source/blender/bmesh/operators/removedoubles.c [new file with mode: 0644]

diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c
new file mode 100644 (file)
index 0000000..d2f5103
--- /dev/null
@@ -0,0 +1,225 @@
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "bmesh.h"
+#include "mesh_intern.h"
+#include "bmesh_private.h"
+#include "BLI_arithb.h"
+#include "BLI_ghash.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BL(ptr) ((BMLoop*)(ptr))
+
+void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op)
+{
+       BMIter liter;
+       BMLoop *l;
+       BMVert *v2, *doub;
+       int split=0;
+
+       BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+               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)
+               {
+                       doub = l->v;
+                       split = 1;
+                       break;
+               }
+       }
+
+       if (split) {
+               BMLoop *nl;
+               BMFace *f2 = BM_Split_Face(bm, f, doub, v2, &nl, NULL);
+
+               remdoubles_splitface(f, bm, op);
+               remdoubles_splitface(f2, bm, op);
+       }
+}
+
+#define ELE_DEL                1
+#define EDGE_COL       2
+#define FACE_MARK      2
+
+#if 0
+int remdoubles_face_overlaps(BMesh *bm, BMVert **varr, 
+                            int len, BMFace *exclude, 
+                            BMFace **overlapface)
+{
+       BMIter vertfaces;
+       BMFace *f;
+       int i, amount;
+
+       if (overlapface) *overlapface = NULL;
+
+       for(i=0; i < len; i++){
+               f = BMIter_New(&vertfaces, bm, BM_FACES_OF_VERT, varr[i] );
+               while(f){
+                       amount = BM_Verts_In_Face(bm, f, varr, len);
+                       if(amount >= len){
+                               if (overlapface) *overlapface = f;
+                               return 1;                               
+                       }
+                       f = BMIter_Step(&vertfaces);
+               }
+       }
+       return 0;
+}
+#endif
+
+void bmesh_weldverts_exec(BMesh *bm, BMOperator *op)
+{
+       BMIter iter, liter;
+       BMVert *v, *v2;
+       BMEdge *e, *e2, **edges = NULL;
+       V_DECLARE(edges);
+       BMLoop *l;
+       BMFace *f, *f2;
+       int a;
+
+       BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+               if (BMO_Get_MapPointer(bm, op, "targetmap", v))
+                       BMO_SetFlag(bm, v, ELE_DEL);
+       }
+
+       BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+               remdoubles_splitface(f, bm, op);
+       }
+       
+       BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+               v = BMO_Get_MapPointer(bm, op, "targetmap", e->v1);
+               v2 = BMO_Get_MapPointer(bm, op, "targetmap", e->v2);
+               
+               if (!v) v = e->v1;
+               if (!v2) v2 = e->v2;
+
+               if ((e->v1 != v) || (e->v2 != v2)) {
+                       if (v == v2) BMO_SetFlag(bm, e, EDGE_COL);
+                       else BM_Make_Edge(bm, v, v2, e, 1);
+
+                       BMO_SetFlag(bm, e, ELE_DEL);
+               }
+       }
+
+       BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+               BMINDEX_SET(f, 0);
+               BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+                       if (BMO_TestFlag(bm, l->v, ELE_DEL))
+                               BMO_SetFlag(bm, f, FACE_MARK);
+                       if (BMO_TestFlag(bm, l->e, EDGE_COL)) 
+                               BMINDEX_SET(f, BMINDEX_GET(f)+1);
+               }
+       }
+
+       BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
+               if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
+               if (f->len - BMINDEX_GET(f) + 1 < 3) {
+                       BMO_SetFlag(bm, f, ELE_DEL);
+                       continue;
+               }
+
+               V_RESET(edges);
+               a = 0;
+               BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) {
+                       v = l->v;
+                       v2 = BL(l->head.next)->v;
+                       if (BMO_TestFlag(bm, v, ELE_DEL)) 
+                               v = BMO_Get_MapPointer(bm, op, "targetmap", v);
+                       if (BMO_TestFlag(bm, v2, ELE_DEL)) 
+                                       v2 = BMO_Get_MapPointer(bm, op, "targetmap", v2);
+                       
+                       e2 = BM_Edge_Exist(v, v2);
+                       if (e2) {
+                               V_GROW(edges);
+                               edges[a++] = e2;
+                       }
+               }
+               
+               f2 = BM_Make_Ngon(bm, v, v2, edges, a, 0);
+               if (f2) {
+                       BM_Copy_Attributes(bm, bm, f, f2);
+                       BMO_SetFlag(bm, f, ELE_DEL);
+               }
+
+               /*need to still copy customdata stuff here, will do later*/
+       }
+
+       BMO_CallOpf(bm, "del geom=%fvef context=%i", ELE_DEL, DEL_ONLYTAGGED);
+
+       V_FREE(edges);
+}
+
+static int vergaverco(const void *e1, const void *e2)
+{
+       const BMVert *v1 = e1, *v2 = e2;
+       float x1 = v1->co[0] + v1->co[1] + v1->co[2];
+       float x2 = v2->co[0] + v2->co[1] + v2->co[2];
+
+       if (x1 > x2) return 1;
+       else if (x1 < x2) return -1;
+       else return 0;
+}
+
+#define VERT_TESTED    1
+#define VERT_DOUBLE    2
+#define VERT_TARGET    4
+
+void bmesh_removedoubles_exec(BMesh *bm, BMOperator *op)
+{
+       BMOperator weldop;
+       BMOIter oiter;
+       BMVert *v, *v2;
+       BMVert **verts=NULL;
+       V_DECLARE(verts);
+       float dist, distsqr;
+       int i, j, len;
+
+       dist = BMO_Get_Float(op, "dist");
+       distsqr = dist*dist;
+
+       BMO_Init_Op(&weldop, "weldverts");
+       
+       i = 0;
+       BMO_ITER(v, &oiter, bm, op, "verts", BM_VERT) {
+               V_GROW(verts);
+               verts[i++] = v;
+       }
+
+       /*sort by vertex coordinates added together*/
+       qsort(verts, V_COUNT(verts), sizeof(void*), vergaverco);
+       
+       len = V_COUNT(verts);
+       for (i=0; i<len; i++) {
+               v = verts[i];
+               if (BMO_TestFlag(bm, v, VERT_TESTED)) continue;
+               
+               BMO_SetFlag(bm, v, VERT_TESTED);
+               for (j=i+1; j<len; j++) {
+                       float vec[3];
+                       
+                       v2 = verts[j];
+                       vec[0] = v->co[0] - v2->co[0];
+                       vec[1] = v->co[1] - v2->co[1];
+                       vec[2] = v->co[2] - v2->co[2];
+                       
+                       if (INPR(vec, vec) < distsqr) {
+                               BMO_SetFlag(bm, v2, VERT_TESTED);
+                               BMO_SetFlag(bm, v2, VERT_DOUBLE);
+                               BMO_SetFlag(bm, v, VERT_TARGET);
+                       
+                               BMO_Insert_MapPointer(bm, &weldop, "targetmap", v2, v);
+                       }
+               }
+       }
+
+       V_FREE(verts);
+
+       BMO_Exec_Op(bm, &weldop);
+       BMO_Finish_Op(bm, &weldop);
+}