{ Copyright by T. W. Lougheed 27 April 1981 } { This program plots a set of points given by the function Y = F(X). } { This is a plotting program that uses the graphic symbols of the VDP 80's VIO board. It puts the VIO board in the extended character set mode, plots all the points given, then returns to the original mode. All the magic with the screen takes place in the external module PLOT. All values of the points to be plotted are generated by the external function F. } { First version 20 August 1980 By T. W. Lougheed Dept. T. & A. Mechanics Thurston Hall, Cornell U. Ithaca, NY 14853 Last version 17 January 1981 } { This program is in the public domain and may not be sold by any person or corperation without express permission of the author. } PROGRAM GRAPH14; CONST VERSION = 14; ROWS = 23; { Number of rows used for graphics on the screen. } { Number of columns is assumed 80 see PLOT to change. } TYPE POINT = RECORD X, Y :REAL END; VAR C : CHAR; CENTER : POINT; DATA : ARRAY[ 1..100 ] OF POINT; DX, { Increment to make along X axis. } START, STOP, { First and last X values. } TOP, BOTTOM : REAL; { Largest & smallest Y values. } K, L : INTEGER; { Dummy indicies. } { This is the function to be plotted. } EXTERNAL FUNCTION F( X :REAL) :REAL; { This procedure plots an X,Y graph of the DATA points given on the screen. It handles the video itself, without outside help. } EXTERNAL PROCEDURE PLOT ( L : INTEGER; { Number of points to plot. } VAR DATA : ARRAY[ M..N :INTEGER ] OF POINT; ORIGIN : POINT; { Center of the axes -- if out-of-bounds it is set to lie at the upper corner of the screen. } X_MIN, X_MAX, { Bounds for X & Y values. If MIN <= MAX then .. } Y_MIN, { .. scaling is done automaticly for that axis. } Y_MAX : REAL ); { This procedure clears the video screen. } PROCEDURE CLEAR; { Writing controll-Z erases the screen. } BEGIN WRITE( CHR($1A) ) END; { The following procedure positions the cursor on the screen to the row & column indicated, using escape codes appropriate to an IMSAI VIO board. } PROCEDURE CURSOR( ROW, COLUMN :INTEGER); CONST OFFSET = $1F; { The VIO offsets all co-ordinates. } ESC = $1B; { ASCII character code. } VAR A, B : CHAR; BEGIN A := CHR( $1F + ROW ); B := CHR( $1F + COLUMN ); WRITE( CHR(ESC), '=', A, B ); END; { Prints the plotters sign-on message. } PROCEDURE SIGN_ON; BEGIN CLEAR; { Erase screen. } WRITELN; WRITELN( ' F U N C T I O N P L O T T E R (version ', VERSION, ') ' ); WRITELN; WRITELN; WRITELN( ' This program plots the value of the function "F" provided when the' ); WRITELN( 'program was linked. Note that the abscissa (X-axis) runs down the' ); WRITELN( 'screen and the ordinate (Y-axis) runs across: they are rotated ninety' ); WRITELN( 'degrees from the customary directions for plotting functions.' ); WRITELN; WRITELN( ' The program will now ask you for initial and final values of X and' ); WRITELN( 'extreem values for Y in order to determine the scales for the two axes.' ); WRITELN( 'After the plot is made you may start over, so if the plot does not' ); WRITELN( 'satisfy you, you may try again using different paramiters.' ); WRITELN; WRITELN; END; { This procedure querries the user for paramiters. } PROCEDURE PARAMITERS; BEGIN REPEAT WRITELN; WRITE( 'Where is the plot to start on the abscissa ? ', '(X axis) ' ); READ( START ); WRITE( ' ... and where is it to stop ? ' ); READ( STOP ); IF START = STOP THEN WRITELN( 'HOLD IT ! They''re the same. ' ); UNTIL START <> STOP; WRITELN; WRITE( 'Do you want automatic scaling ? (Y/N) ' ); READ( C ); WRITELN; IF C IN [ 'n', 'N' ] THEN REPEAT WRITE( 'What is the lower limit for plotted values ', 'along the ordinate ? (Y-Axis) ' ); READ( BOTTOM ); WRITE( ' ... and the upper limit ? ' ); READ( TOP ); IF BOTTOM = TOP THEN WRITELN( 'Wait a minute: They''re the same !' ); UNTIL BOTTOM <> TOP ELSE BEGIN BOTTOM := 0; TOP := 0 END; { Forces auto-scaling. } END; BEGIN { GRAPHICS. } { Introduce the program: } SIGN_ON; REPEAT PARAMITERS; { Find out where to start and stop, &c. } { Figure what the points ought to be. } WRITELN; WRITE( 'Calculating points ' ); L := 3*ROWS; DX := (STOP - START)/(L - 1); FOR K := 1 TO L DO WITH DATA[K] DO BEGIN WRITE('.'); IF K MOD 5 = 0 THEN WRITE( ' ' ); { Talley of points. } IF K MOD 50 = 0 THEN BEGIN WRITELN; WRITE( ' ':18 ) END; X := K*DX + START; Y := F(X); { This is the only appearance of "F" } END; WRITELN( ' Done. ' ); WRITELN; WRITE( 'Hit any key when you''re ready to see the plot.' ); READ( C ); { Dummy input. } { Call plotting routine. } { CENTER is the location of the origin -- if impropper it will default to the upper corner. } CENTER.X := 0.0; CENTER.Y := 0.0; { For the meaning of the paramiters, consult comments on PLOT. } PLOT( L, DATA, CENTER, START, STOP, BOTTOM, TOP ); WRITELN; REPEAT WRITE( 'Another plot ? (Y/N) ' ); READ( C ); WRITELN; UNTIL C IN [ 'y', 'Y', 'n', 'N' ]; UNTIL C IN [ 'n', 'N' ]; WRITELN; WRITELN( 'Normal end of program.' ); END .