aeqd.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import adjust_lon from '../common/adjust_lon';
  2. import {HALF_PI, EPSLN} from '../constants/values';
  3. import mlfn from '../common/mlfn';
  4. import e0fn from '../common/e0fn';
  5. import e1fn from '../common/e1fn';
  6. import e2fn from '../common/e2fn';
  7. import e3fn from '../common/e3fn';
  8. import gN from '../common/gN';
  9. import asinz from '../common/asinz';
  10. import imlfn from '../common/imlfn';
  11. export function init() {
  12. this.sin_p12 = Math.sin(this.lat0);
  13. this.cos_p12 = Math.cos(this.lat0);
  14. }
  15. export function forward(p) {
  16. var lon = p.x;
  17. var lat = p.y;
  18. var sinphi = Math.sin(p.y);
  19. var cosphi = Math.cos(p.y);
  20. var dlon = adjust_lon(lon - this.long0);
  21. var e0, e1, e2, e3, Mlp, Ml, tanphi, Nl1, Nl, psi, Az, G, H, GH, Hs, c, kp, cos_c, s, s2, s3, s4, s5;
  22. if (this.sphere) {
  23. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  24. //North Pole case
  25. p.x = this.x0 + this.a * (HALF_PI - lat) * Math.sin(dlon);
  26. p.y = this.y0 - this.a * (HALF_PI - lat) * Math.cos(dlon);
  27. return p;
  28. }
  29. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  30. //South Pole case
  31. p.x = this.x0 + this.a * (HALF_PI + lat) * Math.sin(dlon);
  32. p.y = this.y0 + this.a * (HALF_PI + lat) * Math.cos(dlon);
  33. return p;
  34. }
  35. else {
  36. //default case
  37. cos_c = this.sin_p12 * sinphi + this.cos_p12 * cosphi * Math.cos(dlon);
  38. c = Math.acos(cos_c);
  39. kp = c ? c / Math.sin(c) : 1;
  40. p.x = this.x0 + this.a * kp * cosphi * Math.sin(dlon);
  41. p.y = this.y0 + this.a * kp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * Math.cos(dlon));
  42. return p;
  43. }
  44. }
  45. else {
  46. e0 = e0fn(this.es);
  47. e1 = e1fn(this.es);
  48. e2 = e2fn(this.es);
  49. e3 = e3fn(this.es);
  50. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  51. //North Pole case
  52. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  53. Ml = this.a * mlfn(e0, e1, e2, e3, lat);
  54. p.x = this.x0 + (Mlp - Ml) * Math.sin(dlon);
  55. p.y = this.y0 - (Mlp - Ml) * Math.cos(dlon);
  56. return p;
  57. }
  58. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  59. //South Pole case
  60. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  61. Ml = this.a * mlfn(e0, e1, e2, e3, lat);
  62. p.x = this.x0 + (Mlp + Ml) * Math.sin(dlon);
  63. p.y = this.y0 + (Mlp + Ml) * Math.cos(dlon);
  64. return p;
  65. }
  66. else {
  67. //Default case
  68. tanphi = sinphi / cosphi;
  69. Nl1 = gN(this.a, this.e, this.sin_p12);
  70. Nl = gN(this.a, this.e, sinphi);
  71. psi = Math.atan((1 - this.es) * tanphi + this.es * Nl1 * this.sin_p12 / (Nl * cosphi));
  72. Az = Math.atan2(Math.sin(dlon), this.cos_p12 * Math.tan(psi) - this.sin_p12 * Math.cos(dlon));
  73. if (Az === 0) {
  74. s = Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi));
  75. }
  76. else if (Math.abs(Math.abs(Az) - Math.PI) <= EPSLN) {
  77. s = -Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi));
  78. }
  79. else {
  80. s = Math.asin(Math.sin(dlon) * Math.cos(psi) / Math.sin(Az));
  81. }
  82. G = this.e * this.sin_p12 / Math.sqrt(1 - this.es);
  83. H = this.e * this.cos_p12 * Math.cos(Az) / Math.sqrt(1 - this.es);
  84. GH = G * H;
  85. Hs = H * H;
  86. s2 = s * s;
  87. s3 = s2 * s;
  88. s4 = s3 * s;
  89. s5 = s4 * s;
  90. c = Nl1 * s * (1 - s2 * Hs * (1 - Hs) / 6 + s3 / 8 * GH * (1 - 2 * Hs) + s4 / 120 * (Hs * (4 - 7 * Hs) - 3 * G * G * (1 - 7 * Hs)) - s5 / 48 * GH);
  91. p.x = this.x0 + c * Math.sin(Az);
  92. p.y = this.y0 + c * Math.cos(Az);
  93. return p;
  94. }
  95. }
  96. }
  97. export function inverse(p) {
  98. p.x -= this.x0;
  99. p.y -= this.y0;
  100. var rh, z, sinz, cosz, lon, lat, con, e0, e1, e2, e3, Mlp, M, N1, psi, Az, cosAz, tmp, A, B, D, Ee, F, sinpsi;
  101. if (this.sphere) {
  102. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  103. if (rh > (2 * HALF_PI * this.a)) {
  104. return;
  105. }
  106. z = rh / this.a;
  107. sinz = Math.sin(z);
  108. cosz = Math.cos(z);
  109. lon = this.long0;
  110. if (Math.abs(rh) <= EPSLN) {
  111. lat = this.lat0;
  112. }
  113. else {
  114. lat = asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh);
  115. con = Math.abs(this.lat0) - HALF_PI;
  116. if (Math.abs(con) <= EPSLN) {
  117. if (this.lat0 >= 0) {
  118. lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y));
  119. }
  120. else {
  121. lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y));
  122. }
  123. }
  124. else {
  125. /*con = cosz - this.sin_p12 * Math.sin(lat);
  126. if ((Math.abs(con) < EPSLN) && (Math.abs(p.x) < EPSLN)) {
  127. //no-op, just keep the lon value as is
  128. } else {
  129. var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh));
  130. lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh)));
  131. }*/
  132. lon = adjust_lon(this.long0 + Math.atan2(p.x * sinz, rh * this.cos_p12 * cosz - p.y * this.sin_p12 * sinz));
  133. }
  134. }
  135. p.x = lon;
  136. p.y = lat;
  137. return p;
  138. }
  139. else {
  140. e0 = e0fn(this.es);
  141. e1 = e1fn(this.es);
  142. e2 = e2fn(this.es);
  143. e3 = e3fn(this.es);
  144. if (Math.abs(this.sin_p12 - 1) <= EPSLN) {
  145. //North pole case
  146. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  147. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  148. M = Mlp - rh;
  149. lat = imlfn(M / this.a, e0, e1, e2, e3);
  150. lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y));
  151. p.x = lon;
  152. p.y = lat;
  153. return p;
  154. }
  155. else if (Math.abs(this.sin_p12 + 1) <= EPSLN) {
  156. //South pole case
  157. Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI);
  158. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  159. M = rh - Mlp;
  160. lat = imlfn(M / this.a, e0, e1, e2, e3);
  161. lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y));
  162. p.x = lon;
  163. p.y = lat;
  164. return p;
  165. }
  166. else {
  167. //default case
  168. rh = Math.sqrt(p.x * p.x + p.y * p.y);
  169. Az = Math.atan2(p.x, p.y);
  170. N1 = gN(this.a, this.e, this.sin_p12);
  171. cosAz = Math.cos(Az);
  172. tmp = this.e * this.cos_p12 * cosAz;
  173. A = -tmp * tmp / (1 - this.es);
  174. B = 3 * this.es * (1 - A) * this.sin_p12 * this.cos_p12 * cosAz / (1 - this.es);
  175. D = rh / N1;
  176. Ee = D - A * (1 + A) * Math.pow(D, 3) / 6 - B * (1 + 3 * A) * Math.pow(D, 4) / 24;
  177. F = 1 - A * Ee * Ee / 2 - D * Ee * Ee * Ee / 6;
  178. psi = Math.asin(this.sin_p12 * Math.cos(Ee) + this.cos_p12 * Math.sin(Ee) * cosAz);
  179. lon = adjust_lon(this.long0 + Math.asin(Math.sin(Az) * Math.sin(Ee) / Math.cos(psi)));
  180. sinpsi = Math.sin(psi);
  181. lat = Math.atan2((sinpsi - this.es * F * this.sin_p12) * Math.tan(psi), sinpsi * (1 - this.es));
  182. p.x = lon;
  183. p.y = lat;
  184. return p;
  185. }
  186. }
  187. }
  188. export var names = ["Azimuthal_Equidistant", "aeqd"];
  189. export default {
  190. init: init,
  191. forward: forward,
  192. inverse: inverse,
  193. names: names
  194. };