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