Blender  V2.59
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  * $Id: BME_structure.c 35247 2011-02-27 20:40:57Z jesterking $
00007  *
00008  * ***** BEGIN GPL LICENSE BLOCK *****
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU General Public License
00012  * as published by the Free Software Foundation; either version 2
00013  * of the License, or (at your option) any later version.
00014  * about this.  
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00024  *
00025  * The Original Code is Copyright (C) 2007 Blender Foundation.
00026  * All rights reserved.
00027  *
00028  * The Original Code is: all of this file.
00029  *
00030  * Contributor(s): Geoffrey Bantle.
00031  *
00032  * ***** END GPL LICENSE BLOCK *****
00033  */
00034 
00040 #include <limits.h>
00041 
00042 #include "MEM_guardedalloc.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;
00507         BME_Edge *curedge;
00508         int len, 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);
00515                 len = BME_cycle_length(diskbase);
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 }