BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){ BME_Vert *nv, *ov; BME_CycleNode *diskbase; BME_Edge *ne; int i, edok, valance1=0, valance2=0; if(BME_vert_in_edge(e,tv) == 0) return NULL; ov = BME_edge_getothervert(e,tv); //v2 = tv; /*count valance of v1*/ diskbase = BME_disk_getpointer(e, ov); valance1 = BME_cycle_length(diskbase); /*count valance of v2*/ diskbase = BME_disk_getpointer(e, tv); valance2 = BME_cycle_length(diskbase); nv = BME_addvertlist(bm, tv); ne = BME_addedgelist(bm, nv, tv, e); //e->v2 = nv; /*remove e from v2's disk cycle*/ BME_disk_remove_edge(e, tv); /*swap out tv for nv in e*/ BME_edge_swapverts(e, tv, nv); /*add e to nv's disk cycle*/ BME_disk_append_edge(e, nv); /*add ne to nv's disk cycle*/ BME_disk_append_edge(ne, nv); /*add ne to tv's disk cycle*/ BME_disk_append_edge(ne, tv); /*verify disk cycles*/ diskbase = BME_disk_getpointer(ov->edge,ov); edok = BME_cycle_validate(valance1, diskbase); if(!edok) BME_error(); diskbase = BME_disk_getpointer(tv->edge,tv); edok = BME_cycle_validate(valance2, diskbase); if(!edok) BME_error(); diskbase = BME_disk_getpointer(nv->edge,nv); edok = BME_cycle_validate(2, diskbase); if(!edok) BME_error(); /*Split the radial cycle if present*/ if(e->loop){ BME_Loop *nl,*l; BME_CycleNode *radEBase=NULL, *radNEBase=NULL; int radlen = BME_cycle_length(&(e->loop->radial)); /*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/ while(e->loop){ l=e->loop; l->f->len++; BME_radial_remove_loop(l,e); nl = BME_create_loop(bm,NULL,NULL,l->f,l); nl->prev = l; nl->next = l->next; nl->prev->next = nl; nl->next->prev = nl; nl->v = nv; /*assign the correct edge to the correct loop*/ if(BME_verts_in_edge(nl->v, nl->next->v, e)){ nl->e = e; l->e = ne; /*append l into ne's rad cycle*/ if(!radNEBase){ radNEBase = &(l->radial); radNEBase->next = NULL; radNEBase->prev = NULL; } if(!radEBase){ radEBase = &(nl->radial); radEBase->next = NULL; radEBase->prev = NULL; } BME_cycle_append(radEBase,&(nl->radial)); BME_cycle_append(radNEBase,&(l->radial)); } else if(BME_verts_in_edge(nl->v,nl->next->v,ne)){ nl->e = ne; l->e = e; if(!radNEBase){ radNEBase = &(nl->radial); radNEBase->next = NULL; radNEBase->prev = NULL; } if(!radEBase){ radEBase = &(l->radial); radEBase->next = NULL; radEBase->prev = NULL; } BME_cycle_append(radEBase,&(l->radial)); BME_cycle_append(radNEBase,&(nl->radial)); } } e->loop = radEBase->data; ne->loop = radNEBase->data; /*verify length of radial cycle*/ edok = BME_cycle_validate(radlen,&(e->loop->radial)); if(!edok) BME_error(); edok = BME_cycle_validate(radlen,&(ne->loop->radial)); if(!edok) BME_error(); /*verify loop->v and loop->next->v pointers for e*/ for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){ if(!(l->e == e)) BME_error(); if(!(l->radial.data == l)) BME_error(); if(l->prev->e != ne && l->next->e != ne) BME_error(); edok = BME_verts_in_edge(l->v, l->next->v, e); if(!edok) BME_error(); if(l->v == l->next->v) BME_error(); if(l->e == l->next->e) BME_error(); /*verify loop cycle for kloop->f*/ edok = BME_cycle_validate(l->f->len, l->f->loopbase); if(!edok) BME_error(); } /*verify loop->v and loop->next->v pointers for ne*/ for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){ if(!(l->e == ne)) BME_error(); if(!(l->radial.data == l)) BME_error(); if(l->prev->e != e && l->next->e != e) BME_error(); edok = BME_verts_in_edge(l->v, l->next->v, ne); if(!edok) BME_error(); if(l->v == l->next->v) BME_error(); if(l->e == l->next->e) BME_error(); /*verify loop cycle for kloop->f. Redundant*/ edok = BME_cycle_validate(l->f->len, l->f->loopbase); if(!edok) BME_error(); } } if(re) *re = ne; return nv; }
/** * BME_JEKV * * JOIN EDGE KILL VERT: * Takes a an edge and pointer to one of its vertices and collapses * the edge on that vertex. * * Before: OE KE * ------- ------- * | || | * OV KV TV * * * After: OE * --------------- * | | * OV TV * * * Restrictions: * KV is a vertex that must have a valance of exactly two. Furthermore * both edges in KV's disk cycle (OE and KE) must be unique (no double * edges). * * It should also be noted that this euler has the possibility of creating * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. * * Returns - * 1 for success, 0 for failure. */ int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv) { BME_Edge *oe; BME_Vert *ov, *tv; BME_CycleNode *diskbase; BME_Loop *killoop,*nextl; int len,radlen=0, halt = 0, i, valance1, valance2,edok; if(BME_vert_in_edge(ke,kv) == 0) return 0; diskbase = BME_disk_getpointer(kv->edge, kv); len = BME_cycle_length(diskbase); if(len == 2){ oe = BME_disk_nextedge(ke, kv); tv = BME_edge_getothervert(ke, kv); ov = BME_edge_getothervert(oe, kv); halt = BME_verts_in_edge(kv, tv, oe); //check for double edges if(halt) return 0; else{ /*For verification later, count valance of ov and tv*/ diskbase = BME_disk_getpointer(ov->edge, ov); valance1 = BME_cycle_length(diskbase); diskbase = BME_disk_getpointer(tv->edge, tv); valance2 = BME_cycle_length(diskbase); /*remove oe from kv's disk cycle*/ BME_disk_remove_edge(oe,kv); /*relink oe->kv to be oe->tv*/ BME_edge_swapverts(oe, kv, tv); /*append oe to tv's disk cycle*/ BME_disk_append_edge(oe, tv); /*remove ke from tv's disk cycle*/ BME_disk_remove_edge(ke, tv); /*deal with radial cycle of ke*/ if(ke->loop){ /*first step, fix the neighboring loops of all loops in ke's radial cycle*/ radlen = BME_cycle_length(&(ke->loop->radial)); for(i=0,killoop = ke->loop; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){ /*relink loops and fix vertex pointer*/ killoop->next->prev = killoop->prev; killoop->prev->next = killoop->next; if(killoop->next->v == kv) killoop->next->v = tv; /*fix len attribute of face*/ killoop->f->len--; if(killoop->f->loopbase == killoop) killoop->f->loopbase = killoop->next; } /*second step, remove all the hanging loops attached to ke*/ killoop = ke->loop; radlen = BME_cycle_length(&(ke->loop->radial)); /*make sure we have enough room in bm->lpar*/ if(bm->lparlen < radlen){ MEM_freeN(bm->lpar); bm->lpar = MEM_callocN(sizeof(BME_Loop *)* radlen, "BMesh Loop pointer array"); bm->lparlen = bm->lparlen * radlen; } /*this should be wrapped into a bme_free_radial function to be used by BME_KF as well...*/ i=0; while(i<radlen){ bm->lpar[i] = killoop; killoop = killoop->radial.next->data; i++; } i=0; while(i<radlen){ BME_free_loop(bm,bm->lpar[i]); i++; } /*Validate radial cycle of oe*/ edok = BME_cycle_validate(radlen,&(oe->loop->radial)); } /*Validate disk cycles*/ diskbase = BME_disk_getpointer(ov->edge,ov); edok = BME_cycle_validate(valance1, diskbase); if(!edok) BME_error(); diskbase = BME_disk_getpointer(tv->edge,tv); edok = BME_cycle_validate(valance2, diskbase); if(!edok) BME_error(); /*Validate loop cycle of all faces attached to oe*/ for(i=0,nextl = oe->loop; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){ edok = BME_cycle_validate(nextl->f->len,nextl->f->loopbase); if(!edok) BME_error(); } /*deallocate edge*/ BLI_remlink(&(bm->edges), ke); BME_free_edge(bm, ke); /*deallocate vertex*/ BLI_remlink(&(bm->verts), kv); BME_free_vert(bm, kv); return 1; } } return 0; }
int BME_validate_mesh(struct BME_Mesh *bm, int halt) { BME_Vert *v; BME_Edge *e; BME_Poly *f; BME_Loop *l; BME_CycleNode *diskbase; int i, ok; /*Simple edge verification*/ for(e=bm->edges.first; e; e=e->next){ if(e->v1 == e->v2) VHALT(halt); /*validate e->d1.data and e->d2.data*/ if(e->d1.data != e || e->d2.data != e) VHALT(halt); /*validate e->loop->e*/ if(e->loop){ if(e->loop->e != e) VHALT(halt); } } /*calculate disk cycle lengths*/ for(v=bm->verts.first; v; v=v->next) v->tflag1 = v->tflag2 = 0; for(e=bm->edges.first; e; e=e->next){ e->v1->tflag1++; e->v2->tflag1++; } /*Validate vertices and disk cycle*/ for(v=bm->verts.first; v; v=v->next){ /*validate v->edge pointer*/ if(v->tflag1){ if(v->edge){ ok = BME_vert_in_edge(v->edge,v); if(!ok) VHALT(halt); /*validate length of disk cycle*/ diskbase = BME_disk_getpointer(v->edge, v); ok = BME_cycle_validate(v->tflag1, diskbase); if(!ok) VHALT(halt); /*validate that each edge in disk cycle contains V*/ for(i=0, e=v->edge; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){ ok = BME_vert_in_edge(e, v); if(!ok) VHALT(halt); } } else VHALT(halt); } } /*validate edges*/ for(e=bm->edges.first; e; e=e->next){ /*seperate these into BME_disk_hasedge (takes pointer to edge)*/ /*search v1 disk cycle for edge*/ ok = BME_disk_hasedge(e->v1,e); if(!ok) VHALT(halt); /*search v2 disk cycle for edge*/ ok = BME_disk_hasedge(e->v2,e); if(!ok) VHALT(halt); } for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces /*Validate the loop cycle integrity.*/ for(f=bm->polys.first; f; f=f->next){ ok = BME_cycle_length(f->loopbase); if(ok > 1){ f->tflag1 = ok; } else VHALT(halt); for(i=0, l=f->loopbase; i < f->tflag1; i++, l=l->next){ /*verify loop->v pointers*/ ok = BME_verts_in_edge(l->v, l->next->v, l->e); if(!ok) VHALT(halt); /*verify radial node data pointer*/ if(l->radial.data != l) VHALT(halt); /*validate l->e->loop poitner*/ if(l->e->loop == NULL) VHALT(halt); /*validate l->f pointer*/ if(l->f != f) VHALT(halt); /*see if l->e->loop is actually in radial cycle*/ l->e->tflag2++; } } /*validate length of radial cycle*/ for(e=bm->edges.first; e; e=e->next){ if(e->loop){ ok = BME_cycle_validate(e->tflag2,&(e->loop->radial)); if(!ok) VHALT(halt); } } /*validate that EIDs are within range... if not indicates corrupted mem*/ /*if we get this far, pretty safe to return 1*/ return 1; }