ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.21
Committed: Thu Jul 3 22:41:44 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.20: +10 -10 lines
Log Message:
Reduced compile problems on Windows.

File Contents

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