ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.16
Committed: Fri Jul 25 12:08:06 1997 UTC (26 years, 8 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.15: +25 -35 lines
Log Message:
eliminated use of "glow" type and applied boxcorr and new cylcorr

File Contents

# User Rev Content
1 greg 2.13 /* Copyright (c) 1996 Regents of the University of California */
2 greg 1.1
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 greg 2.8 #include <math.h>
15 greg 2.14 #include <sys/types.h>
16 greg 1.1 #include <ctype.h>
17 greg 1.2 #include "color.h"
18 greg 2.4 #include "paths.h"
19 greg 1.1
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 greg 2.12 /* 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 greg 1.1 /* 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 greg 2.10 #define T_TLT "%.dat"
87 greg 2.12 #define T_OCT ".oct"
88 greg 1.1 /* 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 greg 2.4 #define abspath(p) (ISDIRSEP((p)[0]) || (p)[0] == '.')
98 greg 1.1
99 greg 1.2 static char default_name[] = "default";
100    
101 greg 1.1 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 greg 1.2 char *deflamp = NULL; /* default lamp type */
108 greg 1.1 float defcolor[3] = {1.,1.,1.}; /* default lamp color */
109 greg 1.2 float *lampcolor = defcolor; /* pointer to current lamp color */
110 greg 1.1 double multiplier = 1.0; /* multiplier for all light sources */
111     char units[64] = "meters"; /* output units */
112 greg 2.13 int out2stdout = 0; /* put out to stdout r.t. file */
113 greg 2.12 int instantiate = 0; /* instantiate geometry */
114 greg 1.1 double illumrad = 0.0; /* radius for illum sphere */
115    
116     typedef struct {
117 greg 2.12 int isillum; /* do as illum */
118 greg 1.1 int type; /* RECT, DISK, SPHERE */
119 greg 2.12 double mult; /* candela multiplier */
120 greg 1.1 double w, l, h; /* width, length, height */
121 greg 1.3 double area; /* max. projected area */
122 greg 2.12 } SRCINFO; /* a source shape (units=meters) */
123 greg 1.1
124     int gargc; /* global argc (minus filenames) */
125     char **gargv; /* global argv */
126    
127     extern char *strcpy(), *strcat(), *stradd(), *tailtrunc(), *filetrunc(),
128 greg 2.6 *filename(), *libname(), *fullname(), *malloc(),
129     *getword(), *atos();
130 greg 1.1 extern float *matchlamp();
131 greg 2.14 extern time_t fdate();
132 greg 1.1
133 greg 2.6 #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 greg 1.1
137 greg 2.6
138 greg 1.1 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 greg 2.13 case 'o': /* output file root name */
210 greg 1.1 outfile = argv[++i];
211     break;
212 greg 2.13 case 's': /* output to stdout */
213     out2stdout = !out2stdout;
214     break;
215 greg 1.1 case 'i': /* illum */
216     illumrad = atof(argv[++i]);
217     break;
218 greg 2.12 case 'g': /* instatiate geometry? */
219     instantiate = !instantiate;
220     break;
221 greg 1.2 case 't': /* override lamp type */
222 greg 1.1 lamptype = argv[++i];
223     break;
224 greg 1.2 case 'u': /* default lamp type */
225     deflamp = argv[++i];
226     break;
227 greg 1.1 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 greg 1.2 initlamps(); /* get lamp data (if needed) */
244 greg 1.1 /* 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 greg 2.13 else
251     goto needsingle;
252 greg 1.1 } else if (i >= argc) {
253     fprintf(stderr, "%s: missing output file specification\n",
254     argv[0]);
255     exit(1);
256     }
257 greg 2.13 if (out2stdout && i != argc-1)
258     goto needsingle;
259 greg 1.1 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 greg 2.13 needsingle:
267     fprintf(stderr, "%s: single input file required\n", argv[0]);
268     exit(1);
269 greg 1.2 }
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 greg 1.1 }
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 greg 2.4 libname(stradd(path, libdir, DIRSEP), fname, suffix);
339 greg 1.1
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 greg 2.4 strcpy(stradd(stradd(path, prefdir, DIRSEP), fname, 0), suffix);
352 greg 1.1
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 greg 2.4 if (ISDIRSEP(*path))
365 greg 1.1 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 greg 2.4 if (ISDIRSEP(*p2))
378 greg 1.1 p1 = p2;
379 greg 2.12 if (p1 == path && ISDIRSEP(*p1))
380     p1++;
381 greg 1.1 *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 greg 2.12 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 greg 1.1 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 greg 2.12 SRCINFO srcinfo;
461 greg 1.1 char buf[MAXLINE], tltid[MAXWORD];
462 greg 2.12 char geomfile[128];
463 greg 1.1 FILE *inpfp, *outfp;
464 greg 2.12 int lineno = 0;
465 greg 1.1
466 greg 2.12 geomfile[0] = '\0';
467     srcinfo.isillum = 0;
468 greg 1.1 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 greg 2.13 if (out2stdout)
476     outfp = stdout;
477     else if ((outfp = fopen(fullname(buf,outname,T_RAD), "w")) == NULL) {
478 greg 1.1 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 greg 2.12 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 greg 1.1 fputs("#<", outfp);
498     fputs(buf, outfp);
499     putc('\n', outfp);
500 greg 2.12 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 greg 1.1 }
509     if (lampcolor == NULL) {
510     fprintf(stderr, "%s: warning - no lamp type\n", inpname);
511 greg 2.9 fputs("# Unknown lamp type (used default)\n", outfp);
512 greg 1.1 lampcolor = defcolor;
513 greg 2.9 } 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 greg 1.1 if (feof(inpfp)) {
517     fprintf(stderr, "%s: not in IES format\n", inpname);
518     goto readerr;
519     }
520 greg 2.6 atos(tltid, MAXWORD, buf+TLTSTRLEN);
521 greg 1.1 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 greg 2.12 if (dosource(&srcinfo, inpfp, outfp, tltid, outname) != 0) {
530 greg 1.1 fprintf(stderr, "%s: bad luminaire data\n", inpname);
531     goto readerr;
532     }
533     fclose(inpfp);
534 greg 2.12 /* 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 greg 1.1 return(0);
540     readerr:
541 greg 2.12 fclose(inpfp);
542 greg 1.1 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 greg 2.4 if (ISDIRSEP(tltspec[0]))
565 greg 1.1 strcpy(buf, tltspec);
566     else
567 greg 2.4 strcpy(stradd(buf, dir, DIRSEP), tltspec);
568 greg 1.1 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 greg 2.6 if (!scnint(datin,&tlt_type) || !scnint(datin,&nangles)
582 greg 1.1 || 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 greg 2.12 dosource(sinf, in, out, mod, name) /* create source and distribution */
622     SRCINFO *sinf;
623 greg 1.1 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 greg 2.6 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 greg 1.1 fprintf(stderr, "dosource: bad lamp specification\n");
640     return(-1);
641     }
642 greg 2.12 sinf->mult = multiplier*mult*bfactor*pfactor;
643 greg 1.1 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 greg 2.12 if (makeshape(sinf, width, length, height) != 0) {
653 greg 1.1 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 greg 1.5 if (cvdata(in, datout, 2, nangles, 1./WHTEFFICACY, bounds) != 0) {
661 greg 1.1 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 greg 2.7 fprintf(out, "7 ");
677 greg 1.1 else
678 greg 2.7 fprintf(out, "5 ");
679 greg 1.1 fprintf(out, "%s %s source.cal ",
680 gregl 2.16 sinf->type==SPHERE ? "corr" :
681     sinf->type==DISK ? "cylcorr" : "boxcorr",
682 greg 1.1 libname(buf,name,T_DST));
683     if (pmtype == PM_B) {
684     if (FEQ(bounds[1][0],0.))
685     fprintf(out, "srcB_horiz2 ");
686     else
687     fprintf(out, "srcB_horiz ");
688     fprintf(out, "srcB_vert ");
689     } else {
690     if (nangles[1] >= 2) {
691     d1 = bounds[1][1] - bounds[1][0];
692     if (d1 <= 90.+FTINY)
693     fprintf(out, "src_phi4 ");
694     else if (d1 <= 180.+FTINY)
695     fprintf(out, "src_phi2 ");
696     else
697     fprintf(out, "src_phi ");
698 greg 2.7 fprintf(out, "src_theta ");
699 greg 1.1 if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.))
700     fprintf(out, "-rz -90 ");
701     } else
702     fprintf(out, "src_theta ");
703     }
704 gregl 2.16 if (sinf->type == SPHERE)
705     fprintf(out, "\n0\n1 %g\n", sinf->mult/sinf->area);
706     else if (sinf->type == DISK)
707     fprintf(out, "\n0\n3 %g %g %g\n", sinf->mult,
708     sinf->l, sinf->h);
709     else
710     fprintf(out, "\n0\n4 %g %g %g %g\n", sinf->mult,
711     sinf->l, sinf->w, sinf->h);
712 greg 2.12 if (putsource(sinf, out, id, filename(name),
713 greg 1.1 bounds[0][0]<90., bounds[0][1]>90.) != 0)
714     return(-1);
715     return(0);
716     }
717    
718    
719     putsource(shp, fp, mod, name, dolower, doupper) /* put out source */
720 greg 2.12 SRCINFO *shp;
721 greg 1.1 FILE *fp;
722     char *mod, *name;
723     int dolower, doupper;
724     {
725 gregl 2.16 int dosides = doupper && dolower && shp->h > MINDIM;
726     char lname[MAXWORD];
727 greg 1.1
728 gregl 2.16 strcat(strcpy(lname, name), "_light");
729     fprintf(fp, "\n%s %s %s\n", mod,
730     shp->isillum ? "illum" : "light", lname);
731 greg 1.1 fprintf(fp, "0\n0\n3 %g %g %g\n",
732 gregl 2.16 lampcolor[0], lampcolor[1], lampcolor[2]);
733 greg 1.1 switch (shp->type) {
734     case RECT:
735     if (dolower)
736 gregl 2.16 putrectsrc(shp, fp, lname, name, 0);
737 greg 1.1 if (doupper)
738 gregl 2.16 putrectsrc(shp, fp, lname, name, 1);
739     if (dosides)
740     putsides(shp, fp, lname, name);
741 greg 1.1 break;
742     case DISK:
743     if (dolower)
744 gregl 2.16 putdisksrc(shp, fp, lname, name, 0);
745 greg 1.1 if (doupper)
746 gregl 2.16 putdisksrc(shp, fp, lname, name, 1);
747     if (dosides)
748     putcyl(shp, fp, lname, name);
749 greg 1.1 break;
750     case SPHERE:
751 gregl 2.16 putspheresrc(shp, fp, lname, name);
752 greg 1.1 break;
753     }
754     return(0);
755     }
756    
757    
758     makeshape(shp, width, length, height) /* make source shape */
759 greg 2.12 register SRCINFO *shp;
760 greg 1.1 double width, length, height;
761     {
762 greg 2.11 if (illumrad/meters2out >= MINDIM/2.) {
763 greg 2.12 shp->isillum = 1;
764 greg 1.1 shp->type = SPHERE;
765 greg 2.11 shp->w = shp->l = shp->h = 2.*illumrad / meters2out;
766 greg 1.1 } else if (width < MINDIM) {
767     width = -width;
768     if (width < MINDIM) {
769     shp->type = SPHERE;
770     shp->w = shp->l = shp->h = MINDIM;
771     } else if (height < .5*width) {
772     shp->type = DISK;
773     shp->w = shp->l = width;
774     if (height >= MINDIM)
775     shp->h = height;
776     else
777     shp->h = .5*MINDIM;
778     } else {
779     shp->type = SPHERE;
780     shp->w = shp->l = shp->h = width;
781     }
782     } else {
783     shp->type = RECT;
784     shp->w = width;
785     if (length >= MINDIM)
786     shp->l = length;
787     else
788     shp->l = MINDIM;
789     if (height >= MINDIM)
790     shp->h = height;
791     else
792     shp->h = .5*MINDIM;
793     }
794     switch (shp->type) {
795     case RECT:
796     shp->area = shp->w * shp->l;
797     break;
798     case DISK:
799 greg 1.3 case SPHERE:
800 greg 1.1 shp->area = PI/4. * shp->w * shp->w;
801     break;
802     }
803     return(0);
804     }
805    
806    
807     putrectsrc(shp, fp, mod, name, up) /* rectangular source */
808 greg 2.12 SRCINFO *shp;
809 greg 1.1 FILE *fp;
810     char *mod, *name;
811     int up;
812     {
813     if (up)
814     putrect(shp, fp, mod, name, ".u", 4, 5, 7, 6);
815     else
816     putrect(shp, fp, mod, name, ".d", 0, 2, 3, 1);
817     }
818    
819    
820     putsides(shp, fp, mod, name) /* put out sides of box */
821 greg 2.12 register SRCINFO *shp;
822 greg 1.1 FILE *fp;
823     char *mod, *name;
824     {
825     putrect(shp, fp, mod, name, ".1", 0, 1, 5, 4);
826     putrect(shp, fp, mod, name, ".2", 1, 3, 7, 5);
827     putrect(shp, fp, mod, name, ".3", 3, 2, 6, 7);
828     putrect(shp, fp, mod, name, ".4", 2, 0, 4, 6);
829     }
830    
831    
832     putrect(shp, fp, mod, name, suffix, a, b, c, d) /* put out a rectangle */
833 greg 2.12 SRCINFO *shp;
834 greg 1.1 FILE *fp;
835     char *mod, *name, *suffix;
836     int a, b, c, d;
837     {
838     fprintf(fp, "\n%s polygon %s%s\n0\n0\n12\n", mod, name, suffix);
839     putpoint(shp, fp, a);
840     putpoint(shp, fp, b);
841     putpoint(shp, fp, c);
842     putpoint(shp, fp, d);
843     }
844    
845    
846     putpoint(shp, fp, p) /* put out a point */
847 greg 2.12 register SRCINFO *shp;
848 greg 1.1 FILE *fp;
849     int p;
850     {
851     static double mult[2] = {-.5, .5};
852    
853     fprintf(fp, "\t%g\t%g\t%g\n",
854     mult[p&1]*shp->l*meters2out,
855     mult[p>>1&1]*shp->w*meters2out,
856     mult[p>>2]*shp->h*meters2out);
857     }
858    
859    
860     putdisksrc(shp, fp, mod, name, up) /* put out a disk source */
861 greg 2.12 register SRCINFO *shp;
862 greg 1.1 FILE *fp;
863     char *mod, *name;
864     int up;
865     {
866     if (up) {
867     fprintf(fp, "\n%s ring %s.u\n", mod, name);
868     fprintf(fp, "0\n0\n8\n");
869     fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
870     fprintf(fp, "\t0 0 1\n");
871     fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
872     } else {
873     fprintf(fp, "\n%s ring %s.d\n", mod, name);
874     fprintf(fp, "0\n0\n8\n");
875     fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
876     fprintf(fp, "\t0 0 -1\n");
877     fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
878     }
879     }
880    
881    
882     putcyl(shp, fp, mod, name) /* put out a cylinder */
883 greg 2.12 register SRCINFO *shp;
884 greg 1.1 FILE *fp;
885     char *mod, *name;
886     {
887     fprintf(fp, "\n%s cylinder %s.c\n", mod, name);
888     fprintf(fp, "0\n0\n7\n");
889     fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
890     fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
891     fprintf(fp, "\t%g\n", .5*shp->w*meters2out);
892     }
893    
894    
895     putspheresrc(shp, fp, mod, name) /* put out a sphere source */
896 greg 2.12 SRCINFO *shp;
897 greg 1.1 FILE *fp;
898     char *mod, *name;
899     {
900     fprintf(fp, "\n%s sphere %s.s\n", mod, name);
901     fprintf(fp, "0\n0\n4 0 0 0 %g\n", .5*shp->w*meters2out);
902     }
903    
904    
905     cvdata(in, out, ndim, npts, mult, lim) /* convert data */
906     FILE *in, *out;
907     int ndim, npts[];
908     double mult, lim[][2];
909     {
910 greg 2.3 double *pt[4];
911 greg 1.1 register int i, j;
912     double val;
913     int total;
914    
915     total = 1; j = 0;
916     for (i = 0; i < ndim; i++)
917     if (npts[i] > 1) {
918     total *= npts[i];
919     j++;
920     }
921     fprintf(out, "%d\n", j);
922     /* get coordinates */
923     for (i = 0; i < ndim; i++) {
924     pt[i] = (double *)malloc(npts[i]*sizeof(double));
925     for (j = 0; j < npts[i]; j++)
926 greg 2.6 if (!scnflt(in, &pt[i][j]))
927     return(-1);
928 greg 1.1 if (lim != NULL) {
929     lim[i][0] = pt[i][0];
930     lim[i][1] = pt[i][npts[i]-1];
931     }
932     }
933     /* write out in reverse */
934     for (i = ndim-1; i >= 0; i--) {
935     if (npts[i] > 1) {
936     for (j = 1; j < npts[i]-1; j++)
937     if (!FEQ(pt[i][j]-pt[i][j-1],
938     pt[i][j+1]-pt[i][j]))
939     break;
940     if (j == npts[i]-1)
941     fprintf(out, "%g %g %d\n", pt[i][0], pt[i][j],
942     npts[i]);
943     else {
944     fprintf(out, "0 0 %d", npts[i]);
945     for (j = 0; j < npts[i]; j++) {
946     if (j%4 == 0)
947     putc('\n', out);
948     fprintf(out, "\t%g", pt[i][j]);
949     }
950     putc('\n', out);
951     }
952     }
953     free((char *)pt[i]);
954     }
955     for (i = 0; i < total; i++) {
956     if (i%4 == 0)
957     putc('\n', out);
958 greg 2.6 if (!scnflt(in, &val))
959 greg 1.1 return(-1);
960     fprintf(out, "\t%g", val*mult);
961     }
962     putc('\n', out);
963     return(0);
964 greg 2.6 }
965    
966    
967     char *
968     getword(fp) /* scan a word from fp */
969     register FILE *fp;
970     {
971     static char word[MAXWORD];
972     register char *cp;
973     register int c;
974    
975     while (isspace(c=getc(fp)))
976     ;
977     for (cp = word; c != EOF && cp < word+MAXWORD-1;
978     *cp++ = c, c = getc(fp))
979     if (isspace(c) || c == ',') {
980     while (isspace(c))
981     c = getc(fp);
982     if (c != EOF & c != ',')
983     ungetc(c, fp);
984     *cp = '\0';
985     return(word);
986     }
987     *cp = '\0';
988     return(cp > word ? word : NULL);
989     }
990    
991    
992     cvtint(ip, word) /* convert a word to an integer */
993     int *ip;
994     char *word;
995     {
996     if (word == NULL || !isint(word))
997     return(0);
998     *ip = atoi(word);
999     return(1);
1000     }
1001    
1002    
1003     cvtflt(rp, word) /* convert a word to a double */
1004     double *rp;
1005     char *word;
1006     {
1007     if (word == NULL || !isflt(word))
1008     return(0);
1009     *rp = atof(word);
1010     return(1);
1011 greg 2.12 }
1012    
1013    
1014     cvgeometry(inpname, sinf, outname, outfp)
1015     char *inpname;
1016     register SRCINFO *sinf;
1017     char *outname;
1018     FILE *outfp; /* close output file upon return */
1019     {
1020     char buf[256];
1021     register char *cp;
1022    
1023     if (inpname == NULL || !inpname[0]) { /* no geometry file */
1024     fclose(outfp);
1025     return(0);
1026     }
1027     putc('\n', outfp);
1028     strcpy(buf, "mgf2rad "); /* build mgf2rad command */
1029     cp = buf+8;
1030     if (!FEQ(sinf->mult, 1.0)) {
1031     sprintf(cp, "-m %f ", sinf->mult);
1032     cp += strlen(cp);
1033     }
1034     sprintf(cp, "-g %f %s ",
1035     sqrt(sinf->w*sinf->w + sinf->h*sinf->h + sinf->l*sinf->l),
1036     inpname);
1037     cp += strlen(cp);
1038     if (instantiate) { /* instantiate octree */
1039     strcpy(cp, "| oconv - > ");
1040     cp += 12;
1041     fullname(cp,outname,T_OCT);
1042 greg 2.14 if (fdate(inpname) > fdate(outname) &&
1043     system(buf)) { /* create octree */
1044 greg 2.12 fclose(outfp);
1045     return(-1);
1046     }
1047     fprintf(outfp, "void instance %s_inst\n", outname);
1048     if (!FEQ(meters2out, 1.0))
1049     fprintf(outfp, "3 %s -s %f\n",
1050     libname(buf,outname,T_OCT),
1051     meters2out);
1052     else
1053     fprintf(outfp, "1 %s\n", libname(buf,outname,T_OCT));
1054     fprintf(outfp, "0\n0\n");
1055     fclose(outfp);
1056     } else { /* else append to luminaire file */
1057     if (!FEQ(meters2out, 1.0)) { /* apply scalefactor */
1058     sprintf(cp, "| xform -s %f ", meters2out);
1059     cp += strlen(cp);
1060     }
1061 greg 2.13 if (!out2stdout) {
1062     fclose(outfp);
1063     strcpy(cp, ">> "); /* append works for DOS? */
1064     cp += 3;
1065     fullname(cp,outname,T_RAD);
1066     }
1067 greg 2.12 if (system(buf))
1068     return(-1);
1069     }
1070     return(0);
1071 greg 1.1 }