-> New Euler: "Unglue Face Region Make Vert"
authorGeoffrey Bantle <hairbat@yahoo.com>
Fri, 6 Mar 2009 18:57:43 +0000 (18:57 +0000)
committerGeoffrey Bantle <hairbat@yahoo.com>
Fri, 6 Mar 2009 18:57:43 +0000 (18:57 +0000)
Added a new euler that will take as an argument a face
that is part of a disk and a vertex in the face. The euler
will then 'unglue' this region. An example of this would
be two cones joined at the tip...

Note that this code is untested and probably will have
bugs so shouldnt be trusted yet...

source/blender/bmesh/intern/bmesh_eulers.c
source/blender/bmesh/intern/bmesh_structure.h

index bf918c92cca558a8aedbf8f31df35b235bccf0fc..1871bb5dcc7316a39e73e7e1d9f394a9d0989636 100644 (file)
@@ -983,3 +983,171 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
        bmesh_free_poly(bm, f2);        
        return f1;
 }
+
+/**
+*    bmesh_URMV
+*
+*    UNGLUE REGION MAKE VERT:
+*
+*    Takes a locally manifold disk of face corners and 'unglues' it
+*    creating a new vertex
+*
+**/
+
+#define URMV_VISIT    1
+#define URMV_VISIT2   2
+
+BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv)
+{
+    BMVert *nv = NULL;
+    BMLoop *l = NULL, *sl = NULL;
+    BMEdge *curedge = NULL;
+    int numloops = 0, numedges = 0, i, maxedges, maxloops;
+
+
+    /*Todo: Validation*/
+    /*validate radial cycle of all collected loops*/
+    /*validate the disk cycle of sv, and nv*/
+    /*validate the face length of all faces? overkill?*/
+    /*validate the l->e pointers of all affected faces, ie: l->v and l->next->v should be equivalent to l->e*/
+   
+    /*verify that sv has edges*/
+    if(sv->edge == NULL)
+        return NULL;
+   
+    /*first verify no wire edges on sv*/
+    curedge = sv->edge;
+    do{
+        if(curedge->loop == NULL)
+            return NULL;
+        curedge = bmesh_disk_nextedge(curedge, sv);
+    }while(curedge != sv->edge);
+   
+    /*next verify that sv is in sf*/
+    l = sf->loopbase;
+    do{
+        if(l->v == sv){
+            sl = l;
+            break;
+        }
+        l = (BMLoop*)(l->head.next);
+    }while(l != sf->loopbase);
+   
+    if(sl == NULL)
+        return NULL;
+   
+    /*clear euler flags*/
+    sv->head.eflag1 = 0;
+   
+    curedge = sv->edge;
+    do{
+        curedge->head.eflag1 = 0;
+        l = curedge->loop;
+        do{
+            l->head.eflag1 = 0;
+            l->f->head.eflag1 = 0;
+            l = bmesh_radial_nextloop(l);
+        }while(l != curedge->loop);
+        curedge = bmesh_disk_nextedge(curedge, sv);
+    }while(curedge != sv->edge);
+   
+    /*search through face disk and flag elements as we go.*/
+    /*Note, test this to make sure that it works correct on
+    non-manifold faces!
+    */
+    l = sl;
+    l->e->head.eflag1 |= URMV_VISIT;
+    l->f->head.eflag1 |= URMV_VISIT;
+    do{
+        if(l->v == sv)
+            l = bmesh_radial_nextloop((BMLoop*)(l->head.prev));
+        else
+            l = bmesh_radial_nextloop((BMLoop*)(l->head.next));
+        l->e->head.eflag1 |= URMV_VISIT;
+        l->f->head.eflag1 |= URMV_VISIT;
+    }while(l != sl && (bmesh_cycle_length(&(l->radial)) > 1) );
+   
+    /*Verify that all visited edges are at least 1 or 2 manifold*/
+    curedge = sv->edge;
+    do{
+        if(curedge->head.eflag1 && (bmesh_cycle_length(&(curedge->loop->radial)) > 2) )
+            return NULL;
+        curedge = bmesh_disk_nextedge(curedge, sv);
+    }while(curedge != sv->edge);
+
+       /*allocate temp storage - we overallocate here instead of trying to be clever*/
+       maxedges = 0;
+       maxloops = 0;
+       curedge = sv->edge;
+       do{
+               if(curedge->loop){
+                       l = curedge->loop;
+                       do{
+                               maxloops += l->f->len;
+                               l = bmesh_radial_nextloop(l);
+                       }while(l != curedge->loop);
+               }
+               maxedges+= 1;
+               curedge = bmesh_disk_nextedge(curedge,sv);
+       }while(curedge != sv->edge);
+
+       if(bm->edarlen < maxedges){
+               MEM_freeN(bm->edar);
+               bm->edar = MEM_callocN(sizeof(BMEdge *) * maxedges, "BM Edge pointer array");
+               bm->edarlen = maxedges;
+       }
+       if(bm->lparlen < maxloops){
+               MEM_freeN(bm->lpar);
+               bm->lpar = MEM_callocN(sizeof(BMLoop *) * maxloops, "BM Loop pointer array");
+               bm->lparlen = maxloops;
+       }
+
+    /*first get loops by looping around edges and loops around that edges faces*/
+    curedge = sv->edge;
+    do{
+        if(curedge->loop){
+            l = curedge->loop;
+            do{
+                if( (l->head.eflag1 & URMV_VISIT) && (!(l->head.eflag1 & URMV_VISIT2)) ){
+                    bm->lpar[numloops] = l;
+                    l->head.eflag1 |= URMV_VISIT2;
+                    numloops++;
+                }
+                l = bmesh_radial_nextloop(l);
+            }while(l != curedge->loop);
+        }
+        curedge = bmesh_disk_nextedge(curedge, sv);
+    }while(curedge != sv->edge);
+
+    /*now collect edges by looping around edges and looking at visited flags*/
+    curedge = sv->edge;
+    do{
+        if(curedge->head.eflag1 & URMV_VISIT){
+            bm->edar[numedges] = curedge;
+            numedges++;
+        }
+        curedge = bmesh_disk_nextedge(curedge, sv);
+    }while(curedge != sv->edge);
+   
+    /*make new vertex*/
+    nv = bmesh_addvertlist(bm, sv);
+   
+    /*go through and relink edges*/
+    for(i = 0;  i <  numedges; i++){
+        curedge = bm->edar[i];
+        /*remove curedge from sv*/
+        bmesh_disk_remove_edge(curedge, sv);
+        /*swap out sv for nv in curedge*/
+        bmesh_edge_swapverts(curedge, sv, nv);
+        /*add curedge to nv's disk cycle*/
+        bmesh_disk_append_edge(curedge, nv);
+    }
+   
+    /*go through and relink loops*/
+    for(i = 0; i < numloops; i ++){
+        l = bm->lpar[i];
+        if(l->v == sv)
+            l->v = nv;
+       }
+       return nv;
+}
index 3135457938e169693e53d430455af4a96a5d3631..ba63bb8f65f69c5da82f9d7c6208915023f2ee30 100644 (file)
@@ -94,4 +94,7 @@ int bmesh_jekv(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv);
 int bmesh_loop_reverse(struct BMesh *bm, struct BMFace *f);
 struct BMFace *bmesh_jfke(struct BMesh *bm, struct BMFace *f1, BMFace *f2, BMEdge *e);
 
+struct BMVert *bmesh_urmv(struct BMesh *bm, struct BMFace *sf, struct BMVert *sv);
+//int *bmesh_grkv(struct BMesh *bm, struct BMFace *sf, struct BMVert *kv);
+
 #endif