ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/wrapBSDF.c
Revision: 2.1
Committed: Wed Feb 11 18:08:10 2015 UTC (7 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Checking in first compilable version of new program

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * Wrap BSDF data in valid WINDOW XML wrapper
6 *
7 * G. Ward January 2015
8 */
9
10 #include <ctype.h>
11 #include "rtio.h"
12 #include "rtprocess.h"
13 #include "ezxml.h"
14 #include "bsdf.h"
15 #include "bsdf_m.h"
16 /* XML template file names */
17 const char def_template[] = "minimalBSDFt.xml";
18 const char win6_template[] = "window6BSDFt.xml";
19
20 const char stdin_name[] = "<stdin>";
21
22 /* input files (can be stdin_name) */
23 const char *xml_input = NULL;
24 /* unit for materials & geometry */
25 const char *attr_unit = "millimeter";
26 const char legal_units[] = "meter|foot|inch|centimeter|millimeter";
27 /* system materials & geometry */
28 const char *mgf_geometry = NULL;
29
30 /* angle basis */
31 enum { ABdefault=-1, ABklemsFull=0, ABklemsHalf, ABklemsQuarter,
32 ABtensorTree3, ABtensorTree4, ABend };
33
34 int angle_basis = ABdefault;
35
36 /* field IDs and nicknames */
37 struct s_fieldID {
38 char nickName[4];
39 int has_unit;
40 const char *fullName;
41 } XMLfieldID[] = {
42 {"m", 0, "Manufacturer"},
43 {"n", 0, "Name"},
44 {"c", 0, "ThermalConductivity"},
45 {"ef", 0, "EmissivityFront"},
46 {"eb", 0, "EmissivityBack"},
47 {"tir", 0, "TIR"},
48 {"eo", 0, "EffectiveOpennessFraction"},
49 {"t", 1, "Thickness"},
50 {"h", 1, "Height"},
51 {"w", 1, "Width"},
52 {"\0", -1, NULL} /* terminator */
53 };
54 /* field assignments */
55 #define MAXASSIGN 12
56 const char *field_assignment[MAXASSIGN];
57 int nfield_assign = 0;
58 #define FASEP ';'
59
60 /* data file(s) & spectra */
61 enum { DTtransForward, DTtransBackward, DTreflForward, DTreflBackward };
62
63 enum { DSsolar=-1, DSnir=-2, DSxbar31=-3, DSvisible=-4, DSzbar31=-5 };
64
65 #define MAXFILES 20
66
67 struct s_dfile {
68 const char *fname; /* input data file name */
69 short type; /* BSDF data type */
70 short spectrum; /* BSDF sensor spectrum */
71 } data_file[MAXFILES];
72
73 int ndataf = 0; /* number of data files */
74
75 const char *spectr_file[MAXFILES]; /* custom spectral curve input */
76
77 const char top_level_name[] = "WindowElement";
78
79 static char *basis_definition[] = {
80
81 "\t\t<IncidentDataStructure>Columns</IncidentDataStructure>\n"
82 "\t\t<AngleBasis>\n"
83 "\t\t\t<AngleBasisName>LBNL/Klems Full</AngleBasisName>\n"
84 "\t\t</AngleBasis>\n",
85
86 "\t\t<IncidentDataStructure>Columns</IncidentDataStructure>\n"
87 "\t\t<AngleBasis>\n"
88 "\t\t\t<AngleBasisName>LBNL/Klems Half</AngleBasisName>\n"
89 "\t\t</AngleBasis>\n",
90
91 "\t\t<IncidentDataStructure>Columns</IncidentDataStructure>\n"
92 "\t\t<AngleBasis>\n"
93 "\t\t\t<AngleBasisName>LBNL/Klems Quarter</AngleBasisName>\n"
94 "\t\t</AngleBasis>\n",
95
96 "\t\t<IncidentDataStructure>TensorTree3</IncidentDataStructure>\n",
97
98 "\t\t<IncidentDataStructure>TensorTree4</IncidentDataStructure>\n",
99 };
100
101 /* Copy data from file descriptor to stdout and close */
102 static int
103 copy_and_close(int fd)
104 {
105 int ok = 1;
106 char buf[8192];
107 int n;
108
109 if (fd < 0)
110 return 0;
111 while ((n = read(fd, buf, sizeof(buf))) > 0)
112 if (write(fileno(stdout), buf, n) != n) {
113 ok = 0;
114 break;
115 }
116 ok &= (n == 0);
117 close(fd);
118 return ok;
119 }
120
121 /* Allocate and assign string from file or stream */
122 static char *
123 input2str(const char *inpspec)
124 {
125 FILE *fp = NULL;
126 char *str;
127 int len, pos, n;
128
129 if (inpspec == NULL || !*inpspec)
130 return "";
131 if (inpspec == stdin_name) { /* read from stdin */
132 fp = stdin;
133 } else if (*inpspec == '!') { /* read from command */
134 fp = popen(inpspec+1, "r");
135 if (fp == NULL) {
136 fprintf(stderr, "Cannot start process '%s'\n",
137 inpspec+1);
138 return "";
139 }
140 } else { /* else load file */
141 int fd = open(inpspec, O_RDONLY);
142 if (fd < 0) {
143 fprintf(stderr, "%s: cannot open\n", inpspec);
144 return "";
145 }
146 len = lseek(fd, 0L, SEEK_END);
147 if (len < 0) {
148 fprintf(stderr, "%s: seek error\n", inpspec);
149 close(fd);
150 return "";
151 }
152 lseek(fd, 0L, SEEK_SET);
153 str = (char *)malloc(len+1);
154 if (str == NULL) {
155 close(fd);
156 goto memerr;
157 }
158 if (read(fd, str, len) != len) {
159 fprintf(stderr, "%s: read error\n", inpspec);
160 free(str);
161 close(fd);
162 return "";
163 }
164 str[len] = '\0';
165 close(fd);
166 return str;
167 }
168 /* reading from stream */
169 str = (char *)malloc((len=8192)+1);
170 if (str == NULL)
171 goto memerr;
172 pos = 0;
173 while ((n = read(fileno(fp), str+pos, len-pos)) > 0)
174 if ((pos += n) >= len) { /* need more space? */
175 str = (char *)realloc(str, (len += len>>2) + 1);
176 if (str == NULL)
177 goto memerr;
178 }
179 if (n < 0) {
180 fprintf(stderr, "%s: read error\n", inpspec);
181 free(str);
182 str = "";
183 } else { /* tidy up result */
184 str[pos] = '\0';
185 str = (char *)realloc(str, (len=pos)+1);
186 if (str == NULL)
187 goto memerr;
188 }
189 if (*inpspec != '!')
190 fclose(fp);
191 else if (pclose(fp))
192 fprintf(stderr, "Error running command '%s'\n", inpspec+1);
193 return str;
194 memerr:
195 fprintf(stderr, "%s: error allocating memory\n", inpspec);
196 if (fp != NULL)
197 (*inpspec == '!') ? pclose(fp) : fclose(fp);
198 return "";
199 }
200
201 /* Make material assignments in field_assignment to XML fields */
202 static int
203 mat_assignments(const char *caller, const char *fn, ezxml_t wtl)
204 {
205 int i;
206
207 if (!nfield_assign)
208 return 1;
209 wtl = ezxml_child(wtl, "Material");
210 if (wtl == NULL) {
211 fprintf(stderr, "%s: missing <Material> tag\n", fn);
212 return 0;
213 }
214 for (i = 0; i < nfield_assign; i++) {
215 const char *fnext = field_assignment[i];
216 for ( ; ; ) {
217 ezxml_t fld;
218 char sbuf[512];
219 int j;
220
221 while (isspace(*fnext))
222 ++fnext;
223 if (!*fnext)
224 break;
225 for (j = 0; (*fnext != '=') & !isspace(*fnext); ) {
226 if (!*fnext | (*fnext == FASEP) |
227 (j >= sizeof(sbuf)-1)) {
228 fprintf(stderr,
229 "%s: bad tag name in assignment '%s'\n",
230 caller, field_assignment[i]);
231 return 0;
232 }
233 sbuf[j++] = *fnext++;
234 }
235 sbuf[j] = '\0'; /* check nick-names */
236 for (j = 0; XMLfieldID[j].nickName[0]; j++)
237 if (!strcasecmp(sbuf, XMLfieldID[j].nickName)) {
238 strcpy(sbuf, XMLfieldID[j].fullName);
239 break;
240 }
241 /* check if tag exists */
242 fld = ezxml_child(wtl, sbuf);
243 if (fld == NULL) { /* otherwise, create one */
244 fprintf(stderr, "%s: warning - adding tag <%s>\n",
245 fn, sbuf);
246 fld = ezxml_add_child_d(wtl, sbuf, strlen(wtl->txt));
247 }
248 if (XMLfieldID[j].has_unit)
249 ezxml_set_attr(fld, "unit", attr_unit);
250 while (isspace(*fnext))
251 ++fnext;
252 if (*fnext++ != '=') {
253 fprintf(stderr,
254 "%s: missing '=' in assignment '%s'\n",
255 caller, field_assignment[i]);
256 return 0;
257 }
258 for (j = 0; *fnext & (*fnext != FASEP); ) {
259 if (j >= sizeof(sbuf)-1) {
260 fprintf(stderr,
261 "%s: field too long in '%s'\n",
262 caller, field_assignment[i]);
263 return 0;
264 }
265 sbuf[j++] = *fnext++;
266 }
267 sbuf[j] = '\0';
268 ezxml_set_txt_d(fld, sbuf);
269 fnext += (*fnext == FASEP);
270 }
271 }
272 return 1; /* no errors */
273 }
274
275 /* Complete angle basis specification */
276 static int
277 finish_angle_basis(ezxml_t ab)
278 {
279 const char *bn = ezxml_txt(ezxml_child(ab, "AngleBasisName"));
280 int i, n = nabases;
281 char buf[32];
282
283 if (!*bn) {
284 fputs("Internal error - missing <AngleBasisName>!\n", stderr);
285 return 0;
286 }
287 while (n-- > 0)
288 if (!strcasecmp(bn, abase_list[n].name))
289 break;
290 if (n < 0) {
291 fprintf(stderr, "Internal error - unknown angle basis '%s'", bn);
292 return 0;
293 }
294 for (i = 0; abase_list[n].lat[i].nphis; i++) {
295 ezxml_t tb, abb = ezxml_add_child(ab, "AngleBasisBlock",
296 strlen(ab->txt));
297 sprintf(buf, "%g", i ?
298 .5*(abase_list[n].lat[i].tmin + abase_list[n].lat[i+1].tmin) :
299 .0);
300 ezxml_set_txt_d(ezxml_add_child(abb,"Theta",strlen(abb->txt)), buf);
301 sprintf(buf, "%d", abase_list[n].lat[i].nphis);
302 ezxml_set_txt_d(ezxml_add_child(abb,"nPhis",strlen(abb->txt)), buf);
303 tb = ezxml_add_child(abb, "ThetaBounds", strlen(abb->txt));
304 sprintf(buf, "%g", abase_list[n].lat[i].tmin);
305 ezxml_set_txt(ezxml_add_child(tb,"LowerTheta",strlen(tb->txt)), buf);
306 sprintf(buf, "%g", abase_list[n].lat[i+1].tmin);
307 ezxml_set_txt(ezxml_add_child(tb,"UpperTheta",strlen(tb->txt)), buf);
308 }
309 return 1;
310 }
311
312 /* Determine our angle basis from current tags */
313 static int
314 determine_angle_basis(const char *fn, ezxml_t wtl)
315 {
316 const char *ids;
317 int i;
318
319 wtl = ezxml_child(wtl, "DataDefinition");
320 if (wtl == NULL)
321 return -1;
322 ids = ezxml_txt(ezxml_child(wtl, "IncidentDataStructure"));
323 if (ids == NULL)
324 return -1;
325 for (i = 0; i < ABend; i++) {
326 ezxml_t parsed = ezxml_parse_str(basis_definition[i],
327 strlen(basis_definition[i]));
328 int match = 0;
329 if (!strcmp(ids, ezxml_txt(ezxml_child(parsed,
330 "IncidentDataStructure")))) {
331 const char *abn0 = ezxml_txt(
332 ezxml_child(ezxml_child(wtl,
333 "AngleBasis"), "AngleBasisName"));
334 const char *abn1 = ezxml_txt(
335 ezxml_child(ezxml_child(parsed,
336 "AngleBasis"), "AngleBasisName"));
337 match = !strcmp(abn0, abn1);
338 }
339 ezxml_free(parsed);
340 if (match)
341 return i;
342 }
343 return -1;
344 }
345
346 /* Write out BSDF data block with surrounding tags */
347 static int
348 writeBSDFblock(const char *caller, struct s_dfile *df)
349 {
350 char *cp;
351
352 puts("\t<WavelengthData>");
353 puts("\t\t<LayerNumber>System</LayerNumber>");
354 switch (df->spectrum) {
355 case DSvisible:
356 puts("\t\t<Wavelength unit=\"Integral\">Visible</Wavelength>");
357 puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
358 puts("\t\t<DetectorSpectrum>ASTM E308 1931 Y.dsp</DetectorSpectrum>");
359 break;
360 case DSxbar31:
361 puts("\t\t<Wavelength unit=\"Integral\">CIE-X</Wavelength>");
362 puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
363 puts("\t\t<DetectorSpectrum>ASTM E308 1931 X.dsp</DetectorSpectrum>");
364 break;
365 case DSzbar31:
366 puts("\t\t<Wavelength unit=\"Integral\">CIE-Z</Wavelength>");
367 puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
368 puts("\t\t<DetectorSpectrum>ASTM E308 1931 Z.dsp</DetectorSpectrum>");
369 break;
370 case DSsolar:
371 puts("\t\t<Wavelength unit=\"Integral\">Solar</Wavelength>");
372 puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
373 puts("\t\t<DetectorSpectrum>None</DetectorSpectrum>");
374 break;
375 case DSnir:
376 puts("\t\t<Wavelength unit=\"Integral\">NIR</Wavelength>");
377 puts("\t\tSourceSpectrum>PLACE_HOLDER</SourceSpectrum>");
378 puts("\t\t<DetectorSpectrum>PLACE_HOLDER</DetectorSpectrum>");
379 break;
380 default:
381 cp = strrchr(spectr_file[df->spectrum], '.');
382 if (cp != NULL)
383 *cp = '\0';
384 printf("\t\t<Wavelength unit=\"Integral\">%s</Wavelength>\n",
385 spectr_file[df->spectrum]);
386 if (cp != NULL)
387 *cp = '.';
388 puts("\t\tSourceSpectrum>CIE Illuminant D65 1nm.ssp</SourceSpectrum>");
389 printf("\t\t<DetectorSpectrum>%s</DetectorSpectrum>\n",
390 spectr_file[df->spectrum]);
391 break;
392 }
393 puts("\t\t<WavelengthDataBlock>");
394 fputs("\t\t\t<WavelengthDataDirection>", stdout);
395 switch (df->type) {
396 case DTtransForward:
397 fputs("Transmission Front", stdout);
398 break;
399 case DTtransBackward:
400 fputs("Transmission Back", stdout);
401 break;
402 case DTreflForward:
403 fputs("Reflection Front", stdout);
404 break;
405 case DTreflBackward:
406 fputs("Reflection Back", stdout);
407 break;
408 default:
409 fprintf(stderr, "%s: internal - bad BSDF type (%d)\n", caller, df->type);
410 return 0;
411 }
412 puts("</WavelengthDataDirection>");
413 switch (angle_basis) {
414 case ABklemsFull:
415 puts("\t\t\t<ColumnAngleBasis>LBNL/Klems Full</ColumnAngleBasis>");
416 break;
417 case ABklemsHalf:
418 puts("\t\t\t<ColumnAngleBasis>LBNL/Klems Half</ColumnAngleBasis>");
419 break;
420 case ABklemsQuarter:
421 puts("\t\t\t<ColumnAngleBasis>LBNL/Klems Quarter</ColumnAngleBasis>");
422 break;
423 case ABtensorTree3:
424 case ABtensorTree4:
425 puts("\t\t\t<AngleBasis>LBNL/Shirley-Chiu</AngleBasis>");
426 break;
427 default:
428 fprintf(stderr, "%s: bad angle basis (%d)\n", caller, angle_basis);
429 return 0;
430 }
431 puts("\t\t\t<ScatteringDataType>BTDF</ScatteringDataType>");
432 puts("\t\t\t<ScatteringData>");
433 fflush(stdout);
434 if (df->fname == stdin_name) {
435 copy_and_close(fileno(stdin));
436 } else if (*df->fname != '!') {
437 if (!copy_and_close(open(df->fname, O_RDONLY))) {
438 fprintf(stderr, "%s: error reading from '%s'\n",
439 caller, df->fname);
440 return 0;
441 }
442 } else if (system(df->fname+1)) {
443 fprintf(stderr, "%s: error running '%s'\n", caller, df->fname+1);
444 return 0;
445 }
446 puts("\t\t\t</ScatteringData>");
447 puts("\t\t</WavelengthDataBlock>");
448 puts("\t</WavelengthData>");
449 return 1;
450 }
451
452 /* Write out XML, interpolating BSDF data block(s) */
453 static int
454 writeBSDF(const char *caller, ezxml_t fl)
455 {
456 char *xml = ezxml_toxml(fl);
457 int ei, i;
458 /* locate trailer */
459 for (ei = strlen(xml)-strlen("</Layer></Optical></WindowElement>");
460 ei >= 0; ei--)
461 if (!strncmp(xml+ei, "</Layer>", 8))
462 break;
463 if (ei < 0) {
464 fprintf(stderr, "%s: internal - cannot find trailer\n",
465 caller);
466 free(xml);
467 return 0;
468 }
469 fflush(stdout); /* write previous XML info. */
470 if (write(fileno(stdout), xml, ei) != ei) {
471 free(xml);
472 return 0;
473 }
474 for (i = 0; i < ndataf; i++) /* interpolate new data */
475 if (!writeBSDFblock(caller, &data_file[i])) {
476 free(xml);
477 return 0;
478 }
479 fputs(xml+ei, stdout); /* write trailer */
480 free(xml);
481 return (fflush(stdout) == 0);
482 }
483
484 /* Insert BSDF data into XML wrapper */
485 static int
486 wrapBSDF(const char *caller)
487 {
488 const char *xml_path = getpath((char *)xml_input, getrlibpath(), R_OK);
489 ezxml_t fl, wtl;
490 /* load previous XML/template */
491 if (xml_path == NULL) {
492 fprintf(stderr, "%s: cannot find XML file named '%s'\n",
493 caller, xml_input==NULL ? "NULL" : xml_input);
494 return 0;
495 }
496 fl = ezxml_parse_file(xml_path);
497 if (fl == NULL) {
498 fprintf(stderr, "%s: cannot open XML path '%s'\n",
499 caller, xml_path);
500 return 0;
501 }
502 if (ezxml_error(fl)[0]) {
503 fprintf(stderr, "%s: error in XML %s: %s\n", caller, xml_path,
504 ezxml_error(fl));
505 goto failure;
506 }
507 if (strcmp(ezxml_name(fl), top_level_name)) {
508 fprintf(stderr, "%s: top level in XML '%s' not '%s'\n",
509 caller, xml_path, top_level_name);
510 goto failure;
511 }
512 wtl = ezxml_child(fl, "FileType");
513 if (wtl != NULL && strcmp(ezxml_txt(wtl), "BSDF")) {
514 fprintf(stderr, "%s: wrong FileType in XML '%s' (must be 'BSDF')",
515 caller, xml_path);
516 goto failure;
517 }
518 wtl = ezxml_child(ezxml_child(fl, "Optical"), "Layer");
519 if (wtl == NULL) {
520 fprintf(stderr, "%s: no optical layers in XML '%s'",
521 caller, xml_path);
522 goto failure;
523 }
524 /* make material assignments */
525 if (!mat_assignments(caller, xml_path, wtl)) {
526 goto failure;
527 }
528 if (mgf_geometry != NULL) { /* add geometry if specified */
529 ezxml_t geom = ezxml_child(wtl, "Geometry");
530 if (geom == NULL)
531 geom = ezxml_add_child(wtl, "Geometry", 0);
532 ezxml_set_attr(geom, "format", "MGF");
533 geom = ezxml_child(geom, "MGFblock");
534 if (geom == NULL) {
535 geom = ezxml_child(wtl, "Geometry");
536 geom = ezxml_add_child(geom, "MGFblock", strlen(geom->txt));
537 }
538 ezxml_set_attr(geom, "unit", attr_unit);
539 ezxml_set_txt(geom, input2str(mgf_geometry));
540 if (geom->txt[0])
541 ezxml_set_flag(geom, EZXML_TXTM);
542 }
543 /* check basis */
544 if (angle_basis != ABdefault) {
545 ezxml_t ab, dd = ezxml_child(wtl, "DataDefinition");
546 if (dd == NULL) {
547 dd = ezxml_add_child(wtl, "DataDefinition", 0);
548 } else {
549 if (ezxml_child(dd, "DataDefinition") != NULL)
550 fprintf(stderr,
551 "%s: warning - replacing existing <DataDefinition> in '%s'\n",
552 caller, xml_path);
553 while (dd->child != NULL)
554 ezxml_remove(dd->child);
555 }
556 ezxml_insert(ezxml_parse_str(basis_definition[angle_basis],
557 strlen(basis_definition[angle_basis])),
558 dd, 0);
559 if ((ab = ezxml_child(dd, "AngleBasis")) != NULL &&
560 !finish_angle_basis(ab))
561 goto failure;
562 } else if ((angle_basis = determine_angle_basis(xml_path, wtl)) < 0) {
563 fprintf(stderr, "%s: need -a option to set angle basis\n",
564 caller);
565 goto failure;
566 }
567 /* write & add BSDF data blocks */
568 if (!writeBSDF(caller, fl))
569 goto failure;
570 ezxml_free(fl); /* all done */
571 return 1;
572 failure:
573 ezxml_free(fl);
574 return 0;
575 }
576
577 /* Report usage and exit */
578 static void
579 UsageExit(const char *pname)
580 {
581 fputs("Usage: ", stderr);
582 fputs(pname, stderr);
583 fputs(" [options] [input.xml]\n", stderr);
584 exit(1);
585 }
586
587 /* Load XML file and use to wrap BSDF data (or modify fields) */
588 int
589 main(int argc, char *argv[])
590 {
591 int cur_spectrum = DSvisible;
592 int ncust_spec = 0;
593 int used_stdin = 0;
594 int units_set = 0;
595 int i;
596 /* get/check arguments */
597 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
598 switch (argv[i][1]) {
599 case 'W': /* customize for WINDOW 6 output */
600 xml_input = win6_template;
601 continue;
602 case 'f': /* field assignment(s) */
603 if (++i >= argc)
604 UsageExit(argv[0]);
605 if (nfield_assign >= MAXASSIGN) {
606 fprintf(stderr, "%s: too many -f options",
607 argv[0]);
608 return 1;
609 }
610 field_assignment[nfield_assign++] = argv[i];
611 continue;
612 case 'u': /* unit */
613 if (++i >= argc)
614 UsageExit(argv[0]);
615 if (units_set++) {
616 fprintf(stderr, "%s: only one -u option allowed\n",
617 argv[0]);
618 return 1;
619 }
620 if (strstr(argv[i], legal_units) == NULL) {
621 fprintf(stderr, "%s: unit must be one of (%s)\n",
622 argv[0], legal_units);
623 return 1;
624 }
625 attr_unit = argv[i];
626 continue;
627 case 'a': /* angle basis */
628 if (++i >= argc)
629 UsageExit(argv[0]);
630 if (angle_basis != ABdefault) {
631 fprintf(stderr, "%s: only one -a option allowed\n",
632 argv[0]);
633 return 1;
634 }
635 if (!strcasecmp(argv[i], "kf"))
636 angle_basis = ABklemsFull;
637 else if (!strcasecmp(argv[i], "kh"))
638 angle_basis = ABklemsHalf;
639 else if (!strcasecmp(argv[i], "kq"))
640 angle_basis = ABklemsQuarter;
641 else if (!strcasecmp(argv[i], "t3"))
642 angle_basis = ABtensorTree3;
643 else if (!strcasecmp(argv[i], "t4"))
644 angle_basis = ABtensorTree4;
645 else
646 UsageExit(argv[0]);
647 continue;
648 case 't': /* transmission */
649 if (i >= argc-1)
650 UsageExit(argv[0]);
651 if (ndataf >= MAXFILES) {
652 fprintf(stderr, "%s: too many data files\n",
653 argv[0]);
654 return 1;
655 }
656 if (!strcmp(argv[i], "-tf"))
657 data_file[ndataf].type = DTtransForward;
658 else if (!strcmp(argv[i], "-tb"))
659 data_file[ndataf].type = DTtransBackward;
660 else
661 UsageExit(argv[0]);
662 if (!strcmp(argv[++i], "-")) {
663 if (used_stdin++) UsageExit(argv[i]);
664 argv[i] = (char *)stdin_name;
665 }
666 data_file[ndataf].fname = argv[i];
667 data_file[ndataf].spectrum = cur_spectrum;
668 ndataf++;
669 continue;
670 case 'r': /* reflection */
671 if (i >= argc-1)
672 UsageExit(argv[0]);
673 if (ndataf >= MAXFILES) {
674 fprintf(stderr, "%s: too many data files\n",
675 argv[0]);
676 return 1;
677 }
678 if (!strcmp(argv[i], "-rf"))
679 data_file[ndataf].type = DTreflForward;
680 else if (!strcmp(argv[i], "-rb"))
681 data_file[ndataf].type = DTreflBackward;
682 else
683 UsageExit(argv[0]);
684 if (!strcmp(argv[++i], "-")) {
685 if (used_stdin++) UsageExit(argv[i]);
686 argv[i] = (char *)stdin_name;
687 }
688 data_file[ndataf].fname = argv[i];
689 data_file[ndataf++].spectrum = cur_spectrum;
690 continue;
691 case 's': /* spectrum name or input file */
692 if (++i >= argc)
693 UsageExit(argv[0]);
694 if (!strcasecmp(argv[i], "Solar"))
695 cur_spectrum = DSsolar;
696 else if (!strcasecmp(argv[i], "Visible") ||
697 !strcasecmp(argv[i], "CIE-Y"))
698 cur_spectrum = DSvisible;
699 else if (!strcasecmp(argv[i], "CIE-X"))
700 cur_spectrum = DSxbar31;
701 else if (!strcasecmp(argv[i], "CIE-Z"))
702 cur_spectrum = DSzbar31;
703 else if (!strcasecmp(argv[i], "NIR"))
704 cur_spectrum = DSnir;
705 else {
706 if (!strcmp(argv[i], "-")) {
707 fprintf(stderr,
708 "%s: cannot read spectra from stdin",
709 argv[0]);
710 return 1;
711 }
712 cur_spectrum = ncust_spec;
713 spectr_file[ncust_spec++] = argv[i];
714 }
715 continue;
716 case 'g': /* MGF geometry file */
717 if (i >= argc-1)
718 UsageExit(argv[0]);
719 if (mgf_geometry != NULL) {
720 fprintf(stderr, "%s: only one -g option allowed\n",
721 argv[0]);
722 return 1;
723 }
724 if (!strcmp(argv[++i], "-")) {
725 if (used_stdin++) UsageExit(argv[i]);
726 argv[i] = (char *)stdin_name;
727 }
728 mgf_geometry = argv[i];
729 continue;
730 case '\0': /* input XML from stdin */
731 break;
732 default:
733 UsageExit(argv[0]);
734 break;
735 }
736 break;
737 }
738 doneOptions: /* get XML input */
739 if (i >= argc) {
740 if (xml_input == NULL)
741 xml_input = def_template;
742 } else if ((i < argc-1) | (xml_input != NULL)) {
743 fprintf(stderr, "%s: only one XML input allowed\n", argv[0]);
744 UsageExit(argv[0]);
745 } else if (!strcmp(argv[i], "-")) {
746 if (used_stdin++) UsageExit(argv[0]);
747 xml_input = stdin_name;
748 } else {
749 xml_input = argv[i];
750 }
751 if ((xml_input == win6_template) & (angle_basis == ABdefault))
752 angle_basis = ABklemsFull;
753 /* wrap it! */
754 return !wrapBSDF(argv[0]);
755 }