ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/ies2rad.c
Revision: 2.17
Committed: Mon Nov 10 10:13:58 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 2.16: +12 -12 lines
Log Message:
removed use of "word", which is a typedef on Cray systems

File Contents

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