3
#include <grass/glocale.h>
9
/* **********************************************************************c */
16
/* satellite / + / c */
19
/* / . \ _avis-_+_-asol_/ . c */
20
/* . \- -+ / . north c */
27
/* west + + + + + + + . + + + + +\+ + + + + . + + + + + + + + east c */
32
/* . + .. . , ' .. c */
36
/* south . . (phiv-phi0) c */
40
/* **********************************************************************c */
43
/* To take into account the variation of the solar constant as a function
47
dsol is a multiplicative factor to apply to the mean value of solar constant
49
float GeomCond::varsol ()
51
/* calculation of the variability of the solar constant during the year.
52
jday is the number of the day in the month */
54
if (month <= 2) j = (month - 1) * 31 + jday;
55
else if (month > 8) j = (month - 1) * 31 - (month - 2) / 2 - 2 + jday;
56
else j = (month - 1) * 31 - (month - 1) / 2 - 2 + jday;
58
/* Computing 2nd power */
59
double tmp = 1.f - cos ((float) (j - 4) * 0.9856f * M_PI / 180.f) * .01673f;
60
return 1.f / (float)(tmp * tmp);
64
/* spot, landsat5 and landsat7 is handled the same way */
65
void GeomCond::landsat(float tu)
68
/* xlon and xlat are the coordinates of the scene center. */
75
To compute the solar azimuthal and zenithal angles (in degrees) for a point over
76
the globe defined by its longitude and its latitude (in dec. degrees) for a day of the year (fixed by
77
number of the month and number of the day in the month) at any Greenwich Meridian Time (GMT
80
void GeomCond::possol(float tu)
84
/* solar position (zenithal angle asol,azimuthal angle phi0 */
86
/* jday is the number of the day in the month */
87
day_number(ia, nojour);
90
G_warning(_("The sun is not raised"));
93
void GeomCond::day_number(long int ia, long int& j)
97
j = (month - 1) * 31 + jday;
101
if (month > 8) j = (month - 1) * 31 - (month - 2) / 2 - 2 + jday;
102
else j = (month - 1) * 31 - (month - 1) / 2 - 2 + jday;
104
if (ia != 0 && ia % 4 == 0) ++j;
107
/* returns the sign of the element */
108
#define SIGN(X) (((X) >= 0) ? 1. : -1.)
110
void GeomCond::pos_fft (long int j, float tu)
112
/* Local variables */
113
double ah, et, az, caz, xla, tet, tsm, tsv, elev, azim, delta, amuzero;
115
/* solar position (zenithal angle asol,azimuthal angle phi0 */
117
/* j is the day number in the year */
119
/* mean solar time (heure decimale) */
120
tsm = tu + xlon / 15.;
121
xla = xlat * M_PI / 180.;
122
tet = (float)(j) * M_PI2 / 365.;
124
/* time equation (in mn.dec) */
125
et = 7.5e-5f + 0.001868f * cos (tet) - 0.032077f * sin (tet) -
126
0.014615f * cos (tet * 2.f) - 0.040849f * sin (tet * 2.f);
128
et = et * 12.f * 60.f / M_PI;
130
/* true solar time */
131
tsv = tsm + et / 60.f;
135
ah = tsv * 15.f * M_PI / 180.f;
137
/* solar declination (in radian) */
138
delta = 0.006918f - 0.399912f * cos (tet) + 0.070257f * sin (tet) -
139
0.006758f * cos (tet * 2.f) + 9.07e-4f * sin (tet * 2.f) -
140
0.002697f * cos (tet * 3.f) + 0.00148f * sin (tet * 3.f);
142
/* elevation,azimuth */
143
amuzero = sin (xla) * sin (delta) + cos (xla) * cos (delta) * cos (ah);
144
elev = asin (amuzero);
145
az = cos (delta) * sin (ah) / cos (elev);
147
if (fabs (az) - 1.f > 0.f) az = SIGN(az);
149
caz = (-cos (xla) * sin (delta) + sin (xla) * cos (delta) * cos (ah)) / cos (elev);
151
if (caz <= 0.f) azim = M_PI - azim;
153
if (caz > 0.f && az <= 0.f) azim += M_PI2;
156
if (azim > M_PI2) azim -= M_PI2;
158
elev = elev * 180. / M_PI;
160
/* conversion in degrees */
161
asol = (float)(90. - elev);
162
phi0 = (float)(azim * 180. / M_PI);
167
1 = meteosat observation
168
2 = goes east observation
169
3 = goes west observation
171
void GeomCond::posobs(float tu, int nc, int nl)
175
if(igeom == 1) /* meteosat observation */
179
alti = 42164.0 - 6378.155;
181
else if(igeom == 2) /* goes east observation */
185
alti = 42107.0 - 6378.155;
187
else /* goes west observation */
191
alti = 42147.0 - 6378.155;
195
const double re = 6378.155;
196
const double aaa = 1. / 297.;
197
const double rp = re / (1.f + aaa);
198
const double cdr = M_PI / 180.;
199
const double crd = 180. / M_PI;
206
deltax = 18.0 / 5000.0;
207
deltay = 18.0 / 2500.0;
211
deltax = 18.0 / 12997.0;
212
deltay = 20.0 / 17331.0;
215
double x = xr * deltax * cdr;
216
double y = yr * deltay * cdr;
217
double rs = re + alti;
218
double tanx = tan(x);
219
double tany = tan(y);
220
double val1 = 1.0 + (tanx * tanx);
221
double val2 = 1.0 + (tany * (1.0 + aaa)) * (tany * (1.0 + aaa));
223
double cosx2 = 1. / (val1 * val2);
225
double sn, zt, xt, yt, teta, ylat, ylon;
226
if((1. / cosx2) > ((yk * yk) / (yk*yk - 1.)))
228
G_warning(_("No possibility to compute lat. and long."));
233
sn = (rs - (re * (sqrt((yk * yk) - (yk*yk - 1.) * (1. / cosx2))))) / (1. / cosx2);
236
yt = sn * tany / cos(x);
237
teta = asin(yt / rp);
238
ylat = (atan(((tan(teta)) * rp) / re));
239
ylon = atan(xt / zt);
242
xlat = (float)(ylat * crd);
244
if(igeom == 1) xlon = (float)(ylon * crd);
245
else if(igeom == 2) xlon = (float)(ylon * crd - 75.);
246
else xlon = (float)(ylon * crd - 135.);
250
if(igeom == 1) ylon = xlon * M_PI / 180.;
251
else if(igeom == 2) ylon = xlon * M_PI / 180. + 75. * cdr;
252
else ylon = xlon * M_PI / 180. + 135. * cdr;
254
ylat = xlat * M_PI / 180.;
255
double gam = sqrt(((1. / cosx2) - 1.) * cosx2);
256
avis = (float)(asin((1. + alti / re) * (gam)) * 180. / M_PI);
257
phiv = (float)((atan2(tan(ylon),sin(ylat)) + M_PI) * 180. / M_PI);
260
void GeomCond::posnoa(float tu, int nc, float xlonan, float campm, float hna)
263
orbite inclination ai in radians
266
campm allows the user to switch to pm platforms */
268
const double r = 860. / 6378.155;
269
const double ai = 98.96 * M_PI / 180.;
270
const double an = 360. * M_PI / (6119. * 180.);
271
double ylonan = xlonan * M_PI / 180.;
272
double t = tu * 3600;
277
double delt = ((nc - (2048 + 1) / 2.) * 55.385 / ((2048. - 1) / 2.));
278
delt = campm * delt * M_PI / 180.;
279
avis = (float)asin((1 + r) * sin(delt));
280
double d = avis - delt;
281
double y = cos(d) * cos(ai) * sin(u) - sin(ai) * sin(d);
282
double z = cos(d) * sin(ai) * sin(u) + cos(ai) * sin(d);
283
double ylat = asin(z);
284
double cosy = cos(d) * cos(u) / cos(ylat);
286
double siny = y / cos(ylat);
287
double ylon = asin(siny);
290
if(siny > 0) ylon = M_PI - ylon;
291
if(siny <= 0) ylon = -(M_PI + ylon);
293
double ylo1 = ylon + ylonan - (t - hnam) * 2. * M_PI / 86400.;
294
xlat = (float)(ylat * 180. / M_PI);
295
xlon = (float)(ylo1 * 180. / M_PI);
301
double zlat = asin(sin(ai) * sin(u));
302
double zlon = atan2(cos(ai) * sin(u),cos(u));
305
double xnum = sin(zlon - ylon) * cos(zlat) / sin(fabs(d));
306
double xden = (sin(zlat) - sin(ylat) * cos(d)) / cos(ylat) / sin(fabs(d));
307
phiv = (float)atan2(xnum,xden);
310
phiv = (float)(phiv * 180. / M_PI);
311
avis = (float)(fabs(avis) * 180. / M_PI);
314
void GeomCond::parse()
317
cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
319
float campm = -1.0f; /* initialize in case igeom == 5 */
320
float tu, xlonan, hna;
325
case 0: /* internal format */
333
cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
336
case 1: /* meteosat observation */
337
case 2: /* goes east observation */
338
case 3: /* goes west observation */
345
cin.ignore(numeric_limits<int>::max(),'\n');
349
case 4: campm = 1.0f;
358
cin.ignore(numeric_limits<int>::max(),'\n');
359
posnoa(tu, nc, xlonan, campm, hna);
362
case 6: /* hrv ( spot ) * enter month,day,hh.ddd,long.,lat. */
363
case 7: /* tm ( landsat ) * enter month,day,hh.ddd,long.,lat. */
364
case 8: /* etm+ ( landsat7) * enter month,day,hh.ddd,long.,lat. */
365
case 9: /* liss ( IRS 1C) * enter month,day,hh.ddd,long.,lat. */
366
case 10: /* aster * enter month,day,hh.ddd,long.,lat. */
367
case 11: /* avnir * enter month,day,hh.ddd,long.,lat. */
368
case 12: /* ikonos * enter month,day,hh.ddd,long.,lat. */
369
case 13: /* rapideye * enter month,day,hh.ddd,long.,lat. */
370
case 14: /* vgt1_spot4 * enter month,day,hh.ddd,long.,lat. */
371
case 15: /* vgt2_spot5 * enter month,day,hh.ddd,long.,lat. */
372
case 16: /* worldview2 * enter month,day,hh.ddd,long.,lat. */
373
case 17: /* quickbird2 * enter month,day,hh.ddd,long.,lat. */
374
case 18: /* Landsat 8 * enter month,day,hh.ddd,long.,lat. */
381
cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
385
default: G_fatal_error(_("Unsupported/unreadable format in control file (found igeom=%ld)"), igeom);
389
/* ********************************************************************** */
391
/* / scattered direction */
395
/* incident + + + + + + + + + + + + + + + */
398
/* ********************************************************************** */
399
phi = (float)fabs(phiv - phi0);
400
phirad = (phi0 - phiv) * (float)M_PI / 180.f;
401
if (phirad < 0.f) phirad += (float)M_PI2;
402
if (phirad > M_PI2) phirad -= (float)M_PI2;
404
xmus = (float)cos (asol * M_PI / 180.f);
405
xmuv = (float)cos (avis * M_PI / 180.f);
406
xmup = (float)cos (phirad);
407
xmud = -xmus * xmuv - (float)sqrt (1.f - xmus * xmus) * (float)sqrt (1.f - xmuv * xmuv) * xmup;
409
/* test vermote bug */
410
if (xmud > 1.f) xmud = 1.f;
411
if (xmud < -1.f) xmud = -1.f;
412
adif = (float)acos (xmud) * 180.f / (float)M_PI;
417
/* ---- print geometrical conditions ---- */
418
void GeomCond::print()
420
static const string etiq1[] = {
421
string(" user defined conditions "),
422
string(" Meteosat observation "),
423
string(" GOES east observation "),
424
string(" GOES west observation "),
425
string(" AVHRR (AM noaa) observation "),
426
string(" AVHRR (PM noaa) observation "),
427
string(" H.R.V. observation "),
428
string(" T.M. observation "),
429
string(" ETM+ observation "),
430
string(" LISS observation "),
431
string(" ASTER observation "),
432
string(" AVNIR observation "),
433
string(" Ikonos observation "),
434
string(" Rapideye observation "),
435
string(" VGT1-SPOT4 observation "),
436
string(" VGT2-SPOT5 observation "),
437
string(" Worldview2 observation "),
438
string(" Quickbird2 observation "),
439
string(" Landsat 8 observation ")
442
static const string head(" geometrical conditions identity ");
443
static const string line(" ------------------------------- ");
444
Output::Begin(); Output::Repeat(22,' '); Output::Print(head); Output::End();
445
Output::Begin(); Output::Repeat(22,' '); Output::Print(line); Output::End();
448
Output::Begin(); Output::Repeat(22,' '); Output::Print(etiq1[igeom]); Output::End();
449
Output::Begin(); Output::End();
452
Output::Begin(); Output::Repeat(2,' ');
454
s1.setf(ios::fixed, ios::floatfield);
455
s1 << " month: " << month << " day: " << jday;
457
Output::Print(s1.str());
461
Output::Begin(); Output::Repeat(2,' ');
463
s2.setf(ios::fixed, ios::floatfield);
464
s2 << setprecision(2);
467
s2 << " solar zenith angle: " << setw(6) << asol << " deg ";
468
s2 << " solar azimuthal angle: " << setw(6) << phi0 << " deg";
470
Output::Print(s2.str());
474
Output::Begin(); Output::Repeat(2,' ');
476
s3.setf(ios::fixed, ios::floatfield);
477
s3 << setprecision(2);
478
s3 << " view zenith angle: " << setw(6) << avis << " deg ";
479
s3 << " view azimuthal angle: " << setw(6) << phiv << " deg ";
481
Output::Print(s3.str());
483
Output::Begin(); Output::Repeat(2,' ');
485
s4.setf(ios::fixed, ios::floatfield);
486
s4 << setprecision(2);
487
s4 << " scattering angle: " << setw(6) << adif << " deg ";
488
s4 << " azimuthal angle difference: " << setw(6) << phi << " deg ";
490
Output::Print(s4.str());
493
Output::Begin(); Output::End();
496
GeomCond GeomCond::Parse()