u-lchoqu%sunset.utah.edu@utah-cs.UUCP (Lee Choquette) (02/03/88)
This PostScript program comes from our freely distributed Macintosh software library. It draws interlocking stylized fish: four large ones in the center, growing continually smaller toward the edges. ---- Lee Choquette u-lchoqu@ug.utah.edu University of Utah Computer Center utah-gr!utah-ug!u-lchoqu MEB 3440 Choquette@UTAHCCA.Bitnet Salt Lake City, UT 84112-1180 (801) 581-8504 "All right, all right, we're not all programmed for perfection, you know." % "Square Limit" drawing by M. C. Escher % Functions derived by Peter Henderson % Paper in 1982 Conference on LISP and Functional Programming % Coding by Michael Parsons, Sept. 1985 % Translation to PostScript for Sun CRT by Peter Bumbulis, July 1986 % Adaptation for Apple LaserWriter by Price Collins, Jan. 1988 % corner defines one corner of the picture at level n /corner { dup 0 le { pop { } { } { } u quartet } { 1 sub dup corner exch side dup 90 rot u quartet } ifelse } def % cycle combines 4 copies of image each rotated by 90 degrees /cycle { dup 270 rot dup 180 rot dup 90 rot quartet } def % fish gives a border to produce the final drawing /fish { squarelimit exec newpath 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath stroke } def % flip inverts the image /flip { .5 .5 translate 1 -1 scale -.5 -.5 translate } def % nonet arranges 9 images in equal sized squares to form 1 image /nonet { 9 -1 roll 1 3 div 0 1 zoom 9 -1 roll 1 3 div .5 1 zoom 9 -1 roll 1 3 div 1 1 zoom 9 -1 roll 1 3 div 0 .5 zoom 9 -1 roll 1 3 div .5 .5 zoom 9 -1 roll 1 3 div 1 .5 zoom 9 -1 roll 1 3 div 0 0 zoom 9 -1 roll 1 3 div .5 0 zoom 9 -1 roll 1 3 div 1 0 zoom 9 { exec } /repeat cvx 12 array astore cvx } def % quadcorner forms 1 quarter of the image at level n. /quadcorner { dup corner exch side dup dup 90 rot dup u exch t 90 rot dup 3 1 roll { q } 90 rot nonet } def % quartet combines 4 images, 1 in each quadrant, to produce 1 image /quartet { 4 -1 roll 1 2 div 0 1 zoom 4 -1 roll 1 2 div 1 1 zoom 4 -1 roll 1 2 div 0 0 zoom 4 -1 roll 1 2 div 1 0 zoom 4 { exec } /repeat cvx 7 array astore cvx } def % rot rotates image by the radians anti-clockwise about the image center /rotcode { gsave .5 .5 translate rotate -.5 -.5 translate exec grestore } def /rot { /rotcode cvx 3 array astore cvx } def % side defines one side of the picture at level n /side { dup 0 le { pop { } dup t 90 rot t quartet } { 1 sub side dup t 90 rot t quartet } ifelse } def % squarelimit produces the fish drawing /squarelimit { quadcorner cycle } def % zoom scales an image up or down with one fixed point /zoomcode { gsave 2 copy neg exch neg exch 5 2 roll translate dup scale translate exec grestore } def /zoom { /zoomcode cvx 5 array astore cvx } def % p, q, r and s are the data needed to draw the fish /p { gsave flip .0625 .0625 scale newpath 3 12 moveto 0 8 lineto 0 13 lineto 3 12 lineto 4 12 moveto 6 16 lineto 7 10 moveto 4 11 lineto 4 6 lineto 7 10 lineto 8 4 moveto 16 6 lineto 8 8 moveto 10 12 lineto 13 11 lineto 16 12 lineto 9 10 moveto 12 9 lineto 16 10 lineto 10 0 moveto 12 2 lineto 16 3 lineto 10 12 moveto 11 16 lineto 14 14 lineto 16 14 lineto 12 0 moveto 13 1 lineto 16 2 lineto 14 0 moveto 16 1 lineto 16 4 moveto 12 4 lineto 8 0 lineto 6 1 lineto 0 0 lineto 4 3 lineto 8 8 lineto 12 7 lineto 16 8 lineto stroke grestore } def /q { gsave flip .0625 .0625 scale newpath 0 0 moveto 0 4 lineto 3 3 lineto 5 2 lineto 4 0 lineto 0 6 moveto 7 5 lineto 2 0 moveto 3 3 lineto 2 16 moveto 4 11 lineto 4 9 lineto 6 9 lineto 4 9 moveto 0 8 lineto 0 16 lineto 8 16 lineto 10 10 lineto 10 7 lineto 4 16 moveto 6 11 lineto 6 9 lineto 12 6 lineto 16 0 lineto 15 6 lineto 16 8 lineto 13 12 lineto 12 16 lineto 16 16 lineto 5 2 moveto 7 1 lineto 8 0 lineto 6 0 moveto 7 1 lineto 6 16 moveto 8 11 lineto 8 1 moveto 11 1 lineto 9 3 lineto 8 1 lineto 8 11 moveto 8 8 lineto 9 4 moveto 12 4 lineto 10 6 lineto 9 4 lineto 10 16 moveto 14 5 lineto 13 16 moveto 16 10 lineto 14 16 moveto 16 12 lineto 15 16 moveto 16 14 lineto stroke grestore } def /r { gsave flip .0625 .0625 scale newpath 0 4 moveto 1 2 lineto 0 8 moveto 2 4 lineto 0 12 moveto 5 6 lineto 0 16 moveto 8 8 lineto 1 15 moveto 4 16 lineto 2 14 moveto 8 16 lineto 3 13 moveto 8 14 lineto 12 16 lineto 5 11 moveto 12 13 lineto 16 16 lineto 6 0 moveto 11 6 lineto 16 10 lineto 11 0 moveto 12 4 lineto 16 8 lineto 12 4 moveto 16 0 lineto 15 1 moveto 16 2 lineto 14 2 moveto 16 4 lineto 13 3 moveto 16 6 lineto 16 12 moveto 14 10 lineto 8 8 lineto 2 4 lineto 0 0 lineto stroke grestore } def /s { gsave flip .0625 .0625 scale newpath 0 16 moveto 4 14 lineto 8 14 lineto 16 16 lineto 10 12 lineto 8 10 lineto 7 8 lineto 7 3 lineto 8 0 lineto 0 2 moveto 7 3 lineto 0 4 moveto 7 6 lineto 0 6 moveto 7 8 lineto 0 8 moveto 8 10 lineto 0 10 moveto 7 12 lineto 0 12 moveto 2 15 lineto 10 0 moveto 11 6 lineto 12 0 moveto 13 3 lineto 12 12 moveto 12 9 lineto 10 10 lineto 12 12 lineto 14 5 moveto 16 4 lineto 15 7 moveto 13 3 lineto 16 2 lineto 15 11 moveto 15 8 lineto 13 9 lineto 15 11 lineto 16 6 moveto 15 7 lineto 16 8 lineto stroke grestore } def % t is one of the basic fish rearrangements /t { { p } { q } { r } { s } quartet } def % u is another of the basic fish rearrangements /u { { q } 90 rot cycle } def % display a level 2 fish .001 setlinewidth 0 setgray 60 150 translate 500 500 scale 2 2 fish showpage