You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

5004 line
138 KiB

  1. // https://d3js.org/d3-geo-projection/ v4.0.0 Copyright 2013-2021 Mike Bostock, 2015 Ricky Reusser
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-geo'), require('d3-array')) :
  4. typeof define === 'function' && define.amd ? define(['exports', 'd3-geo', 'd3-array'], factory) :
  5. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}, global.d3, global.d3));
  6. }(this, (function (exports, d3Geo, d3Array) { 'use strict';
  7. var abs = Math.abs;
  8. var atan = Math.atan;
  9. var atan2 = Math.atan2;
  10. var cos = Math.cos;
  11. var exp = Math.exp;
  12. var floor = Math.floor;
  13. var log = Math.log;
  14. var max = Math.max;
  15. var min = Math.min;
  16. var pow = Math.pow;
  17. var round = Math.round;
  18. var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
  19. var sin = Math.sin;
  20. var tan = Math.tan;
  21. var epsilon$1 = 1e-6;
  22. var epsilon2 = 1e-12;
  23. var pi = Math.PI;
  24. var halfPi = pi / 2;
  25. var quarterPi = pi / 4;
  26. var sqrt1_2 = Math.SQRT1_2;
  27. var sqrt2 = sqrt(2);
  28. var sqrtPi = sqrt(pi);
  29. var tau = pi * 2;
  30. var degrees = 180 / pi;
  31. var radians = pi / 180;
  32. function sinci(x) {
  33. return x ? x / Math.sin(x) : 1;
  34. }
  35. function asin(x) {
  36. return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
  37. }
  38. function acos(x) {
  39. return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
  40. }
  41. function sqrt(x) {
  42. return x > 0 ? Math.sqrt(x) : 0;
  43. }
  44. function tanh(x) {
  45. x = exp(2 * x);
  46. return (x - 1) / (x + 1);
  47. }
  48. function sinh(x) {
  49. return (exp(x) - exp(-x)) / 2;
  50. }
  51. function cosh(x) {
  52. return (exp(x) + exp(-x)) / 2;
  53. }
  54. function arsinh(x) {
  55. return log(x + sqrt(x * x + 1));
  56. }
  57. function arcosh(x) {
  58. return log(x + sqrt(x * x - 1));
  59. }
  60. function airyRaw(beta) {
  61. var tanBeta_2 = tan(beta / 2),
  62. b = 2 * log(cos(beta / 2)) / (tanBeta_2 * tanBeta_2);
  63. function forward(x, y) {
  64. var cosx = cos(x),
  65. cosy = cos(y),
  66. siny = sin(y),
  67. cosz = cosy * cosx,
  68. k = -((1 - cosz ? log((1 + cosz) / 2) / (1 - cosz) : -0.5) + b / (1 + cosz));
  69. return [k * cosy * sin(x), k * siny];
  70. }
  71. forward.invert = function(x, y) {
  72. var r = sqrt(x * x + y * y),
  73. z = -beta / 2,
  74. i = 50, delta;
  75. if (!r) return [0, 0];
  76. do {
  77. var z_2 = z / 2,
  78. cosz_2 = cos(z_2),
  79. sinz_2 = sin(z_2),
  80. tanz_2 = sinz_2 / cosz_2,
  81. lnsecz_2 = -log(abs(cosz_2));
  82. z -= delta = (2 / tanz_2 * lnsecz_2 - b * tanz_2 - r) / (-lnsecz_2 / (sinz_2 * sinz_2) + 1 - b / (2 * cosz_2 * cosz_2)) * (cosz_2 < 0 ? 0.7 : 1);
  83. } while (abs(delta) > epsilon$1 && --i > 0);
  84. var sinz = sin(z);
  85. return [atan2(x * sinz, r * cos(z)), asin(y * sinz / r)];
  86. };
  87. return forward;
  88. }
  89. function airy() {
  90. var beta = halfPi,
  91. m = d3Geo.geoProjectionMutator(airyRaw),
  92. p = m(beta);
  93. p.radius = function(_) {
  94. return arguments.length ? m(beta = _ * radians) : beta * degrees;
  95. };
  96. return p
  97. .scale(179.976)
  98. .clipAngle(147);
  99. }
  100. function aitoffRaw(x, y) {
  101. var cosy = cos(y), sincia = sinci(acos(cosy * cos(x /= 2)));
  102. return [2 * cosy * sin(x) * sincia, sin(y) * sincia];
  103. }
  104. // Abort if [x, y] is not within an ellipse centered at [0, 0] with
  105. // semi-major axis pi and semi-minor axis pi/2.
  106. aitoffRaw.invert = function(x, y) {
  107. if (x * x + 4 * y * y > pi * pi + epsilon$1) return;
  108. var x1 = x, y1 = y, i = 25;
  109. do {
  110. var sinx = sin(x1),
  111. sinx_2 = sin(x1 / 2),
  112. cosx_2 = cos(x1 / 2),
  113. siny = sin(y1),
  114. cosy = cos(y1),
  115. sin_2y = sin(2 * y1),
  116. sin2y = siny * siny,
  117. cos2y = cosy * cosy,
  118. sin2x_2 = sinx_2 * sinx_2,
  119. c = 1 - cos2y * cosx_2 * cosx_2,
  120. e = c ? acos(cosy * cosx_2) * sqrt(f = 1 / c) : f = 0,
  121. f,
  122. fx = 2 * e * cosy * sinx_2 - x,
  123. fy = e * siny - y,
  124. dxdx = f * (cos2y * sin2x_2 + e * cosy * cosx_2 * sin2y),
  125. dxdy = f * (0.5 * sinx * sin_2y - e * 2 * siny * sinx_2),
  126. dydx = f * 0.25 * (sin_2y * sinx_2 - e * siny * cos2y * sinx),
  127. dydy = f * (sin2y * cosx_2 + e * sin2x_2 * cosy),
  128. z = dxdy * dydx - dydy * dxdx;
  129. if (!z) break;
  130. var dx = (fy * dxdy - fx * dydy) / z,
  131. dy = (fx * dydx - fy * dxdx) / z;
  132. x1 -= dx, y1 -= dy;
  133. } while ((abs(dx) > epsilon$1 || abs(dy) > epsilon$1) && --i > 0);
  134. return [x1, y1];
  135. };
  136. function aitoff() {
  137. return d3Geo.geoProjection(aitoffRaw)
  138. .scale(152.63);
  139. }
  140. function armadilloRaw(phi0) {
  141. var sinPhi0 = sin(phi0),
  142. cosPhi0 = cos(phi0),
  143. sPhi0 = phi0 >= 0 ? 1 : -1,
  144. tanPhi0 = tan(sPhi0 * phi0),
  145. k = (1 + sinPhi0 - cosPhi0) / 2;
  146. function forward(lambda, phi) {
  147. var cosPhi = cos(phi),
  148. cosLambda = cos(lambda /= 2);
  149. return [
  150. (1 + cosPhi) * sin(lambda),
  151. (sPhi0 * phi > -atan2(cosLambda, tanPhi0) - 1e-3 ? 0 : -sPhi0 * 10) + k + sin(phi) * cosPhi0 - (1 + cosPhi) * sinPhi0 * cosLambda // TODO D3 core should allow null or [NaN, NaN] to be returned.
  152. ];
  153. }
  154. forward.invert = function(x, y) {
  155. var lambda = 0,
  156. phi = 0,
  157. i = 50;
  158. do {
  159. var cosLambda = cos(lambda),
  160. sinLambda = sin(lambda),
  161. cosPhi = cos(phi),
  162. sinPhi = sin(phi),
  163. A = 1 + cosPhi,
  164. fx = A * sinLambda - x,
  165. fy = k + sinPhi * cosPhi0 - A * sinPhi0 * cosLambda - y,
  166. dxdLambda = A * cosLambda / 2,
  167. dxdPhi = -sinLambda * sinPhi,
  168. dydLambda = sinPhi0 * A * sinLambda / 2,
  169. dydPhi = cosPhi0 * cosPhi + sinPhi0 * cosLambda * sinPhi,
  170. denominator = dxdPhi * dydLambda - dydPhi * dxdLambda,
  171. dLambda = (fy * dxdPhi - fx * dydPhi) / denominator / 2,
  172. dPhi = (fx * dydLambda - fy * dxdLambda) / denominator;
  173. if (abs(dPhi) > 2) dPhi /= 2;
  174. lambda -= dLambda, phi -= dPhi;
  175. } while ((abs(dLambda) > epsilon$1 || abs(dPhi) > epsilon$1) && --i > 0);
  176. return sPhi0 * phi > -atan2(cos(lambda), tanPhi0) - 1e-3 ? [lambda * 2, phi] : null;
  177. };
  178. return forward;
  179. }
  180. function armadillo() {
  181. var phi0 = 20 * radians,
  182. sPhi0 = phi0 >= 0 ? 1 : -1,
  183. tanPhi0 = tan(sPhi0 * phi0),
  184. m = d3Geo.geoProjectionMutator(armadilloRaw),
  185. p = m(phi0),
  186. stream_ = p.stream;
  187. p.parallel = function(_) {
  188. if (!arguments.length) return phi0 * degrees;
  189. tanPhi0 = tan((sPhi0 = (phi0 = _ * radians) >= 0 ? 1 : -1) * phi0);
  190. return m(phi0);
  191. };
  192. p.stream = function(stream) {
  193. var rotate = p.rotate(),
  194. rotateStream = stream_(stream),
  195. sphereStream = (p.rotate([0, 0]), stream_(stream)),
  196. precision = p.precision();
  197. p.rotate(rotate);
  198. rotateStream.sphere = function() {
  199. sphereStream.polygonStart(), sphereStream.lineStart();
  200. for (var lambda = sPhi0 * -180; sPhi0 * lambda < 180; lambda += sPhi0 * 90)
  201. sphereStream.point(lambda, sPhi0 * 90);
  202. if (phi0) while (sPhi0 * (lambda -= 3 * sPhi0 * precision) >= -180) {
  203. sphereStream.point(lambda, sPhi0 * -atan2(cos(lambda * radians / 2), tanPhi0) * degrees);
  204. }
  205. sphereStream.lineEnd(), sphereStream.polygonEnd();
  206. };
  207. return rotateStream;
  208. };
  209. return p
  210. .scale(218.695)
  211. .center([0, 28.0974]);
  212. }
  213. function augustRaw(lambda, phi) {
  214. var tanPhi = tan(phi / 2),
  215. k = sqrt(1 - tanPhi * tanPhi),
  216. c = 1 + k * cos(lambda /= 2),
  217. x = sin(lambda) * k / c,
  218. y = tanPhi / c,
  219. x2 = x * x,
  220. y2 = y * y;
  221. return [
  222. 4 / 3 * x * (3 + x2 - 3 * y2),
  223. 4 / 3 * y * (3 + 3 * x2 - y2)
  224. ];
  225. }
  226. augustRaw.invert = function(x, y) {
  227. x *= 3 / 8, y *= 3 / 8;
  228. if (!x && abs(y) > 1) return null;
  229. var x2 = x * x,
  230. y2 = y * y,
  231. s = 1 + x2 + y2,
  232. sin3Eta = sqrt((s - sqrt(s * s - 4 * y * y)) / 2),
  233. eta = asin(sin3Eta) / 3,
  234. xi = sin3Eta ? arcosh(abs(y / sin3Eta)) / 3 : arsinh(abs(x)) / 3,
  235. cosEta = cos(eta),
  236. coshXi = cosh(xi),
  237. d = coshXi * coshXi - cosEta * cosEta;
  238. return [
  239. sign(x) * 2 * atan2(sinh(xi) * cosEta, 0.25 - d),
  240. sign(y) * 2 * atan2(coshXi * sin(eta), 0.25 + d)
  241. ];
  242. };
  243. function august() {
  244. return d3Geo.geoProjection(augustRaw)
  245. .scale(66.1603);
  246. }
  247. var sqrt8 = sqrt(8),
  248. phi0 = log(1 + sqrt2);
  249. function bakerRaw(lambda, phi) {
  250. var phi0 = abs(phi);
  251. return phi0 < quarterPi
  252. ? [lambda, log(tan(quarterPi + phi / 2))]
  253. : [lambda * cos(phi0) * (2 * sqrt2 - 1 / sin(phi0)), sign(phi) * (2 * sqrt2 * (phi0 - quarterPi) - log(tan(phi0 / 2)))];
  254. }
  255. bakerRaw.invert = function(x, y) {
  256. if ((y0 = abs(y)) < phi0) return [x, 2 * atan(exp(y)) - halfPi];
  257. var phi = quarterPi, i = 25, delta, y0;
  258. do {
  259. var cosPhi_2 = cos(phi / 2), tanPhi_2 = tan(phi / 2);
  260. phi -= delta = (sqrt8 * (phi - quarterPi) - log(tanPhi_2) - y0) / (sqrt8 - cosPhi_2 * cosPhi_2 / (2 * tanPhi_2));
  261. } while (abs(delta) > epsilon2 && --i > 0);
  262. return [x / (cos(phi) * (sqrt8 - 1 / sin(phi))), sign(y) * phi];
  263. };
  264. function baker() {
  265. return d3Geo.geoProjection(bakerRaw)
  266. .scale(112.314);
  267. }
  268. function berghausRaw(lobes) {
  269. var k = 2 * pi / lobes;
  270. function forward(lambda, phi) {
  271. var p = d3Geo.geoAzimuthalEquidistantRaw(lambda, phi);
  272. if (abs(lambda) > halfPi) { // back hemisphere
  273. var theta = atan2(p[1], p[0]),
  274. r = sqrt(p[0] * p[0] + p[1] * p[1]),
  275. theta0 = k * round((theta - halfPi) / k) + halfPi,
  276. alpha = atan2(sin(theta -= theta0), 2 - cos(theta)); // angle relative to lobe end
  277. theta = theta0 + asin(pi / r * sin(alpha)) - alpha;
  278. p[0] = r * cos(theta);
  279. p[1] = r * sin(theta);
  280. }
  281. return p;
  282. }
  283. forward.invert = function(x, y) {
  284. var r = sqrt(x * x + y * y);
  285. if (r > halfPi) {
  286. var theta = atan2(y, x),
  287. theta0 = k * round((theta - halfPi) / k) + halfPi,
  288. s = theta > theta0 ? -1 : 1,
  289. A = r * cos(theta0 - theta),
  290. cotAlpha = 1 / tan(s * acos((A - pi) / sqrt(pi * (pi - 2 * A) + r * r)));
  291. theta = theta0 + 2 * atan((cotAlpha + s * sqrt(cotAlpha * cotAlpha - 3)) / 3);
  292. x = r * cos(theta), y = r * sin(theta);
  293. }
  294. return d3Geo.geoAzimuthalEquidistantRaw.invert(x, y);
  295. };
  296. return forward;
  297. }
  298. function berghaus() {
  299. var lobes = 5,
  300. m = d3Geo.geoProjectionMutator(berghausRaw),
  301. p = m(lobes),
  302. projectionStream = p.stream,
  303. epsilon = 1e-2,
  304. cr = -cos(epsilon * radians),
  305. sr = sin(epsilon * radians);
  306. p.lobes = function(_) {
  307. return arguments.length ? m(lobes = +_) : lobes;
  308. };
  309. p.stream = function(stream) {
  310. var rotate = p.rotate(),
  311. rotateStream = projectionStream(stream),
  312. sphereStream = (p.rotate([0, 0]), projectionStream(stream));
  313. p.rotate(rotate);
  314. rotateStream.sphere = function() {
  315. sphereStream.polygonStart(), sphereStream.lineStart();
  316. for (var i = 0, delta = 360 / lobes, delta0 = 2 * pi / lobes, phi = 90 - 180 / lobes, phi0 = halfPi; i < lobes; ++i, phi -= delta, phi0 -= delta0) {
  317. sphereStream.point(atan2(sr * cos(phi0), cr) * degrees, asin(sr * sin(phi0)) * degrees);
  318. if (phi < -90) {
  319. sphereStream.point(-90, -180 - phi - epsilon);
  320. sphereStream.point(-90, -180 - phi + epsilon);
  321. } else {
  322. sphereStream.point(90, phi + epsilon);
  323. sphereStream.point(90, phi - epsilon);
  324. }
  325. }
  326. sphereStream.lineEnd(), sphereStream.polygonEnd();
  327. };
  328. return rotateStream;
  329. };
  330. return p
  331. .scale(87.8076)
  332. .center([0, 17.1875])
  333. .clipAngle(180 - 1e-3);
  334. }
  335. function hammerRaw(A, B) {
  336. if (arguments.length < 2) B = A;
  337. if (B === 1) return d3Geo.geoAzimuthalEqualAreaRaw;
  338. if (B === Infinity) return hammerQuarticAuthalicRaw;
  339. function forward(lambda, phi) {
  340. var coordinates = d3Geo.geoAzimuthalEqualAreaRaw(lambda / B, phi);
  341. coordinates[0] *= A;
  342. return coordinates;
  343. }
  344. forward.invert = function(x, y) {
  345. var coordinates = d3Geo.geoAzimuthalEqualAreaRaw.invert(x / A, y);
  346. coordinates[0] *= B;
  347. return coordinates;
  348. };
  349. return forward;
  350. }
  351. function hammerQuarticAuthalicRaw(lambda, phi) {
  352. return [
  353. lambda * cos(phi) / cos(phi /= 2),
  354. 2 * sin(phi)
  355. ];
  356. }
  357. hammerQuarticAuthalicRaw.invert = function(x, y) {
  358. var phi = 2 * asin(y / 2);
  359. return [
  360. x * cos(phi / 2) / cos(phi),
  361. phi
  362. ];
  363. };
  364. function hammer() {
  365. var B = 2,
  366. m = d3Geo.geoProjectionMutator(hammerRaw),
  367. p = m(B);
  368. p.coefficient = function(_) {
  369. if (!arguments.length) return B;
  370. return m(B = +_);
  371. };
  372. return p
  373. .scale(169.529);
  374. }
  375. // Approximate Newton-Raphson
  376. // Solve f(x) = y, start from x
  377. function solve(f, y, x) {
  378. var steps = 100, delta, f0, f1;
  379. x = x === undefined ? 0 : +x;
  380. y = +y;
  381. do {
  382. f0 = f(x);
  383. f1 = f(x + epsilon$1);
  384. if (f0 === f1) f1 = f0 + epsilon$1;
  385. x -= delta = (-1 * epsilon$1 * (f0 - y)) / (f0 - f1);
  386. } while (steps-- > 0 && abs(delta) > epsilon$1);
  387. return steps < 0 ? NaN : x;
  388. }
  389. // Approximate Newton-Raphson in 2D
  390. // Solve f(a,b) = [x,y]
  391. function solve2d(f, MAX_ITERATIONS, eps) {
  392. if (MAX_ITERATIONS === undefined) MAX_ITERATIONS = 40;
  393. if (eps === undefined) eps = epsilon2;
  394. return function(x, y, a, b) {
  395. var err2, da, db;
  396. a = a === undefined ? 0 : +a;
  397. b = b === undefined ? 0 : +b;
  398. for (var i = 0; i < MAX_ITERATIONS; i++) {
  399. var p = f(a, b),
  400. // diffs
  401. tx = p[0] - x,
  402. ty = p[1] - y;
  403. if (abs(tx) < eps && abs(ty) < eps) break; // we're there!
  404. // backtrack if we overshot
  405. var h = tx * tx + ty * ty;
  406. if (h > err2) {
  407. a -= da /= 2;
  408. b -= db /= 2;
  409. continue;
  410. }
  411. err2 = h;
  412. // partial derivatives
  413. var ea = (a > 0 ? -1 : 1) * eps,
  414. eb = (b > 0 ? -1 : 1) * eps,
  415. pa = f(a + ea, b),
  416. pb = f(a, b + eb),
  417. dxa = (pa[0] - p[0]) / ea,
  418. dya = (pa[1] - p[1]) / ea,
  419. dxb = (pb[0] - p[0]) / eb,
  420. dyb = (pb[1] - p[1]) / eb,
  421. // determinant
  422. D = dyb * dxa - dya * dxb,
  423. // newton step — or half-step for small D
  424. l = (abs(D) < 0.5 ? 0.5 : 1) / D;
  425. da = (ty * dxb - tx * dyb) * l;
  426. db = (tx * dya - ty * dxa) * l;
  427. a += da;
  428. b += db;
  429. if (abs(da) < eps && abs(db) < eps) break; // we're crawling
  430. }
  431. return [a, b];
  432. };
  433. }
  434. // Bertin 1953 as a modified Briesemeister
  435. // https://bl.ocks.org/Fil/5b9ee9636dfb6ffa53443c9006beb642
  436. function bertin1953Raw() {
  437. var hammer = hammerRaw(1.68, 2),
  438. fu = 1.4, k = 12;
  439. function forward(lambda, phi) {
  440. if (lambda + phi < -fu) {
  441. var u = (lambda - phi + 1.6) * (lambda + phi + fu) / 8;
  442. lambda += u;
  443. phi -= 0.8 * u * sin(phi + pi / 2);
  444. }
  445. var r = hammer(lambda, phi);
  446. var d = (1 - cos(lambda * phi)) / k;
  447. if (r[1] < 0) {
  448. r[0] *= 1 + d;
  449. }
  450. if (r[1] > 0) {
  451. r[1] *= 1 + d / 1.5 * r[0] * r[0];
  452. }
  453. return r;
  454. }
  455. forward.invert = solve2d(forward);
  456. return forward;
  457. }
  458. function bertin() {
  459. // this projection should not be rotated
  460. return d3Geo.geoProjection(bertin1953Raw())
  461. .rotate([-16.5, -42])
  462. .scale(176.57)
  463. .center([7.93, 0.09]);
  464. }
  465. function mollweideBromleyTheta(cp, phi) {
  466. var cpsinPhi = cp * sin(phi), i = 30, delta;
  467. do phi -= delta = (phi + sin(phi) - cpsinPhi) / (1 + cos(phi));
  468. while (abs(delta) > epsilon$1 && --i > 0);
  469. return phi / 2;
  470. }
  471. function mollweideBromleyRaw(cx, cy, cp) {
  472. function forward(lambda, phi) {
  473. return [cx * lambda * cos(phi = mollweideBromleyTheta(cp, phi)), cy * sin(phi)];
  474. }
  475. forward.invert = function(x, y) {
  476. return y = asin(y / cy), [x / (cx * cos(y)), asin((2 * y + sin(2 * y)) / cp)];
  477. };
  478. return forward;
  479. }
  480. var mollweideRaw = mollweideBromleyRaw(sqrt2 / halfPi, sqrt2, pi);
  481. function mollweide$1() {
  482. return d3Geo.geoProjection(mollweideRaw)
  483. .scale(169.529);
  484. }
  485. var k = 2.00276,
  486. w = 1.11072;
  487. function boggsRaw(lambda, phi) {
  488. var theta = mollweideBromleyTheta(pi, phi);
  489. return [k * lambda / (1 / cos(phi) + w / cos(theta)), (phi + sqrt2 * sin(theta)) / k];
  490. }
  491. boggsRaw.invert = function(x, y) {
  492. var ky = k * y, theta = y < 0 ? -quarterPi : quarterPi, i = 25, delta, phi;
  493. do {
  494. phi = ky - sqrt2 * sin(theta);
  495. theta -= delta = (sin(2 * theta) + 2 * theta - pi * sin(phi)) / (2 * cos(2 * theta) + 2 + pi * cos(phi) * sqrt2 * cos(theta));
  496. } while (abs(delta) > epsilon$1 && --i > 0);
  497. phi = ky - sqrt2 * sin(theta);
  498. return [x * (1 / cos(phi) + w / cos(theta)) / k, phi];
  499. };
  500. function boggs$1() {
  501. return d3Geo.geoProjection(boggsRaw)
  502. .scale(160.857);
  503. }
  504. function parallel1(projectAt) {
  505. var phi0 = 0,
  506. m = d3Geo.geoProjectionMutator(projectAt),
  507. p = m(phi0);
  508. p.parallel = function(_) {
  509. return arguments.length ? m(phi0 = _ * radians) : phi0 * degrees;
  510. };
  511. return p;
  512. }
  513. function sinusoidalRaw(lambda, phi) {
  514. return [lambda * cos(phi), phi];
  515. }
  516. sinusoidalRaw.invert = function(x, y) {
  517. return [x / cos(y), y];
  518. };
  519. function sinusoidal$1() {
  520. return d3Geo.geoProjection(sinusoidalRaw)
  521. .scale(152.63);
  522. }
  523. function bonneRaw(phi0) {
  524. if (!phi0) return sinusoidalRaw;
  525. var cotPhi0 = 1 / tan(phi0);
  526. function forward(lambda, phi) {
  527. var rho = cotPhi0 + phi0 - phi,
  528. e = rho ? lambda * cos(phi) / rho : rho;
  529. return [rho * sin(e), cotPhi0 - rho * cos(e)];
  530. }
  531. forward.invert = function(x, y) {
  532. var rho = sqrt(x * x + (y = cotPhi0 - y) * y),
  533. phi = cotPhi0 + phi0 - rho;
  534. return [rho / cos(phi) * atan2(x, y), phi];
  535. };
  536. return forward;
  537. }
  538. function bonne() {
  539. return parallel1(bonneRaw)
  540. .scale(123.082)
  541. .center([0, 26.1441])
  542. .parallel(45);
  543. }
  544. function bottomleyRaw(sinPsi) {
  545. function forward(lambda, phi) {
  546. var rho = halfPi - phi,
  547. eta = rho ? lambda * sinPsi * sin(rho) / rho : rho;
  548. return [rho * sin(eta) / sinPsi, halfPi - rho * cos(eta)];
  549. }
  550. forward.invert = function(x, y) {
  551. var x1 = x * sinPsi,
  552. y1 = halfPi - y,
  553. rho = sqrt(x1 * x1 + y1 * y1),
  554. eta = atan2(x1, y1);
  555. return [(rho ? rho / sin(rho) : 1) * eta / sinPsi, halfPi - rho];
  556. };
  557. return forward;
  558. }
  559. function bottomley() {
  560. var sinPsi = 0.5,
  561. m = d3Geo.geoProjectionMutator(bottomleyRaw),
  562. p = m(sinPsi);
  563. p.fraction = function(_) {
  564. return arguments.length ? m(sinPsi = +_) : sinPsi;
  565. };
  566. return p
  567. .scale(158.837);
  568. }
  569. var bromleyRaw = mollweideBromleyRaw(1, 4 / pi, pi);
  570. function bromley() {
  571. return d3Geo.geoProjection(bromleyRaw)
  572. .scale(152.63);
  573. }
  574. // Azimuthal distance.
  575. function distance(dPhi, c1, s1, c2, s2, dLambda) {
  576. var cosdLambda = cos(dLambda), r;
  577. if (abs(dPhi) > 1 || abs(dLambda) > 1) {
  578. r = acos(s1 * s2 + c1 * c2 * cosdLambda);
  579. } else {
  580. var sindPhi = sin(dPhi / 2), sindLambda = sin(dLambda / 2);
  581. r = 2 * asin(sqrt(sindPhi * sindPhi + c1 * c2 * sindLambda * sindLambda));
  582. }
  583. return abs(r) > epsilon$1 ? [r, atan2(c2 * sin(dLambda), c1 * s2 - s1 * c2 * cosdLambda)] : [0, 0];
  584. }
  585. // Angle opposite a, and contained between sides of lengths b and c.
  586. function angle$1(b, c, a) {
  587. return acos((b * b + c * c - a * a) / (2 * b * c));
  588. }
  589. // Normalize longitude.
  590. function longitude(lambda) {
  591. return lambda - 2 * pi * floor((lambda + pi) / (2 * pi));
  592. }
  593. function chamberlinRaw(p0, p1, p2) {
  594. var points = [
  595. [p0[0], p0[1], sin(p0[1]), cos(p0[1])],
  596. [p1[0], p1[1], sin(p1[1]), cos(p1[1])],
  597. [p2[0], p2[1], sin(p2[1]), cos(p2[1])]
  598. ];
  599. for (var a = points[2], b, i = 0; i < 3; ++i, a = b) {
  600. b = points[i];
  601. a.v = distance(b[1] - a[1], a[3], a[2], b[3], b[2], b[0] - a[0]);
  602. a.point = [0, 0];
  603. }
  604. var beta0 = angle$1(points[0].v[0], points[2].v[0], points[1].v[0]),
  605. beta1 = angle$1(points[0].v[0], points[1].v[0], points[2].v[0]),
  606. beta2 = pi - beta0;
  607. points[2].point[1] = 0;
  608. points[0].point[0] = -(points[1].point[0] = points[0].v[0] / 2);
  609. var mean = [
  610. points[2].point[0] = points[0].point[0] + points[2].v[0] * cos(beta0),
  611. 2 * (points[0].point[1] = points[1].point[1] = points[2].v[0] * sin(beta0))
  612. ];
  613. function forward(lambda, phi) {
  614. var sinPhi = sin(phi),
  615. cosPhi = cos(phi),
  616. v = new Array(3), i;
  617. // Compute distance and azimuth from control points.
  618. for (i = 0; i < 3; ++i) {
  619. var p = points[i];
  620. v[i] = distance(phi - p[1], p[3], p[2], cosPhi, sinPhi, lambda - p[0]);
  621. if (!v[i][0]) return p.point;
  622. v[i][1] = longitude(v[i][1] - p.v[1]);
  623. }
  624. // Arithmetic mean of interception points.
  625. var point = mean.slice();
  626. for (i = 0; i < 3; ++i) {
  627. var j = i == 2 ? 0 : i + 1;
  628. var a = angle$1(points[i].v[0], v[i][0], v[j][0]);
  629. if (v[i][1] < 0) a = -a;
  630. if (!i) {
  631. point[0] += v[i][0] * cos(a);
  632. point[1] -= v[i][0] * sin(a);
  633. } else if (i == 1) {
  634. a = beta1 - a;
  635. point[0] -= v[i][0] * cos(a);
  636. point[1] -= v[i][0] * sin(a);
  637. } else {
  638. a = beta2 - a;
  639. point[0] += v[i][0] * cos(a);
  640. point[1] += v[i][0] * sin(a);
  641. }
  642. }
  643. point[0] /= 3, point[1] /= 3;
  644. return point;
  645. }
  646. return forward;
  647. }
  648. function pointRadians(p) {
  649. return p[0] *= radians, p[1] *= radians, p;
  650. }
  651. function chamberlinAfrica() {
  652. return chamberlin([0, 22], [45, 22], [22.5, -22])
  653. .scale(380)
  654. .center([22.5, 2]);
  655. }
  656. function chamberlin(p0, p1, p2) { // TODO order matters!
  657. var c = d3Geo.geoCentroid({type: "MultiPoint", coordinates: [p0, p1, p2]}),
  658. R = [-c[0], -c[1]],
  659. r = d3Geo.geoRotation(R),
  660. f = chamberlinRaw(pointRadians(r(p0)), pointRadians(r(p1)), pointRadians(r(p2)));
  661. f.invert = solve2d(f);
  662. var p = d3Geo.geoProjection(f).rotate(R),
  663. center = p.center;
  664. delete p.rotate;
  665. p.center = function(_) {
  666. return arguments.length ? center(r(_)) : r.invert(center());
  667. };
  668. return p
  669. .clipAngle(90);
  670. }
  671. function collignonRaw(lambda, phi) {
  672. var alpha = sqrt(1 - sin(phi));
  673. return [(2 / sqrtPi) * lambda * alpha, sqrtPi * (1 - alpha)];
  674. }
  675. collignonRaw.invert = function(x, y) {
  676. var lambda = (lambda = y / sqrtPi - 1) * lambda;
  677. return [lambda > 0 ? x * sqrt(pi / lambda) / 2 : 0, asin(1 - lambda)];
  678. };
  679. function collignon$1() {
  680. return d3Geo.geoProjection(collignonRaw)
  681. .scale(95.6464)
  682. .center([0, 30]);
  683. }
  684. function craigRaw(phi0) {
  685. var tanPhi0 = tan(phi0);
  686. function forward(lambda, phi) {
  687. return [lambda, (lambda ? lambda / sin(lambda) : 1) * (sin(phi) * cos(lambda) - tanPhi0 * cos(phi))];
  688. }
  689. forward.invert = tanPhi0 ? function(x, y) {
  690. if (x) y *= sin(x) / x;
  691. var cosLambda = cos(x);
  692. return [x, 2 * atan2(sqrt(cosLambda * cosLambda + tanPhi0 * tanPhi0 - y * y) - cosLambda, tanPhi0 - y)];
  693. } : function(x, y) {
  694. return [x, asin(x ? y * tan(x) / x : y)];
  695. };
  696. return forward;
  697. }
  698. function craig() {
  699. return parallel1(craigRaw)
  700. .scale(249.828)
  701. .clipAngle(90);
  702. }
  703. var sqrt3 = sqrt(3);
  704. function crasterRaw(lambda, phi) {
  705. return [sqrt3 * lambda * (2 * cos(2 * phi / 3) - 1) / sqrtPi, sqrt3 * sqrtPi * sin(phi / 3)];
  706. }
  707. crasterRaw.invert = function(x, y) {
  708. var phi = 3 * asin(y / (sqrt3 * sqrtPi));
  709. return [sqrtPi * x / (sqrt3 * (2 * cos(2 * phi / 3) - 1)), phi];
  710. };
  711. function craster() {
  712. return d3Geo.geoProjection(crasterRaw)
  713. .scale(156.19);
  714. }
  715. function cylindricalEqualAreaRaw(phi0) {
  716. var cosPhi0 = cos(phi0);
  717. function forward(lambda, phi) {
  718. return [lambda * cosPhi0, sin(phi) / cosPhi0];
  719. }
  720. forward.invert = function(x, y) {
  721. return [x / cosPhi0, asin(y * cosPhi0)];
  722. };
  723. return forward;
  724. }
  725. function cylindricalEqualArea() {
  726. return parallel1(cylindricalEqualAreaRaw)
  727. .parallel(38.58) // acos(sqrt(width / height / pi)) * radians
  728. .scale(195.044); // width / (sqrt(width / height / pi) * 2 * pi)
  729. }
  730. function cylindricalStereographicRaw(phi0) {
  731. var cosPhi0 = cos(phi0);
  732. function forward(lambda, phi) {
  733. return [lambda * cosPhi0, (1 + cosPhi0) * tan(phi / 2)];
  734. }
  735. forward.invert = function(x, y) {
  736. return [x / cosPhi0, atan(y / (1 + cosPhi0)) * 2];
  737. };
  738. return forward;
  739. }
  740. function cylindricalStereographic() {
  741. return parallel1(cylindricalStereographicRaw)
  742. .scale(124.75);
  743. }
  744. function eckert1Raw(lambda, phi) {
  745. var alpha = sqrt(8 / (3 * pi));
  746. return [
  747. alpha * lambda * (1 - abs(phi) / pi),
  748. alpha * phi
  749. ];
  750. }
  751. eckert1Raw.invert = function(x, y) {
  752. var alpha = sqrt(8 / (3 * pi)),
  753. phi = y / alpha;
  754. return [
  755. x / (alpha * (1 - abs(phi) / pi)),
  756. phi
  757. ];
  758. };
  759. function eckert1() {
  760. return d3Geo.geoProjection(eckert1Raw)
  761. .scale(165.664);
  762. }
  763. function eckert2Raw(lambda, phi) {
  764. var alpha = sqrt(4 - 3 * sin(abs(phi)));
  765. return [
  766. 2 / sqrt(6 * pi) * lambda * alpha,
  767. sign(phi) * sqrt(2 * pi / 3) * (2 - alpha)
  768. ];
  769. }
  770. eckert2Raw.invert = function(x, y) {
  771. var alpha = 2 - abs(y) / sqrt(2 * pi / 3);
  772. return [
  773. x * sqrt(6 * pi) / (2 * alpha),
  774. sign(y) * asin((4 - alpha * alpha) / 3)
  775. ];
  776. };
  777. function eckert2() {
  778. return d3Geo.geoProjection(eckert2Raw)
  779. .scale(165.664);
  780. }
  781. function eckert3Raw(lambda, phi) {
  782. var k = sqrt(pi * (4 + pi));
  783. return [
  784. 2 / k * lambda * (1 + sqrt(1 - 4 * phi * phi / (pi * pi))),
  785. 4 / k * phi
  786. ];
  787. }
  788. eckert3Raw.invert = function(x, y) {
  789. var k = sqrt(pi * (4 + pi)) / 2;
  790. return [
  791. x * k / (1 + sqrt(1 - y * y * (4 + pi) / (4 * pi))),
  792. y * k / 2
  793. ];
  794. };
  795. function eckert3() {
  796. return d3Geo.geoProjection(eckert3Raw)
  797. .scale(180.739);
  798. }
  799. function eckert4Raw(lambda, phi) {
  800. var k = (2 + halfPi) * sin(phi);
  801. phi /= 2;
  802. for (var i = 0, delta = Infinity; i < 10 && abs(delta) > epsilon$1; i++) {
  803. var cosPhi = cos(phi);
  804. phi -= delta = (phi + sin(phi) * (cosPhi + 2) - k) / (2 * cosPhi * (1 + cosPhi));
  805. }
  806. return [
  807. 2 / sqrt(pi * (4 + pi)) * lambda * (1 + cos(phi)),
  808. 2 * sqrt(pi / (4 + pi)) * sin(phi)
  809. ];
  810. }
  811. eckert4Raw.invert = function(x, y) {
  812. var A = y * sqrt((4 + pi) / pi) / 2,
  813. k = asin(A),
  814. c = cos(k);
  815. return [
  816. x / (2 / sqrt(pi * (4 + pi)) * (1 + c)),
  817. asin((k + A * (c + 2)) / (2 + halfPi))
  818. ];
  819. };
  820. function eckert4() {
  821. return d3Geo.geoProjection(eckert4Raw)
  822. .scale(180.739);
  823. }
  824. function eckert5Raw(lambda, phi) {
  825. return [
  826. lambda * (1 + cos(phi)) / sqrt(2 + pi),
  827. 2 * phi / sqrt(2 + pi)
  828. ];
  829. }
  830. eckert5Raw.invert = function(x, y) {
  831. var k = sqrt(2 + pi),
  832. phi = y * k / 2;
  833. return [
  834. k * x / (1 + cos(phi)),
  835. phi
  836. ];
  837. };
  838. function eckert5() {
  839. return d3Geo.geoProjection(eckert5Raw)
  840. .scale(173.044);
  841. }
  842. function eckert6Raw(lambda, phi) {
  843. var k = (1 + halfPi) * sin(phi);
  844. for (var i = 0, delta = Infinity; i < 10 && abs(delta) > epsilon$1; i++) {
  845. phi -= delta = (phi + sin(phi) - k) / (1 + cos(phi));
  846. }
  847. k = sqrt(2 + pi);
  848. return [
  849. lambda * (1 + cos(phi)) / k,
  850. 2 * phi / k
  851. ];
  852. }
  853. eckert6Raw.invert = function(x, y) {
  854. var j = 1 + halfPi,
  855. k = sqrt(j / 2);
  856. return [
  857. x * 2 * k / (1 + cos(y *= k)),
  858. asin((y + sin(y)) / j)
  859. ];
  860. };
  861. function eckert6() {
  862. return d3Geo.geoProjection(eckert6Raw)
  863. .scale(173.044);
  864. }
  865. var eisenlohrK = 3 + 2 * sqrt2;
  866. function eisenlohrRaw(lambda, phi) {
  867. var s0 = sin(lambda /= 2),
  868. c0 = cos(lambda),
  869. k = sqrt(cos(phi)),
  870. c1 = cos(phi /= 2),
  871. t = sin(phi) / (c1 + sqrt2 * c0 * k),
  872. c = sqrt(2 / (1 + t * t)),
  873. v = sqrt((sqrt2 * c1 + (c0 + s0) * k) / (sqrt2 * c1 + (c0 - s0) * k));
  874. return [
  875. eisenlohrK * (c * (v - 1 / v) - 2 * log(v)),
  876. eisenlohrK * (c * t * (v + 1 / v) - 2 * atan(t))
  877. ];
  878. }
  879. eisenlohrRaw.invert = function(x, y) {
  880. if (!(p = augustRaw.invert(x / 1.2, y * 1.065))) return null;
  881. var lambda = p[0], phi = p[1], i = 20, p;
  882. x /= eisenlohrK, y /= eisenlohrK;
  883. do {
  884. var _0 = lambda / 2,
  885. _1 = phi / 2,
  886. s0 = sin(_0),
  887. c0 = cos(_0),
  888. s1 = sin(_1),
  889. c1 = cos(_1),
  890. cos1 = cos(phi),
  891. k = sqrt(cos1),
  892. t = s1 / (c1 + sqrt2 * c0 * k),
  893. t2 = t * t,
  894. c = sqrt(2 / (1 + t2)),
  895. v0 = (sqrt2 * c1 + (c0 + s0) * k),
  896. v1 = (sqrt2 * c1 + (c0 - s0) * k),
  897. v2 = v0 / v1,
  898. v = sqrt(v2),
  899. vm1v = v - 1 / v,
  900. vp1v = v + 1 / v,
  901. fx = c * vm1v - 2 * log(v) - x,
  902. fy = c * t * vp1v - 2 * atan(t) - y,
  903. deltatDeltaLambda = s1 && sqrt1_2 * k * s0 * t2 / s1,
  904. deltatDeltaPhi = (sqrt2 * c0 * c1 + k) / (2 * (c1 + sqrt2 * c0 * k) * (c1 + sqrt2 * c0 * k) * k),
  905. deltacDeltat = -0.5 * t * c * c * c,
  906. deltacDeltaLambda = deltacDeltat * deltatDeltaLambda,
  907. deltacDeltaPhi = deltacDeltat * deltatDeltaPhi,
  908. A = (A = 2 * c1 + sqrt2 * k * (c0 - s0)) * A * v,
  909. deltavDeltaLambda = (sqrt2 * c0 * c1 * k + cos1) / A,
  910. deltavDeltaPhi = -(sqrt2 * s0 * s1) / (k * A),
  911. deltaxDeltaLambda = vm1v * deltacDeltaLambda - 2 * deltavDeltaLambda / v + c * (deltavDeltaLambda + deltavDeltaLambda / v2),
  912. deltaxDeltaPhi = vm1v * deltacDeltaPhi - 2 * deltavDeltaPhi / v + c * (deltavDeltaPhi + deltavDeltaPhi / v2),
  913. deltayDeltaLambda = t * vp1v * deltacDeltaLambda - 2 * deltatDeltaLambda / (1 + t2) + c * vp1v * deltatDeltaLambda + c * t * (deltavDeltaLambda - deltavDeltaLambda / v2),
  914. deltayDeltaPhi = t * vp1v * deltacDeltaPhi - 2 * deltatDeltaPhi / (1 + t2) + c * vp1v * deltatDeltaPhi + c * t * (deltavDeltaPhi - deltavDeltaPhi / v2),
  915. denominator = deltaxDeltaPhi * deltayDeltaLambda - deltayDeltaPhi * deltaxDeltaLambda;
  916. if (!denominator) break;
  917. var deltaLambda = (fy * deltaxDeltaPhi - fx * deltayDeltaPhi) / denominator,
  918. deltaPhi = (fx * deltayDeltaLambda - fy * deltaxDeltaLambda) / denominator;
  919. lambda -= deltaLambda;
  920. phi = max(-halfPi, min(halfPi, phi - deltaPhi));
  921. } while ((abs(deltaLambda) > epsilon$1 || abs(deltaPhi) > epsilon$1) && --i > 0);
  922. return abs(abs(phi) - halfPi) < epsilon$1 ? [0, phi] : i && [lambda, phi];
  923. };
  924. function eisenlohr() {
  925. return d3Geo.geoProjection(eisenlohrRaw)
  926. .scale(62.5271);
  927. }
  928. var faheyK = cos(35 * radians);
  929. function faheyRaw(lambda, phi) {
  930. var t = tan(phi / 2);
  931. return [lambda * faheyK * sqrt(1 - t * t), (1 + faheyK) * t];
  932. }
  933. faheyRaw.invert = function(x, y) {
  934. var t = y / (1 + faheyK);
  935. return [x && x / (faheyK * sqrt(1 - t * t)), 2 * atan(t)];
  936. };
  937. function fahey() {
  938. return d3Geo.geoProjection(faheyRaw)
  939. .scale(137.152);
  940. }
  941. function foucautRaw(lambda, phi) {
  942. var k = phi / 2, cosk = cos(k);
  943. return [ 2 * lambda / sqrtPi * cos(phi) * cosk * cosk, sqrtPi * tan(k)];
  944. }
  945. foucautRaw.invert = function(x, y) {
  946. var k = atan(y / sqrtPi), cosk = cos(k), phi = 2 * k;
  947. return [x * sqrtPi / 2 / (cos(phi) * cosk * cosk), phi];
  948. };
  949. function foucaut() {
  950. return d3Geo.geoProjection(foucautRaw)
  951. .scale(135.264);
  952. }
  953. function foucautSinusoidalRaw(alpha) {
  954. var beta = 1 - alpha,
  955. equatorial = raw(pi, 0)[0] - raw(-pi, 0)[0],
  956. polar = raw(0, halfPi)[1] - raw(0, -halfPi)[1],
  957. ratio = sqrt(2 * polar / equatorial);
  958. function raw(lambda, phi) {
  959. var cosphi = cos(phi),
  960. sinphi = sin(phi);
  961. return [
  962. cosphi / (beta + alpha * cosphi) * lambda,
  963. beta * phi + alpha * sinphi
  964. ];
  965. }
  966. function forward(lambda, phi) {
  967. var p = raw(lambda, phi);
  968. return [p[0] * ratio, p[1] / ratio];
  969. }
  970. function forwardMeridian(phi) {
  971. return forward(0, phi)[1];
  972. }
  973. forward.invert = function(x, y) {
  974. var phi = solve(forwardMeridian, y),
  975. lambda = x / ratio * (alpha + beta / cos(phi));
  976. return [lambda, phi];
  977. };
  978. return forward;
  979. }
  980. function foucautSinusoidal() {
  981. var alpha = 0.5,
  982. m = d3Geo.geoProjectionMutator(foucautSinusoidalRaw),
  983. p = m(alpha);
  984. p.alpha = function(_) {
  985. return arguments.length ? m(alpha = +_) : alpha;
  986. };
  987. return p
  988. .scale(168.725);
  989. }
  990. function gilbertForward(point) {
  991. return [point[0] / 2, asin(tan(point[1] / 2 * radians)) * degrees];
  992. }
  993. function gilbertInvert(point) {
  994. return [point[0] * 2, 2 * atan(sin(point[1] * radians)) * degrees];
  995. }
  996. function gilbert(projectionType) {
  997. if (projectionType == null) projectionType = d3Geo.geoOrthographic;
  998. var projection = projectionType(),
  999. equirectangular = d3Geo.geoEquirectangular().scale(degrees).precision(0).clipAngle(null).translate([0, 0]); // antimeridian cutting
  1000. function gilbert(point) {
  1001. return projection(gilbertForward(point));
  1002. }
  1003. if (projection.invert) gilbert.invert = function(point) {
  1004. return gilbertInvert(projection.invert(point));
  1005. };
  1006. gilbert.stream = function(stream) {
  1007. var s1 = projection.stream(stream), s0 = equirectangular.stream({
  1008. point: function(lambda, phi) { s1.point(lambda / 2, asin(tan(-phi / 2 * radians)) * degrees); },
  1009. lineStart: function() { s1.lineStart(); },
  1010. lineEnd: function() { s1.lineEnd(); },
  1011. polygonStart: function() { s1.polygonStart(); },
  1012. polygonEnd: function() { s1.polygonEnd(); }
  1013. });
  1014. s0.sphere = s1.sphere;
  1015. return s0;
  1016. };
  1017. function property(name) {
  1018. gilbert[name] = function() {
  1019. return arguments.length ? (projection[name].apply(projection, arguments), gilbert) : projection[name]();
  1020. };
  1021. }
  1022. gilbert.rotate = function(_) {
  1023. return arguments.length ? (equirectangular.rotate(_), gilbert) : equirectangular.rotate();
  1024. };
  1025. gilbert.center = function(_) {
  1026. return arguments.length ? (projection.center(gilbertForward(_)), gilbert) : gilbertInvert(projection.center());
  1027. };
  1028. property("angle");
  1029. property("clipAngle");
  1030. property("clipExtent");
  1031. property("fitExtent");
  1032. property("fitHeight");
  1033. property("fitSize");
  1034. property("fitWidth");
  1035. property("scale");
  1036. property("translate");
  1037. property("precision");
  1038. return gilbert
  1039. .scale(249.5);
  1040. }
  1041. function gingeryRaw(rho, n) {
  1042. var k = 2 * pi / n,
  1043. rho2 = rho * rho;
  1044. function forward(lambda, phi) {
  1045. var p = d3Geo.geoAzimuthalEquidistantRaw(lambda, phi),
  1046. x = p[0],
  1047. y = p[1],
  1048. r2 = x * x + y * y;
  1049. if (r2 > rho2) {
  1050. var r = sqrt(r2),
  1051. theta = atan2(y, x),
  1052. theta0 = k * round(theta / k),
  1053. alpha = theta - theta0,
  1054. rhoCosAlpha = rho * cos(alpha),
  1055. k_ = (rho * sin(alpha) - alpha * sin(rhoCosAlpha)) / (halfPi - rhoCosAlpha),
  1056. s_ = gingeryLength(alpha, k_),
  1057. e = (pi - rho) / gingeryIntegrate(s_, rhoCosAlpha, pi);
  1058. x = r;
  1059. var i = 50, delta;
  1060. do {
  1061. x -= delta = (rho + gingeryIntegrate(s_, rhoCosAlpha, x) * e - r) / (s_(x) * e);
  1062. } while (abs(delta) > epsilon$1 && --i > 0);
  1063. y = alpha * sin(x);
  1064. if (x < halfPi) y -= k_ * (x - halfPi);
  1065. var s = sin(theta0),
  1066. c = cos(theta0);
  1067. p[0] = x * c - y * s;
  1068. p[1] = x * s + y * c;
  1069. }
  1070. return p;
  1071. }
  1072. forward.invert = function(x, y) {
  1073. var r2 = x * x + y * y;
  1074. if (r2 > rho2) {
  1075. var r = sqrt(r2),
  1076. theta = atan2(y, x),
  1077. theta0 = k * round(theta / k),
  1078. dTheta = theta - theta0;
  1079. x = r * cos(dTheta);
  1080. y = r * sin(dTheta);
  1081. var x_halfPi = x - halfPi,
  1082. sinx = sin(x),
  1083. alpha = y / sinx,
  1084. delta = x < halfPi ? Infinity : 0,
  1085. i = 10;
  1086. while (true) {
  1087. var rhosinAlpha = rho * sin(alpha),
  1088. rhoCosAlpha = rho * cos(alpha),
  1089. sinRhoCosAlpha = sin(rhoCosAlpha),
  1090. halfPi_RhoCosAlpha = halfPi - rhoCosAlpha,
  1091. k_ = (rhosinAlpha - alpha * sinRhoCosAlpha) / halfPi_RhoCosAlpha,
  1092. s_ = gingeryLength(alpha, k_);
  1093. if (abs(delta) < epsilon2 || !--i) break;
  1094. alpha -= delta = (alpha * sinx - k_ * x_halfPi - y) / (
  1095. sinx - x_halfPi * 2 * (
  1096. halfPi_RhoCosAlpha * (rhoCosAlpha + alpha * rhosinAlpha * cos(rhoCosAlpha) - sinRhoCosAlpha) -
  1097. rhosinAlpha * (rhosinAlpha - alpha * sinRhoCosAlpha)
  1098. ) / (halfPi_RhoCosAlpha * halfPi_RhoCosAlpha));
  1099. }
  1100. r = rho + gingeryIntegrate(s_, rhoCosAlpha, x) * (pi - rho) / gingeryIntegrate(s_, rhoCosAlpha, pi);
  1101. theta = theta0 + alpha;
  1102. x = r * cos(theta);
  1103. y = r * sin(theta);
  1104. }
  1105. return d3Geo.geoAzimuthalEquidistantRaw.invert(x, y);
  1106. };
  1107. return forward;
  1108. }
  1109. function gingeryLength(alpha, k) {
  1110. return function(x) {
  1111. var y_ = alpha * cos(x);
  1112. if (x < halfPi) y_ -= k;
  1113. return sqrt(1 + y_ * y_);
  1114. };
  1115. }
  1116. // Numerical integration: trapezoidal rule.
  1117. function gingeryIntegrate(f, a, b) {
  1118. var n = 50,
  1119. h = (b - a) / n,
  1120. s = f(a) + f(b);
  1121. for (var i = 1, x = a; i < n; ++i) s += 2 * f(x += h);
  1122. return s * 0.5 * h;
  1123. }
  1124. function gingery() {
  1125. var n = 6,
  1126. rho = 30 * radians,
  1127. cRho = cos(rho),
  1128. sRho = sin(rho),
  1129. m = d3Geo.geoProjectionMutator(gingeryRaw),
  1130. p = m(rho, n),
  1131. stream_ = p.stream,
  1132. epsilon = 1e-2,
  1133. cr = -cos(epsilon * radians),
  1134. sr = sin(epsilon * radians);
  1135. p.radius = function(_) {
  1136. if (!arguments.length) return rho * degrees;
  1137. cRho = cos(rho = _ * radians);
  1138. sRho = sin(rho);
  1139. return m(rho, n);
  1140. };
  1141. p.lobes = function(_) {
  1142. if (!arguments.length) return n;
  1143. return m(rho, n = +_);
  1144. };
  1145. p.stream = function(stream) {
  1146. var rotate = p.rotate(),
  1147. rotateStream = stream_(stream),
  1148. sphereStream = (p.rotate([0, 0]), stream_(stream));
  1149. p.rotate(rotate);
  1150. rotateStream.sphere = function() {
  1151. sphereStream.polygonStart(), sphereStream.lineStart();
  1152. for (var i = 0, delta = 2 * pi / n, phi = 0; i < n; ++i, phi -= delta) {
  1153. sphereStream.point(atan2(sr * cos(phi), cr) * degrees, asin(sr * sin(phi)) * degrees);
  1154. sphereStream.point(atan2(sRho * cos(phi - delta / 2), cRho) * degrees, asin(sRho * sin(phi - delta / 2)) * degrees);
  1155. }
  1156. sphereStream.lineEnd(), sphereStream.polygonEnd();
  1157. };
  1158. return rotateStream;
  1159. };
  1160. return p
  1161. .rotate([90, -40])
  1162. .scale(91.7095)
  1163. .clipAngle(180 - 1e-3);
  1164. }
  1165. function ginzburgPolyconicRaw(a, b, c, d, e, f, g, h) {
  1166. if (arguments.length < 8) h = 0;
  1167. function forward(lambda, phi) {
  1168. if (!phi) return [a * lambda / pi, 0];
  1169. var phi2 = phi * phi,
  1170. xB = a + phi2 * (b + phi2 * (c + phi2 * d)),
  1171. yB = phi * (e - 1 + phi2 * (f - h + phi2 * g)),
  1172. m = (xB * xB + yB * yB) / (2 * yB),
  1173. alpha = lambda * asin(xB / m) / pi;
  1174. return [m * sin(alpha), phi * (1 + phi2 * h) + m * (1 - cos(alpha))];
  1175. }
  1176. forward.invert = function(x, y) {
  1177. var lambda = pi * x / a,
  1178. phi = y,
  1179. deltaLambda, deltaPhi, i = 50;
  1180. do {
  1181. var phi2 = phi * phi,
  1182. xB = a + phi2 * (b + phi2 * (c + phi2 * d)),
  1183. yB = phi * (e - 1 + phi2 * (f - h + phi2 * g)),
  1184. p = xB * xB + yB * yB,
  1185. q = 2 * yB,
  1186. m = p / q,
  1187. m2 = m * m,
  1188. dAlphadLambda = asin(xB / m) / pi,
  1189. alpha = lambda * dAlphadLambda,
  1190. xB2 = xB * xB,
  1191. dxBdPhi = (2 * b + phi2 * (4 * c + phi2 * 6 * d)) * phi,
  1192. dyBdPhi = e + phi2 * (3 * f + phi2 * 5 * g),
  1193. dpdPhi = 2 * (xB * dxBdPhi + yB * (dyBdPhi - 1)),
  1194. dqdPhi = 2 * (dyBdPhi - 1),
  1195. dmdPhi = (dpdPhi * q - p * dqdPhi) / (q * q),
  1196. cosAlpha = cos(alpha),
  1197. sinAlpha = sin(alpha),
  1198. mcosAlpha = m * cosAlpha,
  1199. msinAlpha = m * sinAlpha,
  1200. dAlphadPhi = ((lambda / pi) * (1 / sqrt(1 - xB2 / m2)) * (dxBdPhi * m - xB * dmdPhi)) / m2,
  1201. fx = msinAlpha - x,
  1202. fy = phi * (1 + phi2 * h) + m - mcosAlpha - y,
  1203. deltaxDeltaPhi = dmdPhi * sinAlpha + mcosAlpha * dAlphadPhi,
  1204. deltaxDeltaLambda = mcosAlpha * dAlphadLambda,
  1205. deltayDeltaPhi = 1 + dmdPhi - (dmdPhi * cosAlpha - msinAlpha * dAlphadPhi),
  1206. deltayDeltaLambda = msinAlpha * dAlphadLambda,
  1207. denominator = deltaxDeltaPhi * deltayDeltaLambda - deltayDeltaPhi * deltaxDeltaLambda;
  1208. if (!denominator) break;
  1209. lambda -= deltaLambda = (fy * deltaxDeltaPhi - fx * deltayDeltaPhi) / denominator;
  1210. phi -= deltaPhi = (fx * deltayDeltaLambda - fy * deltaxDeltaLambda) / denominator;
  1211. } while ((abs(deltaLambda) > epsilon$1 || abs(deltaPhi) > epsilon$1) && --i > 0);
  1212. return [lambda, phi];
  1213. };
  1214. return forward;
  1215. }
  1216. var ginzburg4Raw = ginzburgPolyconicRaw(2.8284, -1.6988, 0.75432, -0.18071, 1.76003, -0.38914, 0.042555);
  1217. function ginzburg4() {
  1218. return d3Geo.geoProjection(ginzburg4Raw)
  1219. .scale(149.995);
  1220. }
  1221. var ginzburg5Raw = ginzburgPolyconicRaw(2.583819, -0.835827, 0.170354, -0.038094, 1.543313, -0.411435,0.082742);
  1222. function ginzburg5() {
  1223. return d3Geo.geoProjection(ginzburg5Raw)
  1224. .scale(153.93);
  1225. }
  1226. var ginzburg6Raw = ginzburgPolyconicRaw(5 / 6 * pi, -0.62636, -0.0344, 0, 1.3493, -0.05524, 0, 0.045);
  1227. function ginzburg6() {
  1228. return d3Geo.geoProjection(ginzburg6Raw)
  1229. .scale(130.945);
  1230. }
  1231. function ginzburg8Raw(lambda, phi) {
  1232. var lambda2 = lambda * lambda,
  1233. phi2 = phi * phi;
  1234. return [
  1235. lambda * (1 - 0.162388 * phi2) * (0.87 - 0.000952426 * lambda2 * lambda2),
  1236. phi * (1 + phi2 / 12)
  1237. ];
  1238. }
  1239. ginzburg8Raw.invert = function(x, y) {
  1240. var lambda = x,
  1241. phi = y,
  1242. i = 50, delta;
  1243. do {
  1244. var phi2 = phi * phi;
  1245. phi -= delta = (phi * (1 + phi2 / 12) - y) / (1 + phi2 / 4);
  1246. } while (abs(delta) > epsilon$1 && --i > 0);
  1247. i = 50;
  1248. x /= 1 -0.162388 * phi2;
  1249. do {
  1250. var lambda4 = (lambda4 = lambda * lambda) * lambda4;
  1251. lambda -= delta = (lambda * (0.87 - 0.000952426 * lambda4) - x) / (0.87 - 0.00476213 * lambda4);
  1252. } while (abs(delta) > epsilon$1 && --i > 0);
  1253. return [lambda, phi];
  1254. };
  1255. function ginzburg8() {
  1256. return d3Geo.geoProjection(ginzburg8Raw)
  1257. .scale(131.747);
  1258. }
  1259. var ginzburg9Raw = ginzburgPolyconicRaw(2.6516, -0.76534, 0.19123, -0.047094, 1.36289, -0.13965,0.031762);
  1260. function ginzburg9() {
  1261. return d3Geo.geoProjection(ginzburg9Raw)
  1262. .scale(131.087);
  1263. }
  1264. function squareRaw(project) {
  1265. var dx = project(halfPi, 0)[0] - project(-halfPi, 0)[0];
  1266. function projectSquare(lambda, phi) {
  1267. var s = lambda > 0 ? -0.5 : 0.5,
  1268. point = project(lambda + s * pi, phi);
  1269. point[0] -= s * dx;
  1270. return point;
  1271. }
  1272. if (project.invert) projectSquare.invert = function(x, y) {
  1273. var s = x > 0 ? -0.5 : 0.5,
  1274. location = project.invert(x + s * dx, y),
  1275. lambda = location[0] - s * pi;
  1276. if (lambda < -pi) lambda += 2 * pi;
  1277. else if (lambda > pi) lambda -= 2 * pi;
  1278. location[0] = lambda;
  1279. return location;
  1280. };
  1281. return projectSquare;
  1282. }
  1283. function gringortenRaw(lambda, phi) {
  1284. var sLambda = sign(lambda),
  1285. sPhi = sign(phi),
  1286. cosPhi = cos(phi),
  1287. x = cos(lambda) * cosPhi,
  1288. y = sin(lambda) * cosPhi,
  1289. z = sin(sPhi * phi);
  1290. lambda = abs(atan2(y, z));
  1291. phi = asin(x);
  1292. if (abs(lambda - halfPi) > epsilon$1) lambda %= halfPi;
  1293. var point = gringortenHexadecant(lambda > pi / 4 ? halfPi - lambda : lambda, phi);
  1294. if (lambda > pi / 4) z = point[0], point[0] = -point[1], point[1] = -z;
  1295. return (point[0] *= sLambda, point[1] *= -sPhi, point);
  1296. }
  1297. gringortenRaw.invert = function(x, y) {
  1298. if (abs(x) > 1) x = sign(x) * 2 - x;
  1299. if (abs(y) > 1) y = sign(y) * 2 - y;
  1300. var sx = sign(x),
  1301. sy = sign(y),
  1302. x0 = -sx * x,
  1303. y0 = -sy * y,
  1304. t = y0 / x0 < 1,
  1305. p = gringortenHexadecantInvert(t ? y0 : x0, t ? x0 : y0),
  1306. lambda = p[0],
  1307. phi = p[1],
  1308. cosPhi = cos(phi);
  1309. if (t) lambda = -halfPi - lambda;
  1310. return [sx * (atan2(sin(lambda) * cosPhi, -sin(phi)) + pi), sy * asin(cos(lambda) * cosPhi)];
  1311. };
  1312. function gringortenHexadecant(lambda, phi) {
  1313. if (phi === halfPi) return [0, 0];
  1314. var sinPhi = sin(phi),
  1315. r = sinPhi * sinPhi,
  1316. r2 = r * r,
  1317. j = 1 + r2,
  1318. k = 1 + 3 * r2,
  1319. q = 1 - r2,
  1320. z = asin(1 / sqrt(j)),
  1321. v = q + r * j * z,
  1322. p2 = (1 - sinPhi) / v,
  1323. p = sqrt(p2),
  1324. a2 = p2 * j,
  1325. a = sqrt(a2),
  1326. h = p * q,
  1327. x,
  1328. i;
  1329. if (lambda === 0) return [0, -(h + r * a)];
  1330. var cosPhi = cos(phi),
  1331. secPhi = 1 / cosPhi,
  1332. drdPhi = 2 * sinPhi * cosPhi,
  1333. dvdPhi = (-3 * r + z * k) * drdPhi,
  1334. dp2dPhi = (-v * cosPhi - (1 - sinPhi) * dvdPhi) / (v * v),
  1335. dpdPhi = (0.5 * dp2dPhi) / p,
  1336. dhdPhi = q * dpdPhi - 2 * r * p * drdPhi,
  1337. dra2dPhi = r * j * dp2dPhi + p2 * k * drdPhi,
  1338. mu = -secPhi * drdPhi,
  1339. nu = -secPhi * dra2dPhi,
  1340. zeta = -2 * secPhi * dhdPhi,
  1341. lambda1 = 4 * lambda / pi,
  1342. delta;
  1343. // Slower but accurate bisection method.
  1344. if (lambda > 0.222 * pi || phi < pi / 4 && lambda > 0.175 * pi) {
  1345. x = (h + r * sqrt(a2 * (1 + r2) - h * h)) / (1 + r2);
  1346. if (lambda > pi / 4) return [x, x];
  1347. var x1 = x, x0 = 0.5 * x;
  1348. x = 0.5 * (x0 + x1), i = 50;
  1349. do {
  1350. var g = sqrt(a2 - x * x),
  1351. f = (x * (zeta + mu * g) + nu * asin(x / a)) - lambda1;
  1352. if (!f) break;
  1353. if (f < 0) x0 = x;
  1354. else x1 = x;
  1355. x = 0.5 * (x0 + x1);
  1356. } while (abs(x1 - x0) > epsilon$1 && --i > 0);
  1357. }
  1358. // Newton-Raphson.
  1359. else {
  1360. x = epsilon$1, i = 25;
  1361. do {
  1362. var x2 = x * x,
  1363. g2 = sqrt(a2 - x2),
  1364. zetaMug = zeta + mu * g2,
  1365. f2 = x * zetaMug + nu * asin(x / a) - lambda1,
  1366. df = zetaMug + (nu - mu * x2) / g2;
  1367. x -= delta = g2 ? f2 / df : 0;
  1368. } while (abs(delta) > epsilon$1 && --i > 0);
  1369. }
  1370. return [x, -h - r * sqrt(a2 - x * x)];
  1371. }
  1372. function gringortenHexadecantInvert(x, y) {
  1373. var x0 = 0,
  1374. x1 = 1,
  1375. r = 0.5,
  1376. i = 50;
  1377. while (true) {
  1378. var r2 = r * r,
  1379. sinPhi = sqrt(r),
  1380. z = asin(1 / sqrt(1 + r2)),
  1381. v = (1 - r2) + r * (1 + r2) * z,
  1382. p2 = (1 - sinPhi) / v,
  1383. p = sqrt(p2),
  1384. a2 = p2 * (1 + r2),
  1385. h = p * (1 - r2),
  1386. g2 = a2 - x * x,
  1387. g = sqrt(g2),
  1388. y0 = y + h + r * g;
  1389. if (abs(x1 - x0) < epsilon2 || --i === 0 || y0 === 0) break;
  1390. if (y0 > 0) x0 = r;
  1391. else x1 = r;
  1392. r = 0.5 * (x0 + x1);
  1393. }
  1394. if (!i) return null;
  1395. var phi = asin(sinPhi),
  1396. cosPhi = cos(phi),
  1397. secPhi = 1 / cosPhi,
  1398. drdPhi = 2 * sinPhi * cosPhi,
  1399. dvdPhi = (-3 * r + z * (1 + 3 * r2)) * drdPhi,
  1400. dp2dPhi = (-v * cosPhi - (1 - sinPhi) * dvdPhi) / (v * v),
  1401. dpdPhi = 0.5 * dp2dPhi / p,
  1402. dhdPhi = (1 - r2) * dpdPhi - 2 * r * p * drdPhi,
  1403. zeta = -2 * secPhi * dhdPhi,
  1404. mu = -secPhi * drdPhi,
  1405. nu = -secPhi * (r * (1 + r2) * dp2dPhi + p2 * (1 + 3 * r2) * drdPhi);
  1406. return [pi / 4 * (x * (zeta + mu * g) + nu * asin(x / sqrt(a2))), phi];
  1407. }
  1408. function gringorten$1() {
  1409. return d3Geo.geoProjection(squareRaw(gringortenRaw))
  1410. .scale(239.75);
  1411. }
  1412. // Returns [sn, cn, dn](u + iv|m).
  1413. function ellipticJi(u, v, m) {
  1414. var a, b, c;
  1415. if (!u) {
  1416. b = ellipticJ(v, 1 - m);
  1417. return [
  1418. [0, b[0] / b[1]],
  1419. [1 / b[1], 0],
  1420. [b[2] / b[1], 0]
  1421. ];
  1422. }
  1423. a = ellipticJ(u, m);
  1424. if (!v) return [[a[0], 0], [a[1], 0], [a[2], 0]];
  1425. b = ellipticJ(v, 1 - m);
  1426. c = b[1] * b[1] + m * a[0] * a[0] * b[0] * b[0];
  1427. return [
  1428. [a[0] * b[2] / c, a[1] * a[2] * b[0] * b[1] / c],
  1429. [a[1] * b[1] / c, -a[0] * a[2] * b[0] * b[2] / c],
  1430. [a[2] * b[1] * b[2] / c, -m * a[0] * a[1] * b[0] / c]
  1431. ];
  1432. }
  1433. // Returns [sn, cn, dn, ph](u|m).
  1434. function ellipticJ(u, m) {
  1435. var ai, b, phi, t, twon;
  1436. if (m < epsilon$1) {
  1437. t = sin(u);
  1438. b = cos(u);
  1439. ai = m * (u - t * b) / 4;
  1440. return [
  1441. t - ai * b,
  1442. b + ai * t,
  1443. 1 - m * t * t / 2,
  1444. u - ai
  1445. ];
  1446. }
  1447. if (m >= 1 - epsilon$1) {
  1448. ai = (1 - m) / 4;
  1449. b = cosh(u);
  1450. t = tanh(u);
  1451. phi = 1 / b;
  1452. twon = b * sinh(u);
  1453. return [
  1454. t + ai * (twon - u) / (b * b),
  1455. phi - ai * t * phi * (twon - u),
  1456. phi + ai * t * phi * (twon + u),
  1457. 2 * atan(exp(u)) - halfPi + ai * (twon - u) / b
  1458. ];
  1459. }
  1460. var a = [1, 0, 0, 0, 0, 0, 0, 0, 0],
  1461. c = [sqrt(m), 0, 0, 0, 0, 0, 0, 0, 0],
  1462. i = 0;
  1463. b = sqrt(1 - m);
  1464. twon = 1;
  1465. while (abs(c[i] / a[i]) > epsilon$1 && i < 8) {
  1466. ai = a[i++];
  1467. c[i] = (ai - b) / 2;
  1468. a[i] = (ai + b) / 2;
  1469. b = sqrt(ai * b);
  1470. twon *= 2;
  1471. }
  1472. phi = twon * a[i] * u;
  1473. do {
  1474. t = c[i] * sin(b = phi) / a[i];
  1475. phi = (asin(t) + phi) / 2;
  1476. } while (--i);
  1477. return [sin(phi), t = cos(phi), t / cos(phi - b), phi];
  1478. }
  1479. // Calculate F(phi+iPsi|m).
  1480. // See Abramowitz and Stegun, 17.4.11.
  1481. function ellipticFi(phi, psi, m) {
  1482. var r = abs(phi),
  1483. i = abs(psi),
  1484. sinhPsi = sinh(i);
  1485. if (r) {
  1486. var cscPhi = 1 / sin(r),
  1487. cotPhi2 = 1 / (tan(r) * tan(r)),
  1488. b = -(cotPhi2 + m * (sinhPsi * sinhPsi * cscPhi * cscPhi) - 1 + m),
  1489. c = (m - 1) * cotPhi2,
  1490. cotLambda2 = (-b + sqrt(b * b - 4 * c)) / 2;
  1491. return [
  1492. ellipticF(atan(1 / sqrt(cotLambda2)), m) * sign(phi),
  1493. ellipticF(atan(sqrt((cotLambda2 / cotPhi2 - 1) / m)), 1 - m) * sign(psi)
  1494. ];
  1495. }
  1496. return [
  1497. 0,
  1498. ellipticF(atan(sinhPsi), 1 - m) * sign(psi)
  1499. ];
  1500. }
  1501. // Calculate F(phi|m) where m = k² = sin²α.
  1502. // See Abramowitz and Stegun, 17.6.7.
  1503. function ellipticF(phi, m) {
  1504. if (!m) return phi;
  1505. if (m === 1) return log(tan(phi / 2 + quarterPi));
  1506. var a = 1,
  1507. b = sqrt(1 - m),
  1508. c = sqrt(m);
  1509. for (var i = 0; abs(c) > epsilon$1; i++) {
  1510. if (phi % pi) {
  1511. var dPhi = atan(b * tan(phi) / a);
  1512. if (dPhi < 0) dPhi += pi;
  1513. phi += dPhi + ~~(phi / pi) * pi;
  1514. } else phi += phi;
  1515. c = (a + b) / 2;
  1516. b = sqrt(a * b);
  1517. c = ((a = c) - b) / 2;
  1518. }
  1519. return phi / (pow(2, i) * a);
  1520. }
  1521. function guyouRaw(lambda, phi) {
  1522. var k_ = (sqrt2 - 1) / (sqrt2 + 1),
  1523. k = sqrt(1 - k_ * k_),
  1524. K = ellipticF(halfPi, k * k),
  1525. f = -1,
  1526. psi = log(tan(pi / 4 + abs(phi) / 2)),
  1527. r = exp(f * psi) / sqrt(k_),
  1528. at = guyouComplexAtan(r * cos(f * lambda), r * sin(f * lambda)),
  1529. t = ellipticFi(at[0], at[1], k * k);
  1530. return [-t[1], (phi >= 0 ? 1 : -1) * (0.5 * K - t[0])];
  1531. }
  1532. function guyouComplexAtan(x, y) {
  1533. var x2 = x * x,
  1534. y_1 = y + 1,
  1535. t = 1 - x2 - y * y;
  1536. return [
  1537. 0.5 * ((x >= 0 ? halfPi : -halfPi) - atan2(t, 2 * x)),
  1538. -0.25 * log(t * t + 4 * x2) +0.5 * log(y_1 * y_1 + x2)
  1539. ];
  1540. }
  1541. function guyouComplexDivide(a, b) {
  1542. var denominator = b[0] * b[0] + b[1] * b[1];
  1543. return [
  1544. (a[0] * b[0] + a[1] * b[1]) / denominator,
  1545. (a[1] * b[0] - a[0] * b[1]) / denominator
  1546. ];
  1547. }
  1548. guyouRaw.invert = function(x, y) {
  1549. var k_ = (sqrt2 - 1) / (sqrt2 + 1),
  1550. k = sqrt(1 - k_ * k_),
  1551. K = ellipticF(halfPi, k * k),
  1552. f = -1,
  1553. j = ellipticJi(0.5 * K - y, -x, k * k),
  1554. tn = guyouComplexDivide(j[0], j[1]),
  1555. lambda = atan2(tn[1], tn[0]) / f;
  1556. return [
  1557. lambda,
  1558. 2 * atan(exp(0.5 / f * log(k_ * tn[0] * tn[0] + k_ * tn[1] * tn[1]))) - halfPi
  1559. ];
  1560. };
  1561. function guyou() {
  1562. return d3Geo.geoProjection(squareRaw(guyouRaw))
  1563. .scale(151.496);
  1564. }
  1565. function hammerRetroazimuthalRaw(phi0) {
  1566. var sinPhi0 = sin(phi0),
  1567. cosPhi0 = cos(phi0),
  1568. rotate = hammerRetroazimuthalRotation(phi0);
  1569. rotate.invert = hammerRetroazimuthalRotation(-phi0);
  1570. function forward(lambda, phi) {
  1571. var p = rotate(lambda, phi);
  1572. lambda = p[0], phi = p[1];
  1573. var sinPhi = sin(phi),
  1574. cosPhi = cos(phi),
  1575. cosLambda = cos(lambda),
  1576. z = acos(sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosLambda),
  1577. sinz = sin(z),
  1578. K = abs(sinz) > epsilon$1 ? z / sinz : 1;
  1579. return [
  1580. K * cosPhi0 * sin(lambda),
  1581. (abs(lambda) > halfPi ? K : -K) // rotate for back hemisphere
  1582. * (sinPhi0 * cosPhi - cosPhi0 * sinPhi * cosLambda)
  1583. ];
  1584. }
  1585. forward.invert = function(x, y) {
  1586. var rho = sqrt(x * x + y * y),
  1587. sinz = -sin(rho),
  1588. cosz = cos(rho),
  1589. a = rho * cosz,
  1590. b = -y * sinz,
  1591. c = rho * sinPhi0,
  1592. d = sqrt(a * a + b * b - c * c),
  1593. phi = atan2(a * c + b * d, b * c - a * d),
  1594. lambda = (rho > halfPi ? -1 : 1) * atan2(x * sinz, rho * cos(phi) * cosz + y * sin(phi) * sinz);
  1595. return rotate.invert(lambda, phi);
  1596. };
  1597. return forward;
  1598. }
  1599. // Latitudinal rotation by phi0.
  1600. // Temporary hack until D3 supports arbitrary small-circle clipping origins.
  1601. function hammerRetroazimuthalRotation(phi0) {
  1602. var sinPhi0 = sin(phi0),
  1603. cosPhi0 = cos(phi0);
  1604. return function(lambda, phi) {
  1605. var cosPhi = cos(phi),
  1606. x = cos(lambda) * cosPhi,
  1607. y = sin(lambda) * cosPhi,
  1608. z = sin(phi);
  1609. return [
  1610. atan2(y, x * cosPhi0 - z * sinPhi0),
  1611. asin(z * cosPhi0 + x * sinPhi0)
  1612. ];
  1613. };
  1614. }
  1615. function hammerRetroazimuthal() {
  1616. var phi0 = 0,
  1617. m = d3Geo.geoProjectionMutator(hammerRetroazimuthalRaw),
  1618. p = m(phi0),
  1619. rotate_ = p.rotate,
  1620. stream_ = p.stream,
  1621. circle = d3Geo.geoCircle();
  1622. p.parallel = function(_) {
  1623. if (!arguments.length) return phi0 * degrees;
  1624. var r = p.rotate();
  1625. return m(phi0 = _ * radians).rotate(r);
  1626. };
  1627. // Temporary hack; see hammerRetroazimuthalRotation.
  1628. p.rotate = function(_) {
  1629. if (!arguments.length) return (_ = rotate_.call(p), _[1] += phi0 * degrees, _);
  1630. rotate_.call(p, [_[0], _[1] - phi0 * degrees]);
  1631. circle.center([-_[0], -_[1]]);
  1632. return p;
  1633. };
  1634. p.stream = function(stream) {
  1635. stream = stream_(stream);
  1636. stream.sphere = function() {
  1637. stream.polygonStart();
  1638. var epsilon = 1e-2,
  1639. ring = circle.radius(90 - epsilon)().coordinates[0],
  1640. n = ring.length - 1,
  1641. i = -1,
  1642. p;
  1643. stream.lineStart();
  1644. while (++i < n) stream.point((p = ring[i])[0], p[1]);
  1645. stream.lineEnd();
  1646. ring = circle.radius(90 + epsilon)().coordinates[0];
  1647. n = ring.length - 1;
  1648. stream.lineStart();
  1649. while (--i >= 0) stream.point((p = ring[i])[0], p[1]);
  1650. stream.lineEnd();
  1651. stream.polygonEnd();
  1652. };
  1653. return stream;
  1654. };
  1655. return p
  1656. .scale(79.4187)
  1657. .parallel(45)
  1658. .clipAngle(180 - 1e-3);
  1659. }
  1660. var K$1 = 3,
  1661. healpixParallel = asin(1 - 1 / K$1) * degrees,
  1662. healpixLambert = cylindricalEqualAreaRaw(0);
  1663. function healpixRaw(H) {
  1664. var phi0 = healpixParallel * radians,
  1665. dx = collignonRaw(pi, phi0)[0] - collignonRaw(-pi, phi0)[0],
  1666. y0 = healpixLambert(0, phi0)[1],
  1667. y1 = collignonRaw(0, phi0)[1],
  1668. dy1 = sqrtPi - y1,
  1669. k = tau / H,
  1670. w = 4 / tau,
  1671. h = y0 + (dy1 * dy1 * 4) / tau;
  1672. function forward(lambda, phi) {
  1673. var point,
  1674. phi2 = abs(phi);
  1675. if (phi2 > phi0) {
  1676. var i = min(H - 1, max(0, floor((lambda + pi) / k)));
  1677. lambda += pi * (H - 1) / H - i * k;
  1678. point = collignonRaw(lambda, phi2);
  1679. point[0] = point[0] * tau / dx - tau * (H - 1) / (2 * H) + i * tau / H;
  1680. point[1] = y0 + (point[1] - y1) * 4 * dy1 / tau;
  1681. if (phi < 0) point[1] = -point[1];
  1682. } else {
  1683. point = healpixLambert(lambda, phi);
  1684. }
  1685. point[0] *= w, point[1] /= h;
  1686. return point;
  1687. }
  1688. forward.invert = function(x, y) {
  1689. x /= w, y *= h;
  1690. var y2 = abs(y);
  1691. if (y2 > y0) {
  1692. var i = min(H - 1, max(0, floor((x + pi) / k)));
  1693. x = (x + pi * (H - 1) / H - i * k) * dx / tau;
  1694. var point = collignonRaw.invert(x, 0.25 * (y2 - y0) * tau / dy1 + y1);
  1695. point[0] -= pi * (H - 1) / H - i * k;
  1696. if (y < 0) point[1] = -point[1];
  1697. return point;
  1698. }
  1699. return healpixLambert.invert(x, y);
  1700. };
  1701. return forward;
  1702. }
  1703. function sphereTop(x, i) {
  1704. return [x, i & 1 ? 90 - epsilon$1 : healpixParallel];
  1705. }
  1706. function sphereBottom(x, i) {
  1707. return [x, i & 1 ? -90 + epsilon$1 : -healpixParallel];
  1708. }
  1709. function sphereNudge(d) {
  1710. return [d[0] * (1 - epsilon$1), d[1]];
  1711. }
  1712. function sphere(step) {
  1713. var c = [].concat(
  1714. d3Array.range(-180, 180 + step / 2, step).map(sphereTop),
  1715. d3Array.range(180, -180 - step / 2, -step).map(sphereBottom)
  1716. );
  1717. return {
  1718. type: "Polygon",
  1719. coordinates: [step === 180 ? c.map(sphereNudge) : c]
  1720. };
  1721. }
  1722. function healpix() {
  1723. var H = 4,
  1724. m = d3Geo.geoProjectionMutator(healpixRaw),
  1725. p = m(H),
  1726. stream_ = p.stream;
  1727. p.lobes = function(_) {
  1728. return arguments.length ? m(H = +_) : H;
  1729. };
  1730. p.stream = function(stream) {
  1731. var rotate = p.rotate(),
  1732. rotateStream = stream_(stream),
  1733. sphereStream = (p.rotate([0, 0]), stream_(stream));
  1734. p.rotate(rotate);
  1735. rotateStream.sphere = function() { d3Geo.geoStream(sphere(180 / H), sphereStream); };
  1736. return rotateStream;
  1737. };
  1738. return p
  1739. .scale(239.75);
  1740. }
  1741. function hillRaw(K) {
  1742. var L = 1 + K,
  1743. sinBt = sin(1 / L),
  1744. Bt = asin(sinBt),
  1745. A = 2 * sqrt(pi / (B = pi + 4 * Bt * L)),
  1746. B,
  1747. rho0 = 0.5 * A * (L + sqrt(K * (2 + K))),
  1748. K2 = K * K,
  1749. L2 = L * L;
  1750. function forward(lambda, phi) {
  1751. var t = 1 - sin(phi),
  1752. rho,
  1753. omega;
  1754. if (t && t < 2) {
  1755. var theta = halfPi - phi, i = 25, delta;
  1756. do {
  1757. var sinTheta = sin(theta),
  1758. cosTheta = cos(theta),
  1759. Bt_Bt1 = Bt + atan2(sinTheta, L - cosTheta),
  1760. C = 1 + L2 - 2 * L * cosTheta;
  1761. theta -= delta = (theta - K2 * Bt - L * sinTheta + C * Bt_Bt1 -0.5 * t * B) / (2 * L * sinTheta * Bt_Bt1);
  1762. } while (abs(delta) > epsilon2 && --i > 0);
  1763. rho = A * sqrt(C);
  1764. omega = lambda * Bt_Bt1 / pi;
  1765. } else {
  1766. rho = A * (K + t);
  1767. omega = lambda * Bt / pi;
  1768. }
  1769. return [
  1770. rho * sin(omega),
  1771. rho0 - rho * cos(omega)
  1772. ];
  1773. }
  1774. forward.invert = function(x, y) {
  1775. var rho2 = x * x + (y -= rho0) * y,
  1776. cosTheta = (1 + L2 - rho2 / (A * A)) / (2 * L),
  1777. theta = acos(cosTheta),
  1778. sinTheta = sin(theta),
  1779. Bt_Bt1 = Bt + atan2(sinTheta, L - cosTheta);
  1780. return [
  1781. asin(x / sqrt(rho2)) * pi / Bt_Bt1,
  1782. asin(1 - 2 * (theta - K2 * Bt - L * sinTheta + (1 + L2 - 2 * L * cosTheta) * Bt_Bt1) / B)
  1783. ];
  1784. };
  1785. return forward;
  1786. }
  1787. function hill() {
  1788. var K = 1,
  1789. m = d3Geo.geoProjectionMutator(hillRaw),
  1790. p = m(K);
  1791. p.ratio = function(_) {
  1792. return arguments.length ? m(K = +_) : K;
  1793. };
  1794. return p
  1795. .scale(167.774)
  1796. .center([0, 18.67]);
  1797. }
  1798. var sinuMollweidePhi = 0.7109889596207567;
  1799. var sinuMollweideY = 0.0528035274542;
  1800. function sinuMollweideRaw(lambda, phi) {
  1801. return phi > -sinuMollweidePhi
  1802. ? (lambda = mollweideRaw(lambda, phi), lambda[1] += sinuMollweideY, lambda)
  1803. : sinusoidalRaw(lambda, phi);
  1804. }
  1805. sinuMollweideRaw.invert = function(x, y) {
  1806. return y > -sinuMollweidePhi
  1807. ? mollweideRaw.invert(x, y - sinuMollweideY)
  1808. : sinusoidalRaw.invert(x, y);
  1809. };
  1810. function sinuMollweide$1() {
  1811. return d3Geo.geoProjection(sinuMollweideRaw)
  1812. .rotate([-20, -55])
  1813. .scale(164.263)
  1814. .center([0, -5.4036]);
  1815. }
  1816. function homolosineRaw(lambda, phi) {
  1817. return abs(phi) > sinuMollweidePhi
  1818. ? (lambda = mollweideRaw(lambda, phi), lambda[1] -= phi > 0 ? sinuMollweideY : -sinuMollweideY, lambda)
  1819. : sinusoidalRaw(lambda, phi);
  1820. }
  1821. homolosineRaw.invert = function(x, y) {
  1822. return abs(y) > sinuMollweidePhi
  1823. ? mollweideRaw.invert(x, y + (y > 0 ? sinuMollweideY : -sinuMollweideY))
  1824. : sinusoidalRaw.invert(x, y);
  1825. };
  1826. function homolosine$1() {
  1827. return d3Geo.geoProjection(homolosineRaw)
  1828. .scale(152.63);
  1829. }
  1830. function hufnagelRaw(a, b, psiMax, ratio) {
  1831. var k = sqrt(
  1832. (4 * pi) /
  1833. (2 * psiMax +
  1834. (1 + a - b / 2) * sin(2 * psiMax) +
  1835. ((a + b) / 2) * sin(4 * psiMax) +
  1836. (b / 2) * sin(6 * psiMax))
  1837. ),
  1838. c = sqrt(
  1839. ratio *
  1840. sin(psiMax) *
  1841. sqrt((1 + a * cos(2 * psiMax) + b * cos(4 * psiMax)) / (1 + a + b))
  1842. ),
  1843. M = psiMax * mapping(1);
  1844. function radius(psi) {
  1845. return sqrt(1 + a * cos(2 * psi) + b * cos(4 * psi));
  1846. }
  1847. function mapping(t) {
  1848. var psi = t * psiMax;
  1849. return (
  1850. (2 * psi +
  1851. (1 + a - b / 2) * sin(2 * psi) +
  1852. ((a + b) / 2) * sin(4 * psi) +
  1853. (b / 2) * sin(6 * psi)) /
  1854. psiMax
  1855. );
  1856. }
  1857. function inversemapping(psi) {
  1858. return radius(psi) * sin(psi);
  1859. }
  1860. var forward = function(lambda, phi) {
  1861. var psi = psiMax * solve(mapping, (M * sin(phi)) / psiMax, phi / pi);
  1862. if (isNaN(psi)) psi = psiMax * sign(phi);
  1863. var kr = k * radius(psi);
  1864. return [((kr * c * lambda) / pi) * cos(psi), (kr / c) * sin(psi)];
  1865. };
  1866. forward.invert = function(x, y) {
  1867. var psi = solve(inversemapping, (y * c) / k);
  1868. return [
  1869. (x * pi) / (cos(psi) * k * c * radius(psi)),
  1870. asin((psiMax * mapping(psi / psiMax)) / M)
  1871. ];
  1872. };
  1873. if (psiMax === 0) {
  1874. k = sqrt(ratio / pi);
  1875. forward = function(lambda, phi) {
  1876. return [lambda * k, sin(phi) / k];
  1877. };
  1878. forward.invert = function(x, y) {
  1879. return [x / k, asin(y * k)];
  1880. };
  1881. }
  1882. return forward;
  1883. }
  1884. function hufnagel() {
  1885. var a = 1,
  1886. b = 0,
  1887. psiMax = 45 * radians,
  1888. ratio = 2,
  1889. mutate = d3Geo.geoProjectionMutator(hufnagelRaw),
  1890. projection = mutate(a, b, psiMax, ratio);
  1891. projection.a = function(_) {
  1892. return arguments.length ? mutate((a = +_), b, psiMax, ratio) : a;
  1893. };
  1894. projection.b = function(_) {
  1895. return arguments.length ? mutate(a, (b = +_), psiMax, ratio) : b;
  1896. };
  1897. projection.psiMax = function(_) {
  1898. return arguments.length
  1899. ? mutate(a, b, (psiMax = +_ * radians), ratio)
  1900. : psiMax * degrees;
  1901. };
  1902. projection.ratio = function(_) {
  1903. return arguments.length ? mutate(a, b, psiMax, (ratio = +_)) : ratio;
  1904. };
  1905. return projection.scale(180.739);
  1906. }
  1907. // https://github.com/scijs/integrate-adaptive-simpson
  1908. // This algorithm adapted from pseudocode in:
  1909. // http://www.math.utk.edu/~ccollins/refs/Handouts/rich.pdf
  1910. function adsimp (f, a, b, fa, fm, fb, V0, tol, maxdepth, depth, state) {
  1911. if (state.nanEncountered) {
  1912. return NaN;
  1913. }
  1914. var h, f1, f2, sl, sr, s2, m, V1, V2, err;
  1915. h = b - a;
  1916. f1 = f(a + h * 0.25);
  1917. f2 = f(b - h * 0.25);
  1918. // Simple check for NaN:
  1919. if (isNaN(f1)) {
  1920. state.nanEncountered = true;
  1921. return;
  1922. }
  1923. // Simple check for NaN:
  1924. if (isNaN(f2)) {
  1925. state.nanEncountered = true;
  1926. return;
  1927. }
  1928. sl = h * (fa + 4 * f1 + fm) / 12;
  1929. sr = h * (fm + 4 * f2 + fb) / 12;
  1930. s2 = sl + sr;
  1931. err = (s2 - V0) / 15;
  1932. if (depth > maxdepth) {
  1933. state.maxDepthCount++;
  1934. return s2 + err;
  1935. } else if (Math.abs(err) < tol) {
  1936. return s2 + err;
  1937. } else {
  1938. m = a + h * 0.5;
  1939. V1 = adsimp(f, a, m, fa, f1, fm, sl, tol * 0.5, maxdepth, depth + 1, state);
  1940. if (isNaN(V1)) {
  1941. state.nanEncountered = true;
  1942. return NaN;
  1943. }
  1944. V2 = adsimp(f, m, b, fm, f2, fb, sr, tol * 0.5, maxdepth, depth + 1, state);
  1945. if (isNaN(V2)) {
  1946. state.nanEncountered = true;
  1947. return NaN;
  1948. }
  1949. return V1 + V2;
  1950. }
  1951. }
  1952. function integrate (f, a, b, tol, maxdepth) {
  1953. var state = {
  1954. maxDepthCount: 0,
  1955. nanEncountered: false
  1956. };
  1957. if (tol === undefined) {
  1958. tol = 1e-8;
  1959. }
  1960. if (maxdepth === undefined) {
  1961. maxdepth = 20;
  1962. }
  1963. var fa = f(a);
  1964. var fm = f(0.5 * (a + b));
  1965. var fb = f(b);
  1966. var V0 = (fa + 4 * fm + fb) * (b - a) / 6;
  1967. var result = adsimp(f, a, b, fa, fm, fb, V0, tol, maxdepth, 1, state);
  1968. /*
  1969. if (state.maxDepthCount > 0 && console && console.warn) {
  1970. console.warn('integrate-adaptive-simpson: Warning: maximum recursion depth (' + maxdepth + ') reached ' + state.maxDepthCount + ' times');
  1971. }
  1972. if (state.nanEncountered && console && console.warn) {
  1973. console.warn('integrate-adaptive-simpson: Warning: NaN encountered. Halting early.');
  1974. }
  1975. */
  1976. return result;
  1977. }
  1978. function hyperellipticalRaw(alpha, k, gamma) {
  1979. function elliptic (f) {
  1980. return alpha + (1 - alpha) * pow(1 - pow(f, k), 1 / k);
  1981. }
  1982. function z(f) {
  1983. return integrate(elliptic, 0, f, 1e-4);
  1984. }
  1985. var G = 1 / z(1),
  1986. n = 1000,
  1987. m = (1 + 1e-8) * G,
  1988. approx = [];
  1989. for (var i = 0; i <= n; i++)
  1990. approx.push(z(i / n) * m);
  1991. function Y(sinphi) {
  1992. var rmin = 0, rmax = n, r = n >> 1;
  1993. do {
  1994. if (approx[r] > sinphi) rmax = r; else rmin = r;
  1995. r = (rmin + rmax) >> 1;
  1996. } while (r > rmin);
  1997. var u = approx[r + 1] - approx[r];
  1998. if (u) u = (sinphi - approx[r + 1]) / u;
  1999. return (r + 1 + u) / n;
  2000. }
  2001. var ratio = 2 * Y(1) / pi * G / gamma;
  2002. var forward = function(lambda, phi) {
  2003. var y = Y(abs(sin(phi))),
  2004. x = elliptic(y) * lambda;
  2005. y /= ratio;
  2006. return [ x, (phi >= 0) ? y : -y ];
  2007. };
  2008. forward.invert = function(x, y) {
  2009. var phi;
  2010. y *= ratio;
  2011. if (abs(y) < 1) phi = sign(y) * asin(z(abs(y)) * G);
  2012. return [ x / elliptic(abs(y)), phi ];
  2013. };
  2014. return forward;
  2015. }
  2016. function hyperelliptical() {
  2017. var alpha = 0,
  2018. k = 2.5,
  2019. gamma = 1.183136, // affine = sqrt(2 * gamma / pi) = 0.8679
  2020. m = d3Geo.geoProjectionMutator(hyperellipticalRaw),
  2021. p = m(alpha, k, gamma);
  2022. p.alpha = function(_) {
  2023. return arguments.length ? m(alpha = +_, k, gamma) : alpha;
  2024. };
  2025. p.k = function(_) {
  2026. return arguments.length ? m(alpha, k = +_, gamma) : k;
  2027. };
  2028. p.gamma = function(_) {
  2029. return arguments.length ? m(alpha, k, gamma = +_) : gamma;
  2030. };
  2031. return p
  2032. .scale(152.63);
  2033. }
  2034. function pointEqual$1(a, b) {
  2035. return abs(a[0] - b[0]) < epsilon$1 && abs(a[1] - b[1]) < epsilon$1;
  2036. }
  2037. function interpolateLine(coordinates, m) {
  2038. var i = -1,
  2039. n = coordinates.length,
  2040. p0 = coordinates[0],
  2041. p1,
  2042. dx,
  2043. dy,
  2044. resampled = [];
  2045. while (++i < n) {
  2046. p1 = coordinates[i];
  2047. dx = (p1[0] - p0[0]) / m;
  2048. dy = (p1[1] - p0[1]) / m;
  2049. for (var j = 0; j < m; ++j) resampled.push([p0[0] + j * dx, p0[1] + j * dy]);
  2050. p0 = p1;
  2051. }
  2052. resampled.push(p1);
  2053. return resampled;
  2054. }
  2055. function interpolateSphere(lobes) {
  2056. var coordinates = [],
  2057. lobe,
  2058. lambda0, phi0, phi1,
  2059. lambda2, phi2,
  2060. i, n = lobes[0].length;
  2061. // Northern Hemisphere
  2062. for (i = 0; i < n; ++i) {
  2063. lobe = lobes[0][i];
  2064. lambda0 = lobe[0][0], phi0 = lobe[0][1], phi1 = lobe[1][1];
  2065. lambda2 = lobe[2][0], phi2 = lobe[2][1];
  2066. coordinates.push(interpolateLine([
  2067. [lambda0 + epsilon$1, phi0 + epsilon$1],
  2068. [lambda0 + epsilon$1, phi1 - epsilon$1],
  2069. [lambda2 - epsilon$1, phi1 - epsilon$1],
  2070. [lambda2 - epsilon$1, phi2 + epsilon$1]
  2071. ], 30));
  2072. }
  2073. // Southern Hemisphere
  2074. for (i = lobes[1].length - 1; i >= 0; --i) {
  2075. lobe = lobes[1][i];
  2076. lambda0 = lobe[0][0], phi0 = lobe[0][1], phi1 = lobe[1][1];
  2077. lambda2 = lobe[2][0], phi2 = lobe[2][1];
  2078. coordinates.push(interpolateLine([
  2079. [lambda2 - epsilon$1, phi2 - epsilon$1],
  2080. [lambda2 - epsilon$1, phi1 + epsilon$1],
  2081. [lambda0 + epsilon$1, phi1 + epsilon$1],
  2082. [lambda0 + epsilon$1, phi0 - epsilon$1]
  2083. ], 30));
  2084. }
  2085. return {
  2086. type: "Polygon",
  2087. coordinates: [d3Array.merge(coordinates)]
  2088. };
  2089. }
  2090. function interrupt(project, lobes, inverse) {
  2091. var sphere, bounds;
  2092. function forward(lambda, phi) {
  2093. var sign = phi < 0 ? -1 : +1, lobe = lobes[+(phi < 0)];
  2094. for (var i = 0, n = lobe.length - 1; i < n && lambda > lobe[i][2][0]; ++i);
  2095. var p = project(lambda - lobe[i][1][0], phi);
  2096. p[0] += project(lobe[i][1][0], sign * phi > sign * lobe[i][0][1] ? lobe[i][0][1] : phi)[0];
  2097. return p;
  2098. }
  2099. if (inverse) {
  2100. forward.invert = inverse(forward);
  2101. } else if (project.invert) {
  2102. forward.invert = function(x, y) {
  2103. var bound = bounds[+(y < 0)], lobe = lobes[+(y < 0)];
  2104. for (var i = 0, n = bound.length; i < n; ++i) {
  2105. var b = bound[i];
  2106. if (b[0][0] <= x && x < b[1][0] && b[0][1] <= y && y < b[1][1]) {
  2107. var p = project.invert(x - project(lobe[i][1][0], 0)[0], y);
  2108. p[0] += lobe[i][1][0];
  2109. return pointEqual$1(forward(p[0], p[1]), [x, y]) ? p : null;
  2110. }
  2111. }
  2112. };
  2113. }
  2114. var p = d3Geo.geoProjection(forward),
  2115. stream_ = p.stream;
  2116. p.stream = function(stream) {
  2117. var rotate = p.rotate(),
  2118. rotateStream = stream_(stream),
  2119. sphereStream = (p.rotate([0, 0]), stream_(stream));
  2120. p.rotate(rotate);
  2121. rotateStream.sphere = function() { d3Geo.geoStream(sphere, sphereStream); };
  2122. return rotateStream;
  2123. };
  2124. p.lobes = function(_) {
  2125. if (!arguments.length) return lobes.map(function(lobe) {
  2126. return lobe.map(function(l) {
  2127. return [
  2128. [l[0][0] * degrees, l[0][1] * degrees],
  2129. [l[1][0] * degrees, l[1][1] * degrees],
  2130. [l[2][0] * degrees, l[2][1] * degrees]
  2131. ];
  2132. });
  2133. });
  2134. sphere = interpolateSphere(_);
  2135. lobes = _.map(function(lobe) {
  2136. return lobe.map(function(l) {
  2137. return [
  2138. [l[0][0] * radians, l[0][1] * radians],
  2139. [l[1][0] * radians, l[1][1] * radians],
  2140. [l[2][0] * radians, l[2][1] * radians]
  2141. ];
  2142. });
  2143. });
  2144. bounds = lobes.map(function(lobe) {
  2145. return lobe.map(function(l) {
  2146. var x0 = project(l[0][0], l[0][1])[0],
  2147. x1 = project(l[2][0], l[2][1])[0],
  2148. y0 = project(l[1][0], l[0][1])[1],
  2149. y1 = project(l[1][0], l[1][1])[1],
  2150. t;
  2151. if (y0 > y1) t = y0, y0 = y1, y1 = t;
  2152. return [[x0, y0], [x1, y1]];
  2153. });
  2154. });
  2155. return p;
  2156. };
  2157. if (lobes != null) p.lobes(lobes);
  2158. return p;
  2159. }
  2160. var lobes$6 = [[ // northern hemisphere
  2161. [[-180, 0], [-100, 90], [ -40, 0]],
  2162. [[ -40, 0], [ 30, 90], [ 180, 0]]
  2163. ], [ // southern hemisphere
  2164. [[-180, 0], [-160, -90], [-100, 0]],
  2165. [[-100, 0], [ -60, -90], [ -20, 0]],
  2166. [[ -20, 0], [ 20, -90], [ 80, 0]],
  2167. [[ 80, 0], [ 140, -90], [ 180, 0]]
  2168. ]];
  2169. function boggs() {
  2170. return interrupt(boggsRaw, lobes$6)
  2171. .scale(160.857);
  2172. }
  2173. var lobes$5 = [[ // northern hemisphere
  2174. [[-180, 0], [-100, 90], [ -40, 0]],
  2175. [[ -40, 0], [ 30, 90], [ 180, 0]]
  2176. ], [ // southern hemisphere
  2177. [[-180, 0], [-160, -90], [-100, 0]],
  2178. [[-100, 0], [ -60, -90], [ -20, 0]],
  2179. [[ -20, 0], [ 20, -90], [ 80, 0]],
  2180. [[ 80, 0], [ 140, -90], [ 180, 0]]
  2181. ]];
  2182. function homolosine() {
  2183. return interrupt(homolosineRaw, lobes$5)
  2184. .scale(152.63);
  2185. }
  2186. var lobes$4 = [[ // northern hemisphere
  2187. [[-180, 0], [-100, 90], [ -40, 0]],
  2188. [[ -40, 0], [ 30, 90], [ 180, 0]]
  2189. ], [ // southern hemisphere
  2190. [[-180, 0], [-160, -90], [-100, 0]],
  2191. [[-100, 0], [ -60, -90], [ -20, 0]],
  2192. [[ -20, 0], [ 20, -90], [ 80, 0]],
  2193. [[ 80, 0], [ 140, -90], [ 180, 0]]
  2194. ]];
  2195. function mollweide() {
  2196. return interrupt(mollweideRaw, lobes$4)
  2197. .scale(169.529);
  2198. }
  2199. var lobes$3 = [[ // northern hemisphere
  2200. [[-180, 0], [ -90, 90], [ 0, 0]],
  2201. [[ 0, 0], [ 90, 90], [ 180, 0]]
  2202. ], [ // southern hemisphere
  2203. [[-180, 0], [ -90, -90], [ 0, 0]],
  2204. [[ 0, 0], [ 90, -90], [ 180, 0]]
  2205. ]];
  2206. function mollweideHemispheres() {
  2207. return interrupt(mollweideRaw, lobes$3)
  2208. .scale(169.529)
  2209. .rotate([20, 0]);
  2210. }
  2211. var lobes$2 = [[ // northern hemisphere
  2212. [[-180, 35], [ -30, 90], [ 0, 35]],
  2213. [[ 0, 35], [ 30, 90], [ 180, 35]]
  2214. ], [ // southern hemisphere
  2215. [[-180, -10], [-102, -90], [ -65, -10]],
  2216. [[ -65, -10], [ 5, -90], [ 77, -10]],
  2217. [[ 77, -10], [ 103, -90], [ 180, -10]]
  2218. ]];
  2219. function sinuMollweide() {
  2220. return interrupt(sinuMollweideRaw, lobes$2, solve2d)
  2221. .rotate([-20, -55])
  2222. .scale(164.263)
  2223. .center([0, -5.4036]);
  2224. }
  2225. var lobes$1 = [[ // northern hemisphere
  2226. [[-180, 0], [-110, 90], [ -40, 0]],
  2227. [[ -40, 0], [ 0, 90], [ 40, 0]],
  2228. [[ 40, 0], [ 110, 90], [ 180, 0]]
  2229. ], [ // southern hemisphere
  2230. [[-180, 0], [-110, -90], [ -40, 0]],
  2231. [[ -40, 0], [ 0, -90], [ 40, 0]],
  2232. [[ 40, 0], [ 110, -90], [ 180, 0]]
  2233. ]];
  2234. function sinusoidal() {
  2235. return interrupt(sinusoidalRaw, lobes$1)
  2236. .scale(152.63)
  2237. .rotate([-20, 0]);
  2238. }
  2239. function kavrayskiy7Raw(lambda, phi) {
  2240. return [3 / tau * lambda * sqrt(pi * pi / 3 - phi * phi), phi];
  2241. }
  2242. kavrayskiy7Raw.invert = function(x, y) {
  2243. return [tau / 3 * x / sqrt(pi * pi / 3 - y * y), y];
  2244. };
  2245. function kavrayskiy7() {
  2246. return d3Geo.geoProjection(kavrayskiy7Raw)
  2247. .scale(158.837);
  2248. }
  2249. function lagrangeRaw(n) {
  2250. function forward(lambda, phi) {
  2251. if (abs(abs(phi) - halfPi) < epsilon$1) return [0, phi < 0 ? -2 : 2];
  2252. var sinPhi = sin(phi),
  2253. v = pow((1 + sinPhi) / (1 - sinPhi), n / 2),
  2254. c = 0.5 * (v + 1 / v) + cos(lambda *= n);
  2255. return [
  2256. 2 * sin(lambda) / c,
  2257. (v - 1 / v) / c
  2258. ];
  2259. }
  2260. forward.invert = function(x, y) {
  2261. var y0 = abs(y);
  2262. if (abs(y0 - 2) < epsilon$1) return x ? null : [0, sign(y) * halfPi];
  2263. if (y0 > 2) return null;
  2264. x /= 2, y /= 2;
  2265. var x2 = x * x,
  2266. y2 = y * y,
  2267. t = 2 * y / (1 + x2 + y2); // tanh(nPhi)
  2268. t = pow((1 + t) / (1 - t), 1 / n);
  2269. return [
  2270. atan2(2 * x, 1 - x2 - y2) / n,
  2271. asin((t - 1) / (t + 1))
  2272. ];
  2273. };
  2274. return forward;
  2275. }
  2276. function lagrange() {
  2277. var n = 0.5,
  2278. m = d3Geo.geoProjectionMutator(lagrangeRaw),
  2279. p = m(n);
  2280. p.spacing = function(_) {
  2281. return arguments.length ? m(n = +_) : n;
  2282. };
  2283. return p
  2284. .scale(124.75);
  2285. }
  2286. var pi_sqrt2 = pi / sqrt2;
  2287. function larriveeRaw(lambda, phi) {
  2288. return [
  2289. lambda * (1 + sqrt(cos(phi))) / 2,
  2290. phi / (cos(phi / 2) * cos(lambda / 6))
  2291. ];
  2292. }
  2293. larriveeRaw.invert = function(x, y) {
  2294. var x0 = abs(x),
  2295. y0 = abs(y),
  2296. lambda = epsilon$1,
  2297. phi = halfPi;
  2298. if (y0 < pi_sqrt2) phi *= y0 / pi_sqrt2;
  2299. else lambda += 6 * acos(pi_sqrt2 / y0);
  2300. for (var i = 0; i < 25; i++) {
  2301. var sinPhi = sin(phi),
  2302. sqrtcosPhi = sqrt(cos(phi)),
  2303. sinPhi_2 = sin(phi / 2),
  2304. cosPhi_2 = cos(phi / 2),
  2305. sinLambda_6 = sin(lambda / 6),
  2306. cosLambda_6 = cos(lambda / 6),
  2307. f0 = 0.5 * lambda * (1 + sqrtcosPhi) - x0,
  2308. f1 = phi / (cosPhi_2 * cosLambda_6) - y0,
  2309. df0dPhi = sqrtcosPhi ? -0.25 * lambda * sinPhi / sqrtcosPhi : 0,
  2310. df0dLambda = 0.5 * (1 + sqrtcosPhi),
  2311. df1dPhi = (1 + 0.5 * phi * sinPhi_2 / cosPhi_2) / (cosPhi_2 * cosLambda_6),
  2312. df1dLambda = (phi / cosPhi_2) * (sinLambda_6 / 6) / (cosLambda_6 * cosLambda_6),
  2313. denom = df0dPhi * df1dLambda - df1dPhi * df0dLambda,
  2314. dPhi = (f0 * df1dLambda - f1 * df0dLambda) / denom,
  2315. dLambda = (f1 * df0dPhi - f0 * df1dPhi) / denom;
  2316. phi -= dPhi;
  2317. lambda -= dLambda;
  2318. if (abs(dPhi) < epsilon$1 && abs(dLambda) < epsilon$1) break;
  2319. }
  2320. return [x < 0 ? -lambda : lambda, y < 0 ? -phi : phi];
  2321. };
  2322. function larrivee() {
  2323. return d3Geo.geoProjection(larriveeRaw)
  2324. .scale(97.2672);
  2325. }
  2326. function laskowskiRaw(lambda, phi) {
  2327. var lambda2 = lambda * lambda, phi2 = phi * phi;
  2328. return [
  2329. lambda * (0.975534 + phi2 * (-0.119161 + lambda2 * -0.0143059 + phi2 * -0.0547009)),
  2330. phi * (1.00384 + lambda2 * (0.0802894 + phi2 * -0.02855 + lambda2 * 0.000199025) + phi2 * (0.0998909 + phi2 * -0.0491032))
  2331. ];
  2332. }
  2333. laskowskiRaw.invert = function(x, y) {
  2334. var lambda = sign(x) * pi,
  2335. phi = y / 2,
  2336. i = 50;
  2337. do {
  2338. var lambda2 = lambda * lambda,
  2339. phi2 = phi * phi,
  2340. lambdaPhi = lambda * phi,
  2341. fx = lambda * (0.975534 + phi2 * (-0.119161 + lambda2 * -0.0143059 + phi2 * -0.0547009)) - x,
  2342. fy = phi * (1.00384 + lambda2 * (0.0802894 + phi2 * -0.02855 + lambda2 * 0.000199025) + phi2 * (0.0998909 + phi2 * -0.0491032)) - y,
  2343. deltaxDeltaLambda = 0.975534 - phi2 * (0.119161 + 3 * lambda2 * 0.0143059 + phi2 * 0.0547009),
  2344. deltaxDeltaPhi = -lambdaPhi * (2 * 0.119161 + 4 * 0.0547009 * phi2 + 2 * 0.0143059 * lambda2),
  2345. deltayDeltaLambda = lambdaPhi * (2 * 0.0802894 + 4 * 0.000199025 * lambda2 + 2 * -0.02855 * phi2),
  2346. deltayDeltaPhi = 1.00384 + lambda2 * (0.0802894 + 0.000199025 * lambda2) + phi2 * (3 * (0.0998909 - 0.02855 * lambda2) - 5 * 0.0491032 * phi2),
  2347. denominator = deltaxDeltaPhi * deltayDeltaLambda - deltayDeltaPhi * deltaxDeltaLambda,
  2348. deltaLambda = (fy * deltaxDeltaPhi - fx * deltayDeltaPhi) / denominator,
  2349. deltaPhi = (fx * deltayDeltaLambda - fy * deltaxDeltaLambda) / denominator;
  2350. lambda -= deltaLambda, phi -= deltaPhi;
  2351. } while ((abs(deltaLambda) > epsilon$1 || abs(deltaPhi) > epsilon$1) && --i > 0);
  2352. return i && [lambda, phi];
  2353. };
  2354. function laskowski() {
  2355. return d3Geo.geoProjection(laskowskiRaw)
  2356. .scale(139.98);
  2357. }
  2358. function littrowRaw(lambda, phi) {
  2359. return [
  2360. sin(lambda) / cos(phi),
  2361. tan(phi) * cos(lambda)
  2362. ];
  2363. }
  2364. littrowRaw.invert = function(x, y) {
  2365. var x2 = x * x,
  2366. y2 = y * y,
  2367. y2_1 = y2 + 1,
  2368. x2_y2_1 = x2 + y2_1,
  2369. cosPhi = x
  2370. ? sqrt1_2 * sqrt((x2_y2_1 - sqrt(x2_y2_1 * x2_y2_1 - 4 * x2)) / x2)
  2371. : 1 / sqrt(y2_1);
  2372. return [
  2373. asin(x * cosPhi),
  2374. sign(y) * acos(cosPhi)
  2375. ];
  2376. };
  2377. function littrow() {
  2378. return d3Geo.geoProjection(littrowRaw)
  2379. .scale(144.049)
  2380. .clipAngle(90 - 1e-3);
  2381. }
  2382. function loximuthalRaw(phi0) {
  2383. var cosPhi0 = cos(phi0),
  2384. tanPhi0 = tan(quarterPi + phi0 / 2);
  2385. function forward(lambda, phi) {
  2386. var y = phi - phi0,
  2387. x = abs(y) < epsilon$1 ? lambda * cosPhi0
  2388. : abs(x = quarterPi + phi / 2) < epsilon$1 || abs(abs(x) - halfPi) < epsilon$1
  2389. ? 0 : lambda * y / log(tan(x) / tanPhi0);
  2390. return [x, y];
  2391. }
  2392. forward.invert = function(x, y) {
  2393. var lambda,
  2394. phi = y + phi0;
  2395. return [
  2396. abs(y) < epsilon$1 ? x / cosPhi0
  2397. : (abs(lambda = quarterPi + phi / 2) < epsilon$1 || abs(abs(lambda) - halfPi) < epsilon$1) ? 0
  2398. : x * log(tan(lambda) / tanPhi0) / y,
  2399. phi
  2400. ];
  2401. };
  2402. return forward;
  2403. }
  2404. function loximuthal() {
  2405. return parallel1(loximuthalRaw)
  2406. .parallel(40)
  2407. .scale(158.837);
  2408. }
  2409. function millerRaw(lambda, phi) {
  2410. return [lambda, 1.25 * log(tan(quarterPi + 0.4 * phi))];
  2411. }
  2412. millerRaw.invert = function(x, y) {
  2413. return [x, 2.5 * atan(exp(0.8 * y)) - 0.625 * pi];
  2414. };
  2415. function miller$1() {
  2416. return d3Geo.geoProjection(millerRaw)
  2417. .scale(108.318);
  2418. }
  2419. function modifiedStereographicRaw(C) {
  2420. var m = C.length - 1;
  2421. function forward(lambda, phi) {
  2422. var cosPhi = cos(phi),
  2423. k = 2 / (1 + cosPhi * cos(lambda)),
  2424. zr = k * cosPhi * sin(lambda),
  2425. zi = k * sin(phi),
  2426. i = m,
  2427. w = C[i],
  2428. ar = w[0],
  2429. ai = w[1],
  2430. t;
  2431. while (--i >= 0) {
  2432. w = C[i];
  2433. ar = w[0] + zr * (t = ar) - zi * ai;
  2434. ai = w[1] + zr * ai + zi * t;
  2435. }
  2436. ar = zr * (t = ar) - zi * ai;
  2437. ai = zr * ai + zi * t;
  2438. return [ar, ai];
  2439. }
  2440. forward.invert = function(x, y) {
  2441. var i = 20,
  2442. zr = x,
  2443. zi = y;
  2444. do {
  2445. var j = m,
  2446. w = C[j],
  2447. ar = w[0],
  2448. ai = w[1],
  2449. br = 0,
  2450. bi = 0,
  2451. t;
  2452. while (--j >= 0) {
  2453. w = C[j];
  2454. br = ar + zr * (t = br) - zi * bi;
  2455. bi = ai + zr * bi + zi * t;
  2456. ar = w[0] + zr * (t = ar) - zi * ai;
  2457. ai = w[1] + zr * ai + zi * t;
  2458. }
  2459. br = ar + zr * (t = br) - zi * bi;
  2460. bi = ai + zr * bi + zi * t;
  2461. ar = zr * (t = ar) - zi * ai - x;
  2462. ai = zr * ai + zi * t - y;
  2463. var denominator = br * br + bi * bi, deltar, deltai;
  2464. zr -= deltar = (ar * br + ai * bi) / denominator;
  2465. zi -= deltai = (ai * br - ar * bi) / denominator;
  2466. } while (abs(deltar) + abs(deltai) > epsilon$1 * epsilon$1 && --i > 0);
  2467. if (i) {
  2468. var rho = sqrt(zr * zr + zi * zi),
  2469. c = 2 * atan(rho * 0.5),
  2470. sinc = sin(c);
  2471. return [atan2(zr * sinc, rho * cos(c)), rho ? asin(zi * sinc / rho) : 0];
  2472. }
  2473. };
  2474. return forward;
  2475. }
  2476. var alaska = [[0.9972523, 0], [0.0052513, -0.0041175], [0.0074606, 0.0048125], [-0.0153783, -0.1968253], [0.0636871, -0.1408027], [0.3660976, -0.2937382]],
  2477. gs48 = [[0.98879, 0], [0, 0], [-0.050909, 0], [0, 0], [0.075528, 0]],
  2478. gs50 = [[0.9842990, 0], [0.0211642, 0.0037608], [-0.1036018, -0.0575102], [-0.0329095, -0.0320119], [0.0499471, 0.1223335], [0.0260460, 0.0899805], [0.0007388, -0.1435792], [0.0075848, -0.1334108], [-0.0216473, 0.0776645], [-0.0225161, 0.0853673]],
  2479. miller = [[0.9245, 0], [0, 0], [0.01943, 0]],
  2480. lee = [[0.721316, 0], [0, 0], [-0.00881625, -0.00617325]];
  2481. function modifiedStereographicAlaska() {
  2482. return modifiedStereographic(alaska, [152, -64])
  2483. .scale(1400)
  2484. .center([-160.908, 62.4864])
  2485. .clipAngle(30)
  2486. .angle(7.8);
  2487. }
  2488. function modifiedStereographicGs48() {
  2489. return modifiedStereographic(gs48, [95, -38])
  2490. .scale(1000)
  2491. .clipAngle(55)
  2492. .center([-96.5563, 38.8675]);
  2493. }
  2494. function modifiedStereographicGs50() {
  2495. return modifiedStereographic(gs50, [120, -45])
  2496. .scale(359.513)
  2497. .clipAngle(55)
  2498. .center([-117.474, 53.0628]);
  2499. }
  2500. function modifiedStereographicMiller() {
  2501. return modifiedStereographic(miller, [-20, -18])
  2502. .scale(209.091)
  2503. .center([20, 16.7214])
  2504. .clipAngle(82);
  2505. }
  2506. function modifiedStereographicLee() {
  2507. return modifiedStereographic(lee, [165, 10])
  2508. .scale(250)
  2509. .clipAngle(130)
  2510. .center([-165, -10]);
  2511. }
  2512. function modifiedStereographic(coefficients, rotate) {
  2513. var p = d3Geo.geoProjection(modifiedStereographicRaw(coefficients)).rotate(rotate).clipAngle(90),
  2514. r = d3Geo.geoRotation(rotate),
  2515. center = p.center;
  2516. delete p.rotate;
  2517. p.center = function(_) {
  2518. return arguments.length ? center(r(_)) : r.invert(center());
  2519. };
  2520. return p;
  2521. }
  2522. var sqrt6 = sqrt(6),
  2523. sqrt7 = sqrt(7);
  2524. function mtFlatPolarParabolicRaw(lambda, phi) {
  2525. var theta = asin(7 * sin(phi) / (3 * sqrt6));
  2526. return [
  2527. sqrt6 * lambda * (2 * cos(2 * theta / 3) - 1) / sqrt7,
  2528. 9 * sin(theta / 3) / sqrt7
  2529. ];
  2530. }
  2531. mtFlatPolarParabolicRaw.invert = function(x, y) {
  2532. var theta = 3 * asin(y * sqrt7 / 9);
  2533. return [
  2534. x * sqrt7 / (sqrt6 * (2 * cos(2 * theta / 3) - 1)),
  2535. asin(sin(theta) * 3 * sqrt6 / 7)
  2536. ];
  2537. };
  2538. function mtFlatPolarParabolic() {
  2539. return d3Geo.geoProjection(mtFlatPolarParabolicRaw)
  2540. .scale(164.859);
  2541. }
  2542. function mtFlatPolarQuarticRaw(lambda, phi) {
  2543. var k = (1 + sqrt1_2) * sin(phi),
  2544. theta = phi;
  2545. for (var i = 0, delta; i < 25; i++) {
  2546. theta -= delta = (sin(theta / 2) + sin(theta) - k) / (0.5 * cos(theta / 2) + cos(theta));
  2547. if (abs(delta) < epsilon$1) break;
  2548. }
  2549. return [
  2550. lambda * (1 + 2 * cos(theta) / cos(theta / 2)) / (3 * sqrt2),
  2551. 2 * sqrt(3) * sin(theta / 2) / sqrt(2 + sqrt2)
  2552. ];
  2553. }
  2554. mtFlatPolarQuarticRaw.invert = function(x, y) {
  2555. var sinTheta_2 = y * sqrt(2 + sqrt2) / (2 * sqrt(3)),
  2556. theta = 2 * asin(sinTheta_2);
  2557. return [
  2558. 3 * sqrt2 * x / (1 + 2 * cos(theta) / cos(theta / 2)),
  2559. asin((sinTheta_2 + sin(theta)) / (1 + sqrt1_2))
  2560. ];
  2561. };
  2562. function mtFlatPolarQuartic() {
  2563. return d3Geo.geoProjection(mtFlatPolarQuarticRaw)
  2564. .scale(188.209);
  2565. }
  2566. function mtFlatPolarSinusoidalRaw(lambda, phi) {
  2567. var A = sqrt(6 / (4 + pi)),
  2568. k = (1 + pi / 4) * sin(phi),
  2569. theta = phi / 2;
  2570. for (var i = 0, delta; i < 25; i++) {
  2571. theta -= delta = (theta / 2 + sin(theta) - k) / (0.5 + cos(theta));
  2572. if (abs(delta) < epsilon$1) break;
  2573. }
  2574. return [
  2575. A * (0.5 + cos(theta)) * lambda / 1.5,
  2576. A * theta
  2577. ];
  2578. }
  2579. mtFlatPolarSinusoidalRaw.invert = function(x, y) {
  2580. var A = sqrt(6 / (4 + pi)),
  2581. theta = y / A;
  2582. if (abs(abs(theta) - halfPi) < epsilon$1) theta = theta < 0 ? -halfPi : halfPi;
  2583. return [
  2584. 1.5 * x / (A * (0.5 + cos(theta))),
  2585. asin((theta / 2 + sin(theta)) / (1 + pi / 4))
  2586. ];
  2587. };
  2588. function mtFlatPolarSinusoidal() {
  2589. return d3Geo.geoProjection(mtFlatPolarSinusoidalRaw)
  2590. .scale(166.518);
  2591. }
  2592. function naturalEarth2Raw(lambda, phi) {
  2593. var phi2 = phi * phi, phi4 = phi2 * phi2, phi6 = phi2 * phi4;
  2594. return [
  2595. lambda * (0.84719 - 0.13063 * phi2 + phi6 * phi6 * (-0.04515 + 0.05494 * phi2 - 0.02326 * phi4 + 0.00331 * phi6)),
  2596. phi * (1.01183 + phi4 * phi4 * (-0.02625 + 0.01926 * phi2 - 0.00396 * phi4))
  2597. ];
  2598. }
  2599. naturalEarth2Raw.invert = function(x, y) {
  2600. var phi = y, i = 25, delta, phi2, phi4, phi6;
  2601. do {
  2602. phi2 = phi * phi; phi4 = phi2 * phi2;
  2603. phi -= delta = ((phi * (1.01183 + phi4 * phi4 * (-0.02625 + 0.01926 * phi2 - 0.00396 * phi4))) - y) /
  2604. (1.01183 + phi4 * phi4 * ((9 * -0.02625) + (11 * 0.01926) * phi2 + (13 * -0.00396) * phi4));
  2605. } while (abs(delta) > epsilon2 && --i > 0);
  2606. phi2 = phi * phi; phi4 = phi2 * phi2; phi6 = phi2 * phi4;
  2607. return [
  2608. x / (0.84719 - 0.13063 * phi2 + phi6 * phi6 * (-0.04515 + 0.05494 * phi2 - 0.02326 * phi4 + 0.00331 * phi6)),
  2609. phi
  2610. ];
  2611. };
  2612. function naturalEarth2() {
  2613. return d3Geo.geoProjection(naturalEarth2Raw)
  2614. .scale(175.295);
  2615. }
  2616. function nellHammerRaw(lambda, phi) {
  2617. return [
  2618. lambda * (1 + cos(phi)) / 2,
  2619. 2 * (phi - tan(phi / 2))
  2620. ];
  2621. }
  2622. nellHammerRaw.invert = function(x, y) {
  2623. var p = y / 2;
  2624. for (var i = 0, delta = Infinity; i < 10 && abs(delta) > epsilon$1; ++i) {
  2625. var c = cos(y / 2);
  2626. y -= delta = (y - tan(y / 2) - p) / (1 - 0.5 / (c * c));
  2627. }
  2628. return [
  2629. 2 * x / (1 + cos(y)),
  2630. y
  2631. ];
  2632. };
  2633. function nellHammer() {
  2634. return d3Geo.geoProjection(nellHammerRaw)
  2635. .scale(152.63);
  2636. }
  2637. var lobes = [[ // northern hemisphere
  2638. [[-180, 0], [-90, 90], [ 0, 0]],
  2639. [[ 0, 0], [ 90, 90], [ 180, 0]]
  2640. ], [ // southern hemisphere
  2641. [[-180, 0], [-90, -90], [ 0, 0]],
  2642. [[ 0, 0], [ 90, -90], [180, 0]]
  2643. ]];
  2644. function quarticAuthalic() {
  2645. return interrupt(hammerRaw(Infinity), lobes)
  2646. .rotate([20, 0])
  2647. .scale(152.63);
  2648. }
  2649. // Based on Torben Jansen's implementation
  2650. // https://beta.observablehq.com/@toja/nicolosi-globular-projection
  2651. // https://beta.observablehq.com/@toja/nicolosi-globular-inverse
  2652. function nicolosiRaw(lambda, phi) {
  2653. var sinPhi = sin(phi),
  2654. q = cos(phi),
  2655. s = sign(lambda);
  2656. if (lambda === 0 || abs(phi) === halfPi) return [0, phi];
  2657. else if (phi === 0) return [lambda, 0];
  2658. else if (abs(lambda) === halfPi) return [lambda * q, halfPi * sinPhi];
  2659. var b = pi / (2 * lambda) - (2 * lambda) / pi,
  2660. c = (2 * phi) / pi,
  2661. d = (1 - c * c) / (sinPhi - c);
  2662. var b2 = b * b,
  2663. d2 = d * d,
  2664. b2d2 = 1 + b2 / d2,
  2665. d2b2 = 1 + d2 / b2;
  2666. var M = ((b * sinPhi) / d - b / 2) / b2d2,
  2667. N = ((d2 * sinPhi) / b2 + d / 2) / d2b2,
  2668. m = M * M + (q * q) / b2d2,
  2669. n = N * N - ((d2 * sinPhi * sinPhi) / b2 + d * sinPhi - 1) / d2b2;
  2670. return [
  2671. halfPi * (M + sqrt(m) * s),
  2672. halfPi * (N + sqrt(n < 0 ? 0 : n) * sign(-phi * b) * s)
  2673. ];
  2674. }
  2675. nicolosiRaw.invert = function(x, y) {
  2676. x /= halfPi;
  2677. y /= halfPi;
  2678. var x2 = x * x,
  2679. y2 = y * y,
  2680. x2y2 = x2 + y2,
  2681. pi2 = pi * pi;
  2682. return [
  2683. x ? (x2y2 -1 + sqrt((1 - x2y2) * (1 - x2y2) + 4 * x2)) / (2 * x) * halfPi : 0,
  2684. solve(function(phi) {
  2685. return (
  2686. x2y2 * (pi * sin(phi) - 2 * phi) * pi +
  2687. 4 * phi * phi * (y - sin(phi)) +
  2688. 2 * pi * phi -
  2689. pi2 * y
  2690. );
  2691. }, 0)
  2692. ];
  2693. };
  2694. function nicolosi() {
  2695. return d3Geo.geoProjection(nicolosiRaw)
  2696. .scale(127.267);
  2697. }
  2698. // Based on Java implementation by Bojan Savric.
  2699. // https://github.com/OSUCartography/JMapProjLib/blob/master/src/com/jhlabs/map/proj/PattersonProjection.java
  2700. var pattersonK1 = 1.0148,
  2701. pattersonK2 = 0.23185,
  2702. pattersonK3 = -0.14499,
  2703. pattersonK4 = 0.02406,
  2704. pattersonC1 = pattersonK1,
  2705. pattersonC2 = 5 * pattersonK2,
  2706. pattersonC3 = 7 * pattersonK3,
  2707. pattersonC4 = 9 * pattersonK4,
  2708. pattersonYmax = 1.790857183;
  2709. function pattersonRaw(lambda, phi) {
  2710. var phi2 = phi * phi;
  2711. return [
  2712. lambda,
  2713. phi * (pattersonK1 + phi2 * phi2 * (pattersonK2 + phi2 * (pattersonK3 + pattersonK4 * phi2)))
  2714. ];
  2715. }
  2716. pattersonRaw.invert = function(x, y) {
  2717. if (y > pattersonYmax) y = pattersonYmax;
  2718. else if (y < -pattersonYmax) y = -pattersonYmax;
  2719. var yc = y, delta;
  2720. do { // Newton-Raphson
  2721. var y2 = yc * yc;
  2722. yc -= delta = ((yc * (pattersonK1 + y2 * y2 * (pattersonK2 + y2 * (pattersonK3 + pattersonK4 * y2)))) - y) / (pattersonC1 + y2 * y2 * (pattersonC2 + y2 * (pattersonC3 + pattersonC4 * y2)));
  2723. } while (abs(delta) > epsilon$1);
  2724. return [x, yc];
  2725. };
  2726. function patterson() {
  2727. return d3Geo.geoProjection(pattersonRaw)
  2728. .scale(139.319);
  2729. }
  2730. function polyconicRaw(lambda, phi) {
  2731. if (abs(phi) < epsilon$1) return [lambda, 0];
  2732. var tanPhi = tan(phi),
  2733. k = lambda * sin(phi);
  2734. return [
  2735. sin(k) / tanPhi,
  2736. phi + (1 - cos(k)) / tanPhi
  2737. ];
  2738. }
  2739. polyconicRaw.invert = function(x, y) {
  2740. if (abs(y) < epsilon$1) return [x, 0];
  2741. var k = x * x + y * y,
  2742. phi = y * 0.5,
  2743. i = 10, delta;
  2744. do {
  2745. var tanPhi = tan(phi),
  2746. secPhi = 1 / cos(phi),
  2747. j = k - 2 * y * phi + phi * phi;
  2748. phi -= delta = (tanPhi * j + 2 * (phi - y)) / (2 + j * secPhi * secPhi + 2 * (phi - y) * tanPhi);
  2749. } while (abs(delta) > epsilon$1 && --i > 0);
  2750. tanPhi = tan(phi);
  2751. return [
  2752. (abs(y) < abs(phi + 1 / tanPhi) ? asin(x * tanPhi) : sign(y) * sign(x) * (acos(abs(x * tanPhi)) + halfPi)) / sin(phi),
  2753. phi
  2754. ];
  2755. };
  2756. function polyconic() {
  2757. return d3Geo.geoProjection(polyconicRaw)
  2758. .scale(103.74);
  2759. }
  2760. // Note: 6-element arrays are used to denote the 3x3 affine transform matrix:
  2761. // [a, b, c,
  2762. // d, e, f,
  2763. // 0, 0, 1] - this redundant row is left out.
  2764. // Transform matrix for [a0, a1] -> [b0, b1].
  2765. function matrix(a, b) {
  2766. var u = subtract(a[1], a[0]),
  2767. v = subtract(b[1], b[0]),
  2768. phi = angle(u, v),
  2769. s = length(u) / length(v);
  2770. return multiply([
  2771. 1, 0, a[0][0],
  2772. 0, 1, a[0][1]
  2773. ], multiply([
  2774. s, 0, 0,
  2775. 0, s, 0
  2776. ], multiply([
  2777. cos(phi), sin(phi), 0,
  2778. -sin(phi), cos(phi), 0
  2779. ], [
  2780. 1, 0, -b[0][0],
  2781. 0, 1, -b[0][1]
  2782. ])));
  2783. }
  2784. // Inverts a transform matrix.
  2785. function inverse(m) {
  2786. var k = 1 / (m[0] * m[4] - m[1] * m[3]);
  2787. return [
  2788. k * m[4], -k * m[1], k * (m[1] * m[5] - m[2] * m[4]),
  2789. -k * m[3], k * m[0], k * (m[2] * m[3] - m[0] * m[5])
  2790. ];
  2791. }
  2792. // Multiplies two 3x2 matrices.
  2793. function multiply(a, b) {
  2794. return [
  2795. a[0] * b[0] + a[1] * b[3],
  2796. a[0] * b[1] + a[1] * b[4],
  2797. a[0] * b[2] + a[1] * b[5] + a[2],
  2798. a[3] * b[0] + a[4] * b[3],
  2799. a[3] * b[1] + a[4] * b[4],
  2800. a[3] * b[2] + a[4] * b[5] + a[5]
  2801. ];
  2802. }
  2803. // Subtracts 2D vectors.
  2804. function subtract(a, b) {
  2805. return [a[0] - b[0], a[1] - b[1]];
  2806. }
  2807. // Magnitude of a 2D vector.
  2808. function length(v) {
  2809. return sqrt(v[0] * v[0] + v[1] * v[1]);
  2810. }
  2811. // Angle between two 2D vectors.
  2812. function angle(a, b) {
  2813. return atan2(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]);
  2814. }
  2815. // Creates a polyhedral projection.
  2816. // * root: a spanning tree of polygon faces. Nodes are automatically
  2817. // augmented with a transform matrix.
  2818. // * face: a function that returns the appropriate node for a given {lambda, phi}
  2819. // point (radians).
  2820. function polyhedral(root, face) {
  2821. recurse(root, {transform: null});
  2822. function recurse(node, parent) {
  2823. node.edges = faceEdges(node.face);
  2824. // Find shared edge.
  2825. if (parent.face) {
  2826. var shared = node.shared = sharedEdge(node.face, parent.face),
  2827. m = matrix(shared.map(parent.project), shared.map(node.project));
  2828. node.transform = parent.transform ? multiply(parent.transform, m) : m;
  2829. // Replace shared edge in parent edges array.
  2830. var edges = parent.edges;
  2831. for (var i = 0, n = edges.length; i < n; ++i) {
  2832. if (pointEqual(shared[0], edges[i][1]) && pointEqual(shared[1], edges[i][0])) edges[i] = node;
  2833. if (pointEqual(shared[0], edges[i][0]) && pointEqual(shared[1], edges[i][1])) edges[i] = node;
  2834. }
  2835. edges = node.edges;
  2836. for (i = 0, n = edges.length; i < n; ++i) {
  2837. if (pointEqual(shared[0], edges[i][0]) && pointEqual(shared[1], edges[i][1])) edges[i] = parent;
  2838. if (pointEqual(shared[0], edges[i][1]) && pointEqual(shared[1], edges[i][0])) edges[i] = parent;
  2839. }
  2840. } else {
  2841. node.transform = parent.transform;
  2842. }
  2843. if (node.children) {
  2844. node.children.forEach(function(child) {
  2845. recurse(child, node);
  2846. });
  2847. }
  2848. return node;
  2849. }
  2850. function forward(lambda, phi) {
  2851. var node = face(lambda, phi),
  2852. point = node.project([lambda * degrees, phi * degrees]),
  2853. t;
  2854. if (t = node.transform) {
  2855. return [
  2856. t[0] * point[0] + t[1] * point[1] + t[2],
  2857. -(t[3] * point[0] + t[4] * point[1] + t[5])
  2858. ];
  2859. }
  2860. point[1] = -point[1];
  2861. return point;
  2862. }
  2863. // Naive inverse! A faster solution would use bounding boxes, or even a
  2864. // polygonal quadtree.
  2865. if (hasInverse(root)) forward.invert = function(x, y) {
  2866. var coordinates = faceInvert(root, [x, -y]);
  2867. return coordinates && (coordinates[0] *= radians, coordinates[1] *= radians, coordinates);
  2868. };
  2869. function faceInvert(node, coordinates) {
  2870. var invert = node.project.invert,
  2871. t = node.transform,
  2872. point = coordinates;
  2873. if (t) {
  2874. t = inverse(t);
  2875. point = [
  2876. t[0] * point[0] + t[1] * point[1] + t[2],
  2877. (t[3] * point[0] + t[4] * point[1] + t[5])
  2878. ];
  2879. }
  2880. if (invert && node === faceDegrees(p = invert(point))) return p;
  2881. var p,
  2882. children = node.children;
  2883. for (var i = 0, n = children && children.length; i < n; ++i) {
  2884. if (p = faceInvert(children[i], coordinates)) return p;
  2885. }
  2886. }
  2887. function faceDegrees(coordinates) {
  2888. return face(coordinates[0] * radians, coordinates[1] * radians);
  2889. }
  2890. var proj = d3Geo.geoProjection(forward),
  2891. stream_ = proj.stream;
  2892. proj.stream = function(stream) {
  2893. var rotate = proj.rotate(),
  2894. rotateStream = stream_(stream),
  2895. sphereStream = (proj.rotate([0, 0]), stream_(stream));
  2896. proj.rotate(rotate);
  2897. rotateStream.sphere = function() {
  2898. sphereStream.polygonStart();
  2899. sphereStream.lineStart();
  2900. outline(sphereStream, root);
  2901. sphereStream.lineEnd();
  2902. sphereStream.polygonEnd();
  2903. };
  2904. return rotateStream;
  2905. };
  2906. return proj.angle(-30);
  2907. }
  2908. function outline(stream, node, parent) {
  2909. var point,
  2910. edges = node.edges,
  2911. n = edges.length,
  2912. edge,
  2913. multiPoint = {type: "MultiPoint", coordinates: node.face},
  2914. notPoles = node.face.filter(function(d) { return abs(d[1]) !== 90; }),
  2915. b = d3Geo.geoBounds({type: "MultiPoint", coordinates: notPoles}),
  2916. inside = false,
  2917. j = -1,
  2918. dx = b[1][0] - b[0][0];
  2919. // TODO
  2920. var c = dx === 180 || dx === 360
  2921. ? [(b[0][0] + b[1][0]) / 2, (b[0][1] + b[1][1]) / 2]
  2922. : d3Geo.geoCentroid(multiPoint);
  2923. // First find the shared edge…
  2924. if (parent) while (++j < n) {
  2925. if (edges[j] === parent) break;
  2926. }
  2927. ++j;
  2928. for (var i = 0; i < n; ++i) {
  2929. edge = edges[(i + j) % n];
  2930. if (Array.isArray(edge)) {
  2931. if (!inside) {
  2932. stream.point((point = d3Geo.geoInterpolate(edge[0], c)(epsilon$1))[0], point[1]);
  2933. inside = true;
  2934. }
  2935. stream.point((point = d3Geo.geoInterpolate(edge[1], c)(epsilon$1))[0], point[1]);
  2936. } else {
  2937. inside = false;
  2938. if (edge !== parent) outline(stream, edge, node);
  2939. }
  2940. }
  2941. }
  2942. // Tests equality of two spherical points.
  2943. function pointEqual(a, b) {
  2944. return a && b && a[0] === b[0] && a[1] === b[1];
  2945. }
  2946. // Finds a shared edge given two clockwise polygons.
  2947. function sharedEdge(a, b) {
  2948. var x, y, n = a.length, found = null;
  2949. for (var i = 0; i < n; ++i) {
  2950. x = a[i];
  2951. for (var j = b.length; --j >= 0;) {
  2952. y = b[j];
  2953. if (x[0] === y[0] && x[1] === y[1]) {
  2954. if (found) return [found, x];
  2955. found = x;
  2956. }
  2957. }
  2958. }
  2959. }
  2960. // Converts an array of n face vertices to an array of n + 1 edges.
  2961. function faceEdges(face) {
  2962. var n = face.length,
  2963. edges = [];
  2964. for (var a = face[n - 1], i = 0; i < n; ++i) edges.push([a, a = face[i]]);
  2965. return edges;
  2966. }
  2967. function hasInverse(node) {
  2968. return node.project.invert || node.children && node.children.some(hasInverse);
  2969. }
  2970. // TODO generate on-the-fly to avoid external modification.
  2971. var octahedron = [
  2972. [0, 90],
  2973. [-90, 0], [0, 0], [90, 0], [180, 0],
  2974. [0, -90]
  2975. ];
  2976. var octahedron$1 = [
  2977. [0, 2, 1],
  2978. [0, 3, 2],
  2979. [5, 1, 2],
  2980. [5, 2, 3],
  2981. [0, 1, 4],
  2982. [0, 4, 3],
  2983. [5, 4, 1],
  2984. [5, 3, 4]
  2985. ].map(function(face) {
  2986. return face.map(function(i) {
  2987. return octahedron[i];
  2988. });
  2989. });
  2990. function butterfly(faceProjection) {
  2991. faceProjection = faceProjection || function(face) {
  2992. var c = d3Geo.geoCentroid({type: "MultiPoint", coordinates: face});
  2993. return d3Geo.geoGnomonic().scale(1).translate([0, 0]).rotate([-c[0], -c[1]]);
  2994. };
  2995. var faces = octahedron$1.map(function(face) {
  2996. return {face: face, project: faceProjection(face)};
  2997. });
  2998. [-1, 0, 0, 1, 0, 1, 4, 5].forEach(function(d, i) {
  2999. var node = faces[d];
  3000. node && (node.children || (node.children = [])).push(faces[i]);
  3001. });
  3002. return polyhedral(faces[0], function(lambda, phi) {
  3003. return faces[lambda < -pi / 2 ? phi < 0 ? 6 : 4
  3004. : lambda < 0 ? phi < 0 ? 2 : 0
  3005. : lambda < pi / 2 ? phi < 0 ? 3 : 1
  3006. : phi < 0 ? 7 : 5];
  3007. })
  3008. .angle(-30)
  3009. .scale(101.858)
  3010. .center([0, 45]);
  3011. }
  3012. var kx = 2 / sqrt(3);
  3013. function collignonK(a, b) {
  3014. var p = collignonRaw(a, b);
  3015. return [p[0] * kx, p[1]];
  3016. }
  3017. collignonK.invert = function(x,y) {
  3018. return collignonRaw.invert(x / kx, y);
  3019. };
  3020. function collignon(faceProjection) {
  3021. faceProjection = faceProjection || function(face) {
  3022. var c = d3Geo.geoCentroid({type: "MultiPoint", coordinates: face});
  3023. return d3Geo.geoProjection(collignonK).translate([0, 0]).scale(1).rotate(c[1] > 0 ? [-c[0], 0] : [180 - c[0], 180]);
  3024. };
  3025. var faces = octahedron$1.map(function(face) {
  3026. return {face: face, project: faceProjection(face)};
  3027. });
  3028. [-1, 0, 0, 1, 0, 1, 4, 5].forEach(function(d, i) {
  3029. var node = faces[d];
  3030. node && (node.children || (node.children = [])).push(faces[i]);
  3031. });
  3032. return polyhedral(faces[0], function(lambda, phi) {
  3033. return faces[lambda < -pi / 2 ? phi < 0 ? 6 : 4
  3034. : lambda < 0 ? phi < 0 ? 2 : 0
  3035. : lambda < pi / 2 ? phi < 0 ? 3 : 1
  3036. : phi < 0 ? 7 : 5];
  3037. })
  3038. .angle(-30)
  3039. .scale(121.906)
  3040. .center([0, 48.5904]);
  3041. }
  3042. function waterman(faceProjection) {
  3043. faceProjection = faceProjection || function(face) {
  3044. var c = face.length === 6 ? d3Geo.geoCentroid({type: "MultiPoint", coordinates: face}) : face[0];
  3045. return d3Geo.geoGnomonic().scale(1).translate([0, 0]).rotate([-c[0], -c[1]]);
  3046. };
  3047. var w5 = octahedron$1.map(function(face) {
  3048. var xyz = face.map(cartesian),
  3049. n = xyz.length,
  3050. a = xyz[n - 1],
  3051. b,
  3052. hexagon = [];
  3053. for (var i = 0; i < n; ++i) {
  3054. b = xyz[i];
  3055. hexagon.push(spherical([
  3056. a[0] * 0.9486832980505138 + b[0] * 0.31622776601683794,
  3057. a[1] * 0.9486832980505138 + b[1] * 0.31622776601683794,
  3058. a[2] * 0.9486832980505138 + b[2] * 0.31622776601683794
  3059. ]), spherical([
  3060. b[0] * 0.9486832980505138 + a[0] * 0.31622776601683794,
  3061. b[1] * 0.9486832980505138 + a[1] * 0.31622776601683794,
  3062. b[2] * 0.9486832980505138 + a[2] * 0.31622776601683794
  3063. ]));
  3064. a = b;
  3065. }
  3066. return hexagon;
  3067. });
  3068. var cornerNormals = [];
  3069. var parents = [-1, 0, 0, 1, 0, 1, 4, 5];
  3070. w5.forEach(function(hexagon, j) {
  3071. var face = octahedron$1[j],
  3072. n = face.length,
  3073. normals = cornerNormals[j] = [];
  3074. for (var i = 0; i < n; ++i) {
  3075. w5.push([
  3076. face[i],
  3077. hexagon[(i * 2 + 2) % (2 * n)],
  3078. hexagon[(i * 2 + 1) % (2 * n)]
  3079. ]);
  3080. parents.push(j);
  3081. normals.push(cross(
  3082. cartesian(hexagon[(i * 2 + 2) % (2 * n)]),
  3083. cartesian(hexagon[(i * 2 + 1) % (2 * n)])
  3084. ));
  3085. }
  3086. });
  3087. var faces = w5.map(function(face) {
  3088. return {
  3089. project: faceProjection(face),
  3090. face: face
  3091. };
  3092. });
  3093. parents.forEach(function(d, i) {
  3094. var parent = faces[d];
  3095. parent && (parent.children || (parent.children = [])).push(faces[i]);
  3096. });
  3097. function face(lambda, phi) {
  3098. var cosphi = cos(phi),
  3099. p = [cosphi * cos(lambda), cosphi * sin(lambda), sin(phi)];
  3100. var hexagon = lambda < -pi / 2 ? phi < 0 ? 6 : 4
  3101. : lambda < 0 ? phi < 0 ? 2 : 0
  3102. : lambda < pi / 2 ? phi < 0 ? 3 : 1
  3103. : phi < 0 ? 7 : 5;
  3104. var n = cornerNormals[hexagon];
  3105. return faces[dot(n[0], p) < 0 ? 8 + 3 * hexagon
  3106. : dot(n[1], p) < 0 ? 8 + 3 * hexagon + 1
  3107. : dot(n[2], p) < 0 ? 8 + 3 * hexagon + 2
  3108. : hexagon];
  3109. }
  3110. return polyhedral(faces[0], face)
  3111. .angle(-30)
  3112. .scale(110.625)
  3113. .center([0,45]);
  3114. }
  3115. function dot(a, b) {
  3116. for (var i = 0, n = a.length, s = 0; i < n; ++i) s += a[i] * b[i];
  3117. return s;
  3118. }
  3119. function cross(a, b) {
  3120. return [
  3121. a[1] * b[2] - a[2] * b[1],
  3122. a[2] * b[0] - a[0] * b[2],
  3123. a[0] * b[1] - a[1] * b[0]
  3124. ];
  3125. }
  3126. // Converts 3D Cartesian to spherical coordinates (degrees).
  3127. function spherical(cartesian) {
  3128. return [
  3129. atan2(cartesian[1], cartesian[0]) * degrees,
  3130. asin(max(-1, min(1, cartesian[2]))) * degrees
  3131. ];
  3132. }
  3133. // Converts spherical coordinates (degrees) to 3D Cartesian.
  3134. function cartesian(coordinates) {
  3135. var lambda = coordinates[0] * radians,
  3136. phi = coordinates[1] * radians,
  3137. cosphi = cos(phi);
  3138. return [
  3139. cosphi * cos(lambda),
  3140. cosphi * sin(lambda),
  3141. sin(phi)
  3142. ];
  3143. }
  3144. var noop = () => {};
  3145. function clockwise(ring) {
  3146. if ((n = ring.length) < 4) return false;
  3147. var i = 0,
  3148. n,
  3149. area = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];
  3150. while (++i < n) area += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];
  3151. return area <= 0;
  3152. }
  3153. function contains(ring, point) {
  3154. var x = point[0],
  3155. y = point[1],
  3156. contains = false;
  3157. for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) {
  3158. var pi = ring[i], xi = pi[0], yi = pi[1],
  3159. pj = ring[j], xj = pj[0], yj = pj[1];
  3160. if (((yi > y) ^ (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) contains = !contains;
  3161. }
  3162. return contains;
  3163. }
  3164. function index(object, projection) {
  3165. var stream = projection.stream, project;
  3166. if (!stream) throw new Error("invalid projection");
  3167. switch (object && object.type) {
  3168. case "Feature": project = projectFeature; break;
  3169. case "FeatureCollection": project = projectFeatureCollection; break;
  3170. default: project = projectGeometry; break;
  3171. }
  3172. return project(object, stream);
  3173. }
  3174. function projectFeatureCollection(o, stream) {
  3175. return {
  3176. type: "FeatureCollection",
  3177. features: o.features.map(function(f) {
  3178. return projectFeature(f, stream);
  3179. })
  3180. };
  3181. }
  3182. function projectFeature(o, stream) {
  3183. return {
  3184. type: "Feature",
  3185. id: o.id,
  3186. properties: o.properties,
  3187. geometry: projectGeometry(o.geometry, stream)
  3188. };
  3189. }
  3190. function projectGeometryCollection(o, stream) {
  3191. return {
  3192. type: "GeometryCollection",
  3193. geometries: o.geometries.map(function(o) {
  3194. return projectGeometry(o, stream);
  3195. })
  3196. };
  3197. }
  3198. function projectGeometry(o, stream) {
  3199. if (!o) return null;
  3200. if (o.type === "GeometryCollection") return projectGeometryCollection(o, stream);
  3201. var sink;
  3202. switch (o.type) {
  3203. case "Point": sink = sinkPoint; break;
  3204. case "MultiPoint": sink = sinkPoint; break;
  3205. case "LineString": sink = sinkLine; break;
  3206. case "MultiLineString": sink = sinkLine; break;
  3207. case "Polygon": sink = sinkPolygon; break;
  3208. case "MultiPolygon": sink = sinkPolygon; break;
  3209. case "Sphere": sink = sinkPolygon; break;
  3210. default: return null;
  3211. }
  3212. d3Geo.geoStream(o, stream(sink));
  3213. return sink.result();
  3214. }
  3215. var points = [],
  3216. lines = [];
  3217. var sinkPoint = {
  3218. point: function(x, y) {
  3219. points.push([x, y]);
  3220. },
  3221. result: function() {
  3222. var result = !points.length ? null
  3223. : points.length < 2 ? {type: "Point", coordinates: points[0]}
  3224. : {type: "MultiPoint", coordinates: points};
  3225. points = [];
  3226. return result;
  3227. }
  3228. };
  3229. var sinkLine = {
  3230. lineStart: noop,
  3231. point: function(x, y) {
  3232. points.push([x, y]);
  3233. },
  3234. lineEnd: function() {
  3235. if (points.length) lines.push(points), points = [];
  3236. },
  3237. result: function() {
  3238. var result = !lines.length ? null
  3239. : lines.length < 2 ? {type: "LineString", coordinates: lines[0]}
  3240. : {type: "MultiLineString", coordinates: lines};
  3241. lines = [];
  3242. return result;
  3243. }
  3244. };
  3245. var sinkPolygon = {
  3246. polygonStart: noop,
  3247. lineStart: noop,
  3248. point: function(x, y) {
  3249. points.push([x, y]);
  3250. },
  3251. lineEnd: function() {
  3252. var n = points.length;
  3253. if (n) {
  3254. do points.push(points[0].slice()); while (++n < 4);
  3255. lines.push(points), points = [];
  3256. }
  3257. },
  3258. polygonEnd: noop,
  3259. result: function() {
  3260. if (!lines.length) return null;
  3261. var polygons = [],
  3262. holes = [];
  3263. // https://github.com/d3/d3/issues/1558
  3264. lines.forEach(function(ring) {
  3265. if (clockwise(ring)) polygons.push([ring]);
  3266. else holes.push(ring);
  3267. });
  3268. holes.forEach(function(hole) {
  3269. var point = hole[0];
  3270. polygons.some(function(polygon) {
  3271. if (contains(polygon[0], point)) {
  3272. polygon.push(hole);
  3273. return true;
  3274. }
  3275. }) || polygons.push([hole]);
  3276. });
  3277. lines = [];
  3278. return !polygons.length ? null
  3279. : polygons.length > 1 ? {type: "MultiPolygon", coordinates: polygons}
  3280. : {type: "Polygon", coordinates: polygons[0]};
  3281. }
  3282. };
  3283. function quincuncial(project) {
  3284. var dx = project(halfPi, 0)[0] - project(-halfPi, 0)[0];
  3285. function projectQuincuncial(lambda, phi) {
  3286. var t = abs(lambda) < halfPi,
  3287. p = project(t ? lambda : lambda > 0 ? lambda - pi : lambda + pi, phi),
  3288. x = (p[0] - p[1]) * sqrt1_2,
  3289. y = (p[0] + p[1]) * sqrt1_2;
  3290. if (t) return [x, y];
  3291. var d = dx * sqrt1_2,
  3292. s = x > 0 ^ y > 0 ? -1 : 1;
  3293. return [s * x - sign(y) * d, s * y - sign(x) * d];
  3294. }
  3295. if (project.invert) projectQuincuncial.invert = function(x0, y0) {
  3296. var x = (x0 + y0) * sqrt1_2,
  3297. y = (y0 - x0) * sqrt1_2,
  3298. t = abs(x) < 0.5 * dx && abs(y) < 0.5 * dx;
  3299. if (!t) {
  3300. var d = dx * sqrt1_2,
  3301. s = x > 0 ^ y > 0 ? -1 : 1,
  3302. x1 = -s * x0 + (y > 0 ? 1 : -1) * d,
  3303. y1 = -s * y0 + (x > 0 ? 1 : -1) * d;
  3304. x = (-x1 - y1) * sqrt1_2;
  3305. y = (x1 - y1) * sqrt1_2;
  3306. }
  3307. var p = project.invert(x, y);
  3308. if (!t) p[0] += x > 0 ? pi : -pi;
  3309. return p;
  3310. };
  3311. return d3Geo.geoProjection(projectQuincuncial)
  3312. .rotate([-90, -90, 45])
  3313. .clipAngle(180 - 1e-3);
  3314. }
  3315. function gringorten() {
  3316. return quincuncial(gringortenRaw)
  3317. .scale(176.423);
  3318. }
  3319. function peirce() {
  3320. return quincuncial(guyouRaw)
  3321. .scale(111.48);
  3322. }
  3323. function quantize$1(input, digits) {
  3324. if (!(0 <= (digits = +digits) && digits <= 20)) throw new Error("invalid digits");
  3325. function quantizePoint(input) {
  3326. var n = input.length, i = 2, output = new Array(n);
  3327. output[0] = +input[0].toFixed(digits);
  3328. output[1] = +input[1].toFixed(digits);
  3329. while (i < n) output[i] = input[i], ++i;
  3330. return output;
  3331. }
  3332. function quantizePoints(input) {
  3333. return input.map(quantizePoint);
  3334. }
  3335. function quantizePointsNoDuplicates(input) {
  3336. var point0 = quantizePoint(input[0]);
  3337. var output = [point0];
  3338. for (var i = 1; i < input.length; i++) {
  3339. var point = quantizePoint(input[i]);
  3340. if (point.length > 2 || point[0] != point0[0] || point[1] != point0[1]) {
  3341. output.push(point);
  3342. point0 = point;
  3343. }
  3344. }
  3345. if (output.length === 1 && input.length > 1) {
  3346. output.push(quantizePoint(input[input.length - 1]));
  3347. }
  3348. return output;
  3349. }
  3350. function quantizePolygon(input) {
  3351. return input.map(quantizePointsNoDuplicates);
  3352. }
  3353. function quantizeGeometry(input) {
  3354. if (input == null) return input;
  3355. var output;
  3356. switch (input.type) {
  3357. case "GeometryCollection": output = {type: "GeometryCollection", geometries: input.geometries.map(quantizeGeometry)}; break;
  3358. case "Point": output = {type: "Point", coordinates: quantizePoint(input.coordinates)}; break;
  3359. case "MultiPoint": output = {type: input.type, coordinates: quantizePoints(input.coordinates)}; break;
  3360. case "LineString": output = {type: input.type, coordinates: quantizePointsNoDuplicates(input.coordinates)}; break;
  3361. case "MultiLineString": case "Polygon": output = {type: input.type, coordinates: quantizePolygon(input.coordinates)}; break;
  3362. case "MultiPolygon": output = {type: "MultiPolygon", coordinates: input.coordinates.map(quantizePolygon)}; break;
  3363. default: return input;
  3364. }
  3365. if (input.bbox != null) output.bbox = input.bbox;
  3366. return output;
  3367. }
  3368. function quantizeFeature(input) {
  3369. var output = {type: "Feature", properties: input.properties, geometry: quantizeGeometry(input.geometry)};
  3370. if (input.id != null) output.id = input.id;
  3371. if (input.bbox != null) output.bbox = input.bbox;
  3372. return output;
  3373. }
  3374. if (input != null) switch (input.type) {
  3375. case "Feature": return quantizeFeature(input);
  3376. case "FeatureCollection": {
  3377. var output = {type: "FeatureCollection", features: input.features.map(quantizeFeature)};
  3378. if (input.bbox != null) output.bbox = input.bbox;
  3379. return output;
  3380. }
  3381. default: return quantizeGeometry(input);
  3382. }
  3383. return input;
  3384. }
  3385. function rectangularPolyconicRaw(phi0) {
  3386. var sinPhi0 = sin(phi0);
  3387. function forward(lambda, phi) {
  3388. var A = sinPhi0 ? tan(lambda * sinPhi0 / 2) / sinPhi0 : lambda / 2;
  3389. if (!phi) return [2 * A, -phi0];
  3390. var E = 2 * atan(A * sin(phi)),
  3391. cotPhi = 1 / tan(phi);
  3392. return [
  3393. sin(E) * cotPhi,
  3394. phi + (1 - cos(E)) * cotPhi - phi0
  3395. ];
  3396. }
  3397. // TODO return null for points outside outline.
  3398. forward.invert = function(x, y) {
  3399. if (abs(y += phi0) < epsilon$1) return [sinPhi0 ? 2 * atan(sinPhi0 * x / 2) / sinPhi0 : x, 0];
  3400. var k = x * x + y * y,
  3401. phi = 0,
  3402. i = 10, delta;
  3403. do {
  3404. var tanPhi = tan(phi),
  3405. secPhi = 1 / cos(phi),
  3406. j = k - 2 * y * phi + phi * phi;
  3407. phi -= delta = (tanPhi * j + 2 * (phi - y)) / (2 + j * secPhi * secPhi + 2 * (phi - y) * tanPhi);
  3408. } while (abs(delta) > epsilon$1 && --i > 0);
  3409. var E = x * (tanPhi = tan(phi)),
  3410. A = tan(abs(y) < abs(phi + 1 / tanPhi) ? asin(E) * 0.5 : acos(E) * 0.5 + pi / 4) / sin(phi);
  3411. return [
  3412. sinPhi0 ? 2 * atan(sinPhi0 * A) / sinPhi0 : 2 * A,
  3413. phi
  3414. ];
  3415. };
  3416. return forward;
  3417. }
  3418. function rectangularPolyconic() {
  3419. return parallel1(rectangularPolyconicRaw)
  3420. .scale(131.215);
  3421. }
  3422. var K = [
  3423. [0.9986, -0.062],
  3424. [1.0000, 0.0000],
  3425. [0.9986, 0.0620],
  3426. [0.9954, 0.1240],
  3427. [0.9900, 0.1860],
  3428. [0.9822, 0.2480],
  3429. [0.9730, 0.3100],
  3430. [0.9600, 0.3720],
  3431. [0.9427, 0.4340],
  3432. [0.9216, 0.4958],
  3433. [0.8962, 0.5571],
  3434. [0.8679, 0.6176],
  3435. [0.8350, 0.6769],
  3436. [0.7986, 0.7346],
  3437. [0.7597, 0.7903],
  3438. [0.7186, 0.8435],
  3439. [0.6732, 0.8936],
  3440. [0.6213, 0.9394],
  3441. [0.5722, 0.9761],
  3442. [0.5322, 1.0000]
  3443. ];
  3444. K.forEach(function(d) {
  3445. d[1] *= 1.593415793900743;
  3446. });
  3447. function robinsonRaw(lambda, phi) {
  3448. var i = min(18, abs(phi) * 36 / pi),
  3449. i0 = floor(i),
  3450. di = i - i0,
  3451. ax = (k = K[i0])[0],
  3452. ay = k[1],
  3453. bx = (k = K[++i0])[0],
  3454. by = k[1],
  3455. cx = (k = K[min(19, ++i0)])[0],
  3456. cy = k[1],
  3457. k;
  3458. return [
  3459. lambda * (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2),
  3460. sign(phi) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2)
  3461. ];
  3462. }
  3463. robinsonRaw.invert = function(x, y) {
  3464. var phi = y * 90,
  3465. i = min(18, abs(phi / 5)),
  3466. i0 = max(0, floor(i));
  3467. do {
  3468. var ay = K[i0][1],
  3469. by = K[i0 + 1][1],
  3470. cy = K[min(19, i0 + 2)][1],
  3471. u = cy - ay,
  3472. v = cy - 2 * by + ay,
  3473. t = 2 * (abs(y) - by) / u,
  3474. c = v / u,
  3475. di = t * (1 - c * t * (1 - 2 * c * t));
  3476. if (di >= 0 || i0 === 1) {
  3477. phi = (y >= 0 ? 5 : -5) * (di + i);
  3478. var j = 50, delta;
  3479. do {
  3480. i = min(18, abs(phi) / 5);
  3481. i0 = floor(i);
  3482. di = i - i0;
  3483. ay = K[i0][1];
  3484. by = K[i0 + 1][1];
  3485. cy = K[min(19, i0 + 2)][1];
  3486. phi -= (delta = sign(y) * (by + di * (cy - ay) / 2 + di * di * (cy - 2 * by + ay) / 2) - y) * degrees;
  3487. } while (abs(delta) > epsilon2 && --j > 0);
  3488. break;
  3489. }
  3490. } while (--i0 >= 0);
  3491. var ax = K[i0][0],
  3492. bx = K[i0 + 1][0],
  3493. cx = K[min(19, i0 + 2)][0];
  3494. return [
  3495. x / (bx + di * (cx - ax) / 2 + di * di * (cx - 2 * bx + ax) / 2),
  3496. phi * radians
  3497. ];
  3498. };
  3499. function robinson() {
  3500. return d3Geo.geoProjection(robinsonRaw)
  3501. .scale(152.63);
  3502. }
  3503. function satelliteVerticalRaw(P) {
  3504. function forward(lambda, phi) {
  3505. var cosPhi = cos(phi),
  3506. k = (P - 1) / (P - cosPhi * cos(lambda));
  3507. return [
  3508. k * cosPhi * sin(lambda),
  3509. k * sin(phi)
  3510. ];
  3511. }
  3512. forward.invert = function(x, y) {
  3513. var rho2 = x * x + y * y,
  3514. rho = sqrt(rho2),
  3515. sinc = (P - sqrt(1 - rho2 * (P + 1) / (P - 1))) / ((P - 1) / rho + rho / (P - 1));
  3516. return [
  3517. atan2(x * sinc, rho * sqrt(1 - sinc * sinc)),
  3518. rho ? asin(y * sinc / rho) : 0
  3519. ];
  3520. };
  3521. return forward;
  3522. }
  3523. function satelliteRaw(P, omega) {
  3524. var vertical = satelliteVerticalRaw(P);
  3525. if (!omega) return vertical;
  3526. var cosOmega = cos(omega),
  3527. sinOmega = sin(omega);
  3528. function forward(lambda, phi) {
  3529. var coordinates = vertical(lambda, phi),
  3530. y = coordinates[1],
  3531. A = y * sinOmega / (P - 1) + cosOmega;
  3532. return [
  3533. coordinates[0] * cosOmega / A,
  3534. y / A
  3535. ];
  3536. }
  3537. forward.invert = function(x, y) {
  3538. var k = (P - 1) / (P - 1 - y * sinOmega);
  3539. return vertical.invert(k * x, k * y * cosOmega);
  3540. };
  3541. return forward;
  3542. }
  3543. function satellite() {
  3544. var distance = 2,
  3545. omega = 0,
  3546. m = d3Geo.geoProjectionMutator(satelliteRaw),
  3547. p = m(distance, omega);
  3548. // As a multiple of radius.
  3549. p.distance = function(_) {
  3550. if (!arguments.length) return distance;
  3551. return m(distance = +_, omega);
  3552. };
  3553. p.tilt = function(_) {
  3554. if (!arguments.length) return omega * degrees;
  3555. return m(distance, omega = _ * radians);
  3556. };
  3557. return p
  3558. .scale(432.147)
  3559. .clipAngle(acos(1 / distance) * degrees - 1e-6);
  3560. }
  3561. var epsilon = 1e-4,
  3562. epsilonInverse = 1e4,
  3563. x0 = -180, x0e = x0 + epsilon,
  3564. x1 = 180, x1e = x1 - epsilon,
  3565. y0 = -90, y0e = y0 + epsilon,
  3566. y1 = 90, y1e = y1 - epsilon;
  3567. function nonempty(coordinates) {
  3568. return coordinates.length > 0;
  3569. }
  3570. function quantize(x) {
  3571. return Math.floor(x * epsilonInverse) / epsilonInverse;
  3572. }
  3573. function normalizePoint(y) {
  3574. return y === y0 || y === y1 ? [0, y] : [x0, quantize(y)]; // pole or antimeridian?
  3575. }
  3576. function clampPoint(p) {
  3577. var x = p[0], y = p[1], clamped = false;
  3578. if (x <= x0e) x = x0, clamped = true;
  3579. else if (x >= x1e) x = x1, clamped = true;
  3580. if (y <= y0e) y = y0, clamped = true;
  3581. else if (y >= y1e) y = y1, clamped = true;
  3582. return clamped ? [x, y] : p;
  3583. }
  3584. function clampPoints(points) {
  3585. return points.map(clampPoint);
  3586. }
  3587. // For each ring, detect where it crosses the antimeridian or pole.
  3588. function extractFragments(rings, polygon, fragments) {
  3589. for (var j = 0, m = rings.length; j < m; ++j) {
  3590. var ring = rings[j].slice();
  3591. // By default, assume that this ring doesn’t need any stitching.
  3592. fragments.push({index: -1, polygon: polygon, ring: ring});
  3593. for (var i = 0, n = ring.length; i < n; ++i) {
  3594. var point = ring[i],
  3595. x = point[0],
  3596. y = point[1];
  3597. // If this is an antimeridian or polar point…
  3598. if (x <= x0e || x >= x1e || y <= y0e || y >= y1e) {
  3599. ring[i] = clampPoint(point);
  3600. // Advance through any antimeridian or polar points…
  3601. for (var k = i + 1; k < n; ++k) {
  3602. var pointk = ring[k],
  3603. xk = pointk[0],
  3604. yk = pointk[1];
  3605. if (xk > x0e && xk < x1e && yk > y0e && yk < y1e) break;
  3606. }
  3607. // If this was just a single antimeridian or polar point,
  3608. // we don’t need to cut this ring into a fragment;
  3609. // we can just leave it as-is.
  3610. if (k === i + 1) continue;
  3611. // Otherwise, if this is not the first point in the ring,
  3612. // cut the current fragment so that it ends at the current point.
  3613. // The current point is also normalized for later joining.
  3614. if (i) {
  3615. var fragmentBefore = {index: -1, polygon: polygon, ring: ring.slice(0, i + 1)};
  3616. fragmentBefore.ring[fragmentBefore.ring.length - 1] = normalizePoint(y);
  3617. fragments[fragments.length - 1] = fragmentBefore;
  3618. }
  3619. // If the ring started with an antimeridian fragment,
  3620. // we can ignore that fragment entirely.
  3621. else fragments.pop();
  3622. // If the remainder of the ring is an antimeridian fragment,
  3623. // move on to the next ring.
  3624. if (k >= n) break;
  3625. // Otherwise, add the remaining ring fragment and continue.
  3626. fragments.push({index: -1, polygon: polygon, ring: ring = ring.slice(k - 1)});
  3627. ring[0] = normalizePoint(ring[0][1]);
  3628. i = -1;
  3629. n = ring.length;
  3630. }
  3631. }
  3632. }
  3633. }
  3634. // Now stitch the fragments back together into rings.
  3635. function stitchFragments(fragments) {
  3636. var i, n = fragments.length;
  3637. // To connect the fragments start-to-end, create a simple index by end.
  3638. var fragmentByStart = {},
  3639. fragmentByEnd = {},
  3640. fragment,
  3641. start,
  3642. startFragment,
  3643. end,
  3644. endFragment;
  3645. // For each fragment…
  3646. for (i = 0; i < n; ++i) {
  3647. fragment = fragments[i];
  3648. start = fragment.ring[0];
  3649. end = fragment.ring[fragment.ring.length - 1];
  3650. // If this fragment is closed, add it as a standalone ring.
  3651. if (start[0] === end[0] && start[1] === end[1]) {
  3652. fragment.polygon.push(fragment.ring);
  3653. fragments[i] = null;
  3654. continue;
  3655. }
  3656. fragment.index = i;
  3657. fragmentByStart[start] = fragmentByEnd[end] = fragment;
  3658. }
  3659. // For each open fragment…
  3660. for (i = 0; i < n; ++i) {
  3661. fragment = fragments[i];
  3662. if (fragment) {
  3663. start = fragment.ring[0];
  3664. end = fragment.ring[fragment.ring.length - 1];
  3665. startFragment = fragmentByEnd[start];
  3666. endFragment = fragmentByStart[end];
  3667. delete fragmentByStart[start];
  3668. delete fragmentByEnd[end];
  3669. // If this fragment is closed, add it as a standalone ring.
  3670. if (start[0] === end[0] && start[1] === end[1]) {
  3671. fragment.polygon.push(fragment.ring);
  3672. continue;
  3673. }
  3674. if (startFragment) {
  3675. delete fragmentByEnd[start];
  3676. delete fragmentByStart[startFragment.ring[0]];
  3677. startFragment.ring.pop(); // drop the shared coordinate
  3678. fragments[startFragment.index] = null;
  3679. fragment = {index: -1, polygon: startFragment.polygon, ring: startFragment.ring.concat(fragment.ring)};
  3680. if (startFragment === endFragment) {
  3681. // Connect both ends to this single fragment to create a ring.
  3682. fragment.polygon.push(fragment.ring);
  3683. } else {
  3684. fragment.index = n++;
  3685. fragments.push(fragmentByStart[fragment.ring[0]] = fragmentByEnd[fragment.ring[fragment.ring.length - 1]] = fragment);
  3686. }
  3687. } else if (endFragment) {
  3688. delete fragmentByStart[end];
  3689. delete fragmentByEnd[endFragment.ring[endFragment.ring.length - 1]];
  3690. fragment.ring.pop(); // drop the shared coordinate
  3691. fragment = {index: n++, polygon: endFragment.polygon, ring: fragment.ring.concat(endFragment.ring)};
  3692. fragments[endFragment.index] = null;
  3693. fragments.push(fragmentByStart[fragment.ring[0]] = fragmentByEnd[fragment.ring[fragment.ring.length - 1]] = fragment);
  3694. } else {
  3695. fragment.ring.push(fragment.ring[0]); // close ring
  3696. fragment.polygon.push(fragment.ring);
  3697. }
  3698. }
  3699. }
  3700. }
  3701. function stitchFeature(input) {
  3702. var output = {type: "Feature", geometry: stitchGeometry(input.geometry)};
  3703. if (input.id != null) output.id = input.id;
  3704. if (input.bbox != null) output.bbox = input.bbox;
  3705. if (input.properties != null) output.properties = input.properties;
  3706. return output;
  3707. }
  3708. function stitchGeometry(input) {
  3709. if (input == null) return input;
  3710. var output, fragments, i, n;
  3711. switch (input.type) {
  3712. case "GeometryCollection": output = {type: "GeometryCollection", geometries: input.geometries.map(stitchGeometry)}; break;
  3713. case "Point": output = {type: "Point", coordinates: clampPoint(input.coordinates)}; break;
  3714. case "MultiPoint": case "LineString": output = {type: input.type, coordinates: clampPoints(input.coordinates)}; break;
  3715. case "MultiLineString": output = {type: "MultiLineString", coordinates: input.coordinates.map(clampPoints)}; break;
  3716. case "Polygon": {
  3717. var polygon = [];
  3718. extractFragments(input.coordinates, polygon, fragments = []);
  3719. stitchFragments(fragments);
  3720. output = {type: "Polygon", coordinates: polygon};
  3721. break;
  3722. }
  3723. case "MultiPolygon": {
  3724. fragments = [], i = -1, n = input.coordinates.length;
  3725. var polygons = new Array(n);
  3726. while (++i < n) extractFragments(input.coordinates[i], polygons[i] = [], fragments);
  3727. stitchFragments(fragments);
  3728. output = {type: "MultiPolygon", coordinates: polygons.filter(nonempty)};
  3729. break;
  3730. }
  3731. default: return input;
  3732. }
  3733. if (input.bbox != null) output.bbox = input.bbox;
  3734. return output;
  3735. }
  3736. function stitch(input) {
  3737. if (input == null) return input;
  3738. switch (input.type) {
  3739. case "Feature": return stitchFeature(input);
  3740. case "FeatureCollection": {
  3741. var output = {type: "FeatureCollection", features: input.features.map(stitchFeature)};
  3742. if (input.bbox != null) output.bbox = input.bbox;
  3743. return output;
  3744. }
  3745. default: return stitchGeometry(input);
  3746. }
  3747. }
  3748. function timesRaw(lambda, phi) {
  3749. var t = tan(phi / 2),
  3750. s = sin(quarterPi * t);
  3751. return [
  3752. lambda * (0.74482 - 0.34588 * s * s),
  3753. 1.70711 * t
  3754. ];
  3755. }
  3756. timesRaw.invert = function(x, y) {
  3757. var t = y / 1.70711,
  3758. s = sin(quarterPi * t);
  3759. return [
  3760. x / (0.74482 - 0.34588 * s * s),
  3761. 2 * atan(t)
  3762. ];
  3763. };
  3764. function times() {
  3765. return d3Geo.geoProjection(timesRaw)
  3766. .scale(146.153);
  3767. }
  3768. // Compute the origin as the midpoint of the two reference points.
  3769. // Rotate one of the reference points by the origin.
  3770. // Apply the spherical law of sines to compute gamma rotation.
  3771. function twoPoint(raw, p0, p1) {
  3772. var i = d3Geo.geoInterpolate(p0, p1),
  3773. o = i(0.5),
  3774. a = d3Geo.geoRotation([-o[0], -o[1]])(p0),
  3775. b = i.distance / 2,
  3776. y = -asin(sin(a[1] * radians) / sin(b)),
  3777. R = [-o[0], -o[1], -(a[0] > 0 ? pi - y : y) * degrees],
  3778. p = d3Geo.geoProjection(raw(b)).rotate(R),
  3779. r = d3Geo.geoRotation(R),
  3780. center = p.center;
  3781. delete p.rotate;
  3782. p.center = function(_) {
  3783. return arguments.length ? center(r(_)) : r.invert(center());
  3784. };
  3785. return p
  3786. .clipAngle(90);
  3787. }
  3788. function twoPointAzimuthalRaw(d) {
  3789. var cosd = cos(d);
  3790. function forward(lambda, phi) {
  3791. var coordinates = d3Geo.geoGnomonicRaw(lambda, phi);
  3792. coordinates[0] *= cosd;
  3793. return coordinates;
  3794. }
  3795. forward.invert = function(x, y) {
  3796. return d3Geo.geoGnomonicRaw.invert(x / cosd, y);
  3797. };
  3798. return forward;
  3799. }
  3800. function twoPointAzimuthalUsa() {
  3801. return twoPointAzimuthal([-158, 21.5], [-77, 39])
  3802. .clipAngle(60)
  3803. .scale(400);
  3804. }
  3805. function twoPointAzimuthal(p0, p1) {
  3806. return twoPoint(twoPointAzimuthalRaw, p0, p1);
  3807. }
  3808. function twoPointEquidistantRaw(z0) {
  3809. if (!(z0 *= 2)) return d3Geo.geoAzimuthalEquidistantRaw;
  3810. var lambdaa = -z0 / 2,
  3811. lambdab = -lambdaa,
  3812. z02 = z0 * z0,
  3813. tanLambda0 = tan(lambdab),
  3814. S = 0.5 / sin(lambdab);
  3815. function forward(lambda, phi) {
  3816. var za = acos(cos(phi) * cos(lambda - lambdaa)),
  3817. zb = acos(cos(phi) * cos(lambda - lambdab)),
  3818. ys = phi < 0 ? -1 : 1;
  3819. za *= za, zb *= zb;
  3820. return [
  3821. (za - zb) / (2 * z0),
  3822. ys * sqrt(4 * z02 * zb - (z02 - za + zb) * (z02 - za + zb)) / (2 * z0)
  3823. ];
  3824. }
  3825. forward.invert = function(x, y) {
  3826. var y2 = y * y,
  3827. cosza = cos(sqrt(y2 + (t = x + lambdaa) * t)),
  3828. coszb = cos(sqrt(y2 + (t = x + lambdab) * t)),
  3829. t,
  3830. d;
  3831. return [
  3832. atan2(d = cosza - coszb, t = (cosza + coszb) * tanLambda0),
  3833. (y < 0 ? -1 : 1) * acos(sqrt(t * t + d * d) * S)
  3834. ];
  3835. };
  3836. return forward;
  3837. }
  3838. function twoPointEquidistantUsa() {
  3839. return twoPointEquidistant([-158, 21.5], [-77, 39])
  3840. .clipAngle(130)
  3841. .scale(122.571);
  3842. }
  3843. function twoPointEquidistant(p0, p1) {
  3844. return twoPoint(twoPointEquidistantRaw, p0, p1);
  3845. }
  3846. function vanDerGrintenRaw(lambda, phi) {
  3847. if (abs(phi) < epsilon$1) return [lambda, 0];
  3848. var sinTheta = abs(phi / halfPi),
  3849. theta = asin(sinTheta);
  3850. if (abs(lambda) < epsilon$1 || abs(abs(phi) - halfPi) < epsilon$1) return [0, sign(phi) * pi * tan(theta / 2)];
  3851. var cosTheta = cos(theta),
  3852. A = abs(pi / lambda - lambda / pi) / 2,
  3853. A2 = A * A,
  3854. G = cosTheta / (sinTheta + cosTheta - 1),
  3855. P = G * (2 / sinTheta - 1),
  3856. P2 = P * P,
  3857. P2_A2 = P2 + A2,
  3858. G_P2 = G - P2,
  3859. Q = A2 + G;
  3860. return [
  3861. sign(lambda) * pi * (A * G_P2 + sqrt(A2 * G_P2 * G_P2 - P2_A2 * (G * G - P2))) / P2_A2,
  3862. sign(phi) * pi * (P * Q - A * sqrt((A2 + 1) * P2_A2 - Q * Q)) / P2_A2
  3863. ];
  3864. }
  3865. vanDerGrintenRaw.invert = function(x, y) {
  3866. if (abs(y) < epsilon$1) return [x, 0];
  3867. if (abs(x) < epsilon$1) return [0, halfPi * sin(2 * atan(y / pi))];
  3868. var x2 = (x /= pi) * x,
  3869. y2 = (y /= pi) * y,
  3870. x2_y2 = x2 + y2,
  3871. z = x2_y2 * x2_y2,
  3872. c1 = -abs(y) * (1 + x2_y2),
  3873. c2 = c1 - 2 * y2 + x2,
  3874. c3 = -2 * c1 + 1 + 2 * y2 + z,
  3875. d = y2 / c3 + (2 * c2 * c2 * c2 / (c3 * c3 * c3) - 9 * c1 * c2 / (c3 * c3)) / 27,
  3876. a1 = (c1 - c2 * c2 / (3 * c3)) / c3,
  3877. m1 = 2 * sqrt(-a1 / 3),
  3878. theta1 = acos(3 * d / (a1 * m1)) / 3;
  3879. return [
  3880. pi * (x2_y2 - 1 + sqrt(1 + 2 * (x2 - y2) + z)) / (2 * x),
  3881. sign(y) * pi * (-m1 * cos(theta1 + pi / 3) - c2 / (3 * c3))
  3882. ];
  3883. };
  3884. function vanDerGrinten() {
  3885. return d3Geo.geoProjection(vanDerGrintenRaw)
  3886. .scale(79.4183);
  3887. }
  3888. function vanDerGrinten2Raw(lambda, phi) {
  3889. if (abs(phi) < epsilon$1) return [lambda, 0];
  3890. var sinTheta = abs(phi / halfPi),
  3891. theta = asin(sinTheta);
  3892. if (abs(lambda) < epsilon$1 || abs(abs(phi) - halfPi) < epsilon$1) return [0, sign(phi) * pi * tan(theta / 2)];
  3893. var cosTheta = cos(theta),
  3894. A = abs(pi / lambda - lambda / pi) / 2,
  3895. A2 = A * A,
  3896. x1 = cosTheta * (sqrt(1 + A2) - A * cosTheta) / (1 + A2 * sinTheta * sinTheta);
  3897. return [
  3898. sign(lambda) * pi * x1,
  3899. sign(phi) * pi * sqrt(1 - x1 * (2 * A + x1))
  3900. ];
  3901. }
  3902. vanDerGrinten2Raw.invert = function(x, y) {
  3903. if (!x) return [0, halfPi * sin(2 * atan(y / pi))];
  3904. var x1 = abs(x / pi),
  3905. A = (1 - x1 * x1 - (y /= pi) * y) / (2 * x1),
  3906. A2 = A * A,
  3907. B = sqrt(A2 + 1);
  3908. return [
  3909. sign(x) * pi * (B - A),
  3910. sign(y) * halfPi * sin(2 * atan2(sqrt((1 - 2 * A * x1) * (A + B) - x1), sqrt(B + A + x1)))
  3911. ];
  3912. };
  3913. function vanDerGrinten2() {
  3914. return d3Geo.geoProjection(vanDerGrinten2Raw)
  3915. .scale(79.4183);
  3916. }
  3917. function vanDerGrinten3Raw(lambda, phi) {
  3918. if (abs(phi) < epsilon$1) return [lambda, 0];
  3919. var sinTheta = phi / halfPi,
  3920. theta = asin(sinTheta);
  3921. if (abs(lambda) < epsilon$1 || abs(abs(phi) - halfPi) < epsilon$1) return [0, pi * tan(theta / 2)];
  3922. var A = (pi / lambda - lambda / pi) / 2,
  3923. y1 = sinTheta / (1 + cos(theta));
  3924. return [
  3925. pi * (sign(lambda) * sqrt(A * A + 1 - y1 * y1) - A),
  3926. pi * y1
  3927. ];
  3928. }
  3929. vanDerGrinten3Raw.invert = function(x, y) {
  3930. if (!y) return [x, 0];
  3931. var y1 = y / pi,
  3932. A = (pi * pi * (1 - y1 * y1) - x * x) / (2 * pi * x);
  3933. return [
  3934. x ? pi * (sign(x) * sqrt(A * A + 1) - A) : 0,
  3935. halfPi * sin(2 * atan(y1))
  3936. ];
  3937. };
  3938. function vanDerGrinten3() {
  3939. return d3Geo.geoProjection(vanDerGrinten3Raw)
  3940. .scale(79.4183);
  3941. }
  3942. function vanDerGrinten4Raw(lambda, phi) {
  3943. if (!phi) return [lambda, 0];
  3944. var phi0 = abs(phi);
  3945. if (!lambda || phi0 === halfPi) return [0, phi];
  3946. var B = phi0 / halfPi,
  3947. B2 = B * B,
  3948. C = (8 * B - B2 * (B2 + 2) - 5) / (2 * B2 * (B - 1)),
  3949. C2 = C * C,
  3950. BC = B * C,
  3951. B_C2 = B2 + C2 + 2 * BC,
  3952. B_3C = B + 3 * C,
  3953. lambda0 = lambda / halfPi,
  3954. lambda1 = lambda0 + 1 / lambda0,
  3955. D = sign(abs(lambda) - halfPi) * sqrt(lambda1 * lambda1 - 4),
  3956. D2 = D * D,
  3957. F = B_C2 * (B2 + C2 * D2 - 1) + (1 - B2) * (B2 * (B_3C * B_3C + 4 * C2) + 12 * BC * C2 + 4 * C2 * C2),
  3958. x1 = (D * (B_C2 + C2 - 1) + 2 * sqrt(F)) / (4 * B_C2 + D2);
  3959. return [
  3960. sign(lambda) * halfPi * x1,
  3961. sign(phi) * halfPi * sqrt(1 + D * abs(x1) - x1 * x1)
  3962. ];
  3963. }
  3964. vanDerGrinten4Raw.invert = function(x, y) {
  3965. var delta;
  3966. if (!x || !y) return [x, y];
  3967. var sy = sign(y);
  3968. y = abs(y) / pi;
  3969. var x1 = sign(x) * x / halfPi,
  3970. D = (x1 * x1 - 1 + 4 * y * y) / abs(x1),
  3971. D2 = D * D,
  3972. B = y * (2 - (y > 0.5 ? min(y, abs(x)) : 0)),
  3973. r = x * x + y * y,
  3974. i = 50;
  3975. do {
  3976. var B2 = B * B,
  3977. C = (8 * B - B2 * (B2 + 2) - 5) / (2 * B2 * (B - 1)),
  3978. C_ = (3 * B - B2 * B - 10) / (2 * B2 * B),
  3979. C2 = C * C,
  3980. BC = B * C,
  3981. B_C = B + C,
  3982. B_C2 = B_C * B_C,
  3983. B_3C = B + 3 * C,
  3984. F = B_C2 * (B2 + C2 * D2 - 1) + (1 - B2) * (B2 * (B_3C * B_3C + 4 * C2) + C2 * (12 * BC + 4 * C2)),
  3985. F_ = -2 * B_C * (4 * BC * C2 + (1 - 4 * B2 + 3 * B2 * B2) * (1 + C_) + C2 * (-6 + 14 * B2 - D2 + (-8 + 8 * B2 - 2 * D2) * C_) + BC * (-8 + 12 * B2 + (-10 + 10 * B2 - D2) * C_)),
  3986. sqrtF = sqrt(F),
  3987. f = D * (B_C2 + C2 - 1) + 2 * sqrtF - x1 * (4 * B_C2 + D2),
  3988. f_ = D * (2 * C * C_ + 2 * B_C * (1 + C_)) + F_ / sqrtF - 8 * B_C * (D * (-1 + C2 + B_C2) + 2 * sqrtF) * (1 + C_) / (D2 + 4 * B_C2);
  3989. B -= delta = f / f_;
  3990. } while (delta * r * r > epsilon$1 && --i > 0);
  3991. return [
  3992. sign(x) * (sqrt(D * D + 4) + D) * pi / 4,
  3993. sy * halfPi * B
  3994. ];
  3995. };
  3996. function vanDerGrinten4() {
  3997. return d3Geo.geoProjection(vanDerGrinten4Raw)
  3998. .scale(127.16);
  3999. }
  4000. function wagnerFormula(cx, cy, m1, m2, n) {
  4001. function forward(lambda, phi) {
  4002. var s = m1 * sin(m2 * phi),
  4003. c0 = sqrt(1 - s * s),
  4004. c1 = sqrt(2 / (1 + c0 * cos(lambda *= n)));
  4005. return [
  4006. cx * c0 * c1 * sin(lambda),
  4007. cy * s * c1
  4008. ];
  4009. }
  4010. forward.invert = function(x, y) {
  4011. var t1 = x / cx,
  4012. t2 = y / cy,
  4013. p = sqrt(t1 * t1 + t2 * t2),
  4014. c = 2 * asin(p / 2);
  4015. return [
  4016. atan2(x * tan(c), cx * p) / n,
  4017. p && asin(y * sin(c) / (cy * m1 * p)) / m2
  4018. ];
  4019. };
  4020. return forward;
  4021. }
  4022. function wagnerRaw(poleline, parallels, inflation, ratio) {
  4023. // 60 is always used as reference parallel
  4024. var phi1 = pi / 3;
  4025. // sanitizing the input values
  4026. // poleline and parallels may approximate but never equal 0
  4027. poleline = max(poleline, epsilon$1);
  4028. parallels = max(parallels, epsilon$1);
  4029. // poleline must be <= 90; parallels may approximate but never equal 180
  4030. poleline = min(poleline, halfPi);
  4031. parallels = min(parallels, pi - epsilon$1);
  4032. // 0 <= inflation <= 99.999
  4033. inflation = max(inflation, 0);
  4034. inflation = min(inflation, 100 - epsilon$1);
  4035. // ratio > 0.
  4036. // sensible values, i.e. something that renders a map which still can be
  4037. // recognized as world map, are e.g. 20 <= ratio <= 1000.
  4038. ratio = max(ratio, epsilon$1);
  4039. // convert values from boehm notation
  4040. // areal inflation e.g. from 0 to 1 or 20 to 1.2:
  4041. var vinflation = inflation/100 + 1;
  4042. // axial ratio e.g. from 200 to 2:
  4043. var vratio = ratio / 100;
  4044. // the other ones are a bit more complicated...
  4045. var m2 = acos(vinflation * cos(phi1)) / phi1,
  4046. m1 = sin(poleline) / sin(m2 * halfPi),
  4047. n = parallels / pi,
  4048. k = sqrt(vratio * sin(poleline / 2) / sin(parallels / 2)),
  4049. cx = k / sqrt(n * m1 * m2),
  4050. cy = 1 / (k * sqrt(n * m1 * m2));
  4051. return wagnerFormula(cx, cy, m1, m2, n);
  4052. }
  4053. function wagner() {
  4054. // default values generate wagner8
  4055. var poleline = 65 * radians,
  4056. parallels = 60 * radians,
  4057. inflation = 20,
  4058. ratio = 200,
  4059. mutate = d3Geo.geoProjectionMutator(wagnerRaw),
  4060. projection = mutate(poleline, parallels, inflation, ratio);
  4061. projection.poleline = function(_) {
  4062. return arguments.length ? mutate(poleline = +_ * radians, parallels, inflation, ratio) : poleline * degrees;
  4063. };
  4064. projection.parallels = function(_) {
  4065. return arguments.length ? mutate(poleline, parallels = +_ * radians, inflation, ratio) : parallels * degrees;
  4066. };
  4067. projection.inflation = function(_) {
  4068. return arguments.length ? mutate(poleline, parallels, inflation = +_, ratio) : inflation;
  4069. };
  4070. projection.ratio = function(_) {
  4071. return arguments.length ? mutate(poleline, parallels, inflation, ratio = +_) : ratio;
  4072. };
  4073. return projection
  4074. .scale(163.775);
  4075. }
  4076. function wagner7() {
  4077. return wagner()
  4078. .poleline(65)
  4079. .parallels(60)
  4080. .inflation(0)
  4081. .ratio(200)
  4082. .scale(172.633);
  4083. }
  4084. var A = 4 * pi + 3 * sqrt(3),
  4085. B = 2 * sqrt(2 * pi * sqrt(3) / A);
  4086. var wagner4Raw = mollweideBromleyRaw(B * sqrt(3) / pi, B, A / 6);
  4087. function wagner4() {
  4088. return d3Geo.geoProjection(wagner4Raw)
  4089. .scale(176.84);
  4090. }
  4091. function wagner6Raw(lambda, phi) {
  4092. return [lambda * sqrt(1 - 3 * phi * phi / (pi * pi)), phi];
  4093. }
  4094. wagner6Raw.invert = function(x, y) {
  4095. return [x / sqrt(1 - 3 * y * y / (pi * pi)), y];
  4096. };
  4097. function wagner6() {
  4098. return d3Geo.geoProjection(wagner6Raw)
  4099. .scale(152.63);
  4100. }
  4101. function wiechelRaw(lambda, phi) {
  4102. var cosPhi = cos(phi),
  4103. sinPhi = cos(lambda) * cosPhi,
  4104. sin1_Phi = 1 - sinPhi,
  4105. cosLambda = cos(lambda = atan2(sin(lambda) * cosPhi, -sin(phi))),
  4106. sinLambda = sin(lambda);
  4107. cosPhi = sqrt(1 - sinPhi * sinPhi);
  4108. return [
  4109. sinLambda * cosPhi - cosLambda * sin1_Phi,
  4110. -cosLambda * cosPhi - sinLambda * sin1_Phi
  4111. ];
  4112. }
  4113. wiechelRaw.invert = function(x, y) {
  4114. var w = (x * x + y * y) / -2,
  4115. k = sqrt(-w * (2 + w)),
  4116. b = y * w + x * k,
  4117. a = x * w - y * k,
  4118. D = sqrt(a * a + b * b);
  4119. return [
  4120. atan2(k * b, D * (1 + w)),
  4121. D ? -asin(k * a / D) : 0
  4122. ];
  4123. };
  4124. function wiechel() {
  4125. return d3Geo.geoProjection(wiechelRaw)
  4126. .rotate([0, -90, 45])
  4127. .scale(124.75)
  4128. .clipAngle(180 - 1e-3);
  4129. }
  4130. function winkel3Raw(lambda, phi) {
  4131. var coordinates = aitoffRaw(lambda, phi);
  4132. return [
  4133. (coordinates[0] + lambda / halfPi) / 2,
  4134. (coordinates[1] + phi) / 2
  4135. ];
  4136. }
  4137. winkel3Raw.invert = function(x, y) {
  4138. var lambda = x, phi = y, i = 25;
  4139. do {
  4140. var cosphi = cos(phi),
  4141. sinphi = sin(phi),
  4142. sin_2phi = sin(2 * phi),
  4143. sin2phi = sinphi * sinphi,
  4144. cos2phi = cosphi * cosphi,
  4145. sinlambda = sin(lambda),
  4146. coslambda_2 = cos(lambda / 2),
  4147. sinlambda_2 = sin(lambda / 2),
  4148. sin2lambda_2 = sinlambda_2 * sinlambda_2,
  4149. C = 1 - cos2phi * coslambda_2 * coslambda_2,
  4150. E = C ? acos(cosphi * coslambda_2) * sqrt(F = 1 / C) : F = 0,
  4151. F,
  4152. fx = 0.5 * (2 * E * cosphi * sinlambda_2 + lambda / halfPi) - x,
  4153. fy = 0.5 * (E * sinphi + phi) - y,
  4154. dxdlambda = 0.5 * F * (cos2phi * sin2lambda_2 + E * cosphi * coslambda_2 * sin2phi) + 0.5 / halfPi,
  4155. dxdphi = F * (sinlambda * sin_2phi / 4 - E * sinphi * sinlambda_2),
  4156. dydlambda = 0.125 * F * (sin_2phi * sinlambda_2 - E * sinphi * cos2phi * sinlambda),
  4157. dydphi = 0.5 * F * (sin2phi * coslambda_2 + E * sin2lambda_2 * cosphi) + 0.5,
  4158. denominator = dxdphi * dydlambda - dydphi * dxdlambda,
  4159. dlambda = (fy * dxdphi - fx * dydphi) / denominator,
  4160. dphi = (fx * dydlambda - fy * dxdlambda) / denominator;
  4161. lambda -= dlambda, phi -= dphi;
  4162. } while ((abs(dlambda) > epsilon$1 || abs(dphi) > epsilon$1) && --i > 0);
  4163. return [lambda, phi];
  4164. };
  4165. function winkel3() {
  4166. return d3Geo.geoProjection(winkel3Raw)
  4167. .scale(158.837);
  4168. }
  4169. exports.geoAiry = airy;
  4170. exports.geoAiryRaw = airyRaw;
  4171. exports.geoAitoff = aitoff;
  4172. exports.geoAitoffRaw = aitoffRaw;
  4173. exports.geoArmadillo = armadillo;
  4174. exports.geoArmadilloRaw = armadilloRaw;
  4175. exports.geoAugust = august;
  4176. exports.geoAugustRaw = augustRaw;
  4177. exports.geoBaker = baker;
  4178. exports.geoBakerRaw = bakerRaw;
  4179. exports.geoBerghaus = berghaus;
  4180. exports.geoBerghausRaw = berghausRaw;
  4181. exports.geoBertin1953 = bertin;
  4182. exports.geoBertin1953Raw = bertin1953Raw;
  4183. exports.geoBoggs = boggs$1;
  4184. exports.geoBoggsRaw = boggsRaw;
  4185. exports.geoBonne = bonne;
  4186. exports.geoBonneRaw = bonneRaw;
  4187. exports.geoBottomley = bottomley;
  4188. exports.geoBottomleyRaw = bottomleyRaw;
  4189. exports.geoBromley = bromley;
  4190. exports.geoBromleyRaw = bromleyRaw;
  4191. exports.geoChamberlin = chamberlin;
  4192. exports.geoChamberlinAfrica = chamberlinAfrica;
  4193. exports.geoChamberlinRaw = chamberlinRaw;
  4194. exports.geoCollignon = collignon$1;
  4195. exports.geoCollignonRaw = collignonRaw;
  4196. exports.geoCraig = craig;
  4197. exports.geoCraigRaw = craigRaw;
  4198. exports.geoCraster = craster;
  4199. exports.geoCrasterRaw = crasterRaw;
  4200. exports.geoCylindricalEqualArea = cylindricalEqualArea;
  4201. exports.geoCylindricalEqualAreaRaw = cylindricalEqualAreaRaw;
  4202. exports.geoCylindricalStereographic = cylindricalStereographic;
  4203. exports.geoCylindricalStereographicRaw = cylindricalStereographicRaw;
  4204. exports.geoEckert1 = eckert1;
  4205. exports.geoEckert1Raw = eckert1Raw;
  4206. exports.geoEckert2 = eckert2;
  4207. exports.geoEckert2Raw = eckert2Raw;
  4208. exports.geoEckert3 = eckert3;
  4209. exports.geoEckert3Raw = eckert3Raw;
  4210. exports.geoEckert4 = eckert4;
  4211. exports.geoEckert4Raw = eckert4Raw;
  4212. exports.geoEckert5 = eckert5;
  4213. exports.geoEckert5Raw = eckert5Raw;
  4214. exports.geoEckert6 = eckert6;
  4215. exports.geoEckert6Raw = eckert6Raw;
  4216. exports.geoEisenlohr = eisenlohr;
  4217. exports.geoEisenlohrRaw = eisenlohrRaw;
  4218. exports.geoFahey = fahey;
  4219. exports.geoFaheyRaw = faheyRaw;
  4220. exports.geoFoucaut = foucaut;
  4221. exports.geoFoucautRaw = foucautRaw;
  4222. exports.geoFoucautSinusoidal = foucautSinusoidal;
  4223. exports.geoFoucautSinusoidalRaw = foucautSinusoidalRaw;
  4224. exports.geoGilbert = gilbert;
  4225. exports.geoGingery = gingery;
  4226. exports.geoGingeryRaw = gingeryRaw;
  4227. exports.geoGinzburg4 = ginzburg4;
  4228. exports.geoGinzburg4Raw = ginzburg4Raw;
  4229. exports.geoGinzburg5 = ginzburg5;
  4230. exports.geoGinzburg5Raw = ginzburg5Raw;
  4231. exports.geoGinzburg6 = ginzburg6;
  4232. exports.geoGinzburg6Raw = ginzburg6Raw;
  4233. exports.geoGinzburg8 = ginzburg8;
  4234. exports.geoGinzburg8Raw = ginzburg8Raw;
  4235. exports.geoGinzburg9 = ginzburg9;
  4236. exports.geoGinzburg9Raw = ginzburg9Raw;
  4237. exports.geoGringorten = gringorten$1;
  4238. exports.geoGringortenQuincuncial = gringorten;
  4239. exports.geoGringortenRaw = gringortenRaw;
  4240. exports.geoGuyou = guyou;
  4241. exports.geoGuyouRaw = guyouRaw;
  4242. exports.geoHammer = hammer;
  4243. exports.geoHammerRaw = hammerRaw;
  4244. exports.geoHammerRetroazimuthal = hammerRetroazimuthal;
  4245. exports.geoHammerRetroazimuthalRaw = hammerRetroazimuthalRaw;
  4246. exports.geoHealpix = healpix;
  4247. exports.geoHealpixRaw = healpixRaw;
  4248. exports.geoHill = hill;
  4249. exports.geoHillRaw = hillRaw;
  4250. exports.geoHomolosine = homolosine$1;
  4251. exports.geoHomolosineRaw = homolosineRaw;
  4252. exports.geoHufnagel = hufnagel;
  4253. exports.geoHufnagelRaw = hufnagelRaw;
  4254. exports.geoHyperelliptical = hyperelliptical;
  4255. exports.geoHyperellipticalRaw = hyperellipticalRaw;
  4256. exports.geoInterrupt = interrupt;
  4257. exports.geoInterruptedBoggs = boggs;
  4258. exports.geoInterruptedHomolosine = homolosine;
  4259. exports.geoInterruptedMollweide = mollweide;
  4260. exports.geoInterruptedMollweideHemispheres = mollweideHemispheres;
  4261. exports.geoInterruptedQuarticAuthalic = quarticAuthalic;
  4262. exports.geoInterruptedSinuMollweide = sinuMollweide;
  4263. exports.geoInterruptedSinusoidal = sinusoidal;
  4264. exports.geoKavrayskiy7 = kavrayskiy7;
  4265. exports.geoKavrayskiy7Raw = kavrayskiy7Raw;
  4266. exports.geoLagrange = lagrange;
  4267. exports.geoLagrangeRaw = lagrangeRaw;
  4268. exports.geoLarrivee = larrivee;
  4269. exports.geoLarriveeRaw = larriveeRaw;
  4270. exports.geoLaskowski = laskowski;
  4271. exports.geoLaskowskiRaw = laskowskiRaw;
  4272. exports.geoLittrow = littrow;
  4273. exports.geoLittrowRaw = littrowRaw;
  4274. exports.geoLoximuthal = loximuthal;
  4275. exports.geoLoximuthalRaw = loximuthalRaw;
  4276. exports.geoMiller = miller$1;
  4277. exports.geoMillerRaw = millerRaw;
  4278. exports.geoModifiedStereographic = modifiedStereographic;
  4279. exports.geoModifiedStereographicAlaska = modifiedStereographicAlaska;
  4280. exports.geoModifiedStereographicGs48 = modifiedStereographicGs48;
  4281. exports.geoModifiedStereographicGs50 = modifiedStereographicGs50;
  4282. exports.geoModifiedStereographicLee = modifiedStereographicLee;
  4283. exports.geoModifiedStereographicMiller = modifiedStereographicMiller;
  4284. exports.geoModifiedStereographicRaw = modifiedStereographicRaw;
  4285. exports.geoMollweide = mollweide$1;
  4286. exports.geoMollweideRaw = mollweideRaw;
  4287. exports.geoMtFlatPolarParabolic = mtFlatPolarParabolic;
  4288. exports.geoMtFlatPolarParabolicRaw = mtFlatPolarParabolicRaw;
  4289. exports.geoMtFlatPolarQuartic = mtFlatPolarQuartic;
  4290. exports.geoMtFlatPolarQuarticRaw = mtFlatPolarQuarticRaw;
  4291. exports.geoMtFlatPolarSinusoidal = mtFlatPolarSinusoidal;
  4292. exports.geoMtFlatPolarSinusoidalRaw = mtFlatPolarSinusoidalRaw;
  4293. exports.geoNaturalEarth2 = naturalEarth2;
  4294. exports.geoNaturalEarth2Raw = naturalEarth2Raw;
  4295. exports.geoNellHammer = nellHammer;
  4296. exports.geoNellHammerRaw = nellHammerRaw;
  4297. exports.geoNicolosi = nicolosi;
  4298. exports.geoNicolosiRaw = nicolosiRaw;
  4299. exports.geoPatterson = patterson;
  4300. exports.geoPattersonRaw = pattersonRaw;
  4301. exports.geoPeirceQuincuncial = peirce;
  4302. exports.geoPolyconic = polyconic;
  4303. exports.geoPolyconicRaw = polyconicRaw;
  4304. exports.geoPolyhedral = polyhedral;
  4305. exports.geoPolyhedralButterfly = butterfly;
  4306. exports.geoPolyhedralCollignon = collignon;
  4307. exports.geoPolyhedralWaterman = waterman;
  4308. exports.geoProject = index;
  4309. exports.geoQuantize = quantize$1;
  4310. exports.geoQuincuncial = quincuncial;
  4311. exports.geoRectangularPolyconic = rectangularPolyconic;
  4312. exports.geoRectangularPolyconicRaw = rectangularPolyconicRaw;
  4313. exports.geoRobinson = robinson;
  4314. exports.geoRobinsonRaw = robinsonRaw;
  4315. exports.geoSatellite = satellite;
  4316. exports.geoSatelliteRaw = satelliteRaw;
  4317. exports.geoSinuMollweide = sinuMollweide$1;
  4318. exports.geoSinuMollweideRaw = sinuMollweideRaw;
  4319. exports.geoSinusoidal = sinusoidal$1;
  4320. exports.geoSinusoidalRaw = sinusoidalRaw;
  4321. exports.geoStitch = stitch;
  4322. exports.geoTimes = times;
  4323. exports.geoTimesRaw = timesRaw;
  4324. exports.geoTwoPointAzimuthal = twoPointAzimuthal;
  4325. exports.geoTwoPointAzimuthalRaw = twoPointAzimuthalRaw;
  4326. exports.geoTwoPointAzimuthalUsa = twoPointAzimuthalUsa;
  4327. exports.geoTwoPointEquidistant = twoPointEquidistant;
  4328. exports.geoTwoPointEquidistantRaw = twoPointEquidistantRaw;
  4329. exports.geoTwoPointEquidistantUsa = twoPointEquidistantUsa;
  4330. exports.geoVanDerGrinten = vanDerGrinten;
  4331. exports.geoVanDerGrinten2 = vanDerGrinten2;
  4332. exports.geoVanDerGrinten2Raw = vanDerGrinten2Raw;
  4333. exports.geoVanDerGrinten3 = vanDerGrinten3;
  4334. exports.geoVanDerGrinten3Raw = vanDerGrinten3Raw;
  4335. exports.geoVanDerGrinten4 = vanDerGrinten4;
  4336. exports.geoVanDerGrinten4Raw = vanDerGrinten4Raw;
  4337. exports.geoVanDerGrintenRaw = vanDerGrintenRaw;
  4338. exports.geoWagner = wagner;
  4339. exports.geoWagner4 = wagner4;
  4340. exports.geoWagner4Raw = wagner4Raw;
  4341. exports.geoWagner6 = wagner6;
  4342. exports.geoWagner6Raw = wagner6Raw;
  4343. exports.geoWagner7 = wagner7;
  4344. exports.geoWagnerRaw = wagnerRaw;
  4345. exports.geoWiechel = wiechel;
  4346. exports.geoWiechelRaw = wiechelRaw;
  4347. exports.geoWinkel3 = winkel3;
  4348. exports.geoWinkel3Raw = winkel3Raw;
  4349. Object.defineProperty(exports, '__esModule', { value: true });
  4350. })));