packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/demo/graftest.mod

MODULE GrafTest;

	(****************************************************************)
	(*								*)
	(*		Test of music and graphics.			*)
	(*								*)
	(*  Programmer:		P. Moylan				*)
	(*  Last edited:	7 March 1994				*)
	(*  Status:		Working					*)
	(*								*)
	(****************************************************************)

FROM Timer IMPORT
    (* proc *)	Sleep;

FROM MusicDemonstration IMPORT
    (* proc *)	WaitForEndOfMusic;

FROM Graphics IMPORT
    (* proc *)	SetMode, PlotMark, PlotLine;

FROM MATHLIB IMPORT
    (* proc *)	Sin, Cos, Sqrt, ATan;

(************************************************************************)

CONST colour = 1;
      stretch = 2.0;
      PI = LONGREAL(3.14159265358979323);

(************************************************************************)

PROCEDURE PlotScaledLine (x0, y0, x1, y1: LONGREAL);

    (* Draws a line from (x0,y0) to (x1,y1), with coordinates scaled to	*)
    (* the standards expected by procedure Triangle, below.		*)

    CONST xorg = 159.5;  yorg = 99.5;  scale = 99.5;

    VAR intx0, inty0, intx1, inty1: CARDINAL;

    BEGIN
	intx0 := TRUNC (stretch*(xorg+scale*x0)+0.5);
	inty0 := TRUNC (yorg+scale*y0+0.5);
	intx1 := TRUNC (stretch*(xorg+scale*x1)+0.5);
	inty1 := TRUNC (yorg+scale*y1+0.5);
	PlotLine (intx0,inty0,intx1,inty1,colour);
    END PlotScaledLine;

(************************************************************************)

PROCEDURE Triangle (x0, y0, side, theta, alpha: LONGREAL);

    (* Plots an equilateral triangle, starting at (x0, y0), with each	*)
    (* side being "side" units long, and tilted at angle theta to the	*)
    (* the horizontal.  The units are scaled such that the centre of	*)
    (* the screen is point (0.0,0.0), and side=1.0 gives the biggest	*)
    (* triangle which will fit in the first quadrant.  Part of the	*)
    (* second side is deliberately omitted - only the first "alpha" of	*)
    (* it (0<alpha<1) is plotted.					*)

    VAR x1, y1, x2, y2: LONGREAL;

    BEGIN
	x1 := x0 + side*Cos(theta);  x2 := x0 + side*Cos(theta + PI/3.0);
	y1 := y0 + side*Sin(theta);  y2 := y0 + side*Sin(theta + PI/3.0);
	PlotScaledLine (x0,y0, x1,y1);
	PlotScaledLine (x1,y1,(1.0-alpha)*x1+alpha*x2,(1.0-alpha)*y1+alpha*y2);
	PlotScaledLine (x2,y2, x0,y0);
    END Triangle;

(************************************************************************)

PROCEDURE FilledTriangle (k: CARDINAL);

    (* Plots a sequence of nested triangles, with the outer one		*)
    (* oriented at 60k degrees from the horizontal.			*)

    CONST alpha = 0.1;  small = 0.01;

    VAR xorigin, yorigin, side: LONGREAL;
	theta: LONGREAL;

    BEGIN
	xorigin := 0.0;  yorigin := 0.0;  side := 1.0;
	theta := LONGREAL(k)*PI/3.0;
	REPEAT
	    Triangle (xorigin, yorigin, side, theta, alpha);
	    xorigin := xorigin + alpha*side*Cos(theta);
	    yorigin := yorigin + alpha*side*Sin(theta);
	    theta := theta + ATan(alpha*Sqrt(3.0)/(2.0-3.0*alpha));
	    side := side * Sqrt(1.0 - 3.0*alpha*(1.0-alpha));
	UNTIL side < small;
    END FilledTriangle;

(************************************************************************)

PROCEDURE Hexagon;

    (* Plots an interesting hexagon shape. *)

    VAR j: [0..5];

    BEGIN
	SetMode (16, TRUE);
	FOR j := 0 TO 5 DO
	    FilledTriangle(j);
	END (*FOR*);
	Sleep (3000);
    END Hexagon;

(************************************************************************)

PROCEDURE Doyley (vertices: CARDINAL);

    (* Plots a polygon, with lines between all pairs of vertices.	*)
    (* Assumption: "vertices" is a prime number.  If not, the procedure	*)
    (* still does something but the resulting picture is not as		*)
    (* interesting.							*)

    CONST colour = 1;
	  stretch = 2.0;

    TYPE Subscript = [0..30];

    VAR previous, next: Subscript;
	step, j: CARDINAL;
	X, Y: ARRAY Subscript OF CARDINAL;
	xcentre, ycentre, radius, theta, angle: LONGREAL;

    BEGIN
	SetMode (16, TRUE);

	(* Set up the vertex coordinates in arrays X and Y. *)

	xcentre := 160.0;  ycentre := 99.5;  radius := 99.5;
	theta := 2.0*PI/LONGREAL(FLOAT(vertices));
	FOR j := 0 TO vertices-1 DO
	    angle := LONGREAL(j)*theta;
	    X[j] := TRUNC (stretch*(xcentre + radius*Cos(angle) + 0.5));
	    Y[j] := TRUNC (ycentre + radius*Sin(angle) + 0.5);
	END (*FOR*);

	(* Now the actual plotting. *)

	FOR step := 1 TO vertices DIV 2 DO
	    previous := 0;
	    FOR j := 1 TO vertices DO
		next := (previous + step) MOD vertices;
		    PlotLine (X[previous], Y[previous], X[next], Y[next],
								colour);
		previous := next;
	    END (*FOR*)
	END (*FOR*);

	Sleep (3000);
    END Doyley;

(************************************************************************)

PROCEDURE RunGraphicsTest;

    (* Runs us through a sequence of graphics tests.	*)

    VAR N: [3..23];

    BEGIN
	FOR N := 3 TO 23 BY 2 DO
	    Doyley (N);
	END (*FOR*);
	Hexagon;
    END RunGraphicsTest;

(************************************************************************)
(*				MAIN PROGRAM				*)
(************************************************************************)

BEGIN
    RunGraphicsTest;
    RunGraphicsTest;
    WaitForEndOfMusic;
END GrafTest.