1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
// cut.cmd
// Cut multiply connected surface into simply connected surface.
// Algorithm: Grow simply connected region, adding triangles, and
// zipping up seams.
/* Usage: cut
Leaves the cut edges with ecutmark = 1
*/
// Programmer: Ken Brakke, brakke@susqu.edu www.susqu.edu/brakke
define edge attribute ecutmark integer;
/* 0 for not a cut, 1 for possible cut, 2 for valence 1 edge */
define facet attribute fcutmark integer;
// G
cut_groom := {
// smooth out sawteeth by moving cut on two sides of a facet
// to one side, if vertex involved only has two cut edges.
local changes;
do
{ changes := 0;
foreach facet ff where sum(ff.edge,ecutmark==1)==2 do
{ foreach ff.vertex vv where
sum(vv.edge ee,ecutmark==1) == 2 and
sum(vv.edge ee where sum(ee.facet,id==ff.id),ecutmark==1)==2 do
{
set ff.edge ecutmark (1-ecutmark) where ecutmark!=2;
changes++;
break;
}
}
} while changes;
recalc;
}
cut := {
local changes,endcrit;
if max(edge, valence) > 2 then
{ errprintf "ERROR: 'cut' requires maximum edge valence 2.\n";
abort;
};
set edge ecutmark (3-valence); // all start as cuts
set facet fcutmark 0;
foreach facet ff do { ff.fcutmark := 1; break; };
// grow connected region
do
{ changes := 0;
foreach edge ee where ee.ecutmark == 1 do
{ if sum(ee.facet,fcutmark)==1 then
{ set ee.facet fcutmark 1;
ee.ecutmark := 0;
changes++;
};
if sum(ee.facet,fcutmark)==2 then
{ // see if can sew up
endcrit := min(ee.vertex vv, sum(vv.edge eee,eee ecutmark)==1);
if endcrit == 1 then
{ ee.ecutmark := 0;
changes++;
}
};
};
} while changes;
set edge ecutmark 0 where ecutmark == 2; // unmark valence 1 edges
cut_groom;
}
// End cut.cmd
// Usage: cut
|