void read_PEP_file(char *filename, char **types, t_blockinfo *blocks, t_blockdest *dest) { FILE *infile; t_lookup *tbl; t_fieldinfo *fld; t_dest *dst; t_blockdest *sdest = dest; int i, len = 0, ch, num, num2, ralloc; char *restptr, *rtmp; HLinput_file = filename; HLinput_line = 1; /* Open the file, read the header. */ if (!(infile = fopen(filename, "r"))) nc_error("could not open file for reading"); ReadCmdToken(infile); if (strcmp(sbuf, "PEP")) nc_error("keyword `PEP' expected"); /* Check if the file's type (second line of file) is one of those that are allowed. */ ReadNewline(infile); ReadCmdToken(infile); for (; *types && strcmp(sbuf,*types); types++); if (!*types) nc_error("unexpected format identifier '%s'",sbuf); filetype = MYstrdup(sbuf); ReadNewline(infile); ReadCmdToken(infile); if (strncmp(sbuf, "FORMAT_N", 8)) nc_error("keyword 'FORMAT_N' or 'FORMAT_N2' expected"); tbl = (t_lookup*) MYmalloc(sizeof(t_lookup)*(128-' ')) - ' '; ReadNewline(infile); while (!feof(infile)) { /* Read next block id. */ ReadCmdToken(infile); blocktype = MYstrdup(sbuf); /* Identify block. */ for (; blocks->name && strcmp(blocks->name,sbuf); blocks++) if (!blocks->optional) nc_error("keyword '%s' expected",blocks->name); if (!blocks->name) nc_error("unknown keyword '%s'",sbuf); for (dest = sdest; dest->name; dest++) if (!strcmp(blocks->name,dest->name)) break; /* Set up tbl. */ for (i=' '; i<128; tbl[i++].type = 0); for (i=' '; i<128; tbl[i++].ptr = NULL); for (fld = blocks->field; fld->c; fld++) tbl[(int)fld->c].type = fld->type; if (!blocks->line) ReadNewline(infile); /* Read lines until next block begins. Every line yields one new entity of the type determined by the current block. */ for(;;) { if (isupper(ch = ReadCharComment(infile))) { char ch2 = getc(infile); ungetc(ch2,infile); /* We assume that uppercase letters at the start of a line always indicates a new block. */ if (isupper((int)ch2)) break; } if (feof(infile)) break; if (ch == '\n') continue; *(rtmp = restptr = MYmalloc(ralloc = 64)) = '\0'; /* If information about this block is wanted, take the information where to store data from dest. */ if (dest->name) for (dst = dest->destarray; dst->c; dst++) { t_lookup *l = tbl + dst->c; l->ptr = dst->ptr; switch(l->type) { case FT_STRING: case FT_COORDS: *(char**)(l->ptr) = NULL; break; case FT_NUMBER: case FT_FLAG: *(int*)(l->ptr) = 0; break; default: nc_error("internal error: don't " "know the type of field '%c'",dst->c); break; } } /* Parse until end of line. We assume that all information about an entity (place, transition etc.) is stored in one single line. */ while (ch != '\n') { if (isdigit(ch) || ch == '-') { /* Numbers are treated specially. x@y gets stored in the '@' field, and plain numbers are stored in the '0' field. */ ungetc(ch,infile); ReadNumber(infile,&num); if ((ch=ReadWhiteSpace(infile)) == '@' || ch == '<' || ch == '>') { ch = '@'; ReadNumber(infile,&num2); len = 24; } else { ungetc(ch,infile); ch = '0'; len = 12; } } else { if (ch == '\'' || ch == '"') ungetc(ch,infile); switch(tbl[ch].type) { case FT_STRING: ReadEnclString(infile); len = 3+strlen(sbuf); break; case FT_NUMBER: ReadNumber(infile,&num); len = 12; break; case FT_COORDS: ReadCoordinates(infile, &num, &num2); len = 24; break; case FT_FLAG: len = 1; break; default: nc_error("unknown token '%c'",ch); break; } } /* Store data in the memory locations specified by the dest array. If no location is given for a particular field, its contents are written to a 'rest' string. */ while (!tbl[ch].ptr && rtmp-restptr+len >= ralloc) { restptr = MYrealloc(restptr, ralloc += 64); rtmp = restptr + strlen(restptr); } switch(tbl[ch].type) { case FT_STRING: if (tbl[ch].ptr) *(char**)(tbl[ch].ptr) = MYstrdup(sbuf); else if (strchr("'\"",ch)) sprintf(rtmp,"\"%s\"",sbuf); else sprintf(rtmp,"%c\"%s\"",ch,sbuf); break; case FT_NUMBER: if (tbl[ch].ptr) *(int*)(tbl[ch].ptr) = num; else if (ch == '0') sprintf(rtmp,"%d ",num); else sprintf(rtmp,"%c%d",ch,num); break; case FT_COORDS: if (tbl[ch].ptr) { *((t_coords**)(tbl[ch].ptr)) = MYmalloc(sizeof(t_coords)); (*(t_coords**)(tbl[ch].ptr))->x = num; (*(t_coords**)(tbl[ch].ptr))->y = num2; } else if (ch == '@') sprintf(rtmp,"%d@%d ",num,num2); else sprintf(rtmp,"%c%d@%d",ch,num,num2); break; case FT_FLAG: if (tbl[ch].ptr) (*(int*)(tbl[ch].ptr))++; else sprintf(rtmp,"%c",ch); break; } if (!tbl[ch].ptr) rtmp += strlen(rtmp); ch = ReadCharComment(infile); } /* end of while */ /* When the whole line has been read, see if information about the current block is wanted - if so, call the corresponding hook function. */ if (dest->name) { if (dest->restptr) *(dest->restptr) = restptr; if (dest->hookfunc()) nc_error("read aborted"); } else free(restptr); HLinput_line++; } free(blocktype); if (!feof(infile)) ungetc(ch,infile); blocks++; } /* Check for mandatory blocks that didn't occur in the file. */ for (; blocks->name; blocks++) if (!blocks->optional) nc_error("section '%s' not found",blocks->name); free(tbl+' '); fclose(infile); }
// Reads the scene file and stores the information as PolygonGroup and Polygon structures bool ReadSceneFile(void) { FILE *SceneFile; // File pointer for the scene file PolygonGroup *Head = NULL; // Head of the linked list of polygon groups int nPolygons = 0; // Number of polygons read from the scene file Coordinate MaxCoordinates; // The maximum coordinates observed in the scene // Attempt to open the scene file if (fopen_s(&SceneFile, SceneFilename, "r") != 0) { printf("Could not open scene file '%s'\n", SceneFilename); return false; } else { // Flags used whilst reading scene file data bool EndOfFile; bool ReadingParameters; bool SuccessfulRead; bool FirstGroup; char *Buffer; // Text buffer for reading strings from the scene file char *Context = NULL; // Used for getting tokens from the buffer string char *Parameter; // Stores the identifier letter at the start of each scene file string char *Comment; // Used in removing comments from strings int LineCount; // Used for monitoring the position of errors in the scene file Coordinate CoordinateBuffer; // Stores coordinates read from the buffer Coordinate Offset; // Stores the current coordinate offset PolygonGroup *PolygonGroupBuffer; // Stores polygon group parameters as they are read from the file Polygon *PolygonBuffer; // Stores polygon parameters as they are read from the file Polygon **PolygonListTail; // Tail of the linked list of polygons // Allocate memory for a new polygon group and the coordinate buffer PolygonGroupBuffer = NewPolygonGroup(NULL); PolygonListTail = &PolygonGroupBuffer->PolygonList; // Initiate the buffers CoordinateBuffer.X = 0; CoordinateBuffer.Y = 0; CoordinateBuffer.Z = 0; Offset.X = 0; Offset.Y = 0; Offset.Z = 0; // Allocate memory for the buffer Buffer = (char*) malloc(200*sizeof(char)); // Initialise the flags EndOfFile = false; ReadingParameters = false; SuccessfulRead = true; FirstGroup = true; // Initialise the line count to 0 LineCount = 0; printf("\nReading polygon information from scene file '%s'\n\n", SceneFilename); // Read the scene file, one line at a time do { if (fgets(Buffer, 200, SceneFile) != NULL) { // Keep track of the line number LineCount++; // Search for and remove comments Comment = strstr(Buffer, "//"); if (Comment != NULL) { Comment[0] = NULL; // Replace with 0 to mark a new end of the string } // Remove leading whitespace and read the parameter type character (p,t,z,o,h,v) Parameter = strtok_s(Buffer, "\t ", &Context); if (Parameter != NULL) { switch (Parameter[0]) { // Read the electrical parameters case 'p': // Set the reading parameters flag, create a new polygon group and add the old one to the list ReadingParameters = true; // Add the polygon buffer to the list if this is not the first read if (FirstGroup == true) { FirstGroup = false; } else { AddPolygonGroupToList(&Head, PolygonGroupBuffer); PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer); PolygonListTail = &PolygonGroupBuffer->PolygonList; // FIXME: Should the offset be reset upon reading a 'p'? //Offset.X = 0; //Offset.Y = 0; //Offset.Z = 0; } SuccessfulRead = ReadParameters(&Context, PolygonGroupBuffer); break; // Read the wall thickness case 't': // If not currently reading parameters (i.e. not just read a p, z or t) create a new polygon group and add the old one to the list if (ReadingParameters == false) { ReadingParameters = true; AddPolygonGroupToList(&Head, PolygonGroupBuffer); PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer); PolygonListTail = &PolygonGroupBuffer->PolygonList; // FIXME: Should the offset be reset upon reading a 't'? //Offset.X = 0; //Offset.Y = 0; //Offset.Z = 0; } SuccessfulRead = ReadThickness(&Context, PolygonGroupBuffer); break; // Read the priority case 'z': // If not currently reading parameters (i.e. not just read a p, z or t) create a new polygon group and add the old one to the list if (ReadingParameters == false) { ReadingParameters = true; AddPolygonGroupToList(&Head, PolygonGroupBuffer); PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer); PolygonListTail = &PolygonGroupBuffer->PolygonList; // FIXME: Should the offset be reset upon reading a 'z'? //Offset.X = 0; //Offset.Y = 0; //Offset.Z = 0; } SuccessfulRead = ReadPriority(&Context, PolygonGroupBuffer); break; // Read the offset case 'o': SuccessfulRead = ReadCoordinates(&Context, &Offset); break; // Read a vertical polygon case 'v': // Ensure any previous polygons were also vertical if (ReadingParameters == false && PolygonGroupBuffer->Type != Vertical) { AddPolygonGroupToList(&Head, PolygonGroupBuffer); PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer); PolygonListTail = &PolygonGroupBuffer->PolygonList; } ReadingParameters = false; PolygonGroupBuffer->Type = Vertical; // Allocate memory for a new polygon structure with 2 vertices PolygonBuffer = NewPolygon(); PolygonBuffer->Vertices = (Coordinate*)malloc(2*sizeof(Coordinate)); // Read in 2 sets of coordinates while (ReadCoordinates(&Context, &CoordinateBuffer) == true) { // Increment the number of vertices and ensure only 2 are read for a vertical polygon if (PolygonBuffer->nVertices < 2) { PolygonBuffer->Vertices[PolygonBuffer->nVertices].X = CoordinateBuffer.X + Offset.X; PolygonBuffer->Vertices[PolygonBuffer->nVertices].Y = CoordinateBuffer.Y + Offset.Y; PolygonBuffer->Vertices[PolygonBuffer->nVertices].Z = CoordinateBuffer.Z + Offset.Z; } PolygonBuffer->nVertices++; } // Ensure both both vertices have been read if (PolygonBuffer->nVertices != 2) { SuccessfulRead = false; } else { nPolygons++; *PolygonListTail = PolygonBuffer; PolygonListTail = &(*PolygonListTail)->NextPolygon; } break; // Read a horizontal polygon case 'h': // Ensure any previous polygons were also horizontal if (ReadingParameters == false && PolygonGroupBuffer->Type != Horizontal) { AddPolygonGroupToList(&Head, PolygonGroupBuffer); PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer); PolygonListTail = &PolygonGroupBuffer->PolygonList; } ReadingParameters = false; PolygonGroupBuffer->Type = Horizontal; // Allocate memory for a new polygon structure with 2 vertices PolygonBuffer = NewPolygon(); PolygonBuffer->Vertices = (Coordinate*)malloc(50*sizeof(Coordinate)); // Read in at least 3 sets of coordinates while (ReadCoordinates(&Context, &CoordinateBuffer) == true) { // Increment the number of vertices and ensure there is enough memory for all of the vertices, reallocating 10 vertices at a time PolygonBuffer->Vertices[PolygonBuffer->nVertices].X = CoordinateBuffer.X + Offset.X; PolygonBuffer->Vertices[PolygonBuffer->nVertices].Y = CoordinateBuffer.Y + Offset.Y; PolygonBuffer->Vertices[PolygonBuffer->nVertices].Z = CoordinateBuffer.Z + Offset.Z; PolygonBuffer->nVertices++; } // Ensure at least 3 vertices have been read if (PolygonBuffer->nVertices < 3) { SuccessfulRead = false; } else { nPolygons++; *PolygonListTail = PolygonBuffer; PolygonListTail = &(*PolygonListTail)->NextPolygon; } PolygonBuffer->Vertices = (Coordinate*)realloc(PolygonBuffer->Vertices, PolygonBuffer->nVertices*sizeof(Coordinate)); break; } } } else if (feof(SceneFile) != 0) { EndOfFile = true; } } while (EndOfFile == false && SuccessfulRead == true); // Add the final group to the list AddPolygonGroupToList(&Head, PolygonGroupBuffer); // Free allocated memory free(Buffer); fclose(SceneFile); // Check to see if there were any errors in the scene file if (SuccessfulRead == false) { printf("Error in scene file, line %d\n", LineCount); // Free memory allocated to the polygons FreePolygonGroupList(Head); return false; } else { printf("Scene file parsed successfully\nRead %d polygons\n\n", nPolygons); } } // Find the maximum coordinates in the system and allocate enough memory for a rectangle of this size MaxCoordinates = FindMaxSize(Head); // Print information on the polygons to the display if (InputData.DisplayPolygonInformation.Flag == true) { PrintPolygonGroupList(Head); } // Allocate memory for the TLM grid AllocateGridMemory(MaxCoordinates); // Add the polygons into the grid AddPolygonsToGrid(Head); // Free memory allocated to the polygons FreePolygonGroupList(Head); // Calculate the reflection and transmission coefficients based on their impedances CalculateReflectionTransmissionCoefficients(); return true; }