ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.15
Committed: Fri Jul 25 11:18:18 1997 UTC (26 years, 9 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.14: +5 -6 lines
Log Message:
eliminated output of sides when they're not wanted

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 int dosides = 0;
718 char buf[MAXWORD];
719
720 fprintf(fp, "\n%s %s %s_light\n", mod,
721 shp->isillum ? "illum" : "light",
722 name);
723 fprintf(fp, "0\n0\n3 %g %g %g\n",
724 lampcolor[0]/shp->area,
725 lampcolor[1]/shp->area,
726 lampcolor[2]/shp->area);
727 if (doupper && dolower && shp->type != SPHERE && shp->h > MINDIM)
728 if (!shp->isillum) {
729 fprintf(fp, "\n%s glow %s_glow\n", mod, name);
730 fprintf(fp, "0\n0\n4 %g %g %g -1\n",
731 lampcolor[0]/shp->area,
732 lampcolor[1]/shp->area,
733 lampcolor[2]/shp->area);
734 dosides++;
735 }
736 switch (shp->type) {
737 case RECT:
738 strcat(strcpy(buf, name), "_light");
739 if (dolower)
740 putrectsrc(shp, fp, buf, name, 0);
741 if (doupper)
742 putrectsrc(shp, fp, buf, name, 1);
743 if (dosides) {
744 strcat(strcpy(buf, name), "_glow");
745 putsides(shp, fp, buf, name);
746 }
747 break;
748 case DISK:
749 strcat(strcpy(buf, name), "_light");
750 if (dolower)
751 putdisksrc(shp, fp, buf, name, 0);
752 if (doupper)
753 putdisksrc(shp, fp, buf, name, 1);
754 if (dosides) {
755 strcat(strcpy(buf, name), "_glow");
756 putcyl(shp, fp, buf, name);
757 }
758 break;
759 case SPHERE:
760 strcat(strcpy(buf, name), "_light");
761 putspheresrc(shp, fp, buf, name);
762 break;
763 }
764 return(0);
765 }
766
767
768 makeshape(shp, width, length, height) /* make source shape */
769 register SRCINFO *shp;
770 double width, length, height;
771 {
772 if (illumrad/meters2out >= MINDIM/2.) {
773 shp->isillum = 1;
774 shp->type = SPHERE;
775 shp->w = shp->l = shp->h = 2.*illumrad / meters2out;
776 } else if (width < MINDIM) {
777 width = -width;
778 if (width < MINDIM) {
779 shp->type = SPHERE;
780 shp->w = shp->l = shp->h = MINDIM;
781 } else if (height < .5*width) {
782 shp->type = DISK;
783 shp->w = shp->l = width;
784 if (height >= MINDIM)
785 shp->h = height;
786 else
787 shp->h = .5*MINDIM;
788 } else {
789 shp->type = SPHERE;
790 shp->w = shp->l = shp->h = width;
791 }
792 } else {
793 shp->type = RECT;
794 shp->w = width;
795 if (length >= MINDIM)
796 shp->l = length;
797 else
798 shp->l = MINDIM;
799 if (height >= MINDIM)
800 shp->h = height;
801 else
802 shp->h = .5*MINDIM;
803 }
804 switch (shp->type) {
805 case RECT:
806 shp->area = shp->w * shp->l;
807 break;
808 case DISK:
809 case SPHERE:
810 shp->area = PI/4. * shp->w * shp->w;
811 break;
812 }
813 return(0);
814 }
815
816
817 putrectsrc(shp, fp, mod, name, up) /* rectangular source */
818 SRCINFO *shp;
819 FILE *fp;
820 char *mod, *name;
821 int up;
822 {
823 if (up)
824 putrect(shp, fp, mod, name, ".u", 4, 5, 7, 6);
825 else
826 putrect(shp, fp, mod, name, ".d", 0, 2, 3, 1);
827 }
828
829
830 putsides(shp, fp, mod, name) /* put out sides of box */
831 register SRCINFO *shp;
832 FILE *fp;
833 char *mod, *name;
834 {
835 putrect(shp, fp, mod, name, ".1", 0, 1, 5, 4);
836 putrect(shp, fp, mod, name, ".2", 1, 3, 7, 5);
837 putrect(shp, fp, mod, name, ".3", 3, 2, 6, 7);
838 putrect(shp, fp, mod, name, ".4", 2, 0, 4, 6);
839 }
840
841
842 putrect(shp, fp, mod, name, suffix, a, b, c, d) /* put out a rectangle */
843 SRCINFO *shp;
844 FILE *fp;
845 char *mod, *name, *suffix;
846 int a, b, c, d;
847 {
848 fprintf(fp, "\n%s polygon %s%s\n0\n0\n12\n", mod, name, suffix);
849 putpoint(shp, fp, a);
850 putpoint(shp, fp, b);
851 putpoint(shp, fp, c);
852 putpoint(shp, fp, d);
853 }
854
855
856 putpoint(shp, fp, p) /* put out a point */
857 register SRCINFO *shp;
858 FILE *fp;
859 int p;
860 {
861 static double mult[2] = {-.5, .5};
862
863 fprintf(fp, "\t%g\t%g\t%g\n",
864 mult[p&1]*shp->l*meters2out,
865 mult[p>>1&1]*shp->w*meters2out,
866 mult[p>>2]*shp->h*meters2out);
867 }
868
869
870 putdisksrc(shp, fp, mod, name, up) /* put out a disk source */
871 register SRCINFO *shp;
872 FILE *fp;
873 char *mod, *name;
874 int up;
875 {
876 if (up) {
877 fprintf(fp, "\n%s ring %s.u\n", mod, name);
878 fprintf(fp, "0\n0\n8\n");
879 fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
880 fprintf(fp, "\t0 0 1\n");
881 fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
882 } else {
883 fprintf(fp, "\n%s ring %s.d\n", mod, name);
884 fprintf(fp, "0\n0\n8\n");
885 fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
886 fprintf(fp, "\t0 0 -1\n");
887 fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
888 }
889 }
890
891
892 putcyl(shp, fp, mod, name) /* put out a cylinder */
893 register SRCINFO *shp;
894 FILE *fp;
895 char *mod, *name;
896 {
897 fprintf(fp, "\n%s cylinder %s.c\n", mod, name);
898 fprintf(fp, "0\n0\n7\n");
899 fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
900 fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
901 fprintf(fp, "\t%g\n", .5*shp->w*meters2out);
902 }
903
904
905 putspheresrc(shp, fp, mod, name) /* put out a sphere source */
906 SRCINFO *shp;
907 FILE *fp;
908 char *mod, *name;
909 {
910 fprintf(fp, "\n%s sphere %s.s\n", mod, name);
911 fprintf(fp, "0\n0\n4 0 0 0 %g\n", .5*shp->w*meters2out);
912 }
913
914
915 cvdata(in, out, ndim, npts, mult, lim) /* convert data */
916 FILE *in, *out;
917 int ndim, npts[];
918 double mult, lim[][2];
919 {
920 double *pt[4];
921 register int i, j;
922 double val;
923 int total;
924
925 total = 1; j = 0;
926 for (i = 0; i < ndim; i++)
927 if (npts[i] > 1) {
928 total *= npts[i];
929 j++;
930 }
931 fprintf(out, "%d\n", j);
932 /* get coordinates */
933 for (i = 0; i < ndim; i++) {
934 pt[i] = (double *)malloc(npts[i]*sizeof(double));
935 for (j = 0; j < npts[i]; j++)
936 if (!scnflt(in, &pt[i][j]))
937 return(-1);
938 if (lim != NULL) {
939 lim[i][0] = pt[i][0];
940 lim[i][1] = pt[i][npts[i]-1];
941 }
942 }
943 /* write out in reverse */
944 for (i = ndim-1; i >= 0; i--) {
945 if (npts[i] > 1) {
946 for (j = 1; j < npts[i]-1; j++)
947 if (!FEQ(pt[i][j]-pt[i][j-1],
948 pt[i][j+1]-pt[i][j]))
949 break;
950 if (j == npts[i]-1)
951 fprintf(out, "%g %g %d\n", pt[i][0], pt[i][j],
952 npts[i]);
953 else {
954 fprintf(out, "0 0 %d", npts[i]);
955 for (j = 0; j < npts[i]; j++) {
956 if (j%4 == 0)
957 putc('\n', out);
958 fprintf(out, "\t%g", pt[i][j]);
959 }
960 putc('\n', out);
961 }
962 }
963 free((char *)pt[i]);
964 }
965 for (i = 0; i < total; i++) {
966 if (i%4 == 0)
967 putc('\n', out);
968 if (!scnflt(in, &val))
969 return(-1);
970 fprintf(out, "\t%g", val*mult);
971 }
972 putc('\n', out);
973 return(0);
974 }
975
976
977 char *
978 getword(fp) /* scan a word from fp */
979 register FILE *fp;
980 {
981 static char word[MAXWORD];
982 register char *cp;
983 register int c;
984
985 while (isspace(c=getc(fp)))
986 ;
987 for (cp = word; c != EOF && cp < word+MAXWORD-1;
988 *cp++ = c, c = getc(fp))
989 if (isspace(c) || c == ',') {
990 while (isspace(c))
991 c = getc(fp);
992 if (c != EOF & c != ',')
993 ungetc(c, fp);
994 *cp = '\0';
995 return(word);
996 }
997 *cp = '\0';
998 return(cp > word ? word : NULL);
999 }
1000
1001
1002 cvtint(ip, word) /* convert a word to an integer */
1003 int *ip;
1004 char *word;
1005 {
1006 if (word == NULL || !isint(word))
1007 return(0);
1008 *ip = atoi(word);
1009 return(1);
1010 }
1011
1012
1013 cvtflt(rp, word) /* convert a word to a double */
1014 double *rp;
1015 char *word;
1016 {
1017 if (word == NULL || !isflt(word))
1018 return(0);
1019 *rp = atof(word);
1020 return(1);
1021 }
1022
1023
1024 cvgeometry(inpname, sinf, outname, outfp)
1025 char *inpname;
1026 register SRCINFO *sinf;
1027 char *outname;
1028 FILE *outfp; /* close output file upon return */
1029 {
1030 char buf[256];
1031 register char *cp;
1032
1033 if (inpname == NULL || !inpname[0]) { /* no geometry file */
1034 fclose(outfp);
1035 return(0);
1036 }
1037 putc('\n', outfp);
1038 strcpy(buf, "mgf2rad "); /* build mgf2rad command */
1039 cp = buf+8;
1040 if (!FEQ(sinf->mult, 1.0)) {
1041 sprintf(cp, "-m %f ", sinf->mult);
1042 cp += strlen(cp);
1043 }
1044 sprintf(cp, "-g %f %s ",
1045 sqrt(sinf->w*sinf->w + sinf->h*sinf->h + sinf->l*sinf->l),
1046 inpname);
1047 cp += strlen(cp);
1048 if (instantiate) { /* instantiate octree */
1049 strcpy(cp, "| oconv - > ");
1050 cp += 12;
1051 fullname(cp,outname,T_OCT);
1052 if (fdate(inpname) > fdate(outname) &&
1053 system(buf)) { /* create octree */
1054 fclose(outfp);
1055 return(-1);
1056 }
1057 fprintf(outfp, "void instance %s_inst\n", outname);
1058 if (!FEQ(meters2out, 1.0))
1059 fprintf(outfp, "3 %s -s %f\n",
1060 libname(buf,outname,T_OCT),
1061 meters2out);
1062 else
1063 fprintf(outfp, "1 %s\n", libname(buf,outname,T_OCT));
1064 fprintf(outfp, "0\n0\n");
1065 fclose(outfp);
1066 } else { /* else append to luminaire file */
1067 if (!FEQ(meters2out, 1.0)) { /* apply scalefactor */
1068 sprintf(cp, "| xform -s %f ", meters2out);
1069 cp += strlen(cp);
1070 }
1071 if (!out2stdout) {
1072 fclose(outfp);
1073 strcpy(cp, ">> "); /* append works for DOS? */
1074 cp += 3;
1075 fullname(cp,outname,T_RAD);
1076 }
1077 if (system(buf))
1078 return(-1);
1079 }
1080 return(0);
1081 }