[comp.lang.postscript] Finding the bounding shape of an object

orr@cs.glasgow.ac.uk (Fraser Orr) (09/23/88)

Given an arbitrary path, I would like to be able to get a path
that discribes the outside shape of this. Has anybody done this
or have you any suggestions as to how to do this?

Any help would be most appreciated,

Regards,

==Fraser Orr ( Dept C.S., Univ. Glasgow, Glasgow, G12 8QQ, UK)
UseNet: {uk}!cs.glasgow.ac.uk!orr       JANET: orr@uk.ac.glasgow.cs
ARPANet(preferred xAtlantic): orr%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk

kjk@pbhyf.PacBell.COM (Ken Keirnan) (09/25/88)

In article <1658@crete.cs.glasgow.ac.uk> orr%cs.glasgow.ac.uk@nss.ucl.ac.uk (Fraser Orr) writes:
>Given an arbitrary path, I would like to be able to get a path
>that discribes the outside shape of this. Has anybody done this
>or have you any suggestions as to how to do this?
>
>Any help would be most appreciated,
>
>Regards,
>
>==Fraser Orr ( Dept C.S., Univ. Glasgow, Glasgow, G12 8QQ, UK)
>UseNet: {uk}!cs.glasgow.ac.uk!orr       JANET: orr@uk.ac.glasgow.cs
>ARPANet(preferred xAtlantic): orr%cs.glasgow.ac.uk@nss.cs.ucl.ac.uk


I know this isn't exactly what you had in mind (outline path of an
arbitrary PostScript figure), but perhaps it will be a start.  Even if
you can't use it, others may find it useful.

The following PostScript routines, prepended to a PostScript figure,
will print the figure surrounded by the bounding box and coordinates.
This handy little piece of PostScript was included in the "psfig"
ditroff figure preprocessor software by Trevor Darrell and Ned Batchelder.

-- Ken Keirnan


%-------- CUT HERE -------- CUT HERE -------- CUT HERE --------
%! 
% bb.ps --
% 
% Prints a file, but keeps track of bounding box info, and prints the box at
% the end (around the figure).  Does not handle images and clipping well.
% --Trevor
% trevor@linc.cis.upenn.edu
% uucp: seismo!linc.cis.upenn.edu!trevor (or any arpa/uucp gateway)
% 

50 dict dup /$BoundingBox exch def begin

/xdef {
        exch def
} def

/xstore {
        exch store
} def

/bb-pt+ {
        exch
        4 -1 roll add
        3 1 roll add
} def

% 
% Stubs of old functions.
% 

/-stroke /stroke load def
/-fill /fill load def
/-eofill /eofill load def
/-image /image load def
/-show /show load def
/-awidthshow /awidthshow load def
/-showpage /showpage load def

% 
% New Functions.
% 

/stroke {
        gsave
        {
                flattenpath
                strokepath      % Make sure to take line width into account.
        } stopped {             % strokepath often hits a limitcheck.
                grestore        % Restore the original path
                gsave
        } if
        bb-path                 % Accumulate it into our box.
        grestore

        -stroke
} def

/fill {
        gsave
        bb-path
        grestore

        -fill
} def

/eofill {
        gsave
        bb-path
        grestore

        -eofill
} def

% 
% Text is implemented by reducing everything to an `awidthshow'.
% 

/show {
        0 0 0 0 0               % Extra parameters for awidthshow
        6 -1 roll               % Bring the string back up
        awidthshow
} def

/widthshow {
        0 0                     % Extra parameters for awidthshow
        3 -1 roll               % Bring the string back up.
        awidthshow
} def

/ashow {
        0 0 0 
        6 3 roll
        awidthshow
} def

/awidthshow {
        5 dict begin
        gsave
        currentpoint
        2 copy /@starty xdef /@startx xdef
        2 index stringwidth     % Get the natural length of the string
        bb-pt+                  % Add to the start to get the end.

        2 index length          % How many characters?

        dup                     % Add the offsets to each character
        6 index mul
        exch 5 index mul
        bb-pt+

        5 index 3 index
        bb-chcount              % How many padding characters?

        dup                     % Add the offsets for each pad.
        9 index mul
        exch 8 index mul
        bb-pt+

        /@endy xdef /@endx xdef

        bb-fontheight           % Get the height and depth of the current font.
        
        4 copy
        @startx @starty bb-pt+ bb-point
        @startx @starty bb-pt+ bb-point
        @endx @endy bb-pt+ bb-point
        @endx @endy bb-pt+ bb-point

        newpath                         % $Debug
        @startx @starty moveto          % $Debug
        @endx @endy lineto              % $Debug
        bb-bwstroke                     % $Debug
        
        grestore
        end

        -awidthshow
} def

% 
% `image':
% 
% Assume here that the image lands in the unit square.
% 

