--- ray/src/cv/ies2rad.c 1991/01/29 12:19:10 1.3 +++ ray/src/cv/ies2rad.c 2003/06/30 14:59:11 2.19 @@ -1,23 +1,67 @@ -/* Copyright (c) 1990 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: ies2rad.c,v 2.19 2003/06/30 14:59:11 schorsch Exp $"; #endif - /* * Convert IES luminaire data to Radiance description * * 07Apr90 Greg Ward + * + * Fixed correction factor for flat sources 29Oct2001 GW */ #include +#include +#include #include #include "color.h" +#include "paths.h" #define PI 3.14159265358979323846 /* floating comparisons */ #define FTINY 1e-6 #define FEQ(a,b) ((a)<=(b)+FTINY&&(a)>=(b)-FTINY) + /* keywords */ +#define MAGICID "IESNA" +#define LMAGICID 5 +#define FIRSTREV 86 +#define LASTREV 95 + +#define D86 0 /* keywords defined in LM-63-1986 */ + +#define K_TST 0 +#define K_MAN 1 +#define K_LMC 2 +#define K_LMN 3 +#define K_LPC 4 +#define K_LMP 5 +#define K_BAL 6 +#define K_MTC 7 +#define K_OTH 8 +#define K_SCH 9 +#define K_MOR 10 +#define K_BLK 11 +#define K_EBK 12 + +#define D91 ((1L<<13)-1) /* keywords defined in LM-63-1991 */ + +#define K_LMG 13 + +#define D95 ((1L<<14)-1) /* keywords defined in LM-63-1995 */ + +char k_kwd[][20] = {"TEST", "MANUFAC", "LUMCAT", "LUMINAIRE", "LAMPCAT", + "LAMP", "BALLAST", "MAINTCAT", "OTHER", "SEARCH", + "MORE", "BLOCK", "ENDBLOCK", "LUMINOUSGEOMETRY"}; + +long k_defined[] = {D86, D86, D86, D86, D86, D91, D91, D91, D91, D95}; + +int filerev = FIRSTREV; + +#define keymatch(i,s) (k_defined[filerev-FIRSTREV]&1L<<(i) &&\ + k_match(k_kwd[i],s)) + +#define checklamp(s) (!(k_defined[filerev-FIRSTREV]&(1<= argc) { fprintf(stderr, "%s: missing output file specification\n", argv[0]); exit(1); } + if (out2stdout && i != argc-1) + goto needsingle; status = 0; for ( ; i < argc; i++) { tailtrunc(strcpy(outname,filename(argv[i]))); @@ -216,6 +261,9 @@ char *argv[]; status = 1; } exit(status); +needsingle: + fprintf(stderr, "%s: single input file required\n", argv[0]); + exit(1); } @@ -277,7 +325,7 @@ int sep; char * -fullname(path, fname, suffix) /* return full path name */ +fullnam(path, fname, suffix) /* return full path name */ char *path, *fname, *suffix; { if (prefdir != NULL && abspath(prefdir)) @@ -285,7 +333,7 @@ char *path, *fname, *suffix; else if (abspath(fname)) strcpy(stradd(path, fname, 0), suffix); else - libname(stradd(path, libdir, '/'), fname, suffix); + libname(stradd(path, libdir, DIRSEP), fname, suffix); return(path); } @@ -298,7 +346,7 @@ char *path, *fname, *suffix; if (abspath(fname)) strcpy(stradd(path, fname, 0), suffix); else - strcpy(stradd(stradd(path, prefdir, '/'), fname, 0), suffix); + strcpy(stradd(stradd(path, prefdir, DIRSEP), fname, 0), suffix); return(path); } @@ -311,7 +359,7 @@ register char *path; register char *cp; for (cp = path; *path; path++) - if (*path == '/') + if (ISDIRSEP(*path)) cp = path+1; return(cp); } @@ -324,8 +372,10 @@ char *path; register char *p1, *p2; for (p1 = p2 = path; *p2; p2++) - if (*p2 == '/') + if (ISDIRSEP(*p2)) p1 = p2; + if (p1 == path && ISDIRSEP(*p1)) + p1++; *p1 = '\0'; return(path); } @@ -362,6 +412,30 @@ char *s; } +k_match(kwd, hdl) /* header line matches keyword? */ +register char *kwd, *hdl; +{ + if (!*hdl++ == '[') + return(0); + while (islower(*hdl) ? toupper(*hdl) == *kwd++ : *hdl == *kwd++) + if (!*hdl++) + return(0); + return(!*kwd & *hdl == ']'); +} + + +char * +keyargs(hdl) /* return keyword arguments */ +register char *hdl; +{ + while (*hdl && *hdl++ != ']') + ; + while (isspace(*hdl)) + hdl++; + return(hdl); +} + + putheader(out) /* print header */ FILE *out; { @@ -381,9 +455,14 @@ FILE *out; ies2rad(inpname, outname) /* convert IES file */ char *inpname, *outname; { + SRCINFO srcinfo; char buf[MAXLINE], tltid[MAXWORD]; + char geomfile[128]; FILE *inpfp, *outfp; + int lineno = 0; + geomfile[0] = '\0'; + srcinfo.isillum = 0; if (inpname == NULL) { inpname = ""; inpfp = stdin; @@ -391,7 +470,9 @@ char *inpname, *outname; perror(inpname); return(-1); } - if ((outfp = fopen(fullname(buf,outname,T_RAD), "w")) == NULL) { + if (out2stdout) + outfp = stdout; + else if ((outfp = fopen(fullnam(buf,outname,T_RAD), "w")) == NULL) { perror(buf); fclose(inpfp); return(-1); @@ -404,21 +485,37 @@ char *inpname, *outname; blanktrunc(buf); if (!buf[0]) continue; + if (!lineno++ && !strncmp(buf, MAGICID, LMAGICID)) { + filerev = atoi(buf+LMAGICID); + if (filerev < FIRSTREV) + filerev = FIRSTREV; + else if (filerev > LASTREV) + filerev = LASTREV; + } fputs("#<", outfp); fputs(buf, outfp); putc('\n', outfp); - if (lampcolor == NULL) - lampcolor = matchlamp(buf); + if (lampcolor == NULL && checklamp(buf)) + lampcolor = matchlamp( buf[0] == '[' ? + keyargs(buf) : buf ); + if (keymatch(K_LMG, buf)) { /* geometry file */ + strcpy(geomfile, inpname); + strcpy(filename(geomfile), keyargs(buf)); + srcinfo.isillum = 1; + } } if (lampcolor == NULL) { fprintf(stderr, "%s: warning - no lamp type\n", inpname); + fputs("# Unknown lamp type (used default)\n", outfp); lampcolor = defcolor; - } + } else if (lamptype == NULL) + fprintf(outfp,"# CIE(x,y) = (%f,%f)\n# Depreciation = %.1f%%\n", + lampcolor[3], lampcolor[4], 100.*lampcolor[5]); if (feof(inpfp)) { fprintf(stderr, "%s: not in IES format\n", inpname); goto readerr; } - sscanf(buf+TLTSTRLEN, "%s", tltid); + atos(tltid, MAXWORD, buf+TLTSTRLEN); if (inpfp == stdin) buf[0] = '\0'; else @@ -427,17 +524,21 @@ char *inpname, *outname; fprintf(stderr, "%s: bad tilt data\n", inpname); goto readerr; } - if (dosource(inpfp, outfp, tltid, outname) != 0) { + if (dosource(&srcinfo, inpfp, outfp, tltid, outname) != 0) { fprintf(stderr, "%s: bad luminaire data\n", inpname); goto readerr; } - fclose(outfp); fclose(inpfp); + /* cvgeometry closes outfp */ + if (cvgeometry(geomfile, &srcinfo, outname, outfp) != 0) { + fprintf(stderr, "%s: bad geometry file\n", geomfile); + return(-1); + } return(0); readerr: - fclose(outfp); fclose(inpfp); - unlink(fullname(buf,outname,T_RAD)); + fclose(outfp); + unlink(fullnam(buf,outname,T_RAD)); return(-1); } @@ -448,7 +549,7 @@ char *dir, *tltspec, *dfltname, *tltid; { int nangles, tlt_type; double minmax[2]; - char buf[MAXPATH], tltname[MAXWORD]; + char buf[PATH_MAX], tltname[MAXWORD]; FILE *datin, *datout; if (!strcmp(tltspec, TLTNONE)) { @@ -458,10 +559,10 @@ char *dir, *tltspec, *dfltname, *tltid; datin = in; strcpy(tltname, dfltname); } else { - if (tltspec[0] == '/') + if (ISDIRSEP(tltspec[0])) strcpy(buf, tltspec); else - strcpy(stradd(buf, dir, '/'), tltspec); + strcpy(stradd(buf, dir, DIRSEP), tltspec); if ((datin = fopen(buf, "r")) == NULL) { perror(buf); return(-1); @@ -469,19 +570,19 @@ char *dir, *tltspec, *dfltname, *tltid; tailtrunc(strcpy(tltname,filename(tltspec))); } if (datin != NULL) { - if ((datout = fopen(fullname(buf,tltname,T_TLT),"w")) == NULL) { + if ((datout = fopen(fullnam(buf,tltname,T_TLT),"w")) == NULL) { perror(buf); if (datin != in) fclose(datin); return(-1); } - if (fscanf(datin, "%d %d", &tlt_type, &nangles) != 2 + if (!scnint(datin,&tlt_type) || !scnint(datin,&nangles) || cvdata(datin,datout,1,&nangles,1.,minmax) != 0) { fprintf(stderr, "%s: data format error\n", tltspec); fclose(datout); if (datin != in) fclose(datin); - unlink(fullname(buf,tltname,T_TLT)); + unlink(fullnam(buf,tltname,T_TLT)); return(-1); } fclose(datout); @@ -515,25 +616,29 @@ char *dir, *tltspec, *dfltname, *tltid; } -dosource(in, out, mod, name) /* create source and distribution */ +dosource(sinf, in, out, mod, name) /* create source and distribution */ +SRCINFO *sinf; FILE *in, *out; char *mod, *name; { - SHAPE srcshape; - char buf[MAXPATH], id[MAXWORD]; + char buf[PATH_MAX], id[MAXWORD]; FILE *datout; double mult, bfactor, pfactor, width, length, height, wattage; double bounds[2][2]; int nangles[2], pmtype, unitype; double d1; + int doupper, dolower, dosides; - if (fscanf(in, "%*d %*f %lf %d %d %d %d %lf %lf %lf %lf %lf %lf", - &mult, &nangles[0], &nangles[1], &pmtype, &unitype, - &width, &length, &height, &bfactor, &pfactor, - &wattage) != 11) { + if (!isint(getword(in)) || !isflt(getword(in)) || !scnflt(in,&mult) + || !scnint(in,&nangles[0]) || !scnint(in,&nangles[1]) + || !scnint(in,&pmtype) || !scnint(in,&unitype) + || !scnflt(in,&width) || !scnflt(in,&length) + || !scnflt(in,&height) || !scnflt(in,&bfactor) + || !scnflt(in,&pfactor) || !scnflt(in,&wattage)) { fprintf(stderr, "dosource: bad lamp specification\n"); return(-1); } + sinf->mult = multiplier*mult*bfactor*pfactor; if (nangles[0] < 2 || nangles[1] < 1) { fprintf(stderr, "dosource: too few measured angles\n"); return(-1); @@ -543,18 +648,18 @@ char *mod, *name; length *= F_M; height *= F_M; } - if (makeshape(&srcshape, width, length, height) != 0) { + if (makeshape(sinf, width, length, height) != 0) { fprintf(stderr, "dosource: illegal source dimensions"); return(-1); } - if ((datout = fopen(fullname(buf,name,T_DST), "w")) == NULL) { + if ((datout = fopen(fullnam(buf,name,T_DST), "w")) == NULL) { perror(buf); return(-1); } - if (cvdata(in, datout, 2, nangles, 1./683., bounds) != 0) { + if (cvdata(in, datout, 2, nangles, 1./WHTEFFICACY, bounds) != 0) { fprintf(stderr, "dosource: bad distribution data\n"); fclose(datout); - unlink(fullname(buf,name,T_DST)); + unlink(fullnam(buf,name,T_DST)); return(-1); } fclose(datout); @@ -567,11 +672,16 @@ char *mod, *name; else if (pmtype == PM_B) fprintf(out, "5 "); else if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.)) - fprintf(out, "8 "); + fprintf(out, "7 "); else - fprintf(out, "6 "); + fprintf(out, "5 "); + dolower = (bounds[0][0] < 90.); + doupper = (bounds[0][1] > 90.); + dosides = (doupper & dolower && sinf->h > MINDIM); fprintf(out, "%s %s source.cal ", - srcshape.type==SPHERE ? "corr" : "flatcorr", + sinf->type==SPHERE ? "corr" : + !dosides ? "flatcorr" : + sinf->type==DISK ? "cylcorr" : "boxcorr", libname(buf,name,T_DST)); if (pmtype == PM_B) { if (FEQ(bounds[1][0],0.)) @@ -579,77 +689,71 @@ char *mod, *name; else fprintf(out, "srcB_horiz "); fprintf(out, "srcB_vert "); - } else { + } else /* pmtype == PM_A */ { if (nangles[1] >= 2) { d1 = bounds[1][1] - bounds[1][0]; if (d1 <= 90.+FTINY) fprintf(out, "src_phi4 "); - else if (d1 <= 180.+FTINY) - fprintf(out, "src_phi2 "); - else + else if (d1 <= 180.+FTINY) { + if (FEQ(bounds[1][0],90.)) + fprintf(out, "src_phi2+90 "); + else + fprintf(out, "src_phi2 "); + } else fprintf(out, "src_phi "); - fprintf(out, "src_theta -my "); + fprintf(out, "src_theta "); if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.)) fprintf(out, "-rz -90 "); } else fprintf(out, "src_theta "); } - fprintf(out, "\n0\n1 %g\n", multiplier*mult*bfactor*pfactor); - if (putsource(&srcshape, out, id, filename(name), - bounds[0][0]<90., bounds[0][1]>90.) != 0) + if (!dosides || sinf->type == SPHERE) + fprintf(out, "\n0\n1 %g\n", sinf->mult/sinf->area); + else if (sinf->type == DISK) + fprintf(out, "\n0\n3 %g %g %g\n", sinf->mult, + sinf->w, sinf->h); + else + fprintf(out, "\n0\n4 %g %g %g %g\n", sinf->mult, + sinf->l, sinf->w, sinf->h); + if (putsource(sinf, out, id, filename(name), + dolower, doupper, dosides) != 0) return(-1); return(0); } -putsource(shp, fp, mod, name, dolower, doupper) /* put out source */ -SHAPE *shp; +putsource(shp, fp, mod, name, dolower, doupper, dosides) /* put out source */ +SRCINFO *shp; FILE *fp; char *mod, *name; int dolower, doupper; { - char buf[MAXWORD]; + char lname[MAXWORD]; - fprintf(fp, "\n%s %s %s_light\n", mod, - illumrad>=MINDIM/2. ? "illum" : "light", - name); + strcat(strcpy(lname, name), "_light"); + fprintf(fp, "\n%s %s %s\n", mod, + shp->isillum ? "illum" : "light", lname); fprintf(fp, "0\n0\n3 %g %g %g\n", - lampcolor[0]/shp->area, - lampcolor[1]/shp->area, - lampcolor[2]/shp->area); - if (doupper && dolower && shp->type != SPHERE && shp->h > MINDIM) { - fprintf(fp, "\n%s glow %s_glow\n", mod, name); - fprintf(fp, "0\n0\n4 %g %g %g 0\n", - lampcolor[0]/shp->area, - lampcolor[1]/shp->area, - lampcolor[2]/shp->area); - } + lampcolor[0], lampcolor[1], lampcolor[2]); switch (shp->type) { case RECT: - strcat(strcpy(buf, name), "_light"); if (dolower) - putrectsrc(shp, fp, buf, name, 0); + putrectsrc(shp, fp, lname, name, 0); if (doupper) - putrectsrc(shp, fp, buf, name, 1); - if (doupper && dolower && shp->h > MINDIM) { - strcat(strcpy(buf, name), "_glow"); - putsides(shp, fp, buf, name); - } + putrectsrc(shp, fp, lname, name, 1); + if (dosides) + putsides(shp, fp, lname, name); break; case DISK: - strcat(strcpy(buf, name), "_light"); if (dolower) - putdisksrc(shp, fp, buf, name, 0); + putdisksrc(shp, fp, lname, name, 0); if (doupper) - putdisksrc(shp, fp, buf, name, 1); - if (doupper && dolower && shp->h > MINDIM) { - strcat(strcpy(buf, name), "_glow"); - putcyl(shp, fp, buf, name); - } + putdisksrc(shp, fp, lname, name, 1); + if (dosides) + putcyl(shp, fp, lname, name); break; case SPHERE: - strcat(strcpy(buf, name), "_light"); - putspheresrc(shp, fp, buf, name); + putspheresrc(shp, fp, lname, name); break; } return(0); @@ -657,12 +761,13 @@ int dolower, doupper; makeshape(shp, width, length, height) /* make source shape */ -register SHAPE *shp; +register SRCINFO *shp; double width, length, height; { - if (illumrad >= MINDIM/2.) { + if (illumrad/meters2out >= MINDIM/2.) { + shp->isillum = 1; shp->type = SPHERE; - shp->w = shp->l = shp->h = 2.*illumrad; + shp->w = shp->l = shp->h = 2.*illumrad / meters2out; } else if (width < MINDIM) { width = -width; if (width < MINDIM) { @@ -705,7 +810,7 @@ double width, length, height; putrectsrc(shp, fp, mod, name, up) /* rectangular source */ -SHAPE *shp; +SRCINFO *shp; FILE *fp; char *mod, *name; int up; @@ -718,7 +823,7 @@ int up; putsides(shp, fp, mod, name) /* put out sides of box */ -register SHAPE *shp; +register SRCINFO *shp; FILE *fp; char *mod, *name; { @@ -730,7 +835,7 @@ char *mod, *name; putrect(shp, fp, mod, name, suffix, a, b, c, d) /* put out a rectangle */ -SHAPE *shp; +SRCINFO *shp; FILE *fp; char *mod, *name, *suffix; int a, b, c, d; @@ -744,7 +849,7 @@ int a, b, c, d; putpoint(shp, fp, p) /* put out a point */ -register SHAPE *shp; +register SRCINFO *shp; FILE *fp; int p; { @@ -758,7 +863,7 @@ int p; putdisksrc(shp, fp, mod, name, up) /* put out a disk source */ -register SHAPE *shp; +register SRCINFO *shp; FILE *fp; char *mod, *name; int up; @@ -780,7 +885,7 @@ int up; putcyl(shp, fp, mod, name) /* put out a cylinder */ -register SHAPE *shp; +register SRCINFO *shp; FILE *fp; char *mod, *name; { @@ -793,7 +898,7 @@ char *mod, *name; putspheresrc(shp, fp, mod, name) /* put out a sphere source */ -SHAPE *shp; +SRCINFO *shp; FILE *fp; char *mod, *name; { @@ -807,7 +912,7 @@ FILE *in, *out; int ndim, npts[]; double mult, lim[][2]; { - register double *pt[4]; + double *pt[4]; register int i, j; double val; int total; @@ -823,7 +928,8 @@ double mult, lim[][2]; for (i = 0; i < ndim; i++) { pt[i] = (double *)malloc(npts[i]*sizeof(double)); for (j = 0; j < npts[i]; j++) - fscanf(in, "%lf", &pt[i][j]); + if (!scnflt(in, &pt[i][j])) + return(-1); if (lim != NULL) { lim[i][0] = pt[i][0]; lim[i][1] = pt[i][npts[i]-1]; @@ -849,15 +955,122 @@ double mult, lim[][2]; putc('\n', out); } } - free((char *)pt[i]); + free((void *)pt[i]); } for (i = 0; i < total; i++) { if (i%4 == 0) putc('\n', out); - if (fscanf(in, "%lf", &val) != 1) + if (!scnflt(in, &val)) return(-1); fprintf(out, "\t%g", val*mult); } putc('\n', out); + return(0); +} + + +char * +getword(fp) /* scan a word from fp */ +register FILE *fp; +{ + static char wrd[MAXWORD]; + register char *cp; + register int c; + + while (isspace(c=getc(fp))) + ; + for (cp = wrd; c != EOF && cp < wrd+MAXWORD-1; + *cp++ = c, c = getc(fp)) + if (isspace(c) || c == ',') { + while (isspace(c)) + c = getc(fp); + if (c != EOF & c != ',') + ungetc(c, fp); + *cp = '\0'; + return(wrd); + } + *cp = '\0'; + return(cp > wrd ? wrd : NULL); +} + + +cvtint(ip, wrd) /* convert a word to an integer */ +int *ip; +char *wrd; +{ + if (wrd == NULL || !isint(wrd)) + return(0); + *ip = atoi(wrd); + return(1); +} + + +cvtflt(rp, wrd) /* convert a word to a double */ +double *rp; +char *wrd; +{ + if (wrd == NULL || !isflt(wrd)) + return(0); + *rp = atof(wrd); + return(1); +} + + +cvgeometry(inpname, sinf, outname, outfp) +char *inpname; +register SRCINFO *sinf; +char *outname; +FILE *outfp; /* close output file upon return */ +{ + char buf[256]; + register char *cp; + + if (inpname == NULL || !inpname[0]) { /* no geometry file */ + fclose(outfp); + return(0); + } + putc('\n', outfp); + strcpy(buf, "mgf2rad "); /* build mgf2rad command */ + cp = buf+8; + if (!FEQ(sinf->mult, 1.0)) { + sprintf(cp, "-m %f ", sinf->mult); + cp += strlen(cp); + } + sprintf(cp, "-g %f %s ", + sqrt(sinf->w*sinf->w + sinf->h*sinf->h + sinf->l*sinf->l), + inpname); + cp += strlen(cp); + if (instantiate) { /* instantiate octree */ + strcpy(cp, "| oconv - > "); + cp += 12; + fullnam(cp,outname,T_OCT); + if (fdate(inpname) > fdate(outname) && + system(buf)) { /* create octree */ + fclose(outfp); + return(-1); + } + fprintf(outfp, "void instance %s_inst\n", outname); + if (!FEQ(meters2out, 1.0)) + fprintf(outfp, "3 %s -s %f\n", + libname(buf,outname,T_OCT), + meters2out); + else + fprintf(outfp, "1 %s\n", libname(buf,outname,T_OCT)); + fprintf(outfp, "0\n0\n"); + fclose(outfp); + } else { /* else append to luminaire file */ + if (!FEQ(meters2out, 1.0)) { /* apply scalefactor */ + sprintf(cp, "| xform -s %f ", meters2out); + cp += strlen(cp); + } + if (!out2stdout) { + fclose(outfp); + strcpy(cp, ">> "); /* append works for DOS? */ + cp += 3; + fullnam(cp,outname,T_RAD); + } + if (system(buf)) + return(-1); + } return(0); }