ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.14
Committed: Tue Jun 18 21:28:52 1996 UTC (27 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.13: +4 -1 lines
Log Message:
added check to avoid rerunning oconv unnecessarily

File Contents

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