Blender V2.61 - r43446

BME_structure.c

Go to the documentation of this file.
00001 /*
00002  * BME_structure.c    jan 2007
00003  *
00004  *  Low level routines for manipulating the BMesh structure.
00005  *
00006  *
00007  * ***** BEGIN GPL LICENSE BLOCK *****
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License
00011  * as published by the Free Software Foundation; either version 2
00012  * of the License, or (at your option) any later version.
00013  * about this.  
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * The Original Code is Copyright (C) 2007 Blender Foundation.
00025  * All rights reserved.
00026  *
00027  * The Original Code is: all of this file.
00028  *
00029  * Contributor(s): Geoffrey Bantle.
00030  *
00031  * ***** END GPL LICENSE BLOCK *****
00032  */
00033 
00039 #include <limits.h>
00040 
00041 #include "MEM_guardedalloc.h"
00042 #include "BLI_listbase.h"
00043 #include "BLI_utildefines.h"
00044 #include "BKE_bmesh.h"
00050 int BME_vert_in_edge(BME_Edge *e, BME_Vert *v){
00051     if(e->v1 == v || e->v2 == v) return 1;
00052     return 0;
00053 }
00054 int BME_verts_in_edge(BME_Vert *v1, BME_Vert *v2, BME_Edge *e){
00055     if(e->v1 == v1 && e->v2 == v2) return 1;
00056     else if(e->v1 == v2 && e->v2 == v1) return 1;
00057     return 0;
00058 }
00059 
00060 BME_Vert *BME_edge_getothervert(BME_Edge *e, BME_Vert *v){  
00061     if(e->v1 == v) return e->v2;
00062     else if(e->v2 == v) return e->v1;
00063     return NULL;
00064 }
00065 
00066 int BME_edge_swapverts(BME_Edge *e, BME_Vert *orig, BME_Vert *new){
00067     if(e->v1 == orig){ 
00068         e->v1 = new;
00069         e->d1.next = NULL;
00070         e->d1.prev = NULL;
00071         return 1;
00072     }
00073     else if(e->v2 == orig){
00074         e->v2 = new;
00075         e->d2.next = NULL;
00076         e->d2.prev = NULL;
00077         return 1;
00078     }
00079     return 0;
00080 }
00081 
00086 BME_Vert *BME_addvertlist(BME_Mesh *bm, BME_Vert *example){
00087     BME_Vert *v=NULL;
00088     v = BLI_mempool_alloc(bm->vpool);
00089     v->next = v->prev = NULL;
00090     v->EID = bm->nextv;
00091     v->co[0] = v->co[1] = v->co[2] = 0.0f;
00092     v->no[0] = v->no[1] = v->no[2] = 0.0f;
00093     v->edge = NULL;
00094     v->data = NULL;
00095     v->eflag1 = v->eflag2 = v->tflag1 = v->tflag2 = 0;
00096     v->flag = v->h = 0;
00097     v->bweight = 0.0f;
00098     BLI_addtail(&(bm->verts), v);
00099     bm->nextv++;
00100     bm->totvert++;
00101 
00102     if(example){
00103         VECCOPY(v->co,example->co);
00104         CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data);
00105     }
00106     else
00107         CustomData_bmesh_set_default(&bm->vdata, &v->data);
00108 
00109     return v;
00110 }
00111 BME_Edge *BME_addedgelist(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge *example){
00112     BME_Edge *e=NULL;
00113     e = BLI_mempool_alloc(bm->epool);
00114     e->next = e->prev = NULL;
00115     e->EID = bm->nexte;
00116     e->v1 = v1;
00117     e->v2 = v2;
00118     e->d1.next = e->d1.prev = e->d2.next = e->d2.prev = NULL;
00119     e->d1.data = e;
00120     e->d2.data = e;
00121     e->loop = NULL;
00122     e->data = NULL;
00123     e->eflag1 = e->eflag2 = e->tflag1 = e->tflag2 = 0;
00124     e->flag = e->h = 0;
00125     e->crease = e->bweight = 0.0f;
00126     bm->nexte++;
00127     bm->totedge++;
00128     BLI_addtail(&(bm->edges), e);
00129     
00130     if(example)
00131         CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->data, &e->data);
00132     else
00133         CustomData_bmesh_set_default(&bm->edata, &e->data);
00134 
00135 
00136     return e;
00137 }
00138 BME_Loop *BME_create_loop(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Poly *f, BME_Loop *example){
00139     BME_Loop *l=NULL;
00140     l = BLI_mempool_alloc(bm->lpool);
00141     l->next = l->prev = NULL;
00142     l->EID = bm->nextl;
00143     l->radial.next = l->radial.prev = NULL;
00144     l->radial.data = l;
00145     l->v = v;
00146     l->e = e;
00147     l->f = f;
00148     l->data = NULL;
00149     l->eflag1 = l->eflag2 = l->tflag1 = l->tflag2 = 0;
00150     l->flag = l->h = 0; //stupid waste!
00151     bm->nextl++;
00152     bm->totloop++;
00153     
00154     if(example)
00155         CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, example->data, &l->data);
00156     else
00157         CustomData_bmesh_set_default(&bm->ldata, &l->data);
00158 
00159     return l;
00160 }
00161 
00162 BME_Poly *BME_addpolylist(BME_Mesh *bm, BME_Poly *example){
00163     BME_Poly *f = NULL;
00164     f = BLI_mempool_alloc(bm->ppool);
00165     f->next = f->prev = NULL;
00166     f->EID = bm->nextp;
00167     f->loopbase = NULL;
00168     f->len = 0;
00169     f->data = NULL;
00170     f->eflag1 = f->eflag2 = f->tflag1 = f->tflag2 = 0;
00171     f->flag = f->h = f->mat_nr;
00172     BLI_addtail(&(bm->polys),f);
00173     bm->nextp++;
00174     bm->totpoly++;
00175 
00176     if(example)
00177         CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data);
00178     else
00179         CustomData_bmesh_set_default(&bm->pdata, &f->data);
00180 
00181 
00182     return f;
00183 }
00184 
00185 /*  free functions dont do much *yet*. When per-vertex, per-edge and per-face/faceloop
00186     data is added though these will be needed.
00187 */
00188 void BME_free_vert(BME_Mesh *bm, BME_Vert *v){
00189     bm->totvert--;
00190     CustomData_bmesh_free_block(&bm->vdata, &v->data);
00191     BLI_mempool_free(bm->vpool, v);
00192 }
00193 void BME_free_edge(BME_Mesh *bm, BME_Edge *e){
00194     bm->totedge--;
00195     CustomData_bmesh_free_block(&bm->edata, &e->data);
00196     BLI_mempool_free(bm->epool, e);
00197 }
00198 void BME_free_poly(BME_Mesh *bm, BME_Poly *f){
00199     bm->totpoly--;
00200     CustomData_bmesh_free_block(&bm->pdata, &f->data);
00201     BLI_mempool_free(bm->ppool, f);
00202 }
00203 void BME_free_loop(BME_Mesh *bm, BME_Loop *l){
00204     bm->totloop--;
00205     CustomData_bmesh_free_block(&bm->ldata, &l->data);
00206     BLI_mempool_free(bm->lpool, l);
00207 }
00281 void BME_cycle_append(void *h, void *nt)
00282 {
00283     BME_CycleNode *oldtail, *head, *newtail;
00284     
00285     head = (BME_CycleNode*)h;
00286     newtail = (BME_CycleNode*)nt;
00287     
00288     if(head->next == NULL){
00289         head->next = newtail;
00290         head->prev = newtail;
00291         newtail->next = head;
00292         newtail->prev = head;
00293     }
00294     else{
00295         oldtail = head->prev;
00296         oldtail->next = newtail;
00297         newtail->next = head;
00298         newtail->prev = oldtail;
00299         head->prev = newtail;
00300         
00301     }
00302 }
00303 
00313 int BME_cycle_length(void *h){
00314     
00315     int len = 0;
00316     BME_CycleNode *head, *curnode;
00317     head = (BME_CycleNode*)h;
00318     
00319     if(head){ 
00320         len = 1;
00321         for(curnode = head->next; curnode != head; curnode=curnode->next){ 
00322             if(len == INT_MAX){ //check for infinite loop/corrupted cycle
00323                     return -1;
00324             }
00325             len++;
00326         }
00327     }
00328     return len;
00329 }
00330 
00331 
00341 int BME_cycle_remove(void *h, void *remn)
00342 {
00343     int i, len;
00344     BME_CycleNode *head, *remnode, *curnode;
00345     
00346     head = (BME_CycleNode*)h;
00347     remnode = (BME_CycleNode*)remn;
00348     len = BME_cycle_length(h);
00349     
00350     if(len == 1 && head == remnode){
00351         head->next = NULL;
00352         head->prev = NULL;
00353         return 1;
00354     }
00355     else{
00356         for(i=0, curnode = head; i < len; curnode = curnode->next){
00357             if(curnode == remnode){
00358                 remnode->prev->next = remnode->next;
00359                 remnode->next->prev = remnode->prev;
00360                 /*zero out remnode pointers, important!*/
00361                 //remnode->next = NULL;
00362                 //remnode->prev = NULL;
00363                 return 1;
00364         
00365             }
00366         }
00367     }
00368     return 0;
00369 }
00370 
00382 int BME_cycle_validate(int len, void *h){
00383     int i;
00384     BME_CycleNode *curnode, *head;
00385     head = (BME_CycleNode*)h;
00386     
00387     /*forward validation*/
00388     for(i = 0, curnode = head; i < len; i++, curnode = curnode->next);
00389     if(curnode != head) return 0;
00390     
00391     /*reverse validation*/
00392     for(i = 0, curnode = head; i < len; i++, curnode = curnode->prev);
00393     if(curnode != head) return 0;
00394     
00395     return 1;
00396 }
00397 
00398 /*Begin Disk Cycle routines*/
00399 
00409 BME_Edge *BME_disk_nextedge(BME_Edge *e, BME_Vert *v)
00410 {   
00411     if(BME_vert_in_edge(e, v)){
00412         if(e->v1 == v) return e->d1.next->data;
00413         else if(e->v2 == v) return e->d2.next->data;
00414     }
00415     return NULL;
00416 }
00417 
00426 BME_CycleNode *BME_disk_getpointer(BME_Edge *e, BME_Vert *v){
00427     /*returns pointer to the cycle node for the appropriate vertex in this disk*/
00428     if(e->v1 == v) return &(e->d1);
00429     else if (e->v2 == v) return &(e->d2);
00430     return NULL;
00431 }
00432 
00442 int BME_disk_append_edge(BME_Edge *e, BME_Vert *v)
00443 { 
00444     
00445     BME_CycleNode *base, *tail;
00446     
00447     if(BME_vert_in_edge(e, v) == 0) return 0; /*check to make sure v is in e*/
00448     
00449     /*check for loose vert first*/
00450     if(v->edge == NULL){
00451         v->edge = e;
00452         base = tail = BME_disk_getpointer(e, v);
00453         BME_cycle_append(base, tail); /*circular reference is ok!*/
00454         return 1;
00455     }
00456     
00457     /*insert e at the end of disk cycle and make it the new v->edge*/
00458     base = BME_disk_getpointer(v->edge, v);
00459     tail = BME_disk_getpointer(e, v);
00460     BME_cycle_append(base, tail);
00461     return 1;
00462 }
00463 
00475 void BME_disk_remove_edge(BME_Edge *e, BME_Vert *v)
00476 {
00477     BME_CycleNode *base, *remnode;
00478     BME_Edge *newbase;
00479     int len;
00480     
00481     base = BME_disk_getpointer(v->edge, v);
00482     remnode = BME_disk_getpointer(e, v);
00483     
00484     /*first deal with v->edge pointer...*/
00485     len = BME_cycle_length(base);
00486     if(len == 1) newbase = NULL;
00487     else if(v->edge == e) newbase = base->next-> data;
00488     else newbase = v->edge;
00489     
00490     /*remove and rebase*/
00491     BME_cycle_remove(base, remnode);
00492     v->edge = newbase;
00493 }
00494 
00504 BME_Edge *BME_disk_next_edgeflag(BME_Edge *e, BME_Vert *v, int eflag, int tflag){
00505     
00506     /* BME_CycleNode *diskbase; */ /* UNUSED */
00507     BME_Edge *curedge;
00508     int /* len, */ /* UNUSED */ ok;
00509     
00510     if(eflag && tflag) return NULL;
00511     
00512     ok = BME_vert_in_edge(e,v);
00513     if(ok){
00514         /* diskbase = BME_disk_getpointer(e, v); */ /* UNUSED */
00515         /* len = BME_cycle_length(diskbase); */ /* UNUSED */
00516         curedge = BME_disk_nextedge(e,v);
00517         while(curedge != e){
00518             if(tflag){
00519                 if(curedge->tflag1 == tflag) return curedge;
00520             }
00521             else if(eflag){
00522                 if(curedge->eflag1 == eflag) return curedge;
00523             }
00524             curedge = BME_disk_nextedge(curedge, v);
00525         }
00526     }
00527     return NULL;
00528 }
00529 
00540 int BME_disk_count_edgeflag(BME_Vert *v, int eflag, int tflag){
00541     BME_CycleNode *diskbase;
00542     BME_Edge *curedge;
00543     int i, len=0, count=0;
00544     
00545     if(v->edge){
00546         if(eflag && tflag) return 0; /*tflag and eflag are reserved for different functions!*/
00547         diskbase = BME_disk_getpointer(v->edge, v);
00548         len = BME_cycle_length(diskbase);
00549         
00550         for(i = 0, curedge=v->edge; i<len; i++){
00551             if(tflag){
00552                 if(curedge->tflag1 == tflag) count++;
00553             }
00554             else if(eflag){
00555                 if(curedge->eflag1 == eflag) count++;
00556             }
00557             curedge = BME_disk_nextedge(curedge, v);
00558         }
00559     }
00560     return count;
00561 }
00562 
00563 int BME_disk_hasedge(BME_Vert *v, BME_Edge *e){
00564     BME_CycleNode *diskbase;
00565     BME_Edge *curedge;
00566     int i, len=0;
00567     
00568     if(v->edge){
00569         diskbase = BME_disk_getpointer(v->edge,v);
00570         len = BME_cycle_length(diskbase);
00571         
00572         for(i = 0, curedge=v->edge; i<len; i++){
00573             if(curedge == e) return 1;
00574             else curedge=BME_disk_nextedge(curedge, v);
00575         }
00576     }
00577     return 0;
00578 }
00579 /*end disk cycle routines*/
00580 
00581 BME_Loop *BME_radial_nextloop(BME_Loop *l){
00582     return (BME_Loop*)(l->radial.next->data);
00583 }
00584 
00585 void BME_radial_append(BME_Edge *e, BME_Loop *l){
00586     if(e->loop == NULL) e->loop = l;
00587     BME_cycle_append(&(e->loop->radial), &(l->radial));
00588 }
00589 
00590 void BME_radial_remove_loop(BME_Loop *l, BME_Edge *e)
00591 {
00592     BME_Loop *newbase;
00593     int len;
00594     
00595     /*deal with edge->loop pointer*/
00596     len = BME_cycle_length(&(e->loop->radial));
00597     if(len == 1) newbase = NULL;
00598     else if(e->loop == l) newbase = e->loop->radial.next->data;
00599     else newbase = e->loop;
00600     
00601     /*remove and rebase*/
00602     BME_cycle_remove(&(e->loop->radial), &(l->radial));
00603     e->loop = newbase;
00604 }
00605 
00606 int BME_radial_find_face(BME_Edge *e,BME_Poly *f)
00607 {
00608         
00609     BME_Loop *curloop;
00610     int i, len;
00611     
00612     len = BME_cycle_length(&(e->loop->radial));
00613     for(i = 0, curloop = e->loop; i < len; i++, curloop = curloop->radial.next->data){
00614         if(curloop->f == f) return 1;
00615     }
00616     return 0;
00617 }
00618 
00619 struct BME_Loop *BME_loop_find_loop(struct BME_Poly *f, struct BME_Vert *v) {
00620     BME_Loop *l;
00621     int i, len;
00622     
00623     len = BME_cycle_length(f->loopbase);
00624     for (i = 0, l=f->loopbase; i < len; i++, l=l->next) {
00625         if (l->v == v) return l;
00626     }
00627     return NULL;
00628 }