/****************************************************************************** * Bsp-Read.c - Bspline handling routines - read from file. * ******************************************************************************* * Written by Gershon Elber, Aug. 90. * ******************************************************************************/ #ifdef __MSDOS__ #include #endif /* __MSDOS__ */ #include #include #include #include "cagd_loc.h" /****************************************************************************** * Reads and returns a bspline curve. * * If error is found in reading the file, ErrStr is set to string describing * * it and Line to the line it occured in file. * * If no error is detected *ErrStr = NULL. * ******************************************************************************/ CagdCrvStruct *BspCrvReadFromFile(char *FileName, char **ErrStr, int *ErrLine) { FILE *f; char StringToken[LINE_LEN]; CagdCrvStruct *Crv, *CrvTail = NULL, *CrvList = NULL; if ((f = fopen(FileName, "r")) == NULL) { *ErrStr = "File not found"; return NULL; } while (_CagdGetToken(f, StringToken) == TOKEN_OPEN_PAREN) { _CagdUnGetToken(StringToken); Crv = BspCrvReadFromFile2(f, FALSE, ErrStr, ErrLine); if (CrvList == NULL) CrvList = CrvTail = Crv; else { CrvTail -> Pnext = Crv; CrvTail = Crv; } } fclose(f); return CrvList; } /****************************************************************************** * Reads and returns a bspline curve. * * If NameWasRead is TRUE, it is assumed prefix "[CURVE BSPLINE" has already * * been read. This is useful for a global parser which invokes this routine. * * For exactly this reason, the file is NOT closed in the end. * * If error is found in reading the file, ErrStr is set to string describing * * it and ErrLine to line it occured in file relative to begining of curve. * * If no error is detected *ErrStr is set to NULL. * ******************************************************************************/ CagdCrvStruct *BspCrvReadFromFile2(FILE *f, CagdBType NameWasRead, char **ErrStr, int *ErrLine) { CagdPointType PType; TokenNumType Token; int i, j, Length, Order, MaxCoord; char StringToken[LINE_LEN]; CagdCrvStruct *NewCrv; _CagdGlblLineCount = *ErrLine; if (!NameWasRead) { while ((Token = _CagdGetToken(f, StringToken)) != TOKEN_EOF && Token != TOKEN_OPEN_PAREN); /* We found beginning of definition - read one: */ if (_CagdGetToken(f, StringToken) != TOKEN_CURVE || _CagdGetToken(f, StringToken) != TOKEN_BSPLINE) { *ErrStr = "CURVE BSPLINE key words expected"; *ErrLine = _CagdGlblLineCount; return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) == TOKEN_OPEN_PAREN) { if ((*ErrStr = _CagdGetCurveAttributes(f)) != NULL) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; return NULL; } } else _CagdUnGetToken(StringToken); if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &Length) != 1) { *ErrStr = "BSPLINE Number of points expected"; *ErrLine = _CagdGlblLineCount; return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &Order) != 1) { *ErrStr = "BSPLINE Order expected"; *ErrLine = _CagdGlblLineCount; return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || strlen(StringToken) != 2 || (StringToken[0] != 'E' && StringToken[0] != 'P') || !isdigit(StringToken[1]) || atoi(&StringToken[1]) >= CAGD_MAX_PT_COORD) { *ErrStr = "BSPLINE Point type expected"; *ErrLine = _CagdGlblLineCount; return NULL; } PType = CAGD_MAKE_PT_TYPE(StringToken[0] == 'P', atoi(&StringToken[1])); NewCrv = BspCrvNew(Length, Order, PType); /* Read the knot vector first: */ if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OPEN_PAREN) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_KV) { *ErrStr = "KV expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } for (i = 0; i < Order + Length; i++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &NewCrv -> KnotVector[i]) != 1) { #else sscanf(StringToken, "%f", &NewCrv -> KnotVector[i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } /* Read the points themselves: */ MaxCoord = CAGD_NUM_OF_PT_COORD(PType); for (i = 0; i < Length; i++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OPEN_PAREN) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } if (CAGD_IS_RATIONAL_PT(PType)) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &NewCrv -> Points[W][i]) != 1) { #else sscanf(StringToken, "%f", &NewCrv -> Points[W][i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } } for (j = 1; j <= MaxCoord; j++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &NewCrv -> Points[j][i]) != 1) { #else sscanf(StringToken, "%f", &NewCrv -> Points[j][i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdCrvFree(NewCrv); return NULL; } *ErrLine = _CagdGlblLineCount; *ErrStr = NULL; return NewCrv; } /****************************************************************************** * Reads and returns a bspline surface. * * If error is found in reading the file, ErrStr is set to string describing * * it and Line to the line it occured in file. * * If no error is detected *ErrStr = NULL. * ******************************************************************************/ CagdSrfStruct *BspSrfReadFromFile(char *FileName, char **ErrStr, int *ErrLine) { FILE *f; char StringToken[LINE_LEN]; CagdSrfStruct *Srf, *SrfTail = NULL, *SrfList = NULL; if ((f = fopen(FileName, "r")) == NULL) { *ErrStr = "File not found"; return NULL; } while (_CagdGetToken(f, StringToken) == TOKEN_OPEN_PAREN) { _CagdUnGetToken(StringToken); Srf = BspSrfReadFromFile2(f, FALSE, ErrStr, ErrLine); if (SrfList == NULL) SrfList = SrfTail = Srf; else { SrfTail -> Pnext = Srf; SrfTail = Srf; } } fclose(f); return SrfList; } /****************************************************************************** * Reads and returns a bspline surface. * * If NameWasRead is TRUE, it is assumed prefix "[SURFACE BSPLINE" has already * * been read. This is useful for a global parser which invokes this routine. * * For exactly this reason, the file is NOT closed in the end. * * If error is found in reading the file, ErrStr is set to string describing * * it and ErrLine to the line it occured in file. * * If no error is detected *ErrStr = NULL. * ******************************************************************************/ CagdSrfStruct *BspSrfReadFromFile2(FILE *f, CagdBType NameWasRead, char **ErrStr, int *ErrLine) { int i, j, k, Len, ULength, VLength, UOrder, VOrder, MaxCoord; char StringToken[LINE_LEN]; CagdRType *KnotVector; CagdPointType PType; TokenNumType Token; CagdSrfStruct *NewSrf; _CagdGlblLineCount = *ErrLine; if (!NameWasRead) { while ((Token = _CagdGetToken(f, StringToken)) != TOKEN_EOF && Token != TOKEN_OPEN_PAREN); /* We found beginning of definition - read one: */ if (_CagdGetToken(f, StringToken) != TOKEN_SURFACE || _CagdGetToken(f, StringToken) != TOKEN_BSPLINE) { *ErrStr = "SURFACE BSPLINE key words expected"; *ErrLine = _CagdGlblLineCount; return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) == TOKEN_OPEN_PAREN) { if ((*ErrStr = _CagdGetSurfaceAttributes(f)) != NULL) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; return NULL; } } else _CagdUnGetToken(StringToken); if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &ULength) != 1 || (Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &VLength) != 1) { *ErrStr = "BSPLINE Number of points expected"; *ErrLine = _CagdGlblLineCount; return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &UOrder) != 1 || (Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || sscanf(StringToken, "%d", &VOrder) != 1) { *ErrStr = "BSPLINE Order expected"; *ErrLine = _CagdGlblLineCount; return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || strlen(StringToken) != 2 || (StringToken[0] != 'E' && StringToken[0] != 'P') || !isdigit(StringToken[1]) || atoi(&StringToken[1]) >= CAGD_MAX_PT_COORD) { *ErrStr = "BSPLINE Point type expected"; *ErrLine = _CagdGlblLineCount; return NULL; } PType = CAGD_MAKE_PT_TYPE(StringToken[0] == 'P', atoi(&StringToken[1])); NewSrf = BspSrfNew(ULength, VLength, UOrder, VOrder, PType); /* Read the knot vectors first: */ for (k = 0; k < 2; k++) { if (k == 0) { KnotVector = NewSrf -> UKnotVector; Len = NewSrf -> UOrder + NewSrf -> ULength; } else { KnotVector = NewSrf -> VKnotVector; Len = NewSrf -> VOrder + NewSrf -> VLength; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OPEN_PAREN) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_KV) { *ErrStr = "KV expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } for (i = 0; i < Len; i++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &KnotVector[i]) != 1) { #else sscanf(StringToken, "%f", &KnotVector[i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } } /* Read the points themselves: */ MaxCoord = CAGD_NUM_OF_PT_COORD(PType); for (i = 0; i < ULength * VLength; i++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OPEN_PAREN) { *ErrStr = "\"[\" expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } if (CAGD_IS_RATIONAL_PT(PType)) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &NewSrf -> Points[W][i]) != 1) { #else sscanf(StringToken, "%f", &NewSrf -> Points[W][i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } } for (j = 1; j <= MaxCoord; j++) { if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_OTHER || #ifdef CAGD_DOUBLE sscanf(StringToken, "%lf", &NewSrf -> Points[j][i]) != 1) { #else sscanf(StringToken, "%f", &NewSrf -> Points[j][i]) != 1) { #endif /* CAGD_DOUBLE */ *ErrStr = "Numeric data expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } } if ((Token = _CagdGetToken(f, StringToken)) != TOKEN_CLOSE_PAREN) { *ErrStr = "\"]\" expected"; *ErrLine = _CagdGlblLineCount; CagdSrfFree(NewSrf); return NULL; } *ErrStr = NULL; *ErrLine = _CagdGlblLineCount; return NewSrf; }