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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: arch2rad.c,v 2.4 2019/12/28 18:05:14 greg Exp $";
3 #endif
4 /*
5 * Convert Architrion file to Radiance
6 *
7 * Greg Ward
8 */
9
10 #include <stdlib.h>
11
12 #include "rtio.h"
13 #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 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
118 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 {
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 void
170 arch2rad( /* translate Architrion file to Radiance */
171 FILE *inp,
172 FILE *out
173 )
174 {
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 void
198 arch2names( /* get name list from an Architrion file */
199 FILE *inp
200 )
201 {
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 int
213 hasmatch( /* check for any match in rule list */
214 BLOCK *bp,
215 RULEHD *mp
216 )
217 {
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 void
227 getfhead( /* get file header */
228 FILE *fp
229 )
230 {
231 char buf[MAXSTR];
232 int i, n;
233 int c;
234 /* get file name */
235 if (fgets(buf, MAXSTR, fp) == NULL)
236 goto readerr;
237 buf[strlen(buf)-1] = '\0';
238 fhead.filename = savestr(buf);
239 /* get layers */
240 fhead.layer[0] = "Worksheet";
241 for (i = 1; i <= 8; i++) {
242 if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
243 goto readerr;
244 while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
245 ;
246 if (c == EOF)
247 goto readerr;
248 ungetc(c, fp);
249 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 void
284 puthead( /* put out header information */
285 FILE *fp
286 )
287 {
288 int i;
289
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 int
302 getblock( /* get an Architrion block */
303 BLOCK *bp,
304 FILE *fp
305 )
306 {
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 int
345 getopening( /* read in opening from fp */
346 OPNG *op,
347 FILE *fp
348 )
349 {
350 int c;
351 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 void
386 doneblock( /* free data associated with bp */
387 BLOCK *bp
388 )
389 {
390 int i;
391
392 if (bp->nopenings > 0) {
393 for (i = 0; i < bp->nopenings; i++)
394 doneid(&bp->opening[i].frame);
395 free((void *)bp->opening);
396 }
397 doneid(&bp->refid);
398 }
399
400
401 void
402 add2quals( /* add to qualifier lists */
403 BLOCK *bp
404 )
405 {
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 void
424 putblock( /* put out a block */
425 BLOCK *bp,
426 FILE *fp
427 )
428 {
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 void
463 putopenmod( /* put out opening modifier */
464 char *sm,
465 char *ml[],
466 int nm,
467 FILE *fp
468 )
469 {
470 int rept, nrepts;
471 int i, j;
472
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 if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
481 rept |= 1<<i;
482 nrepts++;
483 continue;
484 }
485 for (j = 0; j < i; j++)
486 if (!(rept & 1<<j) && ml[j] == ml[i]) {
487 rept |= 1<<j;
488 nrepts++;
489 }
490 }
491 /* print antimatter and modlist */
492 fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
493 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 void
502 putopening( /* put out an opening */
503 OPNG *op,
504 FILE *fp
505 )
506 {
507 static int nopens = 0;
508 char buf[32];
509 PRISM *p = &op->p;
510 PRISM newp;
511 int i;
512 /* 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 if (p->x[2] > p->x[0]) {
521 newp.x[0] -= 2;
522 newp.x[1] -= 2;
523 newp.x[2] += 2;
524 newp.x[3] += 2;
525 } else if (p->x[0] > p->x[2]) {
526 newp.x[0] += 2;
527 newp.x[1] += 2;
528 newp.x[2] -= 2;
529 newp.x[3] -= 2;
530 }
531 if (p->y[2] > p->y[0]) {
532 newp.y[0] -= 2;
533 newp.y[1] -= 2;
534 newp.y[2] += 2;
535 newp.y[3] += 2;
536 } else if (p->y[0] > p->y[2]) {
537 newp.y[0] += 2;
538 newp.y[1] += 2;
539 newp.y[2] -= 2;
540 newp.y[3] -= 2;
541 }
542 /* put out faces */
543 sprintf(buf, "op%d", ++nopens);
544 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 putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
549 putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
550 }
551
552
553 int
554 matchrule( /* see if block matches this rule */
555 BLOCK *bp,
556 RULEHD *rp
557 )
558 {
559 int i;
560 ID tmpid;
561
562 if (rp->qflg & FL(Q_LAY)) { /* check layer */
563 tmpid.name = fhead.layer[bp->layer];
564 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 void
589 putfaces( /* put out faces */
590 char *m,
591 BLOCK *bp,
592 int ff,
593 FILE *fp
594 )
595 {
596 char *blkname(), *bn;
597
598 if (!strcmp(m, VOIDID))
599 return;
600 bn = blkname(bp);
601 if (ff & 1<<F_REF)
602 putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
603 if (ff & 1<<F_OPP)
604 putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
605 if (ff & 1<<F_END) {
606 putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
607 putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
608 }
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 blkname( /* think up a good name for this block */
618 BLOCK *bp
619 )
620 {
621 static char nambuf[32];
622 static int blkcnt = 0;
623 char *nam;
624 int i, j;
625
626 sprintf(nambuf, "l%d.", bp->layer);
627 i = strlen(nambuf);
628 nam = bp->refid.name;
629 if (nam == NULL) {
630 nam = fhead.layer[bp->layer];
631 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 else
639 nambuf[i++] = nam[j];
640 }
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 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 {
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 void
698 lcross( /* compute cross product */
699 long vr[3],
700 long v1[3],
701 long v2[3]
702 )
703 {
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 int
714 checkface( /* check a face for validity */
715 PRISM *p,
716 int a,
717 int b,
718 int c,
719 int d
720 )
721 {
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 void
769 putpoint( /* put out a point */
770 PRISM *p,
771 int n,
772 FILE *fp
773 )
774 {
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 void
783 eputs(
784 const char *s
785 )
786 {
787 fputs(s, stderr);
788 }
789
790
791 void
792 quit(
793 int code
794 )
795 {
796 exit(code);
797 }
798