home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Routines to get new function to draw from: totally new or derivation of *
- * current one *
- * *
- * Written by: Gershon Elber Ver 0.2, Apr. 1989 *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <graphics.h>
- #include <setjmp.h>
- #include "Program.h"
- #include "Expr2TrG.h"
- #include "GraphGnG.h"
- #include "MathErr.h"
-
- static jmp_buf LongJumpBuffer; /* Used in error trapping */
-
- static void GetFunction(int InputKind, ExprNode **PFuncX, ExprNode **PFuncY,
- char *SFuncX, char *SFuncY, double *min, double *max);
- static ExprNode *GetOneFunction(char *SFunc, char *Header, char *Default,
- int Param);
- static void Calc3Deriv(int InputKind, ExprNode *PFuncX[], ExprNode *PFuncY[],
- char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG]);
-
- /*****************************************************************************
- * Main routine of the GetFunc module - set the Menu and call the *
- * requested routines. *
- * Returns some statistics on the data - extremum values & Input Kind: *
- * if InputKind = Y_FUNC_X then Y = F(x) & Xmin, Xmax holds extremum values. *
- * InputKind = XY_FUNC_T then X = F(t), Y = F(t) & Tmin/max have extremums *
- * On return PFunc? points on binary trees of new function (Only PFuncY if *
- * InputKind == Y_FUNC_X) and SFunc? on a string format of the function. *
- *****************************************************************************/
- void DoGetFunc(ExprNode **PFuncX, ExprNode **PFuncY,
- char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG],
- int *InputKind,
- double *Xmin, double *Xmax, double *Ymax, double *Tmin, double *Tmax)
- {
- static struct MenuItem GetFuncMenu[] = { /* Load Data Menu */
- YELLOW, "Get Function",
- MAGENTA, "Y=F(x)",
- MAGENTA, "X=F(t), Y=F(t)",
- MAGENTA, "Deriv -> Func.",
- GREEN, "Redraw",
- CYAN, "Help",
- BLACK, "",
- BLUE, "Exit"
- };
-
- if (setjmp(LongJumpBuffer) != 0) PrintMathError();
- /* If math error occurs - long jump to given place: */
- MathErrorSetUp(ME_LONGJMP, &LongJumpBuffer);
-
- GGMenuDraw(7, GetFuncMenu, TRUE); /* Draw Menu */
- while (TRUE) {
- switch (GGMenuPick()) {
- case 1: /* Get function: Y = F(x) */
- *InputKind = Y_FUNC_X;
- GetFunction(*InputKind, &PFuncX[0], &PFuncY[0],
- SFuncX[0], SFuncY[0], Xmin, Xmax);
- Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
- PrintTree(PFuncY[0], SFuncY[0]); /* why? see case 2 */
- RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
- *Tmin, *Tmax, *InputKind);
- break;
- case 2: /* Get function: X = F(t), Y = F(t) */
- *InputKind = XY_FUNC_T;
- GetFunction(*InputKind, &PFuncX[0], &PFuncY[0],
- SFuncX[0], SFuncY[0], Tmin, Tmax);
- Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
- PrintTree(PFuncX[0], SFuncX[0]); /* Actually should be there */
- PrintTree(PFuncY[0], SFuncY[0]); /* but make consistent form */
- RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
- *Tmin, *Tmax, *InputKind);
- break;
- case 3: /* Get function: Func = Func' (From derivative) */
- FreeTree(PFuncX[0]); /* Free old function tree and */
- PFuncX[0] = PFuncX[1]; /* Copy new from der. */
- FreeTree(PFuncY[0]); /* Free old function tree and */
- PFuncY[0] = PFuncY[1]; /* Copy new from der. */
- PFuncX[1] = PFuncY[1] = NULL; /* Clear first der. */
- strcpy(SFuncX[0], SFuncX[1]); /* Copy string rep.*/
- strcpy(SFuncY[0], SFuncY[1]); /* Copy string rep.*/
- Calc3Deriv(*InputKind, PFuncX, PFuncY, SFuncX, SFuncY);
- RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
- *Tmin, *Tmax, *InputKind);
- break;
- case 4: /* Redraw */
- RedrawScreen(PFuncX, PFuncY, SFuncX, SFuncY, Xmin, Xmax, Ymax,
- *Tmin, *Tmax, *InputKind);
- break;
- case 5: /* Help */
- GGPrintHelpMenu("DrawFunc.hlp", "GETFUNCTION");
- GGMenuDraw(7, GetFuncMenu, TRUE); /* Draw Menu */
- break;
- case 7: /* Exit */
- MathErrorSetUp(ME_KILL, NULL);
- return;
- }
- }
- }
-
- /*****************************************************************************
- * Routine to get the X(t), Y(t) functions : *
- *****************************************************************************/
- static void GetFunction(int InputKind, ExprNode **PFuncX, ExprNode **PFuncY,
- char *SFuncX, char *SFuncY, double *min, double *max)
- {
- char s[LINE_LEN];
-
- GGViewPortMenuArea();
- GGMySetColor(READ_COLOR);
- GGPutMsgXY("Enter Function:", MSG_AREA_X, MSG_AREA_Y+0.5);
-
- if (InputKind == XY_FUNC_T) {
- FreeTree(*PFuncX); /* Free old trees (if were any) */
- FreeTree(*PFuncY);
- *PFuncX = GetOneFunction(SFuncX, "Enter X(t):", "t", PARAMETER_T);
- *PFuncY = GetOneFunction(SFuncY, "Enter Y(t):", "", PARAMETER_T);
- }
- else PFuncY[0] = GetOneFunction(SFuncY, "Enter Y(x):", "", PARAMETER_X);
-
- GGMySetColor(READ_COLOR);
- if (InputKind == XY_FUNC_T)
- GGPutMsgXY("Set T interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
- else GGPutMsgXY("Set X interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
-
- sprintf(s, "%lf", *min);
- do if (InputKind == XY_FUNC_T)
- GetLine("T mimimum :", s);
- else GetLine("X minimum :", s);
- while (sscanf(s, "%lf", min) != 1);
- GGMySetColor(BLACK);
-
- sprintf(s, "%lf", *max);
- do if (InputKind == XY_FUNC_T)
- GetLine("T maximum :", s);
- else GetLine("X maximum :", s);
- while ((sscanf(s, "%lf", max) != 1) || (*max <= *min));
-
- GGMySetColor(BLACK);
- if (InputKind == XY_FUNC_T)
- GGPutMsgXY("Set T interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
- else GGPutMsgXY("Set X interval :", MSG_AREA_X, MSG_AREA_Y+0.4);
- GGPutMsgXY("Enter Function:", MSG_AREA_X, MSG_AREA_Y+0.5);
- }
-
- /*****************************************************************************
- * Routine to get one function of t or x (According to Param) : *
- *****************************************************************************/
- static ExprNode *GetOneFunction(char *SFunc, char *Header, char *Default,
- int Param)
- {
- ExprNode *p;
- int i;
-
- GGMySetColor(READ_COLOR);
- GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.4);
-
- ParserError(); /* Clear error flags */
- do {
- if (!strlen(SFunc)) strcpy(SFunc, Default); /* Try Default */
- GetLine("Function = ", SFunc); /* Get function name */
- if (!strlen(SFunc)) strcpy(SFunc, Default); /* Try Default */
- for (i=strlen(SFunc); i<LINE_LEN; i++) SFunc[i] = 0;
- if ((p = Expr2Tree(SFunc)) == NULL) { /* Convert expr into bin. tree */
- /* Error in expression - print error message */
- GGMySetColor(RED);
- GGPutMsgXY(SFunc, MSG_AREA_X, MSG_AREA_Y + 0.25);
- switch (ParserError()) {
- case P_ERR_WrongSyntax:
- GGPutErrorMsg("Wrong syntax");
- break;
- case P_ERR_ParamExpect:
- GGPutErrorMsg("Param. expected");
- break;
- case P_ERR_OneOperand:
- GGPutErrorMsg("One operand only");
- break;
- case P_ERR_TwoOperand:
- GGPutErrorMsg("Two operand only");
- break;
- case P_ERR_StackOV:
- GGPutErrorMsg("Stack O.F.");
- break;
- case P_ERR_ParaMatch:
- GGPutErrorMsg("Mismatch paran.");
- break;
- case P_ERR_UndefToken:
- GGPutErrorMsg("Undefined token");
- break;
- }
- GGMySetColor(BLACK);
- GGPutMsgXY(SFunc, MSG_AREA_X, MSG_AREA_Y + 0.25);
- }
- else for (i=PARAMETER_A; i<=PARAMETER_Z; i++)/* Check if other param.*/
- if ((i != Param) && (ParamInTree(p, i))) { /* exists in tree. */
- FreeTree(p);
- p = NULL;
- GGPutErrorMsg("Invalid Parameters");
- }
- }
- while (p == NULL);
-
- GGMySetColor(BLACK);
- GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.4);
-
- return p;
- }
-
- /*****************************************************************************
- * Routine to read one line from terminal at bottom of screen: *
- *****************************************************************************/
- void GetLine(char *Header, char *s)
- {
- GGMySetColor(READ_COLOR);
- GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.25);
-
- GGGetGraphicLine(MSG_AREA_X, MSG_AREA_Y, s, GREEN);
-
- GGMySetColor(BLACK);
- GGPutMsgXY(Header, MSG_AREA_X, MSG_AREA_Y+0.25);
- }
-
-
- /*****************************************************************************
- * Routine to calc the first, second and third derivative of the given func.: *
- *****************************************************************************/
- static void Calc3Deriv(int InputKind, ExprNode *PFuncX[], ExprNode *PFuncY[],
- char SFuncX[][LINE_LEN_LONG], char SFuncY[][LINE_LEN_LONG])
- {
- int i, error;
-
- DerivError(); /* Clear error flags */
- for (i=1; i<=3; i++) {
- FreeTree(PFuncY[i]); /* Free old tree (if was any) */
- switch (InputKind) {
- case XY_FUNC_T:
- PFuncY[i] = DerivTree(PFuncY[i-1], PARAMETER_T);
- break;
- case Y_FUNC_X:
- PFuncY[i] = DerivTree(PFuncY[i-1], PARAMETER_X);
- break;
- }
- if ((error = DerivError()) != 0) {
- GGMySetColor(RED);
- GGPutMsgXY("No Derivative for:", MSG_AREA_X, MSG_AREA_Y + 0.2);
-
- switch (error) {
- case D_ERR_NoneConstExp:
- GGPutErrorMsg("Const. Exp. only");
- break;
- case D_ERR_NoAbsDeriv:
- GGPutErrorMsg("ABS function.");
- break;
- case D_ERR_NoModDeriv:
- GGPutErrorMsg("MOD operator.");
- break;
- case D_ERR_NoMinDeriv:
- GGPutErrorMsg("MIN operator.");
- break;
- case D_ERR_NoMaxDeriv:
- GGPutErrorMsg("MAX operator.");
- break;
- }
-
- GGMySetColor(BLACK);
- GGPutMsgXY("No Derivative for:", MSG_AREA_X, MSG_AREA_Y+ 0.2);
-
- PFuncY[i] = NULL; /* No tree */
- strcpy(SFuncY[i], ""); /* No string */
- }
- else PrintTree(PFuncY[i], SFuncY[i]);
- if (InputKind == XY_FUNC_T) {
- PFuncX[i] = DerivTree(PFuncX[i-1], PARAMETER_T);
- if ((error = DerivError()) != 0) {
- switch (error) {
- case D_ERR_NoneConstExp:
- GGPutErrorMsg("Const. Exp. only");
- break;
- case D_ERR_NoAbsDeriv:
- GGPutErrorMsg("No deriv - ABS");
- break;
- case D_ERR_NoModDeriv:
- GGPutErrorMsg("MOD operator.");
- break;
- case D_ERR_NoMinDeriv:
- GGPutErrorMsg("MIN operator.");
- break;
- case D_ERR_NoMaxDeriv:
- GGPutErrorMsg("MAX operator.");
- break;
- }
- PFuncX[i] = NULL; /* No tree */
- strcpy(SFuncX[i], ""); /* No string */
- }
- else PrintTree(PFuncX[i], SFuncX[i]);
- }
- }
- }