// Include Files #include #include #include #include #include #include #include "trulla.h" #include "loadws.h" // External Declarations extern int showGrid; // Globals int wsSizeInCells; // wsWidthInCells * wsHgtInCells char workSpaceFile[15]; float feetPerGridel; int sizeOfCharInPix; int optionsLine; int gridelOffset; int xOffsetInPix, yOffsetInPix; // offset to cell center from upper left of cell int currCellXInPix, currCellYInPix; int maxXCoord, maxYCoord; int cellWidthInPix, cellHgtInPix; int currCellX, currCellY; int goalCellX, goalCellY; int wsWidthInCells, wsHgtInCells; int pathsAreDisplayed; GRIDEL * gridPtr; // Symbolic Constants #define BUFFER_SIZE 25 // size of buffer into which lines of workspace file are read // Function Prototypes void ReadWorkSpaceFile ( char wsFileName[] ); void DrawGrid (); void InitGridParams (); void ColorCell ( int left, int top, int right, int bottom, GRIDEL * tempGridPtr ); void DisplayOptions (); void DrawGoalIndicator (); ///////////////////////////////////////////////////////////////////// // Function: LoadFile // Purpose: Reads a workspace file, draws the corresponding grid // and initializes such values as workspace size and the initial // goal. See the specific functions for more detailed information. ///////////////////////////////////////////////////////////////////// void LoadFile ( char wsFileName[] ) { pathsAreDisplayed = 0; ReadWorkSpaceFile (wsFileName); InitGridParams (); if ( showGrid ) { DrawGrid (); DisplayOptions (); DrawGoalIndicator (); } } ///////////////////////////////////////////////////////////////////// // Function: ReadWorkSpaceFile // Purpose: Prompts the user for the name of the workspace file if // the name was not sent by the function call. Initializes the // size in cells of the workspace. Allocate memory for an array // of GRIDELs. Read the weight of each cell from the workspace // file into the corresponding GRIDEL of the array. All weights // are stored into the array as read except the obstacle weight; // if 'x' is read from the file, then MAXWGT (currently 15) is // stored in the GRIDEL. NOTE: This function assumes the // workspace is a rectangle. ///////////////////////////////////////////////////////////////////// void ReadWorkSpaceFile (char wsFileName[]) { char * endptr; char buffer [BUFFER_SIZE]; GRIDEL * tempGridPtr; char * tempRowWgts; int widthCount, hgtCount; FILE * fp; if (wsFileName == NULL) { printf ("Enter name of workspace file: "); scanf("%s",wsFileName); } strcpy(workSpaceFile,wsFileName); if ( ( fp = fopen ( workSpaceFile, "r" ) ) == NULL ) { printf ( "\nCannot open file %s\n", workSpaceFile ); printf ( "Press any key to halt."); getch(); exit (BADEXIT); } // read the number of feet per gridel from first line of file fgets ( buffer, BUFFER_SIZE, fp ); feetPerGridel = (float) strtod ( buffer, &endptr ); // read width and height from next two lines of file fgets ( buffer, BUFFER_SIZE, fp ); wsWidthInCells = (int) strtol ( buffer, &endptr, 10 ); // 10=decimal number fgets ( buffer, BUFFER_SIZE, fp ); wsHgtInCells = (int) strtol ( buffer, & endptr, 10 ); // 10=decimal number wsSizeInCells = wsWidthInCells * wsHgtInCells; // allocate memory for workspace gridels free ( gridPtr ); // free memory if any was previously allocated gridPtr = ( GRIDEL * ) malloc ( sizeof (GRIDEL) * wsSizeInCells ); tempGridPtr = gridPtr; if ( tempGridPtr == NULL || gridPtr == NULL ) { printf ("Could not allocate memory for tempGridPtr or gridPtr\n"); printf ( "Press any key to halt."); getch(); exit (BADEXIT); } // Allocate memory for a row of weights. See the note (below) at the point // where "fgets" reads into tempRowWgts for an explanation of why 3 is added // to the size of the memory allocated. tempRowWgts = ( char * ) malloc ( wsWidthInCells + 3 ); if ( tempRowWgts == NULL ) { printf ("Could not allocate memory for tempRowWgts\n"); printf ( "Press any key to halt."); getch(); exit (BADEXIT); } // initialize gridel wgts // valid file wgts: 1-9,x // valid r_weight wgts: 1-9,MAXWGT for ( hgtCount = 0; hgtCount < wsHgtInCells; hgtCount++ ) { // fgets reads (wsWidthInCells-1) so add 3: 1 for unread char, 1 for newline, // 1 for the null byte added to the end of the string by fgets fgets ( tempRowWgts, wsWidthInCells+3, fp ); for ( widthCount = 0; widthCount < wsWidthInCells; widthCount++ ) { tempGridPtr->r_weight = ( * (tempRowWgts+widthCount) == OBSTACLE ) ? MAXWGT : ( * (tempRowWgts+widthCount) - '0' ); tempGridPtr++; } } free ( tempRowWgts ); fclose ( fp ); } ///////////////////////////////////////////////////////////////////// // Function: InitGridParams // Purpose: Initializes some workspace-dependent variables (e.g., // size of a cell in pixels) and the goal cell. ///////////////////////////////////////////////////////////////////// void InitGridParams () { // -1 means there is no goal yet goalCellX = goalCellY = -1; // make the center cell the initial starting point currCellX = (wsWidthInCells - 1) / 2; currCellY = (wsHgtInCells - 1) / 2; // size of one cell in pixels cellWidthInPix = maxXCoord / wsWidthInCells; cellHgtInPix = maxYCoord / wsHgtInCells; // current position in pix is upper left of cell currCellXInPix = currCellX * cellWidthInPix; currCellYInPix = currCellY * cellHgtInPix; // the offset gets to the center of the cell xOffsetInPix = cellWidthInPix / 2; yOffsetInPix = cellHgtInPix / 2; // The variable gridelOffset is an offset from gridPtr to the desired // gridel within the array of gridels. Here, the offset points to the // center cell as defined above. gridelOffset = currCellY * wsWidthInCells + currCellX; } ///////////////////////////////////////////////////////////////////// // Function: DrawGrid // Purpose: Draws the workspace grid and colors each cell of the // grid to correspond to the weight of the cell. ///////////////////////////////////////////////////////////////////// void DrawGrid () { int left, top, right, bottom; int widthCount, hgtCount; GRIDEL * tempGridPtr; clrscr (); clearviewport (); setbkcolor ( BLACK ); tempGridPtr = gridPtr; for ( top = 0, bottom = cellHgtInPix, hgtCount = 0; hgtCount < wsHgtInCells; top = bottom, bottom += cellHgtInPix, hgtCount++ ) { for ( left = 0, right = cellWidthInPix, widthCount = 0; widthCount < wsWidthInCells; left = right, right += cellWidthInPix, widthCount++ ) { ColorCell ( left, top, right, bottom, tempGridPtr ); tempGridPtr++; } } } ///////////////////////////////////////////////////////////////////// // Function: DisplayOptions // Purpose: Displays the user options and the name of the current // workspace file. ///////////////////////////////////////////////////////////////////// void DisplayOptions () { setbkcolor ( BLACK ); // black setcolor ( WHITE ); // white outtextxy ( 0, optionsLine, "Load Workspace File Generate Paths Quit Current File: " ); // The name of the workspace file will display after the previous text but on // the same line. The previous text contains 69 characters which we want to // bypass. Each of these characters is multiplied by the size in pixels of // a character. outtextxy ( 69 * sizeOfCharInPix , optionsLine, workSpaceFile ); } ///////////////////////////////////////////////////////////////////// // Function: ColorCell // Purpose: Colors the indicated cell to represent the weight of // the cell. NOTE: The palette contains a gray scale from 0 to // MAXWGT which represents BLACK to WHITE. The r_weight values // range from 0 to MAXWGT as well; however, the higher the number, // the darker will the cell be drawn. There was an unsightly white // border around the grid when the palette was changed so that 0 // to MAXWGT represented WHITE to BLACK instead of BLACK to WHITE. // This explains why setfillstyle() is called with MAXWGT - r_weight. ///////////////////////////////////////////////////////////////////// void ColorCell ( int left, int top, int right, int bottom, GRIDEL * tempGridPtr ) { setcolor ( BLACK ); setfillstyle ( SOLID_FILL, MAXWGT - tempGridPtr->r_weight ); bar3d ( left, top, right, bottom, 0, 0 ); } ///////////////////////////////////////////////////////////////////// // Function: DrawGoalIndicator // Purpose: Draws an asterisk (the goal indicator) in the current // cell to indicate that this cell will be considered the goal // when the option to generate paths is selected. The color of // the goal indicator depends on the gridel color. The indicator // drawn in black is more noticeable on gray background shades // which correspond to r_weight values up to and including 5; the // indicator drawn in white is better for r_weight values from 6 // through MAXWGT. ///////////////////////////////////////////////////////////////////// void DrawGoalIndicator () { // valid wgts:1-9,MAXWGT if ( (gridPtr+gridelOffset)->r_weight <= 5 ) setcolor ( BLACK ); else setcolor ( WHITE ); outtextxy ( currCellXInPix + xOffsetInPix, currCellYInPix + yOffsetInPix, "*" ); }