home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
irit
/
drawfuns.arc
/
GETFUNC.C
< prev
next >
Wrap
Text File
|
1989-07-29
|
11KB
|
302 lines
/*****************************************************************************
* 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]);
}
}
}