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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: ies2rad.c,v 2.22 2003/07/27 22:12:01 schorsch Exp $";
3 #endif
4 /*
5 * Convert IES luminaire data to Radiance description
6 *
7 * 07Apr90 Greg Ward
8 *
9 * Fixed correction factor for flat sources 29Oct2001 GW
10 */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <math.h>
15 #include <sys/types.h>
16 #include <ctype.h>
17
18 #include "rtio.h"
19 #include "color.h"
20 #include "paths.h"
21
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 /* 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 /* 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 #define RMAXWORD 76
85 /* file types */
86 #define T_RAD ".rad"
87 #define T_DST ".dat"
88 #define T_TLT "%.dat"
89 #define T_OCT ".oct"
90 /* 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 #define abspath(p) (ISDIRSEP((p)[0]) || (p)[0] == '.')
100
101 static char default_name[] = "default";
102
103 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 char *deflamp = NULL; /* default lamp type */
110 float defcolor[3] = {1.,1.,1.}; /* default lamp color */
111 float *lampcolor = defcolor; /* pointer to current lamp color */
112 double multiplier = 1.0; /* multiplier for all light sources */
113 char units[64] = "meters"; /* output units */
114 int out2stdout = 0; /* put out to stdout r.t. file */
115 int instantiate = 0; /* instantiate geometry */
116 double illumrad = 0.0; /* radius for illum sphere */
117
118 typedef struct {
119 int isillum; /* do as illum */
120 int type; /* RECT, DISK, SPHERE */
121 double mult; /* candela multiplier */
122 double w, l, h; /* width, length, height */
123 double area; /* max. projected area */
124 } SRCINFO; /* a source shape (units=meters) */
125
126 int gargc; /* global argc (minus filenames) */
127 char **gargv; /* global argv */
128
129
130 #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
134
135 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 {
169 char *outfile = NULL;
170 int status;
171 char outname[RMAXWORD];
172 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 case 'o': /* output file root name */
237 outfile = argv[++i];
238 break;
239 case 's': /* output to stdout */
240 out2stdout = !out2stdout;
241 break;
242 case 'i': /* illum */
243 illumrad = atof(argv[++i]);
244 break;
245 case 'g': /* instatiate geometry? */
246 instantiate = !instantiate;
247 break;
248 case 't': /* override lamp type */
249 lamptype = argv[++i];
250 break;
251 case 'u': /* default lamp type */
252 deflamp = argv[++i];
253 break;
254 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 initlamps(); /* get lamp data (if needed) */
271 /* 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 else
278 goto needsingle;
279 } else if (i >= argc) {
280 fprintf(stderr, "%s: missing output file specification\n",
281 argv[0]);
282 exit(1);
283 }
284 if (out2stdout && i != argc-1)
285 goto needsingle;
286 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 needsingle:
294 fprintf(stderr, "%s: single input file required\n", argv[0]);
295 exit(1);
296 }
297
298 void
299 initlamps(void) /* set up lamps */
300 {
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 }
337
338
339 char *
340 stradd( /* add a string at dst */
341 register char *dst,
342 register char *src,
343 int sep
344 )
345 {
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 fullnam( /* return full path name */
360 char *path,
361 char *fname,
362 char *suffix
363 )
364 {
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 libname(stradd(path, libdir, DIRSEP), fname, suffix);
371
372 return(path);
373 }
374
375
376 char *
377 libname( /* return library relative name */
378 char *path,
379 char *fname,
380 char *suffix
381 )
382 {
383 if (abspath(fname))
384 strcpy(stradd(path, fname, 0), suffix);
385 else
386 strcpy(stradd(stradd(path, prefdir, DIRSEP), fname, 0), suffix);
387
388 return(path);
389 }
390
391
392 char *
393 filename( /* get final component of pathname */
394 register char *path
395 )
396 {
397 register char *cp;
398
399 for (cp = path; *path; path++)
400 if (ISDIRSEP(*path))
401 cp = path+1;
402 return(cp);
403 }
404
405
406 char *
407 filetrunc( /* truncate filename at end of path */
408 char *path
409 )
410 {
411 register char *p1, *p2;
412
413 for (p1 = p2 = path; *p2; p2++)
414 if (ISDIRSEP(*p2))
415 p1 = p2;
416 if (p1 == path && ISDIRSEP(*p1))
417 p1++;
418 *p1 = '\0';
419 return(path);
420 }
421
422
423 char *
424 tailtrunc( /* truncate tail of filename */
425 char *name
426 )
427 {
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 void
443 blanktrunc( /* truncate spaces at end of line */
444 char *s
445 )
446 {
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 int
458 k_match( /* header line matches keyword? */
459 register char *kwd,
460 register char *hdl
461 )
462 {
463 if (!*hdl++ == '[')
464 return(0);
465 while (islower(*hdl) ? toupper(*hdl) == *kwd++ : *hdl == *kwd++)
466 if (!*hdl++)
467 return(0);
468 return((!*kwd) & (*hdl == ']'));
469 }
470
471
472 char *
473 keyargs( /* return keyword arguments */
474 register char *hdl
475 )
476 {
477 while (*hdl && *hdl++ != ']')
478 ;
479 while (isspace(*hdl))
480 hdl++;
481 return(hdl);
482 }
483
484
485 void
486 putheader( /* print header */
487 FILE *out
488 )
489 {
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 int
504 ies2rad( /* convert IES file */
505 char *inpname,
506 char *outname
507 )
508 {
509 SRCINFO srcinfo;
510 char buf[MAXLINE], tltid[RMAXWORD];
511 char geomfile[128];
512 FILE *inpfp, *outfp;
513 int lineno = 0;
514
515 geomfile[0] = '\0';
516 srcinfo.isillum = 0;
517 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 if (out2stdout)
525 outfp = stdout;
526 else if ((outfp = fopen(fullnam(buf,outname,T_RAD), "w")) == NULL) {
527 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 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 fputs("#<", outfp);
547 fputs(buf, outfp);
548 putc('\n', outfp);
549 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 }
558 if (lampcolor == NULL) {
559 fprintf(stderr, "%s: warning - no lamp type\n", inpname);
560 fputs("# Unknown lamp type (used default)\n", outfp);
561 lampcolor = defcolor;
562 } 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 if (feof(inpfp)) {
566 fprintf(stderr, "%s: not in IES format\n", inpname);
567 goto readerr;
568 }
569 atos(tltid, RMAXWORD, buf+TLTSTRLEN);
570 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 if (dosource(&srcinfo, inpfp, outfp, tltid, outname) != 0) {
579 fprintf(stderr, "%s: bad luminaire data\n", inpname);
580 goto readerr;
581 }
582 fclose(inpfp);
583 /* 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 return(0);
589 readerr:
590 fclose(inpfp);
591 fclose(outfp);
592 unlink(fullnam(buf,outname,T_RAD));
593 return(-1);
594 }
595
596
597 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 {
607 int nangles, tlt_type;
608 double minmax[1][2];
609 char buf[PATH_MAX], tltname[RMAXWORD];
610 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 if (ISDIRSEP(tltspec[0]))
620 strcpy(buf, tltspec);
621 else
622 strcpy(stradd(buf, dir, DIRSEP), tltspec);
623 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 if ((datout = fopen(fullnam(buf,tltname,T_TLT),"w")) == NULL) {
631 perror(buf);
632 if (datin != in)
633 fclose(datin);
634 return(-1);
635 }
636 if (!scnint(datin,&tlt_type) || !scnint(datin,&nangles)
637 || 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 unlink(fullnam(buf,tltname,T_TLT));
643 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 minmax[0][1]>90.+FTINY ? "tilt_ang" : "tilt_ang2");
655 break;
656 case TLT_H0: /* horiz. in 0 deg. plane */
657 fprintf(out, "6 noop %s tilt.cal %s -rz 90\n", buf,
658 minmax[0][1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
659 break;
660 case TLT_H90:
661 fprintf(out, "4 noop %s tilt.cal %s\n", buf,
662 minmax[0][1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
663 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 int
677 dosource( /* create source and distribution */
678 SRCINFO *sinf,
679 FILE *in,
680 FILE *out,
681 char *mod,
682 char *name
683 )
684 {
685 char buf[PATH_MAX], id[RMAXWORD];
686 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 int doupper, dolower, dosides;
692
693 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 fprintf(stderr, "dosource: bad lamp specification\n");
700 return(-1);
701 }
702 sinf->mult = multiplier*mult*bfactor*pfactor;
703 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 if (makeshape(sinf, width, length, height) != 0) {
713 fprintf(stderr, "dosource: illegal source dimensions");
714 return(-1);
715 }
716 if ((datout = fopen(fullnam(buf,name,T_DST), "w")) == NULL) {
717 perror(buf);
718 return(-1);
719 }
720 if (cvdata(in, datout, 2, nangles, 1./WHTEFFICACY, bounds) != 0) {
721 fprintf(stderr, "dosource: bad distribution data\n");
722 fclose(datout);
723 unlink(fullnam(buf,name,T_DST));
724 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 fprintf(out, "7 ");
737 else
738 fprintf(out, "5 ");
739 dolower = (bounds[0][0] < 90.);
740 doupper = (bounds[0][1] > 90.);
741 dosides = (doupper & dolower && sinf->h > MINDIM);
742 fprintf(out, "%s %s source.cal ",
743 sinf->type==SPHERE ? "corr" :
744 !dosides ? "flatcorr" :
745 sinf->type==DISK ? "cylcorr" : "boxcorr",
746 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 } else /* pmtype == PM_A */ {
754 if (nangles[1] >= 2) {
755 d1 = bounds[1][1] - bounds[1][0];
756 if (d1 <= 90.+FTINY)
757 fprintf(out, "src_phi4 ");
758 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 fprintf(out, "src_phi ");
765 fprintf(out, "src_theta ");
766 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 if (!dosides || sinf->type == SPHERE)
772 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 sinf->w, sinf->h);
776 else
777 fprintf(out, "\n0\n4 %g %g %g %g\n", sinf->mult,
778 sinf->l, sinf->w, sinf->h);
779 if (putsource(sinf, out, id, filename(name),
780 dolower, doupper, dosides) != 0)
781 return(-1);
782 return(0);
783 }
784
785
786 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 {
797 char lname[RMAXWORD];
798
799 strcat(strcpy(lname, name), "_light");
800 fprintf(fp, "\n%s %s %s\n", mod,
801 shp->isillum ? "illum" : "light", lname);
802 fprintf(fp, "0\n0\n3 %g %g %g\n",
803 lampcolor[0], lampcolor[1], lampcolor[2]);
804 switch (shp->type) {
805 case RECT:
806 if (dolower)
807 putrectsrc(shp, fp, lname, name, 0);
808 if (doupper)
809 putrectsrc(shp, fp, lname, name, 1);
810 if (dosides)
811 putsides(shp, fp, lname, name);
812 break;
813 case DISK:
814 if (dolower)
815 putdisksrc(shp, fp, lname, name, 0);
816 if (doupper)
817 putdisksrc(shp, fp, lname, name, 1);
818 if (dosides)
819 putcyl(shp, fp, lname, name);
820 break;
821 case SPHERE:
822 putspheresrc(shp, fp, lname, name);
823 break;
824 }
825 return(0);
826 }
827
828
829 int
830 makeshape( /* make source shape */
831 register SRCINFO *shp,
832 double width,
833 double length,
834 double height
835 )
836 {
837 if (illumrad/meters2out >= MINDIM/2.) {
838 shp->isillum = 1;
839 shp->type = SPHERE;
840 shp->w = shp->l = shp->h = 2.*illumrad / meters2out;
841 } 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 case SPHERE:
875 shp->area = PI/4. * shp->w * shp->w;
876 break;
877 }
878 return(0);
879 }
880
881
882 void
883 putrectsrc( /* rectangular source */
884 SRCINFO *shp,
885 FILE *fp,
886 char *mod,
887 char *name,
888 int up
889 )
890 {
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 void
899 putsides( /* put out sides of box */
900 register SRCINFO *shp,
901 FILE *fp,
902 char *mod,
903 char *name
904 )
905 {
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 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 {
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 void
935 putpoint( /* put out a point */
936 register SRCINFO *shp,
937 FILE *fp,
938 int p
939 )
940 {
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 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 {
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 void
976 putcyl( /* put out a cylinder */
977 register SRCINFO *shp,
978 FILE *fp,
979 char *mod,
980 char *name
981 )
982 {
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 void
992 putspheresrc( /* put out a sphere source */
993 SRCINFO *shp,
994 FILE *fp,
995 char *mod,
996 char *name
997 )
998 {
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 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 {
1014 double *pt[4];
1015 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 if (!scnflt(in, &pt[i][j]))
1031 return(-1);
1032 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 free((void *)pt[i]);
1058 }
1059 for (i = 0; i < total; i++) {
1060 if (i%4 == 0)
1061 putc('\n', out);
1062 if (!scnflt(in, &val))
1063 return(-1);
1064 fprintf(out, "\t%g", val*mult);
1065 }
1066 putc('\n', out);
1067 return(0);
1068 }
1069
1070
1071 char *
1072 getword( /* scan a word from fp */
1073 register FILE *fp
1074 )
1075 {
1076 static char wrd[RMAXWORD];
1077 register char *cp;
1078 register int c;
1079
1080 while (isspace(c=getc(fp)))
1081 ;
1082 for (cp = wrd; c != EOF && cp < wrd+RMAXWORD-1;
1083 *cp++ = c, c = getc(fp))
1084 if (isspace(c) || c == ',') {
1085 while (isspace(c))
1086 c = getc(fp);
1087 if ((c != EOF) & (c != ','))
1088 ungetc(c, fp);
1089 *cp = '\0';
1090 return(wrd);
1091 }
1092 *cp = '\0';
1093 return(cp > wrd ? wrd : NULL);
1094 }
1095
1096
1097 int
1098 cvtint( /* convert a word to an integer */
1099 int *ip,
1100 char *wrd
1101 )
1102 {
1103 if (wrd == NULL || !isint(wrd))
1104 return(0);
1105 *ip = atoi(wrd);
1106 return(1);
1107 }
1108
1109
1110 int
1111 cvtflt( /* convert a word to a double */
1112 double *rp,
1113 char *wrd
1114 )
1115 {
1116 if (wrd == NULL || !isflt(wrd))
1117 return(0);
1118 *rp = atof(wrd);
1119 return(1);
1120 }
1121
1122
1123 int
1124 cvgeometry(
1125 char *inpname,
1126 register SRCINFO *sinf,
1127 char *outname,
1128 FILE *outfp /* close output file upon return */
1129 )
1130 {
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 fullnam(cp,outname,T_OCT);
1153 if (fdate(inpname) > fdate(outname) &&
1154 system(buf)) { /* create octree */
1155 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 if (!out2stdout) {
1173 fclose(outfp);
1174 strcpy(cp, ">> "); /* append works for DOS? */
1175 cp += 3;
1176 fullnam(cp,outname,T_RAD);
1177 }
1178 if (system(buf))
1179 return(-1);
1180 }
1181 return(0);
1182 }