Thread View: comp.lang.postscript
1 messages
1 total messages
Started by Lee Choquette
Wed, 03 Feb 1988 02:09
Escher's Fish.ps: Draws interlocking, endless fish
Author: Lee Choquette
Date: Wed, 03 Feb 1988 02:09
Date: Wed, 03 Feb 1988 02:09
291 lines
8168 bytes
8168 bytes
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
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads