ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.26
Committed: Wed Jun 22 19:57:17 2011 UTC (12 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad4R2, rad4R1, rad4R2P1
Changes since 2.25: +2 -2 lines
Log Message:
Fixed mgf2rad -m option that needed to be -e

File Contents

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