ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.19
Committed: Mon Jun 30 14:59:11 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.18: +3 -3 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ies2rad.c,v 2.18 2003/02/22 02:07:23 greg Exp $";
3 #endif
4 /*
5 * Convert IES luminaire data to Radiance description
6 *
7 * 07Apr90 Greg Ward
8 *
9 * Fixed correction factor for flat sources 29Oct2001 GW
10 */
11
12 #include <stdio.h>
13 #include <math.h>
14 #include <sys/types.h>
15 #include <ctype.h>
16 #include "color.h"
17 #include "paths.h"
18
19 #define PI 3.14159265358979323846
20 /* floating comparisons */
21 #define FTINY 1e-6
22 #define FEQ(a,b) ((a)<=(b)+FTINY&&(a)>=(b)-FTINY)
23 /* keywords */
24 #define MAGICID "IESNA"
25 #define LMAGICID 5
26 #define FIRSTREV 86
27 #define LASTREV 95
28
29 #define D86 0 /* keywords defined in LM-63-1986 */
30
31 #define K_TST 0
32 #define K_MAN 1
33 #define K_LMC 2
34 #define K_LMN 3
35 #define K_LPC 4
36 #define K_LMP 5
37 #define K_BAL 6
38 #define K_MTC 7
39 #define K_OTH 8
40 #define K_SCH 9
41 #define K_MOR 10
42 #define K_BLK 11
43 #define K_EBK 12
44
45 #define D91 ((1L<<13)-1) /* keywords defined in LM-63-1991 */
46
47 #define K_LMG 13
48
49 #define D95 ((1L<<14)-1) /* keywords defined in LM-63-1995 */
50
51 char k_kwd[][20] = {"TEST", "MANUFAC", "LUMCAT", "LUMINAIRE", "LAMPCAT",
52 "LAMP", "BALLAST", "MAINTCAT", "OTHER", "SEARCH",
53 "MORE", "BLOCK", "ENDBLOCK", "LUMINOUSGEOMETRY"};
54
55 long k_defined[] = {D86, D86, D86, D86, D86, D91, D91, D91, D91, D95};
56
57 int filerev = FIRSTREV;
58
59 #define keymatch(i,s) (k_defined[filerev-FIRSTREV]&1L<<(i) &&\
60 k_match(k_kwd[i],s))
61
62 #define checklamp(s) (!(k_defined[filerev-FIRSTREV]&(1<<K_LMP|1<<K_LPC)) ||\
63 keymatch(K_LMP,s) || keymatch(K_LPC,s))
64
65 /* tilt specs */
66 #define TLTSTR "TILT="
67 #define TLTSTRLEN 5
68 #define TLTNONE "NONE"
69 #define TLTINCL "INCLUDE"
70 #define TLT_VERT 1
71 #define TLT_H0 2
72 #define TLT_H90 3
73 /* photometric types */
74 #define PM_C 1
75 #define PM_B 2
76 /* unit types */
77 #define U_FEET 1
78 #define U_METERS 2
79 /* string lengths */
80 #define MAXLINE 132
81 #define MAXWORD 76
82 /* file types */
83 #define T_RAD ".rad"
84 #define T_DST ".dat"
85 #define T_TLT "%.dat"
86 #define T_OCT ".oct"
87 /* shape types */
88 #define RECT 1
89 #define DISK 2
90 #define SPHERE 3
91
92 #define MINDIM .001 /* minimum dimension (point source) */
93
94 #define F_M .3048 /* feet to meters */
95
96 #define abspath(p) (ISDIRSEP((p)[0]) || (p)[0] == '.')
97
98 static char default_name[] = "default";
99
100 char *libdir = NULL; /* library directory location */
101 char *prefdir = NULL; /* subdirectory */
102 char *lampdat = "lamp.tab"; /* lamp data file */
103
104 double meters2out = 1.0; /* conversion from meters to output */
105 char *lamptype = NULL; /* selected lamp type */
106 char *deflamp = NULL; /* default lamp type */
107 float defcolor[3] = {1.,1.,1.}; /* default lamp color */
108 float *lampcolor = defcolor; /* pointer to current lamp color */
109 double multiplier = 1.0; /* multiplier for all light sources */
110 char units[64] = "meters"; /* output units */
111 int out2stdout = 0; /* put out to stdout r.t. file */
112 int instantiate = 0; /* instantiate geometry */
113 double illumrad = 0.0; /* radius for illum sphere */
114
115 typedef struct {
116 int isillum; /* do as illum */
117 int type; /* RECT, DISK, SPHERE */
118 double mult; /* candela multiplier */
119 double w, l, h; /* width, length, height */
120 double area; /* max. projected area */
121 } SRCINFO; /* a source shape (units=meters) */
122
123 int gargc; /* global argc (minus filenames) */
124 char **gargv; /* global argv */
125
126 extern char *strcpy(), *strcat(), *stradd(), *tailtrunc(), *filetrunc(),
127 *filename(), *libname(), *fullnam(), *getword(), *atos();
128 extern float *matchlamp();
129 extern time_t fdate();
130
131 #define scnint(fp,ip) cvtint(ip,getword(fp))
132 #define scnflt(fp,rp) cvtflt(rp,getword(fp))
133 #define isint isflt /* IES allows real as integer */
134
135
136 main(argc, argv)
137 int argc;
138 char *argv[];
139 {
140 char *outfile = NULL;
141 int status;
142 char outname[MAXWORD];
143 double d1;
144 int i;
145
146 for (i = 1; i < argc && argv[i][0] == '-'; i++)
147 switch (argv[i][1]) {
148 case 'd': /* dimensions */
149 if (argv[i][2] == '\0')
150 goto badopt;
151 if (argv[i][3] == '\0')
152 d1 = 1.0;
153 else if (argv[i][3] == '/') {
154 d1 = atof(argv[i]+4);
155 if (d1 <= FTINY)
156 goto badopt;
157 } else
158 goto badopt;
159 switch (argv[i][2]) {
160 case 'c': /* centimeters */
161 if (FEQ(d1,10.))
162 strcpy(units,"millimeters");
163 else {
164 strcpy(units,"centimeters");
165 strcat(units,argv[i]+3);
166 }
167 meters2out = 100.*d1;
168 break;
169 case 'm': /* meters */
170 if (FEQ(d1,1000.))
171 strcpy(units,"millimeters");
172 else if (FEQ(d1,100.))
173 strcpy(units,"centimeters");
174 else {
175 strcpy(units,"meters");
176 strcat(units,argv[i]+3);
177 }
178 meters2out = d1;
179 break;
180 case 'i': /* inches */
181 strcpy(units,"inches");
182 strcat(units,argv[i]+3);
183 meters2out = d1*(12./F_M);
184 break;
185 case 'f': /* feet */
186 if (FEQ(d1,12.))
187 strcpy(units,"inches");
188 else {
189 strcpy(units,"feet");
190 strcat(units,argv[i]+3);
191 }
192 meters2out = d1/F_M;
193 break;
194 default:
195 goto badopt;
196 }
197 break;
198 case 'l': /* library directory */
199 libdir = argv[++i];
200 break;
201 case 'p': /* prefix subdirectory */
202 prefdir = argv[++i];
203 break;
204 case 'f': /* lamp data file */
205 lampdat = argv[++i];
206 break;
207 case 'o': /* output file root name */
208 outfile = argv[++i];
209 break;
210 case 's': /* output to stdout */
211 out2stdout = !out2stdout;
212 break;
213 case 'i': /* illum */
214 illumrad = atof(argv[++i]);
215 break;
216 case 'g': /* instatiate geometry? */
217 instantiate = !instantiate;
218 break;
219 case 't': /* override lamp type */
220 lamptype = argv[++i];
221 break;
222 case 'u': /* default lamp type */
223 deflamp = argv[++i];
224 break;
225 case 'c': /* default lamp color */
226 defcolor[0] = atof(argv[++i]);
227 defcolor[1] = atof(argv[++i]);
228 defcolor[2] = atof(argv[++i]);
229 break;
230 case 'm': /* multiplier */
231 multiplier = atof(argv[++i]);
232 break;
233 default:
234 badopt:
235 fprintf(stderr, "%s: bad option: %s\n",
236 argv[0], argv[i]);
237 exit(1);
238 }
239 gargc = i;
240 gargv = argv;
241 initlamps(); /* get lamp data (if needed) */
242 /* convert ies file(s) */
243 if (outfile != NULL) {
244 if (i == argc)
245 exit(ies2rad(NULL, outfile) == 0 ? 0 : 1);
246 else if (i == argc-1)
247 exit(ies2rad(argv[i], outfile) == 0 ? 0 : 1);
248 else
249 goto needsingle;
250 } else if (i >= argc) {
251 fprintf(stderr, "%s: missing output file specification\n",
252 argv[0]);
253 exit(1);
254 }
255 if (out2stdout && i != argc-1)
256 goto needsingle;
257 status = 0;
258 for ( ; i < argc; i++) {
259 tailtrunc(strcpy(outname,filename(argv[i])));
260 if (ies2rad(argv[i], outname) != 0)
261 status = 1;
262 }
263 exit(status);
264 needsingle:
265 fprintf(stderr, "%s: single input file required\n", argv[0]);
266 exit(1);
267 }
268
269
270 initlamps() /* set up lamps */
271 {
272 float *lcol;
273 int status;
274
275 if (lamptype != NULL && !strcmp(lamptype, default_name) &&
276 deflamp == NULL)
277 return; /* no need for data */
278 /* else load file */
279 if ((status = loadlamps(lampdat)) < 0)
280 exit(1);
281 if (status == 0) {
282 fprintf(stderr, "%s: warning - no lamp data\n", lampdat);
283 lamptype = default_name;
284 return;
285 }
286 if (deflamp != NULL) { /* match default type */
287 if ((lcol = matchlamp(deflamp)) == NULL)
288 fprintf(stderr,
289 "%s: warning - unknown default lamp type\n",
290 deflamp);
291 else
292 copycolor(defcolor, lcol);
293 }
294 if (lamptype != NULL) { /* match selected type */
295 if (strcmp(lamptype, default_name)) {
296 if ((lcol = matchlamp(lamptype)) == NULL) {
297 fprintf(stderr,
298 "%s: warning - unknown lamp type\n",
299 lamptype);
300 lamptype = default_name;
301 } else
302 copycolor(defcolor, lcol);
303 }
304 freelamps(); /* all done with data */
305 }
306 /* else keep lamp data */
307 }
308
309
310 char *
311 stradd(dst, src, sep) /* add a string at dst */
312 register char *dst, *src;
313 int sep;
314 {
315 if (src && *src) {
316 do
317 *dst++ = *src++;
318 while (*src);
319 if (sep && dst[-1] != sep)
320 *dst++ = sep;
321 }
322 *dst = '\0';
323 return(dst);
324 }
325
326
327 char *
328 fullnam(path, fname, suffix) /* return full path name */
329 char *path, *fname, *suffix;
330 {
331 if (prefdir != NULL && abspath(prefdir))
332 libname(path, fname, suffix);
333 else if (abspath(fname))
334 strcpy(stradd(path, fname, 0), suffix);
335 else
336 libname(stradd(path, libdir, DIRSEP), fname, suffix);
337
338 return(path);
339 }
340
341
342 char *
343 libname(path, fname, suffix) /* return library relative name */
344 char *path, *fname, *suffix;
345 {
346 if (abspath(fname))
347 strcpy(stradd(path, fname, 0), suffix);
348 else
349 strcpy(stradd(stradd(path, prefdir, DIRSEP), fname, 0), suffix);
350
351 return(path);
352 }
353
354
355 char *
356 filename(path) /* get final component of pathname */
357 register char *path;
358 {
359 register char *cp;
360
361 for (cp = path; *path; path++)
362 if (ISDIRSEP(*path))
363 cp = path+1;
364 return(cp);
365 }
366
367
368 char *
369 filetrunc(path) /* truncate filename at end of path */
370 char *path;
371 {
372 register char *p1, *p2;
373
374 for (p1 = p2 = path; *p2; p2++)
375 if (ISDIRSEP(*p2))
376 p1 = p2;
377 if (p1 == path && ISDIRSEP(*p1))
378 p1++;
379 *p1 = '\0';
380 return(path);
381 }
382
383
384 char *
385 tailtrunc(name) /* truncate tail of filename */
386 char *name;
387 {
388 register char *p1, *p2;
389
390 for (p1 = filename(name); *p1 == '.'; p1++)
391 ;
392 p2 = NULL;
393 for ( ; *p1; p1++)
394 if (*p1 == '.')
395 p2 = p1;
396 if (p2 != NULL)
397 *p2 = '\0';
398 return(name);
399 }
400
401
402 blanktrunc(s) /* truncate spaces at end of line */
403 char *s;
404 {
405 register char *cp;
406
407 for (cp = s; *cp; cp++)
408 ;
409 while (cp-- > s && isspace(*cp))
410 ;
411 *++cp = '\0';
412 }
413
414
415 k_match(kwd, hdl) /* header line matches keyword? */
416 register char *kwd, *hdl;
417 {
418 if (!*hdl++ == '[')
419 return(0);
420 while (islower(*hdl) ? toupper(*hdl) == *kwd++ : *hdl == *kwd++)
421 if (!*hdl++)
422 return(0);
423 return(!*kwd & *hdl == ']');
424 }
425
426
427 char *
428 keyargs(hdl) /* return keyword arguments */
429 register char *hdl;
430 {
431 while (*hdl && *hdl++ != ']')
432 ;
433 while (isspace(*hdl))
434 hdl++;
435 return(hdl);
436 }
437
438
439 putheader(out) /* print header */
440 FILE *out;
441 {
442 register int i;
443
444 putc('#', out);
445 for (i = 0; i < gargc; i++) {
446 putc(' ', out);
447 fputs(gargv[i], out);
448 }
449 fputs("\n# Dimensions in ", out);
450 fputs(units, out);
451 putc('\n', out);
452 }
453
454
455 ies2rad(inpname, outname) /* convert IES file */
456 char *inpname, *outname;
457 {
458 SRCINFO srcinfo;
459 char buf[MAXLINE], tltid[MAXWORD];
460 char geomfile[128];
461 FILE *inpfp, *outfp;
462 int lineno = 0;
463
464 geomfile[0] = '\0';
465 srcinfo.isillum = 0;
466 if (inpname == NULL) {
467 inpname = "<stdin>";
468 inpfp = stdin;
469 } else if ((inpfp = fopen(inpname, "r")) == NULL) {
470 perror(inpname);
471 return(-1);
472 }
473 if (out2stdout)
474 outfp = stdout;
475 else if ((outfp = fopen(fullnam(buf,outname,T_RAD), "w")) == NULL) {
476 perror(buf);
477 fclose(inpfp);
478 return(-1);
479 }
480 putheader(outfp);
481 if (lamptype == NULL)
482 lampcolor = NULL;
483 while (fgets(buf,sizeof(buf),inpfp) != NULL
484 && strncmp(buf,TLTSTR,TLTSTRLEN)) {
485 blanktrunc(buf);
486 if (!buf[0])
487 continue;
488 if (!lineno++ && !strncmp(buf, MAGICID, LMAGICID)) {
489 filerev = atoi(buf+LMAGICID);
490 if (filerev < FIRSTREV)
491 filerev = FIRSTREV;
492 else if (filerev > LASTREV)
493 filerev = LASTREV;
494 }
495 fputs("#<", outfp);
496 fputs(buf, outfp);
497 putc('\n', outfp);
498 if (lampcolor == NULL && checklamp(buf))
499 lampcolor = matchlamp( buf[0] == '[' ?
500 keyargs(buf) : buf );
501 if (keymatch(K_LMG, buf)) { /* geometry file */
502 strcpy(geomfile, inpname);
503 strcpy(filename(geomfile), keyargs(buf));
504 srcinfo.isillum = 1;
505 }
506 }
507 if (lampcolor == NULL) {
508 fprintf(stderr, "%s: warning - no lamp type\n", inpname);
509 fputs("# Unknown lamp type (used default)\n", outfp);
510 lampcolor = defcolor;
511 } else if (lamptype == NULL)
512 fprintf(outfp,"# CIE(x,y) = (%f,%f)\n# Depreciation = %.1f%%\n",
513 lampcolor[3], lampcolor[4], 100.*lampcolor[5]);
514 if (feof(inpfp)) {
515 fprintf(stderr, "%s: not in IES format\n", inpname);
516 goto readerr;
517 }
518 atos(tltid, MAXWORD, buf+TLTSTRLEN);
519 if (inpfp == stdin)
520 buf[0] = '\0';
521 else
522 filetrunc(strcpy(buf, inpname));
523 if (dotilt(inpfp, outfp, buf, tltid, outname, tltid) != 0) {
524 fprintf(stderr, "%s: bad tilt data\n", inpname);
525 goto readerr;
526 }
527 if (dosource(&srcinfo, inpfp, outfp, tltid, outname) != 0) {
528 fprintf(stderr, "%s: bad luminaire data\n", inpname);
529 goto readerr;
530 }
531 fclose(inpfp);
532 /* cvgeometry closes outfp */
533 if (cvgeometry(geomfile, &srcinfo, outname, outfp) != 0) {
534 fprintf(stderr, "%s: bad geometry file\n", geomfile);
535 return(-1);
536 }
537 return(0);
538 readerr:
539 fclose(inpfp);
540 fclose(outfp);
541 unlink(fullnam(buf,outname,T_RAD));
542 return(-1);
543 }
544
545
546 dotilt(in, out, dir, tltspec, dfltname, tltid) /* convert tilt data */
547 FILE *in, *out;
548 char *dir, *tltspec, *dfltname, *tltid;
549 {
550 int nangles, tlt_type;
551 double minmax[2];
552 char buf[PATH_MAX], tltname[MAXWORD];
553 FILE *datin, *datout;
554
555 if (!strcmp(tltspec, TLTNONE)) {
556 datin = NULL;
557 strcpy(tltid, "void");
558 } else if (!strcmp(tltspec, TLTINCL)) {
559 datin = in;
560 strcpy(tltname, dfltname);
561 } else {
562 if (ISDIRSEP(tltspec[0]))
563 strcpy(buf, tltspec);
564 else
565 strcpy(stradd(buf, dir, DIRSEP), tltspec);
566 if ((datin = fopen(buf, "r")) == NULL) {
567 perror(buf);
568 return(-1);
569 }
570 tailtrunc(strcpy(tltname,filename(tltspec)));
571 }
572 if (datin != NULL) {
573 if ((datout = fopen(fullnam(buf,tltname,T_TLT),"w")) == NULL) {
574 perror(buf);
575 if (datin != in)
576 fclose(datin);
577 return(-1);
578 }
579 if (!scnint(datin,&tlt_type) || !scnint(datin,&nangles)
580 || cvdata(datin,datout,1,&nangles,1.,minmax) != 0) {
581 fprintf(stderr, "%s: data format error\n", tltspec);
582 fclose(datout);
583 if (datin != in)
584 fclose(datin);
585 unlink(fullnam(buf,tltname,T_TLT));
586 return(-1);
587 }
588 fclose(datout);
589 if (datin != in)
590 fclose(datin);
591 strcat(strcpy(tltid, filename(tltname)), "_tilt");
592 fprintf(out, "\nvoid brightdata %s\n", tltid);
593 libname(buf,tltname,T_TLT);
594 switch (tlt_type) {
595 case TLT_VERT: /* vertical */
596 fprintf(out, "4 noop %s tilt.cal %s\n", buf,
597 minmax[1]>90.+FTINY ? "tilt_ang" : "tilt_ang2");
598 break;
599 case TLT_H0: /* horiz. in 0 deg. plane */
600 fprintf(out, "6 noop %s tilt.cal %s -rz 90\n", buf,
601 minmax[1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
602 break;
603 case TLT_H90:
604 fprintf(out, "4 noop %s tilt.cal %s\n", buf,
605 minmax[1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
606 break;
607 default:
608 fprintf(stderr,
609 "%s: illegal lamp to luminaire geometry (%d)\n",
610 tltspec, tlt_type);
611 return(-1);
612 }
613 fprintf(out, "0\n0\n");
614 }
615 return(0);
616 }
617
618
619 dosource(sinf, in, out, mod, name) /* create source and distribution */
620 SRCINFO *sinf;
621 FILE *in, *out;
622 char *mod, *name;
623 {
624 char buf[PATH_MAX], id[MAXWORD];
625 FILE *datout;
626 double mult, bfactor, pfactor, width, length, height, wattage;
627 double bounds[2][2];
628 int nangles[2], pmtype, unitype;
629 double d1;
630 int doupper, dolower, dosides;
631
632 if (!isint(getword(in)) || !isflt(getword(in)) || !scnflt(in,&mult)
633 || !scnint(in,&nangles[0]) || !scnint(in,&nangles[1])
634 || !scnint(in,&pmtype) || !scnint(in,&unitype)
635 || !scnflt(in,&width) || !scnflt(in,&length)
636 || !scnflt(in,&height) || !scnflt(in,&bfactor)
637 || !scnflt(in,&pfactor) || !scnflt(in,&wattage)) {
638 fprintf(stderr, "dosource: bad lamp specification\n");
639 return(-1);
640 }
641 sinf->mult = multiplier*mult*bfactor*pfactor;
642 if (nangles[0] < 2 || nangles[1] < 1) {
643 fprintf(stderr, "dosource: too few measured angles\n");
644 return(-1);
645 }
646 if (unitype == U_FEET) {
647 width *= F_M;
648 length *= F_M;
649 height *= F_M;
650 }
651 if (makeshape(sinf, width, length, height) != 0) {
652 fprintf(stderr, "dosource: illegal source dimensions");
653 return(-1);
654 }
655 if ((datout = fopen(fullnam(buf,name,T_DST), "w")) == NULL) {
656 perror(buf);
657 return(-1);
658 }
659 if (cvdata(in, datout, 2, nangles, 1./WHTEFFICACY, bounds) != 0) {
660 fprintf(stderr, "dosource: bad distribution data\n");
661 fclose(datout);
662 unlink(fullnam(buf,name,T_DST));
663 return(-1);
664 }
665 fclose(datout);
666 fprintf(out, "# %g watt luminaire, lamp*ballast factor = %g\n",
667 wattage, bfactor*pfactor);
668 strcat(strcpy(id, filename(name)), "_dist");
669 fprintf(out, "\n%s brightdata %s\n", mod, id);
670 if (nangles[1] < 2)
671 fprintf(out, "4 ");
672 else if (pmtype == PM_B)
673 fprintf(out, "5 ");
674 else if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.))
675 fprintf(out, "7 ");
676 else
677 fprintf(out, "5 ");
678 dolower = (bounds[0][0] < 90.);
679 doupper = (bounds[0][1] > 90.);
680 dosides = (doupper & dolower && sinf->h > MINDIM);
681 fprintf(out, "%s %s source.cal ",
682 sinf->type==SPHERE ? "corr" :
683 !dosides ? "flatcorr" :
684 sinf->type==DISK ? "cylcorr" : "boxcorr",
685 libname(buf,name,T_DST));
686 if (pmtype == PM_B) {
687 if (FEQ(bounds[1][0],0.))
688 fprintf(out, "srcB_horiz2 ");
689 else
690 fprintf(out, "srcB_horiz ");
691 fprintf(out, "srcB_vert ");
692 } else /* pmtype == PM_A */ {
693 if (nangles[1] >= 2) {
694 d1 = bounds[1][1] - bounds[1][0];
695 if (d1 <= 90.+FTINY)
696 fprintf(out, "src_phi4 ");
697 else if (d1 <= 180.+FTINY) {
698 if (FEQ(bounds[1][0],90.))
699 fprintf(out, "src_phi2+90 ");
700 else
701 fprintf(out, "src_phi2 ");
702 } else
703 fprintf(out, "src_phi ");
704 fprintf(out, "src_theta ");
705 if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.))
706 fprintf(out, "-rz -90 ");
707 } else
708 fprintf(out, "src_theta ");
709 }
710 if (!dosides || sinf->type == SPHERE)
711 fprintf(out, "\n0\n1 %g\n", sinf->mult/sinf->area);
712 else if (sinf->type == DISK)
713 fprintf(out, "\n0\n3 %g %g %g\n", sinf->mult,
714 sinf->w, sinf->h);
715 else
716 fprintf(out, "\n0\n4 %g %g %g %g\n", sinf->mult,
717 sinf->l, sinf->w, sinf->h);
718 if (putsource(sinf, out, id, filename(name),
719 dolower, doupper, dosides) != 0)
720 return(-1);
721 return(0);
722 }
723
724
725 putsource(shp, fp, mod, name, dolower, doupper, dosides) /* put out source */
726 SRCINFO *shp;
727 FILE *fp;
728 char *mod, *name;
729 int dolower, doupper;
730 {
731 char lname[MAXWORD];
732
733 strcat(strcpy(lname, name), "_light");
734 fprintf(fp, "\n%s %s %s\n", mod,
735 shp->isillum ? "illum" : "light", lname);
736 fprintf(fp, "0\n0\n3 %g %g %g\n",
737 lampcolor[0], lampcolor[1], lampcolor[2]);
738 switch (shp->type) {
739 case RECT:
740 if (dolower)
741 putrectsrc(shp, fp, lname, name, 0);
742 if (doupper)
743 putrectsrc(shp, fp, lname, name, 1);
744 if (dosides)
745 putsides(shp, fp, lname, name);
746 break;
747 case DISK:
748 if (dolower)
749 putdisksrc(shp, fp, lname, name, 0);
750 if (doupper)
751 putdisksrc(shp, fp, lname, name, 1);
752 if (dosides)
753 putcyl(shp, fp, lname, name);
754 break;
755 case SPHERE:
756 putspheresrc(shp, fp, lname, name);
757 break;
758 }
759 return(0);
760 }
761
762
763 makeshape(shp, width, length, height) /* make source shape */
764 register SRCINFO *shp;
765 double width, length, height;
766 {
767 if (illumrad/meters2out >= MINDIM/2.) {
768 shp->isillum = 1;
769 shp->type = SPHERE;
770 shp->w = shp->l = shp->h = 2.*illumrad / meters2out;
771 } else if (width < MINDIM) {
772 width = -width;
773 if (width < MINDIM) {
774 shp->type = SPHERE;
775 shp->w = shp->l = shp->h = MINDIM;
776 } else if (height < .5*width) {
777 shp->type = DISK;
778 shp->w = shp->l = width;
779 if (height >= MINDIM)
780 shp->h = height;
781 else
782 shp->h = .5*MINDIM;
783 } else {
784 shp->type = SPHERE;
785 shp->w = shp->l = shp->h = width;
786 }
787 } else {
788 shp->type = RECT;
789 shp->w = width;
790 if (length >= MINDIM)
791 shp->l = length;
792 else
793 shp->l = MINDIM;
794 if (height >= MINDIM)
795 shp->h = height;
796 else
797 shp->h = .5*MINDIM;
798 }
799 switch (shp->type) {
800 case RECT:
801 shp->area = shp->w * shp->l;
802 break;
803 case DISK:
804 case SPHERE:
805 shp->area = PI/4. * shp->w * shp->w;
806 break;
807 }
808 return(0);
809 }
810
811
812 putrectsrc(shp, fp, mod, name, up) /* rectangular source */
813 SRCINFO *shp;
814 FILE *fp;
815 char *mod, *name;
816 int up;
817 {
818 if (up)
819 putrect(shp, fp, mod, name, ".u", 4, 5, 7, 6);
820 else
821 putrect(shp, fp, mod, name, ".d", 0, 2, 3, 1);
822 }
823
824
825 putsides(shp, fp, mod, name) /* put out sides of box */
826 register SRCINFO *shp;
827 FILE *fp;
828 char *mod, *name;
829 {
830 putrect(shp, fp, mod, name, ".1", 0, 1, 5, 4);
831 putrect(shp, fp, mod, name, ".2", 1, 3, 7, 5);
832 putrect(shp, fp, mod, name, ".3", 3, 2, 6, 7);
833 putrect(shp, fp, mod, name, ".4", 2, 0, 4, 6);
834 }
835
836
837 putrect(shp, fp, mod, name, suffix, a, b, c, d) /* put out a rectangle */
838 SRCINFO *shp;
839 FILE *fp;
840 char *mod, *name, *suffix;
841 int a, b, c, d;
842 {
843 fprintf(fp, "\n%s polygon %s%s\n0\n0\n12\n", mod, name, suffix);
844 putpoint(shp, fp, a);
845 putpoint(shp, fp, b);
846 putpoint(shp, fp, c);
847 putpoint(shp, fp, d);
848 }
849
850
851 putpoint(shp, fp, p) /* put out a point */
852 register SRCINFO *shp;
853 FILE *fp;
854 int p;
855 {
856 static double mult[2] = {-.5, .5};
857
858 fprintf(fp, "\t%g\t%g\t%g\n",
859 mult[p&1]*shp->l*meters2out,
860 mult[p>>1&1]*shp->w*meters2out,
861 mult[p>>2]*shp->h*meters2out);
862 }
863
864
865 putdisksrc(shp, fp, mod, name, up) /* put out a disk source */
866 register SRCINFO *shp;
867 FILE *fp;
868 char *mod, *name;
869 int up;
870 {
871 if (up) {
872 fprintf(fp, "\n%s ring %s.u\n", mod, name);
873 fprintf(fp, "0\n0\n8\n");
874 fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
875 fprintf(fp, "\t0 0 1\n");
876 fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
877 } else {
878 fprintf(fp, "\n%s ring %s.d\n", mod, name);
879 fprintf(fp, "0\n0\n8\n");
880 fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
881 fprintf(fp, "\t0 0 -1\n");
882 fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
883 }
884 }
885
886
887 putcyl(shp, fp, mod, name) /* put out a cylinder */
888 register SRCINFO *shp;
889 FILE *fp;
890 char *mod, *name;
891 {
892 fprintf(fp, "\n%s cylinder %s.c\n", mod, name);
893 fprintf(fp, "0\n0\n7\n");
894 fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
895 fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
896 fprintf(fp, "\t%g\n", .5*shp->w*meters2out);
897 }
898
899
900 putspheresrc(shp, fp, mod, name) /* put out a sphere source */
901 SRCINFO *shp;
902 FILE *fp;
903 char *mod, *name;
904 {
905 fprintf(fp, "\n%s sphere %s.s\n", mod, name);
906 fprintf(fp, "0\n0\n4 0 0 0 %g\n", .5*shp->w*meters2out);
907 }
908
909
910 cvdata(in, out, ndim, npts, mult, lim) /* convert data */
911 FILE *in, *out;
912 int ndim, npts[];
913 double mult, lim[][2];
914 {
915 double *pt[4];
916 register int i, j;
917 double val;
918 int total;
919
920 total = 1; j = 0;
921 for (i = 0; i < ndim; i++)
922 if (npts[i] > 1) {
923 total *= npts[i];
924 j++;
925 }
926 fprintf(out, "%d\n", j);
927 /* get coordinates */
928 for (i = 0; i < ndim; i++) {
929 pt[i] = (double *)malloc(npts[i]*sizeof(double));
930 for (j = 0; j < npts[i]; j++)
931 if (!scnflt(in, &pt[i][j]))
932 return(-1);
933 if (lim != NULL) {
934 lim[i][0] = pt[i][0];
935 lim[i][1] = pt[i][npts[i]-1];
936 }
937 }
938 /* write out in reverse */
939 for (i = ndim-1; i >= 0; i--) {
940 if (npts[i] > 1) {
941 for (j = 1; j < npts[i]-1; j++)
942 if (!FEQ(pt[i][j]-pt[i][j-1],
943 pt[i][j+1]-pt[i][j]))
944 break;
945 if (j == npts[i]-1)
946 fprintf(out, "%g %g %d\n", pt[i][0], pt[i][j],
947 npts[i]);
948 else {
949 fprintf(out, "0 0 %d", npts[i]);
950 for (j = 0; j < npts[i]; j++) {
951 if (j%4 == 0)
952 putc('\n', out);
953 fprintf(out, "\t%g", pt[i][j]);
954 }
955 putc('\n', out);
956 }
957 }
958 free((void *)pt[i]);
959 }
960 for (i = 0; i < total; i++) {
961 if (i%4 == 0)
962 putc('\n', out);
963 if (!scnflt(in, &val))
964 return(-1);
965 fprintf(out, "\t%g", val*mult);
966 }
967 putc('\n', out);
968 return(0);
969 }
970
971
972 char *
973 getword(fp) /* scan a word from fp */
974 register FILE *fp;
975 {
976 static char wrd[MAXWORD];
977 register char *cp;
978 register int c;
979
980 while (isspace(c=getc(fp)))
981 ;
982 for (cp = wrd; c != EOF && cp < wrd+MAXWORD-1;
983 *cp++ = c, c = getc(fp))
984 if (isspace(c) || c == ',') {
985 while (isspace(c))
986 c = getc(fp);
987 if (c != EOF & c != ',')
988 ungetc(c, fp);
989 *cp = '\0';
990 return(wrd);
991 }
992 *cp = '\0';
993 return(cp > wrd ? wrd : NULL);
994 }
995
996
997 cvtint(ip, wrd) /* convert a word to an integer */
998 int *ip;
999 char *wrd;
1000 {
1001 if (wrd == NULL || !isint(wrd))
1002 return(0);
1003 *ip = atoi(wrd);
1004 return(1);
1005 }
1006
1007
1008 cvtflt(rp, wrd) /* convert a word to a double */
1009 double *rp;
1010 char *wrd;
1011 {
1012 if (wrd == NULL || !isflt(wrd))
1013 return(0);
1014 *rp = atof(wrd);
1015 return(1);
1016 }
1017
1018
1019 cvgeometry(inpname, sinf, outname, outfp)
1020 char *inpname;
1021 register SRCINFO *sinf;
1022 char *outname;
1023 FILE *outfp; /* close output file upon return */
1024 {
1025 char buf[256];
1026 register char *cp;
1027
1028 if (inpname == NULL || !inpname[0]) { /* no geometry file */
1029 fclose(outfp);
1030 return(0);
1031 }
1032 putc('\n', outfp);
1033 strcpy(buf, "mgf2rad "); /* build mgf2rad command */
1034 cp = buf+8;
1035 if (!FEQ(sinf->mult, 1.0)) {
1036 sprintf(cp, "-m %f ", sinf->mult);
1037 cp += strlen(cp);
1038 }
1039 sprintf(cp, "-g %f %s ",
1040 sqrt(sinf->w*sinf->w + sinf->h*sinf->h + sinf->l*sinf->l),
1041 inpname);
1042 cp += strlen(cp);
1043 if (instantiate) { /* instantiate octree */
1044 strcpy(cp, "| oconv - > ");
1045 cp += 12;
1046 fullnam(cp,outname,T_OCT);
1047 if (fdate(inpname) > fdate(outname) &&
1048 system(buf)) { /* create octree */
1049 fclose(outfp);
1050 return(-1);
1051 }
1052 fprintf(outfp, "void instance %s_inst\n", outname);
1053 if (!FEQ(meters2out, 1.0))
1054 fprintf(outfp, "3 %s -s %f\n",
1055 libname(buf,outname,T_OCT),
1056 meters2out);
1057 else
1058 fprintf(outfp, "1 %s\n", libname(buf,outname,T_OCT));
1059 fprintf(outfp, "0\n0\n");
1060 fclose(outfp);
1061 } else { /* else append to luminaire file */
1062 if (!FEQ(meters2out, 1.0)) { /* apply scalefactor */
1063 sprintf(cp, "| xform -s %f ", meters2out);
1064 cp += strlen(cp);
1065 }
1066 if (!out2stdout) {
1067 fclose(outfp);
1068 strcpy(cp, ">> "); /* append works for DOS? */
1069 cp += 3;
1070 fullnam(cp,outname,T_RAD);
1071 }
1072 if (system(buf))
1073 return(-1);
1074 }
1075 return(0);
1076 }