%%BeginResource: procset LoutPiePrependGraphic %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % PostScript @SysPrependGraphic file for @Pie Jeffrey H. Kingston % % Version 1.0 % % % % Jeffrey H. Kingston % % October 2002 % % % % To assist in avoiding name clashes, the names of all symbols % % defined here begin with "lpie". % % % % is two numbers, a point. % % is one number, a length % % is one number, an angle in degrees % % is one number, the preferred length of a dash % % % % The following invariant is maintained from the end of the % % call to lpiebegin to the beginning of the call to lpieend: % % % % lpiecentre is an executable function which leaves the two % % coordinates of the centre of the pie on the % % operand stack (signature - lpiectr ) % % % % lpieradius is the radius of the pie % % % % lpieinitangle is the initial angle % % % % lpietotalweight is the total weight of all slices % % % % lpiecurrentweight is the total weight of all slices so far % % % % The first four are constants set by lpiebegin; the last is % % updated as each slice is printed. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % install error handler into error dictionary errordict begin /handleerror { { /Times-Roman findfont 8 pt scalefont setfont 0 setgray 4 pt 4 pt moveto $error /errorname get dup lpiedict exch known { lpiedict exch get } { 100 string cvs } ifelse show ( Command: ) show $error /command get 100 string cvs show } stopped {} if showpage stop } def end % initial coordinates of debug output /lpiedebugposy 432 def /lpiedebugposx 72 def % lpiedebugprint - % must be defined outside lpiedict since used in arbitrary places % print plus count or stack entries, whichever is the smaller /lpiedebugprint { exch gsave initgraphics lpiedebugposy 72 lt { /lpiedebugposx lpiedebugposx 144 add store /lpiedebugposy 432 store } { /lpiedebugposy lpiedebugposy 12 sub store } ifelse lpiedebugposx lpiedebugposy moveto /Times-Roman findfont 10 scalefont setfont 0 setgray show count 1 sub 2 copy lt { pop } { exch pop } ifelse 1 sub 0 exch 1 exch { /lpiedebugposy lpiedebugposy 12 sub store lpiedebugposx 12 add lpiedebugposy moveto index dup type (dicttype) eq { (begin dict) show { /lpiedebugposy lpiedebugposy 12 sub store lpiedebugposx 24 add lpiedebugposy moveto pop 100 string cvs show } forall /lpiedebugposy lpiedebugposy 12 sub store lpiedebugposx 12 add lpiedebugposy moveto (end dict) show } { dup type (arraytype) eq { dup xcheck { (executable array) } { (literal array) } ifelse show { /lpiedebugposy lpiedebugposy 12 sub store lpiedebugposx 24 add lpiedebugposy moveto 100 string cvs show } forall /lpiedebugposy lpiedebugposy 12 sub store lpiedebugposx 12 add lpiedebugposy moveto (end array) show } { dup xcheck { (ex: ) } { (lit: ) } ifelse show 100 string cvs show } ifelse } ifelse } for grestore } def % name lpiedebugpoint - /lpieshowpoint { dup cvx exec moveto 20 string cvs show newpath } def % begin pie: lpiebegin - % must be defined outside lpiedict since it loads it /lpiebegin { lpiedict begin 20 dict begin xmark ymark /lpiecentre lpiepointdef /lpieradius xmark def /lpieinitialangle exch def /lpietotalweight exch def /lpiecurrentweight 0 def } def % end pie: - lpieend - /lpieend { end end } def % pie dictionary /lpiedict 200 dict def % subsequent definitions are held within the pie dictionary lpiedict begin % error messages /syntaxerror (syntaxerror error: syntax error in text of pie chart?) def /typecheck (typecheck error: syntax error in text of pie chart?) def /undefined (undefined error: unknown or misspelt label?) def /VMError (VMError error: run out of memory?) def % maximum of two numbers: lpiemax /lpiemax { 2 copy gt { pop } { exch pop } ifelse } def % minimum of two numbers: lpiemin /lpiemin { 2 copy lt { pop } { exch pop } ifelse } def % add two points: lpiepadd /lpiepadd { % (Entering padd) 4 lpiedebugprint exch 3 1 roll add 3 1 roll add exch % (Leaving padd) 2 lpiedebugprint } def % subtract first point from second: lpiepsub /lpiepsub { 3 2 roll sub 3 1 roll exch sub exch } def % max two points: lpiepmax /lpiepmax { exch 3 1 roll lpiemax 3 1 roll lpiemax exch } def % min two points: lpiepmin /lpiepmin { exch 3 1 roll lpiemin 3 1 roll lpiemin exch } def % scalar multiplication: lpiepmul /lpiepmul { dup 3 1 roll mul 3 1 roll mul exch } def % distance between two points: lpiedistance /lpiedistance { lpiepsub dup mul exch dup mul add sqrt } def % point at angle and distance % lpieatangle /lpieatangle { 2 copy cos mul 3 1 roll sin mul lpiepadd } def % stroke a solid line: lpiesolid - /lpiesolid { % (Entering lpiesolid) 2 lpiedebugprint gsave pop pop [] 0 setdash 1 setlinecap stroke grestore newpath % (Leaving lpiesolid) 0 lpiedebugprint } def % stroke a dashed line: lpiedashed - /lpiedashed { gsave 2 copy div 2 le 1 index 0 le or { exch pop 1 pt lpiemax [ exch dup ] 0 setdash } { dup [ exch 4 2 roll 2 copy div 1 sub 2 div ceiling dup 4 1 roll 1 add mul sub exch div ] 0 setdash } ifelse 0 setlinecap stroke grestore newpath } def % stroke a cdashed line: lpiecdashed - /lpiecdashed { % (Entering lpiecdashed) 2 lpiedebugprint gsave 2 copy le 1 index 0 le or { exch pop 1 pt lpiemax [ exch dup ] dup 0 get 2 div setdash } { dup [ 4 2 roll exch 2 copy exch div 2 div ceiling div 1 index sub ] exch 2 div setdash } ifelse 0 setlinecap stroke grestore newpath % (Leaving lpiecdashed) 0 lpiedebugprint } def % stroke a dotted line: lpiedotted - /lpiedotted { gsave 2 copy le 1 index 0 le or { exch pop 1 pt lpiemax [ exch 0 exch ] 0 setdash } { 1 index exch div ceiling div [ 0 3 2 roll ] 0 setdash } ifelse 1 setlinecap stroke grestore newpath } def % stroke a noline line: lpienoline - /lpienoline { pop pop } def % label a point in current dictionary: /name lpiepointdef - /lpiepointdef { % (Entering lpiepointdef) 3 lpiedebugprint [ 4 2 roll transform /itransform cvx ] cvx def % (Leaving lpiepointdef) 0 lpiedebugprint } def % find the angle that the current slice starts at % - lpiesliceangle1 /lpiesliceangle1 { lpiecurrentweight lpietotalweight div 360 mul lpieinitialangle add } def % find the angle that the current slice stops at % - lpiesliceangle2 /lpiesliceangle2 { weight lpiecurrentweight add lpietotalweight div 360 mul lpieinitialangle add } def % find the angle that bisects the current slice % - lpieslicemidangle /lpieslicemidangle { weight 2 div lpiecurrentweight add lpietotalweight div 360 mul lpieinitialangle add } def % update the total weight % - lpieupdateweight - /lpieupdateweight { weight lpiecurrentweight add /lpiecurrentweight exch def } def % find the apex of the slice % - lpiesliceapex /lpiesliceapex { lpiecentre lpieradius detach mul lpieslicemidangle lpieatangle } def % find the end of the first arm of the slice % - lpieslicearm1 /lpieslicearm1 { lpiesliceapex lpieradius lpiesliceangle1 lpieatangle } def % find the end of the second arm of the slice % - lpieslicearm2 /lpieslicearm2 { lpiesliceapex lpieradius lpiesliceangle2 lpieatangle } def % set the whole closed path for the current slice % - lpiesetslicepath - /lpiesetslicepath { newpath lpiesliceapex moveto currentpoint lpieradius lpiesliceangle1 lpiesliceangle2 arc closepath } def % set the first segment of the current slice and return its length % - lpiesetsegment1 /lpiesetsegment1 { newpath lpiesliceapex moveto lpieslicearm1 lineto lpieradius } def % set the second segment of the current slice and return its length % - lpiesetsegment2 /lpiesetsegment2 { newpath lpiesliceapex moveto lpieslicearm2 lineto lpieradius } def % set the arc segment of the current slice and return its length % - lpiesetarcsegment /lpiesetarcsegment { newpath lpiesliceapex lpieradius lpiesliceangle1 lpiesliceangle2 arc lpiesliceangle2 lpiesliceangle1 sub 180 div 3.14159 mul lpieradius mul } def % draw one slice % [ ] { } % lpiedrawslice - /lpiebeginslice { % (Entering lpiebeginslice) 6 lpiedebugprint /detach exch def /weight exch def % paint the slice gsave lpiesetslicepath exec grestore % set the line width setlinewidth % stroke each segment separately to get dashes right 2 copy lpiesetsegment1 3 1 roll dup length 0 exch mod get cvx % (Stroking segment1) count 1 sub lpiedebugprint exec 2 copy lpiesetarcsegment 3 1 roll dup length 1 exch mod get cvx % (Stroking arc segment) count 1 sub lpiedebugprint exec lpiesetsegment2 3 1 roll dup length 2 exch mod get cvx % (Stroking segment2) count 1 sub lpiedebugprint exec % (Leaving lpiebeginslice) 0 lpiedebugprint } def % finish off one slice /lpieendslice { % (Entering lpieendslice) 0 lpiedebugprint % update current weight ready for next slice lpieupdateweight % (Leaving lpieendslice) 0 lpiedebugprint } def % translate label % lpietranslatelabel - /lpietranslatelabel { % (Entering lpietranslatelabel) 3 lpiedebugprint /labelradius exch def % lpiecentre (lpiecentre:) 2 lpiedebugprint pop pop % lpieradius (lpieradius:) 1 lpiedebugprint pop % labelradius (labelradius:) 1 lpiedebugprint pop % lpieslicemidangle (lpieslicemidangle:) 1 lpiedebugprint pop xsize 2 div ysize 2 div /labelcentre lpiepointdef labelcentre lpiesliceapex lpieradius labelradius mul lpieslicemidangle lpieatangle lpiepsub lpiepadd translate % (Leaving lpietranslatelabel) 0 lpiedebugprint } def % fix an angle to 0 <= res < 360: lpiefixangle /lpiefixangle { % (Entering lpiefixangle) 1 lpiedebugprint { dup 0 ge { exit } if 360 add } loop { dup 360 lt { exit } if 360 sub } loop % (Leaving lpiefixangle) 1 lpiedebugprint } def % angle from one point to another % lpieangleto /lpieangleto { lpiepsub 2 copy 0 eq exch 0 eq and {pop} {exch atan} ifelse } def % find point on circumference of box: alpha a b lpieboxcircum x y /lpieboxcircum { % (Entering lpieboxcircum) 3 lpiedebugprint 4 dict begin /b exch def /a exch def lpiefixangle /alpha exch def 0 0 a b lpieangleto /theta exch def % a (a:) 1 lpiedebugprint pop % b (b:) 1 lpiedebugprint pop % theta (theta:) 1 lpiedebugprint pop % alpha (alpha:) 1 lpiedebugprint pop % if alpha <= theta, return (a, a*tan(alpha)) alpha theta le { a a alpha sin mul alpha cos div } { % else if alpha <= 180 - theta, return (b*cot(alpha), b) alpha 180 theta sub le { b alpha cos mul alpha sin div b } { % else if alpha <= 180 + theta, return (-a, -a*tan(alpha)) alpha 180 theta add le { a neg a neg alpha sin mul alpha cos div } { % else if alpha <= 360 - theta, return (-b*cot(alpha), -b) alpha 360 theta sub le { b neg alpha cos mul alpha sin div b neg } { % else 360 - theta <= alpha, return (a, a*tan(alpha)) a a alpha sin mul alpha cos div } ifelse } ifelse } ifelse } ifelse end % (Leaving lpieboxcircum) 2 lpiedebugprint } def % draw finger (will immediately follow lpietranslatelabel) % "[" "]" fingerwidth % lpiedrawfinger - /lpiedrawfinger { % (Entering lpidrawfinger) 6 lpiedebugprint % find inner endpoint of finger /fingerradius exch def lpiesliceapex lpieradius fingerradius mul lpieslicemidangle lpieatangle lpiepadd /fingerinner lpiepointdef xsize 2 div ysize 2 div /labelcentre lpiepointdef 0 0 /labelorigin lpiepointdef % find outer endpoint of finger, on circumference of label labelcentre fingerinner lpieangleto xsize 2 div ysize 2 div lpieboxcircum labelcentre lpiepadd /fingerouter lpiepointdef % set the line width setlinewidth % draw line newpath fingerinner moveto fingerouter lineto fingerinner fingerouter lpiedistance 3 1 roll 0 get cvx exec % (Leaving lpiedrawfinger) 0 lpiedebugprint } def % draw arrowhead (will immediately follow lpiedrawfinger if reqd) % lpiedrawarrowhead /lpiedrawarrowhead { gsave /headwidth exch def /headlength exch def fingerinner translate fingerouter fingerinner lpieangleto rotate 0 0 moveto headlength neg headwidth 2 div lineto 0 headwidth neg rlineto closepath fill grestore } def end %%EndResource