home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / CV / ARCH2RAD.C next >
C/C++ Source or Header  |  1993-10-07  |  16KB  |  721 lines

  1. /* Copyright (c) 1990 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)arch2rad.c 2.1 11/12/91 LBL";
  5. #endif
  6.  
  7. /*
  8.  * Convert Architrion file to Radiance
  9.  *
  10.  *    Greg Ward
  11.  */
  12.  
  13. #include <stdio.h>
  14.  
  15. #include "trans.h"
  16.  
  17. #define DEFMAPFILE    "/usr/local/lib/ray/lib/arch.map"
  18.  
  19.                 /* qualifiers */
  20. #define Q_COL        0
  21. #define Q_FAC        1
  22. #define Q_LAY        2
  23. #define Q_REF        3
  24. #define NQUALS        4
  25.  
  26. char    *qname[NQUALS] = {
  27.     "Color",
  28.     "Face",
  29.     "Layer",
  30.     "RefId",
  31. };
  32.  
  33. QLIST    qlist = {NQUALS, qname};
  34.                 /* face ids */
  35. #define F_BOT        0
  36. #define F_END        1
  37. #define F_OPP        2
  38. #define F_REF        3
  39. #define F_SIL        4
  40. #define F_TOP        5
  41. #define NFACES        6
  42. ID    faceId[NFACES] = {
  43.     {"bottom"},{"end"},{"opposite"},{"reference"},{"sill"},{"top"}
  44. };
  45.                 /* valid qualifier ids */
  46. IDLIST    qual[NQUALS] = {
  47.     { 0, NULL },
  48.     { NFACES, faceId },
  49.     { 0, NULL },
  50.     { 0, NULL },
  51. };
  52.                 /* mapping rules */
  53. RULEHD    *ourmap = NULL;
  54.                 /* file header */
  55. struct header {
  56.     char    *filename;
  57.     char    *layer[9];
  58.     char    length_u[16], area_u[16];
  59.     double    length_f, area_f;
  60.     int    nblocks, nopenings;
  61. } fhead;
  62.                 /* block or opening geometry */
  63. typedef struct {
  64.     int    x[4], y[4], z[4], h[4];
  65. } PRISM;
  66.                 /* macros for x,y,z */
  67. #define p_x(p,i)    ((p)->x[(i)&3])
  68. #define p_y(p,i)    ((p)->y[(i)&3])
  69. #define p_z(p,i)    ((i)&4 ? (p)->h[(i)&3] : (p)->z[i])
  70.                 /* opening */
  71. typedef struct {
  72.     PRISM    p;
  73.     int    corner;
  74.     int    depth;
  75.     ID    frame;
  76. } OPNG;
  77.                 /* block */
  78. typedef struct {
  79.     short    layer;
  80.     short    color;
  81.     ID    refid;
  82.     PRISM    p;
  83.     int    nopenings;
  84.     OPNG    *opening;
  85. } BLOCK;
  86.                 /* point format */
  87. char    ptfmt[] = "\t%12.9g %12.9g %12.9g\n";
  88.                 /* antimatter modifier id for openings */
  89. char    openmod[] = "opening";
  90.                 /* return flags for checkface() */
  91. #define T1_OK        1
  92. #define T2_OK        2
  93. #define QL_OK        4
  94.  
  95. char    *progname;        /* argv[0] */
  96.  
  97.  
  98. main(argc, argv)        /* translate Architrion file */
  99. int    argc;
  100. char    *argv[];
  101. {
  102.     int    donames = 0;        /* -n flag, produce namelist */
  103.     int    i;
  104.     
  105.     progname = argv[0];
  106.     for (i = 1; i < argc && argv[i][0] == '-'; i++)
  107.         switch (argv[i][1]) {
  108.         case 'n':        /* just produce name list */
  109.             donames++;
  110.             break;
  111.         case 'm':        /* use custom mapfile */
  112.             ourmap = getmapping(argv[++i], &qlist);
  113.             break;
  114.         default:
  115.             goto userr;
  116.         }
  117.     if (i < argc-1)
  118.         goto userr;
  119.     if (i == argc-1)
  120.         if (freopen(argv[i], "r", stdin) == NULL) {
  121.             fprintf(stderr, "%s: cannot open\n", argv[i]);
  122.             exit(1);
  123.         }
  124.     getfhead(stdin);        /* get Architrion header */
  125.     if (donames) {                /* scan for ids */
  126.         arch2names(stdin);
  127.         printf("filename \"%s\"\n", fhead.filename);
  128.         printf("filetype \"Architrion\"\n");
  129.         write_quals(&qlist, qual, stdout);
  130.     } else {                /* translate file */
  131.         if (ourmap == NULL)
  132.             ourmap = getmapping(DEFMAPFILE, &qlist);
  133.         arch2rad(stdin, stdout);
  134.     }
  135.     return(0);
  136. userr:
  137.     fprintf(stderr, "Usage: %s [-n][-m mapfile] [input]\n", argv[0]);
  138.     exit(1);
  139. }
  140.  
  141.  
  142. arch2rad(inp, out)    /* translate Architrion file to Radiance */
  143. FILE    *inp, *out;
  144. {
  145.     int    nbs, nos;
  146.     BLOCK    blk;
  147.     
  148.     puthead(out);
  149.     nbs = nos = 0;
  150.     while (getblock(&blk, inp) != EOF) {
  151.         putblock(&blk, out);
  152.         nbs++;
  153.         nos += blk.nopenings;
  154.         doneblock(&blk);
  155.     }
  156.     if (nbs != fhead.nblocks)
  157.         fprintf(stderr,
  158.         "%s: warning -- block count incorrect (%d != %d)\n",
  159.                 progname, nbs, fhead.nblocks);
  160.     if (nos != fhead.nopenings)
  161.         fprintf(stderr,
  162.         "%s: warning -- opening count incorrect (%d != %d)\n",
  163.                 progname, nos, fhead.nopenings);
  164. }
  165.  
  166.  
  167. arch2names(inp)        /* get name list from an Architrion file */
  168. FILE    *inp;
  169. {
  170.     BLOCK    blk;
  171.     
  172.     while (getblock(&blk, inp) != EOF) {
  173.         if (ourmap == NULL || hasmatch(&blk, ourmap))
  174.             add2quals(&blk);
  175.         doneblock(&blk);
  176.     }
  177. }
  178.  
  179.  
  180. hasmatch(bp, mp)        /* check for any match in rule list */
  181. BLOCK    *bp;
  182. RULEHD    *mp;
  183. {
  184.     if (mp == NULL)
  185.         return(0);
  186.     if (hasmatch(bp, mp->next))    /* check in order -- more likely */
  187.         return(1);
  188.     return(matchrule(bp, mp));
  189. }
  190.  
  191.  
  192. getfhead(fp)            /* get file header */
  193. FILE    *fp;
  194. {
  195.     char    buf[MAXSTR];
  196.     int    i, n;
  197.     register int    c;
  198.                     /* get file name */
  199.     if (fgets(buf, MAXSTR, fp) == NULL)
  200.         goto readerr;
  201.     buf[strlen(buf)-1] = '\0';
  202.     fhead.filename = savestr(buf);
  203.                     /* get layers */
  204.     fhead.layer[0] = "Worksheet";
  205.     for (i = 1; i <= 8; i++) {
  206.         if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
  207.             goto readerr;
  208.         while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
  209.             ;
  210.         if (c == EOF)
  211.             goto readerr;
  212.         ungetc(c, fp);
  213.         if (fgets(buf, MAXSTR, fp) == NULL)
  214.             goto readerr;
  215.         buf[strlen(buf)-1] = '\0';
  216.         if (buf[0])
  217.             fhead.layer[i] = savestr(buf);
  218.         else
  219.             fhead.layer[i] = NULL;
  220.     }
  221.                     /* get units */
  222.     if (fgets(buf, MAXSTR, fp) == NULL)
  223.         goto readerr;
  224.     if (sscanf(buf, "0 %*f %s %*f %s\n",
  225.             fhead.length_u, fhead.area_u) != 2) {
  226.         fhead.length_u[0] = '\0';
  227.         fhead.area_u[0] = '\0';
  228.     }
  229.     if (fgets(buf, MAXSTR, fp) == NULL ||
  230.             sscanf(buf, "0 %lf\n", &fhead.length_f) != 1)
  231.         goto readerr;
  232.     if (fgets(buf, MAXSTR, fp) == NULL ||
  233.             sscanf(buf, "0 %lf\n", &fhead.area_f) != 1)
  234.         goto readerr;
  235.                     /* get number of blocks and openings */
  236.     if (fgets(buf, MAXSTR, fp) == NULL ||
  237.             sscanf(buf, "0 %d %d\n", &fhead.nblocks,
  238.             &fhead.nopenings) != 2)
  239.         goto readerr;
  240.     return;
  241. readerr:
  242.     fprintf(stderr, "%s: error reading Architrion header\n", progname);
  243.     exit(1);
  244. }
  245.  
  246.  
  247. puthead(fp)            /* put out header information */
  248. FILE    *fp;
  249. {
  250.     register int    i;
  251.     
  252.     fprintf(fp, "# File created by: %s\n", progname);
  253.     fprintf(fp, "# Input file: %s\n", fhead.filename);
  254.     fprintf(fp, "# Input units: %s\n", fhead.length_u);
  255.     fprintf(fp, "# Output units: meters\n");
  256.     fprintf(fp, "# Named layers:\n");
  257.     for (i = 0; i < 8; i++)
  258.         if (fhead.layer[i] != NULL)
  259.             fprintf(fp, "#\tLayer No. %d\t%s\n", i, fhead.layer[i]);
  260. }
  261.  
  262.  
  263. getblock(bp, fp)            /* get an Architrion block */
  264. register BLOCK    *bp;
  265. FILE    *fp;
  266. {
  267.     char    word[32];
  268.     int    i;
  269.     
  270.     if (fgets(word, sizeof(word), fp) == NULL)
  271.         return(EOF);
  272.     if (strncmp(word, "Block", 5))
  273.         return(EOF);
  274.     if (fscanf(fp, "1 %hd %hd %d", &bp->layer,
  275.             &bp->color, &bp->nopenings) != 3)
  276.         return(EOF);
  277.     if (fgetid(&bp->refid, "\n", fp) == EOF)
  278.         return(EOF);
  279.     if (fscanf(fp, "1 %d %d %d %d %d %d %d %d\n",
  280.             &bp->p.x[0], &bp->p.y[0], &bp->p.z[0], &bp->p.h[0],
  281.             &bp->p.x[1], &bp->p.y[1], &bp->p.z[1], &bp->p.h[1]) != 8)
  282.         return(EOF);
  283.     if (fscanf(fp, "1 %d %d %d %d %d %d %d %d\n",
  284.             &bp->p.x[2], &bp->p.y[2], &bp->p.z[2], &bp->p.h[2],
  285.             &bp->p.x[3], &bp->p.y[3], &bp->p.z[3], &bp->p.h[3]) != 8)
  286.         return(EOF);
  287.     if (bp->nopenings == 0) {
  288.         bp->opening = NULL;
  289.         return(0);
  290.     }
  291.     bp->opening = (OPNG *)malloc(bp->nopenings*sizeof(OPNG));
  292.     if (bp->opening == NULL)
  293.         goto memerr;
  294.     for (i = 0; i < bp->nopenings; i++)
  295.         if (getopening(&bp->opening[i], fp) < 0)
  296.             return(EOF);
  297.     return(0);
  298. memerr:
  299.     fprintf(stderr, "%s: out of memory in getblock\n", progname);
  300.     exit(1);
  301. }
  302.  
  303.  
  304. getopening(op, fp)        /* read in opening from fp */
  305. register OPNG    *op;
  306. FILE    *fp;
  307. {
  308.     register int    c;
  309.     char    word[32];
  310.  
  311.     if (fgets(word, sizeof(word), fp) == NULL)
  312.         return(EOF);
  313.     if (strncmp(word, "Opening", 7))
  314.         return(EOF);
  315.     if (fscanf(fp, "2 %d %d %d %d %d %d %d %d\n",
  316.             &op->p.x[0], &op->p.y[0],
  317.             &op->p.z[0], &op->p.h[0],
  318.             &op->p.x[1], &op->p.y[1],
  319.             &op->p.z[1], &op->p.h[1]) != 8)
  320.         return(EOF);
  321.     if (fscanf(fp, "2 %d %d %d %d %d %d %d %d\n",
  322.             &op->p.x[2], &op->p.y[2],
  323.             &op->p.z[2], &op->p.h[2],
  324.             &op->p.x[3], &op->p.y[3],
  325.             &op->p.z[3], &op->p.h[3]) != 8)
  326.         return(EOF);
  327.     c = getc(fp);
  328.     if (c == '3') {
  329.         if (fscanf(fp, "%d %d", &op->corner, &op->depth) != 2)
  330.             return(EOF);
  331.         if (fgetid(&op->frame, "\n", fp) == EOF)
  332.             return(EOF);
  333.     } else {
  334.         op->corner = -1;
  335.         op->frame.name = NULL;
  336.         if (c != EOF)
  337.             ungetc(c, fp);
  338.     }
  339.     return(0);
  340. }
  341.  
  342.  
  343. doneblock(bp)            /* free data associated with bp */
  344. register BLOCK    *bp;
  345. {
  346.     register int    i;
  347.  
  348.     if (bp->nopenings > 0) {
  349.         for (i = 0; i < bp->nopenings; i++)
  350.             doneid(&bp->opening[i].frame);
  351.         free((char *)bp->opening);
  352.     }
  353.     doneid(&bp->refid);
  354. }
  355.  
  356.  
  357. add2quals(bp)            /* add to qualifier lists */
  358. register BLOCK    *bp;
  359. {
  360.     ID    tmpid;
  361.  
  362.     if (fhead.layer[bp->layer] == NULL) {
  363.         tmpid.name = NULL;
  364.         tmpid.number = bp->layer;
  365.     } else {
  366.         tmpid.name = fhead.layer[bp->layer];
  367.         tmpid.number = 0;
  368.     }
  369.     findid(&qual[Q_LAY], &tmpid, 1);
  370.     tmpid.name = NULL;
  371.     tmpid.number = bp->color;
  372.     findid(&qual[Q_COL], &tmpid, 1);
  373.     findid(&qual[Q_REF], &bp->refid, 1);
  374. }
  375.  
  376.  
  377. putblock(bp, fp)            /* put out a block */
  378. BLOCK    *bp;
  379. FILE    *fp;
  380. {
  381.     RULEHD    *rp;
  382.     char    *mod[NFACES], *sillmod;
  383.     int    nmods, i;
  384.     int    donematch, newmatch;
  385.     
  386.     nmods = 0; sillmod = NULL;
  387.     donematch = 0;
  388.     for (rp = ourmap; rp != NULL; rp = rp->next) {
  389.         newmatch = matchrule(bp, rp);        /* test this rule */
  390.         newmatch &= ~donematch;            /* don't repeat */
  391.         if (newmatch == 0)
  392.             continue;
  393.         mod[nmods++] = rp->mnam;
  394.         if (sillmod == NULL && newmatch&F_SIL)
  395.             sillmod = rp->mnam;
  396.         putfaces(rp->mnam, bp, newmatch, fp);    /* put out new faces */
  397.         donematch |= newmatch;
  398.         if (donematch == (1<<NFACES)-1)
  399.             break;                /* done all faces */
  400.     }
  401.                         /* put out openings */
  402.     if (donematch && bp->nopenings > 0) {
  403.         putopenmod(sillmod, mod, nmods, fp);
  404.         for (i = 0; i < bp->nopenings; i++)
  405.             putopening(&bp->opening[i], fp);
  406.     }
  407.     if (ferror(fp)) {
  408.         fprintf(stderr, "%s: write error in putblock\n", progname);
  409.         exit(1);
  410.     }
  411. }
  412.  
  413.  
  414. putopenmod(sm, ml, nm, fp)        /* put out opening modifier */
  415. char    *sm, *ml[];
  416. int    nm;
  417. FILE    *fp;
  418. {
  419.     int    rept, nrepts;
  420.     register int    i, j;
  421.     
  422.     if (sm == NULL) {        /* if no sill modifier, use list */
  423.         sm = *ml++;
  424.         nm--;
  425.     }
  426.                     /* check for repeats */
  427.     rept = 0; nrepts = 0;
  428.     for (i = 0; i < nm; i++) {
  429.         if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
  430.             rept |= 1<<i;
  431.             nrepts++;
  432.             continue;
  433.         }
  434.         for (j = 0; j < i; j++)
  435.             if (!(rept & 1<<j) && ml[j] == ml[i]) {
  436.                 rept |= 1<<j;
  437.                 nrepts++;
  438.             }
  439.     }
  440.                     /* print antimatter and modlist */
  441.     fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
  442.     fprintf(fp, "%d %s", 1+nm-nrepts, sm);
  443.     for (i = 0; i < nm; i++)
  444.         if (!(rept & 1<<i))
  445.             fprintf(fp, " %s", ml[i]);
  446.     fprintf(fp, "\n0\n0\n");
  447. }
  448.  
  449.  
  450. putopening(op, fp)            /* put out an opening */
  451. OPNG    *op;
  452. FILE    *fp;
  453. {
  454.     static int    nopens = 0;
  455.     char    buf[32];
  456.     register PRISM    *p = &op->p;
  457.     PRISM    newp;
  458.     register int    i;
  459.                     /* copy original prism */
  460.     for (i = 0; i < 4; i++) {
  461.         newp.x[i] = p->x[i];
  462.         newp.y[i] = p->y[i];
  463.         newp.z[i] = p->z[i];
  464.         newp.h[i] = p->h[i];
  465.     }
  466.                     /* spread reference and opposite */
  467.     if (p->x[2] > p->x[0]) {
  468.         newp.x[0] -= 2;
  469.         newp.x[1] -= 2;
  470.         newp.x[2] += 2;
  471.         newp.x[3] += 2;
  472.     } else if (p->x[0] > p->x[2]) {
  473.         newp.x[0] += 2;
  474.         newp.x[1] += 2;
  475.         newp.x[2] -= 2;
  476.         newp.x[3] -= 2;
  477.     }
  478.     if (p->y[2] > p->y[0]) {
  479.         newp.y[0] -= 2;
  480.         newp.y[1] -= 2;
  481.         newp.y[2] += 2;
  482.         newp.y[3] += 2;
  483.     } else if (p->y[0] > p->y[2]) {
  484.         newp.y[0] += 2;
  485.         newp.y[1] += 2;
  486.         newp.y[2] -= 2;
  487.         newp.y[3] -= 2;
  488.     }
  489.                         /* put out faces */
  490.     sprintf(buf, "op%d", ++nopens);
  491.     putface(openmod, buf, "ref", &newp, 4, 5, 1, 0, fp);
  492.     putface(openmod, buf, "opp", &newp, 2, 6, 7, 3, fp);
  493.     putface(openmod, buf, "end1", &newp, 5, 6, 2, 1, fp);
  494.     putface(openmod, buf, "end2", &newp, 3, 7, 4, 0, fp);
  495.     putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
  496.     putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
  497. }
  498.  
  499.  
  500. int
  501. matchrule(bp, rp)            /* see if block matches this rule */
  502. register BLOCK    *bp;
  503. register RULEHD    *rp;
  504. {
  505.     register int    i;
  506.     ID    tmpid;
  507.     
  508.     if (rp->qflg & FL(Q_LAY)) {        /* check layer */
  509.         tmpid.name = fhead.layer[bp->layer];
  510.         tmpid.number = bp->layer;
  511.         if (!matchid(&tmpid, &idm(rp)[Q_LAY]))
  512.             return(0);
  513.     }
  514.     if (rp->qflg & FL(Q_COL)) {        /* check color */
  515.         tmpid.name = NULL;
  516.         tmpid.number = bp->color;
  517.         if (!matchid(&tmpid, &idm(rp)[Q_COL]))
  518.             return(0);
  519.     }
  520.     if (rp->qflg & FL(Q_REF)) {        /* check reference id */
  521.         if (!matchid(&bp->refid, &idm(rp)[Q_REF]))
  522.             return(0);
  523.     }
  524.     if (rp->qflg & FL(Q_FAC)) {        /* check faces */
  525.         for (i = 0; i < NFACES; i++)
  526.             if (matchid(&faceId[i], &idm(rp)[Q_FAC]))
  527.                 return(1<<i);    /* match single face */
  528.         return(0);
  529.     }
  530.     return((1<<NFACES)-1);            /* matched all faces */
  531. }        
  532.  
  533.  
  534. putfaces(m, bp, ff, fp)            /* put out faces */
  535. char    *m;
  536. BLOCK    *bp;
  537. register int    ff;
  538. FILE    *fp;
  539. {
  540.     char    *blkname(), *bn;
  541.  
  542.     if (!strcmp(m, VOIDID))
  543.         return;
  544.     bn = blkname(bp);
  545.     if (ff & 1<<F_REF)
  546.         putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
  547.     if (ff & 1<<F_OPP)
  548.         putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
  549.     if (ff & 1<<F_END) {
  550.         putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
  551.         putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
  552.     }
  553.     if (ff & 1<<F_BOT)
  554.         putface(m, bn, "bot", &bp->p, 1, 2, 3, 0, fp);
  555.     if (ff & 1<<F_TOP)
  556.         putface(m, bn, "top", &bp->p, 7, 6, 5, 4, fp);
  557. }
  558.  
  559.  
  560. char *
  561. blkname(bp)        /* think up a good name for this block */
  562. register BLOCK    *bp;
  563. {
  564.     static char    nambuf[32];
  565.     static int    blkcnt = 0;
  566.     register char    *nam;
  567.     register int    i, j;
  568.  
  569.     sprintf(nambuf, "l%d.", bp->layer);
  570.     i = strlen(nambuf);
  571.     nam = bp->refid.name;
  572.     if (nam == NULL) {
  573.         nam = fhead.layer[bp->layer];
  574.         if (nam != NULL)
  575.             i = 0;
  576.     }
  577.     if (nam != NULL) {
  578.         for (j = 0; j < 12 && nam[j]; j++) {
  579.             if (nam[j] == ' ' || nam[j] == '\t')
  580.                 nambuf[i++] = '_';
  581.             else
  582.                 nambuf[i++] = nam[j];
  583.         }
  584.         nambuf[i++] = '.';
  585.     }
  586.     if (bp->refid.number != 0) {
  587.         sprintf(nambuf+i, "r%d.", bp->refid.number);
  588.         i = strlen(nambuf);
  589.     }
  590.     sprintf(nambuf+i, "b%d", ++blkcnt);
  591.     return(nambuf);
  592. }
  593.  
  594.  
  595. putface(m, bn, fn, p, a, b, c, d, fp)    /* put out a face */
  596. char    *m;
  597. char    *bn, *fn;
  598. PRISM    *p;
  599. int    a, b, c, d;
  600. FILE    *fp;
  601. {
  602.     int    cf;
  603.     
  604.     cf = checkface(p, a, b, c, d);
  605.     if (cf & QL_OK) {
  606.         fprintf(fp, "\n%s polygon %s.%s\n", m, bn, fn);
  607.         fprintf(fp, "0\n0\n12\n");
  608.         putpoint(p, a, fp);
  609.         putpoint(p, b, fp);
  610.         putpoint(p, c, fp);
  611.         putpoint(p, d, fp);
  612.         return;
  613.     }
  614.     if (cf & T1_OK) {
  615.         fprintf(fp, "\n%s polygon %s.%sA\n", m, bn, fn);
  616.         fprintf(fp, "0\n0\n9\n");
  617.         putpoint(p, d, fp);
  618.         putpoint(p, a, fp);
  619.         putpoint(p, b, fp);
  620.     }
  621.     if (cf & T2_OK) {
  622.         fprintf(fp, "\n%s polygon %s.%sB\n", m, bn, fn);
  623.         fprintf(fp, "0\n0\n9\n");
  624.         putpoint(p, b, fp);
  625.         putpoint(p, c, fp);
  626.         putpoint(p, d, fp);
  627.     }
  628. }
  629.  
  630.  
  631. #define ldot(v1,v2)    (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
  632.  
  633.  
  634. long
  635. lcross(vr, v1, v2)            /* compute cross product */
  636. register long    vr[3], v1[3], v2[3];
  637. {
  638.     vr[0] = v1[1]*v2[2] - v1[2]*v2[1];
  639.     vr[1] = v1[2]*v2[0] - v1[0]*v2[2];
  640.     vr[2] = v1[0]*v2[1] - v1[1]*v2[0];
  641. }
  642.  
  643.  
  644. #define labs(a)        ((a)>0 ? (a) : -(a))
  645.  
  646.  
  647. checkface(p, a, b, c, d)        /* check a face for validity */
  648. register PRISM    *p;
  649. int    a, b, c, d;
  650. {
  651.     int    rval = 0;
  652.     long    lt;
  653.     long    vc1[3], vc2[3], vt1[3], vt2[3];
  654.     long    vc1l, vc2l, vc1vc2;
  655.                     /* check first triangle */
  656.     vt1[0] = p_x(p,b) - p_x(p,a);
  657.     vt1[1] = p_y(p,b) - p_y(p,a);
  658.     vt1[2] = p_z(p,b) - p_z(p,a);
  659.     vt2[0] = p_x(p,d) - p_x(p,a);
  660.     vt2[1] = p_y(p,d) - p_y(p,a);
  661.     vt2[2] = p_z(p,d) - p_z(p,a);
  662.     lcross(vc1, vt1, vt2);
  663.     lt = labs(vc1[0]) + labs(vc1[1]) + labs(vc1[2]);
  664.     if (lt > 1L<<18) lt = 16;
  665.     else if (lt > 1L<<12) lt = 8;
  666.     else lt = 0;
  667.     if (lt) { vc1[0] >>= lt; vc1[1] >>= lt; vc1[2] >>= lt; }
  668.     vc1l = ldot(vc1,vc1);
  669.     if (vc1l > 4)
  670.         rval |= T1_OK;
  671.                     /* check second triangle */
  672.     vt1[0] = p_x(p,d) - p_x(p,c);
  673.     vt1[1] = p_y(p,d) - p_y(p,c);
  674.     vt1[2] = p_z(p,d) - p_z(p,c);
  675.     vt2[0] = p_x(p,b) - p_x(p,c);
  676.     vt2[1] = p_y(p,b) - p_y(p,c);
  677.     vt2[2] = p_z(p,b) - p_z(p,c);
  678.     lcross(vc2, vt1, vt2);
  679.     lt = labs(vc2[0]) + labs(vc2[1]) + labs(vc2[2]);
  680.     if (lt > 1L<<18) lt = 16;
  681.     else if (lt > 1L<<12) lt = 8;
  682.     else lt = 0;
  683.     if (lt) { vc2[0] >>= lt; vc2[1] >>= lt; vc2[2] >>= lt; }
  684.     vc2l = ldot(vc2,vc2);
  685.     if (vc2l > 4)
  686.         rval |= T2_OK;
  687.                     /* check quadrilateral */
  688.     if (rval == (T1_OK|T2_OK)) {
  689.         vc1vc2 = ldot(vc1,vc2);
  690.         if (vc1vc2*vc1vc2 >= vc1l*vc2l-8)
  691.             rval |= QL_OK;
  692.     }
  693.     return(rval);
  694. }
  695.  
  696.  
  697. putpoint(p, n, fp)            /* put out a point */
  698. register PRISM    *p;
  699. int    n;
  700. FILE    *fp;
  701. {
  702.     register int    i = n&3;
  703.     
  704.     fprintf(fp, ptfmt, p->x[i]*fhead.length_f, p->y[i]*fhead.length_f,
  705.             (n&4 ? p->h[i] : p->z[i])*fhead.length_f);
  706. }
  707.  
  708.  
  709. eputs(s)
  710. char    *s;
  711. {
  712.     fputs(s, stderr);
  713. }
  714.  
  715.  
  716. quit(code)
  717. int    code;
  718. {
  719.     exit(code);
  720. }
  721.