home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * "Irit" - the 3d polygonal solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Mar. 1990 *
- ******************************************************************************
- * Data File Interpreter module - handle data files - to/from geom objects *
- *****************************************************************************/
-
- #ifdef __MSDOS__
- #include <graphics.h>
- #endif /* __MSDOS__ */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include "program.h"
- #include "allocatg.h"
- #include "objects.h"
- #include "geomat3d.h"
- #include "dataprsl.h"
- #include "dataprsg.h" /* Visible to the other modules. */
-
- #ifndef __MSDOS__
- #include "xgraphic.h"
- #endif /* __MSDOS__ */
-
- static int DPGlblLineCount, /* Used to locate errors in input file. */
- DPGlblParserError; /* Save last error number found. */
- static char DPGlblTokenError[LINE_LEN]; /* Last token where error was found. */
- static jmp_buf LclLongJumpBuffer; /* Used in error traping. */
- /* The following are used to hold binary trees of Vertices & Polygon/lines. */
- static struct BinTree *VertexRoot = NULL, *PolygonRoot = NULL;
-
- static int GlblToken = 0; /* Used by the parser, to unget token. */
- static char GlblStringToken[UNGET_STACK_SIZE][LINE_LEN];/* Save unget tokens.*/
-
- /*****************************************************************************
- * Routine to print the data from given object into given file FileName. *
- *****************************************************************************/
- void DataPrsrPutObject(char *FileName, ObjectStruct *PObj)
- {
- char *FileType = NULL, *Pchar;
- char FullFileName[LINE_LEN];
- FILE *f = NULL;
-
- DPGlblParserError = 0;
- VertexRoot = PolygonRoot = NULL;
-
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(LclLongJumpBuffer) != 0) {
- if (f != NULL) fclose(f);
- return;
- }
-
- switch (PObj -> ObjType) {
- case GEOMETRIC_OBJ:
- FileType = ".ply";
- break;
- case MATRIX_OBJ:
- FileType = ".mat";
- break;
- default:
- ParserError(DP_ERR_OnlyMatGeomObj, "");
- }
-
- if ((Pchar = strchr(FileName, '.')) != (char *) NULL)
- *Pchar = NULL; /* Make sure no file type is given. */
- if (strlen(FileName) == 0) ParserError(DP_ERR_EmptyName, "");
-
- strcpy(FullFileName, FileName);
- strcat(FullFileName, FileType);
-
- if ((f = fopen(FullFileName, "w")) == NULL)
- ParserError(DP_ERR_OpenFail, FullFileName);
-
- switch (PObj -> ObjType) {
- case GEOMETRIC_OBJ:
- DataPrsrPutGeomObject(f, PObj);
- break;
- case MATRIX_OBJ:
- DataPrsrPutMatObject(f, PObj);
- break;
- }
-
- fclose(f);
- return;
- }
-
- /*****************************************************************************
- * Routine to print the data from given geometric object into given file f *
- *****************************************************************************/
- static void DataPrsrPutGeomObject(FILE *f, ObjectStruct *PObj)
- {
- int i, CountVertices = 0, BaseVertices, CountPolys = 0;
- char *s;
- struct PolygonStruct *PPoly = PObj -> U.Pl;
- struct VertexStruct *PVertex, *PVFirst;
-
- while (PPoly) {
- PVFirst = PVertex = PPoly -> V;
- BaseVertices = CountVertices; /* To know index of first vertex. */
- if (PVertex == NULL)
- FatalError("DataPrsrPutGeomObject: Attemp to dump empty polygon, exit\n");
-
- do { /* Assume at list one edge in polygon! */
- if (IS_INTERNAL_EDGE(PVertex)) s = "[INTERNAL] ";
- else s = "";
-
- /* Make real zero, if number is smaller than EPSILON: */
- for (i=0; i<3; i++) if (ABS(PVertex -> Pt[i]) < EPSILON)
- PVertex -> Pt[i] = 0.0;
- # ifdef DOUBLE
- fprintf(f, "[VERTEX V%-3d %s%10lg %10lg %10lg]\n",
- # else
- fprintf(f, "[VERTEX V%-3d %s%10g %10g %10g]\n",
- # endif /* DOUBLE */
- CountVertices++, s,
- PVertex -> Pt[0], PVertex -> Pt[1], PVertex -> Pt[2]);
- PVertex = PVertex -> Pnext;
- }
- while (PVertex != PVFirst && PVertex != NULL);
-
- if (IS_POLYLINE_GEOM_OBJ(PObj))
- fprintf(f, "[POLYLINE P%-3d", CountPolys++);
- else {
- for (i=0; i<4; i++) if (ABS(PPoly -> Plane[i]) < EPSILON)
- PPoly -> Plane[i] = 0.0;
- # ifdef DOUBLE
- fprintf(f, "[POLYGON P%-3d [PLANE %10lg %10lg %10lg %10lg]",
- # else
- fprintf(f, "[POLYGON P%-3d [PLANE %10g %10g %10g %10lg]",
- # endif /* DOUBLE */
- CountPolys++, PPoly -> Plane[0], PPoly -> Plane[1],
- PPoly -> Plane[2], PPoly -> Plane[3]);
- }
-
- for (i=BaseVertices; i<CountVertices; i++) {
- if ((i-BaseVertices) % 10 == 0) fprintf(f, "\n\t");
- fprintf(f, "V%-3d ", i);
- }
- fprintf(f, "]\n\n");
-
- PPoly = PPoly -> Pnext;
- }
- fprintf(f, "[OBJECT %s [COLOR %d]", PObj -> Name, GET_OBJECT_COLOR(PObj));
- for (i=0; i<CountPolys; i++) {
- if (i % 10 == 0) fprintf(f, "\n\t");
- fprintf(f, "P%-4d", i);
- }
- fprintf(f, "]\n");
- }
-
- /*****************************************************************************
- * Routine to print the data from given matrix object into given file f *
- *****************************************************************************/
- static void DataPrsrPutMatObject(FILE *f, ObjectStruct *PObj)
- {
- int i, j;
-
- for (i=0; i<4; i++) {
- for (j=0; j<4; j++)
- # ifdef DOUBLE
- fprintf(f, "%17.8le ",
- # else
- fprintf(f, "%17.8e ",
- # endif /* DOUBLE */
- PObj -> U.Mat[i][j]);
- fprintf(f, "\n");
- }
- fprintf(f, "MATRIX %s\n", PObj -> Name);
- }
-
- /*****************************************************************************
- * Routine to read the data from a given file and scans for the Geometric *
- * object named ObjName. Returns a pointer to the data structure represent *
- * that geometic object. If ObjName is NULL, returns first object in file. *
- *****************************************************************************/
- ObjectStruct *DataPrsrGetObject(char *FileName, char *ObjName)
- {
- int i, ObjType;
- char FullFileName[LINE_LEN];
- FILE *f = NULL;
- ObjectStruct *PObj;
-
- DPGlblParserError = 0;
- VertexRoot = PolygonRoot = NULL;
-
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(LclLongJumpBuffer) != 0) {
- if (f != NULL) fclose(f);
- return NULL;
- }
-
- if (strlen(FileName) == 0) ParserError(DP_ERR_EmptyName, "");
-
- strcpy(FullFileName, FileName);
- if (strchr(FullFileName, '.') == NULL) strcat(FullFileName, ".ply");
-
- i = strlen(FullFileName) - 4;
- if (stricmp(&FullFileName[i], ".ply") == 0) ObjType = GEOMETRIC_OBJ;
- else
- if (stricmp(&FullFileName[i], ".mat") == 0) ObjType = MATRIX_OBJ;
- else
- ParserError(DP_ERR_WrongFileType, FullFileName);
-
- if ((f = fopen(FullFileName, "r")) == NULL)
- ParserError(DP_ERR_OpenFail, FullFileName);
-
- switch (ObjType) {
- case GEOMETRIC_OBJ:
- PObj = DataPrsrGetGeomObject(f, ObjName);
- break;
- case MATRIX_OBJ:
- PObj = DataPrsrGetMatObject(f);
- break;
- }
-
- fclose(f);
- return PObj;
- }
-
- /*****************************************************************************
- * Routine to read the data from a given file and scans for the Geometric *
- * object named ObjName. Returns a pointer to the data structure represent *
- * that geometic object. If ObjName is NULL, returns first object in file. *
- *****************************************************************************/
- static ObjectStruct *DataPrsrGetGeomObject(FILE *f, char *ObjName)
- {
- int i, PlaneDefined, PolyType = 0, Color;
- char StringToken[LINE_LEN], CrntObjName[OBJ_NAME_LEN];
- struct BinTree *PBinTree;
- struct VertexStruct *PVertex;
- struct PolygonStruct *PPolygon;
- struct ObjectStruct *PObject;
-
- VertexRoot = PolygonRoot = NULL; /* Start from empty trees. */
- GlblToken = 0;
- DPGlblLineCount = 1; /* Reset line counter. */
-
- EliminateComments(f); /* Skip all comments including '['. */
-
- /* Set the long jump address to trap errors, and start the parser: */
- while (!feof(f)) {
- switch (GetToken(f, StringToken)) {
- case TKN_VERTEX:
- PVertex = AllocVertex(0, 0, NULL, NULL);
- PBinTree = AllocBinTree("", NULL, NULL, (VoidPtr) PVertex);
- GetToken(f, PBinTree -> Name); /* Get the name. */
- /* The following handles the optional attr definition: */
- if (GetToken(f, StringToken) == TKN_OPEN_PARAN) {
- GetVertexAttr(f, PVertex);
- }
- else {
- UnGetToken(StringToken);
- }
- /* The following handles reading of 3 coord. of vertex. */
- for (i=0; i<3 ;i++) {
- GetToken(f, StringToken);
- # ifdef DOUBLE
- if (sscanf(StringToken, "%lf", &PVertex -> Pt[i]) != 1)
- # else
- if (sscanf(StringToken, "%f", &PVertex -> Pt[i]) != 1)
- # endif /* DOUBLE */
- ParserError(DP_ERR_NumberExpected, StringToken);
- }
- if ((i=GetToken(f, StringToken)) != TKN_CLOSE_PARAN)
- ParserError(DP_ERR_CloseParanExpected, StringToken);
- InsertBinTree(&VertexRoot, PBinTree);
- break;
- case TKN_POLYGON:
- if (PolyType && PolyType != TKN_POLYGON)
- ParserError(DP_ERR_MixedPolygonLine, "");
- else PolyType = TKN_POLYGON;
- PPolygon = AllocPolygon(NULL, NULL, 0, 0);
- RST_CONVEX_POLY(PPolygon); /* May be not convex! */
- PBinTree = AllocBinTree("", NULL, NULL, (VoidPtr) PPolygon);
- GetToken(f, PBinTree -> Name); /* Get the name. */
- /* The following handles the optional attr definition: */
- PlaneDefined = FALSE;
- if (GetToken(f, StringToken) == TKN_OPEN_PARAN) {
- GetPolyAttr(f, PPolygon, &PlaneDefined);
- }
- else {
- UnGetToken(StringToken);
- }
- /* The following handles reading the vertex list */
- PPolygon -> V = GetVertexList(f, VertexRoot, PolyType);
- if (!PlaneDefined) DPUpdatePolyPlane(PPolygon);
- InsertBinTree(&PolygonRoot, PBinTree);
- break;
- case TKN_POLYLINE:
- if (PolyType && PolyType != TKN_POLYLINE)
- ParserError(DP_ERR_MixedPolygonLine, "");
- else PolyType = TKN_POLYLINE;
- PPolygon = AllocPolygon(NULL, NULL, 0, 0);
- PBinTree = AllocBinTree("", NULL, NULL, (VoidPtr) PPolygon);
- GetToken(f, PBinTree -> Name); /* Get the name. */
- /* The following handles the optional attr definition: */
- PlaneDefined = FALSE;
- if (GetToken(f, StringToken) == TKN_OPEN_PARAN) {
- GetPolyAttr(f, PPolygon, &PlaneDefined);
- }
- else {
- UnGetToken(StringToken);
- }
- /* The following handles reading the vertex list */
- PPolygon -> V = GetVertexList(f, VertexRoot, PolyType);
- if (!PlaneDefined) DPUpdatePolyPlane(PPolygon);
- InsertBinTree(&PolygonRoot, PBinTree);
- break;
- case TKN_OBJECT:
- PObject = GenGeomObject("", NULL, NULL);
- GetToken(f, CrntObjName); /* Get the name. */
- Color = LoadColor;
- if (GetToken(f, StringToken) == TKN_OPEN_PARAN) {
- GetObjectAttr(f, &Color);
- }
- else {
- UnGetToken(StringToken);
- }
- /* The following handles reading the polygon list. */
- /* Note object might be created from Polygons/lines only. */
- PObject -> U.Pl = GetPolyList(f, PolygonRoot);
- if (ObjName == NULL || strlen(ObjName) == 0 ||
- strcmp(CrntObjName, ObjName) == 0) {
- /* We got it - free unused data and return it: */
- DataPrsrFreeAll(VertexRoot, PolygonRoot);
- if (PolyType == TKN_POLYLINE)
- SET_POLYLINE_GEOM_OBJ(PObject);/* Mark as polyline.*/
- SET_OBJECT_COLOR(PObject, Color);
- return PObject;
- }
- else {
- PObject -> U.Pl = NULL; /* Dont free the polys twice! */
- MyFree((VoidPtr) PObject, OBJECT_TYPE);/* Not the one! */
- }
- break;
- default:
- ParserError(DP_ERR_UndefExprHeader, StringToken);
- break;
- } /* of switch */
- if (!feof(f)) EliminateComments(f);/* Skip comments including '['. */
- } /* of while !eof */
-
- /* If we are here, object was not found in file - return NULL. */
- DataPrsrFreeAll(VertexRoot, PolygonRoot);
- return NULL;
- }
-
- /*****************************************************************************
- * Routine to read the data from a given file and scans for the Matrix *
- * object. The file is assumed to hold 16 (4 by 4 matrix) float numbers. *
- *****************************************************************************/
- static ObjectStruct *DataPrsrGetMatObject(FILE *f)
- {
- int i, j;
- MatrixType Mat;
-
- for (i=0; i<4; i++)
- for (j=0; j<4; j++)
- if (1 !=
- # ifdef DOUBLE
- fscanf(f, "%lg",
- # else
- fscanf(f, "%g",
- # endif /* DOUBLE */
- &Mat[i][j]))
- ParserError(DP_ERR_NonMatrixObject, "");
-
- return GenMatObject("", Mat, NULL);
- }
-
- /*****************************************************************************
- * Routine to update the Plane equation of the given polygon by the order *
- * of the first 3 vertices of that polygon. *
- *****************************************************************************/
- static void DPUpdatePolyPlane(PolygonStruct *PPoly)
- {
- int i;
- VectorType V1, V2;
- RealType Len;
- struct VertexStruct *V;
-
- V = PPoly -> V; PT_SUB(V1, V -> Pt, V -> Pnext -> Pt);
- V = V -> Pnext; PT_SUB(V2, V -> Pt, V -> Pnext -> Pt);
-
- VecCrossProd(PPoly -> Plane, V1, V2); /* Find Plane Normal. */
-
- PPoly -> Plane[3] = (-DOT_PROD(PPoly -> Plane, PPoly -> V -> Pt));
-
- /* Normalize the plane such that the normal has length of 1: */
- Len = PT_LENGTH(PPoly -> Plane);
- for (i=0; i<4; i++) PPoly -> Plane[i] /= Len;
- }
-
- /*****************************************************************************
- * Allocate one BinTree Structure: *
- *****************************************************************************/
- static struct BinTree * AllocBinTree(char *Name,
- BinTree * Right, BinTree * Left, VoidPtr Ptr)
- {
- struct BinTree *p;
-
- p = (BinTree *) MyMalloc(sizeof(BinTree), OTHER_TYPE);
-
- strcpy(p -> Name, Name);
- p -> Right = Right;
- p -> Left = Left;
- p -> U.PVoid = Ptr;
-
- return p;
- }
-
- /*****************************************************************************
- * Free all the old data saved in the vertices/polygons trees. *
- * Note that unused vertices/polygons are also freed (tested via their Count) *
- *****************************************************************************/
- static void DataPrsrFreeAll(BinTree *VertexRoot, BinTree *PolygonRoot)
- {
- DataPrsrFreeTree(VertexRoot, VERTEX_TYPE);
- DataPrsrFreeTree(PolygonRoot, POLYGON_TYPE);
- }
-
- /*****************************************************************************
- * Free all the old data saved in the vertices/polygons trees. *
- * Note that all vertices/polygons are also freed. *
- *****************************************************************************/
- static void DataPrsrFreeTree(BinTree *Root, int ObjType)
- {
- if (Root == NULL) return;
-
- DataPrsrFreeTree(Root->Right, ObjType);
- DataPrsrFreeTree(Root->Left, ObjType);
-
- switch (ObjType) {
- case VERTEX_TYPE:
- MyFree((char *) Root->U.PVertex, VERTEX_TYPE);
- break;
- case POLYGON_TYPE:
- MyFree((char *) Root->U.PPolygon, POLYGON_TYPE);
- break;
- }
- }
-
- /*****************************************************************************
- * Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) *
- *****************************************************************************/
- static void UnGetToken(char *StringToken)
- {
- if (GlblToken >= UNGET_STACK_SIZE) {
- ParserError(DP_ERR_InternalStackOF, StringToken);
- return;
- }
-
- strcpy(GlblStringToken[GlblToken], StringToken);
- GlblToken++; /* GlblToken exists - Something in it (no overflow check). */
- }
-
- /*****************************************************************************
- * Routine to get the next token out of the input file f. *
- * Returns the next token found, as StringToken. *
- * Note: StringToken must be allocated before calling this routine! *
- *****************************************************************************/
- static void GetStringToken(FILE *f, char *StringToken)
- {
- int len;
- char c, *LocalStringToken;
-
- if (GlblToken) { /* get first the unget token */
- GlblToken--;
- strcpy(StringToken, GlblStringToken[GlblToken]);
- return;
- }
- /* skip white spaces: */
- while ((!feof(f))
- && (((c = getc(f)) == ' ') || (c == '\t') || (c == '\n')))
- if (c == '\n') DPGlblLineCount++; /* Count the lines. */
-
- LocalStringToken = StringToken;
- if (c == '[') /* Its a token by itself so return it. */
- *LocalStringToken++ = c; /* Copy the token into string. */
- else {
- if (!feof(f))
- do *LocalStringToken++ = c; /* Copy the token into string. */
- while ((!feof(f)) &&
- ((c = getc(f)) != ' ') && (c != '\t') && (c != '\n'));
- if (c == '\n') ungetc(c, f); /* Save it to be counted next time. */
- }
- *LocalStringToken = NULL; /* Put eos. */
-
- /* The following handles the spacial case were we have XXXX] - we must */
- /* split it into two token XXXX and ], UnGetToken(']') and return XXXX: */
- if ((StringToken[len = strlen(StringToken)-1] == ']') && (len > 0)) {
- /* Return CloseParan */
- UnGetToken(&StringToken[len]); /* Save next token. */
- StringToken[len] = NULL; /* Set end of string on "]". */
- }
- }
-
- /*****************************************************************************
- * Routine to get the next token out of the input file f as token number. *
- * Returns the next token number found, with numeric result in NumericToken *
- * if TokenType is TKN_NUMBER. *
- * Note: StringToken must be allocated before calling this routine! *
- *****************************************************************************/
- static int GetToken(FILE *f, char *StringToken)
- {
- int RetVal;
-
- GetStringToken(f, StringToken);
-
- if (feof(f)) RetVal = TKN_EOF;
-
- else
- if (!strcmp(StringToken, "[")) RetVal = TKN_OPEN_PARAN;
- else
- if (!strcmp(StringToken, "]")) RetVal = TKN_CLOSE_PARAN;
- else
-
- if (!strcmp(StringToken, "VERTEX")) RetVal = TKN_VERTEX;
- else
- if (!strcmp(StringToken, "POLYGON")) RetVal = TKN_POLYGON;
- else
- if (!strcmp(StringToken, "POLYLINE")) RetVal = TKN_POLYLINE;
- else
- if (!strcmp(StringToken, "OBJECT")) RetVal = TKN_OBJECT;
-
- else
- if (!strcmp(StringToken, "PLANE")) RetVal = TKN_PLANE;
- else
- if (!strcmp(StringToken, "INTERNAL")) RetVal = TKN_INTERNAL;
- else
- if (!strcmp(StringToken, "COLOR")) RetVal = TKN_COLOR;
-
- else
- RetVal = TKN_OTHER; /* Must be number or name. */
-
- return RetVal;
- }
-
- /*****************************************************************************
- * Routine to read the input tokens up to a '[' token - skip comments. *
- * Note the routine reads the '[' token, so next is the expression itself. *
- *****************************************************************************/
- static void EliminateComments(FILE *f)
- {
- char StringToken[LINE_LEN];
-
- while ((!feof(f)) && (GetToken(f, StringToken) != TKN_OPEN_PARAN));
- }
-
- /*****************************************************************************
- * Routine to print pasring error according to ErrNum and set GlblParserError.*
- *****************************************************************************/
- static void ParserError(int ErrNum, char *Msg)
- {
- DPGlblParserError = ErrNum;
- strcpy(DPGlblTokenError, Msg); /* Keep the message in safe place... */
-
- DataPrsrFreeAll(VertexRoot, PolygonRoot); /* In case of non empty trees. */
- VertexRoot = PolygonRoot = NULL;
-
- longjmp(LclLongJumpBuffer, 1); /* Jump to... */
- }
-
- /*****************************************************************************
- * Routine to insert new element into a binary tree. If the element already *
- * exists then the new one replace it. *
- *****************************************************************************/
- static void InsertBinTree(BinTree **Tree, BinTree *PNewRecord)
- {
- int Comparison;
-
- if (*Tree == NULL) /* Only might happen if tree empty. */
- *Tree = PNewRecord;
- else { /* Search for the new place to put it */
- /* Test for Match - if so replace old by new: */
- if ((Comparison = strcmp((*Tree) -> Name, PNewRecord -> Name)) == 0) {
- ParserError(DP_ERR_SameName, PNewRecord -> Name);
- return;
- }
- else if (Comparison > 0) /* go to right side - its bigge.r */
- InsertBinTree(&((*Tree) -> Right), PNewRecord);
- else InsertBinTree(&((*Tree) -> Left), PNewRecord); /* smaller. */
- }
- }
-
- /*****************************************************************************
- * Routine to Get an element from binary tree. If the element is found a *
- * pointer to it BinTree record is return, NULL else... *
- *****************************************************************************/
- static BinTree *GetBinTree(char *Name, BinTree *Tree)
- {
- int Comparison;
-
- /* If the tree is empty - not found, return NULL: */
- if (Tree == (BinTree *) NULL) return (BinTree *) NULL;
-
- /* Test for Match - if so return that record: */
- if ((Comparison = strcmp(Tree -> Name, Name)) == 0)
- return Tree; /* Found it - so return it ... */
- else if (Comparison > 0)
- return GetBinTree(Name, Tree -> Right);
- else return GetBinTree(Name, Tree -> Left);
- }
-
- /*****************************************************************************
- * Routine to get linear list of names from file f until ']' is detected. *
- * search for that names in BinTree VetrexRoot. *
- * Create a linear list of pointers to them. Return that linear list. *
- * If PolyType == TKN_POLYLINE, then the list in NULL terminated, otherwise *
- * (TKN_POLYGON) it is made circular. *
- *****************************************************************************/
- static struct VertexStruct *GetVertexList(FILE *f, struct BinTree *VertexRoot,
- int PolyType)
- {
- char StringToken[LINE_LEN];
- struct VertexStruct *PLinHead = NULL, *PLinTail = NULL;
- BinTree *PBin;
-
- while (GetToken(f, StringToken) != TKN_CLOSE_PARAN) {
- if ((PBin = GetBinTree(StringToken, VertexRoot)) == NULL) {
- ParserError(DP_ERR_ListCompUndef, StringToken); /* Record undef. */
- return NULL;
- }
- if (PLinHead == NULL) /* Its first record. */
- PLinHead = PLinTail = AllocVertex(0, 0, NULL, NULL);
- else { /* its record in the middle. */
- PLinTail -> Pnext = AllocVertex(0, 0, NULL, NULL);
- PLinTail = PLinTail -> Pnext;
- }
-
- /* Copy the point coordinates: */
- PT_COPY(PLinTail -> Pt, PBin -> U.PVertex -> Pt);
- PLinTail -> Count = PBin -> U.PVertex -> Count;
- PLinTail -> Tags = PBin -> U.PVertex -> Tags;
- }
- if (PLinTail != NULL)
- if (PolyType == TKN_POLYLINE)
- PLinTail -> Pnext = NULL; /* Mark end of linear list. */
- else PLinTail -> Pnext = PLinHead; /* Make it circular list. */
-
- return PLinHead;
- }
-
- /*****************************************************************************
- * Routine to get linear list of polygons from file f, find them in the *
- * binary tree PolygonRoot, and concat them into a linear list. *
- *****************************************************************************/
- static struct PolygonStruct *GetPolyList(FILE *f, struct BinTree *PolygonRoot)
- {
- char StringToken[LINE_LEN];
- struct PolygonStruct *PLinHead = NULL, *PLinTail = NULL;
- BinTree *PBin;
-
- while (GetToken(f, StringToken) != TKN_CLOSE_PARAN) {
- if ((PBin = GetBinTree(StringToken, PolygonRoot)) == NULL) {
- ParserError(DP_ERR_ListCompUndef, StringToken); /* Record undef. */
- return NULL;
- }
- if (PLinHead == NULL) /* Its first record. */
- PLinHead = PLinTail = AllocPolygon(0, 0, NULL, NULL);
- else { /* Its record in the middle. */
- PLinTail -> Pnext = AllocPolygon(0, 0, NULL, NULL);
- PLinTail = PLinTail -> Pnext;
- }
- /* Polygon can be referred only one - we zap its vertex list: */
- if (PBin -> U.PPolygon -> V == NULL)
- ParserError(DP_ERR_PolyDupRefer, StringToken);
-
- PLANE_COPY(PLinTail -> Plane, PBin -> U.PPolygon -> Plane);
- PLinTail -> Count = PBin -> U.PPolygon -> Count;
- PLinTail -> Tags = PBin -> U.PPolygon -> Tags;
- PLinTail -> V = PBin -> U.PPolygon -> V;
- PBin -> U.PPolygon -> V = NULL;
- }
- if (PLinTail != NULL)
- PLinTail -> Pnext = NULL; /* Mark end of linear list. */
-
- return PLinHead;
- }
-
- /*****************************************************************************
- * Routine to get polygon/polyline attributes. Attribute is allways of the *
- * form [ATTR data1 data2 ...]. It is assumed the '[' was allready read. *
- *****************************************************************************/
- static void GetPolyAttr(FILE *f, PolygonStruct *PPolygon, int *PlaneDefined)
- {
- int i;
- char StringToken[LINE_LEN];
-
- *PlaneDefined = FALSE;
-
- switch (GetToken(f, StringToken)) {
- case TKN_PLANE:
- for (i=0; i<4; i++) {
- GetToken(f, StringToken);
- # ifdef DOUBLE
- if (sscanf(StringToken, "%lf", &PPolygon -> Plane[i]) != 1)
- # else
- if (sscanf(StringToken, "%f", &PPolygon -> Plane[i]) != 1)
- # endif /* DOUBLE */
- ParserError(DP_ERR_NumberExpected, StringToken);
- }
- if (GetToken(f, StringToken) != TKN_CLOSE_PARAN)
- ParserError(DP_ERR_CloseParanExpected, StringToken);
- *PlaneDefined = TRUE;
- break;
- default:
- ParserError(DP_ERR_UndefAttr, StringToken);
- break;
- }
- }
-
- /*****************************************************************************
- * Routine to get vertex attributes. Attribute is allways of the form: *
- * [ATTR data1 data2 ...]. It is assumed the '[' was allready read. *
- *****************************************************************************/
- static void GetVertexAttr(FILE *f, VertexStruct *PVertex)
- {
- char StringToken[LINE_LEN];
-
- switch (GetToken(f, StringToken)) {
- case TKN_INTERNAL:
- if (GetToken(f, StringToken) != TKN_CLOSE_PARAN)
- ParserError(DP_ERR_CloseParanExpected, StringToken);
- SET_INTERNAL_EDGE(PVertex);
- break;
- default:
- ParserError(DP_ERR_UndefAttr, StringToken);
- break;
- }
- }
-
- /*****************************************************************************
- * Routine to get object attributes. Attribute is allways of the form: *
- * [ATTR data1 data2 ...]. It is assumed the '[' was allready read. *
- *****************************************************************************/
- static void GetObjectAttr(FILE *f, int *Color)
- {
- int i;
- char StringToken[LINE_LEN];
-
- switch (GetToken(f, StringToken)) {
- case TKN_COLOR:
- GetToken(f, StringToken);
- if (sscanf(StringToken, "%d", &i) != 1)
- ParserError(DP_ERR_NumberExpected, StringToken);
- if (GetToken(f, StringToken) != TKN_CLOSE_PARAN)
- ParserError(DP_ERR_CloseParanExpected, StringToken);
- *Color = i;
- break;
- default:
- ParserError(DP_ERR_UndefAttr, StringToken);
- break;
- }
- }
-
- /*****************************************************************************
- * Routine to return evaluation error if happen one, zero elsewhere *
- *****************************************************************************/
- int DataPrsrParseError(char **ErrorMsg)
- {
- int Temp;
- char TempCopy[LINE_LEN];
-
- if ((Temp = DPGlblParserError) == 0) return 0;
-
- strcpy(TempCopy, DPGlblTokenError);
- DPGlblParserError = 0;
-
- switch (Temp) {
- case DP_ERR_NumberExpected:
- sprintf(DPGlblTokenError, "Line %d: Numeric data expected - found %s",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_CloseParanExpected:
- sprintf(DPGlblTokenError, "Line %d: ']' expected - found %s",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_ListCompUndef:
- sprintf(DPGlblTokenError, "Line %d: Undefined list element - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_UndefExprHeader:
- sprintf(DPGlblTokenError, "Line %d: Undefined TOKEN - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_InternalStackOF:
- sprintf(DPGlblTokenError, "Line %d: Internal stack O.F. (report it!)",
- DPGlblLineCount);
- break;
- case DP_ERR_SameName:
- sprintf(DPGlblTokenError, "Line %d: Item defined more than once - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_PolyDupRefer:
- sprintf(DPGlblTokenError, "Line %d: Polygon refered more than once - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_UndefAttr:
- sprintf(DPGlblTokenError, "Line %d: Undefined attribute - \"%s\"",
- DPGlblLineCount, TempCopy);
- break;
- case DP_ERR_OnlyMatGeomObj:
- sprintf(DPGlblTokenError, "Only matrix or geometric objects allowed");
- break;
- case DP_ERR_EmptyName:
- sprintf(DPGlblTokenError, "Empty file name was given");
- break;
- case DP_ERR_OpenFail:
- sprintf(DPGlblTokenError, "Fail to open file - %s", TempCopy);
- break;
- case DP_ERR_WrongFileType:
- sprintf(DPGlblTokenError, "Only '.mat' or '.ply' types allowed, found - %s",
- TempCopy);
- break;
- case DP_ERR_MixedPolygonLine:
- sprintf(DPGlblTokenError, "Line %d: Mixed polygon/polylines is not allowed is same file",
- DPGlblLineCount);
- break;
- case DP_ERR_NonMatrixObject:
- sprintf(DPGlblTokenError, "Line %d: No matrix object element found",
- DPGlblLineCount);
- break;
- default:
- sprintf(DPGlblTokenError, "Data file parser - undefined error");
- break;
- }
-
- *ErrorMsg = DPGlblTokenError;
-
- return Temp;
- }
-
- #ifdef DEBUG
-
- /*****************************************************************************
- * Routine to Print the Names in tree in lexicorgaphic order. Used only for *
- * debuging - to see trees content... *
- *****************************************************************************/
- static void PrintBinTree(BinTree *Tree)
- {
- /* If the tree is empty - not found, return NULL: */
- if (Tree == (BinTree *) NULL) return;
-
- PrintBinTree(Tree -> Right);
- printf("%s\n", Tree -> Name);
- PrintBinTree(Tree -> Left);
- }
-
- #endif /* DEBUG */
-