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)