ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.21
Committed: Thu Jul 3 22:41:44 2003 UTC (20 years, 8 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.20: +10 -10 lines
Log Message:
Reduced compile problems on Windows.

File Contents

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