ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/arch2rad.c
Revision: 2.1
Committed: Tue Nov 12 17:02:07 1991 UTC (32 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +0 -0 lines
Log Message:
updated revision number for release 2.0

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1990 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ 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 greg 1.3 register int c;
198 greg 1.1 /* get file name */
199     if (fgets(buf, MAXSTR, fp) == NULL)
200     goto readerr;
201 greg 1.3 buf[strlen(buf)-1] = '\0';
202 greg 1.1 fhead.filename = savestr(buf);
203     /* get layers */
204     fhead.layer[0] = "Worksheet";
205     for (i = 1; i <= 8; i++) {
206 greg 1.3 if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
207 greg 1.1 goto readerr;
208 greg 1.3 while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
209 greg 1.1 ;
210 greg 1.3 if (c == EOF)
211 greg 1.1 goto readerr;
212 greg 1.3 ungetc(c, fp);
213 greg 1.1 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 greg 1.7 if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
430 greg 1.1 rept |= 1<<i;
431     nrepts++;
432 greg 1.7 continue;
433 greg 1.1 }
434     for (j = 0; j < i; j++)
435 greg 1.7 if (!(rept & 1<<j) && ml[j] == ml[i]) {
436 greg 1.1 rept |= 1<<j;
437     nrepts++;
438     }
439     }
440     /* print antimatter and modlist */
441 greg 1.7 fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
442 greg 1.1 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 greg 1.6 if (p->x[2] > p->x[0]) {
468 greg 1.1 newp.x[0] -= 2;
469 greg 1.6 newp.x[1] -= 2;
470 greg 1.1 newp.x[2] += 2;
471 greg 1.6 newp.x[3] += 2;
472     } else if (p->x[0] > p->x[2]) {
473 greg 1.1 newp.x[0] += 2;
474 greg 1.6 newp.x[1] += 2;
475 greg 1.1 newp.x[2] -= 2;
476 greg 1.6 newp.x[3] -= 2;
477 greg 1.1 }
478 greg 1.6 if (p->y[2] > p->y[0]) {
479 greg 1.1 newp.y[0] -= 2;
480 greg 1.6 newp.y[1] -= 2;
481 greg 1.1 newp.y[2] += 2;
482 greg 1.6 newp.y[3] += 2;
483     } else if (p->y[0] > p->y[2]) {
484 greg 1.1 newp.y[0] += 2;
485 greg 1.6 newp.y[1] += 2;
486 greg 1.1 newp.y[2] -= 2;
487 greg 1.6 newp.y[3] -= 2;
488 greg 1.1 }
489     /* put out faces */
490     sprintf(buf, "op%d", ++nopens);
491 greg 1.5 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 greg 1.2 putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
496     putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
497 greg 1.1 }
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 greg 1.4 tmpid.name = fhead.layer[bp->layer];
510 greg 1.1 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 greg 1.5 putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
547 greg 1.1 if (ff & 1<<F_OPP)
548 greg 1.5 putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
549 greg 1.1 if (ff & 1<<F_END) {
550 greg 1.5 putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
551     putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
552 greg 1.1 }
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 greg 1.4 register int i, j;
568 greg 1.1
569 greg 1.4 sprintf(nambuf, "l%d.", bp->layer);
570     i = strlen(nambuf);
571 greg 1.1 nam = bp->refid.name;
572 greg 1.4 if (nam == NULL) {
573 greg 1.1 nam = fhead.layer[bp->layer];
574 greg 1.4 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 greg 1.1 else
582 greg 1.4 nambuf[i++] = nam[j];
583 greg 1.1 }
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     }