/* This class models a cartesian coordinate system.

---------------------------------------------------------------------*/

#ifndef CARTSYS
#define CARTSYS

#include <graphics.h>                       // the Turbo graphics lib

typedef double (*FunctionOfX)(double);
typedef double (*FunctionOfXandY)(double, double);

class CartesianSystem
{
 protected:

   // *** Constants ***********************************************
   enum { NumColors = 7 };                   // density plot colors


   // *** Data Members (Set by Constructor) ***********************
   long
        ColorArray[NumColors],               // array of the colors
        LastRow,                             // screen size variables
        LastCol,                             // (dependent on monitor)
        BottomMargin,                        // space for prompts
        xAxisRow,                            // useful values in
        yAxisCol;                            //  drawing the axes
   double
        xMin, xMax,                          // x-axis endpoints
        yMin, yMax,                          // y-axis endpoints
        zMin, zMax,                          // z-axis endpoints
        xDelta,                              // change per pixel
        yDelta,                              //  for x, y and z
        zDelta,
        xAxisIncrement,                      // useful values in
        yAxisIncrement;                      //  drawing the axes


          // *** PRIVATE UTILITY FUNCTIONS ***********

    long round(double RealVal)               // round off a double value
      {
        return long (RealVal + 0.5);
      }

    long yToRow(double y)                    // map y-value to y-pixel
      {
        return LastRow -                     // pixels run top to bottom
               BottomMargin -                // leave space for margin
               round( (y - yMin) / yDelta);  // scale into y-pixel range
      }

    long xToCol(double x)                    // map x-value to x-pixel
      {
        return round( (x - xMin) / xDelta);  // scale into x-pixel range
      }


 public: // *** PUBLIC INTERFACE FUNCTIONS ***********

    /* --- Class Constructor-------------------------------

        Pre:     A CartesianSystem object has been declared.
        Receive: The extrema for the x, y, and z axes.
        Post:    The screen has been initialized to display
                   a cartesian system with the given extrema.
    -------------------------------------------------------*/
    CartesianSystem(double xLo, double xHi,
                    double yLo, double yHi,
                    double zLo = 0, double zHi = 0);

    /* --- Class Destructor --------------------------------

        Pre:  A CartesianSystem object's lifetime is over.
        Post: The screen is returned to its previous status.
    --------------------------------------------------------*/
    ~CartesianSystem() { closegraph(); }     // GFX funct

    /* --- DisplayMsg puts a message in the bottom margin.

        Receive: Msg, a character string to be displayed.
        Output:  Msg, within the cartesian system margin.
    --------------------------------------------------------*/
    void DisplayMsg(char* Msg);

    /* --- AwaitUser pauses until the user presses <Enter>.

        Input: a single character.
    --------------------------------------------------------*/
    void AwaitUser()
      {   char Ch; cin.get(Ch); }

    /* --- DrawAxes displays labeled x and y axes ----------

        Output: Labeled x and y axes, appropriately scaled.
    -------------------------------------------------------*/
    void DrawAxes();

    /* --- PlotPoint displays a single (x,y) point ------

        Receive: x and y, two double values.
        Output:  The pixel corresponding to (x,y) is "on".
    --------------------------------------------------------*/
    void PlotPoint(double x, double y,
                   int Color = YELLOW)             // GFX const
		     {putpixel(xToCol(x), yToRow(y), Color);}   // GFX funct

    /* --- Graph displays the graph of a function F(x) -------

        Receive: F, a (pointer to a) function F(x).
        Output:  The CartesianSystem graph of F.
    --------------------------------------------------------*/
    void Graph(FunctionOfX F, int Color = YELLOW); // GFX const

    /* DensityPlot displays a function F(x, y)'s density plot.

        Receive: F, a (pointer to a) function F(x, y).
        Output:  The CartesianSystem density plot of F,
                   looking down the z-axis.
    ---------------------------------------------------------*/
    void DensityPlot(FunctionOfXandY F);
 };

#endif


