ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.12
Committed: Tue Apr 25 21:37:14 1995 UTC (29 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.11: +189 -31 lines
Log Message:
added MGF detail geometry conversion

File Contents

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