2 New tools, 'Loop to region' and 'Region to loop'

-> Loop to Region
Examines the current set of selected edges and seperates them into groups
 of 'loops' that each bisect the mesh into two parts. Then for each loop it
selects the smaller 'half' of the mesh.

Example images:
http://www.umsl.edu/~gcbq44/looptoregion2a.jpg
http://www.umsl.edu/~gcbq44/looptoregion2b.jpg

This tool handles multiple loops fine as is shown by these images:
http://www.umsl.edu/~gcbq44/looptoregion1a.jpg
http://www.umsl.edu/~gcbq44/looptoregion1b.jpg

Furthermore it handles 'holes' just fine as well:
http://www.umsl.edu/~gcbq44/looptoregion3a.jpg
http://www.umsl.edu/~gcbq44/looptoregion3b.jpg

-> Region to Loop

This is the 'logical inverse' of loop to region.

Example:
http://www.umsl.edu/~gcbq44/regiontoloop1a.jpg
http://www.umsl.edu/~gcbq44/regiontoloop1b.jpg

Both features can be accessed by the 'Edge Menu' in EditMode (CTRL-E).
This commit is contained in:
Geoffrey Bantle 2006-03-15 20:53:41 +00:00
parent e2660f614d
commit e4439dd050
3 changed files with 193 additions and 4 deletions

@ -209,6 +209,7 @@ int merge_firstlast(int first, int uvmerge);
int merge_target( int target, int uvmerge); int merge_target( int target, int uvmerge);
void pathselect(void); void pathselect(void);
void loop_to_region(void);
void region_to_loop(void);
#endif #endif

@ -2060,7 +2060,7 @@ void editmesh_mark_seam(int clear)
void Edge_Menu() { void Edge_Menu() {
short ret; short ret;
ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8"); ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8|Loop to Region%x9|Region to Loop%x10");
switch(ret) switch(ret)
{ {
@ -2090,6 +2090,12 @@ void Edge_Menu() {
case 8: case 8:
loop_multiselect(1); loop_multiselect(1);
break; break;
case 9:
loop_to_region();
break;
case 10:
region_to_loop();
break;
} }
} }

