_MAKING THE MOVE TO MODULA-2_ by J.V. Auping and Chis Johnston [LISTING ONE] DEFINITION MODULE ModPlot; (* Title : High level Modula-2 Graphics library interface Author : Judy Auping System : PC Graphics Compiler: LOGITECH MODULA-2/86 *) FROM DataDefs IMPORT DeviceType,UnitsType,SizeType,AngleType,LineType,ColorType, FontType,OriginType,SymbolType,ModeType,STRING80; EXPORT QUALIFIED GraphInit,SetPlotDevice,SetPlotArea,SetScaledArea,SetScale,SetUnits, SetCharSize,SetLabelAngle,SetLineType,SetPenColor,SetBackgroundColor, SetLabelOrigin,SetFixedDigits,ReturnRatio,SetFontType, Draw,Move,IncDraw,IncMove,DrawXAxis,DrawYAxis,DrawAxes,DrawGrid, DrawLabel,DrawLabelledAxes,DrawLabelledGrid,DrawFrame,DrawSymbol, Where,NewScreen,CloseGraphics; PROCEDURE GraphInit; (* Initializes system-MUST be called before any output generated *) PROCEDURE SetPlotDevice(GraphDevice: DeviceType); (* Selects output device for subsequent graphics commands *) PROCEDURE SetPlotArea(XMin,XMax,YMin,YMax: REAL); (* Sets the 'clip' area in % of absolute device boundaries*) PROCEDURE SetScaledArea(XMin,XMax,YMin,YMax: REAL); (* Sets the area in % of absolute device boundaries to which subsequent SetScale takes effect*) PROCEDURE SetScale(XMin,XMax,YMin,YMax: REAL); (* Sets the user scale *) PROCEDURE SetUnits(GraphUnits: UnitsType); (* Sets either User (Scaled units) or Device (absolute units) *) PROCEDURE SetCharSize(CharSize: SizeType); (* Sets character size for subsequent labels *) PROCEDURE SetLabelAngle(LabelRotation: AngleType); (* Sets the angle of rotation of subseqent labels *) PROCEDURE SetLineType(LineTypeSelected: LineType); (* Sets the line type for subsequent Draw commands *) PROCEDURE SetPenColor(PenColor: ColorType); (* Sets the pen color for subsequent output *) PROCEDURE SetBackgroundColor(BackgroundColor: ColorType); (* Sets the background color (screen only) *) PROCEDURE SetLabelOrigin(LabelOrigin: OriginType); (* Determines orientation relative to current position with which subsequent labels will be drawn *) PROCEDURE SetFixedDigits(XNumDigits,YNumDigits: CARDINAL); (* Sets number of digits to right of decimal point for subsequent DrawLabelledAxes or DrawLabelledGrid *) PROCEDURE ReturnRatio(): REAL; (* Returns the ratio of the physical dimensions of the plotting area of the current device *) PROCEDURE SetFontType(FontTypeSelected: FontType); (* Sets the font type for subsequent label commands *) PROCEDURE Draw(XCoord,YCoord: REAL); (* Draw a line from the active position to the specified coords *) PROCEDURE Move(XCoord,YCoord: REAL); (* Move the active position to the specified coordinates *) PROCEDURE IncDraw(XIncr,YIncr: REAL); (* Do an incremental draw from the active position *) PROCEDURE IncMove(XIncr,YIncr: REAL); (* Do an incremental move to the new active position *) (* In the following set of axis drawing and labelling procedures, the variables XIntercept, YIntercept, XTicSpacing, YTicSpacing XMin, XMax, YMin, and YMax are all interpreted according to the most recent SetUnits, SetScaledArea, and Set Scale commands. MajorCount is an integer that specifies the number of tic intervals between major tic marks. In DrawLabelledAxes and DrawLabelledGrid, if MajorCount is positive, tic marks are drawn perpendicular to the corresponding axis; if negative, tic marks are parallel. MajorTicFrac specifies the size of the major tics as a percentage of the length of the corresponding axis.*) PROCEDURE DrawXAxis(YIntercept,TicSpacing,XMin,XMax: REAL; MajorCount: INTEGER; MajorTicFrac: REAL); (* Draw an X-axis from XMin to XMax at the specified y-intercept*) PROCEDURE DrawYAxis(XIntercept,TicSpacing,YMin,YMas: REAL; MajorCount: INTEGER; MajorTicFrac: REAL); (* Draw a Y-axis from YMin to YMax at the specified x-intercept*) PROCEDURE DrawAxes(XIntercept,YIntercept,XTicSpacing,YTicSpacing: REAL; XMajorCount,YMajorCount: INTEGER; XMajorTicFrac,YMajorTicFrac: REAL); (* Draws full-scale axes intersecting at XIntercept and YIntercept*) PROCEDURE DrawGrid(XIntercept,YIntercept,XTicSpacing,YTicSpacing: REAL; XMajorCount,YMajorCount: INTEGER; XMinorTicFrac,YMinorTicFrac: REAL); (* Draws a full-scale grid, with lines spaced symmetrically around XIntercept,YIntercept *) PROCEDURE DrawLabel(LabelString: ARRAY OF CHAR); (* Writes LabelString at the current active position according to the current CharSize, LabelOrigin, and LabelRotation settings*) PROCEDURE DrawLabelledAxes(XIntercept,YIntercept,XTicSpacing, YTicSpacing: REAL; XMajorCount,YMajorCount: INTEGER; XMajorTicFrac,YMajorTicFrac: REAL); (* Draws a pair of axes in the same manner as DrawAxes. Puts labels at the major tic marks according to the current CharSize, XNumDigits, and YNumDigits settings *) PROCEDURE DrawLabelledGrid(XIntercept,YIntercept,XTicSpacing, YTicSpacing: REAL; XGridSpacing,YGridSpacing: INTEGER; XMajorTicFrac,YMajorTicFrac: REAL); (* Draws a full-scale grid as in DrawGrid and labels the grid lines as in DrawLabelledAxes *) PROCEDURE DrawFrame; (* Draws a box around the current plotting area *) PROCEDURE DrawSymbol(XCoord,YCoord: REAL; Symbol: SymbolType; Size: REAL); (* Draws the indicated symbol centered at XCoord,YCoord. Size is specified in mm *) PROCEDURE Where(VAR XCoord,YCoord: REAL); (* Returns the coordinate values of the current active position*) PROCEDURE NewScreen(Mode: ModeType); (* Clears the screen and sets the mode. No cursor in Menu mode*) PROCEDURE CloseGraphics; (* Cleans up the interrupts and restores to normal *) END ModPlot. [LISTING TWO] DEFINITION MODULE GDriver; (* Title : Low Level CRT and Plotter Draw module Author : Chris Johnston System : Modula-2 Plotting System Compiler: LOGITECH MODULA-2/86 *) FROM DataDefs IMPORT ModeType, STRING80, DevPresentType; EXPORT QUALIFIED ReadDevices, DrawAbs, MoveAbs, DrawString, SetMode, CleanUp; PROCEDURE ReadDevices(VAR DevicesPresent : DevPresentType); (* Finds out what devices are available: EGA/CGA and IBM7372A/IBM7372B/IBM7371. An HP 7470 is reported as an IBM7371 and the HP 7475 is reported as an IBM7372A or B depending upon the paper size selected *) PROCEDURE DrawAbs(XCoord, YCoord : CARDINAL); (* Draw a line from the current location to XCoord, YCoord on the selected device. Line type and color read from system globals *) PROCEDURE MoveAbs(XCoord, YCoord : CARDINAL); (* Move from the current location to XCoord, YCoord on the selected device with the pen raised. *) PROCEDURE DrawString(XCoord, YCoord : CARDINAL; LabelString : ARRAY OF CHAR); (* Draw the character string LabelString starting at XCoord, YCoord. The font, color, size, and rotation are selected from system globals *) PROCEDURE SetMode( Mode : ModeType); (* Set the mode to text or graphics and clear the screen. This call has ** NO EFFECT ** if the selected device is a plotter *) PROCEDURE CleanUp; (* clean up the interrupt drivers and the character set at the end. *) END GDriver. [LISTING THREE] DEFINITION MODULE DataDefs; (* Title : Data Definitions Author : Judy Auping System : PC Graphics Compiler: LOGITECH MODULA-2/86 *) EXPORT QUALIFIED DeviceType,UnitsType,SizeType,AngleType,LineType,ColorType, FontType,OriginType,SymbolType,DevPresentType,ModeType,STRING80, GraphDevice,LineTypeSelected,CharSize,FontTypeSelected, PenColor,BackgroundColor,LabelRotation,DeviceXMax,DeviceYMax, ErrorString, DriverError; TYPE DeviceType = (EGA,CGA,IBM7372A,IBM7372B,IBM7371); UnitsType = (User,Device); SizeType = (Small,Med,Large,XLarge); AngleType = (Deg0,Deg45,Deg90,Deg135,Deg180,Deg225,Deg270,Deg315); LineType = (Solid, EndPoint, Dotted, ShortDash, LongDash); ColorType = (Black,Blue,Green,Cyan,Red,Magenta,Brown,White, DarkGray,LightBlue,LightGreen,LightCyan, LightRed,LightMagenta,Yellow,IntensifiedWhite); FontType = (Standard,Italic); OriginType = (UpperRight,CenterRight,LowerRight,UpperMiddle, CenterMiddle,LowerMiddle,UpperLeft,CenterLeft, LowerLeft); SymbolType = (Circle,Square,Triangle,Asterisk,Cross,Plus); DevPresentType = ARRAY DeviceType OF BOOLEAN; ModeType = (Graphics,Text,Menu); STRING80 = ARRAY[0..79] OF CHAR; VAR GraphDevice: DeviceType; LineTypeSelected: LineType; CharSize: SizeType; FontTypeSelected: FontType; PenColor: ColorType; BackgroundColor: ColorType; LabelRotation: AngleType; DeviceXMax,DeviceYMax: CARDINAL; DriverError: BOOLEAN; ErrorString: STRING80; END DataDefs. [LISTING FOUR] MODULE Example; (* Title: Example of using the ModPlot graphics library Author: Judy Auping System: PC Graphics *) FROM DataDefs IMPORT DeviceType,SizeType,ColorType,OriginType; FROM ModPlot IMPORT GraphInit,SetPlotArea,SetScaledArea,SetScale,DrawAxes,SetPenColor, Move,Draw,DrawFrame,NewScreen,CloseGraphics,SetLabelOrigin,DrawLabel, SetCharSize,IncDraw,SetPlotDevice; FROM MathLib0 IMPORT sin; FROM InOut IMPORT Read,WriteString,WriteLn; TYPE CornerType = (UpLeft,UpRight,LowLeft,LowRight); CONST NPnts = 1000; pi = 3.14159; VAR XValue: ARRAY[1..NPnts] OF REAL; YValue: ARRAY [UpLeft..LowRight] OF ARRAY[1..NPnts] OF REAL; NumTerms: ARRAY[UpLeft..LowRight] OF CARDINAL; IPlot: CornerType; IPnt,ITerm: CARDINAL; x,NextTerm: REAL; Input: CHAR; PROCEDURE GeneratePlotArrays; (* This procedure generates arrays of data points for the Fourier series approximation of a sawtooth wave, where y = 2 (sin x - sin(2x)/2 + sin(3x)/3 - sin(4x)/4 + ... ) The XValue array contains the x values for the plot in units of pi, where the values vary from zero to 4pi. The YValue array of arrays contains four arrays of y values for different numbers of terms in the summation approximation. *) BEGIN WriteString("Generating approximation functions"); (* Inform user *) NumTerms[UpLeft] := 5; NumTerms[UpRight] := 10; NumTerms[LowLeft] := 20; NumTerms[LowRight] := 100; FOR IPnt := 1 TO NPnts DO IF (IPnt MOD 100)=0 THEN WriteString(" ."); (* Let the user know the progress of *) END (* if *); (* the calculations.*) FOR IPlot := UpLeft TO LowRight DO YValue[IPlot,IPnt] := 0.0; (* Initialize the terms. *) END (* for *); x := FLOAT(IPnt) * (4.0 * pi)/FLOAT(NPnts); XValue[IPnt] := x/pi; FOR ITerm := 1 TO NumTerms[LowRight] DO IF (ITerm MOD 2)=0 THEN (* even terms are negative *) NextTerm := -2.0 * sin(FLOAT(ITerm)* x)/FLOAT(ITerm); ELSE (* odd terms are positive,*) NextTerm := 2.0 * sin(FLOAT(ITerm)* x)/FLOAT(ITerm); END (* if *); FOR IPlot := UpLeft TO LowRight DO IF ITerm<=NumTerms[IPlot] THEN YValue[IPlot,IPnt] := YValue[IPlot,IPnt] + NextTerm; END (* if *); END (* for *); END (* for *); END (* for *); END GeneratePlotArrays; BEGIN GeneratePlotArrays; GraphInit; SetPlotDevice(IBM7372A); WriteLn; WriteString("Drawing plot . . ."); (*Let user know where we are*) FOR IPlot := UpLeft TO LowRight DO (*Draw a plot for each array*) CASE IPlot OF (* For each array, choose the appropriate plotting area*) UpLeft:SetPlotArea(0.0,45.0,60.0,100.0); (*Upper left corner *) SetScaledArea(5.0,40.0,62.0,94.0); |UpRight: SetPlotArea(55.0,100.0,60.0,100.0); (*Upper right corner*) SetScaledArea(60.0,95.0,62.0,94.0); |LowLeft:SetPlotArea(0.0,45.0,0.0,40.0); (*Lower left*) SetScaledArea(5.0,40.0,2.0,34.0); |LowRight:SetPlotArea(55.0,100.0,0.0,40.0); (*Lower right*) SetScaledArea(60.0,95.0,2.0,34.0); END (* case *); SetScale(0.0,4.0,-4.0,4.0); (* remember, x is in units of pi *) SetPenColor(Black); DrawAxes(0.0,0.0,1.0,1.0,2,2,3.0,2.0); (* draw axes without labels *) (* Labels are drawn separately so we can put 'pi' on x-axis labels*) SetCharSize(Small); (* Label the axes *) SetLabelOrigin(CenterLeft); (* First, the y-axis *) Move(-0.05,4.0); DrawLabel("4"); Move(-0.05,2.0); DrawLabel("2"); Move(-0.05,0.0); DrawLabel("0"); Move(-0.05,-2.0); DrawLabel("-2"); Move(-0.05,-4.0); DrawLabel("-4"); SetLabelOrigin(LowerMiddle); (* Then the x-axis *) Move(2.0,-0.5); DrawLabel("2pi"); Move(4.0,-0.5); DrawLabel("4pi"); CASE IPlot OF (*Set a new pen color for each plot *) UpLeft: SetPenColor(Red); |UpRight: SetPenColor(Green); |LowLeft: SetPenColor(Blue); |LowRight: SetPenColor(Magenta); END (* case *); Move(0.0,0.0); (* Start at the origin *) FOR IPnt := 1 TO NPnts DO Draw(XValue[IPnt],YValue[IPlot,IPnt]); (*Draw to each point*) END (* for *); SetPenColor(Black); DrawFrame; (*Draw a box around the plot for this array *) Move(0.75,4.7); SetLabelOrigin(CenterRight); SetCharSize(Small); CASE IPlot OF (*Put the appropriate title on each plot*) UpLeft: DrawLabel("5 terms in series"); |UpRight: DrawLabel("10 terms in series"); |LowLeft:DrawLabel("20 terms in series"); |LowRight:DrawLabel("100 terms in series"); END (* case *); END (* for *); (*Now that all four plots have been drawn, put a title and the formula in the middle area on the page *) SetPlotArea(0.0,100.0,0.0,100.0); (* Set to full screen *); SetScaledArea(0.0,100.0,0.0,100.0); SetScale(0.0,100.0,0.0,100.0); Move(9.0,53.0); SetCharSize(Med); SetLabelOrigin(CenterRight); DrawLabel("FOURIER SERIES APPROXIMATION TO A SAWTOOTH WAVE"); Move(17.0,47.0); SetCharSize(Small); DrawLabel("y = 2 {sin(x) - sin(2x)/2 + sin(3x)/3 - sin(4x)/4 + ... }"); CloseGraphics; (* Clean up and restore the system *) END Example.