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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Convert Architrion file to Radiance
6 *
7 * Greg Ward
8 */
9
10 #include <stdio.h>
11
12 #include <stdlib.h>
13
14 #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 register int c;
197 /* get file name */
198 if (fgets(buf, MAXSTR, fp) == NULL)
199 goto readerr;
200 buf[strlen(buf)-1] = '\0';
201 fhead.filename = savestr(buf);
202 /* get layers */
203 fhead.layer[0] = "Worksheet";
204 for (i = 1; i <= 8; i++) {
205 if (fscanf(fp, "L%*[^0-8]%d", &n) != 1 || n != i)
206 goto readerr;
207 while ((c = getc(fp)) != EOF && (c == ' ' || c == '\t'))
208 ;
209 if (c == EOF)
210 goto readerr;
211 ungetc(c, fp);
212 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 free((void *)bp->opening);
351 }
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 if (ml[i] == sm || !strcmp(ml[i], VOIDID)) {
429 rept |= 1<<i;
430 nrepts++;
431 continue;
432 }
433 for (j = 0; j < i; j++)
434 if (!(rept & 1<<j) && ml[j] == ml[i]) {
435 rept |= 1<<j;
436 nrepts++;
437 }
438 }
439 /* print antimatter and modlist */
440 fprintf(fp, "\n%s antimatter %s\n", VOIDID, openmod);
441 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 if (p->x[2] > p->x[0]) {
467 newp.x[0] -= 2;
468 newp.x[1] -= 2;
469 newp.x[2] += 2;
470 newp.x[3] += 2;
471 } else if (p->x[0] > p->x[2]) {
472 newp.x[0] += 2;
473 newp.x[1] += 2;
474 newp.x[2] -= 2;
475 newp.x[3] -= 2;
476 }
477 if (p->y[2] > p->y[0]) {
478 newp.y[0] -= 2;
479 newp.y[1] -= 2;
480 newp.y[2] += 2;
481 newp.y[3] += 2;
482 } else if (p->y[0] > p->y[2]) {
483 newp.y[0] += 2;
484 newp.y[1] += 2;
485 newp.y[2] -= 2;
486 newp.y[3] -= 2;
487 }
488 /* put out faces */
489 sprintf(buf, "op%d", ++nopens);
490 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 putface(openmod, buf, "bot", &newp, 1, 2, 3, 0, fp);
495 putface(openmod, buf, "top", &newp, 7, 6, 5, 4, fp);
496 }
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 tmpid.name = fhead.layer[bp->layer];
509 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 putface(m, bn, "ref", &bp->p, 4, 5, 1, 0, fp);
546 if (ff & 1<<F_OPP)
547 putface(m, bn, "opp", &bp->p, 2, 6, 7, 3, fp);
548 if (ff & 1<<F_END) {
549 putface(m, bn, "end1", &bp->p, 5, 6, 2, 1, fp);
550 putface(m, bn, "end2", &bp->p, 3, 7, 4, 0, fp);
551 }
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 register int i, j;
567
568 sprintf(nambuf, "l%d.", bp->layer);
569 i = strlen(nambuf);
570 nam = bp->refid.name;
571 if (nam == NULL) {
572 nam = fhead.layer[bp->layer];
573 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 else
581 nambuf[i++] = nam[j];
582 }
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 void
709 eputs(s)
710 char *s;
711 {
712 fputs(s, stderr);
713 }
714
715
716 void
717 quit(code)
718 int code;
719 {
720 exit(code);
721 }