%!
%%BoundingBox: 126 246 486 546
% Cookbook Example Program from First Printing, Revised 7 Jan 1985
% Program: Drawing a Pie Chart     Number: 18
%-----------------------------------------------------------------------------
%
/PieDict 24 dict def                        % Local storage for
                                           % ``DrawPieChart'' and its related
                                           % procedures.
PieDict begin
 /DrawSlice                                % DrawSlice draws an outlined and
   { /grayshade exch def                   % filled-in pie slice. It takes
     /endangle exch def                    % four operands: the label for
     /startangle exch def                  % this particular pie slice, the
     /thelabel exch def                    % starting angle for the slice,
                                           % the ending angle for the slice
                                           % and the shade of gray the slice
                                           % should be.

     newpath                               % Create a path which will draw a
                                           % pie slice.
       0 0 moveto
       0 0 radius startangle endangle arc
     closepath

     1.415 setmiterlimit                   % This guarantees that when we
                                           % outline the pie slices with a
                                           % stroke that we will not get a
                                           % spike on the interior angles.
     gsave grayshade setgray fill grestore % Fill the pie slice path with the
     stroke                                % appropriate gray color. By using
                                           % gsave and grestore we don't lose
                                           % the current path. Since
                                           % PostScript paints color onto the
                                           % page, it is very important that
                                           % we fill the pie slice first and
                                           % then outline it with a stroke.
     gsave                                 % Draw the tick mark and place the
                                           % label:
       startangle endangle add 2 div       % Find the center of the pie slice
         rotate                            % and rotate so that the x-axis
                                           % coincides with this center.
       radius 0 translate                  % Translate the origin out to the
                                           % circumference.
       newpath
         0 0 moveto labelps .8 mul 0 lineto% Draw the tick-mark.
       stroke
       labelps 0 translate                 % Move the origin out a little
                                           % beyond the circumference.
       0 0 transform                       % Next we wish to place the label
     grestore                              % at the current origin. If we
     itransform                            % simply draw the text on the page
     /y exch def /x exch def               % now, it would come out rotated.
     x y moveto                            % Since this is not desired we
                                           % avoid it by returning to the
                                           % previous unrotated coordinate
                                           % system. Before returning,
                                           % though, we would like to
     x 0 lt                                % remember the position of the
       { thelabel stringwidth pop neg      % current origin on the printed
           0 rmoveto                       % page. We will accomplish this by
       } if                                % using the transform and
                                           % itransform operators. Performing
                                           % a transform on the origin pushes
                                           % the coordinates of the origin in
                                           % device space onto the operand
                                           % stack. Performing a grestore
                                           % returns us to the previous
                                           % unrotated coordinate system.
                                           % Next we perform an itransform on
                                           % the two device coordinates left
                                           % on the stack to determine where
                                           % we are in the current coordinate
                                           % system.
     y 0 lt { 0 labelps neg rmoveto } if   % Make some adjustments so that
     thelabel show                         % the label text won't collide
   } def                                   % with the pie slice.
 /findgray                                 % Procedure findgray calculates
   { /i exch def /n exch def               % the gray value for a slice. It
     i 2 mod 0 eq                          % takes two arguments: the total
       { i 2 div n 2 div round add n div } % number of slices and the current
       { i 1 add 2 div n div }             % slice number (Given that there
       ifelse                              % are n pie slices, the slices are
   } def                                   % ``numbered'' from 1 to n). The
end                                         % gray values for the pie slices
                                           % range evenly from white to black
                                           % (i.e. - the values provided to
                                           % setgray range from (n/n, n-1/n,
                                           % ..., 1/n)). Since we don't want
                                           % similar values of gray next to
                                           % each other, findgray
                                           % ``shuffles'' the possible
                                           % combinations of gray.

/DrawPieChart                               % DrawPieChart takes seven
 { PieDict begin                           % arguments: the title of the pie
     /radius exch def                      % chart, the point size to print
     /ycenter exch def /xcenter exch def   % the title in, the point size to
     /PieArray exch def                    % print the labels for each slice
     /labelps exch def /titleps exch def   % in, a special array (described
     /title exch def                       % below where DrawPieChart is
                                           % called), the (x,y) center of the
                                           % pie chart and the radius of the
                                           % pie chart.

     gsave
       xcenter ycenter translate           % Translate the coordinate system
                                           % origin to center of pie chart.
       /Helvetica findfont titleps         % Print the title of the pie chart
         scalefont setfont                 % in Helvetica.
       title stringwidth pop 2 div neg     % Center the title below the pie
                                           % chart.
         radius neg titleps 3 mul sub
         moveto title show
       /Helvetica findfont labelps         % Print the individual pie slice
         scalefont setfont                 % labels in Helvetica
       /numslices PieArray length def
       /slicecnt 0 def
       /curangle 0 def                     % A ``loop'' variable that keeps
                                           % track of the angle of arc to
                                           % begin each pie slice at.
       PieArray                            % Repeat the following for each
                                           % element in the PieArray.
         { /slicearray exch def
           slicearray aload pop            % Push the label and percentage
                                           % onto the stack.
           /percent exch def
           /label exch def
           /perangle percent 360 mul def   % Convert the percentage into
                                           % degrees of angle.
           /slicecnt slicecnt 1 add def
           label curangle
             curangle perangle add
             numslices slicecnt findgray
             DrawSlice
           /curangle curangle perangle add % Update the current starting
                                           % angle.
             def
         } forall
     grestore
   end
 } def

() 18 9
 [ [(Blueberry) .12 ]                      % The pie array is an array of
   [(Cherry) .30 ]                         % arrays. Each array in the pie
   [(Apple) .26 ]                          % array contains a string denoting
   [(Boston Cream) .16 ]                   % the label to be printed next to
   [(Other) .04 ]                          % the pie slice followed by a real
   [(Vanilla Cream) .12 ]                  % number indicating the percentage
 ] 306 396 100 DrawPieChart                % of the pie represented by this
                                           % particular slice.
showpage