/Proj4/PJ_nsper.c

http://github.com/route-me/route-me · C · 152 lines · 147 code · 5 blank · 0 comment · 15 complexity · 48a66bc194b7d17201ee4e63be916f63 MD5 · raw file

  1. #ifndef lint
  2. static const char SCCSID[]="@(#)PJ_nsper.c 4.1 94/02/15 GIE REL";
  3. #endif
  4. #define PROJ_PARMS__ \
  5. double height; \
  6. double sinph0; \
  7. double cosph0; \
  8. double p; \
  9. double rp; \
  10. double pn1; \
  11. double pfact; \
  12. double h; \
  13. double cg; \
  14. double sg; \
  15. double sw; \
  16. double cw; \
  17. int mode; \
  18. int tilt;
  19. #define PJ_LIB__
  20. #include "projects.h"
  21. PROJ_HEAD(nsper, "Near-sided perspective") "\n\tAzi, Sph\n\th=";
  22. PROJ_HEAD(tpers, "Tilted perspective") "\n\tAzi, Sph\n\ttilt= azi= h=";
  23. # define EPS10 1.e-10
  24. # define N_POLE 0
  25. # define S_POLE 1
  26. # define EQUIT 2
  27. # define OBLIQ 3
  28. FORWARD(s_forward); /* spheroid */
  29. double coslam, cosphi, sinphi;
  30. sinphi = sin(lp.phi);
  31. cosphi = cos(lp.phi);
  32. coslam = cos(lp.lam);
  33. switch (P->mode) {
  34. case OBLIQ:
  35. xy.y = P->sinph0 * sinphi + P->cosph0 * cosphi * coslam;
  36. break;
  37. case EQUIT:
  38. xy.y = cosphi * coslam;
  39. break;
  40. case S_POLE:
  41. xy.y = - sinphi;
  42. break;
  43. case N_POLE:
  44. xy.y = sinphi;
  45. break;
  46. }
  47. if (xy.y < P->rp) F_ERROR;
  48. xy.y = P->pn1 / (P->p - xy.y);
  49. xy.x = xy.y * cosphi * sin(lp.lam);
  50. switch (P->mode) {
  51. case OBLIQ:
  52. xy.y *= (P->cosph0 * sinphi -
  53. P->sinph0 * cosphi * coslam);
  54. break;
  55. case EQUIT:
  56. xy.y *= sinphi;
  57. break;
  58. case N_POLE:
  59. coslam = - coslam;
  60. case S_POLE:
  61. xy.y *= cosphi * coslam;
  62. break;
  63. }
  64. if (P->tilt) {
  65. double yt, ba;
  66. yt = xy.y * P->cg + xy.x * P->sg;
  67. ba = 1. / (yt * P->sw * P->h + P->cw);
  68. xy.x = (xy.x * P->cg - xy.y * P->sg) * P->cw * ba;
  69. xy.y = yt * ba;
  70. }
  71. return (xy);
  72. }
  73. INVERSE(s_inverse); /* spheroid */
  74. double rh, cosz, sinz;
  75. if (P->tilt) {
  76. double bm, bq, yt;
  77. yt = 1./(P->pn1 - xy.y * P->sw);
  78. bm = P->pn1 * xy.x * yt;
  79. bq = P->pn1 * xy.y * P->cw * yt;
  80. xy.x = bm * P->cg + bq * P->sg;
  81. xy.y = bq * P->cg - bm * P->sg;
  82. }
  83. rh = hypot(xy.x, xy.y);
  84. if ((sinz = 1. - rh * rh * P->pfact) < 0.) I_ERROR;
  85. sinz = (P->p - sqrt(sinz)) / (P->pn1 / rh + rh / P->pn1);
  86. cosz = sqrt(1. - sinz * sinz);
  87. if (fabs(rh) <= EPS10) {
  88. lp.lam = 0.;
  89. lp.phi = P->phi0;
  90. } else {
  91. switch (P->mode) {
  92. case OBLIQ:
  93. lp.phi = asin(cosz * P->sinph0 + xy.y * sinz * P->cosph0 / rh);
  94. xy.y = (cosz - P->sinph0 * sin(lp.phi)) * rh;
  95. xy.x *= sinz * P->cosph0;
  96. break;
  97. case EQUIT:
  98. lp.phi = asin(xy.y * sinz / rh);
  99. xy.y = cosz * rh;
  100. xy.x *= sinz;
  101. break;
  102. case N_POLE:
  103. lp.phi = asin(cosz);
  104. xy.y = -xy.y;
  105. break;
  106. case S_POLE:
  107. lp.phi = - asin(cosz);
  108. break;
  109. }
  110. lp.lam = atan2(xy.x, xy.y);
  111. }
  112. return (lp);
  113. }
  114. FREEUP; if (P) pj_dalloc(P); }
  115. static PJ *
  116. setup(PJ *P) {
  117. if ((P->height = pj_param(P->params, "dh").f) <= 0.) E_ERROR(-30);
  118. if (fabs(fabs(P->phi0) - HALFPI) < EPS10)
  119. P->mode = P->phi0 < 0. ? S_POLE : N_POLE;
  120. else if (fabs(P->phi0) < EPS10)
  121. P->mode = EQUIT;
  122. else {
  123. P->mode = OBLIQ;
  124. P->sinph0 = sin(P->phi0);
  125. P->cosph0 = cos(P->phi0);
  126. }
  127. P->pn1 = P->height / P->a; /* normalize by radius */
  128. P->p = 1. + P->pn1;
  129. P->rp = 1. / P->p;
  130. P->h = 1. / P->pn1;
  131. P->pfact = (P->p + 1.) * P->h;
  132. P->inv = s_inverse;
  133. P->fwd = s_forward;
  134. P->es = 0.;
  135. return P;
  136. }
  137. ENTRY0(nsper)
  138. P->tilt = 0;
  139. ENDENTRY(setup(P))
  140. ENTRY0(tpers)
  141. double omega, gamma;
  142. omega = pj_param(P->params, "dtilt").f * DEG_TO_RAD;
  143. gamma = pj_param(P->params, "dazi").f * DEG_TO_RAD;
  144. P->tilt = 1;
  145. P->cg = cos(gamma); P->sg = sin(gamma);
  146. P->cw = cos(omega); P->sw = sin(omega);
  147. ENDENTRY(setup(P))