home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1990 Regents of the University of California */
-
- #ifndef lint
- static char SCCSid[] = "@(#)arch2rad.c 2.1 11/12/91 LBL";
- #endif
-
- /*
- * Convert Architrion file to Radiance
- *
- * Greg Ward
- */
-
- #include <stdio.h>
-
- #include "trans.h"
-
- #define DEFMAPFILE "/usr/local/lib/ray/lib/arch.map"
-
- /* qualifiers */
- #define Q_COL 0
- #define Q_FAC 1
- #define Q_LAY 2
- #define Q_REF 3
- #define NQUALS 4
-
- char *qname[NQUALS] = {
- "Color",
- "Face",
- "Layer",
- "RefId",
- };
-
- QLIST qlist = {NQUALS, qname};
- /* face ids */
- #define F_BOT 0
- #define F_END 1
- #define F_OPP 2
- #define F_REF 3
- #define F_SIL 4
- #define F_TOP 5
- #define NFACES 6
- ID faceId[NFACES] = {
- {"bottom"},{"end"},{"opposite"},{"reference"},{"sill"},{"top"}
- };
- /* valid qualifier ids */
- IDLIST qual[NQUALS] = {
- { 0, NULL },
- { NFACES, faceId },
- { 0, NULL },
- { 0, NULL },
- };
- /* mapping rules */
- RULEHD *ourmap = NULL;
- /* file header */
- struct header {
- char *filename;
- char *layer[9];
- char length_u[16], area_u[16];
- double length_f, area_f;
- int nblocks, nopenings;
- } fhead;
- /* block or opening geometry */
- typedef struct {
- int x[4], y[4], z[4], h[4];
- } PRISM;
- /* macros for x,y,z */
- #define p_x(p,i) ((p)->x[(i)&3])
- #define p_y(p,i) ((p)->y[(i)&3])
- #define p_z(p,i) ((i)&4 ? (p)->h[(i)&3] : (p)->z[i])
- /* opening */
- typedef struct {
- PRISM p;
- int corner;
- int depth;
- ID frame;
- } OPNG;
- /* block */
- typedef struct {
- short layer;
- short color;
- ID refid;
- PRISM p;
- int nopenings;
- OPNG *opening;
- } BLOCK;
- /* point format */
- char ptfmt[] = "\t%12.9g %12.9g %12.9g\n";
- /* antimatter modifier id for openings */
- char openmod[] = "opening";
- /* return flags for checkface() */
- #define T1_OK 1
- #define T2_OK 2
- #define QL_OK 4
-
- char *progname; /* argv[0] */
-
-
- main(argc, argv) /* translate Architrion file */
- int argc;
- char *argv[];
- {
- int donames = 0; /* -n flag, produce namelist */
- int i;
-
- progname = argv[0];
- for (i = 1; i < argc && argv[i][0] == '-'; i++)
- switch (argv[i][1]) {
- case 'n': /* just produce name list */
- donames++;
- break;
- case 'm': /* use custom mapfile */
- ourmap = getmapping(argv[++i], &qlist);
- break;
- default:
- goto userr;
- }
- if (i < argc-1)
- goto userr;
- if (i == argc-1)
- if (freopen(argv[i], "r", stdin) == NULL) {
- fprintf(stderr, "%s: cannot open\n", argv[i]);
- exit(1);
- }
- getfhead(stdin); /* get Architrion header */
- if (donames) { /* scan for ids */
- arch2names(stdin);
- printf("filename \"%s\"\n", fhead.filename);
- printf("filetype \"Architrion\"\n");
- write_quals(&qlist, qual, stdout);
- } else { /* translate file */
- if (ourmap == NULL)
- ourmap = getmapping(DEFMAPFILE, &qlist);
- arch2rad(stdin, stdout);
- }
- return(0);
- userr:
- fprintf(stderr, "Usage: %s [-n][-m mapfile] [input]\n", argv[0]);
- exit(1);
- }
-
-
- arch2rad(inp, out) /* translate Architrion file to Radiance */
- FILE *inp, *out;
- {
- int nbs, nos;
- BLOCK blk;
-
- puthead(out);
- nbs = nos = 0;
- while (getblock(&blk, inp) != EOF) {
- putblock(&blk, out);
- nbs++;
- nos += blk.nopenings;
- doneblock(&blk);
- }
- if (nbs != fhead.nblocks)
- fprintf(stderr,
- "%s: warning -- block count incorrect (%d != %d)\n",
- progname, nbs, fhead.nblocks);
- if (nos != fhead.nopenings)
- fprintf(stderr,
- "%s: warning -- opening count incorrect (%d != %d)\n",
- progname, nos, fhead.nopenings);
- }
-
-
- arch2names(inp) /* get name list from an Architrion file */
- FILE *inp;
- {
- BLOCK blk;
-
- while (getblock(&blk, inp) != EOF) {
- if (ourmap == NULL || hasmatch(&blk, ourmap))
- add2quals(&blk);
- doneblock(&blk);
- }
- }
-
-
- hasmatch(bp, mp) /* check for any match in rule list */
- BLOCK *bp;
- RULEHD *mp;
- {
- if (mp == NULL)
- return(0);
- if (hasmatch(bp, mp->next)) /* check in order -- more likely */
- return(1);
- return(matchrule(bp, mp));
- }
-
-
- getfhead(fp) /* get file header */
- FILE *fp;
- {
- char buf[MAXSTR];
- int i, n;
- register int c;
- /* get file name */
- if (fgets(buf, MAXSTR, fp) == NULL)
- goto readerr;
- buf[strlen(buf)-1] = '\0';
- fhead.filename = savestr(buf);
- /* get layers */
- fhead.layer[0] = "Worksheet";
- for (i = 1; i <= 8; i++) {
- if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
- goto readerr;
- while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
- ;
- if (c == EOF)
- goto readerr;
- ungetc(c, fp);
- if (fgets(buf, MAXSTR, fp) == NULL)
- goto readerr;
- buf[strlen(buf)-1] = '\0';
- if (buf[0])
- fhead.layer[i] = savestr(buf);
- else
- fhead.layer[i] = NULL;
- }
- /* get units */
- if (fgets(buf, MAXSTR, fp) == NULL)
- goto readerr;
- if (sscanf(buf, "0 %*f %s %*f %s\n",
- fhead.length_u, fhead.area_u) != 2) {
- fhead.length_u[0] = '\0';
- fhead.area_u[0] = '\0';
- }
- if (fgets(buf, MAXSTR, fp) == NULL ||
- sscanf(buf, "0 %lf\n", &fhead.length_f) != 1)
- goto readerr;
- if (fgets(buf, MAXSTR, fp) == NULL ||
- sscanf(buf, "0 %lf\n", &fhead.area_f) != 1)
- goto readerr;
- /* get number of blocks and openings */
- if (fgets(buf, MAXSTR, fp) == NULL ||
- sscanf(buf, "0 %d %d\n", &fhead.nblocks,
- &fhead.nopenings) != 2)
- goto readerr;
- return;
- readerr:
- fprintf(stderr, "%s: error reading Architrion header\n", progname);
- exit(1);
- }
-
-
- puthead(fp) /* put out header information */
- FILE *fp;
- {
- register int i;
-
- fprintf(fp, "# File created by: %s\n", progname);
- fprintf(fp, "# Input file: %s\n", fhead.filename);
- fprintf(fp, "# Input units: %s\n", fhead.length_u);
- fprintf(fp, "# Output units: meters\n");
- fprintf(fp, "# Named layers:\n");
- for (i = 0; i < 8; i++)
- if (fhead.layer[i] != NULL)
- fprintf(fp, "#\tLayer No. %d\t%s\n", i, fhead.layer[i]);
- }
-
-
- getblock(bp, fp) /* get an Architrion block */
- register BLOCK *bp;
- FILE *fp;
- {
- char word[32];
- int i;
-
- if (fgets(word, sizeof(word), fp) == NULL)
- return(EOF);
- if (strncmp(word, "Block", 5))
- return(EOF);
- if (fscanf(fp, "1 %hd %hd %d", &bp->layer,
- &bp->color, &bp->nopenings) != 3)
- return(EOF);
- if (fgetid(&bp->refid, "\n", fp) == EOF)
- return(EOF);
- if (fscanf(fp, "1 %d %d %d %d %d %d %d %d\n",
- &bp->p.x[0], &bp->p.y[0], &bp->p.z[0], &bp->p.h[0],
- &bp->p.x[1], &bp->p.y[1], &bp->p.z[1], &bp->p.h[1]) != 8)
- return(EOF);
- if (fscanf(fp, "1 %d %d %d %d %d %d %d %d\n",
- &bp->p.x[2], &bp->p.y[2], &bp->p.z[2], &bp->p.h[2],
- &bp->p.x[3], &bp->p.y[3], &bp->p.z[3], &bp->p.h[3]) != 8)
- return(EOF);
- if (bp->nopenings == 0) {
- bp->opening = NULL;
- return(0);
- }
- bp->opening = (OPNG *)malloc(bp->nopenings*sizeof(OPNG));
- if (bp->opening == NULL)
- goto memerr;
- for (i = 0; i < bp->nopenings; i++)
- if (getopening(&bp->opening[i], fp) < 0)
- return(EOF);
- return(0);
- memerr:
- fprintf(stderr, "%s: out of memory in getblock\n", progname);
- exit(1);
- }
-
-
- getopening(op, fp) /* read in opening from fp */
- register OPNG *op;
- FILE *fp;
- {
- register int c;
- char word[32];
-
- if (fgets(word, sizeof(word), fp) == NULL)
- return(EOF);
- if (strncmp(word, "Opening", 7))
- return(EOF);
- if (fscanf(fp, "2 %d %d %d %d %d %d %d %d\n",
- &op->p.x[0], &op->p.y[0],
- &op->p.z[0], &op->p.h[0],
- &op->p.x[1], &op->p.y[1],
- &op->p.z[1], &op->p.h[1]) != 8)
- return(EOF);
- if (fscanf(fp, "2 %d %d %d %d %d %d %d %d\n",
- &op->p.x[2], &op->p.y[2],
- &op->p.z[2], &op->p.h[2],
- &op->p.x[3], &op->p.y[3],
- &op->p.z[3], &op->p.h[3]) != 8)
- return(EOF);
- c = getc(fp);
- if (c == '3') {
- if (fscanf(fp, "%d %d", &op->corner, &op->depth) != 2)
- return(EOF);
- if (fgetid(&op->frame, "\n", fp) == EOF)
- return(EOF);
- } else {
- op->corner = -1;
- op->frame.name = NULL;
- if (c != EOF)
- ungetc(c, fp);
- }
- return(0);
- }
-
-
- doneblock(bp) /* free data associated with bp */
- register BLOCK *bp;
- {
- register int i;
-
- if (bp->nopenings > 0) {
- for (i = 0; i < bp->nopenings; i++)
- doneid(&bp->opening[i].frame);
- free((char *)bp->opening);
- }
- doneid(&bp->refid);
- }
-
-
- add2quals(bp) /* add to qualifier lists */
- register BLOCK *bp;
- {
- ID tmpid;
-
- if (fhead.layer[bp->layer] == NULL) {
- tmpid.name = NULL;
- tmpid.number = bp->layer;
- } else {
- tmpid.name = fhead.layer[bp->layer];
- tmpid.number = 0;
- }
- findid(&qual[Q_LAY], &tmpid, 1);
- tmpid.name = NULL;
- tmpid.number = bp->color;
- findid(&qual[Q_COL], &tmpid, 1);
- findid(&qual[Q_REF], &bp->refid, 1);
- }
-
-
- putblock(bp, fp) /* put out a block */
- BLOCK *bp;
- FILE *fp;
- {
- RULEHD *rp;
- char *mod[NFACES], *sillmod;
- int nmods, i;
- int donematch, newmatch;
-
- nmods = 0; sillmod = NULL;
- donematch = 0;
- for (rp = ourmap; rp != NULL; rp = rp->next) {
- newmatch = matchrule(bp, rp); /* test this rule */
- newmatch &= ~donematch; /* don't repeat */
- if (newmatch == 0)
- continue;
- mod[nmods++] = rp->mnam;
- if (sillmod == NULL && newmatch&F_SIL)
- sillmod = rp->mnam;
- putfaces(rp->mnam, bp, newmatch, fp); /* put out new faces */
- donematch |= newmatch;
- if (donematch == (1<<NFACES)-1)
- break; /* done all faces */
- }
- /* put out openings */
- if (donematch && bp->nopenings > 0) {
- putopenmod(sillmod, mod, nmods, fp);
- for (i = 0; i < bp->nopenings; i++)
- putopening(&bp->opening[i], fp);
- }
- if (ferror(fp)) {
- fprintf(stderr, "%s: write error in putblock\n", progname);
- exit(1);
- }
- }
-
-
- putopenmod(sm, ml, nm, fp) /* put out opening modifier */
- char *sm, *ml[];
- int nm;
- FILE *fp;
- {
- int rept, nrepts;
- register int i, j;
-
- if (sm == NULL) { /* if no sill modifier, use list */
- sm = *ml++;
- nm--;
- }
- /* check for repeats */
- rept = 0; nrepts = 0;
- for (i = 0; i < nm; i++) {
- if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
- rept |= 1<<i;
- nrepts++;
- continue;
- }
- for (j = 0; j < i; j++)
- if (!(rept & 1<<j) && ml[j] == ml[i]) {
- rept |= 1<<j;
- nrepts++;
- }
- }
- /* print antimatter and modlist */
- fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
- fprintf(fp, "%d %s", 1+nm-nrepts, sm);
- for (i = 0; i < nm; i++)
- if (!(rept & 1<<i))
- fprintf(fp, " %s", ml[i]);
- fprintf(fp, "\n0\n0\n");
- }
-
-
- putopening(op, fp) /* put out an opening */
- OPNG *op;
- FILE *fp;
- {
- static int nopens = 0;
- char buf[32];
- register PRISM *p = &op->p;
- PRISM newp;
- register int i;
- /* copy original prism */
- for (i = 0; i < 4; i++) {
- newp.x[i] = p->x[i];
- newp.y[i] = p->y[i];
- newp.z[i] = p->z[i];
- newp.h[i] = p->h[i];
- }
- /* spread reference and opposite */
- if (p->x[2] > p->x[0]) {
- newp.x[0] -= 2;
- newp.x[1] -= 2;
- newp.x[2] += 2;
- newp.x[3] += 2;
- } else if (p->x[0] > p->x[2]) {
- newp.x[0] += 2;
- newp.x[1] += 2;
- newp.x[2] -= 2;
- newp.x[3] -= 2;
- }
- if (p->y[2] > p->y[0]) {
- newp.y[0] -= 2;
- newp.y[1] -= 2;
- newp.y[2] += 2;
- newp.y[3] += 2;
- } else if (p->y[0] > p->y[2]) {
- newp.y[0] += 2;
- newp.y[1] += 2;
- newp.y[2] -= 2;
- newp.y[3] -= 2;
- }
- /* put out faces */
- sprintf(buf, "op%d", ++nopens);
- putface(openmod, buf, "ref", &newp, 4, 5, 1, 0, fp);
- putface(openmod, buf, "opp", &newp, 2, 6, 7, 3, fp);
- putface(openmod, buf, "end1", &newp, 5, 6, 2, 1, fp);
- putface(openmod, buf, "end2", &newp, 3, 7, 4, 0, fp);
- putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
- putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
- }
-
-
- int
- matchrule(bp, rp) /* see if block matches this rule */
- register BLOCK *bp;
- register RULEHD *rp;
- {
- register int i;
- ID tmpid;
-
- if (rp->qflg & FL(Q_LAY)) { /* check layer */
- tmpid.name = fhead.layer[bp->layer];
- tmpid.number = bp->layer;
- if (!matchid(&tmpid, &idm(rp)[Q_LAY]))
- return(0);
- }
- if (rp->qflg & FL(Q_COL)) { /* check color */
- tmpid.name = NULL;
- tmpid.number = bp->color;
- if (!matchid(&tmpid, &idm(rp)[Q_COL]))
- return(0);
- }
- if (rp->qflg & FL(Q_REF)) { /* check reference id */
- if (!matchid(&bp->refid, &idm(rp)[Q_REF]))
- return(0);
- }
- if (rp->qflg & FL(Q_FAC)) { /* check faces */
- for (i = 0; i < NFACES; i++)
- if (matchid(&faceId[i], &idm(rp)[Q_FAC]))
- return(1<<i); /* match single face */
- return(0);
- }
- return((1<<NFACES)-1); /* matched all faces */
- }
-
-
- putfaces(m, bp, ff, fp) /* put out faces */
- char *m;
- BLOCK *bp;
- register int ff;
- FILE *fp;
- {
- char *blkname(), *bn;
-
- if (!strcmp(m, VOIDID))
- return;
- bn = blkname(bp);
- if (ff & 1<<F_REF)
- putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
- if (ff & 1<<F_OPP)
- putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
- if (ff & 1<<F_END) {
- putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
- putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
- }
- if (ff & 1<<F_BOT)
- putface(m, bn, "bot", &bp->p, 1, 2, 3, 0, fp);
- if (ff & 1<<F_TOP)
- putface(m, bn, "top", &bp->p, 7, 6, 5, 4, fp);
- }
-
-
- char *
- blkname(bp) /* think up a good name for this block */
- register BLOCK *bp;
- {
- static char nambuf[32];
- static int blkcnt = 0;
- register char *nam;
- register int i, j;
-
- sprintf(nambuf, "l%d.", bp->layer);
- i = strlen(nambuf);
- nam = bp->refid.name;
- if (nam == NULL) {
- nam = fhead.layer[bp->layer];
- if (nam != NULL)
- i = 0;
- }
- if (nam != NULL) {
- for (j = 0; j < 12 && nam[j]; j++) {
- if (nam[j] == ' ' || nam[j] == '\t')
- nambuf[i++] = '_';
- else
- nambuf[i++] = nam[j];
- }
- nambuf[i++] = '.';
- }
- if (bp->refid.number != 0) {
- sprintf(nambuf+i, "r%d.", bp->refid.number);
- i = strlen(nambuf);
- }
- sprintf(nambuf+i, "b%d", ++blkcnt);
- return(nambuf);
- }
-
-
- putface(m, bn, fn, p, a, b, c, d, fp) /* put out a face */
- char *m;
- char *bn, *fn;
- PRISM *p;
- int a, b, c, d;
- FILE *fp;
- {
- int cf;
-
- cf = checkface(p, a, b, c, d);
- if (cf & QL_OK) {
- fprintf(fp, "\n%s polygon %s.%s\n", m, bn, fn);
- fprintf(fp, "0\n0\n12\n");
- putpoint(p, a, fp);
- putpoint(p, b, fp);
- putpoint(p, c, fp);
- putpoint(p, d, fp);
- return;
- }
- if (cf & T1_OK) {
- fprintf(fp, "\n%s polygon %s.%sA\n", m, bn, fn);
- fprintf(fp, "0\n0\n9\n");
- putpoint(p, d, fp);
- putpoint(p, a, fp);
- putpoint(p, b, fp);
- }
- if (cf & T2_OK) {
- fprintf(fp, "\n%s polygon %s.%sB\n", m, bn, fn);
- fprintf(fp, "0\n0\n9\n");
- putpoint(p, b, fp);
- putpoint(p, c, fp);
- putpoint(p, d, fp);
- }
- }
-
-
- #define ldot(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
-
-
- long
- lcross(vr, v1, v2) /* compute cross product */
- register long vr[3], v1[3], v2[3];
- {
- vr[0] = v1[1]*v2[2] - v1[2]*v2[1];
- vr[1] = v1[2]*v2[0] - v1[0]*v2[2];
- vr[2] = v1[0]*v2[1] - v1[1]*v2[0];
- }
-
-
- #define labs(a) ((a)>0 ? (a) : -(a))
-
-
- checkface(p, a, b, c, d) /* check a face for validity */
- register PRISM *p;
- int a, b, c, d;
- {
- int rval = 0;
- long lt;
- long vc1[3], vc2[3], vt1[3], vt2[3];
- long vc1l, vc2l, vc1vc2;
- /* check first triangle */
- vt1[0] = p_x(p,b) - p_x(p,a);
- vt1[1] = p_y(p,b) - p_y(p,a);
- vt1[2] = p_z(p,b) - p_z(p,a);
- vt2[0] = p_x(p,d) - p_x(p,a);
- vt2[1] = p_y(p,d) - p_y(p,a);
- vt2[2] = p_z(p,d) - p_z(p,a);
- lcross(vc1, vt1, vt2);
- lt = labs(vc1[0]) + labs(vc1[1]) + labs(vc1[2]);
- if (lt > 1L<<18) lt = 16;
- else if (lt > 1L<<12) lt = 8;
- else lt = 0;
- if (lt) { vc1[0] >>= lt; vc1[1] >>= lt; vc1[2] >>= lt; }
- vc1l = ldot(vc1,vc1);
- if (vc1l > 4)
- rval |= T1_OK;
- /* check second triangle */
- vt1[0] = p_x(p,d) - p_x(p,c);
- vt1[1] = p_y(p,d) - p_y(p,c);
- vt1[2] = p_z(p,d) - p_z(p,c);
- vt2[0] = p_x(p,b) - p_x(p,c);
- vt2[1] = p_y(p,b) - p_y(p,c);
- vt2[2] = p_z(p,b) - p_z(p,c);
- lcross(vc2, vt1, vt2);
- lt = labs(vc2[0]) + labs(vc2[1]) + labs(vc2[2]);
- if (lt > 1L<<18) lt = 16;
- else if (lt > 1L<<12) lt = 8;
- else lt = 0;
- if (lt) { vc2[0] >>= lt; vc2[1] >>= lt; vc2[2] >>= lt; }
- vc2l = ldot(vc2,vc2);
- if (vc2l > 4)
- rval |= T2_OK;
- /* check quadrilateral */
- if (rval == (T1_OK|T2_OK)) {
- vc1vc2 = ldot(vc1,vc2);
- if (vc1vc2*vc1vc2 >= vc1l*vc2l-8)
- rval |= QL_OK;
- }
- return(rval);
- }
-
-
- putpoint(p, n, fp) /* put out a point */
- register PRISM *p;
- int n;
- FILE *fp;
- {
- register int i = n&3;
-
- fprintf(fp, ptfmt, p->x[i]*fhead.length_f, p->y[i]*fhead.length_f,
- (n&4 ? p->h[i] : p->z[i])*fhead.length_f);
- }
-
-
- eputs(s)
- char *s;
- {
- fputs(s, stderr);
- }
-
-
- quit(code)
- int code;
- {
- exit(code);
- }
-