18.2 A Graphics Environment

For the purposes of carrying the discussion further, the remainder of this chapter will assume that the student has access to the graphics facilities provided by the following definition module. Although the code required to realize this module is quite implementation dependent, it can be done on both Macintosh and Windows systems with a minimum of work, and the necessary detail may all be found in section 18.6 so that the student can easily add the necessary facilities to her own project libraries if they have not been bundled by the compiler vendor.

The basis for drawing on the screen in a graphics user environment is a pen. At any given time, the pen is in a specific (coordinatized) position, and can be used to draw a trail of dots as desired. Alternately, it can be moved to another position without drawing.

DEFINITION MODULE GraphPaper;

(* Original design copyright 1996 by R. Sutcliffe
    Original implementation 1996 using p1 on the Macintosh
    Windows implementation 1998 05 12 by Joel Schwartz
        with use of examples written by Stony Brook
        Last revision by RS 1998 07 11
*)

TYPE
  CoordSystem = (MacWin, bearing, standard); (* default = standard *)
(* The MacWin Coordinate system grows down and has the origin at the top
   left hand corner with angles measured clockwise. In the bearing
   system the home position (0,0) is the middle of the screen
   from which angles are measured clockwise. The standard system also
   starts in mid screen and grows up but measures from east as zero and
   thence counterclockwise. *)

  AngleType = (deg, rad, grad); (* Allows for angle type specification *)
  LabelType = ARRAY [0..50] OF CHAR;  (* Standard format for labels *)

PROCEDURE SetCoordSystem (kind : CoordSystem);
(* Allows the user to set the system. The default is the standard system so this has to be called only if a change is desired. This procedure concludes by calling Home. Any shift in the system origin must be made after calling this procedure.  *)
PROCEDURE SetAngleType (kind : AngleType);
(* Allows the user to set the angle measurement type. The default is degrees so this has to be called only if a change is desired. This procedure concludes by calling Home. Any shift in the system origin must be made after calling this procedure.  *)

PROCEDURE Home;
(* moves to 0,0 and then
     In the bearing system:
       - sets angle to 0 (North)
       - sets the rotational direction to clockwise
     In the MacWin & standard system:
       - sets the angle to 0 (East)
       - sets the rotational direction to clockwise (MacWin)
               or to counterclockwise (standard) *)

PROCEDURE ShiftOrigin (deltaX, deltaY : INTEGER);
(* Translate the origin by the amount specified.  The direction of the translation on the screen depends, of course, on the coordinate system being used. Drawing is now with respect to the new origin. Does not call home or change  any other settings. *)

PROCEDURE GetDimensions (VAR x, y: INTEGER);
  (* obtains the overall width and height of the drawing screen *)
PROCEDURE GetLocation (VAR x, y: INTEGER);
  (* get the drawing pen location in current coordinates *)

(* The following three procedures work in the current coordinate
system and on the stored pen position only but do no actual drawing. *)

PROCEDURE MoveBy (distance: INTEGER);
  (* move in the stored direction by the supplied distance *)
PROCEDURE MoveTo (x, y : INTEGER);
  (* move the drawing pen to the specified coordinates *)
PROCEDURE Move (dx, dy : INTEGER);
  (* move the drawing pen to a point (x + dx, y + dy) from the currently stored point *)

(* The following three procedures work in the current coordinate system on the stored pen direction only but do no actual drawing. 
The angle is assumed to be in the currently set units. *)

PROCEDURE GetCurrentAngle () : REAL;
  (* Return the current angle in the current units *)
PROCEDURE Turn (angle : REAL);
  (* change the stored pen direction by adding its angle to the one supplied *)
PROCEDURE TurnTo (angle : REAL);
(* change the stored pen direction by setting its angle to the one supplied *)

(* The following two procedures use the pen to draw a line and change the stored position. *)

PROCEDURE LineBy (distance: INTEGER);
  (* Draws in the stored pen direction the number of units supplied. *)
PROCEDURE LineTo (x, y : INTEGER);
(* Draws a line from the current stored position to the supplied one without using or changing the stored direction. *)
PROCEDURE Line (dx, dy : INTEGER);
(* Line to a point (x + dx, y + dy) from the current point without using or changing the stored direction. *)

(* The following two procedures place a dot on the screen, but do not change the pen direction. Measurement is in pixels; not scaled. *)

PROCEDURE Dot;
   (* places a dot at the present location *)
PROCEDURE DotAt (x, y : INTEGER);
   (* does a MoveTo, then a dot *)

(* These procedures are for annotating the graph paper with a scale and labels for the axes. *)

PROCEDURE SetLabels (horix, vert : LabelType);
   (* Sets the names for the horizontal and vertical axes. *)
PROCEDURE ShowLabels;
   (* Show the labels - if no label is set then "x" and "y" are used *)
PROCEDURE ShowAxes;
   (* Show the axes for the graph *)

(* The following procedures allow for a scaling of the graph paper and the plotting of points according to the scale. If the scale is 10, there is one unit every ten division marks. This will make the plotting of functions more readible. The default is one unit per division mark.
    EXAMPLE: setting the scale to 5 using cm's as the unit means 1 cm = 5 division marks.*)

PROCEDURE SetScale (dataPerDivision : CARDINAL);
   (* Set the scale by which the graph is measured *)
PROCEDURE PlotPoint( x, y : REAL);
   (* Plot a scaled point on the graph *)
PROCEDURE PolarPlotPoint (radius, angle : REAL);
   (* Moves to a given angle and radius and places a scaled dot at that point.
	 The angle is assumed to be in the currently set units. *)

END GraphPaper.

NOTE: Implementations of this module for both the Macintosh and Windows systems will be given later in the chapter.

In this module, all three basic coordinate systems are supplied, with options to graph in either rectangular or the appropriate polar style, and to turn on a grid system and do scaling if desired. It should be noted that when graphing polar style the point (10, 30) is different in all three coordinate systems.

Note that plotting pixels is handled by one set of procedures, and plotting points on a scaled (and possibly labeled) piece of graph paper is handled by another set of procedures. This permits the user to work in either. The latter is more useful when graphing functions.

The user can change the origin to some other place on the screen without changing the coordinate system. Also, the user may decide whether to graph in degrees or radians as both are supported in all three. Other options include the ability to show a set of axes and to set up labels for the axes, for in real situations these are seldom just "x" and "y." For the advanced programmer who needs to use the graphics window for other purposes, a procedure to pass out a reference to the window can normally be found at a lower level, where the graphics window is made available to the implementation of GraphPaper. In addition, the user can obtain the screen dimensions (which depend on the monitor and its settings) and determine the location on the screen and angle for the pen.

The defaults for this module are set to not display the axes or labels, and to employ the standard coordinate system.

The underlying implementation stores the current position on the graph paper and also a direction in which any lines drawn with LineBy and any moves made with MoveBy will go. This direction can be changed by Turn which adds the supplied angle to the stored one, or by TurnTo which resets the stored angle. The procedures Line and Move change the position for the next drawing by a specified number of units, so they supply their own direction and do not change the stored one.


Contents