/* 24-384a Computational Geometry * Mechanical Engineering * Carnegie Mellon University * * Eric Paulsen * Programming Project * DrawBrickWall.c * *This Program was written to Interactively Draw Brick Walls using flexible *and versatile code. * */ #include #include typedef double Point[3]; /* type double 3D point */ typedef double Dim[3]; /* type double Dimensions array */ void BeginFile( Point StartRow, FILE *vrmlfile, char *filename ); void DrawBrickWall( Point StartWall, Dim WallDim, Dim BrickDim, double OffSet, int UseCornerBrick[2], FILE *vrmlfile ); void DrawBrickRow( int i, Point StartRow, Dim WallDim, Dim BrickDim, double OSDist, int UseCornerBrick[2], FILE *vrmlfile ); void DrawBrick( Dim BrickDim, FILE *vrmlfile ); double GetRandomNumber(); void CopyPoint( Point A, Point B ); void EndFile( FILE *vrmlfile ); void main() { Dim WallDim; /* ( Length, Height, Width ) */ Dim BrickDim; /* ( Length, Height, Width ) */ double OffSet; /* spacing offset from one row to the next */ int UseCornerBrick[2]; /* ( off/on, off/on ). 0 or 1 specifies the placement*/ /* of a corner brick at ( beginning, end ) */ Point StartWall; /* coordinates to start Wall at:( x, y, z )*/ char vrmlfname[256] = "BrickWall3.wrl"; FILE *vrmlfile; vrmlfile = fopen(vrmlfname, "w"); /*sets dimensions of brick*/ BrickDim[0] = 4; BrickDim[1] = 1; BrickDim[2] = 2; /*sets dimensions of wall*/ WallDim[0] = 5*BrickDim[0]; WallDim[1] = 5*BrickDim[1]; WallDim[2] = BrickDim[2]; OffSet = .5*BrickDim[0];/*defines the offset spaceing between rows*/ UseCornerBrick[0] = 1; UseCornerBrick[1] = 1; StartWall[0] = 0; StartWall[1] = 0; StartWall[2] = 0; BeginFile( StartWall, vrmlfile, vrmlfname ); DrawBrickWall( StartWall, WallDim, BrickDim, OffSet, UseCornerBrick, vrmlfile ); EndFile( vrmlfile ); } void BeginFile( Point StartPoint, FILE *vrmlfile, char *filename ) /* Writes beginning of vrml file. */ { fprintf(vrmlfile, "#VRML V1.0 ascii\n\n"); fprintf(vrmlfile, "DEF BackgroundColor Info { string \"1.0 1.0 1.0\" }"); fprintf(vrmlfile, "\t# White\n\n"); fprintf(vrmlfile, "Separator {\n"); fprintf(vrmlfile, "\t# %s \n", filename); fprintf(vrmlfile, "\tTranslation {translation %f", StartPoint[0]); fprintf(vrmlfile, " %f %f}\n",StartPoint[1],StartPoint[2]); } void DrawBrickWall( Point StartWall, Dim WallDim, Dim BrickDim, double OffSet, int UseCornerBrick[2], FILE *vrmlfile ) /* draws a wall at specified location of specified dimensions. */ { /*row counter, number of rows, 0 <-> 1 switch indicates*/ int row, Rows, OddEven; /*odd or even row*/ double OSDist; /* cumulative offset distance */ Point StartRow; /* coordinates to start Row at: (x, y, z) */ CopyPoint( StartRow, StartWall ); OddEven = 1; OSDist = BrickDim[0]; Rows = floor( (WallDim[1]/BrickDim[1]) ); for(row = 0; row < Rows; row++) { fprintf(vrmlfile, "\tSeparator { #row %d\n", row); DrawBrickRow( OddEven, StartRow, WallDim, BrickDim, OSDist, UseCornerBrick, vrmlfile ); StartRow[1] += BrickDim[1]; if(OddEven == 1){OddEven = 0;} else{OddEven = 1;} OSDist += OffSet; } } void DrawBrickRow( int i, Point StartRow, Dim WallDim, Dim BrickDim, double OSDist, int UseCornerBrick[2], FILE *vrmlfile ) /* Draws a row of bricks at the specified location. The algorith was designed to allow all configurations to use the same code to minimize duplication of code. */ { int j; double k, l, m;/*dummy variables*/ Dim PartialBrickDim1, PartialBrickDim2;/* partial(cut) brick dimensions */ int NB;/*Number of Uncut Bricks*/ Point StartBrick;/*Point where Brick is drawn*/ /*Initializes the partial brick dimensions*/ PartialBrickDim1[0] = BrickDim[0]; PartialBrickDim2[0] = BrickDim[0]; PartialBrickDim1[1] = BrickDim[1]; PartialBrickDim2[1] = BrickDim[1]; PartialBrickDim1[2] = BrickDim[2]; PartialBrickDim2[2] = BrickDim[2]; if(i==1){/*for even rows*/ PartialBrickDim1[0] = ( OSDist - floor( OSDist/BrickDim[0] )*BrickDim[0] ); } else{ /*for odd rows*/ k = floor( (OSDist - UseCornerBrick[0]*BrickDim[2])/BrickDim[0] )*BrickDim[0]; PartialBrickDim1[0] = ( OSDist - ( UseCornerBrick[0]*BrickDim[2] + k ) ); } l = BrickDim[2]*UseCornerBrick[i]; NB = floor( ( WallDim[0] - ( l + PartialBrickDim1[0] ) )/BrickDim[0] ); m = UseCornerBrick[1]*BrickDim[2]; PartialBrickDim2[0] = WallDim[0] - ( PartialBrickDim1[0] + m + NB*BrickDim[0] ); fprintf(vrmlfile, "\t\tTranslation {translation %f %f", StartRow[0], StartRow[1]); fprintf(vrmlfile, " %f}\n", StartRow[2]); if( (i == 0) && ( UseCornerBrick[i] == 1) ){/*inserts space for corner brick when*/ fprintf(vrmlfile, "\t\tTranslation {translation %f 0.0 0.0}\n", BrickDim[2] ); } /*on an odd row and when beginning brick is specified*/ if( PartialBrickDim1[0] > 0.01*BrickDim[0] ){/*Draws a partial brick only when*/ DrawBrick( PartialBrickDim1, vrmlfile ); /* brick is greater than minimum size*/ fprintf(vrmlfile, "\t\tTranslation {translation %f 0.0 0.0}\n", PartialBrickDim1[0]); } /*to avoid wasting file space with very short or zero length bricks*/ for( j = 0; j < NB; j++){/*draws regular bricks*/ DrawBrick( BrickDim, vrmlfile ); fprintf(vrmlfile, "\t\tTranslation {translation %f 0.0 0.0}\n", BrickDim[0]); } if( PartialBrickDim2[0] > 0.01*BrickDim[0] ){ DrawBrick( PartialBrickDim2, vrmlfile ); fprintf(vrmlfile, "\t\tTranslation {translation %f 0.0 0.0}\n", PartialBrickDim2[0]); } if( (i == 1) && ( UseCornerBrick[i] == 1) ){/*inserts space for corner brick when*/ fprintf(vrmlfile, "\t\tTranslation {translation %f 0.0 0.0}\n", BrickDim[2] ); } /*on an even row and when end corner brick is specified*/ fprintf(vrmlfile, "\t}\n"); } void DrawBrick( Dim BrickDim, FILE *vrmlfile ) /* Draws a Brick of specified dimensions to a specified file in vrml format. */ { fprintf(vrmlfile, "\t\tSeparator {\n"); fprintf(vrmlfile, "\t\t\tTranslation {translation %f", .5*BrickDim[0]); fprintf(vrmlfile, " %f %f}\n", .5*BrickDim[1], .5*BrickDim[2]); fprintf(vrmlfile, "\t\t\tMaterial { diffuseColor %2.1f ", GetRandomNumber() ); fprintf(vrmlfile, "%2.1f %2.1f }\n", GetRandomNumber(), GetRandomNumber() ); fprintf(vrmlfile, "\t\t\tCube {\n"); fprintf(vrmlfile, "\t\t\t\twidth %f\n",BrickDim[0]); fprintf(vrmlfile, "\t\t\t\theight %f\n",BrickDim[1]); fprintf(vrmlfile, "\t\t\t\tdepth %f\n",BrickDim[2]); fprintf(vrmlfile, "\t\t\t}\n\t\t}\n"); } void CopyPoint( Point A, Point B ) /* Copies point B to point A */ { int i; for(i=0; i<3; i++) {A[i]=B[i];} } double GetRandomNumber() { double i; int j; i = rand(); i /= 1e4; i -= floor(i); return i; } void EndFile( FILE *vrmlfile ) { fprintf(vrmlfile, "}\n"); fclose(vrmlfile); }