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

File Contents

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