%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% phiCAD2NC %%% %%% Recursive Workpiece Classification %%% %%% Michael Sintek First Version: August 1991 %%% %%% Harold Boley, Markus Perling Current Version: June 1997 %%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % The program mainly uses RELFUN functions defined by functional clauses % which are all deterministic % classify wp % ----------- class-feat(Wp-rng) :- % Wp-rng must be in rng notation Rad .= max-rad(Wp-rng), Class-feat .= class-sec(Rad,Wp-rng) & cwp[Rad,Class-feat]. % classify section class-sec(,) % ------------------------------------------ % end with [] or [X] class-sec(Max,[]) :& []. class-sec(Max,[X]) :& % X thrown out because a single supporting []. % point cannot become a feature % ignore max height cylinders class-sec(Max,[rng[Z1,Ri,Max],rng[Z2,Max,Ro]|Rest]) :& class-sec(Max,[rng[Z2,Max,Ro]|Rest]). % groove: begins with max and split-wp-rng succeeds class-sec(Max,[rng[Z,Max,Ro]|Rest]) :- [Left-wp-rng|Rest-wp-rng] % check for and return part .= split-wp-rng(Max,Rest) & % up to maximum %(rf-print groove) %(rf-print `(tup (rng _z _max _ro) | _rest)) %(rf-print `(tup (rng _z _max _ro) | _left-wp-rng)) tup(class-grv([rng[Z,Max,Ro]|Left-wp-rng])| class-sec(Max,Rest-wp-rng)). % right shoulder: doesn't start with max and split-wp-rng succeeds class-sec(Max,[rng[Z,Ri,Ro]|Rest]) :- /=(Ri,Max), [Left-wp-rng|Rest-wp-rng] .= split-wp-rng(Max,[rng[Z,Ri,Ro]|Rest]) & %(rf-print right-shoulder) %(rf-print `(tup (rng _z _max _ro) | _rest)) %(rf-print _left-wp-rng) tup(class-rsh(Left-wp-rng)|class-sec(Max,Rest-wp-rng)). % left shoulder: no more maxima class-sec(Max,Wp-rng) :& %(rf-print left-shoulder) %(rf-print _wp-rng) tup(class-lsh(Wp-rng)). % classify groove % --------------- class-grv(Wp-rng) :- [Test-flank1|Rest-wp1] .= find-flank(Wp-rng,0), [Test-flank2|Rest-wp2] .= find-flank(reverse-wp-rng(Rest-wp1),0), rng[Tz,Tri,Test-flank1-min] .= rf-last(Test-flank1), Ground-max .= max(Test-flank1-min,max-rad(Rest-wp2)), [L-flank|Rest] .= find-flank(Wp-rng,Ground-max), [R-flank|Ground] .= find-flank(reverse-wp-rng(Rest),Ground-max), class-grd(reverse-wp-rng(Ground),Ground-max,Grd,Refined-ground), R-flank-rev .= reverse-wp-rng(R-flank) & nft[grv[flk[L-flank],Grd,flk[R-flank-rev]],Refined-ground]. % classify left shoulder % ---------------------- class-lsh(Wp-rng) :- [Test-flank|Rest-wp] .= find-flank(Wp-rng,0), rng[Tz,Tri,Test-flank-min] .= rf-last(Test-flank), Ground-max .= max(Test-flank-min,max-rad(Rest-wp)), [Flank|Ground] .= find-flank(Wp-rng,Ground-max), class-grd(Ground,Ground-max,Grd,Refined-ground) & nft[lsh[flk[Flank],Grd],Refined-ground]. % classify right shoulder % ----------------------- class-rsh(Wp-rng) :& reverse-feature(class-lsh(reverse-wp-rng(Wp-rng))). % classify ground % --------------- class-grd([],Ground-max,grd[[]],[]). class-grd([X],Ground-max,grd[[]],[]). class-grd(Ground, Ground-max, grd[[rng[Fz,Ground-max,Ground-max],rng[Lz,Ground-max,Ground-max]]], Refined-ground) :- Refined-ground .= class-sec(Ground-max,Ground), [rng[Fz,Fri,Fro]|Rest-ground] .= Ground, rng[Lz,Lri,Lro] .= rf-last(Ground). % find flank find-flank(,) % ------------------------------------- % (a) asc. ring find-flank([rng[Z,Ri,Ro]|Rest],Min) :- %(rf-print a) >(Ro,Ri) & [[rng[Z,Ri,Ri]]|[rng[Z,Ro,Ro]|Rest]]. % (b) desc. ring passing or downto min find-flank([rng[Z,Ri,Ro]|Rest],Min) :- %(rf-print b) >=(Min,Ro) & [[rng[Z,Ri,Min]]|[rng[Z,Min,Ro]|Rest]]. % (c) desc. last ring above min find-flank([rng[Z,Ri,Ro]],Min) :& %(rf-print c) % >=(Ri,Ro), >(Ro,Min) holds [[rng[Z,Ri,Ro]]|[]]. % (d) asc. truncone find-flank([rng[Z1,Ri1,Ro1],rng[Z2,Ri2,Ro2]|Rest],Min) :- %(rf-print d) >(Ri2,Ro1) & % >=(Ri1,Ro1), >(Ro1,Min) holds [[rng[Z1,Ri1,Ro1]]|[rng[Z1,Ro1,Ro1],rng[Z2,Ri2,Ro2]|Rest]]. % (e1) desc. truncone downto min find-flank([rng[Z1,Ri1,Ro1],rng[Z2,Ri2,Ro2]|Rest],Min) :- %(rf-print e1) =(Min,Ri2) & % >=(Ri1,Ro1), >(Ro1,Min) holds [[rng[Z1,Ri1,Ro1],rng[Z2,Min,Min]]|[rng[Z2,Ri2,Ro2]|Rest]]. % (e2) desc. truncone passing min find-flank([rng[Z1,Ri1,Ro1],rng[Z2,Ri2,Ro2]|Rest],Min) :- %(rf-print e2) >(Min,Ri2), % >=(Ri1,Ro1), >(Ro1,Min) holds Z12 .= split-truncone(Z1,Ro1,Z2,Ri2,Min) & [[rng[Z1,Ri1,Ro1],rng[Z12,Min,Min]]| [rng[Z12,Min,Min],rng[Z2,Ri2,Ro2]|Rest]]. % (f) cylinder or desc. truncone above min find-flank([rng[Z1,Ri1,Ro1],rng[Z2,Ri2,Ro2]|Rest],Min) :- %(rf-print f) % fall through case: >=(Ri1,Ro1,Ri2) holds [Rest-flank|Rest-wp] .= find-flank([rng[Z2,Ri2,Ro2]|Rest],Min) & [[rng[Z1,Ri1,Ro1]|Rest-flank]|Rest-wp]. % reverse feature & reverse feature list % -------------------------------------- reverse-feature(nft[lsh[flk[Flank],grd[Ground]],Refined-ground]) :- Flank-rev .= reverse-wp-rng(Flank), Ground-rev .= reverse-wp-rng(Ground), Refined-ground-rev .= reverse-feature-list(Refined-ground) & nft[rsh[grd[Ground-rev],flk[Flank-rev]],Refined-ground-rev]. reverse-feature(nft[rsh[grd[Ground],flk[Flank]],Refined-ground]) :- Flank-rev .= reverse-wp-rng(Flank), Ground-rev .= reverse-wp-rng(Ground), Refined-ground-rev .= reverse-feature-list(Refined-ground) & nft[lsh[flk[Flank-rev],grd[Ground-rev]],Refined-ground-rev]. reverse-feature(nft[grv[flk[Flank1],grd[Ground],flk[Flank2]],Refined-ground]) :- Flank1-rev .= reverse-wp-rng(Flank1), Ground-rev .= reverse-wp-rng(Ground), Flank2-rev .= reverse-wp-rng(Flank2), Refined-ground-rev .= reverse-feature-list(Refined-ground) & nft[grv[flk[Flank2-rev],grd[Ground-rev],flk[Flank1-rev]], Refined-ground-rev]. reverse-feature-list([]) :& []. reverse-feature-list([H|T]) :& appfun(reverse-feature-list(T),tup(reverse-feature(H))). % auxiliary functions % ------------------- split-wp-rng(Max,[rng[Z,Max,Ro]|Rest]) :& [[rng[Z,Max,Max]]|[rng[Z,Max,Ro]|Rest]]. split-wp-rng(Max,[rng[Z,Ri,Max]|Rest]) :& [[rng[Z,Ri,Max]]|[rng[Z,Max,Max]|Rest]]. split-wp-rng(Max,[rng[Z,Ri,Ro]|Rest]) :- [Left-wp-rng|Rest-wp-rng] .= split-wp-rng(Max,Rest) & [[rng[Z,Ri,Ro]|Left-wp-rng]|Rest-wp-rng]. split-truncone(Z1,R1,Z2,R2,Min) :- H .= -(R1,R2) & +(Z1,/(*(-(Z2,Z1),-(H,-(Min,R2))),H)). max-rad([]) :& 0. max-rad([rng[Z,Ri,Ro]|Rest-rng-list]) :& max(Ri,Ro,max-rad(Rest-rng-list)). reverse-wp-rng([]) :& []. reverse-wp-rng([rng[Z,Ri,Ro]|Rest]) :- Mirr-z .= -(0,Z) & appfun(reverse-wp-rng(Rest),[rng[Mirr-z,Ro,Ri]]). % example % ------- % | D E % 40 +--+ % | / | % 35 / | % | / | F % 30 / +----------------+ % | A B / | G H % 25--------------+ + C | +------------+ % | | | | | | % 20 +--+ +--+ | % | | % 15 | % | | % 10 | % | | % 5 | % | | % 0_______________________________________________________________ % 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 exa() :& [rng[0,0,25], % A rng[40,25,20], % B rng[50,20,25], % C rng[60,40,40], % D rng[70,40,30], % E rng[110,30,20], % F rng[120,20,25], % G rng[150,25,0]]. % H tst1() :& [rng[0,0,25],rng[40,25,0]]. tst2() :& [rng[0,0,25],rng[40,25,75],rng[60,75,0]]. tst3() :& [rng[0,0,25],rng[40,25,75],rng[60,75,25],rng[80,25,0]].