ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glarendx.c
Revision: 2.4
Committed: Thu Mar 24 11:06:59 1994 UTC (30 years, 1 month ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.3: +150 -51 lines
Log Message:
Raphael added dgi, brs_gi, and ugr index calculations

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1991 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8 greg 1.9 * Compute Glare Index given by program name or -t option:
9 greg 1.1 *
10 greg 2.4 * dgi - Daylight Glare Index
11     * brs_gi - Building Research Station Glare Index (Petherbridge
12     * & Hopkinson)
13     * ugr - Unified Glare Rating System (Fischer)
14 greg 1.2 * guth_dgr - Guth discomfort glare rating
15     * guth_vcp - Guth visual comfort probability
16 greg 1.9 * cie_cgi - CIE Glare Index (1983, due to Einhorn)
17     * vert_dir - Direct vertical illuminance
18     * vert_ind - Indirect vertical illuminance (from input)
19     * vert_ill - Total vertical illuminance
20 greg 1.1 *
21     * 12 April 1991 Greg Ward EPFL
22 greg 2.4 * 19 April 1993 R. Compagnon EPFL (added dgi, brs_gi, ugr)
23 greg 1.1 */
24 greg 2.4
25 greg 1.1 #include "standard.h"
26     #include "view.h"
27 greg 2.4
28 greg 1.1 extern double erfc();
29 greg 2.4
30 greg 1.1 double posindex();
31 greg 2.4
32 greg 1.9 double direct(), guth_dgr(), guth_vcp(), cie_cgi(),
33 greg 2.4 indirect(), total(), dgi(), brs_gi(), ugr();
34    
35 greg 1.1 struct named_func {
36     char *name;
37     double (*func)();
38 greg 1.9 char *descrip;
39 greg 1.1 } all_funcs[] = {
40 greg 2.4 {"dgi", dgi, "Daylight Glare Index"},
41     {"brs_gi", brs_gi, "BRS Glare Index"},
42     {"ugr", ugr, "Unified Glare Rating"},
43 greg 1.9 {"guth_vcp", guth_vcp, "Guth Visual Comfort Probability"},
44     {"cie_cgi", cie_cgi, "CIE Glare Index (Einhorn)"},
45     {"guth_dgr", guth_dgr, "Guth Disability Glare Rating"},
46     {"vert_dir", direct, "Direct Vertical Illuminance"},
47     {"vert_ill", total, "Total Vertical Illuminance"},
48     {"vert_ind", indirect, "Indirect Vertical Illuminance"},
49 greg 1.1 {NULL}
50     };
51 greg 2.4
52 greg 1.1 struct glare_src {
53     FVECT dir; /* source direction */
54     double dom; /* solid angle */
55     double lum; /* average luminance */
56     struct glare_src *next;
57     } *all_srcs = NULL;
58 greg 2.4
59 greg 1.1 struct glare_dir {
60     double ang; /* angle (in radians) */
61     double indirect; /* indirect illuminance */
62     struct glare_dir *next;
63     } *all_dirs = NULL;
64 greg 2.4
65 greg 1.1 #define newp(type) (type *)malloc(sizeof(type))
66 greg 2.4
67 greg 1.1 char *progname;
68     int print_header = 1;
69 greg 2.4
70 greg 1.1 VIEW midview = STDVIEW;
71 greg 2.4
72 greg 1.4 int wrongformat = 0;
73 greg 2.4
74    
75 greg 1.1 main(argc, argv)
76     int argc;
77     char *argv[];
78     {
79     extern char *rindex();
80     struct named_func *funp;
81     char *progtail;
82     int i;
83     /* get program name */
84     progname = argv[0];
85     progtail = rindex(progname, '/'); /* final component */
86     if (progtail == NULL)
87     progtail = progname;
88     else
89     progtail++;
90     /* get options */
91     for (i = 1; i < argc && argv[i][0] == '-'; i++)
92     switch (argv[i][1]) {
93     case 't':
94     progtail = argv[++i];
95     break;
96     case 'h':
97     print_header = 0;
98     break;
99     default:
100     goto userr;
101     }
102     if (i < argc-1)
103     goto userr;
104     if (i == argc-1) /* open file */
105     if (freopen(argv[i], "r", stdin) == NULL) {
106     perror(argv[i]);
107     exit(1);
108     }
109 greg 1.9 /* find and run calculation */
110 greg 1.1 for (funp = all_funcs; funp->name != NULL; funp++)
111     if (!strcmp(funp->name, progtail)) {
112 greg 1.9 init();
113     read_input();
114     if (print_header) {
115     printargs(i, argv, stdout);
116     putchar('\n');
117     }
118 greg 1.1 print_values(funp->func);
119     exit(0); /* we're done */
120     }
121     /* invalid function */
122     userr:
123 greg 1.9 fprintf(stderr, "Usage: %s -t type [-h] [input]\n", progname);
124     fprintf(stderr, "\twhere 'type' is one of the following:\n");
125     for (funp = all_funcs; funp->name != NULL; funp++)
126     fprintf(stderr, "\t%12s\t%s\n", funp->name, funp->descrip);
127 greg 1.1 exit(1);
128     }
129 greg 2.4
130    
131 greg 1.1 headline(s) /* get line from header */
132     char *s;
133     {
134 greg 1.4 char fmt[32];
135 greg 2.4
136 greg 1.1 if (print_header) /* copy to output */
137     fputs(s, stdout);
138 greg 2.2 if (isview(s))
139     sscanview(&midview, s);
140 greg 1.4 else if (isformat(s)) {
141     formatval(fmt, s);
142 greg 1.6 wrongformat = strcmp(fmt, "ascii");
143 greg 1.4 }
144 greg 1.1 }
145 greg 2.4
146    
147 greg 1.9 init() /* initialize calculation */
148     {
149     /* read header */
150     getheader(stdin, headline, NULL);
151     if (wrongformat) {
152     fprintf(stderr, "%s: bad input format\n", progname);
153     exit(1);
154     }
155     /* set view */
156     if (setview(&midview) != NULL) {
157     fprintf(stderr, "%s: bad view information in input\n",
158     progname);
159     exit(1);
160     }
161     }
162 greg 2.4
163    
164 greg 1.1 read_input() /* read glare sources from stdin */
165     {
166     #define S_SEARCH 0
167     #define S_SOURCE 1
168     #define S_DIREC 2
169     int state = S_SEARCH;
170     char buf[128];
171     register struct glare_src *gs;
172     register struct glare_dir *gd;
173 greg 2.4
174 greg 1.1 while (fgets(buf, sizeof(buf), stdin) != NULL)
175     switch (state) {
176     case S_SEARCH:
177     if (!strcmp(buf, "BEGIN glare source\n"))
178     state = S_SOURCE;
179     else if (!strcmp(buf, "BEGIN indirect illuminance\n"))
180     state = S_DIREC;
181     break;
182     case S_SOURCE:
183     if (!strncmp(buf, "END", 3)) {
184     state = S_SEARCH;
185     break;
186     }
187     if ((gs = newp(struct glare_src)) == NULL)
188     goto memerr;
189     if (sscanf(buf, "%lf %lf %lf %lf %lf",
190     &gs->dir[0], &gs->dir[1], &gs->dir[2],
191     &gs->dom, &gs->lum) != 5)
192     goto readerr;
193 greg 1.2 normalize(gs->dir);
194 greg 1.1 gs->next = all_srcs;
195     all_srcs = gs;
196     break;
197     case S_DIREC:
198     if (!strncmp(buf, "END", 3)) {
199     state = S_SEARCH;
200     break;
201     }
202     if ((gd = newp(struct glare_dir)) == NULL)
203     goto memerr;
204     if (sscanf(buf, "%lf %lf",
205     &gd->ang, &gd->indirect) != 2)
206     goto readerr;
207     gd->ang *= PI/180.0; /* convert to radians */
208     gd->next = all_dirs;
209     all_dirs = gd;
210     break;
211     }
212     return;
213     memerr:
214     perror(progname);
215     exit(1);
216     readerr:
217     fprintf(stderr, "%s: read error on input\n", progname);
218     exit(1);
219     #undef S_SEARCH
220     #undef S_SOURCE
221     #undef S_DIREC
222     }
223 greg 2.4
224    
225 greg 1.1 print_values(funp) /* print out calculations */
226     double (*funp)();
227     {
228     register struct glare_dir *gd;
229 greg 2.4
230 greg 1.1 for (gd = all_dirs; gd != NULL; gd = gd->next)
231     printf("%f\t%f\n", gd->ang*(180.0/PI), (*funp)(gd));
232     }
233 greg 2.4
234    
235 greg 1.1 double
236 greg 1.9 direct(gd) /* compute direct vertical illuminance */
237 greg 1.1 struct glare_dir *gd;
238     {
239     FVECT mydir;
240     double d, dval;
241     register struct glare_src *gs;
242 greg 2.4
243 greg 1.1 spinvector(mydir, midview.vdir, midview.vup, gd->ang);
244     dval = 0.0;
245     for (gs = all_srcs; gs != NULL; gs = gs->next) {
246     d = DOT(mydir,gs->dir);
247     if (d > FTINY)
248     dval += d * gs->dom * gs->lum;
249     }
250     return(dval);
251 greg 1.9 }
252 greg 2.4
253    
254 greg 1.9 double
255     indirect(gd) /* return indirect vertical illuminance */
256     struct glare_dir *gd;
257     {
258     return(gd->indirect);
259     }
260 greg 2.4
261    
262 greg 1.9 double
263     total(gd) /* return total vertical illuminance */
264     struct glare_dir *gd;
265     {
266     return(direct(gd)+gd->indirect);
267 greg 1.1 }
268 greg 2.4
269    
270 greg 1.1 /*
271     * posindex - compute glare position index from:
272     *
273     * Source Direction
274     * View Direction
275     * View Up Direction
276     *
277     * All vectors are assumed to be normalized.
278     * This function is an implementation of the method proposed by
279     * Robert Levin in his 1975 JIES article.
280 greg 1.5 * This calculation presumes the view direction and up vectors perpendicular.
281 greg 1.1 * We return a value less than zero for improper positions.
282     */
283 greg 2.4
284 greg 1.1 double
285     posindex(sd, vd, vu) /* compute position index */
286     FVECT sd, vd, vu;
287     {
288     double sigma, tau;
289     double d;
290 greg 2.4
291 greg 1.1 d = DOT(sd,vd);
292     if (d <= 0.0)
293     return(-1.0);
294 greg 1.5 if (d >= 1.0)
295     return(1.0);
296 greg 1.1 sigma = acos(d) * (180./PI);
297 greg 2.4 d = fabs(DOT(sd,vu)/sqrt(1.0-d*d));
298 greg 1.5 if (d >= 1.0)
299     tau = 0.0;
300     else
301     tau = acos(d) * (180./PI);
302 greg 1.1 return( exp( sigma*( (35.2 - tau*.31889 - 1.22*exp(-.22222*tau))*1e-3
303     + sigma*(21. + tau*(.26667 + tau*-.002963))*1e-5 )
304     ) );
305     }
306 greg 2.4
307    
308     double
309     dgi(gd) /* compute Daylight Glare Index */
310     struct glare_dir *gd;
311     {
312     register struct glare_src *gs;
313     FVECT mydir,testdir[7],vhor;
314     double r,omega,p[7],sum;
315     int i,n;
316    
317     spinvector(mydir, midview.vdir, midview.vup, gd->ang);
318     sum = 0.0; n = 0;
319     for (gs = all_srcs; gs != NULL; gs = gs->next) {
320 greg 1.1
321 greg 2.4 /* compute 1/p^2 weighted solid angle of the source */
322     r = sqrt(1 - pow(1.-gs->dom/2./PI,2.));
323     fcross(vhor,gs->dir,midview.vup);
324     normalize(vhor);
325     VCOPY(testdir[0],gs->dir);
326     fvsum(testdir[1],gs->dir,vhor,r);
327     fvsum(testdir[2],gs->dir,vhor,0.5*r);
328     fvsum(testdir[5],testdir[2],midview.vup,-0.866*r);
329     fvsum(testdir[2],testdir[2],midview.vup,0.866*r);
330     fvsum(testdir[3],gs->dir,vhor,-r);
331     fvsum(testdir[4],gs->dir,vhor,-0.5*r);
332     fvsum(testdir[6],testdir[4],midview.vup,0.866*r);
333     fvsum(testdir[4],testdir[4],midview.vup,-0.866*r);
334     for (i = 0; i < 7; i++) {
335     normalize(testdir[i]);
336     p[i] = pow(posindex(testdir[i],mydir,midview.vup),-2.0);
337     if (p[i] <= FTINY) p[i] = 0.0;
338     }
339     r = 1-gs->dom/2./PI;
340     omega = gs->dom*p[0];
341     omega += (r*PI*(1+1/r/r)-2*PI)*(-p[0]+(p[1]+p[2])*0.5);
342     omega += (2*PI-r*PI*(1+1/r/r))*(-p[0]-0.1667*(p[1]+p[3])
343     +0.3334*(p[2]+p[4]+p[5]+p[6]));
344 greg 1.1
345 greg 2.4 sum += pow(gs->lum,1.6) * pow(omega,0.8) /
346     (gd->indirect/PI + 0.07*sqrt(gs->dom)*gs->lum);
347     n++;
348     }
349     if (n == 0)
350     return(0.0);
351     return( 10*log10(0.478*sum) );
352     }
353    
354    
355 greg 1.1 double
356 greg 2.4 brs_gi(gd) /* compute BRS Glare Index */
357     struct glare_dir *gd;
358     {
359     register struct glare_src *gs;
360     FVECT mydir;
361     double p;
362     double sum;
363    
364     spinvector(mydir, midview.vdir, midview.vup, gd->ang);
365     sum = 0.0;
366     for (gs = all_srcs; gs != NULL; gs = gs->next) {
367     p = posindex(gs->dir, mydir, midview.vup);
368     if (p <= FTINY)
369     continue;
370     sum += pow(gs->lum/p,1.6) * pow(gs->dom,0.8);
371     }
372     if (sum <= FTINY)
373     return(0.0);
374     sum /= gd->indirect/PI;
375     return(10*log10(0.478*sum));
376     }
377    
378    
379     double
380 greg 1.2 guth_dgr(gd) /* compute Guth discomfort glare rating */
381 greg 1.1 struct glare_dir *gd;
382     {
383     #define q(w) (20.4*w+1.52*pow(w,.2)-.075)
384     register struct glare_src *gs;
385 greg 1.7 FVECT mydir;
386 greg 1.1 double p;
387     double sum;
388 greg 1.3 double wtot, brsum;
389 greg 1.1 int n;
390 greg 2.4
391 greg 1.7 spinvector(mydir, midview.vdir, midview.vup, gd->ang);
392 greg 1.3 sum = wtot = brsum = 0.0; n = 0;
393 greg 1.1 for (gs = all_srcs; gs != NULL; gs = gs->next) {
394 greg 1.7 p = posindex(gs->dir, mydir, midview.vup);
395 greg 1.1 if (p <= FTINY)
396     continue;
397     sum += gs->lum * q(gs->dom) / p;
398 greg 1.3 brsum += gs->lum * gs->dom;
399     wtot += gs->dom;
400 greg 1.1 n++;
401     }
402     if (n == 0)
403     return(0.0);
404 greg 1.8 return( pow(.5*sum/pow((brsum+(5.-wtot)*gd->indirect/PI)/5.,.44),
405 greg 1.1 pow((double)n, -.0914) ) );
406     #undef q
407     }
408 greg 2.4
409    
410 greg 1.1 extern double erf(), erfc();
411 greg 2.4
412 greg 1.1 #ifndef M_SQRT2
413     #define M_SQRT2 1.41421356237309504880
414     #endif
415 greg 2.4
416 greg 1.1 #define norm_integral(z) (1.-.5*erfc((z)/M_SQRT2))
417 greg 2.4
418    
419 greg 1.1 double
420 greg 1.2 guth_vcp(gd) /* compute Guth visual comfort probability */
421 greg 1.1 struct glare_dir *gd;
422     {
423 greg 1.7 double dgr;
424 greg 2.4
425 greg 1.7 dgr = guth_dgr(gd);
426     if (dgr <= FTINY)
427     return(100.0);
428     return(100.*norm_integral(6.374-1.3227*log(dgr)));
429 greg 1.8 }
430 greg 2.4
431    
432 greg 1.8 double
433     cie_cgi(gd) /* compute CIE Glare Index */
434     struct glare_dir *gd;
435     {
436     register struct glare_src *gs;
437     FVECT mydir;
438     double dillum;
439     double p;
440     double sum;
441 greg 2.4
442 greg 1.8 spinvector(mydir, midview.vdir, midview.vup, gd->ang);
443     sum = 0.0;
444     for (gs = all_srcs; gs != NULL; gs = gs->next) {
445     p = posindex(gs->dir, mydir, midview.vup);
446     if (p <= FTINY)
447     continue;
448     sum += gs->lum*gs->lum * gs->dom / (p*p);
449     }
450     if (sum <= FTINY)
451     return(0.0);
452     dillum = direct(gd);
453     return(8.*log10(2.*sum*(1.+dillum/500.)/(dillum+gd->indirect)));
454 greg 2.4 }
455    
456    
457     double
458     ugr(gd) /* compute Unified Glare Rating */
459     struct glare_dir *gd;
460     {
461     register struct glare_src *gs;
462     FVECT mydir;
463     double p;
464     double sum;
465    
466     spinvector(mydir, midview.vdir, midview.vup, gd->ang);
467     sum = 0.0;
468     for (gs = all_srcs; gs != NULL; gs = gs->next) {
469     p = posindex(gs->dir, mydir, midview.vup);
470     if (p <= FTINY)
471     continue;
472     sum += gs->lum*gs->lum * gs->dom / (p*p);
473     }
474     if (sum <= FTINY)
475     return(0.0);
476     return(8.*log10(0.25*sum*PI/gd->indirect));
477 greg 1.1 }