MODULE MandelbrotVoyager;
(*
My voyage on the complex plane.
To compile the source on the Oxford Compiler:
obc MandelbrotVoyager.mod -o MandelbrotVoyager
and to run the native code:
./MandelbrotVoyager
Program needs some refinement.
All the best Ty Harness.
ref: Dynamical Systems and Fractals - Karl-Heinz Becker and Michael Dorfler
*)
IMPORT Out,XYplane;
(*Check your /usr/lib/obc/XYplane.m
has a screen widthxheight of 640x480 change accordingly*)
CONST H=480;
CONST W=640;
(*Complex Number*)
TYPE
Z = RECORD
Re,i : REAL;
END;
VAR
LLZ,URZ : Z;
dRe,di : REAL;
aspect : REAL;
Maxiter : INTEGER;
iter : INTEGER;
x,y,xx,yy,rr : REAL;
finished :BOOLEAN;
RetChar : CHAR;
PROCEDURE Init;
BEGIN
iter := 0;
finished := FALSE;
x := 0;
y := 0;
xx := 0;
yy := 0;
rr := 0;
END Init;
PROCEDURE Draw():CHAR;
VAR
i,j : INTEGER;
c : Z;
a : CHAR;
BEGIN
c := LLZ;
FOR j := 0 TO H-1 DO
FOR i := 0 TO W-1 DO
REPEAT
Calc(c);
test;
UNTIL (iter = Maxiter) OR finished;
(*Paint pixel black inside Mandlebrot Set*)
IF (iter = Maxiter) THEN XYplane.Dot(i,j,XYplane.draw);END;
c.Re := c.Re + dRe;
Init();
END;
IF j < H-1 THEN c.Re := LLZ.Re;END;
(*Dont reset the value at the end*)
c.i := c.i + di;
END;
a := XYplane.Key();
RETURN(a);
END Draw;
PROCEDURE Zoomer(percentage:REAL);
BEGIN
LLZ.Re := LLZ.Re*percentage;
LLZ.i := LLZ.i*percentage;
URZ.Re := URZ.Re*percentage;
URZ.i := URZ.i*percentage;
(*Complex Number to Pixel transformation step size*)
dRe := (URZ.Re - LLZ.Re) / W;
di := (URZ.i - LLZ.i) / H;
Init;
XYplane.Clear();
END Zoomer;
PROCEDURE Pan(panRe,pani:REAL);
BEGIN
LLZ.Re := LLZ.Re + LLZ.Re*panRe*0.01;
LLZ.i := LLZ.i + LLZ.i*pani*0.01;
URZ.Re := URZ.Re - URZ.Re*panRe*0.01;
URZ.i := URZ.i - URZ.i*pani*0.01;
Init;
XYplane.Clear();
END Pan;
PROCEDURE Calc(C:Z);
BEGIN
(*
Square the starting number
add to constant (complex) number
to equal the new number to be squared.
*)
iter := iter +1;
y := x*y;
y := y + y - C.i;
x := xx - yy + C.Re;
xx := x*x;
yy := y*y;
rr := xx + yy;
END Calc;
PROCEDURE test;
BEGIN
finished := (rr > 4);
END test;
PROCEDURE Writedestructions;
BEGIN
Out.String("Mandlebrot Set Zn+1 = Zn^2 + C");Out.Ln;
Out.String("Press s to stop and close Xwindow");Out.Ln;
Out.String("Press i to see current parameters");Out.Ln;
Out.String("Press + to zoom in");Out.Ln;
Out.String("Press - to zoom out");Out.Ln;
Out.String("Press l to pan Real axis left");Out.Ln;
Out.String("Press r to pan Real axis right");Out.Ln;
Out.String("Press u to pan imaginery axis up");Out.Ln;
Out.String("Press d to pan imaginery axis down");Out.Ln;
Out.String("Press n to reduce number of iterations");Out.Ln;
Out.String("Press m to increase the number of iterations CAREFUL NOW");Out.Ln;Out.Ln;
END Writedestructions;
PROCEDURE WriteInfo;
BEGIN
Out.String("Boundries of current plot");Out.Ln;
Out.Real(LLZ.Re); Out.String(" + i("); Out.Real(LLZ.i); Out.String(")");
Out.Ln;
Out.Real(URZ.Re); Out.String(" + i("); Out.Real(URZ.i);Out.String(")");
Out.Ln;
Out.String("Max Iterations:"); Out.Int(Maxiter,0);
Out.Ln;
END WriteInfo;
BEGIN (*Main*)
Writedestructions;
(*Aspect ratio for a non square XYplane W/H *)
aspect := W/H;
(*Set Inital Complex Plane Boundries*)
LLZ.Re := -2;
LLZ.i := -aspect;
URZ.Re := 1;
URZ.i := aspect;
(*Complex Number to Pixel transformation step size*)
dRe := (URZ.Re - LLZ.Re) / W;
di := (URZ.i - LLZ.i) / H;
Maxiter := 24;(*Sensible starting point for Raspberry Pi 2*)
Init;
XYplane.Open;
REPEAT
RetChar := Draw();
IF RetChar = "+" THEN Zoomer(0.9); END;
IF RetChar = "-" THEN Zoomer(1.1); END;
IF RetChar = "l" THEN Pan(-10,0); END;
IF RetChar = "r" THEN Pan(10,0); END;
IF RetChar = "u" THEN Pan(0,10); END;
IF RetChar = "d" THEN Pan(0,-10); END;
IF RetChar = "m" THEN Maxiter := Maxiter +1; END;
IF RetChar = "n" THEN Maxiter := Maxiter -1; END;
IF Maxiter <= 1 THEN Maxiter := 1;END;
IF Maxiter >= 64 THEN Maxiter := 64;END;
IF (RetChar = "m") OR (RetChar = "n") THEN XYplane.Clear; END;
IF RetChar = "i" THEN WriteInfo; END;
UNTIL "s" = RetChar;
Out.Ln;
Out.String("Finished - Bye");
Out.Ln;
END MandelbrotVoyager.