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

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