| 1 | < | /* Copyright (c) 1986 Regents of the University of California */ | 
| 1 | > | /* Copyright (c) 1992 Regents of the University of California */ | 
| 2 |  |  | 
| 3 |  | #ifndef lint | 
| 4 |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 19 |  |  | 
| 20 |  | #include  "color.h" | 
| 21 |  |  | 
| 22 | – | #ifndef atof | 
| 23 | – | extern double  atof(); | 
| 24 | – | #endif | 
| 22 |  | extern char  *strcpy(), *strcat(), *malloc(); | 
| 23 |  | extern double  stadj(), sdec(), sazi(), salt(); | 
| 24 |  |  | 
| 26 |  |  | 
| 27 |  | #define  DOT(v1,v2)     (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]) | 
| 28 |  |  | 
| 29 | + | #define  S_CLEAR        1 | 
| 30 | + | #define  S_OVER         2 | 
| 31 | + | #define  S_UNIF         3 | 
| 32 | + | #define  S_INTER        4 | 
| 33 | + |  | 
| 34 | + | #define  overcast       (skytype==S_OVER|skytype==S_UNIF) | 
| 35 | + |  | 
| 36 |  | double  normsc(); | 
| 37 |  | /* sun calculation constants */ | 
| 38 |  | extern double  s_latitude; | 
| 44 |  | int  tsolar;                                    /* 0=standard, 1=solar */ | 
| 45 |  | double  altitude, azimuth;                      /* or solar angles */ | 
| 46 |  | /* default values */ | 
| 47 | < | int  cloudy = 0;                                /* 1=standard, 2=uniform */ | 
| 47 | > | int  skytype = S_CLEAR;                         /* sky type */ | 
| 48 |  | int  dosun = 1; | 
| 49 | < | double  zenithbr = -1.0; | 
| 49 | > | double  zenithbr = 0.0; | 
| 50 | > | int     u_zenith = 0;                           /* -1=irradiance, 1=radiance */ | 
| 51 |  | double  turbidity = 2.75; | 
| 52 |  | double  gprefl = 0.2; | 
| 53 |  | /* computed values */ | 
| 54 |  | double  sundir[3]; | 
| 55 |  | double  groundbr; | 
| 56 |  | double  F2; | 
| 57 | < | double  solarbr = -1.0; | 
| 57 | > | double  solarbr = 0.0; | 
| 58 | > | int     u_solar = 0;                            /* -1=irradiance, 1=radiance */ | 
| 59 |  |  | 
| 60 |  | char  *progname; | 
| 61 |  | char  errmsg[128]; | 
| 94 |  | if (argv[i][0] == '-' || argv[i][0] == '+') | 
| 95 |  | switch (argv[i][1]) { | 
| 96 |  | case 's': | 
| 97 | < | cloudy = 0; | 
| 97 | > | skytype = S_CLEAR; | 
| 98 |  | dosun = argv[i][0] == '+'; | 
| 99 |  | break; | 
| 100 |  | case 'r': | 
| 101 | + | case 'R': | 
| 102 | + | u_solar = argv[i][1]=='R' ? -1 : 1; | 
| 103 |  | solarbr = atof(argv[++i]); | 
| 104 |  | break; | 
| 105 |  | case 'c': | 
| 106 | < | cloudy = argv[i][0] == '+' ? 2 : 1; | 
| 106 | > | skytype = S_OVER; | 
| 107 |  | dosun = 0; | 
| 108 |  | break; | 
| 109 | + | case 'u': | 
| 110 | + | skytype = S_UNIF; | 
| 111 | + | dosun = 0; | 
| 112 | + | break; | 
| 113 | + | case 'i': | 
| 114 | + | skytype = S_INTER; | 
| 115 | + | dosun = argv[i][0] == '+'; | 
| 116 | + | break; | 
| 117 |  | case 't': | 
| 118 |  | turbidity = atof(argv[++i]); | 
| 119 |  | break; | 
| 120 |  | case 'b': | 
| 121 | + | case 'B': | 
| 122 | + | u_zenith = argv[i][1]=='B' ? -1 : 1; | 
| 123 |  | zenithbr = atof(argv[++i]); | 
| 124 |  | break; | 
| 125 |  | case 'g': | 
| 155 |  |  | 
| 156 |  | computesky()                    /* compute sky parameters */ | 
| 157 |  | { | 
| 158 | + | double  normfactor; | 
| 159 |  | /* compute solar direction */ | 
| 160 |  | if (month) {                    /* from date and time */ | 
| 161 |  | int  jd; | 
| 169 |  | st = hour + stadj(jd); | 
| 170 |  | altitude = salt(sd, st); | 
| 171 |  | azimuth = sazi(sd, st); | 
| 172 | + | printf("# Solar altitude and azimuth: %.1f %.1f\n", | 
| 173 | + | 180./PI*altitude, 180./PI*azimuth); | 
| 174 |  | } | 
| 175 | + | if (!overcast && altitude > 87.*PI/180.) { | 
| 176 | + | fprintf(stderr, | 
| 177 | + | "%s: warning - sun too close to zenith, reducing altitude to 87 degrees\n", | 
| 178 | + | progname); | 
| 179 | + | printf( | 
| 180 | + | "# warning - sun too close to zenith, reducing altitude to 87 degrees\n"); | 
| 181 | + | altitude = 87.*PI/180.; | 
| 182 | + | } | 
| 183 |  | sundir[0] = -sin(azimuth)*cos(altitude); | 
| 184 |  | sundir[1] = -cos(azimuth)*cos(altitude); | 
| 185 |  | sundir[2] = sin(altitude); | 
| 186 |  |  | 
| 187 | + | /* Compute normalization factor */ | 
| 188 | + | switch (skytype) { | 
| 189 | + | case S_UNIF: | 
| 190 | + | normfactor = 1.0; | 
| 191 | + | break; | 
| 192 | + | case S_OVER: | 
| 193 | + | normfactor = 0.777778; | 
| 194 | + | break; | 
| 195 | + | case S_CLEAR: | 
| 196 | + | F2 = 0.274*(0.91 + 10.0*exp(-3.0*(PI/2.0-altitude)) + | 
| 197 | + | 0.45*sundir[2]*sundir[2]); | 
| 198 | + | normfactor = normsc()/F2/PI; | 
| 199 | + | break; | 
| 200 | + | case S_INTER: | 
| 201 | + | F2 = (2.739 + .9891*sin(.3119+2.6*altitude)) * | 
| 202 | + | exp(-(PI/2.0-altitude)*(.4441+1.48*altitude)); | 
| 203 | + | normfactor = normsc()/F2/PI; | 
| 204 | + | break; | 
| 205 | + | } | 
| 206 |  | /* Compute zenith brightness */ | 
| 207 | < | if (zenithbr <= 0.0) | 
| 208 | < | if (cloudy) { | 
| 207 | > | if (u_zenith == -1) | 
| 208 | > | zenithbr /= normfactor*PI; | 
| 209 | > | else if (u_zenith == 0) { | 
| 210 | > | if (overcast) | 
| 211 |  | zenithbr = 8.6*sundir[2] + .123; | 
| 212 | < | zenithbr *= 1000.0/WHTEFFICACY; | 
| 163 | < | } else { | 
| 212 | > | else | 
| 213 |  | zenithbr = (1.376*turbidity-1.81)*tan(altitude)+0.38; | 
| 214 | < | zenithbr *= 1000.0/SKYEFFICACY; | 
| 215 | < | } | 
| 216 | < | if (zenithbr < 0.0) | 
| 217 | < | zenithbr = 0.0; | 
| 169 | < | /* Compute horizontal radiance */ | 
| 170 | < | if (cloudy) { | 
| 171 | < | if (cloudy == 2) | 
| 172 | < | groundbr = zenithbr; | 
| 214 | > | if (skytype == S_INTER) | 
| 215 | > | zenithbr = (zenithbr + 8.6*sundir[2] + .123)/2.0; | 
| 216 | > | if (zenithbr < 0.0) | 
| 217 | > | zenithbr = 0.0; | 
| 218 |  | else | 
| 219 | < | groundbr = zenithbr*0.777778; | 
| 175 | < | printf("# Ground ambient level: %f\n", groundbr); | 
| 176 | < | } else { | 
| 177 | < | F2 = 0.274*(0.91 + 10.0*exp(-3.0*(PI/2.0-altitude)) + | 
| 178 | < | 0.45*sundir[2]*sundir[2]); | 
| 179 | < | groundbr = zenithbr*normsc(altitude)/F2/PI; | 
| 180 | < | printf("# Ground ambient level: %f\n", groundbr); | 
| 181 | < | if (sundir[2] > 0.0 && solarbr != 0.0) { | 
| 182 | < | if (solarbr < 0.0) | 
| 183 | < | solarbr = 1.5e9/SUNEFFICACY * | 
| 184 | < | (1.147 - .147/(sundir[2]>.16?sundir[2]:.16)); | 
| 185 | < | groundbr += solarbr*6e-5*sundir[2]/PI; | 
| 186 | < | } else | 
| 187 | < | dosun = 0; | 
| 219 | > | zenithbr *= 1000.0/SKYEFFICACY; | 
| 220 |  | } | 
| 221 | + | /* Compute horizontal radiance */ | 
| 222 | + | groundbr = zenithbr*normfactor; | 
| 223 | + | printf("# Ground ambient level: %.1f\n", groundbr); | 
| 224 | + | if (sundir[2] > 0.0 && (!u_solar || solarbr > 0.0)) { | 
| 225 | + | if (u_solar == -1) | 
| 226 | + | solarbr /= 6e-5*sundir[2]; | 
| 227 | + | else if (u_solar == 0) { | 
| 228 | + | solarbr = 1.5e9/SUNEFFICACY * | 
| 229 | + | (1.147 - .147/(sundir[2]>.16?sundir[2]:.16)); | 
| 230 | + | if (skytype == S_INTER) | 
| 231 | + | solarbr *= 0.15;        /* fudge factor! */ | 
| 232 | + | } | 
| 233 | + | groundbr += 6e-5/PI*solarbr*sundir[2]; | 
| 234 | + | } else | 
| 235 | + | dosun = 0; | 
| 236 |  | groundbr *= gprefl; | 
| 237 |  | } | 
| 238 |  |  | 
| 249 |  | } | 
| 250 |  |  | 
| 251 |  | printf("\nvoid brightfunc skyfunc\n"); | 
| 252 | < | printf("2 skybright skybright.cal\n"); | 
| 252 | > | printf("2 skybr skybright.cal\n"); | 
| 253 |  | printf("0\n"); | 
| 254 | < | if (cloudy) | 
| 255 | < | printf("3 %d %.2e %.2e\n", cloudy, zenithbr, groundbr); | 
| 254 | > | if (overcast) | 
| 255 | > | printf("3 %d %.2e %.2e\n", skytype, zenithbr, groundbr); | 
| 256 |  | else | 
| 257 | < | printf("7 -1 %.2e %.2e %.2e %f %f %f\n", zenithbr, groundbr, | 
| 258 | < | F2, sundir[0], sundir[1], sundir[2]); | 
| 257 | > | printf("7 %d %.2e %.2e %.2e %f %f %f\n", | 
| 258 | > | skytype, zenithbr, groundbr, F2, | 
| 259 | > | sundir[0], sundir[1], sundir[2]); | 
| 260 |  | } | 
| 261 |  |  | 
| 262 |  |  | 
| 263 |  | printdefaults()                 /* print default values */ | 
| 264 |  | { | 
| 265 | < | if (cloudy == 1) | 
| 265 | > | switch (skytype) { | 
| 266 | > | case S_OVER: | 
| 267 |  | printf("-c\t\t\t\t# Cloudy sky\n"); | 
| 268 | < | else if (cloudy == 2) | 
| 269 | < | printf("+c\t\t\t\t# Uniform cloudy sky\n"); | 
| 270 | < | else if (dosun) | 
| 271 | < | printf("+s\t\t\t\t# Sunny sky with sun\n"); | 
| 272 | < | else | 
| 273 | < | printf("-s\t\t\t\t# Sunny sky without sun\n"); | 
| 268 | > | break; | 
| 269 | > | case S_UNIF: | 
| 270 | > | printf("-u\t\t\t\t# Uniform cloudy sky\n"); | 
| 271 | > | break; | 
| 272 | > | case S_INTER: | 
| 273 | > | if (dosun) | 
| 274 | > | printf("+i\t\t\t\t# Intermediate sky with sun\n"); | 
| 275 | > | else | 
| 276 | > | printf("-i\t\t\t\t# Intermediate sky without sun\n"); | 
| 277 | > | break; | 
| 278 | > | case S_CLEAR: | 
| 279 | > | if (dosun) | 
| 280 | > | printf("+s\t\t\t\t# Sunny sky with sun\n"); | 
| 281 | > | else | 
| 282 | > | printf("-s\t\t\t\t# Sunny sky without sun\n"); | 
| 283 | > | break; | 
| 284 | > | } | 
| 285 |  | printf("-g %f\t\t\t# Ground plane reflectance\n", gprefl); | 
| 286 |  | if (zenithbr > 0.0) | 
| 287 |  | printf("-b %f\t\t\t# Zenith radiance (watts/ster/m2\n", zenithbr); | 
| 306 |  |  | 
| 307 |  |  | 
| 308 |  | double | 
| 309 | < | normsc(theta)                   /* compute normalization factor (E0*F2/L0) */ | 
| 250 | < | double  theta; | 
| 309 | > | normsc()                        /* compute normalization factor (E0*F2/L0) */ | 
| 310 |  | { | 
| 311 | < | static double  nf[5] = {2.766521, 0.547665, | 
| 312 | < | -0.369832, 0.009237, 0.059229}; | 
| 311 | > | static double  nfc[2][5] = { | 
| 312 | > | /* clear sky approx. */ | 
| 313 | > | {2.766521, 0.547665, -0.369832, 0.009237, 0.059229}, | 
| 314 | > | /* intermediate sky approx. */ | 
| 315 | > | {3.5556, -2.7152, -1.3081, 1.0660, 0.60227}, | 
| 316 | > | }; | 
| 317 | > | register double  *nf; | 
| 318 |  | double  x, nsc; | 
| 319 |  | register int  i; | 
| 320 |  | /* polynomial approximation */ | 
| 321 | < | x = (theta - PI/4.0)/(PI/4.0); | 
| 322 | < | nsc = nf[4]; | 
| 323 | < | for (i = 3; i >= 0; i--) | 
| 321 | > | nf = nfc[skytype==S_INTER]; | 
| 322 | > | x = (altitude - PI/4.0)/(PI/4.0); | 
| 323 | > | nsc = nf[i=4]; | 
| 324 | > | while (i--) | 
| 325 |  | nsc = nsc*x + nf[i]; | 
| 326 |  |  | 
| 327 |  | return(nsc); |