Classical Math Fractals in PostScript
Classical Math Fractals in PostScript
Abstract
Classical mathematical fractals in BASIC are explained and converted into mean-and-lean EPSF
defs, of which the .eps pictures are delivered in .pdf format and cropped to the prescribed
BoundingBox when processed by Acrobat Pro, to be included easily in pdf(La)TEX, Word, …
documents. The EPSF fractals are transcriptions of the Turtle Graphics BASIC codes or pro-
grammed anew, recursively, based on the production rules of oriented objects. The Linden-
mayer production rules are enriched by PostScript concepts. Experience gained in converting
a TEX script into WYSIWYG Word is communicated.
Keywords
Acrobat Pro, Adobe, art, attractor, backtracking, BASIC, Cantor Dust, C curve, dragon curve,
EPSF, FIFO, fractal, fractal dimension, fractal geometry, Game of Life, Hilbert curve, IDE (In-
tegrated development Environment), IFS (Iterated Function System), infinity, kronkel (twist),
Lauwerier, Lévy, LIFO, Lindenmayer, minimal encapsulated PostScript, minimal plain TeX,
Minkowski, Monte Carlo, Photoshop, production rule, PSlib, self-similarity, Sierpiński (island,
carpet), Star fractals, TACP, TEXworks, Turtle Graphics, (adaptable) user space, von Koch
(island), Word
Contents
Introduction
Lévy (Properties, PostScript program, Run the program, Turtle Graphics) Cantor0
Lindenmayer enriched by PostScript concepts for the Lévy fractal
von Koch (Properties, PostScript def, Turtle Graphics, von Koch island) Cantor1
Lindenmayer enriched by PostScript concepts for the von Koch fractal Cantor2
Kronkel Cantor3
Minkowski
Dragon figures
Stars
Game of Life
Annotated References
Conclusions (TEX mark up, Conversion into Word)
Acknowledgements (IDE)
Appendix: Fractal Dimension
Appendix: Cantor Dust
Appendix: Hilbert Curve
Peano curves: order 1, 2, 3
Appendix: Sierpiński islands
Introduction
My late professor Hans Lauwerier published nice, inspiring booklets about fractals
with programs in BASIC. However, I don’t know how to include elegantly the pic-
tures, obtained by running the BASIC codes, in my documents. Moreover, I consider
PostScript (PS, for short) more portable in place and time, can include EPSF results in
my TEX documents1 easily, and … do realize that PS is the de-facto standard industrial
printer language.
50 MAPS 44 Kees van der Laan
This note is about conversion of some of Lauwerier’s BASIC Turtle Graphics codes
for the simplest fractals into EPSF, ànd about the programming of new recursive EPSF
defs biased by Lindenmayer production rules for oriented objects, enriched with PS
concepts.
← Hilbert curves
Sierpiński →
islands 1, 2, 3
Now and then I have explained Lauwerier’s algorithms, especially when he asso-
ciates binary and quaternary number representations with fractals.
Fractals have widened the dimension concept into fractal-valued dimensions. Al-
though the fractal dimension concept is not necessary in order to understand the
codes, I have added the appendix Fractal Dimension, because fractal dimensions con-
tribute to characterizing fractals. Moreover, fractal dimension gives meaning to the
19th century ‘monstruous’ plane-filling curves.
Fractals were invented in the 20th century, and became the geometry of this cen-
tury due to the development of computers, because computers are the tools for view-
ing and researching fractals.
The ancestor of fractals is the 1D Cantor Dust. 2D predecessors of fractals are
the plane-filling curves named after Peano, Hilbert, Sierpiński, … , which captivated
mathematicians in the late 19th and the early 20th century.
Sierpiński curves have found their niche in the solution of the travelling salesman
problem.
In the sequel Lévy, von Koch, Kronkel (Dutch, means twist), Minkowski, Dragon
curve, star fractals, and a variant of the Game of Life are discussed. There are 4 ap-
pendices: the first about Fractal Dimension, the second about the historical Cantor
Dust, the third about the classical Hilbert curve, and the last about Sierpiński islands.
In the footsteps of Lauwerier, the reader is invited to experiment with the PS
programs, of which defs are supplied in my PSlib.eps library, which I’ll send on
request. MetaPost aficionados may translate the included Metafont codes into Meta-
Post, I presume.
Lévy fractal
An approximation of the Lévy fractal is also called a C (broken) line of a certain
order. The constructive definition of various orders of C lines starts with a straight
line, let us call this line C0 . An isosceles triangle with angles 45∘ , 90∘ and 45∘ is
built on this line as hypotenuse. The original line is then replaced by the other two
sides of this triangle to obtain C1 . Next, the two new lines each form the base for
another right-angled isosceles triangle, and are replaced by the other two sides of
their respective triangle, to obtain C2 . After two steps, the broken line has taken the
appearance of three sides of a rectangle of twice the length of the original line. At
each subsequent stage, each segment in the C figure is replaced by the other two
sides of a right-angled isosceles triangle built on it. Such a rewriting relates to a
Lindenmayer system. After n stages the C line has length 2n/2 × C0 : 2n segments
each of size 2−n/2 × C0 .
Fractals have various infinite lengths. The question arose: Can these blends of ∞
be used to characterize fractals?2 Below C0 … C6 and C10 have been constructed
from the definition.
Classical Math Fractals in PostScript VOORJAAR 2013 51
Properties
1a. The above sequence of curves loosely obey
Ci = C45 −45
i−1 ⊕ Ci−1 , i = 1, 2, … C0 = segment
⊕ means spliced i−1 means rotated over 45 .
C45 ∘
p0 = C 0 , p45 −45 → p
i ⊕pi i+1 , for i = 0, 1, 2, … with ⊕ the splice operator.
2. In the pen-plotter days the natural question arose: What is the direction of a
segment? Lauwerier(1987) gives the intriguing relationship between the an-
gle ϕk of a segment and its index k (according to the orientation as given un-
der 1b).
π
ϕk = (sk mod 4) with sk = ∑p−1 b
j=0 j
sum of bimals of k
2
p−1
and k = ∑j=0 bj 2
j binary representation of k.
3. The Lévy fractal has fractal dimension 2, a local plane-filling curve, Lauw-
erier(1990). The C curves intersects themselves from order 4 onward.
The PostScript program
One might create an efficient recursive backtracking program based on property 1a,
as a levyC def with the def given below. Scaling is commented out; just remove the
two % signs if scaling is wanted.
%!PS-Adobe-3.0 EPSF-3.0
%%Author: Kees van der Laan
%%Date: april 2011
%%Affiliation: kisa1@xs4all.nl
%%BoundingBox: -1 -1 346 61
%%BeginSetup %crops to BoundingBox
%%EndSetup %by Acrobat Pro
%%BeginProlog%collection of defs
/levyC{%on stack: the order ==> C line
52 MAPS 44 Kees van der Laan
The above mean-and-lean PS def is the result of programming in the spirit of The
Art of Computer Programming, TACP for short. I’ll come back on a more systematic
approach of programming based on production rules, a little further on.
If the levyC def is included in the PSlib.eps library, then the above def can be
replaced by
(C:\\PSlib\\PSlib.eps) run
This feature of the run command is not generally known, so it seems.
Because programming in PostScript is subtle, I have included below the PS def
based on the production rule as stated under property 1b, which is highly similar to
the above backtracking process, but the result differs in orientation. This levyCvar
def is also included in PSlib.eps.
/levyCvar{%order on stack ==> C line
%s = size of segment (global))
dup 0 eq
{0 0 moveto s 0 lineto
currentpoint stroke translate}%draw line
{1 sub %lower order on stack
levyCvar %C line
-90 rotate levyCvar 90 rotate %rotated C line
1 add %adjust order on stack
}ifelse }def
To run the program store the file with extension .eps (or .ps), right-mouse click
the thumbnail of the file and choose the option convert to Adobe PDF in the pop-up
menu. That is all when you have installed Acrobat Pro 7. (Other versions of Creative
Suite ask for open in Acrobat.) I also used Adobe Illustrator and PSView. The latter
just by double-clicking the filename upon which the command window opened and
a little later PSview.3
The Turtle Graphics algorithm is based on property 2. In order to understand the
formula mentioned, a table for the direction (with orientation as mentioned under
property 1b) of each segment is included. Such a table forms the basis for discovering
the regularity.
Classical Math Fractals in PostScript VOORJAAR 2013 53
k
order 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 →
1 → ↓
2 → ↓ ↓ ←
3 → ↓ ↓ ← ↓ ← ← ↑
4 → ↓ ↓ ← ↓ ← ← ↑ ↓ ← ← ↑ ← ↑ ↑ →
sk mod 4 0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 0 …
Below I have included Lauwerier’s program and my conversion in PS, which is in-
teresting because of the transformation of the user space by ϕk , k = 0, 1, 2, … .
In my PWT guide of 1995, I did program the above Lévy fractal in TEX (orientation
1b) by the Turtle graphics method, in the footsteps of Knuth. Nowadays, I much
prefer the much more powerful and useful PostScript for programming my graphics.
Sorry to say so, but Knuth put me on the wrong track by his graphics in the TEXbook.
Lindenmayer enriched by PostScript concepts for the Lévy fractal
What we miss in the 1a property specification is the scaling to smaller size of the
segments when the order increases, as well as a more precise meaning of what spliced
entails. A more accurate and improved production rule à la 1a, can be obtained when
we use PS concepts in the production rule at the expense of simplicity.
54 MAPS 44 Kees van der Laan
Cn = [R45 S( 1
, 1 ) Cn−1 ] ⊕ T s s [R−45 S( 1
, 1 ) Cn−1 ]
√2 √2 2 2 √2 √2
...
...
.
..
.....
....
.....
.... ...
..
..
.
..
..
..
..
....
...
...
..
.
..
..
...
.
..
.
..
...
..
.
....
......
.....
. ..
..
.
...
.....
.....
.
.
.
.
.
....
..
....
....
......
..
..
.......
....
...
....
....
..
.
..
.
..
.
..
..
..
.
...
..
.
..
.
.
.
..
.
...
..
...
.
.
.
........
......
......
..
...
...
.
...
.
.
..
.
....
........
...
....
......
.......
. ....
......
...
. .
..
..
......
.....
..........
.
.
..
.
.....
..
.
..
..
...
....
..
.
....
....
.
.
....
....
..
.... .
..
..
.. .
... .
.......
..
...
..
..
...
..
........
..
..
....
...
..
...
....
..
.
.....
...
...
......
....
.....
.
..
....
.
.....
...
...
.......
......
. ......
......
....
..
.
.
...
....
..
........
........
....
.
..
...
.....
....
..
..
....
.
...
..
....
....
......
..
..
..
....
.......
.......... ..
.
..
..
...
.
.
.
..
..
..
.
..
....
..
.....
..
.....
....
...
..
..
...
..
..
....
.
.
...
.
.
.
.
...
.....
....... ...
..
....
...
.....
.
...
. .
...
.....
...
..
....
.
...
... ... .
..........
. .....
. . ..
.. ..
...
..
.. ..
...
.
..
.
.
..
.
...
.......
... ... .. .
x′ L a −b x a−1
= + and
( y′ ) (b a )(y) ( b )
x′ R c −d x 1−c
= + , a = .5, b = a = c = −d.
( y′ ) (d c )(y) ( −d )
Associated with the Lévy fractal are 2 rotations with rotation centres for L: (-1,0)
and for R: (1,0) and contraction √.5 ≈ .7. Amazing, isn’t it! Laurier’s BASIC program
FRACMC2 and my conversion are given below.
Classical Math Fractals in PostScript VOORJAAR 2013 55
Properties
1. Each von Koch curve contains 4 copies of the von Koch curve of an order lower,
meaning self-similarity, which entails the production rule
Ki = Ki−1 ⊕ K60 −60
i−1 ⊕ Ki−1 ⊕ Ki−1 ,
π
ϕk = ((sk + 1)mod 3 − p) with sk = ∑p−1
j=0 j
q sum of quatermals of k
3
p−1
and k = ∑j=0 qj 4j quaternary representation of k.
5. The von Koch island remains within the circumscribed circle of the initial trian-
gle (see later).
The PostScript def is an efficient and concise implementation of the above specified
rewrite under property 1, neglecting scaling.
/vonKoch{%on stack order >=0; ==> von Koch
%s = size of the line segment (global)
dup 0 eq
{0 0 moveto s 0 lineto currentpoint stroke translate}
{1 sub vonKoch %lower the order on the stack and do von Koch
60 rotate vonKoch
-120 rotate vonKoch
60 rotate vonKoch
1 add %reset order
}ifelse}def
Note that in PS we have to convert the subscript expression for the index of an array
explicitly into integer. Another difference is that the arguments of the trigonometric
functions are in degrees in PS and in radians in BASIC.
Classical Math Fractals in PostScript VOORJAAR 2013 57
A von Koch island is a closed splicing of von Koch fractals; at right a von Koch tile
(van der Laan(1997)).
%!PS-Adobe-3.0 EPSF-3.0
%%Title: von Koch triangular island
%%...
/s 100 def
gsave .5 s mul dup neg exch translate 3 vonKochfractal pop
grestore
gsave .5 s mul dup translate
-120 rotate 3 vonKochfractal pop grestore
gsave 0 -.366 s mul translate
-240 rotate 3 vonKochfractal pop grestore
.001 setlinewidth 0 21 57.8 0 360 arc stroke
showpage
%%EOF
Lindemayer system enriched with PostScript concepts for the von Koch
fractal
What we miss in the program is the scaling to smaller size of the segments when the
order increases, as well as a more precise meaning of what spliced entails. A more
precise production rule enriched with PS concepts reads
Kn = [S 1 1 Kn−1 ] ⊕ T s 0 [S 1 1 R60 Kn−1 ] ⊕ T s s√3
3 3 3 3 3 6 6
with
K0 the initial line,
Kn the von Koch curve of order n,
⊕ splice operator, meaning add properly, i.e. translate,
[ open a new GS on the GS stack,
] remove current graphics state from the GS stack and recall previous,
R60 means rotate US 60∘ in the PS sense,
Sa,b means scale US by a and b, in x- and y-direction
Ta,b means translate US by a and b, in x- and y-direction.
The above PS production rule transcribes systematically into the following PS def.
!PS-Adobe-3.0 EPSF-3.0
%%Author: Kees van der Laan
%%Date: feb 2012 order=0 order=1 order=2 order=3 order=4
...
/vonKoch{%on stack: the order => von Koch curve
%s = size of initial line segment C_0 (global)
dup 0 eq
{0 0 moveto s 0 lineto currentpoint stroke translate}
{1 sub %adjust order on the stack
gsave .3333 dup scale vonKoch grestore
.3333 s mul 0 translate
gsave 60 rotate .3333 dup scale vonKoch grestore
.1666 s mul .285 s mul translate
gsave -60 rotate .3333 dup scale vonKoch grestore
.1666 s mul -.285 s mul translate
gsave .3333 dup scale vonKoch grestore
1 add %reset order on the stack
}ifelse
}def
58 MAPS 44 Kees van der Laan
x′ L a b x a−1
= + and
( y′ ) (b −a ) ( y ) ( b )
x′ R c d x 1−c
= + , a = .5, b = .289, c = a, d = −b.
( y′ ) (d −c ) ( y ) ( −d )
Associated with the von Koch fractal are 2 rotations with mirroring with centres
for L: (-1,0) and for R: (1,0) and contraction .52 + .2892 ≈ .58. Amazing, isn’t it!
Laurier’s BASIC program FRACMC4 and my transcription are given below. (MC is ab-
breviation for Monte Carlo, meaning alternate L and R by gambling.)
REM ***iteratief systeem, 2 spiegelingen, FRACMC4***
REM ***coefficienten***
A=.5 : B=..289 : C=A : D=-B
DET1=A*A+B*B : DET2=C*C+D*D : Q=DET1/(DET1+DET2)
X=1 : Y=0 : K=0 : KMAX=1000
DO WHILE K<KMAX AND INKEY$=" "
R=RND
IF R<Q THEN
X1=A*X+B*Y-1+A : Y1=B*X-A*Y+B 'spiegeling L
ELSE
X1=C*X+D*Y+1-C : Y1=D*X-C*Y-D 'spiegeling R
END IF
X=X1 : Y=Y1
PSET (X,Y),10
K=K+1
LOOP : BEEP
END
Other values of the parameters
a=.5 b=.5 c=.6667 d=0 %bebladerde tak
a=.5 b=.289 c=.5 d=-.289 %von Koch
a=.5 b=.5 c=.5 d=0 %kale tak
a=.5 b=.5 c=.6 d=-.2
a=0 b=.64 c=0 d=-.64 %tegelpatroon
Classical Math Fractals in PostScript VOORJAAR 2013 59
%!PS-Adobe-3.0 EPSF-3.0
%%Title: fracmc4
%%Author: H.A. Lauwerier(1994): Spelen met Graphics en Fractals
%%Transcriptor: Kees van der Laan, febr 2012
%%BoundingBox: -100 -1 103 60
%%BeginSetup
%%EndSetup
%%BeginProlog
/Courier 7 selectfont
/x 1 def /y 0 def /halfmaxint 2 30 exp def/maxint 2 31 exp 1 sub
def
/a .5 def /b .289 def /c a def /d b neg def
/det1 a dup mul b dup mul add def /det2 c dup mul d dup mul add
def
/q det1 det1 det2 add div def
/printxy {x s y s moveto (.) show}def
%%EndProlog
10 srand%10 is seed
/s {100 mul }def%scaling
1000{rand maxint div q lt
{/xnew a x mul b y mul add 1 sub a add def
/y b x mul a y mul sub b add def /x xnew def%mirror L
}
{/xnew c x mul d y mul add 1 add c sub def
/y d x mul c y mul sub d sub def /x xnew def%mirror R
}ifelse
printxy
}repeat
showpage
%%EOF
%!PS-Adobe-3.0 EPSF-3.0
%%Title: von Koch Random fractal, 2012
%%Author: Kees van der Laan, kisa1@xs4all.nl
%%BoundingBox: -5 -125 650 15
%%BeginSetup
%%EndSetup
%%BeginProlog
/vonKoch{dup 0 eq
{0 0 moveto s 0 lineto currentpoint stroke translate}
{1 sub vonKoch
pm{ 60 rotate vonKoch
-120 rotate vonKoch
60 rotate vonKoch}
{ -60 rotate vonKoch
120 rotate vonKoch
-60 rotate vonKoch}ifelse
1 add
}ifelse
}def
22121943 srand
/pm{rand 1073741823 gt{true}{false}ifelse}def
%%EndProlog
%
%Program ---the script---
/s 5 def % s = initial size of line piece
1 vonKoch pop % order 1
2 s mul 0 translate 2 vonKoch pop
3 s mul 0 translate 3 vonKoch pop
showpage
60 MAPS 44 Kees van der Laan
A triangular island (0, 0), (1, 0) (.5, .866) (0, 0) can equally-well be specified, with the
broken model line (0, 0), (.5, 0), (.375, .2165), (.5, 0), (.625, .2165), (.5, 0).
The degenerate Lévy island can be specified by the line (-1, 0), (1, 0), with the
(broken) model line (0, 0), (.5, 0)
%...
(C:\\PSlib\\PSlib.eps) run
%globals s, u, a, b, v, c, d order=0 order=1 order=2 order=3 order=4
/s {30 mul} def
/u 1 def /a [ -1 s 1 s ] def%abcissae corners line (scaled)
/b [ 0 0 ] def%ordinates corners line (scaled)
/v 2 def /c [ 0 .5] def %abcissae corners broken model line
/d [ 0 0 ] def %ordinates corners broken model line
0 kronkel stroke
110 0 translate 1 kronkel stroke
%...
showpage
%%EOF
Minkowski fractal
Much similar to the von Koch fractal is the Minkowski fractal, called sausage by
Mandelbrot. The replacement scheme can be distilled from the illustration below,
especially M0 → M1 .
10 REM ***Sausage of Minkowski***
10 DIM A(7) : A(0)=0 : A(1)=1 : A(2)=0 : A(3)=3
20 A(4)=3 : A(5)=0 : A(6)=1 : A(7)=0
30 P=3 : DIM T(P) : REM***order***
20 H=4^(-P) : X=0 : y=0: PSET (0,0)
30 FOR N=0 TO 8^P-1
40 M=N : FOR L=0 TO P-1
50 T(L)=M MOD 8 : M=M\8 : NEXT L
62 MAPS 44 Kees van der Laan
log 8
The fractal dimension of the Minkowski fractal D = log(1/4 −1 ) = 1.5. The array a
Minkowski island The essentials of the island program in PS are given below.
%!PS-Adobe-3.0 EPSF-3.0
%%Title: Minkowski island
%%...
/l 200 def 4 mink
gsave l 0 translate -90 rotate 4 mink grestore
gsave l l neg translate -180 rotate 4 mink grestore
0 l neg translate -270 rotate 4 mink
showpage
%%EOF
Dragon figures
1 1 1 1
-1
1 1 -1 -1 1
-1 -1 1 -1
1
1
1
-1 -1 -1
1
1
The curve with rounded 90∘ corners is named Dragon curve by Heighway. The
curve does not intersect itself. A nice example for developing the mathematical prob-
lem solving attitude in discovering the intriguing pattern. (Be aware of folding con-
sistently in the right direction.)
Classical Math Fractals in PostScript VOORJAAR 2013 63
Let us set up a table, where for each line piece the continuation angle is given: r
means rotate −90∘ , and l means rotate 90∘ , and unearth the regularity in the direc-
tions d(n), for n = 1, 2, 3, …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
r r l r r l l r r r l l r l l r r r l r r l l l r r l l r l l r
d(n) = r(igℎt) for n = 1, 5, 9, … d(n) = l(eft) for n = 3, 7, 11, … d(n) = d(n⁄2)
for n is even.
Express n in the form k × 2m where k is an odd number. The direction of the nth
turn:
if k mod 4 = 1 then the nth turn is r;
if k mod 4 = 3 then the nth turn is l.
The direction of turn 76376: 76376 = 9547 × 8 & 9547 mod 4 = 3 → d(76376) = l.
For the order p =14 and angle 90∘ I reproduced Lauwerier’s result in PS, see below
at left.
The number of line pieces is 2p . The curve of order 10 with rounded corners is at
right. The curves don’t intersect themselves, which is seen in the figure with rounded
corners. (In Lauwerier’s program the direction D is not in agreement with the folded
paper and the dragon figure. This is adapted in the PS code.)
Knuth in the TEXbook Appendix D p390 also mentions the dragon curve in rela-
tion to Turtle Graphics, and draws dragon figures in TEX. When I tried the order 12
in TEX, in 1995, TEX gave the error message ‘TEX capacity exceeded.’
64 MAPS 44 Kees van der Laan
(Courtesy http://en.wikipedia.org/wiki
..
..
...
...
. .. .
..
...
..
...
...
...
. ..
..
. ..
....
....
...
..
.
..
. .
..
...
..
..
.
.
..
.
..
..
.. .
..
.
.
..
.
. .
....
..
..
. ......
....
...
..
...
...
.
...
....
.. ....
...
. ..
....
..
.
...
..
.
..
.
.....
.
..
..
.....
..
. ..
.... .. .. .. ..
..
...
. .
........ ..
...
..
. . ..
....
....
....
..
.. ....
.
.. ..
....
.. ..
.
..
...
..
....
..
.
..
.. ... ..
. .
.
.
.
..
..
..
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
..
.
.
.
.
.
.
.
.
.
..
.
..
. ..
...
....
.....
..
.
.
..
..
...
.
.... ..
.
.
..
.
.
.
.
.
.
.
.
.
.
.
.
.
..
.
.
..
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
..
.
.
.
..
.
.
.
.
..
.
.
.
.
...
.
.. ..
..
. ... .... .
..
.
.
...
..
.
..
.
..
....
.
.
..
.
.
.
..
.
.
.
..
.
.
.
..
.
.
.
..
.
.
.
..
.
.
.
..
.
.
.
..
.
.
.
....
..
.
.
...
.. ..
...
.
.
.
..
...
..
..............
..
. .. .
The Dragon curve can be generated similarly to the rewriting scheme of the Lévy
fractal, with parts rewritten mirrored.
Star fractals
As introduction a generalization of the program star of the Blue Book p51. The pro-
gram is more general because it allows to draw the pentagram or the 5-star depend-
ing on the value of the angle parameter. Moreover, the number of vertices can be
varied, to obtain for example a heptagon casu quo 7-star (heptagram).
/gonstar%p (order) v ==> star
{gonstardict begin /v exch def /angle exch def
0 0 moveto
v{angle rotate l 0 rlineto}repeat closepath
end} bind def
/gonstardict 2 dict def
%%EndProlog
%
%Program ---the script---
%
/l 100 def 144 5 gonstar stroke
gsave 75 -25 translate
/l 50 def 1.415 setmiterlimit
72 5 gonstar stroke grestore
gsave 0 -110 translate
/l 100 def 1080 7 div 7 gonstar stroke
grestore
gsave 65 -130 translate
/l 35 def 1.415 setmiterlimit
360 7 div 7 gonstar stroke
showpage
Lauwerier’s ingenious, concisely programmed star fractal illustrations, left and right
below, consist also of 1 (broken) line.
Classical Math Fractals in PostScript VOORJAAR 2013 65
Game of Life
Lauwerier(1990) mentions a fractal which he obtained from the Pickover variant of
the Game of Life, made popular by Martin Gardner in a Scientific American in 1970.
The game is played on a grid. Each node can be alive or dead. Once alive it stays alive.
If dead it comes to life if only one neighbour, N, E, S or W is alive. On each heartbeat
the whole grid is inspected in parallel. Lauwerier’s BASIC program is given below.
***naam: PICK1***
40 DEFINT I, J, K, N, T, X, Y
70 IF SCR=9 THEN XM=320 : YM=175
80 IF SCR=12 THEN XM=320 : YM=240
100 INPUT "NUMBER OF ROWS=", N
120 DIM X(N,N), Y(N,N)
130 X(0,0)=1
140 FOR K=1 TO N-1
150 FOR I=0 TO K : FOR J=0 TO K-I
160 IF X(I,J)=0 THEN GOSUB 220 ELSE GOSUB 270
170 NEXT J : NEXT I
180 FOR I=0 TO K : FOR J=0 TO K-I
190 X(I,J)=Y(I,J)
200 NEXT J : NEXT I : NEXT K
210 A$=INPUT$(1) :END
220 IF I>=1 AND J>=1 THEN T=X(I+1,J)+X(I-1,J)+
X(I,J+1)+X(I,J-1)
230 IF I=0 AND J>=1 THEN T=2*X(1,J)+
X(0,J+1)+X(0,J-1)
240 IF I>=1 AND J=0 THEN T=2*X(I,1)+
X(X+1,0)+X(I-1,0)
250 IF T=1 THEN Y(I,J)=1
260 RETURN
270 PSET (XM+2*I, YTM-2*J),14 : PSET (XM-2*I, YM-2*J),14
280 PSET (XM+2*I, YTM+2*J),14 : PSET (XM-2*I, YM+-2*J),14
290 RETURN : END
. .... . . .
...... .............
.
If we start with 1 alive node then the generations 1, 2, 3, 4 look as follows
%!PS-Adobe-3.0 EPSF-3.0
%%Title: Growth Cell model a la Pickover, simplified
%%Author: Kees van der Laan
...
%%Date: March 2012
%%BoundingBox: -195 -195 195 195 .. . .............................
... .... ...
%%BeginSetup
. .. ...........................................................
%%EndSetup
...... ......... .....
%%BeginPrologue
.. .
. .................. ......................................... ......................
%%DocumentFonts: Times-Roman .. .. .. .. .. .. .. ... .. .. .. .. .. .. ..
/Times-Roman 20 selectfont
... ......................................................................................
/printdot{3 i mul -3 j mul moveto (.) show .......... ... ..... ...
........ ....................... ...........
............
3 i mul +3 j mul moveto (.) show . ......... .............. . .. ......... .........
......... . ...... ......................................... ................
-3 i mul -3 j mul moveto (.) show
-3 i mul +3 j mul moveto (.) show . . .
....... .......... .......... .................. .......... .............. .............
. . . . . .
.
. . . .. . . . . . . . . . . . . . . . . . . . . . . . . .. . . .
}def ...... ..... ...... ...... ...... ...... ...... .......... ...... ...... ...... ...... ...... ..... ......
/alive?{%check whether cell has become alive .........................................................................................................................................................................................................................................................................................
i 1 ge j 1 ge and ...... ...... ...... ...... ...... ...... ...... .......... ...... ...... ...... ...... ...... ...... ......
........... ........... ........... ..................... ............ ........... ...........
{ax i 1 sub n mul j add get ...... .... ...... ....... ... .... ....
ax i n mul j 1 sub add get add}if .......................... .................................................... ............................
i 0 eq j 1 ge and ...... ...... ...... .......... ...... ..................
{2 ax n j add get mul
........... ..................... .........
...... ..........
ax j 1 sub get add}if ................................................................................................
i 1 ge j 0 eq and{ax i 1 sub n mul get}if ...... ...... ...... .......... ...... ...... ......
1 eq{ax i n mul j add 1 put printdot}if ........... ..................... ...........
...... ....... ....
}def%alive? ...................................................
/pickover{% stack integer>=0 the order==> cell pattern ...... .......... ......
/n exch def .....................
/ax n 1 add dup mul array def %array
..........
1 1 n n mul{/k exch def ax k 0 put}for ax 0 1 put%initialize
/i 0 def /j 0 def printdot
1 1 n 1 sub {/k exch def
0 1 k{/i exch def /j k i sub def%contradiagonal
alive?
}for%i
}for%k
}def
%%EndProlog
%
% Program
%
64 pickover showpage
%%EOF
The point Lauwerier wanted to make — the game yields fractal patterns — is also
obtained by this simplified game.
Annotated References
- An introductory survey: http://en.wikipedia.org/wiki/Dragon_curve.
- Adobe Red, Green and Blue Books. The musts for PS programmers.
- Biography of H.A. Lauwerier: http://bwnw.cwi-incubator.nl/cgi-bin/uncgi/alf.
- Gleisk, J(1987): CHAOS — making a new science. Penguin.
(An introduction to and survey of the world of non-linearity, strange attractors
and fractals.)
- Goossens, M(2007, sec ed) et. al.: LATEX Graphics Companion. ISBN 978 0 321
50892 8.
- Helmstedt, J(2011): A New Method of Constructing Fractals and Other Graphics.
The Mathematica Journal. (Nice examples of Lindenmayer systems, for which
Lauwerier’s KRONKEL can be used.)
68 MAPS 44 Kees van der Laan
Conclusions
It was pleasure, educative and inspiring to read Lauwerier’s booklets. Some of his
algorithms have found a wider audience by converting his BASIC codes into Post-
Script, hopefully.
I don’t know how to include the results of the BASIC programs elegantly in pub-
lications. The results of the PS programs can be easily included in pdf(La)TeX, Word,
… documents.
PS’ variable user space and recursion alleviated programming, with concise defs
and programs as readable as literature, but … be aware of its subtleness. PostScript’s
variable user space was the key to my adaptation of production rules. Because of PS’
subtleness not many people program in PS, I presume, or … do they consider it of
too low-level?
In programming self-similarity the awareness of orientation is paramount. I did
not find classical Math fractals in PS on the WWW, only one Sierpiński curve in Java.
Lauwerier’s analysis — associating binary, ternary, … tree structures with binary,
ternary, … numbers, is an eye-opener. In his, and my, programs all the self-similar
sub-curves are draw anew. In Metafont/-Post we could just build the paths and splice
them suitably into paths of higher order, as I did in the past with the Pythagoras Tree
in Metafont.
‘Het Wiskunde boek’ states that fractals have renewed and raised interest in Math-
ematics.
Before publishing consult the Wikipedia on aspects of the subject as well as Wol-
fram’s knowledge base http://www.wolframalpha.com.
TEX mark up For the symbols of the number systems I, N, Q, R, C, which curiously
are not provided for in plain TEX, I use the the AMS (blackboard) font msbm10.
L R
The = and = composed relational operators are marked up by \mathrel {\mathop
=^{\rm L}} and not by $\buildrel\rm L \over=$, TEXbook p437; the latter is OK for
the stacked composed symbol as such.
For typesetting tables \halign and the tabbing mechanism have been used
(TEXbook ch22). The 11-element of one of the tables needs an oblique line. I provided
for this in PS, which is simpler and not restricted by obliqueness. In 1995, in my PWT
guide, I used the GKP macros for this, which suffer from the same inconvenience as
LATEX’s picture environment: restricted obliqueness.
A blank line before display math yields too much white space! This blank line is
important, though, in order to avoid widows.
Locally I have used for parallel listings of program texts vbox-s next to each other,
which inhibits proper page breaks. I don’t know how to provide macros for lo-
cal elegantly marked up multi-column texts, which allow page breaks. (I also tried
\valign, alas in vain.) My inserted pictures suffer from the same inconvenience as in
Word: changing the text might disturb the layout, such that the pictures will become
ill-placed.
As known, I could not use footnotes from within a vbox; kludged around.
In TEXworks I used the Terminal font in the edit window with the pleasing effect
that comments remain vertically aligned in the .pdf window.
Conversion of my TEX script into Word made me (hands-on) aware of the differences
between TEX and Word. If you are after utmost accurate, user-controlled typeset
Mathematics then TEX is to be preferred. For bread and butter Mathematics Word
can do, especially with Cambria, I presume. I did not find in Word (MS equation
3.0) the possibility to discern between displayed Math and in-line Math. Tables in
Word are tricky, the WYSIWYG approach does not always yield the table layout you
are after. As in TEX I can’t make an appropriate 11-element. I could not handle the
inclusion of a PS made 11-element in Word. Program texts, as columns in a table,
70 MAPS 44 Kees van der Laan
don’t suffer from difficulties in allowing page breaks. A pre-index, as is usual with
hyper-geometric functions, I could not nicely typeset with MS equation 3.0.
Inclusion of the .jpg figures and .pdf objects went smoothly. I had to convert .png
objects. The inclusion of EPSF object option did not work on my PC, though the
option is available. It invoked Adobe Illustrator CS2 12.0.0 and fell silent. The same
EPSF invoked by AI directly worked. Maybe incompatible versions? Neglecting su-
perfluous spaces, which TEX does automatically, has been lost in the conversion. A
local change in Word might change the document more than local, beyond user con-
trol. I don’t know how to switch off, or change, pre-settings, such as: don’t underline
automatically WWW addresses, maybe by de-activating the option WWW addresses
as hyperlinks?
Conversion also entailed splitting up the original (concept) paper and rewriting
the parts into 2 new papers. Converting back into TEX, after changes were made, was
more difficult than converting into Word.
After I had finished I became aware of Acrobat Pro X which also converts .pdf
into a Word document.
Acknowledgements
Thank you Adobe for your maintained, adapted to LanguageLevel 3 since 1997, good
old, industrial standard PS and Acrobat Pro (actually DISTILLER) to view it, Don
Knuth for your stable plain TEX, Jonathan Kew for the TEXworks IDE, Hàn Thế Thành
for pdf(La)TEX, Hans Lauwerier for your nice booklets with so many inspiring ex-
amples of fractals.
Thank you Jos Willink for proofing, Wim Wilhelm for drawing my attention to
cellulaire automata, and the LATEX graphics environment asymptote which he in-
tegrated in TEXnicCenter; I don’t have experience with them, but they may be of
interest for LATEX users. MAPS editors for improving my use of English and Taco
Hoekwater for procrusting my plain TEX note into MAPS format.
Thank you Zinadia Nikolaevna Gulka for inviting me to submit a paper or two for
the ‘Informatsionnie Texnologii i Matematicheskoe Modelirovanie’ journal’, and her
co-worker for stimulating me to convert the TEX marked up ASCII source of an early
version of this note into the required Word. The invitation stimulated me to adapt
and revise the material. Thank you GUST for publishing a previous version of this
note in the BachoTEX2012 proceedings. Thank you Svetlana Morozova for prompting
me in the use of Word.
IDE My PC runs 32 bits Vista, with Intel Quad CPU Q8300 2.5GHz assisted by
8GB RAM. I visualize PS with Acrobat Pro 7. My PS editor is just Windows ‘klad-
blok (notepad).’ I use the EPSF-feature to crop pictures to their BoundingBox, ready
for inclusion in documents. For document production I use TEXworks IDE with the
plain TEX engine, pdfTEX, with as few as possible structuring macros taken from
my BLUe.tex — adhering minimal TEX markup. I use the Terminal font in the edit
window with the pleasing effect that comments remain vertically aligned in the .pdf
window.
For checking the spelling I use the public domain en_GB dictionary and hyphen-
ation patterns en_GB.aff in TEXworks.
Prior to sending my PDF’s by email the files are optimized towards size by Acrobat
Pro.
The bad news with respect to .eps into .pdf conversion is that the newest Acrobat
10 Pro X does not allow for the run command for library inclusion.
Classical Math Fractals in PostScript VOORJAAR 2013 71
Notes
1. Alas, the \psfig has been lost in pdfTEX. Happily, ConTEXt and LuaTEX allow
direct EPSF inclusion.
2. Lauwerier(1989) narrates what mathematicians thought about the ∞-concept
through the ages from the ancient Greeks onward.
3. Acrobat Pro X does not allow for the library inclusion via run, alas :-(. BASIC is
interactive, PS is batch-oriented.
4. Barnsley is famous for his fern fractal. In his later works he is more ambitious
and constructs fractals given a picture, on demand.
5. The ‘fixed-point’ of the production rule is the fractal. At right my old TEX code is
displayed with its result.
6. The ‘fixed-point’ of the production rule is the real fractal.
The PS code for Cantor Dust of order n has a similar production rule as for the von
Koch fractal:
CDn = [S 1 1 CDn−1 ] ⊕ [S 1 1 T 2s 0 CDn−1 ] with
3 3 3 3 3
CD0 the initial line,
CDn the Cantor Dust of order n,
⊕ splice operator, meaning add properly the second piece to the set,
[ open a new GS on the GS stack,
] remove current graphics state from the GS stack and recall previous,
Sa,b means scale US by a and b, in x- and y-direction
Ta,b means translate US by a and b, in x- and y-direction.
The above PS production rule transcribes systematically into the following PS def.5
%!PS-Adobe-3.0 EPSF-3.0
/cd%integer n>=0 ==> Cantor Dust of order n
{1 sub dup -1 eq
{0 0 moveto s 0 lineto stroke}
{gsave .3333 1 scale dup cd grestore
gsave .3333 1 scale 2 s mul 0 translate dup cd grestore
}ifelse 1 add
}def
%%EndProlog
%
% Program
%
%...
/s 300 def 4 cd pop
305 -2 moveto TR10 setfont (Cantor) show
0 -3 rmoveto TR7 setfont (4) show 0 -10 translate
%...
showpage
%%EOF
%Borrowed from BLUe's pic.dat
\newcount\x\newcount\y\newcount\width
\newdimen\unitlength
\def\E#1{\hbox to 0pt{\kern\x\unitlength
\vbox to 0pt{\vss\hrule width#1\unitlength
\kern\y\unitlength
}\hss
}\advance\x#1 }
\def\cf{\ifnum0=\width \fc\fi
{\E{\the\width}}\divide\width3
\advance\y-3
{\cf}\advance\x\width
\advance\x\width
{\cf}\relax}%
\def\fc#1\relax{\fi}%
$$\width243 \unitlength1pt
\x-\width \divide\x2
\cf$$
The ‘fixed point’ of the production rule is the Cantor Dust fractal. For just showing a
few approximations of the Cantor Dust the TEX code will do. Lauwerier(1987) provides
a tiny BASIC program KAM. He also associates the Cantor dust with the trinary number
system because the interval is divided in 3 pieces, repeatedly. The Cantor dust of [0, 1]
consists of the trinary fractions where only the digits 0 and 2 occur, Lauwerier(1987,
p26). An eye-opener!
Cantor Dust as IFS Lauwerier(1989, ch8) constructs the Cantor Dust of high order by
the IFS
74 MAPS 44 Kees van der Laan
and
L R
xn+1 = xn ⁄3 xn+1 = xn ⁄3 + 2⁄3 n = 0, 1, 2, … x0 = 1⁄3.
If you, kind reader, shrug shoulders about paying so much attention to such a tiny
problem, I can only say that if you don’t analyse tiny problems deeply, your solutions
of bigger problems will lack ingenuity.
Generalization to 2D yield the so-called Sierpiński carpets.
The algorithm reads: divide a square in 32 equal sub-squares and delete the middle,
or the middle cross, and do this repeatedly for the remaining 8 squares.
At the EuroTEX95 Bogusłav Jackowski showed his variant, probably in connection
with his mftoeps program, which transforms Metafont code into PS. (I did not use
mftoeps, because it was PC-biased, and I had a Mac Powerbook 150.) This was at the
time that MetaPost, the preprocessor for PS with Metafont-biased user-language, was
not yet released in the public domain.
In my opinion he was on the right track: PS is mandatory for graphics to be included
in documents. It is just a pity he did not pursue that PS alone, or better EPSF, is
suitable for constructing graphics to be included in documents. His collaborators, Pjotr
and Pjotr, pursued PS in PSview.
I programmed the Sierpiński carpet, it is not the gasket, in TEX and in Metafont
after the conference. For historical reasons I have included the programs below. The
black-and-white figure is created by TEX-alone on-the-fly. (I just copied it from the
revised 1996 FIFO-article, and see,… it still works. The MF program also still works on
my museum Mac Powerbook 150 of 1995!)
The picture at right has been borrowed from the WWW. It illustrates a generalization
of the good old Cantor Dust into 2.5D, also called Menger sponge. Both pictures are
more interesting and more beautiful than the original 1D Cantor Dust.
Classical Math Fractals in PostScript VOORJAAR 2013 75
tracingstats:=1;proofing:=1;screenstrokes; %
pickup pencircle scaled 1;
def sierpinskisquare (expr s, p)=
if s>5:unfill unitsquare scaled .333s
shifted (p+.333s*(1,1));
sierpinskisquare(.333s, p);
sierpinskisquare(.333s, p+(.333s,0));
sierpinskisquare(.333s, p+(.667s,0));
sierpinskisquare(.333s, p+(0,.333s));
sierpinskisquare(.333s, p+(0,.6673s));
sierpinskisquare(.333s, p+(.667s,.333s));
sierpinskisquare(.333s, p+(.667s,.667s));
sierpinskisquare(.333s, p+(.333s,.667s));
fi enddef;
%
s=100; fill unitsquare scaled s;
sierpinskisquare(s,origin);
showit;
end
\newdimen\x\newdimen\y\newdimen\size\newdimen\lsize
\def\sier{\ifdim\size<35pt \reis\fi
\divide\size3
{\sier}{\advance\x\size\sier}{\advance\x2\size\sier}%
{\advance\y\size{\sier}{\advance\x2\size\sier}}%
\advance\y2\size{\sier}{\advance\x\size\sier}%
\advance\x2\size\sier}
\def\reis#1\sier{\fi\putatxy\draw}
%with auxiliaries
\def\putatxy#1{\vbox to0pt{\vss
\hbox to0pt{\kern\x#1\hss}\kern\y}}
\def\draw{{\lsize\size\divide\lsize3
\rlap{\vrule height\size width\lsize
\vbox to\size{\hrule width\lsize height\lsize\vss
\hrule width\lsize height\lsize}%
\vrule height\size width\lsize}}}
$$\vbox to120pt{\vss
\offinterlineskip\size120pt\x=-.5\size\y0pt
\sier}$$
A PS program for a 2.5D Cantor Dust is cumbersome, because it has to deal with
projection and has to handle hidden lines.
% endplot
21
%Program ---the script--- end.
9
%
41
2 3 4 13
3
/s 10 def %size of segment
1 Hilbert pop
4
51
1 1 16
1
2
s 0 translate 2 Hilbert pop
2 s mul 0 translate 3 Hilbert pop
3 s mul 0 translate 4 Hilbert pop
showpage
%%EOF
Joseph’s code is a bit cryptic (but is similar to mine). He uses short names, which does
not make sense, makes the code difficult to read, which is considered a bad practice.
But, … he was on the right track, also with the use of colours via PS.
Conclusion. Such a simple(?) problem yielded already a few variants, of which most
suffer from bad readability, because they are not biased by a production rule, IMHO.
%!PS-Adobe-3.0 EPSF-3.0
%%Title: Sierpinski island Side, March2012
%%Author: Kees van der Laan
%% Affiliation: kisa1@xs4all.nl
%%BoundingBox:-1 -82 287 2
%%BeginSetup
%%EndSetup
%%BeginProlog
/s' s 1.4142 div def
/NE{0 0 moveto s' dup lineto currentpoint stroke translate}def
/SE{0 0 moveto s' dup neg lineto currentpoint stroke translate}def
/E {0 0 moveto s 0 lineto currentpoint stroke translate}def
/SideS{%on stack order >=1 ==> Sierpinski side
%s size of line segment (global)
1 sub dup 0 ge
{ dup SideS
SE
dup -90 rotate SideS 90 rotate
E
78 MAPS 44 Kees van der Laan
Sierpiński islands 0 … 3
For those who don’t own the 1975 book I have included Wirth’s program, translated
into Metafont in 1995.