home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / irit / drawfuns.arc / GETFUNC.C < prev    next >
Text File  |  1989-07-29  |  11KB  |  302 lines

  1. /*****************************************************************************
  2. *   Routines to get new function to draw from: totally new or derivation of  *
  3. * current one                                                                *
  4. *                                                                            *
  5. * Written by:  Gershon Elber                           Ver 0.2, Apr. 1989    *
  6. *****************************************************************************/
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <graphics.h>
  11. #include <setjmp.h>
  12. #include "Program.h"
  13. #include "Expr2TrG.h"
  14. #include "GraphGnG.h"
  15. #include "MathErr.h"
  16.  
  17. static jmp_buf LongJumpBuffer;               /* Used in error trapping */
  18.  
  19. static void GetFunction(int InputKind, ExprNode **PFuncX, ExprNode **PFuncY,
  20.     char *SFuncX, char *SFuncY, double *min, double *max);
  21. static ExprNode *GetOneFunction(char *SFunc, char *Header, char *Default,
  22.                                 int Param);
  23. static void Calc3Deriv(int InputKind, ExprNode *PFuncX[], ExprNode *PFuncY[],
  24.     char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG]);
  25.  
  26. /*****************************************************************************
  27. *   Main routine of the GetFunc module - set the Menu and call the           *
  28. * requested routines.                                                        *
  29. * Returns some statistics on the data - extremum values & Input Kind:        *
  30. * if InputKind = Y_FUNC_X then Y = F(x) & Xmin, Xmax holds extremum values.  *
  31. *    InputKind = XY_FUNC_T then X = F(t), Y = F(t) & Tmin/max have extremums *
  32. * On return PFunc? points on binary trees of new function (Only PFuncY if    *
  33. * InputKind == Y_FUNC_X) and SFunc? on a string format of the function.      *
  34. *****************************************************************************/
  35. void DoGetFunc(ExprNode **PFuncX, ExprNode **PFuncY,
  36.     char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG],
  37.     int *InputKind,
  38.     double *Xmin, double *Xmax, double *Ymax, double *Tmin, double *Tmax)
  39. {
  40.     static struct MenuItem GetFuncMenu[] = {           /* Load Data Menu */
  41.         YELLOW,    "Get Function",
  42.         MAGENTA, "Y=F(x)",
  43.         MAGENTA, "X=F(t), Y=F(t)",
  44.         MAGENTA, "Deriv -> Func.",
  45.     GREEN,    "Redraw",
  46.         CYAN,    "Help",
  47.     BLACK,    "",
  48.         BLUE,    "Exit"
  49.     };
  50.  
  51.     if (setjmp(LongJumpBuffer) != 0) PrintMathError();
  52.     /* If math error occurs - long jump to given place: */
  53.     MathErrorSetUp(ME_LONGJMP, &LongJumpBuffer);
  54.  
  55.     GGMenuDraw(7, GetFuncMenu, TRUE);                /* Draw Menu */
  56.     while (TRUE) {
  57.     switch (GGMenuPick()) {
  58.         case 1:                   /* Get function: Y = F(x) */
  59.                 *InputKind = Y_FUNC_X;
  60.         GetFunction(*InputKind, &PFuncX[0], &PFuncY[0],
  61.                     SFuncX[0], SFuncY[0], Xmin, Xmax);
  62.         Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
  63.         PrintTree(PFuncY[0], SFuncY[0]);      /* why? see case 2 */
  64.         RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
  65.                 *Tmin, *Tmax, *InputKind);
  66.                 break;
  67.         case 2:             /* Get function: X = F(t), Y = F(t) */
  68.                 *InputKind = XY_FUNC_T;
  69.         GetFunction(*InputKind, &PFuncX[0], &PFuncY[0],
  70.                     SFuncX[0], SFuncY[0], Tmin, Tmax);
  71.         Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
  72.         PrintTree(PFuncX[0], SFuncX[0]); /* Actually should be there */
  73.         PrintTree(PFuncY[0], SFuncY[0]); /* but make consistent form */
  74.         RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
  75.                 *Tmin, *Tmax, *InputKind);
  76.                 break;
  77.         case 3:         /* Get function: Func = Func' (From derivative) */
  78.         FreeTree(PFuncX[0]);           /* Free old function tree and */
  79.         PFuncX[0] = PFuncX[1];               /* Copy new from der. */
  80.         FreeTree(PFuncY[0]);           /* Free old function tree and */
  81.         PFuncY[0] = PFuncY[1];               /* Copy new from der. */
  82.         PFuncX[1] = PFuncY[1] = NULL;         /* Clear first der. */
  83.         strcpy(SFuncX[0], SFuncX[1]);          /* Copy string rep.*/
  84.         strcpy(SFuncY[0], SFuncY[1]);          /* Copy string rep.*/
  85.         Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
  86.         RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
  87.                 *Tmin, *Tmax, *InputKind);
  88.                 break;
  89.         case 4:                           /* Redraw */
  90.         RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
  91.                 *Tmin, *Tmax, *InputKind);
  92.                 break;
  93.         case 5:                             /* Help */
  94.         GGPrintHelpMenu("DrawFunc.hlp", "GETFUNCTION");
  95.         GGMenuDraw(7, GetFuncMenu, TRUE);        /* Draw Menu */
  96.                 break;
  97.         case 7:                             /* Exit */
  98.         MathErrorSetUp(ME_KILL, NULL);
  99.                 return;
  100.         }
  101.     }
  102. }
  103.  
  104. /*****************************************************************************
  105. * Routine to get the X(t), Y(t) functions :                                  *
  106. *****************************************************************************/
  107. static void GetFunction(int InputKind, ExprNode **PFuncX, ExprNode **PFuncY,
  108.     char *SFuncX, char *SFuncY, double *min, double *max)
  109. {
  110.     char s[LINE_LEN];
  111.  
  112.     GGViewPortMenuArea();
  113.     GGMySetColor(READ_COLOR);
  114.     GGPutMsgXY("Enter Function:", MSG_AREA_X, MSG_AREA_Y+0.5);
  115.  
  116.     if (InputKind == XY_FUNC_T) {
  117.     FreeTree(*PFuncX);             /* Free old trees (if were any) */
  118.     FreeTree(*PFuncY);
  119.     *PFuncX = GetOneFunction(SFuncX, "Enter X(t):", "t", PARAMETER_T);
  120.     *PFuncY = GetOneFunction(SFuncY, "Enter Y(t):", "", PARAMETER_T);
  121.     }
  122.     else PFuncY[0] = GetOneFunction(SFuncY, "Enter Y(x):", "", PARAMETER_X);
  123.  
  124.     GGMySetColor(READ_COLOR);
  125.     if (InputKind == XY_FUNC_T)
  126.      GGPutMsgXY("Set T interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
  127.     else GGPutMsgXY("Set X interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
  128.  
  129.     sprintf(s, "%lf", *min);
  130.     do if (InputKind == XY_FUNC_T)
  131.         GetLine("T mimimum :", s);
  132.        else GetLine("X minimum :", s);
  133.     while (sscanf(s, "%lf", min) != 1);
  134.     GGMySetColor(BLACK);
  135.  
  136.     sprintf(s, "%lf", *max);
  137.     do if (InputKind == XY_FUNC_T)
  138.         GetLine("T maximum :", s);
  139.        else GetLine("X maximum :", s);
  140.     while ((sscanf(s, "%lf", max) != 1) || (*max <= *min));
  141.  
  142.     GGMySetColor(BLACK);
  143.     if (InputKind == XY_FUNC_T)
  144.      GGPutMsgXY("Set T interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
  145.     else GGPutMsgXY("Set X interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
  146.     GGPutMsgXY("Enter Function:", MSG_AREA_X, MSG_AREA_Y+0.5);
  147. }
  148.  
  149. /*****************************************************************************
  150. * Routine to get one function of t or x (According to Param) :               *
  151. *****************************************************************************/
  152. static ExprNode *GetOneFunction(char *SFunc, char *Header, char *Default,
  153.                                 int Param)
  154. {
  155.     ExprNode *p;
  156.     int i;
  157.  
  158.     GGMySetColor(READ_COLOR);
  159.     GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.4);
  160.  
  161.     ParserError();                    /* Clear error flags */
  162.     do {
  163.     if (!strlen(SFunc)) strcpy(SFunc, Default);         /* Try Default  */
  164.     GetLine("Function = ", SFunc);            /* Get function name */
  165.     if (!strlen(SFunc)) strcpy(SFunc, Default);         /* Try Default  */
  166.     for (i=strlen(SFunc); i<LINE_LEN; i++) SFunc[i] = 0;
  167.     if ((p = Expr2Tree(SFunc)) == NULL) { /* Convert expr into bin. tree */
  168.             /* Error in expression - print error message */
  169.         GGMySetColor(RED);
  170.         GGPutMsgXY(SFunc, MSG_AREA_X, MSG_AREA_Y + 0.25);
  171.         switch (ParserError()) {
  172.         case P_ERR_WrongSyntax:
  173.             GGPutErrorMsg("Wrong syntax");
  174.             break;
  175.         case P_ERR_ParamExpect:
  176.             GGPutErrorMsg("Param. expected");
  177.             break;
  178.         case P_ERR_OneOperand:
  179.             GGPutErrorMsg("One operand only");
  180.             break;
  181.         case P_ERR_TwoOperand:
  182.             GGPutErrorMsg("Two operand only");
  183.             break;
  184.         case P_ERR_StackOV:
  185.             GGPutErrorMsg("Stack O.F.");
  186.             break;
  187.         case P_ERR_ParaMatch:
  188.             GGPutErrorMsg("Mismatch paran.");
  189.             break;
  190.         case P_ERR_UndefToken:
  191.             GGPutErrorMsg("Undefined token");
  192.             break;
  193.             }
  194.         GGMySetColor(BLACK);
  195.         GGPutMsgXY(SFunc, MSG_AREA_X, MSG_AREA_Y + 0.25);
  196.         }
  197.     else for (i=PARAMETER_A; i<=PARAMETER_Z; i++)/* Check if other param.*/
  198.         if ((i != Param) && (ParamInTree(p, i))) {      /* exists in tree. */
  199.         FreeTree(p);
  200.         p = NULL;
  201.         GGPutErrorMsg("Invalid Parameters");
  202.         }
  203.     }
  204.     while (p == NULL);
  205.  
  206.     GGMySetColor(BLACK);
  207.     GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.4);
  208.  
  209.     return p;
  210. }
  211.  
  212. /*****************************************************************************
  213. * Routine to read one line from terminal at bottom of screen:                *
  214. *****************************************************************************/
  215. void GetLine(char *Header, char *s)
  216. {
  217.     GGMySetColor(READ_COLOR);
  218.     GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.25);
  219.  
  220.     GGGetGraphicLine(MSG_AREA_X, MSG_AREA_Y, s, GREEN);
  221.  
  222.     GGMySetColor(BLACK);
  223.     GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.25);
  224. }
  225.  
  226.  
  227. /*****************************************************************************
  228. * Routine to calc the first, second and third derivative of the given func.: *
  229. *****************************************************************************/
  230. static void Calc3Deriv(int InputKind, ExprNode *PFuncX[], ExprNode *PFuncY[],
  231.     char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG])
  232. {
  233.     int i, error;
  234.  
  235.     DerivError();                    /* Clear error flags */
  236.     for (i=1; i<=3; i++) {
  237.     FreeTree(PFuncY[i]);               /* Free old tree (if was any) */
  238.         switch (InputKind) {
  239.         case XY_FUNC_T:
  240.         PFuncY[i] = DerivTree(PFuncY[i-1], PARAMETER_T);
  241.         break;
  242.         case Y_FUNC_X:
  243.         PFuncY[i] = DerivTree(PFuncY[i-1], PARAMETER_X);
  244.         break;
  245.         }
  246.     if ((error = DerivError()) != 0) {
  247.         GGMySetColor(RED);
  248.         GGPutMsgXY("No Derivative for:", MSG_AREA_X, MSG_AREA_Y + 0.2);
  249.  
  250.         switch (error) {
  251.         case D_ERR_NoneConstExp:
  252.             GGPutErrorMsg("Const. Exp. only");
  253.             break;
  254.         case D_ERR_NoAbsDeriv:
  255.             GGPutErrorMsg("ABS function.");
  256.             break;
  257.         case D_ERR_NoModDeriv:
  258.             GGPutErrorMsg("MOD operator.");
  259.             break;
  260.         case D_ERR_NoMinDeriv:
  261.             GGPutErrorMsg("MIN operator.");
  262.             break;
  263.         case D_ERR_NoMaxDeriv:
  264.             GGPutErrorMsg("MAX operator.");
  265.             break;
  266.             }
  267.  
  268.         GGMySetColor(BLACK);
  269.         GGPutMsgXY("No Derivative for:", MSG_AREA_X, MSG_AREA_Y+ 0.2);
  270.  
  271.         PFuncY[i] = NULL;                      /* No tree */
  272.         strcpy(SFuncY[i], "");                /* No string */
  273.     }
  274.     else PrintTree(PFuncY[i], SFuncY[i]);
  275.         if (InputKind == XY_FUNC_T) {
  276.         PFuncX[i] = DerivTree(PFuncX[i-1], PARAMETER_T);
  277.         if ((error = DerivError()) != 0) {
  278.                 switch (error) {
  279.             case D_ERR_NoneConstExp:
  280.             GGPutErrorMsg("Const. Exp. only");
  281.             break;
  282.             case D_ERR_NoAbsDeriv:
  283.             GGPutErrorMsg("No deriv - ABS");
  284.             break;
  285.             case D_ERR_NoModDeriv:
  286.             GGPutErrorMsg("MOD operator.");
  287.             break;
  288.             case D_ERR_NoMinDeriv:
  289.             GGPutErrorMsg("MIN operator.");
  290.             break;
  291.             case D_ERR_NoMaxDeriv:
  292.             GGPutErrorMsg("MAX operator.");
  293.             break;
  294.                 }
  295.         PFuncX[i] = NULL;                  /* No tree */
  296.         strcpy(SFuncX[i], "");                /* No string */
  297.             }
  298.         else PrintTree(PFuncX[i], SFuncX[i]);
  299.     }
  300.     }
  301. }
  302.