/*************************************************************************** * PRINTTILING.C * * version 1.5 * * Written by Matthew Blum 3-15-97 * * Updated last by Matthew Blum 4-24-97 * * * * printtiling takes in a vax file of a matching and creates a postscript * * picture of the corresponding tiling. * **************************************************************************/ #include #include "allocate.h" #include "string.h" #define SMALL 0 #define LARGE 1 #define TRUE 1 #define FALSE 0 #define INVALID 99 #define OUTLINE 1 #define SHADE 2 #define DOMINO 3 #define LOZENGE 4 #define DIABOLO 5 #define DUNGEON 6 #define THIRD 7 #define DRAGON 8 /* print listing of command line arguments */ void printerror(void); /* print different types of tilings */ void domino(void); void lozenge(void); void diabolo(void); void dungeon(void); void third(void); void dragon(void); /* global information about a tiling*/ int maxrow, maxcol, startrow, startcol, method = SHADE; char **vax; void main(int argc, char **argv) { int okay, tiling = DOMINO; int row, col, count, offrow = 0, offcol = 0, start; int titleexist = FALSE; char current, tabwarn = FALSE; char title[100], line[100]; FILE *fp; /* read in command line arguments */ if (argc > 1) if (!strcmp(argv[1],"-help")) printerror(); if (argc == 1 || argv[1][0] == '-') { fp = stdin; start = 1; } else { start = 2; fp = fopen(argv[1],"r"); if (fp == NULL) { printf("Could not open %s for input.\n",argv[1]); exit(1); } } for (count = start; count < argc; count ++) if (!strcmp(argv[count],"-outline")) method = OUTLINE; else if (!strcmp(argv[count],"-shade")) method = SHADE; else if (!strcmp(argv[count],"-domino")) tiling = DOMINO; else if (!strcmp(argv[count],"-lozenge")) tiling = LOZENGE; else if (!strcmp(argv[count],"-diabolo")) tiling = DIABOLO; else if (!strcmp(argv[count],"-dungeon")) tiling = DUNGEON; else if (!strcmp(argv[count],"-third")) tiling = THIRD; else if (!strcmp(argv[count],"-dragon")) tiling = DRAGON; else if (!strcmp(argv[count],"-help")) printerror(); else if (!strcmp(argv[count],"-offset")) { sscanf(argv[count+1],"%d",&offrow); sscanf(argv[count+2],"%d",&offcol); count += 2; } else { printf("Unknown command line argument %s.\n",argv[count]); exit(1); } /* parse comments in header */ do { fgets(line, 100, fp); /* look for title */ if (line[0] == '#') if (line[1] == 'T' && line[2] == 'i' && line[3] == 't') { strcpy(title, line + 8); titleexist = TRUE; } } while (line[0] == '#'); /* get size */ sscanf(line,"%d %d",&maxrow,&maxcol); if (maxrow == 0 || maxcol == 0) { printf("Invalid input file.\n"); exit(1); } /* make space with one space of padding on all four sides*/ vax = (char **) Allocate_2D(maxrow + 2, maxcol + 2, 1); /* initialize array */ for (row = 0; row < maxrow + 2; row++) for (col = 0; col < maxcol + 2; col++) vax[row][col] = ' '; okay = TRUE; /* is this a valid matching?...not yet */ for (row = 0; row <= maxrow; row ++) { for (col = 0; col <= maxcol; col ++) { current = fgetc(fp); if (feof(fp) == FALSE) { if (strchr("AV<> \t\n",current) == NULL) { printf("Illegal character '%c' in input file at row %d col %d.\n",current, row, col); exit(1); } /* display warning if tabs are present */ if (current == '\t') if (tabwarn == FALSE) { fprintf(stderr,"Warning, in input file being interpreted as single space.\n"); tabwarn = TRUE; current = ' '; } /* add one to col and row for padding */ if (current != '\n') vax[row+1][col+1] = current; if (current == '\n') col = maxcol + 3; } else { row = maxrow + 3; col = maxcol + 3; } } if (col < maxcol + 3) { printf("The input file size does not indicate enough columns.\n"); exit(1); } } if (row < maxrow + 3) { printf("The input file size does not indicate enough rows.\n"); exit(1); } /* parse through matching and look for tiles */ /* look for starting place */ for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) if (vax[row][col] != ' ') { startrow = row + offrow; startcol = col + offcol; row = maxrow + 2; col = maxcol + 2; } /* print header for postscript file */ printf("%%!Ps-Adobe-2.1\n"); printf("%%%%Title: Random tiling\n"); printf("%%%%Creator: printtiling.c\n"); printf("%%%%BoundingBox: 40 40 568 752\n"); printf("%%%%EndComments\n"); printf("30 dict begin gsave\n"); printf("0 setlinewidth\n"); printf("/cshow {dup stringwidth pop -2 div 0 rmoveto show} def\n"); if (tiling == DOMINO) domino(); if (tiling == LOZENGE) lozenge(); if (tiling == DIABOLO) diabolo(); if (tiling == DUNGEON) dungeon(); if (tiling == THIRD) third(); if (tiling == DRAGON) dragon(); printf("grestore \n"); if (titleexist) { printf("/Times-Roman findfont 14 scalefont setfont\n"); printf("304 40 moveto (%s) cshow\n", title); } printf("showpage end\n"); } void printerror(void) { printf("Usage for printtiling: printtiling [options]\n"); printf("If matchingfile isn't specified, reads it from stdin\n"); printf("where [options] are :\n"); printf(" -domino draws a domino tiling\n"); printf(" -lozenge draws a lozenge tiling\n"); printf(" -diabolo draws a diabolo tiling\n"); printf(" -dungeon draws a dungeon tiling\n"); printf(" -third draws a third diagonal tiling\n"); printf(" -dragon draws a dragon tiling\n"); printf(" -shade shade tiles different colors\n"); printf(" -outline only draw outlines of the tiles\n"); printf(" -offset row col offset grid by (row, col)\n"); printf(" -help display this help message\n"); printf("Default is domino tilings with shaded tiles with no offset.\n"); exit(1); } void domino(void) { int row, col, relrow, relcol, shape; char current; printf("/block {%f mul} def\n",508.0/maxcol); printf("/dompath {moveto rotate 2 block 0 rlineto 0 1 block rlineto\n"); printf(" -2 block 0 rlineto closepath} def\n"); if (method == OUTLINE) { printf("/dom {6 -1 roll add block exch 5 -1 roll add block gsave\n"); printf(" dompath stroke grestore pop} def\n"); } else { printf("/dom {6 -1 roll add block exch 5 -1 roll add block\n"); printf(" 4 -1 roll gsave setgray 3 copy dompath fill stroke\n"); printf(" grestore gsave dompath stroke grestore} def\n"); } printf("/shape0 {.9 0 1 -1 dom} def\n"); printf("/shape1 {.7 90 0 0 dom} def\n"); printf("/shape2 {.5 0 1 -2 dom} def\n"); printf("/shape3 {.3 90 1 0 dom} def\n"); printf("54 792 %d block sub 2 div translate\n",maxrow + 2); for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relrow = (row - startrow + 4000) % 2; relcol = (col - startcol + 4000) % 2; shape = INVALID; if (relrow ^ relcol == 0) { current = vax[row][col]; if (current == '<') shape = 0; if (current == 'A') shape = 1; if (current == '>') shape = 2; if (current == 'V') shape = 3; } if (shape != INVALID) printf("%d %d shape%d\n",col, maxrow - row, shape); } } void lozenge(void) { int row, col, relrow, relcol, shape; char current; printf("/block {%f mul} def\n",508.0/(maxcol + 1)); printf("/r3block {block 3 sqrt mul} def\n"); printf("/lozpath {moveto rotate 2 block 0 rlineto 1 block 1 r3block\n"); printf(" rlineto -2 block 0 rlineto closepath} def\n"); if (method == OUTLINE) { printf("/loz {6 -1 roll add block exch 5 -1 roll add r3block gsave\n"); printf(" lozpath stroke grestore pop} def\n"); } else { printf("/loz {6 -1 roll add block exch 5 -1 roll add r3block\n"); printf(" 4 -1 roll gsave setgray 3 copy lozpath fill stroke\n"); printf(" grestore gsave lozpath stroke grestore} def\n"); } printf("/shape0 {.9 0 0 -1 loz} def\n"); printf("/shape1 {.6 120 0 1 loz} def\n"); printf("/shape2 {.3 240 1 0 loz} def\n"); printf("54 792 %d r3block sub 2 div translate\n",maxrow); for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relrow = (row - startrow + 4000) % 2; relcol = (col - startcol + 4000) % 2; shape = INVALID; if (relrow ^ relcol == 0) { current = vax[row][col]; if (current == '<') shape = 0; if (current == 'A') shape = 2; if (current == '>') shape = 1; } if (shape != INVALID) printf("%d %d shape%d\n",col, maxrow - row, shape); } } void diabolo(void) { int row, col, relrow, relcol, shape; char current; printf("/block {%f mul} def\n",1016.0/maxcol); printf("/tripath {moveto rotate 1 block -1 block rlineto -2 block\n"); printf(" 0 rlineto closepath} def\n"); printf("/sqpath {moveto 1 block 0 rlineto 0 1 block rlineto -1 block\n"); printf(" 0 rlineto closepath} def\n"); if (method == OUTLINE) { printf("/tri {5 -1 roll add block exch 4 -1 roll add block gsave\n"); printf(" tripath stroke grestore} def\n"); printf("/sq {4 -1 roll add block exch 3 -1 roll add block sqpath\n"); printf(" stroke} def\n"); } else { printf("/tri {5 -1 roll add block exch 4 -1 roll add block gsave\n"); printf(" 3 copy tripath .9 setgray fill stroke grestore\n"); printf(" gsave tripath stroke grestore} def\n"); printf("/sq {4 -1 roll add block exch 3 -1 roll add block 2 copy gsave\n"); printf(" sqpath .4 setgray fill stroke grestore\n"); printf(" sqpath stroke} def\n"); } printf("/shape0 {0 2 0 tri} def\n"); printf("/shape1 {0 2 0 tri} def\n"); printf("/shape2 {90 2 -1 tri} def\n"); printf("/shape3 {90 1 -1 tri} def\n"); printf("/shape4 {180 1 0 tri} def\n"); printf("/shape5 {180 1 0 tri} def\n"); printf("/shape6 {270 1 1 tri} def\n"); printf("/shape7 {270 2 1 tri} def\n"); printf("/shape8 {1 0 sq} def\n"); printf("/shape9 {1 0 sq} def\n"); printf("/shape10 {1 -1 sq} def\n"); printf("/shape11 {1 -1 sq} def\n"); printf("54 792 %d block sub 2 div translate\n",maxrow + 2); for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relrow = (row - startrow + 4000) % 2; relcol = (col - startcol + 4000) % 4; shape = INVALID; if ((relrow + relcol) % 2 == 0) { current = vax[row][col]; if (relrow == 0 && relcol == 0 && current == '<') shape = 0; if (relrow == 1 && relcol == 3 && current == '>') shape = 1; if (relrow == 0 && relcol == 2 && current == 'V') shape = 2; if (relrow == 0 && relcol == 0 && current == 'A') shape = 3; if (relrow == 0 && relcol == 2 && current == '<') shape = 4; if (relrow == 1 && relcol == 1 && current == '>') shape = 5; if (relrow == 1 && relcol == 3 && current == 'A') shape = 6; if (relrow == 1 && relcol == 1 && current == 'V') shape = 7; if (relrow == 1 && relcol == 3 && current == '<') shape = 8; if (relrow == 1 && relcol == 1 && current == '<') shape = 9; if (relrow == 0 && relcol == 0 && current == '>') shape = 10; if (relrow == 0 && relcol == 2 && current == '>') shape = 11; if (shape != INVALID) printf("%.1f %d shape%d\n",(col - relrow) / 2.0, maxrow - row, shape); } } } void dungeon(void) { int row, col, relrow, relcol, shape, size = SMALL; char current; printf("/block {%f mul} def\n",608.0/maxcol); printf("/r3block {block 3 sqrt mul} def\n"); printf("/kitepath {moveto rotate 0 1 r3block rlineto 1 block 0 rlineto\n"); printf(" 0.5 block -0.5 r3block rlineto closepath} def\n"); printf("/equpath {moveto rotate 2 block 0 rlineto -1 block 1 r3block\n"); printf(" rlineto closepath} def\n"); printf("/tripath {moveto rotate 0 2 r3block rlineto 1 block -1 r3block\n"); printf(" rlineto closepath} def\n"); if (method == OUTLINE) { printf("/tri {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave tripath stroke grestore} def\n"); printf("/equ {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave equpath stroke grestore} def\n"); printf("/kite {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave kitepath stroke grestore} def\n"); } else { printf("/tri {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave 3 copy tripath .9 setgray fill stroke grestore\n"); printf(" gsave tripath stroke grestore} def\n"); printf("/equ {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave 3 copy equpath .6 setgray fill stroke grestore\n"); printf(" gsave equpath stroke grestore} def\n"); printf("/kite {5 -1 roll add block exch 4 -1 roll add r3block 2 div\n"); printf(" gsave 3 copy kitepath .3 setgray fill stroke grestore\n"); printf(" gsave kitepath stroke grestore} def\n"); } printf("/shape0 {180 1 1 equ} def\n"); printf("/shape1 {180 1 2 equ} def\n"); printf("/shape2 {0 0 0 equ} def\n"); printf("/shape3 {0 -1 -1 equ} def\n"); printf("/shape4 {180 2 2 equ} def\n"); printf("/shape5 {0 0 -1 equ} def\n"); printf("/shape6 {0 -2 0 tri} def\n"); printf("/shape7 {180 3 1 tri} def\n"); printf("/shape8 {60 -1 2 tri} def\n"); printf("/shape9 {240 2 -1 tri} def\n"); printf("/shape10 {120 1 2 tri} def\n"); printf("/shape11 {300 0 -1 tri} def\n"); printf("/shape12 {60 -1 1 kite} def\n"); printf("/shape13 {180 2 2 kite} def\n"); printf("/shape14 {300 1 -1 kite} def\n"); printf("/shape15 {0 -1 -1 kite} def\n"); printf("/shape16 {240 2 0 kite} def\n"); printf("/shape17 {120 0 2 kite} def\n"); printf("54 792 %d r3block sub 2 div translate\n",maxrow / 2); if (vax[startrow][startcol+2] == ' ') { startrow -= 1; startcol += 2; size == LARGE; } for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relcol = (col - startcol + 4000) % 8; relrow = (row - startrow + 4000 + (relcol > 3) * 2) % 4; relcol %= 4; shape = INVALID; if ((relrow + relcol) % 2 == 0) { current = vax[row][col]; if (relrow == 0 && relcol == 0 && current == 'A') shape = 0; if (relrow == 0 && relcol == 2 && current == '<') shape = 1; if (relrow == 1 && relcol == 1 && current == 'V') shape = 2; if (relrow == 2 && relcol == 0 && current == 'A') shape = 3; if (relrow == 3 && relcol == 1 && current == 'V') shape = 4; if (relrow == 3 && relcol == 3 && current == '>') shape = 5; if (relrow == 3 && relcol == 3 && current == 'A') shape = 6; if (relrow == 0 && relcol == 2 && current == 'V') shape = 7; if (relrow == 0 && relcol == 0 && current == '<') shape = 8; if (relrow == 1 && relcol == 1 && current == '>') shape = 9; if (relrow == 2 && relcol == 0 && current == '<') shape = 10; if (relrow == 3 && relcol == 1 && current == '>') shape = 11; if (relrow == 0 && relcol == 2 && current == '>') shape = 12; if (relrow == 3 && relcol == 1 && current == '<') shape = 13; if (relrow == 0 && relcol == 0 && current == 'V') shape = 14; if (relrow == 2 && relcol == 0 && current == '>') shape = 15; if (relrow == 3 && relcol == 3 && current == '<') shape = 16; if (relrow == 1 && relcol == 1 && current == 'A') shape = 17; if (shape != INVALID) printf("%d %d shape%d\n",(col - startcol % 4 + 4) * 3 / 4, maxrow - row, shape); } } } void third(void) { int row, col, relrow, relcol, shape; char current; printf("/block {%f mul} def\n",700.0 / maxcol); printf("/trappath1 {moveto rotate 2 block 0 rlineto 0 1 block rlineto \n"); printf(" -1 block 0 rlineto closepath} def\n"); printf("/trappath2 {moveto rotate 2 block 0 rlineto 0 -1 block rlineto \n"); printf(" -1 block 0 rlineto closepath} def\n"); printf("/rectpath {moveto rotate 2 block 0 rlineto 0 1 block rlineto \n"); printf(" -2 block 0 rlineto closepath} def\n"); printf("/sqpath {moveto rotate 1 block 0 rlineto 0 1 block rlineto \n"); printf(" -1 block 0 rlineto closepath} def\n"); if (method == OUTLINE) { printf("/trap1 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave trappath1 stroke grestore} def\n"); printf("/trap2 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave trappath2 stroke grestore} def\n"); printf("/rect1 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave rectpath stroke grestore} def\n"); printf("/rect2 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave rectpath stroke grestore} def\n"); printf("/sq {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave sqpath stroke grestore} def\n"); } else { printf("/trap1 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave 3 copy trappath1 .9 setgray fill stroke grestore\n"); printf(" gsave trappath1 stroke grestore} def\n"); printf("/trap2 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave 3 copy trappath2 .7 setgray fill stroke grestore\n"); printf(" gsave trappath2 stroke grestore} def\n"); printf("/rect1 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave 3 copy rectpath .2 setgray fill stroke grestore\n"); printf(" gsave rectpath stroke grestore} def\n"); printf("/rect2 {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave 3 copy rectpath .5 setgray fill stroke grestore\n"); printf(" gsave rectpath stroke grestore} def\n"); printf("/sq {5 -1 roll add block exch 4 -1 roll add block \n"); printf(" gsave 3 copy sqpath .3 setgray fill stroke grestore\n"); printf(" gsave sqpath stroke grestore} def\n"); } printf("/shape0 {0 1 0 trap1} def\n"); printf("/shape1 {180 2 2 trap1} def\n"); printf("/shape2 {0 1 -1 rect1} def\n"); printf("/shape3 {0 1 0 sq} def\n"); printf("/shape4 {270 2 1 trap2} def\n"); printf("/shape5 {90 0 0 trap2} def\n"); printf("/shape6 {90 1 1 rect2} def\n"); printf("34 792 %d block sub 2 div translate\n",maxrow); for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relcol = (row - startrow + col - startcol + 4000) % 4; relrow = (col - startcol + row - startrow) / 4; shape = INVALID; current = vax[row][col]; if (relcol == 0 && current == '<') shape = 0; if (relcol == 2 && current == '<') shape = 1; if (relcol == 2 && current == '>') shape = 2; if (relcol == 0 && current == '>') shape = 3; if (relcol == 0 && current == 'A') shape = 4; if (relcol == 2 && current == 'A') shape = 5; if (relcol == 2 && current == 'V') shape = 6; if (shape != INVALID) printf("%d %d shape%d\n",col - relrow, maxrow - row, shape); } } void dragon(void) { int row, col, relrow, relcol, shape; char current; printf("/block {%f mul} def\n",500.0 / maxcol); printf("/r3block {block 3 sqrt mul} def\n"); printf("/hblock {1 3 sqrt add 4 div mul block} def\n"); printf("/vblock {3 3 sqrt add 4 div mul block} def\n"); printf("/hexpath {moveto rotate 0.5 r3block -.5 block rlineto .5 r3block\n"); printf(" .5 block rlineto 0 1 block rlineto -.5 r3block .5 block\n"); printf(" rlineto -.5 r3block -.5 block rlineto -1 block 0 rlineto\n"); printf(" 0 -1 block rlineto closepath} def\n"); printf("/tripath {moveto rotate 1 block 0 rlineto .5 r3block .5 block \n"); printf(" rlineto -.5 r3block .5 block rlineto -1 block 0 rlineto\n"); printf(" closepath} def\n"); if (method == OUTLINE) { printf("/hex {5 -1 roll add hblock exch 4 -1 roll add vblock \n"); printf(" gsave hexpath stroke grestore} def\n"); printf("/tri {5 -1 roll add hblock exch 4 -1 roll add vblock \n"); printf(" gsave tripath stroke grestore} def\n"); } else { printf("/hex {5 -1 roll add hblock exch 4 -1 roll add vblock \n"); printf(" gsave 3 copy hexpath .8 setgray fill stroke grestore\n"); printf(" gsave hexpath stroke grestore} def\n"); printf("/tri {5 -1 roll add hblock exch 4 -1 roll add vblock \n"); printf(" gsave 3 copy tripath .6 setgray fill stroke grestore\n"); printf(" gsave tripath stroke grestore} def\n"); } printf("/shape0 {0 0.000 0.000 hex} def\n"); printf("/shape1 {60 0.577 0.268 hex} def\n"); printf("/shape2 {120 1.000 -0.464 hex} def\n"); printf("/shape3 {180 0.866 -1.464 hex} def\n"); printf("/shape4 {240 0.268 -1.732 hex} def\n"); printf("/shape5 {300 -0.134 -1.000 hex} def\n"); printf("/shape6 {30 -0.154 -1.000 tri} def\n"); printf("/shape7 {90 0.000 0.000 tri} def\n"); printf("/shape8 {150 0.577 0.268 tri} def\n"); printf("/shape9 {210 1.000 -0.464 tri} def\n"); printf("/shape10 {270 0.866 -1.464 tri} def\n"); printf("/shape11 {330 0.268 -1.732 tri} def\n"); printf("130 792 %d vblock sub 2 div translate\n",maxrow); for (row = 0; row < maxrow + 2; row ++) for (col = 0; col < maxcol + 2; col ++) { /* add large numbers to avoid negative numbers */ relcol = (col - startcol + 4000) % 4; relrow = (row - startrow + 4000) % 4; if (relrow > 1) { relrow -= 2; relcol = (relcol + 2) % 4; } shape = INVALID; current = vax[row][col]; if (relrow == 0 && relcol == 0 && current == '<') shape = 0; if (relrow == 1 && relcol == 1 && current == 'V') shape = 1; if (relrow == 1 && relcol == 3 && current == 'V') shape = 2; if (relrow == 0 && relcol == 0 && current == '>') shape = 3; if (relrow == 1 && relcol == 1 && current == 'A') shape = 4; if (relrow == 1 && relcol == 3 && current == 'A') shape = 5; if (relrow == 1 && relcol == 3 && current == '<') shape = 6; if (relrow == 0 && relcol == 0 && current == 'V') shape = 7; if (relrow == 1 && relcol == 1 && current == '>') shape = 8; if (relrow == 1 && relcol == 3 && current == '>') shape = 9; if (relrow == 0 && relcol == 0 && current == 'A') shape = 10; if (relrow == 1 && relcol == 1 && current == '<') shape = 11; if (shape != INVALID) printf("%d %d shape%d\n",col, maxrow - row, shape); } }