ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/arch2rad.c
Revision: 2.2
Committed: Sat Feb 22 02:07:23 2003 UTC (21 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 2.1: +6 -5 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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