/image {
        -image
} def

% 
% `showpage':
% 
% Just draw the box around the figure and print the page, and then initialize
% the bounding box variables again.
% 

/bb-string 10 string def

/showpage {
        initgraphics

        bb-llx bb-lly itransform        % Convert them into default coords.
        bb-urx bb-ury itransform
        /bb-lly xstore /bb-urx xstore
        /bb-ury xstore /bb-llx xstore

        bb-llx bb-lly moveto            % Make the box
        bb-llx bb-ury lineto
        bb-urx bb-ury lineto
        bb-urx bb-lly lineto
        closepath

        bb-bwstroke                     % Draw the box.

        0 setgray
        /Courier findfont 10 scalefont setfont
        bb-llx bb-lly 12 sub moveto
        bb-llx bb-string cvs -show ( ) -show
        bb-lly bb-string cvs -show ( ) -show
        bb-urx bb-string cvs -show ( ) -show
        bb-ury bb-string cvs -show

        bb-init
        -showpage
} def

% 
% BoundingBox functions:
% 
% We accumulate the information about the bounding box into four variables.
% The data is stored in device coordinates.
% 

/bb-init {
        /bb-llx 99999 store
        /bb-lly 99999 store
        /bb-urx -99999 store
        /bb-ury -99999 store
} def

/bb-llx 0 def
/bb-lly 0 def
/bb-urx 0 def
/bb-ury 0 def

% 
% x y `bb-point' -
% 
% Takes a point in user coordinates and adds it into the bounding box info.
% 

/bb-point {
        transform               % Convert to device coords.
        dup
        dup bb-lly lt { 
                /bb-lly xstore
        } {
                pop
        } ifelse
        dup bb-ury gt {
                /bb-ury xstore
        } {
                pop
        } ifelse

        dup
        dup bb-llx lt {
                /bb-llx xstore
        } {
                pop
        } ifelse
        dup bb-urx gt {
                /bb-urx xstore
        } {
                pop
        } ifelse
} def

% 
% - `bb-path' -
% 
% Incorporates the bounding box of the path into the bounding box info.
% 

/bb-path {
        gsave
        {
                0 setlinejoin
                flattenpath
        } stopped {
                grestore
                gsave
        } if
        pathbbox
        bb-point
        bb-point
        grestore
} def

% 
% A nice black-and white line drawing function.
% 

/bb-bwstroke {
        0 setlinewidth                  % Thinnest possible lines
        1 setgray                       % White first
        [5] 0 setdash                   % Only half the line
        gsave -stroke grestore
        0 setgray                       % Then black
        [5] 5 setdash                   % On the other half
        -stroke
} def

% 
% Stuff for text.
% 

% 
% char-code string `bb-chcount' occurs
% 
% Counts the number of times a character appears in a string.
% 

/bb-chcount {
        0 exch
        {
                2 index eq {
                        1 add
                } if
        } forall
        exch pop
} def

% 
% - `bb-fontheight' heightx heighty depthx depthy
% 
% Returns the offsets to the lowest point and highest point in the current
% font.
% 

/bb-fontheight {
        currentfont begin
        % following line commented out by PHW; replaced by next 2 lines
        % FontBBox
          currentfont /FontBBox get
          dup 0 get exch dup 1 get exch dup 2 get exch 3 get
        exch pop 0 exch
        FontMatrix
        transform
        4 2 roll
        exch pop 0 exch
        FontMatrix
        transform
        end
} def

% Start it up.

bb-init

%  end of bb.ps
%-------- CUT HERE -------- CUT HERE -------- CUT HERE --------
-- 

Ken Keirnan - Pacific Bell - {att,bellcore,sun,ames,pyramid}!pacbell!pbhyf!kjk
  San Ramon, California	                    kjk@pbhyf.PacBell.COM

mh@wlbr.EATON.COM (Mike Hoegeman) (09/26/88)

In article <1658@crete.cs.glasgow.ac.uk> orr%cs.glasgow.ac.uk@nss.ucl.ac.uk (Fraser Orr) writes:
>Given an arbitrary path, I would like to be able to get a path
>that discribes the outside shape of this. Has anybody done this
>or have you any suggestions as to how to do this?
>
>Any help would be most appreciated,
>

depending on what you want to do 'strokepath' may be your ticket.
check it out in the Red Book. 

-mike