ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/arch2rad.c
Revision: 2.5
Committed: Thu Feb 9 21:54:10 2023 UTC (14 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.4: +25 -25 lines
Log Message:
fix: compile error fixes related to redeclaration of eputs() and wputs()

File Contents

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