@ -6242,9 +6242,8 @@ void pathselect(void)
MEM_freeN(cost); MEM_freeN(cost);
MEM_freeN(previous); MEM_freeN(previous);
BLI_heap_free(heap, NULL); BLI_heap_free(heap, NULL);
EM_select_flush(); EM_select_flush();
countall();
} }
} }
else{ else{
@ -6252,3 +6251,186 @@ void pathselect(void)
return; return;
} }
} }
void region_to_loop(void)
{
EditEdge *eed;
EditFace *efa;
if(G.totfacesel){
for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
if(efa->f&SELECT){
efa->e1->f1++;
efa->e2->f1++;
efa->e3->f1++;
if(efa->e4)
efa->e4->f1++;
}
}
EM_clear_flag_all(SELECT);
for(eed=G.editMesh->edges.first; eed; eed=eed->next){
if(eed->f1 == 1) EM_select_edge(eed, 1);
}
G.scene->selectmode = SCE_SELECT_EDGE;
EM_selectmode_set();
countall();
BIF_undo_push("Face Region to Edge Loop");
}
}
static int validate_loop(Collection *edgecollection)
{
EditEdge *eed;
EditFace *efa;
CollectedEdge *curredge;
/*1st test*/
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
curredge->eed->v1->f1 = 0;
curredge->eed->v2->f1 = 0;
}
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
curredge->eed->v1->f1++;
curredge->eed->v2->f1++;
}
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
if(curredge->eed->v1->f1 > 2) return(0); else
if(curredge->eed->v2->f1 > 2) return(0);
}
/*2nd test*/
for(eed = G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0;
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
efa->e1->f1++;
efa->e2->f1++;
efa->e3->f1++;
if(efa->e4) efa->e4->f1++;
}
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next){
if(curredge->eed->f1 > 2) return(0);
}
return(1);
}
static int loop_bisect(Collection *edgecollection){
EditFace *efa, *sf1, *sf2;
EditEdge *eed, *sed;
CollectedEdge *curredge;
int totsf1, totsf2, unbalanced,balancededges;
for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = eed->f2 = 0;
for(efa=G.editMesh->faces.first; efa; efa=efa->next) efa->f1 = 0;
for(curredge = (CollectedEdge*)edgecollection->collectionbase.first; curredge; curredge=curredge->next) curredge->eed->f1 = 1;
sf1 = sf2 = NULL;
sed = ((CollectedEdge*)edgecollection->collectionbase.first)->eed;
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
if(sf2) break;
else if(sf1){
if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf2 = efa;
}
else{
if(efa->e1 == sed || efa->e2 == sed || efa->e3 == sed || ( (efa->e4) ? efa->e4 == sed : 0) ) sf1 = efa;
}
}
if(!(sf1->e1->f1)) sf1->e1->f2 = 1;
if(!(sf1->e2->f1)) sf1->e2->f2 = 1;
if(!(sf1->e3->f1)) sf1->e3->f2 = 1;
if(sf1->e4 && !(sf1->e4->f1)) sf1->e4->f2 = 1;
sf1->f1 = 1;
totsf1 = 1;
if(!(sf2->e1->f1)) sf2->e1->f2 = 2;
if(!(sf2->e2->f1)) sf2->e2->f2 = 2;
if(!(sf2->e3->f1)) sf2->e3->f2 = 2;
if(sf2->e4 && !(sf2->e4->f1)) sf2->e4->f2 = 2;
sf2->f1 = 2;
totsf2 = 1;
/*do sf1*/
unbalanced = 1;
while(unbalanced){
unbalanced = 0;
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
balancededges = 0;
if(efa->f1 == 0){
if(efa->e1->f2 == 1 || efa->e2->f2 == 1 || efa->e3->f2 == 1 || ( (efa->e4) ? efa->e4->f2 == 1 : 0) ){
balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 1;
balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 1;
balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 1;
if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 1;
if(balancededges){
unbalanced = 1;
efa->f1 = 1;
totsf1++;
}
}
}
}
}
/*do sf2*/
unbalanced = 1;
while(unbalanced){
unbalanced = 0;
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
balancededges = 0;
if(efa->f1 == 0){
if(efa->e1->f2 == 2 || efa->e2->f2 == 2 || efa->e3->f2 == 2 || ( (efa->e4) ? efa->e4->f2 == 2 : 0) ){
balancededges += efa->e1->f2 = (efa->e1->f1) ? 0 : 2;
balancededges += efa->e2->f2 = (efa->e2->f1) ? 0 : 2;
balancededges += efa->e3->f2 = (efa->e3->f1) ? 0 : 2;
if(efa->e4) balancededges += efa->e4->f2 = (efa->e4->f1) ? 0 : 2;
if(balancededges){
unbalanced = 1;
efa->f1 = 2;
totsf2++;
}
}
}
}
}
if(totsf1 < totsf2) return(1);
else return(2);
}
void loop_to_region(void)
{
EditFace *efa;
ListBase allcollections={NULL,NULL};
Collection *edgecollection;
int testflag;
build_edgecollection(&allcollections);
for(edgecollection = (Collection *)allcollections.first; edgecollection; edgecollection=edgecollection->next){
if(validate_loop(edgecollection)){
testflag = loop_bisect(edgecollection);
for(efa=G.editMesh->faces.first; efa; efa=efa->next){
if(efa->f1 == testflag){
if(efa->f&SELECT) EM_select_face(efa, 0);
else EM_select_face(efa,1);
}
}
}
}
for(efa=G.editMesh->faces.first; efa; efa=efa->next){ /*fix this*/
if(efa->f&SELECT) EM_select_face(efa,1);
}
countall();
freecollections(&allcollections);
BIF_undo_push("Edge Loop to Face Region");
}