\chapter{ An X--Y Plot: GMatrix}

A graphics object was developed to help visualize data. It uses
the Borland Graphics Interface (BGI), so it requires the Borland
compilers. It uses a virtual matrix to store the data, and
displays an x--y graph on the screen. It is simple as far as
graphics goes. It is intended to be quick and dirty. More
sophisticated graphics are widely available, so there is not
much need to reinvent the wheel. You can write the virtual
matrix to an ASCII file, and use a professional package for high
quality output. 

The \verb+GMatrix+ \index{GMatrix } class combines graphics with
a virtual matrix. The \verb+GMatrix+ keeps the data in a virtual
matrix. Any number of x--y plots can be stored in this matrix.
Once the data has been created, the graph can be displayed. The
graph has titles, axis labels, neat axis values, reference
lines, and various symbols for overlayed graphs. It determines
where to put its elements according to the view settings found
from automatic detection of the graphics system on the machine.
Hence it works for any of the monitors and modes supported by
the BGI. 

\section{The GMatrix Class}

I designed the graph class to be reasonably simple to use so I
could remember what everything meant. I also wanted something
that would get a reasonably good looking graph on the screen
with about 5 minutes of typing. The class definition is given by

\begin{verbatim}
class GMatrix
{
  private:
    // Borland graphics information. bgi files must be available
    int    GraphDriver;
    int    GraphMode;
    int    MaxX, MaxY;
    int    MaxColors;
    int    ErrorCode;
    struct linesettingstype lineinfo;
    struct viewporttype viewinfo;


    // reference lines. can have at most 20 reference lines
    double *hrefs;
    double *vrefs;
    int nvrefs, nhrefs;

    // output a line, and pause function ESC stops program
    int  gprintf(int *xloc, int *yloc, char *fmt, ... );
    void Pause();

    // graph is stored in a VMatrix: [graphid, symbol, x, y] 4 cols
    int    graphnum;        // number of graphs in grf;
    VMatrix *grf;

    // plot a point on the screen
    void plotpoint( int ix, int iy, int symbol);

  public:

    // constructors and destructors

    GMatrix( void );
    GMatrix( VMatrix &ROp, int symbol= -' '); // ROp should be rx2 matrix
                                              // column 1 is x, col 2 is y
    ~GMatrix( void );

    // display a graph
    void Show( void );

    // add a new vector to plot
    void AddVec( VMatrix &ROp, int symbol = -' ');

    // annotation options

    strtype *title, *title2, *xname, *yname, *PathToDriver;
    boolean RectangleOn, YGridOn, XGridOn;
    void Href( double href );
    void Vref( double vref );
    int ClearHref( void ){ int t=nhrefs; nhrefs = -1; return t;}
    int ClearVref( void ){ int t=nvrefs; nvrefs = -1; return t;}

    // save the grf matrix
    void SaveGraph( char *fid ) { Writea( fid, *grf ); }
};
\end{verbatim}

The graphics class is not automatically included in your project
since it is machine-compiler specific. To gain access to the
class you must define the global symbol \verb+VIRTGRAF+. This
can be done in the compiler options of the IDE, or with a
\verb+-DVIRTGRAF+ \index{GMatrix!VIRTGRAF} in the command line 
compiler. This sets a switch in \verb+VIRT.H+ to include the
GMatrix class definition.  You must also make VIRTGRAF.CPP part
of your project.

The strtype pointer \verb+PathToDriver+
\index{GMatrix!PathToDriver} contains the path to the
BGI drivers. You tell your program where the BGI files are by a
command such as \verb+*PathToDriver = "c:\\tc\\bgi"+. There are
two things to note here. First, PathToDriver is a pointer, so
you must use a '*' in front of it to store a value in it.
Secondly, note the double slashes are required for the BGI
autodetection function. 

\subsection{The Private parts of GMatrix}

The first 8 variables are from the BGI
functions. GraphDriver and GraphMode \index{GMatrix!GraphDriver,
GraphMode} are codes for the highest resolution screen available
on the machine. MaxX and MaxY \index{GMatrix!MaxX, MaxY} is the
number of pixels in the x and y axes. MaxColors
\index{GMatrix!MaxColors} is the maximum number of colors in the
display. Most of this information is available in the structures
maintained by the BGI and the autodetection functions. The
structure \verb+viewinfo+ \index{GMatrix!viewinfo} contains most
of this information after a call to the BGI function
\verb+detect+. The structure \verb+lineinfo+ contains a 
discription of the line types and thicknesses. Consult the
Borland library reference manuals about these variables.

Two vectors \verb+hrefs+ and \verb+vrefs+ \index{GMatrix!hrefs,
vrefs} contain the locations of horizontal and vertical
reference lines. The user can specify at most 20 horizontal and
20 vertical reference lines. The members are stored in a
circular fashion: the 21'st reference line overwrites the 1'st
reference line. The variables \verb+nvrefs+ and \verb+nhrefs+
\index{GMatrix!nvrefs, nhrefs} count how many reference lines
have been declared. The number of horizontal lines that will be displayed
will be 20 if \verb+nhrefs+ is 20 or more. Only the 20 most
recently declared lines will be displayed.

The next two functions control the output. \verb+Pause()+
\index{GMatrix!Pause()} allows the graph to be displayed until a
key is pressed. It will also terminate the program if you press
the ESC key. \verb+gprintf()+ \index{GMatrix!gprintf()} is
similar to printf() in C. The first two arguments are the
locations of output relative to the current viewport. The
variable argument list contains a format string for output, and a list
of variables. This function calls sprintf() to create the string
in 140 character buffer. This is dangerous if you put
more than 140 characters for output since you will overwrite
memory in ths sprintf() call. 

