home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d polygonal solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Module to handle overloaded operators for the input parser module. *
- * Note this module should be accessed by Input Parser only (InptPrsr.c). *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <alloc.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "program.h"
- #include "allocate.h"
- #include "booleang.h"
- #include "freeform.h"
- #include "geomat3d.h"
- #include "inptprsg.h"
- #include "inptprsl.h"
- #include "objects.h"
- #include "overload.h"
-
- /* The following table help to decide if the operand are legal for the given */
- /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a */
- /* square matrix of number of object types by number of object types: */
-
- static IritExprType OverLoadDiadicTable[5][9][9] =
- /* POLY_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR CURVE_EXPR SURFACE_EXPR STRING_EXPR OLST_EXPR CTLPT_EXPR */
- { { /* PLUS */
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR },
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR } },
-
- { /* MINUS */
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
-
- { /* MULT */
- { POLY_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, VECTOR_EXPR, NUMERIC_EXPR, VECTOR_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { POLY_EXPR, MATRIX_EXPR, VECTOR_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, CURVE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { POLY_EXPR, NO_EXPR, NO_EXPR, SURFACE_EXPR,NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, OLST_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
-
- { /* DIV */
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NUMERIC_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
-
- { /* POWER */
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NUMERIC_EXPR, NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, MATRIX_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, POLY_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR },
- { NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR, NO_EXPR } },
- };
-
- /* The following table help to decide if the operand are legal for the given */
- /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length */
- /* of number of object types: */
-
- static IritExprType OverLoadMonadicTable[1][9] =
- /* POLY_EXPR NUMERIC_EXPR VECTOR_EXPR MATRIX_EXPR CURVE_EXPR SURFACE_EXPR STRING_EXPR OLST_EXPR CTLPT_EXPR */
- { /* UNARMINUS */
- { POLY_EXPR, NUMERIC_EXPR, VECTOR_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR, NO_EXPR, NO_EXPR }
- };
-
- static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
- IritExprType Left, IritExprType *Result);
- static ObjectStruct *ConvSrfToPolys(ParseTree *Srf);
-
- /*****************************************************************************
- * Routine to perform type checking on the overloaded operators. Returns *
- * TRUE if legal, and set Result to returned object type. *
- * Allows multiple types (I.e. VECTOR_EXPR | MATRIX_EXPR is legal input). *
- * Note output Result may be multiple types as well is a such case. *
- *****************************************************************************/
- int OverLoadTypeCheck(int Operator, IritExprType Right, IritExprType Left,
- IritExprType *Result)
- {
- int i, j, NumRightTypes, NumLeftTypes;
- IritExprType TmpResult;
-
- /* Compute how many types are feasible here (input). */
- for (i = 1, NumRightTypes = 0; i < ERROR_EXPR; i <<= 1)
- NumRightTypes += (i & Right) != 0;
- for (i = 1, NumLeftTypes = 0; i < ERROR_EXPR; i <<= 1)
- NumLeftTypes += (i & Left) != 0;
-
- if (NumLeftTypes < 1 || NumRightTypes < 1)
- return FALSE;
- else if (NumLeftTypes == 1 && NumRightTypes == 1)
- return OverLoadTypeCheckAux(Operator, Right, Left, Result);
- else {
- /* More than one type in the input - compute union of the output */
- /* types and return the union. */
- *Result = 0;
- for (i = 1; i < ERROR_EXPR; i <<= 1) if ((i & Right) != 0)
- for (j = 1; j < ERROR_EXPR; j <<= 1) if ((j & Left) != 0) {
- if (!OverLoadTypeCheckAux(Operator,
- (IritExprType) i,
- (IritExprType) j,
- &TmpResult))
- return FALSE;
- *Result |= TmpResult;
- }
- return TRUE;
- }
- }
-
- /*****************************************************************************
- * Routine to perform type checking on the overloaded operators. Returns *
- * TRUE if legal, and set Result to returned object type. *
- * Assumes a single type (I.e. VECTOR_EXPR | MATRIX_EXPR is illegal input). *
- *****************************************************************************/
- static int OverLoadTypeCheckAux(int Operator, IritExprType Right,
- IritExprType Left, IritExprType *Result)
- {
- int i, IRight, ILeft;
-
- for (i = 1, IRight = 0; i < Right; i <<= 1, IRight++);
- for (i = 1, ILeft = 0; i < Left; i <<= 1, ILeft++);
-
- switch (Operator) {
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case POWER:
- *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
- [IRight][ILeft];
- return *Result != NO_EXPR;
- case UNARMINUS:
- *Result = OverLoadMonadicTable[0][IRight];
- return *Result != NO_EXPR;
- default:
- FatalError("OverLoadTypeCheck: undefined operator\n");
- }
- return FALSE; /* Makes warning silent. */
- }
-
- /*****************************************************************************
- * Routine to evaluate an monadic or diadic expression. It is assumed the *
- * two operands are valid for the given expression - a test which can be made *
- * using OverLoadTypeCheck routine (see above). returned pointer to node with *
- * the result, NULL in case of error (should not happen actually). *
- * Root holds the simple sub-expression (Root has the operator). PObj holds *
- * all the currently defined objects available in the system. IError & CError *
- * will be set to relevant error if was one. *
- *****************************************************************************/
- ParseTree *OverLoadEvalOper(ParseTree *Root, ParseTree *TempR,
- ParseTree *TempL, InptPrsrEvalErrType *IError, char *CError)
- {
- int i,
- OperReversed = FALSE;
- RealType R;
- ParseTree *Temp,
- *RetVal = Root;
- ObjectStruct *TempLObj, *TempRObj;
-
- switch (Root->NodeKind) { /* Dies if undefined operator. */
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case POWER:
- if (TempR == NULL || TempL == NULL) return NULL; /* Error! */
- break;
-
- case UNARMINUS:
- if (TempR == NULL) return NULL; /* Error! */
- break;
-
- default:
- FatalError("OverLoadEvalOper: Undefined operator\n");
- }
-
- /* Make TempL be bigger, so we need handle less cases. */
- if (Root -> NodeKind != UNARMINUS &&
- ((int) TempR -> ObjType) > ((int) TempL -> ObjType)) {
- Temp = TempR;
- TempR = TempL;
- TempL = Temp;
-
- OperReversed = TRUE;
- }
-
- switch (Root->NodeKind) {
- case PLUS:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R + TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_ADD(Root->U.PObj->U.Vec,
- TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatAddTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
- (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
- TempLObj = ConvSrfToPolys(TempL);
- TempRObj = ConvSrfToPolys(TempR);
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanOR(TempLObj, TempRObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
- UpdateCharError("Operator ", PLUS);
- RetVal = NULL;
- }
- }
- else if (IS_OLST_NODE(TempR) && IS_OLST_NODE(TempL)) {
- Root->ObjType = OBJ_LIST_OBJ;
- Root->U.PObj = AppendLists(TempL->U.PObj, TempR->U.PObj);
- }
- else if ((IS_CTLPT_NODE(TempR) || IS_CRV_NODE(TempR)) &&
- (IS_CTLPT_NODE(TempL) || IS_CRV_NODE(TempL))) {
- Root->ObjType = CURVE_OBJ;
- if (OperReversed)
- Root->U.PObj = MergeCurvesAndCtlPoints(TempR->U.PObj,
- TempL->U.PObj);
- else
- Root->U.PObj = MergeCurvesAndCtlPoints(TempL->U.PObj,
- TempR->U.PObj);
- }
- else
- RetVal = NULL;
- break;
- case MINUS:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R - TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_SUB(Root->U.PObj->U.Vec,
- TempL->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatSubTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
- (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
- TempLObj = ConvSrfToPolys(TempL);
- TempRObj = ConvSrfToPolys(TempR);
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanSUB(TempLObj, TempRObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
- UpdateCharError("Operator ", MINUS);
- RetVal = NULL;
- }
- }
- else
- RetVal = NULL;
- break;
- case MULT:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = TempL->U.R * TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = DOT_PROD(TempL->U.PObj->U.Vec,
- TempR->U.PObj->U.Vec);
- }
- else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatMultTwo4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, TempR->U.PObj->U.Mat);
- }
- else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_COPY(Root->U.PObj->U.Vec, TempL->U.PObj->U.Vec);
- PT_SCALE(Root->U.PObj->U.Vec, TempR->U.R);
- }
- else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- MatScale4by4(Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat, &TempR->U.R);
- }
- else if (IS_POLY_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->U.PObj = TransformObject(TempR->U.PObj,
- TempL->U.PObj->U.Mat);
- Root->ObjType = POLY_OBJ;
- }
- else if ((IS_MAT_NODE(TempR) && IS_CRV_NODE(TempL)) ||
- (IS_MAT_NODE(TempR) && IS_SRF_NODE(TempL)) ||
- (IS_MAT_NODE(TempR) && IS_OLST_NODE(TempL))) {
- Root->U.PObj = TransformObject(TempL->U.PObj,
- TempR->U.PObj->U.Mat);
- Root->ObjType = Root->U.PObj->ObjType;
- }
- else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- MatMultVecby4by4(Root->U.PObj->U.Vec,
- TempR->U.PObj->U.Vec, TempL->U.PObj->U.Mat);
- }
- else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
- (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
- TempLObj = ConvSrfToPolys(TempL);
- TempRObj = ConvSrfToPolys(TempR);
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanAND(TempLObj, TempRObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
- UpdateCharError("Operator ", MULT);
- RetVal = NULL;
- }
- }
- else
- RetVal = NULL;
- break;
- case DIV:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) { /* Numeric div. */
- Root->ObjType = NUMERIC_OBJ;
- if (Root->Right->U.R != 0.0) {
- Root->U.R = TempL->U.R / TempR->U.R;
- }
- else {
- *IError = IE_ERR_DIV_BY_ZERO;
- strcpy(CError, "/");
- RetVal = NULL;
- }
- }
- else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
- (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
- TempLObj = ConvSrfToPolys(TempL);
- TempRObj = ConvSrfToPolys(TempR);
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanCUT(TempLObj, TempRObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
- UpdateCharError("Operator ", DIV);
- RetVal = NULL;
- }
- }
- else
- RetVal = NULL;
- break;
- case POWER:
- if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = pow(TempL->U.R, TempR->U.R);
- }
- else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
- i = (int) TempR->U.R; /* Power MUST be integer in this case. */
- if (!APX_EQ(i, TempR->U.R) || i < -1) {
- *IError = IE_ERR_MAT_POWER;
- strcpy(CError, "^");
- RetVal = NULL;
- }
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- if (i == -1) { /* Generate the inverse matrix: */
- if (!MatInverseMatrix(TempL->U.PObj->U.Mat,
- Root->U.PObj->U.Mat)) {
- *IError = IE_ERR_MAT_POWER;
- strcpy(CError, "^");
- RetVal = NULL;
- }
- }
- else { /* I must be positive integer. */
- MatGenUnitMat(Root->U.PObj->U.Mat);
- while (i--) MatMultTwo4by4(Root->U.PObj->U.Mat,
- Root->U.PObj->U.Mat,
- TempL->U.PObj->U.Mat);
- }
- }
- else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
- (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
- TempLObj = ConvSrfToPolys(TempL);
- TempRObj = ConvSrfToPolys(TempR);
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanMERGE(TempLObj, TempRObj);
- if (Root->U.PObj == NULL) {
- IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
- UpdateCharError("Operator ", MINUS);
- RetVal = NULL;
- }
- }
- else
- RetVal = NULL;
- break;
- case UNARMINUS:
- if (IS_NUM_NODE(TempR)) {
- Root->ObjType = NUMERIC_OBJ;
- Root->U.R = -TempR->U.R;
- }
- else if (IS_VEC_NODE(TempR)) {
- Root->ObjType = VECTOR_OBJ;
- Root->U.PObj = AllocObject("", VECTOR_OBJ, NULL);
- PT_COPY(Root->U.PObj->U.Vec, TempR->U.PObj->U.Vec);
- PT_SCALE(Root->U.PObj->U.Vec, -1.0);
- }
- else if (IS_MAT_NODE(TempR)) {
- Root->ObjType = MATRIX_OBJ;
- Root->U.PObj = AllocObject("", MATRIX_OBJ, NULL);
- R = -1.0;
- MatScale4by4(Root->U.PObj->U.Mat, TempR->U.PObj->U.Mat, &R);
- }
- else if (IS_POLY_NODE(TempR)) {
- Root->ObjType = POLY_OBJ;
- Root->U.PObj = BooleanNEG(TempR -> U.PObj);
- }
- else if (IS_CRV_NODE(TempR)) {
- Root->ObjType = CURVE_OBJ;
- Root->U.PObj = CurveReverse(TempR -> U.PObj);
- }
- else if (IS_SRF_NODE(TempR)) {
- Root->ObjType = SURFACE_OBJ;
- Root->U.PObj = SurfaceReverse(TempR -> U.PObj);
- }
- else
- RetVal = NULL;
- break;
- }
- if (RetVal == NULL && *IError == IPE_NO_ERR) { /* Put general error msg: */
- *IError = IE_ERR_TYPE_MISMATCH;
- switch (Root->NodeKind) {
- case PLUS:
- strcpy(CError, "Operator +");
- break;
- case MINUS:
- strcpy(CError, "Operator -");
- break;
- case MULT:
- strcpy(CError, "Operator *");
- break;
- case DIV:
- strcpy(CError, "Operator /");
- break;
- case POWER:
- strcpy(CError, "Operator ^");
- break;
- case UNARMINUS:
- strcpy(CError, "Operator (unary) -");
- break;
- }
- }
-
- return RetVal;
- }
-
- /*****************************************************************************
- * If given object is a surface, its polygonal representation object is *
- * returned instead. Otherwise the given pointer is returned as is. *
- *****************************************************************************/
- static ObjectStruct *ConvSrfToPolys(ParseTree *Srf)
- {
- if (!IS_SRF_NODE(Srf)) return Srf -> U.PObj;
-
- if (Srf -> U.PObj -> U.Srf.Polygons == NULL)
- ComputeSurfacePolygons(Srf -> U.PObj);
-
- return Srf -> U.PObj -> U.Srf.Polygons;
- }
-