ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/arch2rad.c
Revision: 2.3
Committed: Sat Nov 15 17:54:06 2003 UTC (20 years, 4 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R2, rad4R2P2, rad5R0, rad5R1, rad3R7P2, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9, rad4R2P1
Changes since 2.2: +146 -67 lines
Log Message:
Continued ANSIfication and reduced compile warnings.

File Contents

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