[comp.lang.postscript] What does concat do?

sbchanin@ai.mit.edu (Steve Chanin) (12/20/90)

Postscript Wizards,
	I've got some code which draws pictures composed only of lines
in a mac window under mac allegro common lisp.  I wanted to be able to
edit it in a graphics program, so I wrote a few functions to dump
postscript in the format used by idraw (a macpaint clone which runs
under x and uses postscript as its save format).  A line drawn with
idraw and saved as a .ps file looks like:
	Begin %I Line
	%I b 65535
	1 0 0 [] 0 SetB
	%I cfg Black
	0 0 0 SetCFg
	%I cbg White
	1 1 1 SetCBg
	%I p
	0 SetP
	%I t
	[ 1 0 0 1 97 183 ] concat
	%I
	44 441 260 325 Line
	End
Most of the commands are defined in the idraw prolog (at the end of
this message I've included a complete idraw file for a picture
containing two lines in case you need to see this prolog to understand
the preceeding postscript), but the key line seems to be:
	44 441 260 325 Line
As far as I can tell, if I map each line in my mac window into a
paragraph like the one above except with the 4 numbers before Line
changed, everything works fine (i.e. I get a postscript file which I
can view and print).  However, the question I have is what
does the concat command do?  What do the 6 numbers mean?  Different
lines in idraw seem to have a different matrix preceeding the concat
command, but I'm not sure what those matrices do or how to generate
the correct values for them.  In some sense, since it works, maybe I
shouldn't fix it, but I'd like to make the code available to other
people and before I do that, I'd like to make sure that it's "right."
I'd appreciate any help that anyone can give me.  Also, please make
your explanations simple because I don't know anything about
postscript (in fact before yesterday when I decided I needed to dump
postscript, I'd never even seen a postscript program).

Thanks alot,
Steve

--
===============================================================================
DOMAIN: sbchanin@ai.mit.edu                     MIT Artificial Intelligence Lab
USMAIL: Steven Chanin, 545 Technology Square Rm. 827, Cambridge Ma 02139
PHONE : (617) 253-8963

wiml@milton.u.washington.edu (William Lewis) (12/20/90)

  I'm not exactly a PS wizard, but I'll take a stab at this. The 'concat'
operator modifies the current coordinate system. It's a generalization
of translate, scale, and rotate... basically, it takes a 6-element array,
[a b c d e f], converts it into the matrix

[a  c  0]
[b  d  0]
[e  f  1]

  (I may have the upper left corner transposed). Anyway, it then replaces
the current coordinate transformation matrix (which is what specifies
the correspondence between 'points' and device pixels) withe the old
CTM multiplied by this matrix. For instance,

[1 0 0 1 15 37] concat

 has the same effect as

15 37 translate

  ... I think. (In effect, adding 15 to every X coordinate and 37 to every Y
coordinate given from then on.) I'm not sure why a paint program would be 
changing its coordinate system before every line it draws, but who can
fathom machine-generated code?

-- 
 wiml@milton.acs.washington.edu       Seattle, Washington   
     (William Lewis)   |  47 41' 15" N   122 42' 58" W  
"These 2 cents will cost the net thousands upon thousands of 
dollars to send everywhere. Are you sure you want to do this?"

shiva@well.sf.ca.us (Kenneth Porter) (12/25/90)

For those without the Red Book (page 64):
 
PostScript's coordinate transformations are based on the idea
of a transformation matrix.  In a 2-dimensional system, 6
numbers can describe all linear transformations of a
2-dimensional vector. Given a matrix [a b c d tx ty] and a
coordinate pair (x y), a transformed point (newx newy) can be
calculated with:
 
newx = a*x + c*y + tx
newy = b*x + d*y + ty
 
For normal operations, you can think of (x y) as user-space
coordinates, and (newx newy) as the device coordinates.
 
Numerous operators work on matrices; some operate on the
currentmatrix which transforms user coordinates into device
coordinates.
 
Examples of the former are matrix (creates an indentity
matrix), concatmatrix (three arguments, multiplies two matrices
together, putting the result in the third, returns the third),
and invertmatrix.
 
Examples of the latter are scale, translate, rotate, and
concat.
 
The concat operator concatenates its argument with the
currentmatrix (ie. the currentmatrix is changed to the argument
times the old currentmatrix).  This is more efficient than
using separate translate, rotate, and scale operations.  It
also allows skewing, for which there is no builtin operator.
 
Here's a definition of translate:
 
/translate {
  /ty exch def			% get y-translation
  /tx exch def			% get x-translation
  /tmp-matrix matrix def	% create identity matrix
  tmp-matrix 4 tx put
  tmp-matrix 5 ty put
  tmp-matrix concat
} def
 
Here's a definition of scale:
 
/scale {
  /sy exch def			% get y-scale
  /sx exch def			% get x-scale
  /tmp-matrix matrix def	% create identity matrix
  tmp-matrix 0 sx put
  tmp-matrix 2 sy put
  tmp-matrix concat
} def
 
Here's rotate:
 
/rotate {
  /angle exch def
  /tmp-cos angle cos def	% get cosine and sine of angle
  /tmp-sin angle sin def
  /tmp-matrix matrix def	% create identity matrix
  tmp-matrix 0 tmp-cos put
  tmp-matrix 1 tmp-sin put
  tmp-matrix 2 tmp-sin neg put
  tmp-matrix 3 tmp-cos put
  tmp-matrix concat
} def
 
Ken (shiva@well.sf.ca.us)