Back to index

radiance  4R0+20100331
ies2rad.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: ies2rad.c,v 2.25 2008/01/24 23:15:46 greg Exp $";
00003 #endif
00004 /*
00005  * Convert IES luminaire data to Radiance description
00006  *
00007  *     07Apr90              Greg Ward
00008  *
00009  *  Fixed correction factor for flat sources 29Oct2001 GW
00010  */
00011 
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <math.h>
00015 #include <sys/types.h>
00016 #include <ctype.h>
00017 
00018 #include "rtio.h"
00019 #include "color.h"
00020 #include "paths.h"
00021 
00022 #define PI           3.14159265358979323846
00023                                    /* floating comparisons */
00024 #define FTINY        1e-6
00025 #define FEQ(a,b)     ((a)<=(b)+FTINY&&(a)>=(b)-FTINY)
00026                                    /* keywords */
00027 #define MAGICID             "IESNA"
00028 #define LMAGICID     5
00029 #define FIRSTREV     86
00030 #define LASTREV             95
00031 
00032 #define D86          0             /* keywords defined in LM-63-1986 */
00033 
00034 #define K_TST        0
00035 #define K_MAN        1
00036 #define K_LMC        2
00037 #define K_LMN        3
00038 #define K_LPC        4
00039 #define K_LMP        5
00040 #define K_BAL        6
00041 #define K_MTC        7
00042 #define K_OTH        8
00043 #define K_SCH        9
00044 #define K_MOR        10
00045 #define K_BLK        11
00046 #define K_EBK        12
00047 
00048 #define D91          ((1L<<13)-1)  /* keywords defined in LM-63-1991 */
00049 
00050 #define K_LMG        13
00051 
00052 #define D95          ((1L<<14)-1)  /* keywords defined in LM-63-1995 */
00053 
00054 char   k_kwd[][20] = {"TEST", "MANUFAC", "LUMCAT", "LUMINAIRE", "LAMPCAT",
00055                      "LAMP", "BALLAST", "MAINTCAT", "OTHER", "SEARCH",
00056                      "MORE", "BLOCK", "ENDBLOCK", "LUMINOUSGEOMETRY"};
00057 
00058 long k_defined[] = {D86, D86, D86, D86, D86, D91, D91, D91, D91, D95};
00059 
00060 int    filerev = FIRSTREV;
00061 
00062 #define keymatch(i,s)       (k_defined[filerev-FIRSTREV]&1L<<(i) &&\
00063                             k_match(k_kwd[i],s))
00064 
00065 #define checklamp(s) (!(k_defined[filerev-FIRSTREV]&(1<<K_LMP|1<<K_LPC)) ||\
00066                             keymatch(K_LMP,s) || keymatch(K_LPC,s))
00067 
00068                                    /* tilt specs */
00069 #define TLTSTR              "TILT="
00070 #define TLTSTRLEN    5
00071 #define TLTNONE             "NONE"
00072 #define TLTINCL             "INCLUDE"
00073 #define TLT_VERT     1
00074 #define TLT_H0              2
00075 #define TLT_H90             3
00076                                    /* photometric types */
00077 #define PM_C         1
00078 #define PM_B         2
00079 #define PM_A         3
00080                                    /* unit types */
00081 #define U_FEET              1
00082 #define U_METERS     2
00083                                    /* string lengths */
00084 #define MAXLINE             132
00085 #define RMAXWORD     76
00086                                    /* file types */
00087 #define T_RAD        ".rad"
00088 #define T_DST        ".dat"
00089 #define T_TLT        "%.dat"
00090 #define T_OCT        ".oct"
00091                                    /* shape types */
00092 #define RECT         1
00093 #define DISK         2
00094 #define SPHERE              3
00095 
00096 #define MINDIM              .001          /* minimum dimension (point source) */
00097 
00098 #define F_M          .3048         /* feet to meters */
00099 
00100 #define abspath(p)   (ISDIRSEP((p)[0]) || (p)[0] == '.')
00101 
00102 static char   default_name[] = "default";
00103 
00104 char   *libdir = NULL;                    /* library directory location */
00105 char   *prefdir = NULL;            /* subdirectory */
00106 char   *lampdat = "lamp.tab";             /* lamp data file */
00107 
00108 double meters2out = 1.0;           /* conversion from meters to output */
00109 char   *lamptype = NULL;           /* selected lamp type */
00110 char   *deflamp = NULL;            /* default lamp type */
00111 float  defcolor[3] = {1.,1.,1.};   /* default lamp color */
00112 float  *lampcolor = defcolor;             /* pointer to current lamp color */
00113 double multiplier = 1.0;           /* multiplier for all light sources */
00114 char   units[64] = "meters";              /* output units */
00115 int    out2stdout = 0;                    /* put out to stdout r.t. file */
00116 int    instantiate = 0;            /* instantiate geometry */
00117 double illumrad = 0.0;                    /* radius for illum sphere */
00118 
00119 typedef struct {
00120        int    isillum;                    /* do as illum */
00121        int    type;                       /* RECT, DISK, SPHERE */
00122        double mult;                       /* candela multiplier */
00123        double w, l, h;                    /* width, length, height */
00124        double area;                       /* max. projected area */
00125 } SRCINFO;                         /* a source shape (units=meters) */
00126 
00127 int    gargc;                      /* global argc (minus filenames) */
00128 char   **gargv;                    /* global argv */
00129 
00130 
00131 #define scnint(fp,ip)       cvtint(ip,getword(fp))
00132 #define scnflt(fp,rp)       cvtflt(rp,getword(fp))
00133 #define isint        isflt                /* IES allows real as integer */
00134 
00135 
00136 static int ies2rad(char *inpname, char *outname);
00137 static void initlamps(void);
00138 static int dosource(SRCINFO *sinf, FILE *in, FILE *out, char *mod, char *name);
00139 static int dotilt(FILE *in, FILE *out, char *dir, char *tltspec,
00140               char *dfltname, char *tltid);
00141 static int cvgeometry(char *inpname, SRCINFO *sinf, char *outname, FILE *outfp);
00142 static int cvtint(int *ip, char *wrd);
00143 static int cvdata(FILE *in, FILE *out, int ndim, int npts[], double mult,
00144               double lim[][2]);
00145 static int cvtflt(double *rp, char *wrd);
00146 static int makeshape(SRCINFO *shp, double width, double length, double height);
00147 static int putsource(SRCINFO *shp, FILE *fp, char *mod, char *name,
00148               int dolower, int doupper, int dosides);
00149 static void putrectsrc(SRCINFO *shp, FILE *fp, char *mod, char *name, int up);
00150 static void putsides(SRCINFO *shp, FILE *fp, char *mod, char *name);
00151 static void putdisksrc(SRCINFO *shp, FILE *fp, char *mod, char *name, int up);
00152 static void putspheresrc(SRCINFO *shp, FILE *fp, char *mod, char *name);
00153 static void putrect(SRCINFO *shp, FILE *fp, char *mod, char *name, char *suffix,
00154               int a, int b, int c, int d);
00155 static void putpoint(SRCINFO *shp, FILE *fp, int p);
00156 static void putcyl(SRCINFO *shp, FILE *fp, char *mod, char *name);
00157 static char * tailtrunc(char *name);
00158 static char * filename(char *path);
00159 static char * libname(char *path, char *fname, char *suffix);
00160 static char * getword(FILE *fp);
00161 static char * fullnam(char *path, char *fname, char *suffix);
00162 
00163 
00164 int
00165 main(
00166        int    argc,
00167        char   *argv[]
00168 )
00169 {
00170        char   *outfile = NULL;
00171        int    status;
00172        char   outname[RMAXWORD];
00173        double d1;
00174        int    i;
00175        
00176        for (i = 1; i < argc && argv[i][0] == '-'; i++)
00177               switch (argv[i][1]) {
00178               case 'd':            /* dimensions */
00179                      if (argv[i][2] == '\0')
00180                             goto badopt;
00181                      if (argv[i][3] == '\0')
00182                             d1 = 1.0;
00183                      else if (argv[i][3] == '/') {
00184                             d1 = atof(argv[i]+4);
00185                             if (d1 <= FTINY)
00186                                    goto badopt;
00187                      } else
00188                             goto badopt;
00189                      switch (argv[i][2]) {
00190                      case 'c':            /* centimeters */
00191                             if (FEQ(d1,10.))
00192                                    strcpy(units,"millimeters");
00193                             else {
00194                                    strcpy(units,"centimeters");
00195                                    strcat(units,argv[i]+3);
00196                             }
00197                             meters2out = 100.*d1;
00198                             break;
00199                      case 'm':            /* meters */
00200                             if (FEQ(d1,1000.))
00201                                    strcpy(units,"millimeters");
00202                             else if (FEQ(d1,100.))
00203                                    strcpy(units,"centimeters");
00204                             else {
00205                                    strcpy(units,"meters");
00206                                    strcat(units,argv[i]+3);
00207                             }
00208                             meters2out = d1;
00209                             break;
00210                      case 'i':            /* inches */
00211                             strcpy(units,"inches");
00212                             strcat(units,argv[i]+3);
00213                             meters2out = d1*(12./F_M);
00214                             break;
00215                      case 'f':            /* feet */
00216                             if (FEQ(d1,12.))
00217                                    strcpy(units,"inches");
00218                             else {
00219                                    strcpy(units,"feet");
00220                                    strcat(units,argv[i]+3);
00221                             }
00222                             meters2out = d1/F_M;
00223                             break;
00224                      default:
00225                             goto badopt;
00226                      }
00227                      break;
00228               case 'l':            /* library directory */
00229                      libdir = argv[++i];
00230                      break;
00231               case 'p':            /* prefix subdirectory */
00232                      prefdir = argv[++i];
00233                      break;
00234               case 'f':            /* lamp data file */
00235                      lampdat = argv[++i];
00236                      break;
00237               case 'o':            /* output file root name */
00238                      outfile = argv[++i];
00239                      break;
00240               case 's':            /* output to stdout */
00241                      out2stdout = !out2stdout;
00242                      break;
00243               case 'i':            /* illum */
00244                      illumrad = atof(argv[++i]);
00245                      break;
00246               case 'g':            /* instatiate geometry? */
00247                      instantiate = !instantiate;
00248                      break;
00249               case 't':            /* override lamp type */
00250                      lamptype = argv[++i];
00251                      break;
00252               case 'u':            /* default lamp type */
00253                      deflamp = argv[++i];
00254                      break;
00255               case 'c':            /* default lamp color */
00256                      defcolor[0] = atof(argv[++i]);
00257                      defcolor[1] = atof(argv[++i]);
00258                      defcolor[2] = atof(argv[++i]);
00259                      break;
00260               case 'm':            /* multiplier */
00261                      multiplier = atof(argv[++i]);
00262                      break;
00263               default:
00264               badopt:
00265                      fprintf(stderr, "%s: bad option: %s\n",
00266                                    argv[0], argv[i]);
00267                      exit(1);
00268               }
00269        gargc = i;
00270        gargv = argv;
00271        initlamps();                /* get lamp data (if needed) */
00272                                    /* convert ies file(s) */
00273        if (outfile != NULL) {
00274               if (i == argc)
00275                      exit(ies2rad(NULL, outfile) == 0 ? 0 : 1);
00276               else if (i == argc-1)
00277                      exit(ies2rad(argv[i], outfile) == 0 ? 0 : 1);
00278               else
00279                      goto needsingle;
00280        } else if (i >= argc) {
00281               fprintf(stderr, "%s: missing output file specification\n",
00282                             argv[0]);
00283               exit(1);
00284        }
00285        if (out2stdout && i != argc-1)
00286               goto needsingle;
00287        status = 0;
00288        for ( ; i < argc; i++) {
00289               tailtrunc(strcpy(outname,filename(argv[i])));
00290               if (ies2rad(argv[i], outname) != 0)
00291                      status = 1;
00292        }
00293        exit(status);
00294 needsingle:
00295        fprintf(stderr, "%s: single input file required\n", argv[0]);
00296        exit(1);
00297 }
00298 
00299 void
00300 initlamps(void)                           /* set up lamps */
00301 {
00302        float  *lcol;
00303        int    status;
00304 
00305        if (lamptype != NULL && !strcmp(lamptype, default_name) &&
00306                      deflamp == NULL)
00307               return;                            /* no need for data */
00308                                           /* else load file */
00309        if ((status = loadlamps(lampdat)) < 0)
00310               exit(1);
00311        if (status == 0) {
00312               fprintf(stderr, "%s: warning - no lamp data\n", lampdat);
00313               lamptype = default_name;
00314               return;
00315        }
00316        if (deflamp != NULL) {                    /* match default type */
00317               if ((lcol = matchlamp(deflamp)) == NULL)
00318                      fprintf(stderr,
00319                             "%s: warning - unknown default lamp type\n",
00320                                    deflamp);
00321               else
00322                      copycolor(defcolor, lcol);
00323        }
00324        if (lamptype != NULL) {                   /* match selected type */
00325               if (strcmp(lamptype, default_name)) {
00326                      if ((lcol = matchlamp(lamptype)) == NULL) {
00327                             fprintf(stderr,
00328                                    "%s: warning - unknown lamp type\n",
00329                                           lamptype);
00330                             lamptype = default_name;
00331                      } else
00332                             copycolor(defcolor, lcol);
00333               }
00334               freelamps();                /* all done with data */
00335        }
00336                                           /* else keep lamp data */
00337 }
00338 
00339 
00340 char *
00341 stradd(                     /* add a string at dst */
00342        register char *dst,
00343        register char *src,
00344        int    sep
00345 )
00346 {
00347        if (src && *src) {
00348               do
00349                      *dst++ = *src++;
00350               while (*src);
00351               if (sep && dst[-1] != sep)
00352                      *dst++ = sep;
00353        }
00354        *dst = '\0';
00355        return(dst);
00356 }
00357 
00358 
00359 char *
00360 fullnam(             /* return full path name */
00361        char   *path,
00362        char   *fname,
00363        char   *suffix
00364 )
00365 {
00366        if (prefdir != NULL && abspath(prefdir))
00367               libname(path, fname, suffix);
00368        else if (abspath(fname))
00369               strcpy(stradd(path, fname, 0), suffix);
00370        else
00371               libname(stradd(path, libdir, DIRSEP), fname, suffix);
00372 
00373        return(path);
00374 }
00375 
00376 
00377 char *
00378 libname(             /* return library relative name */
00379        char   *path,
00380        char   *fname,
00381        char   *suffix
00382 )
00383 {
00384        if (abspath(fname))
00385               strcpy(stradd(path, fname, 0), suffix);
00386        else
00387               strcpy(stradd(stradd(path, prefdir, DIRSEP), fname, 0), suffix);
00388 
00389        return(path);
00390 }
00391 
00392 
00393 char *
00394 filename(                   /* get final component of pathname */
00395        register char *path
00396 )
00397 {
00398        register char *cp;
00399 
00400        for (cp = path; *path; path++)
00401               if (ISDIRSEP(*path))
00402                      cp = path+1;
00403        return(cp);
00404 }
00405 
00406 
00407 char *
00408 filetrunc(                         /* truncate filename at end of path */
00409        char   *path
00410 )
00411 {
00412        register char *p1, *p2;
00413 
00414        for (p1 = p2 = path; *p2; p2++)
00415               if (ISDIRSEP(*p2))
00416                      p1 = p2;
00417        if (p1 == path && ISDIRSEP(*p1))
00418               p1++;
00419        *p1 = '\0';
00420        return(path);
00421 }
00422 
00423 
00424 char *
00425 tailtrunc(                         /* truncate tail of filename */
00426        char   *name
00427 )
00428 {
00429        register char *p1, *p2;
00430 
00431        for (p1 = filename(name); *p1 == '.'; p1++)
00432               ;
00433        p2 = NULL;
00434        for ( ; *p1; p1++)
00435               if (*p1 == '.')
00436                      p2 = p1;
00437        if (p2 != NULL)
00438               *p2 = '\0';
00439        return(name);
00440 }
00441 
00442 
00443 void
00444 blanktrunc(                        /* truncate spaces at end of line */
00445        char   *s
00446 )
00447 {
00448        register char *cp;
00449 
00450        for (cp = s; *cp; cp++)
00451               ;
00452        while (cp-- > s && isspace(*cp))
00453               ;
00454        *++cp = '\0';
00455 }
00456 
00457 
00458 int
00459 k_match(                    /* header line matches keyword? */
00460        register char *kwd,
00461        register char *hdl
00462 )
00463 {
00464        if (!*hdl++ == '[')
00465               return(0);
00466        while (islower(*hdl) ? toupper(*hdl) == *kwd++ : *hdl == *kwd++)
00467               if (!*hdl++)
00468                      return(0);
00469        return((!*kwd) & (*hdl == ']'));
00470 }
00471 
00472 
00473 char *
00474 keyargs(                           /* return keyword arguments */
00475        register char *hdl
00476 )
00477 {
00478        while (*hdl && *hdl++ != ']')
00479               ;
00480        while (isspace(*hdl))
00481               hdl++;
00482        return(hdl);
00483 }
00484 
00485 
00486 void
00487 putheader(                         /* print header */
00488        FILE   *out
00489 )
00490 {
00491        register int  i;
00492        
00493        putc('#', out);
00494        for (i = 0; i < gargc; i++) {
00495               putc(' ', out);
00496               fputs(gargv[i], out);
00497        }
00498        fputs("\n# Dimensions in ", out);
00499        fputs(units, out);
00500        putc('\n', out);
00501 }
00502 
00503 
00504 int
00505 ies2rad(             /* convert IES file */
00506        char   *inpname,
00507        char   *outname
00508 )
00509 {
00510        SRCINFO       srcinfo;
00511        char   buf[MAXLINE], tltid[RMAXWORD];
00512        char   geomfile[128];
00513        FILE   *inpfp, *outfp;
00514        int    lineno = 0;
00515 
00516        geomfile[0] = '\0';
00517        srcinfo.isillum = 0;
00518        if (inpname == NULL) {
00519               inpname = "<stdin>";
00520               inpfp = stdin;
00521        } else if ((inpfp = fopen(inpname, "r")) == NULL) {
00522               perror(inpname);
00523               return(-1);
00524        }
00525        if (out2stdout)
00526               outfp = stdout;
00527        else if ((outfp = fopen(fullnam(buf,outname,T_RAD), "w")) == NULL) {
00528               perror(buf);
00529               fclose(inpfp);
00530               return(-1);
00531        }
00532        putheader(outfp);
00533        if (lamptype == NULL)
00534               lampcolor = NULL;
00535        while (fgets(buf,sizeof(buf),inpfp) != NULL
00536                      && strncmp(buf,TLTSTR,TLTSTRLEN)) {
00537               blanktrunc(buf);
00538               if (!buf[0])
00539                      continue;
00540               if (!lineno++ && !strncmp(buf, MAGICID, LMAGICID)) {
00541                      filerev = atoi(buf+LMAGICID);
00542                      if (filerev < FIRSTREV)
00543                             filerev = FIRSTREV;
00544                      else if (filerev > LASTREV)
00545                             filerev = LASTREV;
00546               }
00547               fputs("#<", outfp);
00548               fputs(buf, outfp);
00549               putc('\n', outfp);
00550               if (lampcolor == NULL && checklamp(buf))
00551                      lampcolor = matchlamp( buf[0] == '[' ?
00552                                           keyargs(buf) : buf );
00553               if (keymatch(K_LMG, buf)) {        /* geometry file */
00554                      strcpy(geomfile, inpname);
00555                      strcpy(filename(geomfile), keyargs(buf));
00556                      srcinfo.isillum = 1;
00557               }
00558        }
00559        if (lampcolor == NULL) {
00560               fprintf(stderr, "%s: warning - no lamp type\n", inpname);
00561               fputs("# Unknown lamp type (used default)\n", outfp);
00562               lampcolor = defcolor;
00563        } else if (lamptype == NULL)
00564               fprintf(outfp,"# CIE(x,y) = (%f,%f)\n# Depreciation = %.1f%%\n",
00565                             lampcolor[3], lampcolor[4], 100.*lampcolor[5]);
00566        if (feof(inpfp)) {
00567               fprintf(stderr, "%s: not in IES format\n", inpname);
00568               goto readerr;
00569        }
00570        atos(tltid, RMAXWORD, buf+TLTSTRLEN);
00571        if (inpfp == stdin)
00572               buf[0] = '\0';
00573        else
00574               filetrunc(strcpy(buf, inpname));
00575        if (dotilt(inpfp, outfp, buf, tltid, outname, tltid) != 0) {
00576               fprintf(stderr, "%s: bad tilt data\n", inpname);
00577               goto readerr;
00578        }
00579        if (dosource(&srcinfo, inpfp, outfp, tltid, outname) != 0) {
00580               fprintf(stderr, "%s: bad luminaire data\n", inpname);
00581               goto readerr;
00582        }
00583        fclose(inpfp);
00584                                    /* cvgeometry closes outfp */
00585        if (cvgeometry(geomfile, &srcinfo, outname, outfp) != 0) {
00586               fprintf(stderr, "%s: bad geometry file\n", geomfile);
00587               return(-1);
00588        }
00589        return(0);
00590 readerr:
00591        fclose(inpfp);
00592        fclose(outfp);
00593        unlink(fullnam(buf,outname,T_RAD));
00594        return(-1);
00595 }
00596 
00597 
00598 int
00599 dotilt(       /* convert tilt data */
00600        FILE   *in,
00601        FILE   *out,
00602        char   *dir,
00603        char   *tltspec,
00604        char   *dfltname,
00605        char   *tltid
00606 )
00607 {
00608        int    nangles, tlt_type;
00609        double minmax[1][2];
00610        char   buf[PATH_MAX], tltname[RMAXWORD];
00611        FILE   *datin, *datout;
00612 
00613        if (!strcmp(tltspec, TLTNONE)) {
00614               datin = NULL;
00615               strcpy(tltid, "void");
00616        } else if (!strcmp(tltspec, TLTINCL)) {
00617               datin = in;
00618               strcpy(tltname, dfltname);
00619        } else {
00620               if (ISDIRSEP(tltspec[0]))
00621                      strcpy(buf, tltspec);
00622               else
00623                      strcpy(stradd(buf, dir, DIRSEP), tltspec);
00624               if ((datin = fopen(buf, "r")) == NULL) {
00625                      perror(buf);
00626                      return(-1);
00627               }
00628               tailtrunc(strcpy(tltname,filename(tltspec)));
00629        }
00630        if (datin != NULL) {
00631               if ((datout = fopen(fullnam(buf,tltname,T_TLT),"w")) == NULL) {
00632                      perror(buf);
00633                      if (datin != in)
00634                             fclose(datin);
00635                      return(-1);
00636               }
00637               if (!scnint(datin,&tlt_type) || !scnint(datin,&nangles)
00638                      || cvdata(datin,datout,1,&nangles,1.,minmax) != 0) {
00639                      fprintf(stderr, "%s: data format error\n", tltspec);
00640                      fclose(datout);
00641                      if (datin != in)
00642                             fclose(datin);
00643                      unlink(fullnam(buf,tltname,T_TLT));
00644                      return(-1);
00645               }
00646               fclose(datout);
00647               if (datin != in)
00648                      fclose(datin);
00649               strcat(strcpy(tltid, filename(tltname)), "_tilt");
00650               fprintf(out, "\nvoid brightdata %s\n", tltid);
00651               libname(buf,tltname,T_TLT);
00652               switch (tlt_type) {
00653               case TLT_VERT:                     /* vertical */
00654                      fprintf(out, "4 noop %s tilt.cal %s\n", buf,
00655                             minmax[0][1]>90.+FTINY ? "tilt_ang" : "tilt_ang2");
00656                      break;
00657               case TLT_H0:                /* horiz. in 0 deg. plane */
00658                      fprintf(out, "6 noop %s tilt.cal %s -rz 90\n", buf,
00659                      minmax[0][1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
00660                      break;
00661               case TLT_H90:
00662                      fprintf(out, "4 noop %s tilt.cal %s\n", buf,
00663                      minmax[0][1]>90.+FTINY ? "tilt_xang" : "tilt_xang2");
00664                      break;
00665               default:
00666                      fprintf(stderr,
00667                             "%s: illegal lamp to luminaire geometry (%d)\n",
00668                             tltspec, tlt_type);
00669                      return(-1);
00670               }
00671               fprintf(out, "0\n0\n");
00672        }
00673        return(0);
00674 }
00675 
00676 
00677 int
00678 dosource(     /* create source and distribution */
00679        SRCINFO       *sinf,
00680        FILE   *in,
00681        FILE   *out,
00682        char   *mod,
00683        char   *name
00684 )
00685 {
00686        char   buf[PATH_MAX], id[RMAXWORD];
00687        FILE   *datout;
00688        double mult, bfactor, pfactor, width, length, height, wattage;
00689        double bounds[2][2];
00690        int    nangles[2], pmtype, unitype;
00691        double d1;
00692        int    doupper, dolower, dosides; 
00693 
00694        if (!isint(getword(in)) || !isflt(getword(in)) || !scnflt(in,&mult)
00695                      || !scnint(in,&nangles[0]) || !scnint(in,&nangles[1])
00696                      || !scnint(in,&pmtype) || !scnint(in,&unitype)
00697                      || !scnflt(in,&width) || !scnflt(in,&length)
00698                      || !scnflt(in,&height) || !scnflt(in,&bfactor)
00699                      || !scnflt(in,&pfactor) || !scnflt(in,&wattage)) {
00700               fprintf(stderr, "dosource: bad lamp specification\n");
00701               return(-1);
00702        }
00703        if (pmtype != PM_C && pmtype != PM_B) {
00704               fprintf(stderr, "dosource: unsupported photometric type (%d)\n",
00705                             pmtype);
00706               return(-1);
00707        }
00708        sinf->mult = multiplier*mult*bfactor*pfactor;
00709        if (nangles[0] < 2 || nangles[1] < 1) {
00710               fprintf(stderr, "dosource: too few measured angles\n");
00711               return(-1);
00712        }
00713        if (unitype == U_FEET) {
00714               width *= F_M;
00715               length *= F_M;
00716               height *= F_M;
00717        }
00718        if (makeshape(sinf, width, length, height) != 0) {
00719               fprintf(stderr, "dosource: illegal source dimensions");
00720               return(-1);
00721        }
00722        if ((datout = fopen(fullnam(buf,name,T_DST), "w")) == NULL) {
00723               perror(buf);
00724               return(-1);
00725        }
00726        if (cvdata(in, datout, 2, nangles, 1./WHTEFFICACY, bounds) != 0) {
00727               fprintf(stderr, "dosource: bad distribution data\n");
00728               fclose(datout);
00729               unlink(fullnam(buf,name,T_DST));
00730               return(-1);
00731        }
00732        fclose(datout);
00733        fprintf(out, "# %g watt luminaire, lamp*ballast factor = %g\n",
00734                      wattage, bfactor*pfactor);
00735        strcat(strcpy(id, filename(name)), "_dist");
00736        fprintf(out, "\n%s brightdata %s\n", mod, id);
00737        if (nangles[1] < 2)
00738               fprintf(out, "4 ");
00739        else if (pmtype == PM_B)
00740               fprintf(out, "5 ");
00741        else if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.))
00742               fprintf(out, "7 ");
00743        else
00744               fprintf(out, "5 ");
00745        dolower = (bounds[0][0] < 90.-FTINY);
00746        doupper = (bounds[0][1] > 90.+FTINY);
00747        dosides = (doupper & dolower && sinf->h > MINDIM);
00748        fprintf(out, "%s %s source.cal ",
00749                      sinf->type==SPHERE ? "corr" :
00750                      !dosides ? "flatcorr" :
00751                      sinf->type==DISK ? "cylcorr" : "boxcorr",
00752                      libname(buf,name,T_DST));
00753        if (pmtype == PM_B) {
00754               if (FEQ(bounds[1][0],0.))
00755                      fprintf(out, "srcB_horiz2 ");
00756               else
00757                      fprintf(out, "srcB_horiz ");
00758               fprintf(out, "srcB_vert ");
00759        } else /* pmtype == PM_C */ {
00760               if (nangles[1] >= 2) {
00761                      d1 = bounds[1][1] - bounds[1][0];
00762                      if (d1 <= 90.+FTINY)
00763                             fprintf(out, "src_phi4 ");
00764                      else if (d1 <= 180.+FTINY) {
00765                             if (FEQ(bounds[1][0],90.))
00766                                    fprintf(out, "src_phi2+90 ");
00767                             else
00768                                    fprintf(out, "src_phi2 ");
00769                      } else
00770                             fprintf(out, "src_phi ");
00771                      fprintf(out, "src_theta ");
00772                      if (FEQ(bounds[1][0],90.) && FEQ(bounds[1][1],270.))
00773                             fprintf(out, "-rz -90 ");
00774               } else
00775                      fprintf(out, "src_theta ");
00776        }
00777        if (!dosides || sinf->type == SPHERE)
00778               fprintf(out, "\n0\n1 %g\n", sinf->mult/sinf->area);
00779        else if (sinf->type == DISK)
00780               fprintf(out, "\n0\n3 %g %g %g\n", sinf->mult,
00781                             sinf->w, sinf->h);
00782        else
00783               fprintf(out, "\n0\n4 %g %g %g %g\n", sinf->mult,
00784                             sinf->l, sinf->w, sinf->h);
00785        if (putsource(sinf, out, id, filename(name),
00786                      dolower, doupper, dosides) != 0)
00787               return(-1);
00788        return(0);
00789 }
00790 
00791 
00792 int
00793 putsource( /* put out source */
00794        SRCINFO       *shp,
00795        FILE   *fp,
00796        char   *mod,
00797        char   *name,
00798        int    dolower,
00799        int    doupper,
00800        int dosides
00801 )
00802 {
00803        char   lname[RMAXWORD];
00804        
00805        strcat(strcpy(lname, name), "_light");
00806        fprintf(fp, "\n%s %s %s\n", mod,
00807                      shp->isillum ? "illum" : "light", lname);
00808        fprintf(fp, "0\n0\n3 %g %g %g\n",
00809                      lampcolor[0], lampcolor[1], lampcolor[2]);
00810        switch (shp->type) {
00811        case RECT:
00812               if (dolower)
00813                      putrectsrc(shp, fp, lname, name, 0);
00814               if (doupper)
00815                      putrectsrc(shp, fp, lname, name, 1);
00816               if (dosides)
00817                      putsides(shp, fp, lname, name);
00818               break;
00819        case DISK:
00820               if (dolower)
00821                      putdisksrc(shp, fp, lname, name, 0);
00822               if (doupper)
00823                      putdisksrc(shp, fp, lname, name, 1);
00824               if (dosides)
00825                      putcyl(shp, fp, lname, name);
00826               break;
00827        case SPHERE:
00828               putspheresrc(shp, fp, lname, name);
00829               break;
00830        }
00831        return(0);
00832 }
00833 
00834 
00835 int
00836 makeshape(           /* make source shape */
00837        register SRCINFO     *shp,
00838        double width,
00839        double length,
00840        double height
00841 )
00842 {
00843        if (illumrad/meters2out >= MINDIM/2.) {
00844               shp->isillum = 1;
00845               shp->type = SPHERE;
00846               shp->w = shp->l = shp->h = 2.*illumrad / meters2out;
00847        } else if (width < MINDIM) {
00848               width = -width;
00849               if (width < MINDIM) {
00850                      shp->type = SPHERE;
00851                      shp->w = shp->l = shp->h = MINDIM;
00852               } else if (height < .5*width) {
00853                      shp->type = DISK;
00854                      shp->w = shp->l = width;
00855                      if (height >= MINDIM)
00856                             shp->h = height;
00857                      else
00858                             shp->h = .5*MINDIM;
00859               } else {
00860                      shp->type = SPHERE;
00861                      shp->w = shp->l = shp->h = width;
00862               }
00863        } else {
00864               shp->type = RECT;
00865               shp->w = width;
00866               if (length >= MINDIM)
00867                      shp->l = length;
00868               else
00869                      shp->l = MINDIM;
00870               if (height >= MINDIM)
00871                      shp->h = height;
00872               else
00873                      shp->h = .5*MINDIM;
00874        }
00875        switch (shp->type) {
00876        case RECT:
00877               shp->area = shp->w * shp->l;
00878               break;
00879        case DISK:
00880        case SPHERE:
00881               shp->area = PI/4. * shp->w * shp->w;
00882               break;
00883        }
00884        return(0);
00885 }
00886 
00887 
00888 void
00889 putrectsrc(          /* rectangular source */
00890        SRCINFO       *shp,
00891        FILE   *fp,
00892        char   *mod,
00893        char   *name,
00894        int    up
00895 )
00896 {
00897        if (up)
00898               putrect(shp, fp, mod, name, ".u", 4, 5, 7, 6);
00899        else
00900               putrect(shp, fp, mod, name, ".d", 0, 2, 3, 1);
00901 }
00902 
00903 
00904 void
00905 putsides(                   /* put out sides of box */
00906        register SRCINFO     *shp,
00907        FILE   *fp,
00908        char   *mod,
00909        char   *name
00910 )
00911 {
00912        putrect(shp, fp, mod, name, ".1", 0, 1, 5, 4);
00913        putrect(shp, fp, mod, name, ".2", 1, 3, 7, 5);
00914        putrect(shp, fp, mod, name, ".3", 3, 2, 6, 7);
00915        putrect(shp, fp, mod, name, ".4", 2, 0, 4, 6);
00916 }
00917        
00918 
00919 void
00920 putrect(      /* put out a rectangle */
00921        SRCINFO       *shp,
00922        FILE   *fp,
00923        char   *mod,
00924        char   *name,
00925        char   *suffix,
00926        int    a,
00927        int b,
00928        int c,
00929        int d
00930 )
00931 {
00932        fprintf(fp, "\n%s polygon %s%s\n0\n0\n12\n", mod, name, suffix);
00933        putpoint(shp, fp, a);
00934        putpoint(shp, fp, b);
00935        putpoint(shp, fp, c);
00936        putpoint(shp, fp, d);
00937 }
00938 
00939 
00940 void
00941 putpoint(                          /* put out a point */
00942        register SRCINFO     *shp,
00943        FILE   *fp,
00944        int    p
00945 )
00946 {
00947        static double mult[2] = {-.5, .5};
00948 
00949        fprintf(fp, "\t%g\t%g\t%g\n",
00950                      mult[p&1]*shp->l*meters2out,
00951                      mult[p>>1&1]*shp->w*meters2out,
00952                      mult[p>>2]*shp->h*meters2out);
00953 }
00954 
00955 
00956 void
00957 putdisksrc(          /* put out a disk source */
00958        register SRCINFO     *shp,
00959        FILE   *fp,
00960        char   *mod,
00961        char   *name,
00962        int    up
00963 )
00964 {
00965        if (up) {
00966               fprintf(fp, "\n%s ring %s.u\n", mod, name);
00967               fprintf(fp, "0\n0\n8\n");
00968               fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
00969               fprintf(fp, "\t0 0 1\n");
00970               fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
00971        } else {
00972               fprintf(fp, "\n%s ring %s.d\n", mod, name);
00973               fprintf(fp, "0\n0\n8\n");
00974               fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
00975               fprintf(fp, "\t0 0 -1\n");
00976               fprintf(fp, "\t0 %g\n", .5*shp->w*meters2out);
00977        }
00978 }
00979 
00980 
00981 void
00982 putcyl(                     /* put out a cylinder */
00983        register SRCINFO     *shp,
00984        FILE   *fp,
00985        char   *mod,
00986        char   *name
00987 )
00988 {
00989        fprintf(fp, "\n%s cylinder %s.c\n", mod, name);
00990        fprintf(fp, "0\n0\n7\n");
00991        fprintf(fp, "\t0 0 %g\n", .5*shp->h*meters2out);
00992        fprintf(fp, "\t0 0 %g\n", -.5*shp->h*meters2out);
00993        fprintf(fp, "\t%g\n", .5*shp->w*meters2out);
00994 }
00995 
00996 
00997 void
00998 putspheresrc(        /* put out a sphere source */
00999        SRCINFO       *shp,
01000        FILE   *fp,
01001        char   *mod,
01002        char   *name
01003 )
01004 {
01005        fprintf(fp, "\n%s sphere %s.s\n", mod, name);
01006        fprintf(fp, "0\n0\n4 0 0 0 %g\n", .5*shp->w*meters2out);
01007 }
01008 
01009 
01010 int
01011 cvdata(              /* convert data */
01012        FILE   *in,
01013        FILE   *out,
01014        int    ndim,
01015        int    npts[],
01016        double mult,
01017        double lim[][2]
01018 )
01019 {
01020        double *pt[4];
01021        register int  i, j;
01022        double val;
01023        int    total;
01024 
01025        total = 1; j = 0;
01026        for (i = 0; i < ndim; i++)
01027               if (npts[i] > 1) {
01028                      total *= npts[i];
01029                      j++;
01030               }
01031        fprintf(out, "%d\n", j);
01032                                    /* get coordinates */
01033        for (i = 0; i < ndim; i++) {
01034               pt[i] = (double *)malloc(npts[i]*sizeof(double));
01035               for (j = 0; j < npts[i]; j++)
01036                      if (!scnflt(in, &pt[i][j]))
01037                             return(-1);
01038               if (lim != NULL) {
01039                      lim[i][0] = pt[i][0];
01040                      lim[i][1] = pt[i][npts[i]-1];
01041               }
01042        }
01043                                    /* write out in reverse */
01044        for (i = ndim-1; i >= 0; i--) {
01045               if (npts[i] > 1) {
01046                      for (j = 1; j < npts[i]-1; j++)
01047                             if (!FEQ(pt[i][j]-pt[i][j-1],
01048                                           pt[i][j+1]-pt[i][j]))
01049                                    break;
01050                      if (j == npts[i]-1)
01051                             fprintf(out, "%g %g %d\n", pt[i][0], pt[i][j],
01052                                           npts[i]);
01053                      else {
01054                             fprintf(out, "0 0 %d", npts[i]);
01055                             for (j = 0; j < npts[i]; j++) {
01056                                    if (j%4 == 0)
01057                                           putc('\n', out);
01058                                    fprintf(out, "\t%g", pt[i][j]);
01059                             }
01060                             putc('\n', out);
01061                      }
01062               }
01063               free((void *)pt[i]);
01064        }
01065        for (i = 0; i < total; i++) {
01066               if (i%4 == 0)
01067                      putc('\n', out);
01068               if (!scnflt(in, &val))
01069                      return(-1);
01070               fprintf(out, "\t%g", val*mult);
01071        }
01072        putc('\n', out);
01073        return(0);
01074 }
01075 
01076 
01077 char *
01078 getword(                    /* scan a word from fp */
01079        register FILE *fp
01080 )
01081 {
01082        static char   wrd[RMAXWORD];
01083        register char *cp;
01084        register int  c;
01085 
01086        while (isspace(c=getc(fp)))
01087               ;
01088        for (cp = wrd; c != EOF && cp < wrd+RMAXWORD-1;
01089                      *cp++ = c, c = getc(fp))
01090               if (isspace(c) || c == ',') {
01091                      while (isspace(c))
01092                             c = getc(fp);
01093                      if ((c != EOF) & (c != ','))
01094                             ungetc(c, fp);
01095                      *cp = '\0';
01096                      return(wrd);
01097               }
01098        *cp = '\0';
01099        return(cp > wrd ? wrd : NULL);
01100 }
01101 
01102 
01103 int
01104 cvtint(                     /* convert a word to an integer */
01105        int    *ip,
01106        char   *wrd
01107 )
01108 {
01109        if (wrd == NULL || !isint(wrd))
01110               return(0);
01111        *ip = atoi(wrd);
01112        return(1);
01113 }
01114 
01115 
01116 int
01117 cvtflt(                     /* convert a word to a double */
01118        double *rp,
01119        char   *wrd
01120 )
01121 {
01122        if (wrd == NULL || !isflt(wrd))
01123               return(0);
01124        *rp = atof(wrd);
01125        return(1);
01126 }
01127 
01128 
01129 int
01130 cvgeometry(
01131        char   *inpname,
01132        register SRCINFO     *sinf,
01133        char   *outname,
01134        FILE   *outfp               /* close output file upon return */
01135 )
01136 {
01137        char   buf[256];
01138        register char *cp;
01139 
01140        if (inpname == NULL || !inpname[0]) {     /* no geometry file */
01141               fclose(outfp);
01142               return(0);
01143        }
01144        putc('\n', outfp);
01145        strcpy(buf, "mgf2rad ");           /* build mgf2rad command */
01146        cp = buf+8;
01147        if (!FEQ(sinf->mult, 1.0)) {
01148               sprintf(cp, "-m %f ", sinf->mult);
01149               cp += strlen(cp);
01150        }
01151        sprintf(cp, "-g %f %s ",
01152               sqrt(sinf->w*sinf->w + sinf->h*sinf->h + sinf->l*sinf->l),
01153                      inpname);
01154        cp += strlen(cp);
01155        if (instantiate) {          /* instantiate octree */
01156               strcpy(cp, "| oconv - > ");
01157               cp += 12;
01158               fullnam(cp,outname,T_OCT);
01159               if (fdate(inpname) > fdate(outname) &&
01160                             system(buf)) {              /* create octree */
01161                      fclose(outfp);
01162                      return(-1);
01163               }
01164               fprintf(outfp, "void instance %s_inst\n", outname);
01165               if (!FEQ(meters2out, 1.0))
01166                      fprintf(outfp, "3 %s -s %f\n",
01167                                    libname(buf,outname,T_OCT),
01168                                    meters2out);
01169               else
01170                      fprintf(outfp, "1 %s\n", libname(buf,outname,T_OCT));
01171               fprintf(outfp, "0\n0\n");
01172               fclose(outfp);
01173        } else {                    /* else append to luminaire file */
01174               if (!FEQ(meters2out, 1.0)) {       /* apply scalefactor */
01175                      sprintf(cp, "| xform -s %f ", meters2out);
01176                      cp += strlen(cp);
01177               }
01178               if (!out2stdout) {
01179                      fclose(outfp);
01180                      strcpy(cp, ">> ");   /* append works for DOS? */
01181                      cp += 3;
01182                      fullnam(cp,outname,T_RAD);
01183               }
01184               if (system(buf))
01185                      return(-1);
01186        }
01187        return(0);
01188 }