ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.23
Committed: Sat Nov 15 13:29:23 2003 UTC (20 years, 4 months ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1
Changes since 2.22: +205 -100 lines
Log Message:
ANSIfication. Fixed missing dosides parameter in putsource(). Fixed type of minmax variable in dotilt()

File Contents

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