Пример #1
0
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;
}
Пример #2
0
/**
 *			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;
}
Пример #3
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;
}