language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/applications/multiscope/symmetry/symm3.mod
MODULE Symmetry;
(* Symmetric Chaos: three fold *)
(* See "Mathematical Recreations", Scientific American, December 1992 *)
(* J. Andrea, Dec.1992 *)
(* This code may be freely used and distributed, it may not be sold *)
FROM Randomly IMPORT RandomReal;
FROM VGAGraphics IMPORT BeginVGA, EndVGA, EraseScreen, Move, Dot, Text;
FROM Terminal IMPORT Read, ReadString, WriteString, WriteLn;
FROM RealConversions IMPORT StringToReal;
FROM RealInOut IMPORT WriteReal;
FROM Break IMPORT EnableBreak;
CONST
max_iter = 32000; (* maximum size for DOS *)
max_loop = 2; (* so do it again *)
nx = 640; ny = 480;
VAR
a, b, c, d :REAL;
x, x2, x3, y, y2, y3 :REAL;
u, v, f :REAL;
x_min, x_max, y_min, y_max, x_offset, y_offset, x_scale, y_scale :REAL;
i, j, k, iter, loop :CARDINAL;
ch :CHAR;
PROCEDURE Function;
BEGIN
x2 := x * x; x3 := x2 * x;
y2 := y * y; y3 := y2 * y;
f := a + b * (x2 + y2);
u := f * x + c * (x3 - 3.0 * x * y2) + d * (x2 - y2);
v := f * y + c * (3.0 * x2 * y - y3) - d * 2.0 * x * y;
x := u;
y := v;
END Function;
PROCEDURE GetValue( name, default :ARRAY OF CHAR; VAR out :REAL );
VAR
value :ARRAY [0..20] OF CHAR;
ok :BOOLEAN;
longout :LONGREAL;
BEGIN
WriteString( name ); WriteString( ' (default = ' );
WriteString( default ); WriteString( ') ? ' );
ReadString( value ); WriteLn;
IF value[0] = 0C THEN
StringToReal( default, longout, ok );
ELSE
StringToReal( value, longout, ok );
END;
IF ok THEN
out := longout;
ELSE
out := 0.0;
END;
END GetValue;
BEGIN EnableBreak;
GetValue( 'a', '2.5', a );
GetValue( 'b', '-2.5', b );
GetValue( 'c', '0.0', c );
GetValue( 'd', '-0.55', d );
WriteReal( a, 10 ); WriteString( ' ' ); WriteReal( b, 10 ); WriteString( ' ' );
WriteReal( c, 10 ); WriteString( ' ' ); WriteReal( d, 10 ); WriteLn;
WriteString( 'wait...' ); WriteLn;
x := RandomReal( 0.0, 1.0 );
y := RandomReal( 0.0, 1.0 );
x_min := x; x_max := x;
y_min := y; y_max := y;
FOR i := 1 TO 5000 DO
Function;
IF x < x_min THEN
x_min := x;
ELSIF x > x_max THEN
x_max := x;
END;
IF y < y_min THEN
y_min := y;
ELSIF y > y_max THEN
y_max := y;
END;
END;
(* change 10% *)
x_min := x_min - x_min / 10.0;
x_max := x_max + x_max / 10.0;
y_min := y_min - y_min / 10.0;
y_max := y_max + y_max / 10.0;
x_offset := x_min;
y_offset := y_min;
x_scale := FLOAT( nx ) / ( x_max - x_min );
y_scale := FLOAT( ny ) / ( y_max - y_min );
BeginVGA; EraseScreen;
FOR loop := 1 TO max_loop DO
FOR iter := 1 TO max_iter DO
Function;
i := TRUNC( ( x - x_offset ) * x_scale );
j := TRUNC( ( y - y_offset ) * y_scale );
IF ( i > 0 ) & ( i <= nx ) & ( j > 0 ) & ( j <= ny ) THEN
Move( i, j ); Dot;
END;
END; END;
Move( 600, 10 ); Text( 'done' );
Read( ch );
EndVGA;
END Symmetry.