GeomCond.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. extern "C" {
  2. #include <grass/gis.h>
  3. #include <grass/glocale.h>
  4. }
  5. #include "GeomCond.h"
  6. #include "common.h"
  7. /* **********************************************************************c */
  8. /* c */
  9. /* * sun c */
  10. /* \ * / c */
  11. /* * * * * * c */
  12. /* z / * \ c */
  13. /* + /+ c */
  14. /* satellite / + / c */
  15. /* o/ + / c */
  16. /* /.\ + /. c */
  17. /* / . \ _avis-_+_-asol_/ . c */
  18. /* . \- -+ / . north c */
  19. /* . \ + / . + c */
  20. /* . \ + / .+ c */
  21. /* . \ + / +. c */
  22. /* . \ + / + . c */
  23. /* . \ + / + . c */
  24. /* . \ +/ + . c */
  25. /* west + + + + + + + . + + + + +\+ + + + + . + + + + + + + + east c */
  26. /* . +.. . c */
  27. /* . + . . . c */
  28. /* . + . . . c */
  29. /* . + . .'. . c */
  30. /* . + .. . , ' .. c */
  31. /* .+ . \ . c */
  32. /* +. . \ . c */
  33. /* + . . \ . c */
  34. /* south . . (phiv-phi0) c */
  35. /* c */
  36. /* c */
  37. /* c */
  38. /* **********************************************************************c */
  39. /* To take into account the variation of the solar constant as a function
  40. of the Julian day.
  41. return dsol
  42. dsol is a multiplicative factor to apply to the mean value of solar constant
  43. */
  44. float GeomCond::varsol ()
  45. {
  46. /* calculation of the variability of the solar constant during the year.
  47. jday is the number of the day in the month */
  48. long int j;
  49. if (month <= 2) j = (month - 1) * 31 + jday;
  50. else if (month > 8) j = (month - 1) * 31 - (month - 2) / 2 - 2 + jday;
  51. else j = (month - 1) * 31 - (month - 1) / 2 - 2 + jday;
  52. /* Computing 2nd power */
  53. double tmp = 1.f - cos ((float) (j - 4) * 0.9856f * M_PI / 180.f) * .01673f;
  54. return 1.f / (float)(tmp * tmp);
  55. }
  56. /* spot, landsat5 and landsat7 is handled the same way */
  57. void GeomCond::landsat(float tu)
  58. {
  59. /* warning !!! */
  60. /* xlon and xlat are the coordinates of the scene center. */
  61. avis = 0.f;
  62. phiv = 0.f;
  63. possol(tu);
  64. }
  65. /*
  66. To compute the solar azimuthal and zenithal angles (in degrees) for a point over
  67. the globe defined by its longitude and its latitude (in dec. degrees) for a day of the year (fixed by
  68. number of the month and number of the day in the month) at any Greenwich Meridian Time (GMT
  69. dec. hour).
  70. */
  71. void GeomCond::possol(float tu)
  72. {
  73. long int ia = 0;
  74. long int nojour;
  75. /* solar position (zenithal angle asol,azimuthal angle phi0 */
  76. /* in degrees) */
  77. /* jday is the number of the day in the month */
  78. day_number(ia, nojour);
  79. pos_fft (nojour, tu);
  80. if (asol > 90.f)
  81. G_warning(_("The sun is not raised"));
  82. }
  83. void GeomCond::day_number(long int ia, long int& j)
  84. {
  85. if (month <= 2)
  86. {
  87. j = (month - 1) * 31 + jday;
  88. return;
  89. }
  90. if (month > 8) j = (month - 1) * 31 - (month - 2) / 2 - 2 + jday;
  91. else j = (month - 1) * 31 - (month - 1) / 2 - 2 + jday;
  92. if (ia != 0 && ia % 4 == 0) ++j;
  93. }
  94. /* returns the sign of the element */
  95. #define SIGN(X) (((X) >= 0) ? 1. : -1.)
  96. void GeomCond::pos_fft (long int j, float tu)
  97. {
  98. /* Local variables */
  99. double ah, et, az, caz, xla, tet, tsm, tsv, elev, azim, delta, amuzero;
  100. /* solar position (zenithal angle asol,azimuthal angle phi0 */
  101. /* in degrees) */
  102. /* j is the day number in the year */
  103. /* mean solar time (heure decimale) */
  104. tsm = tu + xlon / 15.;
  105. xla = xlat * M_PI / 180.;
  106. tet = (float)(j) * M_PI2 / 365.;
  107. /* time equation (in mn.dec) */
  108. et = 7.5e-5f + 0.001868f * cos (tet) - 0.032077f * sin (tet) -
  109. 0.014615f * cos (tet * 2.f) - 0.040849f * sin (tet * 2.f);
  110. et = et * 12.f * 60.f / M_PI;
  111. /* true solar time */
  112. tsv = tsm + et / 60.f;
  113. tsv += -12.f;
  114. /* hour angle */
  115. ah = tsv * 15.f * M_PI / 180.f;
  116. /* solar declination (in radian) */
  117. delta = 0.006918f - 0.399912f * cos (tet) + 0.070257f * sin (tet) -
  118. 0.006758f * cos (tet * 2.f) + 9.07e-4f * sin (tet * 2.f) -
  119. 0.002697f * cos (tet * 3.f) + 0.00148f * sin (tet * 3.f);
  120. /* elevation,azimuth */
  121. amuzero = sin (xla) * sin (delta) + cos (xla) * cos (delta) * cos (ah);
  122. elev = asin (amuzero);
  123. az = cos (delta) * sin (ah) / cos (elev);
  124. if (fabs (az) - 1.f > 0.f) az = SIGN(az);
  125. caz = (-cos (xla) * sin (delta) + sin (xla) * cos (delta) * cos (ah)) / cos (elev);
  126. azim = asin (az);
  127. if (caz <= 0.f) azim = M_PI - azim;
  128. if (caz > 0.f && az <= 0.f) azim += M_PI2;
  129. azim += M_PI;
  130. if (azim > M_PI2) azim -= M_PI2;
  131. elev = elev * 180. / M_PI;
  132. /* conversion in degrees */
  133. asol = (float)(90. - elev);
  134. phi0 = (float)(azim * 180. / M_PI);
  135. }
  136. /*
  137. convert:
  138. 1 = meteosat observation
  139. 2 = goes east observation
  140. 3 = goes west observation
  141. */
  142. void GeomCond::posobs(float tu, int nc, int nl)
  143. {
  144. double yr, xr, alti;
  145. if(igeom == 1) /* meteosat observation */
  146. {
  147. yr = nl - 1250.5;
  148. xr = nc - 2500.5;
  149. alti = 42164.0 - 6378.155;
  150. }
  151. else if(igeom == 2) /* goes east observation */
  152. {
  153. yr = nl - 8665.5;
  154. xr = nc - 6498.5;
  155. alti = 42107.0 - 6378.155;
  156. }
  157. else /* goes west observation */
  158. {
  159. yr = nl - 8665.5;
  160. xr = nc - 6498.5;
  161. alti = 42147.0 - 6378.155;
  162. }
  163. const double re = 6378.155;
  164. const double aaa = 1. / 297.;
  165. const double rp = re / (1.f + aaa);
  166. const double cdr = M_PI / 180.;
  167. const double crd = 180. / M_PI;
  168. double deltax;
  169. double deltay;
  170. if(igeom == 1)
  171. {
  172. deltax = 18.0 / 5000.0;
  173. deltay = 18.0 / 2500.0;
  174. }
  175. else
  176. {
  177. deltax = 18.0 / 12997.0;
  178. deltay = 20.0 / 17331.0;
  179. }
  180. double x = xr * deltax * cdr;
  181. double y = yr * deltay * cdr;
  182. double rs = re + alti;
  183. double tanx = tan(x);
  184. double tany = tan(y);
  185. double val1 = 1.0 + (tanx * tanx);
  186. double val2 = 1.0 + (tany * (1.0 + aaa)) * (tany * (1.0 + aaa));
  187. double yk = rs / re;
  188. double cosx2 = 1. / (val1 * val2);
  189. double sn, zt, xt, yt, teta, ylat, ylon;
  190. if((1. / cosx2) > ((yk * yk) / (yk*yk - 1.)))
  191. {
  192. G_warning(_("No possibility to compute lat. and long."));
  193. return;
  194. }
  195. else
  196. {
  197. sn = (rs - (re * (sqrt((yk * yk) - (yk*yk - 1.) * (1. / cosx2))))) / (1. / cosx2);
  198. zt = rs - sn;
  199. xt = -(sn * tanx);
  200. yt = sn * tany / cos(x);
  201. teta = asin(yt / rp);
  202. ylat = (atan(((tan(teta)) * rp) / re));
  203. ylon = atan(xt / zt);
  204. }
  205. xlat = (float)(ylat * crd);
  206. if(igeom == 1) xlon = (float)(ylon * crd);
  207. else if(igeom == 2) xlon = (float)(ylon * crd - 75.);
  208. else xlon = (float)(ylon * crd - 135.);
  209. possol(tu);
  210. if(igeom == 1) ylon = xlon * M_PI / 180.;
  211. else if(igeom == 2) ylon = xlon * M_PI / 180. + 75. * cdr;
  212. else ylon = xlon * M_PI / 180. + 135. * cdr;
  213. ylat = xlat * M_PI / 180.;
  214. double gam = sqrt(((1. / cosx2) - 1.) * cosx2);
  215. avis = (float)(asin((1. + alti / re) * (gam)) * 180. / M_PI);
  216. phiv = (float)((atan2(tan(ylon),sin(ylat)) + M_PI) * 180. / M_PI);
  217. }
  218. void GeomCond::posnoa(float tu, int nc, float xlonan, float campm, float hna)
  219. {
  220. /* noaa 6 definition
  221. orbite inclination ai in radians
  222. hor mouv in rad/s an
  223. h/r=860/6378
  224. campm allows the user to switch to pm platforms */
  225. const double r = 860. / 6378.155;
  226. const double ai = 98.96 * M_PI / 180.;
  227. const double an = 360. * M_PI / (6119. * 180.);
  228. double ylonan = xlonan * M_PI / 180.;
  229. double t = tu * 3600;
  230. double hnam = hna;
  231. hnam = hnam * 3600;
  232. double u = t - hnam;
  233. u = campm * u * an;
  234. double delt = ((nc - (2048 + 1) / 2.) * 55.385 / ((2048. - 1) / 2.));
  235. delt = campm * delt * M_PI / 180.;
  236. avis = (float)asin((1 + r) * sin(delt));
  237. double d = avis - delt;
  238. double y = cos(d) * cos(ai) * sin(u) - sin(ai) * sin(d);
  239. double z = cos(d) * sin(ai) * sin(u) + cos(ai) * sin(d);
  240. double ylat = asin(z);
  241. double cosy = cos(d) * cos(u) / cos(ylat);
  242. double siny = y / cos(ylat);
  243. double ylon = asin(siny);
  244. if(cosy <= 0.)
  245. {
  246. if(siny > 0) ylon = M_PI - ylon;
  247. if(siny <= 0) ylon = -(M_PI + ylon);
  248. }
  249. double ylo1 = ylon + ylonan - (t - hnam) * 2. * M_PI / 86400.;
  250. xlat = (float)(ylat * 180. / M_PI);
  251. xlon = (float)(ylo1 * 180. / M_PI);
  252. possol(tu);
  253. double zlat = asin(sin(ai) * sin(u));
  254. double zlon = atan2(cos(ai) * sin(u),cos(u));
  255. if(nc != 1024)
  256. {
  257. double xnum = sin(zlon - ylon) * cos(zlat) / sin(fabs(d));
  258. double xden = (sin(zlat) - sin(ylat) * cos(d)) / cos(ylat) / sin(fabs(d));
  259. phiv = (float)atan2(xnum,xden);
  260. }
  261. else phiv = 0.;
  262. phiv = (float)(phiv * 180. / M_PI);
  263. avis = (float)(fabs(avis) * 180. / M_PI);
  264. }
  265. void GeomCond::parse()
  266. {
  267. cin >> igeom;
  268. cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
  269. float campm = -1.0f; /* initialize in case igeom == 5 */
  270. float tu, xlonan, hna;
  271. int nc, nl;
  272. switch(igeom)
  273. {
  274. case 0: /* internal format */
  275. {
  276. cin >> asol;
  277. cin >> phi0;
  278. cin >> avis;
  279. cin >> phiv;
  280. cin >> month;
  281. cin >> jday;
  282. cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
  283. break;
  284. }
  285. case 1: /* meteosat observation */
  286. case 2: /* goes east observation */
  287. case 3: /* goes west observation */
  288. {
  289. cin >> month;
  290. cin >> jday;
  291. cin >> tu;
  292. cin >> nc;
  293. cin >> nl;
  294. cin.ignore(numeric_limits<int>::max(),'\n');
  295. posobs(tu, nc, nl);
  296. break;
  297. }
  298. case 4: campm = 1.0f;
  299. case 5:
  300. {
  301. cin >> month;
  302. cin >> jday;
  303. cin >> tu;
  304. cin >> nc;
  305. cin >> xlonan;
  306. cin >> hna;
  307. cin.ignore(numeric_limits<int>::max(),'\n');
  308. posnoa(tu, nc, xlonan, campm, hna);
  309. break;
  310. }
  311. case 6: /* hrv ( spot ) * enter month,day,hh.ddd,long.,lat. */
  312. case 7: /* tm ( landsat ) * enter month,day,hh.ddd,long.,lat. */
  313. case 8: /* etm+ ( landsat7) * enter month,day,hh.ddd,long.,lat. */
  314. case 9: /* liss ( IRS 1C) * enter month,day,hh.ddd,long.,lat. */
  315. case 10: /* aster * enter month,day,hh.ddd,long.,lat. */
  316. case 11: /* avnir * enter month,day,hh.ddd,long.,lat. */
  317. case 12: /* ikonos * enter month,day,hh.ddd,long.,lat. */
  318. case 13: /* rapideye * enter month,day,hh.ddd,long.,lat. */
  319. case 14: /* vgt1_spot4 * enter month,day,hh.ddd,long.,lat. */
  320. case 15: /* vgt2_spot5 * enter month,day,hh.ddd,long.,lat. */
  321. {
  322. cin >> month;
  323. cin >> jday;
  324. cin >> tu;
  325. cin >> xlon;
  326. cin >> xlat;
  327. cin.ignore(numeric_limits<int>::max(),'\n'); /* read the rest of the scraps, like comments */
  328. landsat(tu);
  329. break;
  330. }
  331. default: G_fatal_error(_("Unsupported/unreadable format in control file (found igeom=%d)"), igeom);
  332. }
  333. /* ********************************************************************** */
  334. /* */
  335. /* / scattered direction */
  336. /* / */
  337. /* / */
  338. /* / adif */
  339. /* incident + + + + + + + + + + + + + + + */
  340. /* direction */
  341. /* */
  342. /* ********************************************************************** */
  343. phi = (float)fabs(phiv - phi0);
  344. phirad = (phi0 - phiv) * (float)M_PI / 180.f;
  345. if (phirad < 0.f) phirad += (float)M_PI2;
  346. if (phirad > M_PI2) phirad -= (float)M_PI2;
  347. xmus = (float)cos (asol * M_PI / 180.f);
  348. xmuv = (float)cos (avis * M_PI / 180.f);
  349. xmup = (float)cos (phirad);
  350. xmud = -xmus * xmuv - (float)sqrt (1.f - xmus * xmus) * (float)sqrt (1.f - xmuv * xmuv) * xmup;
  351. /* test vermote bug */
  352. if (xmud > 1.f) xmud = 1.f;
  353. if (xmud < -1.f) xmud = -1.f;
  354. adif = (float)acos (xmud) * 180.f / (float)M_PI;
  355. dsol = varsol();
  356. }
  357. /* ---- print geometrical conditions ---- */
  358. void GeomCond::print()
  359. {
  360. static const string etiq1[16] = {
  361. string(" user defined conditions "),
  362. string(" meteosat observation "),
  363. string(" goes east observation "),
  364. string(" goes west observation "),
  365. string(" avhrr (AM noaa) observation "),
  366. string(" avhrr (PM noaa) observation "),
  367. string(" h.r.v. observation "),
  368. string(" t.m. observation "),
  369. string(" etm+ observation "),
  370. string(" liss observation "),
  371. string(" aster observation "),
  372. string(" avnir observation "),
  373. string(" ikonos observation "),
  374. string(" rapideye observation "),
  375. string(" vgt1_spot4 observation "),
  376. string(" vgt2_spot5 observation ")
  377. };
  378. static const string head(" geometrical conditions identity ");
  379. static const string line(" ------------------------------- ");
  380. Output::Begin(); Output::Repeat(22,' '); Output::Print(head); Output::End();
  381. Output::Begin(); Output::Repeat(22,' '); Output::Print(line); Output::End();
  382. Output::Begin(); Output::Repeat(22,' '); Output::Print(etiq1[igeom]); Output::End();
  383. Output::Begin(); Output::End();
  384. Output::Begin(); Output::Repeat(2,' ');
  385. ostringstream s1;
  386. s1.setf(ios::fixed, ios::floatfield);
  387. s1 << " month: " << month << " day: " << jday;
  388. s1 << ends;
  389. Output::Print(s1.str());
  390. Output::End();
  391. Output::Begin(); Output::Repeat(2,' ');
  392. ostringstream s2;
  393. s2.setf(ios::fixed, ios::floatfield);
  394. s2 << setprecision(2);
  395. s2 << " solar zenith angle: " << setw(6) << asol << " deg ";
  396. s2 << " solar azimuthal angle: " << setw(6) << phi0 << " deg";
  397. s2 << ends;
  398. Output::Print(s2.str());
  399. Output::End();
  400. Output::Begin(); Output::Repeat(2,' ');
  401. ostringstream s3;
  402. s3.setf(ios::fixed, ios::floatfield);
  403. s3 << setprecision(2);
  404. s3 << " view zenith angle: " << setw(6) << avis << " deg ";
  405. s3 << " view azimuthal angle: " << setw(6) << phiv << " deg ";
  406. s3 << ends;
  407. Output::Print(s3.str());
  408. Output::End();
  409. Output::Begin(); Output::Repeat(2,' ');
  410. ostringstream s4;
  411. s4.setf(ios::fixed, ios::floatfield);
  412. s4 << setprecision(2);
  413. s4 << " scattering angle: " << setw(6) << adif << " deg ";
  414. s4 << " azimuthal angle difference: " << setw(6) << phi << " deg ";
  415. s4 << ends;
  416. Output::Print(s4.str());
  417. Output::End();
  418. Output::Begin(); Output::End();
  419. }
  420. GeomCond GeomCond::Parse()
  421. {
  422. GeomCond geom;
  423. geom.parse();
  424. return geom;
  425. }