The data is stored in the virtual matrix \verb+grf+
\index{GMatrix!grf}. The data matrix has 4 columns. The first is
the graph number, the second is the symbol to be used for
displaying the graph, the third is the data for the x axis, and
the fourth is the data for the y-axis.  You can have as many
graphs stored in grf as you want. The number of graphs is stored
in the variable \verb+grfnum+.\index{GMatrix!grfnum} You add
them by concatenating the graphs vertically. There is a public
member function for this. The data for the graph is supplied in
a kx2 matrix where the first column is the x data and the second
is the y data. The symbols and graph counts are maintaned
automatically.

The last function \verb+plotpoint()+ \index{GMatrix!plotpoint()}
puts a symbol at point \verb+(ix,iy)+ relative to the current viewport. 

\subsection{The Public Part of GMatrix}

There are two constructors for the GMatrix
class\index{GMatrix!constructors}. The first takes a void
argument which is useful when setting up pointers to GMatrices.
The second constructor takes one or two arguments. The first
argument is a kx2 matrix where k is the number of rows. The
first column is the x data and the second is the y data. The
second argument is the symbol to be plotted. The points of the
graph will be connected by a line if the symbol has a negative
sign. It will be just the symbol if the sign is positive.
\index{GMatrix!symbol}  The default symbol produces a wiggly
line plot.

The Show function is fairly complicated, so I will devote a
section to it later.

The function \verb+AddVec()+\index{GMatrix!AddVec()} lets you
overlay graphs. It actually concatenates the new matrix and
updates the graph number and symbol. The arguments are the same
as the constructor above. 

There are several ways to annotate the graph.
\index{GMatrix!annotation} There are four strtype pointers 
for locating text. The two titles, \verb+title+ and
\verb+title2+, are placed on the top center of the screen. The
\verb+xname+ is the x-axis name and is placed at the
bottom center beneath the graph. The \verb+yname+ is the y-axis
name and is placed above the y-axis. Note that these for
parameters are pointers so the need a '*' in front of it to
store a value. I made them pointers so they only take a pointer
from the stack instead of the space required for a full strtype.
These strings are deleted by the destructor.

There are three booleans for grid display options.
\verb+RectangleOn+ determines whether or not to draw a rectangle
instead of just the x and y axes. Its default value is TTRUE.
Reference lines may be drawn at the tick marks by changing
\verb+XGridOn+ or \verb+YGridOn+ to TTRUE.

Horizontal and vertical reference lines may also be placed at
arbitrary locations using the functions \verb+Href()+ and
\verb+Vref()+.\index{GMatrix!Href(),Vref()} The user can 
specify at most 20 reference lines.  The members are stored in a
circular fashion: the 21'st reference line overwrites the 1'st
reference line. The reference lines can be cleared by the
functions \verb+ClearHref()+ and \verb+ClearVref()+.

You can save the graph matrix using the \verb+SaveGraph()+
command. \index{GMatrix!SaveGraph()} The argument is a file
name to write the ASCII version of the matrix. You can then
retrieve the data into a more sophisticated graphics program.

\section{Show()}

The show function, \verb+Show()+\index{GMatrix!Show()}, displays the
graph. It calls the Borland BGI functions, so it only works for
the PC class video modes that Borland supports. \verb+Show()+
uses autodetection and positions the graph automatically. There
is no way to save the graphics image. If you want to save it,
you need a graphics screen grabber program such as GRAB from
Word Perfect Corp.  You really should write out the graphics
matrix and use a better graphics program for professional
quality. 

\verb+Show()+ is a long routine with several major steps. The steps are
\begin{itemize}
        \item Use auto-detection to find the graphics driver

        \item Initialize the graphics screen at its highest resolution,  
                clear the screen, set the color to the highest
                color.

        \item Determine the screen dimensions, and line settings, 
                write the titles, and determine the axis margins.
                Draw rectangle on the graph margins, if requested.

        \item Construct and display a YAxis object from the graph 
                matrix and margins.

        \item Construct and display a XAxis object from the graph 
                matrix and margins.

        \item Plot the data, and connect the points if requested. 
                Draw the horizontal and vertical reference lines.

        \item Draw the axis labels, then clean up the pointers.
\end{itemize}

The interesting part of \verb+Show()+ is the axis objects. The
axes will cover all of the data, and present neat axis numbers.
The tick marks, positions, and values are calculated by Applied
Statistics Algorithm 183. It is a translated FORTRAN program for
calculating the scale, and values for an axis. This routine is
fairly complicated, so I will refer you to the literature for
it. It has three basic responsibilities: calculate the range for
the axis labels, produce neat values, and fix up. The Axis will
rescale the data by an offset and power so that the axis values
will be neat. This information will appear next to the axis
label if it was required.

The Axis class, 
\verb+Axis+\index{GMatrix!Axis, XAxis, YAxis objects},  is a
base class for the \verb+XAxis+ and \verb+YAxis+ classes. Axis,
supplies a virtual display function that is overloaded in the 
XAxis and YAxis objects. These objects are derived from Axis, so
the Axis functions common to the X-Y axes are performed during
the constructor call. The derived classes' main responsibility
is to put the axis on the screen. The ticks and values are drawn
relative to the viewports for the different axes.\footnote{
This is an example of the design by differences concept that is
making C++ so popular}
