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, 5 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: arch2rad.c,v 2.2 2003/02/22 02:07:23 greg Exp $";
3 #endif
4 /*
5 * Convert Architrion file to Radiance
6 *
7 * Greg Ward
8 */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "rtio.h"
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 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
120 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 {
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 void
172 arch2rad( /* translate Architrion file to Radiance */
173 FILE *inp,
174 FILE *out
175 )
176 {
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 void
200 arch2names( /* get name list from an Architrion file */
201 FILE *inp
202 )
203 {
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 int
215 hasmatch( /* check for any match in rule list */
216 BLOCK *bp,
217 RULEHD *mp
218 )
219 {
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 void
229 getfhead( /* get file header */
230 FILE *fp
231 )
232 {
233 char buf[MAXSTR];
234 int i, n;
235 register int c;
236 /* get file name */
237 if (fgets(buf, MAXSTR, fp) == NULL)
238 goto readerr;
239 buf[strlen(buf)-1] = '\0';
240 fhead.filename = savestr(buf);
241 /* get layers */
242 fhead.layer[0] = "Worksheet";
243 for (i = 1; i <= 8; i++) {
244 if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
245 goto readerr;
246 while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
247 ;
248 if (c == EOF)
249 goto readerr;
250 ungetc(c, fp);
251 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 void
286 puthead( /* put out header information */
287 FILE *fp
288 )
289 {
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 int
304 getblock( /* get an Architrion block */
305 register BLOCK *bp,
306 FILE *fp
307 )
308 {
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 int
347 getopening( /* read in opening from fp */
348 register OPNG *op,
349 FILE *fp
350 )
351 {
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 void
388 doneblock( /* free data associated with bp */
389 register BLOCK *bp
390 )
391 {
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 free((void *)bp->opening);
398 }
399 doneid(&bp->refid);
400 }
401
402
403 void
404 add2quals( /* add to qualifier lists */
405 register BLOCK *bp
406 )
407 {
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 void
426 putblock( /* put out a block */
427 BLOCK *bp,
428 FILE *fp
429 )
430 {
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 void
465 putopenmod( /* put out opening modifier */
466 char *sm,
467 char *ml[],
468 int nm,
469 FILE *fp
470 )
471 {
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 if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
483 rept |= 1<<i;
484 nrepts++;
485 continue;
486 }
487 for (j = 0; j < i; j++)
488 if (!(rept & 1<<j) && ml[j] == ml[i]) {
489 rept |= 1<<j;
490 nrepts++;
491 }
492 }
493 /* print antimatter and modlist */
494 fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
495 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 void
504 putopening( /* put out an opening */
505 OPNG *op,
506 FILE *fp
507 )
508 {
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 if (p->x[2] > p->x[0]) {
523 newp.x[0] -= 2;
524 newp.x[1] -= 2;
525 newp.x[2] += 2;
526 newp.x[3] += 2;
527 } else if (p->x[0] > p->x[2]) {
528 newp.x[0] += 2;
529 newp.x[1] += 2;
530 newp.x[2] -= 2;
531 newp.x[3] -= 2;
532 }
533 if (p->y[2] > p->y[0]) {
534 newp.y[0] -= 2;
535 newp.y[1] -= 2;
536 newp.y[2] += 2;
537 newp.y[3] += 2;
538 } else if (p->y[0] > p->y[2]) {
539 newp.y[0] += 2;
540 newp.y[1] += 2;
541 newp.y[2] -= 2;
542 newp.y[3] -= 2;
543 }
544 /* put out faces */
545 sprintf(buf, "op%d", ++nopens);
546 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 putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
551 putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
552 }
553
554
555 int
556 matchrule( /* see if block matches this rule */
557 register BLOCK *bp,
558 register RULEHD *rp
559 )
560 {
561 register int i;
562 ID tmpid;
563
564 if (rp->qflg & FL(Q_LAY)) { /* check layer */
565 tmpid.name = fhead.layer[bp->layer];
566 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 void
591 putfaces( /* put out faces */
592 char *m,
593 BLOCK *bp,
594 register int ff,
595 FILE *fp
596 )
597 {
598 char *blkname(), *bn;
599
600 if (!strcmp(m, VOIDID))
601 return;
602 bn = blkname(bp);
603 if (ff & 1<<F_REF)
604 putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
605 if (ff & 1<<F_OPP)
606 putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
607 if (ff & 1<<F_END) {
608 putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
609 putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
610 }
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 blkname( /* think up a good name for this block */
620 register BLOCK *bp
621 )
622 {
623 static char nambuf[32];
624 static int blkcnt = 0;
625 register char *nam;
626 register int i, j;
627
628 sprintf(nambuf, "l%d.", bp->layer);
629 i = strlen(nambuf);
630 nam = bp->refid.name;
631 if (nam == NULL) {
632 nam = fhead.layer[bp->layer];
633 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 else
641 nambuf[i++] = nam[j];
642 }
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 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 {
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 void
700 lcross( /* compute cross product */
701 register long vr[3],
702 register long v1[3],
703 register long v2[3]
704 )
705 {
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 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 {
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 void
771 putpoint( /* put out a point */
772 register PRISM *p,
773 int n,
774 FILE *fp
775 )
776 {
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 void
785 eputs(
786 char *s
787 )
788 {
789 fputs(s, stderr);
790 }
791
792
793 void
794 quit(
795 int code
796 )
797 {
798 exit(code);
799 }
800