ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glarendx.c
(Generate patch)

Comparing ray/src/util/glarendx.c (file contents):
Revision 2.9 by greg, Wed Nov 19 16:21:28 2003 UTC vs.
Revision 2.17 by greg, Tue Jun 3 21:31:51 2025 UTC

# Line 18 | Line 18 | static const char      RCSid[] = "$Id$";
18   *              12 April 1991   Greg Ward       EPFL
19   *              19 April 1993   R. Compagnon    EPFL (added dgi, brs_gi, ugr)
20   */
21 <
21 >
22   #include <string.h>
23  
24   #include "standard.h"
25 + #include "paths.h"
26   #include "view.h"
27 <
28 <
29 < double  posindex();
30 <
31 < double  direct(), guth_dgr(), guth_vcp(), cie_cgi(),
32 <        indirect(), total(), dgi(), brs_gi(), ugr();
33 <
27 >
28 >
29 > struct glare_src {
30 >        FVECT   dir;            /* source direction */
31 >        double  dom;            /* solid angle */
32 >        double  lum;            /* average luminance */
33 >        struct glare_src        *next;
34 > } *all_srcs = NULL;
35 >
36 > struct glare_dir {
37 >        double  ang;            /* angle (in radians) */
38 >        double  indirect;       /* indirect illuminance */
39 >        struct glare_dir        *next;
40 > } *all_dirs = NULL;
41 >
42 > typedef double gdfun(struct glare_dir *gd);
43 >
44 > static gdfun dgi;
45 > static gdfun brs_gi;
46 > static gdfun ugr;
47 > static gdfun guth_dgr;
48 > static gdfun guth_vcp;
49 > static gdfun cie_cgi;
50 > static gdfun direct;
51 > static gdfun indirect;
52 > static gdfun total;
53 >
54 > static gethfunc headline;
55 > static void init(void);
56 > static void read_input(void);
57 > static void print_values(gdfun *func);
58 > static double posindex(FVECT sd, FVECT vd, FVECT vu);
59 >
60 >
61   struct named_func {
62          char    *name;
63 <        double  (*func)();
63 >        gdfun   *func;
64          char    *descrip;
65   } all_funcs[] = {
66          {"dgi", dgi, "Daylight Glare Index"},
# Line 46 | Line 74 | struct named_func {
74          {"vert_ind", indirect, "Indirect Vertical Illuminance"},
75          {NULL}
76   };
77 <
50 < struct glare_src {
51 <        FVECT   dir;            /* source direction */
52 <        double  dom;            /* solid angle */
53 <        double  lum;            /* average luminance */
54 <        struct glare_src        *next;
55 < } *all_srcs = NULL;
56 <
57 < struct glare_dir {
58 <        double  ang;            /* angle (in radians) */
59 <        double  indirect;       /* indirect illuminance */
60 <        struct glare_dir        *next;
61 < } *all_dirs = NULL;
62 <
77 >
78   #define newp(type)      (type *)malloc(sizeof(type))
79 <
65 < char    *progname;
79 >
80   int     print_header = 1;
81 <
81 >
82   VIEW    midview = STDVIEW;
83 <
83 >
84   int     wrongformat = 0;
85 <
86 <
87 < main(argc, argv)
88 < int     argc;
89 < char    *argv[];
85 >
86 >
87 > int
88 > main(
89 >        int     argc,
90 >        char    *argv[]
91 > )
92   {
93          struct named_func       *funp;
78        char    *progtail;
94          int     i;
95                                          /* get program name */
96 <        progname = argv[0];
82 <        progtail = strrchr(progname, '/');      /* final component */
83 <        if (progtail == NULL)
84 <                progtail = progname;
85 <        else
86 <                progtail++;
96 >        progname = fixargv0(argv[0]);
97                                          /* get options */
98          for (i = 1; i < argc && argv[i][0] == '-'; i++)
99                  switch (argv[i][1]) {
100                  case 't':
101 <                        progtail = argv[++i];
101 >                        progname = argv[++i];
102                          break;
103                  case 'h':
104                          print_header = 0;
# Line 105 | Line 115 | char   *argv[];
115                  }
116                                          /* find and run calculation */
117          for (funp = all_funcs; funp->name != NULL; funp++)
118 <                if (!strcmp(funp->name, progtail)) {
118 >                if (!strcmp(funp->name, progname)) {
119                          init();
120                          read_input();
121                          if (print_header) {
# Line 123 | Line 133 | userr:
133                  fprintf(stderr, "\t%12s\t%s\n", funp->name, funp->descrip);
134          exit(1);
135   }
136 <
137 <
138 < int
139 < headline(s)                     /* get line from header */
140 < char    *s;
136 >
137 >
138 > static int
139 > headline(                       /* get line from header */
140 >        char    *s,
141 >        void    *p
142 > )
143   {
144 <        char    fmt[32];
145 <
144 >        char    fmt[MAXFMTLEN];
145 >
146          if (print_header)               /* copy to output */
147                  fputs(s, stdout);
148          if (isview(s))
# Line 141 | Line 153 | char   *s;
153          }
154          return(0);
155   }
156 <
157 <
158 < init()                          /* initialize calculation */
156 >
157 >
158 > static void
159 > init(void)                              /* initialize calculation */
160   {
161 +        char    *err;
162                                          /* read header */
163          getheader(stdin, headline, NULL);
164          if (wrongformat) {
# Line 152 | Line 166 | init()                         /* initialize calculation */
166                  exit(1);
167          }
168                                          /* set view */
169 <        if (setview(&midview) != NULL) {
170 <                fprintf(stderr, "%s: bad view information in input\n",
169 >        if ((err = setview(&midview)) != NULL) {
170 >                fprintf(stderr, "%s: %s\n",
171 >                                progname, err);
172 >                exit(1);
173 >        }
174 >        if (fabs(DOT(midview.vdir, midview.vup)) > 1e-4) {
175 >                fprintf(stderr,
176 >                "%s: Input view direction not perpendicular to up vector\n",
177                                  progname);
178                  exit(1);
179          }
180   }
181 <
182 <
183 < read_input()                    /* read glare sources from stdin */
181 >
182 >
183 > static void
184 > read_input(void)                        /* read glare sources from stdin */
185   {
186   #define S_SEARCH        0
187   #define S_SOURCE        1
188   #define S_DIREC         2
189          int     state = S_SEARCH;
190          char    buf[128];
191 <        register struct glare_src       *gs;
192 <        register struct glare_dir       *gd;
193 <
191 >        struct glare_src        *gs;
192 >        struct glare_dir        *gd;
193 >
194          while (fgets(buf, sizeof(buf), stdin) != NULL)
195                  switch (state) {
196                  case S_SEARCH:
# Line 185 | Line 206 | read_input()                   /* read glare sources from stdin */
206                          }
207                          if ((gs = newp(struct glare_src)) == NULL)
208                                  goto memerr;
209 <                        if (sscanf(buf, "%lf %lf %lf %lf %lf",
210 <                                        &gs->dir[0], &gs->dir[1], &gs->dir[2],
211 <                                        &gs->dom, &gs->lum) != 5)
209 >                        if (sscanf(buf, FVFORMAT, &gs->dir[0], &gs->dir[1],
210 >                                                &gs->dir[2]) != 3 ||
211 >                                        sscanf(sskip2(buf, 3), "%lf %lf",
212 >                                                &gs->dom, &gs->lum) != 2)
213                                  goto readerr;
214                          normalize(gs->dir);
215                          gs->next = all_srcs;
# Line 219 | Line 241 | readerr:
241   #undef S_SOURCE
242   #undef S_DIREC
243   }
244 <
245 <
246 < print_values(funp)              /* print out calculations */
247 < double  (*funp)();
244 >
245 >
246 > static void
247 > print_values(           /* print out calculations */
248 >        gdfun *func
249 > )
250   {
251 <        register struct glare_dir       *gd;
252 <
251 >        struct glare_dir        *gd;
252 >
253          for (gd = all_dirs; gd != NULL; gd = gd->next)
254 <                printf("%f\t%f\n", gd->ang*(180.0/PI), (*funp)(gd));
254 >                printf("%f\t%f\n", gd->ang*(180.0/PI), (*func)(gd));
255   }
256 <
257 <
258 < double
259 < direct(gd)                      /* compute direct vertical illuminance */
260 < struct glare_dir        *gd;
256 >
257 >
258 > static double
259 > direct(                 /* compute direct vertical illuminance */
260 >        struct glare_dir        *gd
261 > )
262   {
263          FVECT   mydir;
264          double  d, dval;
265 <        register struct glare_src       *gs;
266 <
265 >        struct glare_src        *gs;
266 >
267          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
268          dval = 0.0;
269          for (gs = all_srcs; gs != NULL; gs = gs->next) {
# Line 248 | Line 273 | struct glare_dir       *gd;
273          }
274          return(dval);
275   }
276 <
277 <
278 < double
279 < indirect(gd)                    /* return indirect vertical illuminance */
280 < struct glare_dir        *gd;
276 >
277 >
278 > static double
279 > indirect(                       /* return indirect vertical illuminance */
280 >        struct glare_dir        *gd
281 > )
282   {
283          return(gd->indirect);
284   }
285 <
286 <
287 < double
288 < total(gd)                       /* return total vertical illuminance */
289 < struct glare_dir        *gd;
285 >
286 >
287 > static double
288 > total(                  /* return total vertical illuminance */
289 >        struct glare_dir        *gd
290 > )
291   {
292          return(direct(gd)+gd->indirect);
293   }
294 <
295 <
294 >
295 >
296   /*
297   * posindex -   compute glare position index from:
298   *
# Line 279 | Line 306 | struct glare_dir       *gd;
306   * This calculation presumes the view direction and up vectors perpendicular.
307   * We return a value less than zero for improper positions.
308   */
309 <
310 < double
311 < posindex(sd, vd, vu)                    /* compute position index */
312 < FVECT   sd, vd, vu;
309 >
310 > static double
311 > posindex(                       /* compute position index */
312 >        FVECT   sd,
313 >        FVECT   vd,
314 >        FVECT   vu
315 > )
316   {
317          double  sigma, tau;
318          double  d;
319 <
319 >
320          d = DOT(sd,vd);
321          if (d <= 0.0)
322                  return(-1.0);
323 <        if (d >= 1.0)
323 >        if (d >= 1.0-FTINY)
324                  return(1.0);
325          sigma = acos(d) * (180./PI);
326          d = fabs(DOT(sd,vu)/sqrt(1.0-d*d));
327 <        if (d >= 1.0)
298 <                tau = 0.0;
299 <        else
300 <                tau = acos(d) * (180./PI);
327 >        tau = Acos(d) * (180./PI);
328          return( exp( sigma*( (35.2 - tau*.31889 - 1.22*exp(-.22222*tau))*1e-3
329                          + sigma*(21. + tau*(.26667 + tau*-.002963))*1e-5 )
330                  ) );
331   }
332 <
333 <
334 < double
335 < dgi(gd)         /* compute Daylight Glare Index */
336 < struct glare_dir        *gd;
332 >
333 >
334 > static double
335 > dgi(            /* compute Daylight Glare Index */
336 >        struct glare_dir        *gd
337 > )
338   {
339 <        register struct glare_src       *gs;
339 >        struct glare_src        *gs;
340          FVECT   mydir,testdir[7],vhor;
341          double  r,posn,omega,p[7],sum;
342 <        int     i,n;
343 <
342 >        int     i;
343 >
344          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
345 <        sum = 0.0; n = 0;
345 >        sum = 0.0;
346          for (gs = all_srcs; gs != NULL; gs = gs->next) {
347  
348                  /* compute 1/p^2 weighted solid angle of the source */
349 <                r = sqrt(1 - pow(1.-gs->dom/2./PI,2.));
349 >                r = 1. - gs->dom*(.5/PI);
350 >                r = sqrt(1. - r*r);
351                  fcross(vhor,gs->dir,midview.vup);
352 <                normalize(vhor);
352 >                if (normalize(vhor) == 0.)
353 >                        continue;
354                  VCOPY(testdir[0],gs->dir);
355                  fvsum(testdir[1],gs->dir,vhor,r);
356                  fvsum(testdir[2],gs->dir,vhor,0.5*r);
# Line 331 | Line 361 | struct glare_dir       *gd;
361                  fvsum(testdir[6],testdir[4],midview.vup,0.866*r);
362                  fvsum(testdir[4],testdir[4],midview.vup,-0.866*r);
363                  for (i = 0; i < 7; i++) {
364 <                        normalize(testdir[i]);
364 >                        p[i] = 0.0;
365 >                        if (normalize(testdir[i]) == 0.)
366 >                                continue;
367                          posn = posindex(testdir[i],mydir,midview.vup);
368 <                        if (posn <= FTINY)
337 <                                p[i] = 0.0;
338 <                        else
368 >                        if (posn > FTINY)
369                                  p[i] = 1./(posn*posn);
370                  }
371 <                r = 1-gs->dom/2./PI;
371 >                r = 1. - gs->dom*(.5/PI);
372                  omega = gs->dom*p[0];
373 <                omega += (r*PI*(1+1/r/r)-2*PI)*(-p[0]+(p[1]+p[2])*0.5);
374 <                omega += (2*PI-r*PI*(1+1/r/r))*(-p[0]-0.1667*(p[1]+p[3])
373 >                omega += (r*PI*(1.+1./(r*r))-2.*PI)*(-p[0]+(p[1]+p[2])*0.5);
374 >                omega += (2.*PI-r*PI*(1.+1./(r*r)))*(-p[0]-0.1667*(p[1]+p[3])
375                            +0.3334*(p[2]+p[4]+p[5]+p[6]));
376 <
377 <                sum += pow(gs->lum,1.6) * pow(omega,0.8) /
378 <                       (gd->indirect/PI + 0.07*sqrt(gs->dom)*gs->lum);
379 <                n++;
376 >                if (omega <= 0.)
377 >                        continue;
378 >                sum += pow(gs->lum,1.6) * pow(omega,0.8) /
379 >                       (gd->indirect*(1./PI) + 0.07*sqrt(gs->dom)*gs->lum);
380          }
381 <        if (n == 0)
381 >        if (sum <= FTINY)
382                  return(0.0);
383 <        return( 10*log10(0.478*sum) );
383 >        return( 10.*log10(0.478*sum) );
384   }
355
385  
386 < double
387 < brs_gi(gd)              /* compute BRS Glare Index */
388 < struct glare_dir        *gd;
386 >
387 > static double
388 > brs_gi(         /* compute BRS Glare Index */
389 >        struct glare_dir        *gd
390 > )
391   {
392 <        register struct glare_src       *gs;
392 >        struct glare_src        *gs;
393          FVECT   mydir;
394          double  p;
395          double  sum;
396 <
396 >
397          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
398          sum = 0.0;
399          for (gs = all_srcs; gs != NULL; gs = gs->next) {
# Line 373 | Line 404 | struct glare_dir       *gd;
404          }
405          if (sum <= FTINY)
406                  return(0.0);
407 <        sum /= gd->indirect/PI;
407 >        sum *= PI/gd->indirect;
408          return(10*log10(0.478*sum));
409   }
410  
411  
412 < double
413 < guth_dgr(gd)            /* compute Guth discomfort glare rating */
414 < struct glare_dir        *gd;
412 > static double
413 > guth_dgr(               /* compute Guth discomfort glare rating */
414 >        struct glare_dir        *gd
415 > )
416   {
417   #define q(w)    (20.4*w+1.52*pow(w,.2)-.075)
418 <        register struct glare_src       *gs;
418 >        struct glare_src        *gs;
419          FVECT   mydir;
420          double  p;
421          double  sum;
422          double  wtot, brsum;
423          int     n;
424 <
424 >
425          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
426          sum = wtot = brsum = 0.0; n = 0;
427          for (gs = all_srcs; gs != NULL; gs = gs->next) {
# Line 407 | Line 439 | struct glare_dir       *gd;
439                          pow((double)n, -.0914) ) );
440   #undef q
441   }
442 <
443 <
442 >
443 >
444   #ifndef M_SQRT2
445   #define M_SQRT2 1.41421356237309504880
446   #endif
447 <
447 >
448   #define norm_integral(z)        (1.-.5*erfc((z)/M_SQRT2))
449 <
450 <
451 < double
452 < guth_vcp(gd)            /* compute Guth visual comfort probability */
453 < struct glare_dir        *gd;
449 >
450 >
451 > static double
452 > guth_vcp(               /* compute Guth visual comfort probability */
453 >        struct glare_dir        *gd
454 > )
455   {
456          extern double   erfc();
457          double  dgr;
458 <
458 >
459          dgr = guth_dgr(gd);
460          if (dgr <= FTINY)
461                  return(100.0);
462          return(100.*norm_integral(6.374-1.3227*log(dgr)));
463   }
464 <
465 <
466 < double
467 < cie_cgi(gd)             /* compute CIE Glare Index */
468 < struct glare_dir        *gd;
464 >
465 >
466 > static double
467 > cie_cgi(                /* compute CIE Glare Index */
468 >        struct glare_dir        *gd
469 > )
470   {
471 <        register struct glare_src       *gs;
471 >        struct glare_src        *gs;
472          FVECT   mydir;
473          double  dillum;
474          double  p;
475          double  sum;
476 <
476 >
477          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
478          sum = 0.0;
479          for (gs = all_srcs; gs != NULL; gs = gs->next) {
# Line 455 | Line 489 | struct glare_dir       *gd;
489   }
490  
491  
492 < double
493 < ugr(gd)         /* compute Unified Glare Rating */
494 < struct glare_dir        *gd;
492 > static double
493 > ugr(            /* compute Unified Glare Rating */
494 >        struct glare_dir        *gd
495 > )
496   {
497 <        register struct glare_src       *gs;
497 >        struct glare_src        *gs;
498          FVECT   mydir;
499          double  p;
500          double  sum;
501 <
501 >
502          spinvector(mydir, midview.vdir, midview.vup, gd->ang);
503          sum = 0.0;
504          for (gs = all_srcs; gs != NULL; gs = gs->next) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines