mapshaper 0.7.46 → 0.7.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/mapshaper.js +1969 -202
  2. package/package.json +1 -1
  3. package/www/mapshaper.js +1969 -202
package/mapshaper.js CHANGED
@@ -2053,12 +2053,12 @@
2053
2053
  // TODO: remove this constant, use actual data from dataset CRS,
2054
2054
  // also consider using ellipsoidal formulas where greater accuracy might be important.
2055
2055
  var R$3 = WGS84.SEMIMAJOR_AXIS;
2056
- var D2R$7 = Math.PI / 180;
2057
- var R2D$6 = 180 / Math.PI;
2056
+ var D2R$8 = Math.PI / 180;
2057
+ var R2D$7 = 180 / Math.PI;
2058
2058
 
2059
2059
  // Equirectangular projection
2060
2060
  function degreesToMeters(deg) {
2061
- return deg * D2R$7 * R$3;
2061
+ return deg * D2R$8 * R$3;
2062
2062
  }
2063
2063
 
2064
2064
  function distance3D(ax, ay, az, bx, by, bz) {
@@ -2205,16 +2205,16 @@
2205
2205
 
2206
2206
  function xyzToLngLat(x, y, z, p) {
2207
2207
  var d = distance3D(0, 0, 0, x, y, z); // normalize
2208
- var lat = Math.asin(z / d) / D2R$7;
2209
- var lng = Math.atan2(y / d, x / d) / D2R$7;
2208
+ var lat = Math.asin(z / d) / D2R$8;
2209
+ var lng = Math.atan2(y / d, x / d) / D2R$8;
2210
2210
  p[0] = lng;
2211
2211
  p[1] = lat;
2212
2212
  }
2213
2213
 
2214
2214
  function lngLatToXYZ(lng, lat, p) {
2215
2215
  var cosLat;
2216
- lng *= D2R$7;
2217
- lat *= D2R$7;
2216
+ lng *= D2R$8;
2217
+ lat *= D2R$8;
2218
2218
  cosLat = Math.cos(lat);
2219
2219
  p[0] = Math.cos(lng) * cosLat * R$3;
2220
2220
  p[1] = Math.sin(lng) * cosLat * R$3;
@@ -2334,9 +2334,9 @@
2334
2334
 
2335
2335
  var Geom = /*#__PURE__*/Object.freeze({
2336
2336
  __proto__: null,
2337
- D2R: D2R$7,
2337
+ D2R: D2R$8,
2338
2338
  R: R$3,
2339
- R2D: R2D$6,
2339
+ R2D: R2D$7,
2340
2340
  bearing: bearing,
2341
2341
  bearing2D: bearing2D,
2342
2342
  containsBounds: containsBounds,
@@ -6264,9 +6264,9 @@
6264
6264
  * ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
6265
6265
  */
6266
6266
 
6267
- var D2R$6 = Math.PI / 180;
6268
- var R2D$5 = 180 / Math.PI;
6269
- var EPS$2 = 1e-12;
6267
+ var D2R$7 = Math.PI / 180;
6268
+ var R2D$6 = 180 / Math.PI;
6269
+ var EPS$3 = 1e-12;
6270
6270
 
6271
6271
  // Build a forward-only spherical polyhedral projection.
6272
6272
  //
@@ -6304,10 +6304,10 @@
6304
6304
  throw new Error('Invalid polyhedral face tree');
6305
6305
  }
6306
6306
  var childEdge = shared.map(function(p) {
6307
- return face.project(p[0] * D2R$6, p[1] * D2R$6);
6307
+ return face.project(p[0] * D2R$7, p[1] * D2R$7);
6308
6308
  });
6309
6309
  var parentEdge = shared.map(function(p) {
6310
- return parent.project(p[0] * D2R$6, p[1] * D2R$6);
6310
+ return parent.project(p[0] * D2R$7, p[1] * D2R$7);
6311
6311
  });
6312
6312
  face.transform = multiplyMatrices(
6313
6313
  parent.transform,
@@ -6318,12 +6318,12 @@
6318
6318
 
6319
6319
  var rootEdge = findLongestEdge(faces[0].coords);
6320
6320
  var rootPlanarEdge = rootEdge.map(function(p) {
6321
- return faces[0].project(p[0] * D2R$6, p[1] * D2R$6);
6321
+ return faces[0].project(p[0] * D2R$7, p[1] * D2R$7);
6322
6322
  });
6323
6323
  var sphericalEdgeLength = angularDistance(rootEdge[0], rootEdge[1]);
6324
6324
  var planarEdgeLength = distance2D(rootPlanarEdge[0], rootPlanarEdge[1]);
6325
6325
  var scale = sphericalEdgeLength / planarEdgeLength;
6326
- var planarAngle = (config.angle || 0) * D2R$6;
6326
+ var planarAngle = (config.angle || 0) * D2R$7;
6327
6327
  var edgeIndex = indexEdges(faces, attachedPairs);
6328
6328
  var outline = buildOutline(faces, attachedPairs).map(function(ring) {
6329
6329
  return ring.map(transformOutputPoint);
@@ -6344,6 +6344,7 @@
6344
6344
  faces: faces,
6345
6345
  outline: outline,
6346
6346
  forward: forward,
6347
+ forwardFace: forwardFace,
6347
6348
  findFace: findFace,
6348
6349
  findTransitionRegion: findTransitionRegion,
6349
6350
  getTopology: getTopology
@@ -6353,14 +6354,30 @@
6353
6354
  var rotated = rotateRadians(
6354
6355
  lam,
6355
6356
  phi,
6356
- config.rotation[0] * D2R$6,
6357
- config.rotation[1] * D2R$6,
6358
- config.rotation[2] * D2R$6
6357
+ config.rotation[0] * D2R$7,
6358
+ config.rotation[1] * D2R$7,
6359
+ config.rotation[2] * D2R$7
6359
6360
  );
6360
6361
  var face = findFaceRotated(rotated[0], rotated[1]);
6361
6362
  if (!face) return null;
6362
- var p = face.project(rotated[0], rotated[1]);
6363
- p = applyMatrix(face.transform, p);
6363
+ return projectFacePoint(face, rotated[0], rotated[1]);
6364
+ }
6365
+
6366
+ function forwardFace(lam, phi, faceId) {
6367
+ var rotated = rotateRadians(
6368
+ lam,
6369
+ phi,
6370
+ config.rotation[0] * D2R$7,
6371
+ config.rotation[1] * D2R$7,
6372
+ config.rotation[2] * D2R$7
6373
+ );
6374
+ var face = faces[faceId];
6375
+ return face ? projectFacePoint(face, rotated[0], rotated[1]) : null;
6376
+ }
6377
+
6378
+ function projectFacePoint(face, lam, phi) {
6379
+ var p = face.project(lam, phi);
6380
+ p = applyMatrix$1(face.transform, p);
6364
6381
  p = transformOutputPoint(p);
6365
6382
  p[0] -= centerX;
6366
6383
  p[1] -= centerY;
@@ -6371,9 +6388,9 @@
6371
6388
  var rotated = rotateRadians(
6372
6389
  lam,
6373
6390
  phi,
6374
- config.rotation[0] * D2R$6,
6375
- config.rotation[1] * D2R$6,
6376
- config.rotation[2] * D2R$6
6391
+ config.rotation[0] * D2R$7,
6392
+ config.rotation[1] * D2R$7,
6393
+ config.rotation[2] * D2R$7
6377
6394
  );
6378
6395
  var face = findFaceRotated(rotated[0], rotated[1]);
6379
6396
  return face ? face.id : -1;
@@ -6383,9 +6400,9 @@
6383
6400
  var rotated = rotateRadians(
6384
6401
  lam,
6385
6402
  phi,
6386
- config.rotation[0] * D2R$6,
6387
- config.rotation[1] * D2R$6,
6388
- config.rotation[2] * D2R$6
6403
+ config.rotation[0] * D2R$7,
6404
+ config.rotation[1] * D2R$7,
6405
+ config.rotation[2] * D2R$7
6389
6406
  );
6390
6407
  var face = findFaceRotated(rotated[0], rotated[1]);
6391
6408
  var region;
@@ -6427,14 +6444,14 @@
6427
6444
  var seams = edgeIndex.map(function(edge) {
6428
6445
  var endpoints = edge.points.map(function(p) {
6429
6446
  var q = rotateRadians(
6430
- p[0] * D2R$6,
6431
- p[1] * D2R$6,
6432
- config.rotation[0] * D2R$6,
6433
- config.rotation[1] * D2R$6,
6434
- config.rotation[2] * D2R$6,
6447
+ p[0] * D2R$7,
6448
+ p[1] * D2R$7,
6449
+ config.rotation[0] * D2R$7,
6450
+ config.rotation[1] * D2R$7,
6451
+ config.rotation[2] * D2R$7,
6435
6452
  true
6436
6453
  );
6437
- return [normalizeLongitude$2(q[0] * R2D$5 + lon0), q[1] * R2D$5];
6454
+ return [normalizeLongitude$3(q[0] * R2D$6 + lon0), q[1] * R2D$6];
6438
6455
  });
6439
6456
  var paths = splitPathAtAntimeridian$2(
6440
6457
  interpolateGreatCircle(endpoints[0], endpoints[1], 0.05)
@@ -6457,16 +6474,23 @@
6457
6474
  });
6458
6475
  return {
6459
6476
  regions: faces.map(function(face) {
6460
- return {id: face.id};
6477
+ return {
6478
+ id: face.id,
6479
+ projected_boundary: getProjectedFaceBoundary(face)
6480
+ };
6461
6481
  }),
6462
6482
  seams: seams,
6463
6483
  findRegion: function(lon, lat) {
6464
- var lam = normalizeLongitude$2(lon - lon0) * D2R$6;
6465
- return findFace(lam, lat * D2R$6);
6484
+ var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
6485
+ return findFace(lam, lat * D2R$7);
6466
6486
  },
6467
6487
  findTransitionRegion: function(lon, lat) {
6468
- var lam = normalizeLongitude$2(lon - lon0) * D2R$6;
6469
- return findTransitionRegion(lam, lat * D2R$6);
6488
+ var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
6489
+ return findTransitionRegion(lam, lat * D2R$7);
6490
+ },
6491
+ projectRegion: function(lon, lat, regionId) {
6492
+ var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
6493
+ return forwardFace(lam, lat * D2R$7, regionId);
6470
6494
  },
6471
6495
  regionsAreAttached: function(a, b) {
6472
6496
  return regionPairs.get(pairKey(a, b)) === true;
@@ -6478,15 +6502,29 @@
6478
6502
  })
6479
6503
  };
6480
6504
  }
6505
+
6506
+ function getProjectedFaceBoundary(face) {
6507
+ var ring = [];
6508
+ for (var i = 0; i < face.coords.length; i++) {
6509
+ var a = face.coords[i];
6510
+ var b = face.coords[(i + 1) % face.coords.length];
6511
+ var edge = interpolateGreatCircle(a, b, 0.5);
6512
+ for (var j = 0; j < edge.length - 1; j++) {
6513
+ ring.push(projectFacePoint(face, edge[j][0] * D2R$7, edge[j][1] * D2R$7));
6514
+ }
6515
+ }
6516
+ ring.push(ring[0].concat());
6517
+ return ring;
6518
+ }
6481
6519
  }
6482
6520
 
6483
6521
  function rotateSphericalRadians(lam, phi, rotation, invert) {
6484
6522
  return rotateRadians(
6485
6523
  lam,
6486
6524
  phi,
6487
- (rotation[0] || 0) * D2R$6,
6488
- (rotation[1] || 0) * D2R$6,
6489
- (rotation[2] || 0) * D2R$6,
6525
+ (rotation[0] || 0) * D2R$7,
6526
+ (rotation[1] || 0) * D2R$7,
6527
+ (rotation[2] || 0) * D2R$7,
6490
6528
  invert
6491
6529
  );
6492
6530
  }
@@ -6523,7 +6561,7 @@
6523
6561
  function faceContainsVector(face, p) {
6524
6562
  for (var i = 0; i < face.edges.length; i++) {
6525
6563
  var edge = face.edges[i];
6526
- if (dot$2(edge.normal, p) * edge.sign < -EPS$2) return false;
6564
+ if (dot$2(edge.normal, p) * edge.sign < -EPS$3) return false;
6527
6565
  }
6528
6566
  return true;
6529
6567
  }
@@ -6559,8 +6597,8 @@
6559
6597
  var adjacent = findAdjacentFace(faces, face.id, a, b);
6560
6598
  if (adjacent >= 0 && attachedPairs.has(pairKey(face.id, adjacent))) continue;
6561
6599
  edges.push([
6562
- applyMatrix(face.transform, face.project(a[0] * D2R$6, a[1] * D2R$6)),
6563
- applyMatrix(face.transform, face.project(b[0] * D2R$6, b[1] * D2R$6))
6600
+ applyMatrix$1(face.transform, face.project(a[0] * D2R$7, a[1] * D2R$7)),
6601
+ applyMatrix$1(face.transform, face.project(b[0] * D2R$7, b[1] * D2R$7))
6564
6602
  ]);
6565
6603
  }
6566
6604
  });
@@ -6677,7 +6715,7 @@
6677
6715
  ];
6678
6716
  }
6679
6717
 
6680
- function applyMatrix(m, p) {
6718
+ function applyMatrix$1(m, p) {
6681
6719
  return [
6682
6720
  m[0] * p[0] + m[1] * p[1] + m[2],
6683
6721
  m[3] * p[0] + m[4] * p[1] + m[5]
@@ -6724,13 +6762,13 @@
6724
6762
  var av = degreesToVector$2(a[0], a[1]);
6725
6763
  var bv = degreesToVector$2(b[0], b[1]);
6726
6764
  var angle = Math.acos(clamp$3(dot$2(av, bv), -1, 1));
6727
- var n = Math.max(1, Math.ceil(angle * R2D$5 / interval));
6765
+ var n = Math.max(1, Math.ceil(angle * R2D$6 / interval));
6728
6766
  var sinAngle = Math.sin(angle);
6729
6767
  var points = [];
6730
6768
  for (var i = 0; i <= n; i++) {
6731
6769
  var t = i / n;
6732
6770
  var p;
6733
- if (sinAngle < EPS$2) {
6771
+ if (sinAngle < EPS$3) {
6734
6772
  p = av;
6735
6773
  } else {
6736
6774
  var ka = Math.sin((1 - t) * angle) / sinAngle;
@@ -6787,7 +6825,7 @@
6787
6825
  }
6788
6826
 
6789
6827
  function degreesToVector$2(lon, lat) {
6790
- return radiansToVector$1(lon * D2R$6, lat * D2R$6);
6828
+ return radiansToVector$1(lon * D2R$7, lat * D2R$7);
6791
6829
  }
6792
6830
 
6793
6831
  function radiansToVector$1(lam, phi) {
@@ -6797,8 +6835,8 @@
6797
6835
 
6798
6836
  function vectorToDegrees$2(p) {
6799
6837
  return [
6800
- Math.atan2(p[1], p[0]) * R2D$5,
6801
- Math.asin(clamp$3(p[2], -1, 1)) * R2D$5
6838
+ Math.atan2(p[1], p[0]) * R2D$6,
6839
+ Math.asin(clamp$3(p[2], -1, 1)) * R2D$6
6802
6840
  ];
6803
6841
  }
6804
6842
 
@@ -6826,7 +6864,7 @@
6826
6864
  }
6827
6865
 
6828
6866
  function sameSphericalPoint(a, b) {
6829
- return Math.abs(a[0] - b[0]) < EPS$2 && Math.abs(a[1] - b[1]) < EPS$2;
6867
+ return Math.abs(a[0] - b[0]) < EPS$3 && Math.abs(a[1] - b[1]) < EPS$3;
6830
6868
  }
6831
6869
 
6832
6870
  function pointsAlmostEqual(a, b) {
@@ -6853,7 +6891,7 @@
6853
6891
  return lam;
6854
6892
  }
6855
6893
 
6856
- function normalizeLongitude$2(lon) {
6894
+ function normalizeLongitude$3(lon) {
6857
6895
  while (lon > 180) lon -= 360;
6858
6896
  while (lon < -180) lon += 360;
6859
6897
  return lon;
@@ -6875,9 +6913,9 @@
6875
6913
  */
6876
6914
 
6877
6915
 
6878
- var D2R$5 = Math.PI / 180;
6879
- var R2D$4 = 180 / Math.PI;
6880
- var SQRT3$1 = Math.sqrt(3);
6916
+ var D2R$6 = Math.PI / 180;
6917
+ var R2D$5 = 180 / Math.PI;
6918
+ var SQRT3$2 = Math.sqrt(3);
6881
6919
  var GRAY_Z = Math.sqrt(5 + 2 * Math.sqrt(5)) / Math.sqrt(15);
6882
6920
  var GRAY_EL = Math.sqrt(8) / Math.sqrt(5 + Math.sqrt(5));
6883
6921
  var GRAY_DVE = Math.sqrt(3 + Math.sqrt(5)) / Math.sqrt(5 + Math.sqrt(5));
@@ -6889,7 +6927,7 @@
6889
6927
  6, 8, 10, 17, 21,
6890
6928
  16, 15, 19, 19
6891
6929
  ];
6892
- var engines$2 = {};
6930
+ var engines$3 = {};
6893
6931
 
6894
6932
  function registerDymaxionProjections(mproj) {
6895
6933
  // Some unit tests import source modules directly in an ESM context where
@@ -6908,9 +6946,9 @@
6908
6946
 
6909
6947
  function getDymaxionEngine(method) {
6910
6948
  method = method || 'fuller';
6911
- if (!engines$2[method]) {
6949
+ if (!engines$3[method]) {
6912
6950
  var data = createAiroceanFaces();
6913
- engines$2[method] = createPolyhedralProjection({
6951
+ engines$3[method] = createPolyhedralProjection({
6914
6952
  faces: data.faces,
6915
6953
  faceSites: data.sites,
6916
6954
  parents: PARENTS,
@@ -6921,7 +6959,7 @@
6921
6959
  createGrayFullerFaceProjector
6922
6960
  });
6923
6961
  }
6924
- return engines$2[method];
6962
+ return engines$3[method];
6925
6963
  }
6926
6964
 
6927
6965
  function initDymaxion(P, method) {
@@ -6937,12 +6975,12 @@
6937
6975
  xy.y = p[1];
6938
6976
  }
6939
6977
  };
6940
- P.__projection_topology = engine.getTopology(P.lam0 * R2D$4);
6978
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$5);
6941
6979
  P.__projected_outline = engine.outline;
6942
6980
  }
6943
6981
 
6944
6982
  function createAiroceanFaces() {
6945
- var theta = Math.atan(0.5) * R2D$4;
6983
+ var theta = Math.atan(0.5) * R2D$5;
6946
6984
  var vertices = [[0, 90], [0, -90]];
6947
6985
  var faces;
6948
6986
  var sites;
@@ -7039,10 +7077,10 @@
7039
7077
  var s = GRAY_Z / (cosPhi * Math.cos(lam));
7040
7078
  var x = cosPhi * Math.sin(lam) * s;
7041
7079
  var y = Math.sin(phi) * s;
7042
- var a1p = Math.atan2(2 * y / SQRT3$1 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7043
- var a2p = Math.atan2(x - y / SQRT3$1 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7044
- var a3p = Math.atan2(GRAY_EL / 3 - x - y / SQRT3$1 - GRAY_EL / 2, GRAY_DVE);
7045
- return [SQRT3$1 * (a2p - a3p), 2 * a1p - a2p - a3p];
7080
+ var a1p = Math.atan2(2 * y / SQRT3$2 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7081
+ var a2p = Math.atan2(x - y / SQRT3$2 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7082
+ var a3p = Math.atan2(GRAY_EL / 3 - x - y / SQRT3$2 - GRAY_EL / 2, GRAY_DVE);
7083
+ return [SQRT3$2 * (a2p - a3p), 2 * a1p - a2p - a3p];
7046
7084
  }
7047
7085
 
7048
7086
  function getSphericalCentroid(coords) {
@@ -7067,16 +7105,16 @@
7067
7105
  }
7068
7106
 
7069
7107
  function degreesToVector$1(p) {
7070
- var lam = p[0] * D2R$5;
7071
- var phi = p[1] * D2R$5;
7108
+ var lam = p[0] * D2R$6;
7109
+ var phi = p[1] * D2R$6;
7072
7110
  var cosPhi = Math.cos(phi);
7073
7111
  return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
7074
7112
  }
7075
7113
 
7076
7114
  function vectorToDegrees$1(p) {
7077
7115
  return [
7078
- Math.atan2(p[1], p[0]) * R2D$4,
7079
- Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$4
7116
+ Math.atan2(p[1], p[0]) * R2D$5,
7117
+ Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$5
7080
7118
  ];
7081
7119
  }
7082
7120
 
@@ -7124,8 +7162,8 @@
7124
7162
  * ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
7125
7163
  */
7126
7164
 
7127
- var D2R$4 = Math.PI / 180;
7128
- var R2D$3 = 180 / Math.PI;
7165
+ var D2R$5 = Math.PI / 180;
7166
+ var R2D$4 = 180 / Math.PI;
7129
7167
 
7130
7168
  function createCahillKeyesRaw(mg) {
7131
7169
  return createCahillKeyesTransform(mg, false);
@@ -7137,12 +7175,12 @@
7137
7175
 
7138
7176
  return function(lambda, phi) {
7139
7177
  if (faceOnly) {
7140
- var lon = lambda * R2D$3;
7178
+ var lon = lambda * R2D$4;
7141
7179
  var side = lon < 0 ? -1 : lon > 0 ? 1 : 0;
7142
- var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$3));
7180
+ var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$4));
7143
7181
  return [local[0], side * local[1]];
7144
7182
  }
7145
- var res = ll2mp(lambda * R2D$3, phi * R2D$3);
7183
+ var res = ll2mp(lambda * R2D$4, phi * R2D$4);
7146
7184
  var xy = mp2xy(res[0], res[1]);
7147
7185
  var p = [xy[0], res[2] * xy[1]];
7148
7186
  return mj2g(p, res[3]);
@@ -7160,7 +7198,7 @@
7160
7198
  CK.cos60 = 0.5;
7161
7199
  CK.pointM = [0, 0];
7162
7200
  CK.pointG = [CK.lengthMG, 0];
7163
- pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$4)];
7201
+ pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$5)];
7164
7202
  CK.pointA = [CK.lengthMA, 0];
7165
7203
  CK.pointB = lineIntersection(CK.pointM, 30, CK.pointA, 45);
7166
7204
  CK.lengthAG = distance(CK.pointA, CK.pointG);
@@ -7171,8 +7209,8 @@
7171
7209
  CK.pointD = interpolate(lengthMB, lengthMN, pointN, CK.pointM);
7172
7210
  CK.pointF = [CK.lengthMG, lengthNG - lengthMB];
7173
7211
  CK.pointE = [
7174
- pointN[0] - CK.lengthMA * Math.sin(30 * D2R$4),
7175
- pointN[1] - CK.lengthMA * Math.cos(30 * D2R$4)
7212
+ pointN[0] - CK.lengthMA * Math.sin(30 * D2R$5),
7213
+ pointN[1] - CK.lengthMA * Math.cos(30 * D2R$5)
7176
7214
  ];
7177
7215
  CK.lengthGF = distance(CK.pointG, CK.pointF);
7178
7216
  CK.lengthBD = distance(CK.pointB, CK.pointD);
@@ -7182,8 +7220,8 @@
7182
7220
  CK.lengthAP73 = CK.lengthMG - CK.lengthMA -
7183
7221
  CK.lengthParallel0to73At0 * 73;
7184
7222
  pointU = [
7185
- CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$4),
7186
- CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$4)
7223
+ CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$5),
7224
+ CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$5)
7187
7225
  ];
7188
7226
  CK.pointT = lineIntersection(pointU, -60, CK.pointB, 30);
7189
7227
 
@@ -7424,8 +7462,8 @@
7424
7462
 
7425
7463
  function radialPoint(origin, length, angle) {
7426
7464
  return [
7427
- origin[0] + length * Math.cos(angle * D2R$4),
7428
- origin[1] + length * Math.sin(angle * D2R$4)
7465
+ origin[0] + length * Math.cos(angle * D2R$5),
7466
+ origin[1] + length * Math.sin(angle * D2R$5)
7429
7467
  ];
7430
7468
  }
7431
7469
 
@@ -7442,8 +7480,8 @@
7442
7480
  -xy[0] * CK.sin60 - xy[1] * CK.cos60
7443
7481
  ];
7444
7482
  }
7445
- var cos = Math.cos(angle * D2R$4);
7446
- var sin = Math.sin(angle * D2R$4);
7483
+ var cos = Math.cos(angle * D2R$5);
7484
+ var sin = Math.sin(angle * D2R$5);
7447
7485
  return [xy[0] * cos - xy[1] * sin, xy[0] * sin + xy[1] * cos];
7448
7486
  }
7449
7487
  }
@@ -7464,8 +7502,8 @@
7464
7502
  }
7465
7503
 
7466
7504
  function lineIntersection(p1, slope1, p2, slope2) {
7467
- var m1 = Math.tan(slope1 * D2R$4);
7468
- var m2 = Math.tan(slope2 * D2R$4);
7505
+ var m1 = Math.tan(slope1 * D2R$5);
7506
+ var m2 = Math.tan(slope2 * D2R$5);
7469
7507
  var x = (m1 * p1[0] - m2 * p2[0] - p1[1] + p2[1]) / (m1 - m2);
7470
7508
  return [x, m1 * (x - p1[0]) + p1[1]];
7471
7509
  }
@@ -7493,8 +7531,8 @@
7493
7531
  return n > 0 ? Math.floor(n) : Math.ceil(n);
7494
7532
  }
7495
7533
 
7496
- var D2R$3 = Math.PI / 180;
7497
- var EPS$1 = 1e-12;
7534
+ var D2R$4 = Math.PI / 180;
7535
+ var EPS$2 = 1e-12;
7498
7536
 
7499
7537
  // Create a smooth facet projection from any radial azimuthal projection.
7500
7538
  // The azimuthal coordinates are warped back to the gnomonic polygon along
@@ -7504,7 +7542,7 @@
7504
7542
  var center = options.planarCenter || getSphericalCenter(coords);
7505
7543
  var gnomonic = createGnomonicProjector(center);
7506
7544
  var planar = coords.map(function(p) {
7507
- return gnomonic(p[0] * D2R$3, p[1] * D2R$3);
7545
+ return gnomonic(p[0] * D2R$4, p[1] * D2R$4);
7508
7546
  });
7509
7547
  var edges = createNormalizedEdges(planar);
7510
7548
  var radial = createRadialFunction(
@@ -7523,7 +7561,7 @@
7523
7561
  function project(lam, phi) {
7524
7562
  var p = gnomonic(lam, phi);
7525
7563
  var r = Math.hypot(p[0], p[1]);
7526
- if (r < EPS$1) return [0, 0];
7564
+ if (r < EPS$2) return [0, 0];
7527
7565
  var c = Math.atan(r);
7528
7566
  var azimuthalRadius = radial(c) * radialScale;
7529
7567
  var boundaryWeight = getBoundaryWeight(p, edges, boundaryStrength);
@@ -7613,8 +7651,8 @@
7613
7651
 
7614
7652
  function getSphericalCenter(coords) {
7615
7653
  var sum = coords.reduce(function(memo, p) {
7616
- var lam = p[0] * D2R$3;
7617
- var phi = p[1] * D2R$3;
7654
+ var lam = p[0] * D2R$4;
7655
+ var phi = p[1] * D2R$4;
7618
7656
  var cosPhi = Math.cos(phi);
7619
7657
  memo[0] += Math.cos(lam) * cosPhi;
7620
7658
  memo[1] += Math.sin(lam) * cosPhi;
@@ -7622,8 +7660,8 @@
7622
7660
  return memo;
7623
7661
  }, [0, 0, 0]);
7624
7662
  return [
7625
- Math.atan2(sum[1], sum[0]) / D2R$3,
7626
- Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$3
7663
+ Math.atan2(sum[1], sum[0]) / D2R$4,
7664
+ Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$4
7627
7665
  ];
7628
7666
  }
7629
7667
 
@@ -7638,8 +7676,8 @@
7638
7676
  */
7639
7677
 
7640
7678
 
7641
- var D2R$2 = Math.PI / 180;
7642
- var R2D$2 = 180 / Math.PI;
7679
+ var D2R$3 = Math.PI / 180;
7680
+ var R2D$3 = 180 / Math.PI;
7643
7681
  var RADIAL_BOUNDARY_STRENGTH = 1;
7644
7682
  var OCTAHEDRON = createOctahedron();
7645
7683
  var BUTTERFLY_PARENTS = [-1, 0, 0, 1, 0, 1, 4, 5];
@@ -7648,7 +7686,7 @@
7648
7686
  butterfly2: -20,
7649
7687
  cahill_keyes: -20
7650
7688
  };
7651
- var engines$1 = {};
7689
+ var engines$2 = {};
7652
7690
 
7653
7691
  function registerButterflyProjections(mproj) {
7654
7692
  if (!mproj) return;
@@ -7666,22 +7704,22 @@
7666
7704
 
7667
7705
  function getButterflyEngine(method) {
7668
7706
  var key = method == 'butterfly2' ? 'butterfly' : method;
7669
- if (!engines$1[key]) {
7707
+ if (!engines$2[key]) {
7670
7708
  if (key == 'cahill_keyes') {
7671
- engines$1[key] = createCahillKeyesEngine();
7709
+ engines$2[key] = createCahillKeyesEngine();
7672
7710
  } else if (key == 'butterfly') {
7673
- engines$1[key] = createButterflyEngine();
7711
+ engines$2[key] = createButterflyEngine();
7674
7712
  } else {
7675
7713
  throw new Error('Unknown butterfly projection: ' + method);
7676
7714
  }
7677
7715
  }
7678
- return engines$1[key];
7716
+ return engines$2[key];
7679
7717
  }
7680
7718
 
7681
7719
  function initButterfly(P, method) {
7682
7720
  var engine = getButterflyEngine(method);
7683
7721
  if (!P.params.lon_0) {
7684
- P.lam0 = DEFAULT_LON0[method] * D2R$2;
7722
+ P.lam0 = DEFAULT_LON0[method] * D2R$3;
7685
7723
  }
7686
7724
  P.es = 0;
7687
7725
  P.inv = null;
@@ -7694,7 +7732,7 @@
7694
7732
  xy.y = p[1];
7695
7733
  }
7696
7734
  };
7697
- P.__projection_topology = engine.getTopology(P.lam0 * R2D$2);
7735
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$3);
7698
7736
  if (engine.removeOutlineExtremeConnectors) {
7699
7737
  P.__remove_outline_extreme_connectors = true;
7700
7738
  }
@@ -7708,8 +7746,8 @@
7708
7746
  // Reuse the Cahill-Keyes polar incisions and 12-zone octant transform,
7709
7747
  // then unfold the faces with the butterfly attachment tree.
7710
7748
  var data = createTruncatedOctahedronFaces(
7711
- Math.cos(17 * D2R$2),
7712
- Math.sin(17 * D2R$2),
7749
+ Math.cos(17 * D2R$3),
7750
+ Math.sin(17 * D2R$3),
7713
7751
  BUTTERFLY_PARENTS
7714
7752
  );
7715
7753
  var faceRaw = createCahillKeyesFaceRaw(10000);
@@ -7722,7 +7760,7 @@
7722
7760
  findFace: createTruncatedFaceFinder(data.cornerNormals),
7723
7761
  faceProjector: function(face) {
7724
7762
  var baseId = face.id < 8 ? face.id : data.parents[face.id];
7725
- var center = faceCenters[baseId] * D2R$2;
7763
+ var center = faceCenters[baseId] * D2R$3;
7726
7764
  var raw = function(lam, phi) {
7727
7765
  return faceRaw(normalizeRadians$1(lam - center), phi);
7728
7766
  };
@@ -7737,7 +7775,7 @@
7737
7775
  // Remove the global placement and scale of a raw facet while preserving its
7738
7776
  // internal shape. The polyhedral engine then controls how facets unfold.
7739
7777
  var points = coords.map(function(p) {
7740
- return raw(p[0] * D2R$2, p[1] * D2R$2);
7778
+ return raw(p[0] * D2R$3, p[1] * D2R$3);
7741
7779
  });
7742
7780
  var edge = 0;
7743
7781
  var maxLengthSq = -1;
@@ -7826,8 +7864,8 @@
7826
7864
 
7827
7865
  function createCahillKeyesEngine() {
7828
7866
  var data = createTruncatedOctahedronFaces(
7829
- Math.cos(17 * D2R$2),
7830
- Math.sin(17 * D2R$2),
7867
+ Math.cos(17 * D2R$3),
7868
+ Math.sin(17 * D2R$3),
7831
7869
  [-1, 3, 0, 2, 0, 1, 4, 5]
7832
7870
  );
7833
7871
  var raw = createCahillKeyesRaw(10000);
@@ -7972,7 +8010,7 @@
7972
8010
  }
7973
8011
 
7974
8012
  function planarAngle(p, project) {
7975
- var q = project(p[0] * D2R$2, p[1] * D2R$2);
8013
+ var q = project(p[0] * D2R$3, p[1] * D2R$3);
7976
8014
  return Math.atan2(q[1], q[0]);
7977
8015
  }
7978
8016
 
@@ -8006,16 +8044,16 @@
8006
8044
  }
8007
8045
 
8008
8046
  function degreesToVector(p) {
8009
- var lam = p[0] * D2R$2;
8010
- var phi = p[1] * D2R$2;
8047
+ var lam = p[0] * D2R$3;
8048
+ var phi = p[1] * D2R$3;
8011
8049
  var cosPhi = Math.cos(phi);
8012
8050
  return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
8013
8051
  }
8014
8052
 
8015
8053
  function vectorToDegrees(p) {
8016
8054
  return [
8017
- Math.atan2(p[1], p[0]) * R2D$2,
8018
- Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$2
8055
+ Math.atan2(p[1], p[0]) * R2D$3,
8056
+ Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$3
8019
8057
  ];
8020
8058
  }
8021
8059
 
@@ -8068,21 +8106,21 @@
8068
8106
  * equations, not Imago's power-law approximation.
8069
8107
  */
8070
8108
 
8071
- var D2R$1 = Math.PI / 180;
8072
- var R2D$1 = 180 / Math.PI;
8109
+ var D2R$2 = Math.PI / 180;
8110
+ var R2D$2 = 180 / Math.PI;
8073
8111
  var HALF_PI = Math.PI / 2;
8074
- var SQRT2 = Math.sqrt(2);
8075
- var SQRT3 = Math.sqrt(3);
8076
- var ASIN_ONE_THIRD = Math.asin(1 / 3);
8112
+ var SQRT2$1 = Math.sqrt(2);
8113
+ var SQRT3$1 = Math.sqrt(3);
8114
+ var ASIN_ONE_THIRD$1 = Math.asin(1 / 3);
8077
8115
  var EDGE_SCALE = Math.acos(-1 / 3) / 2;
8078
- var XMIN = -2 * SQRT3;
8079
- var XMAX = 2 * SQRT3;
8116
+ var XMIN = -2 * SQRT3$1;
8117
+ var XMAX = 2 * SQRT3$1;
8080
8118
  var YMIN = -1.5;
8081
8119
  var YMAX = 1.5;
8082
- var BLOCK_HEIGHT = 2 * SQRT3;
8120
+ var BLOCK_HEIGHT = 2 * SQRT3$1;
8083
8121
  var LAYOUT_SHIFT = 1.16;
8084
- var EPS = 1e-12;
8085
- var engines = {};
8122
+ var EPS$1 = 1e-12;
8123
+ var engines$1 = {};
8086
8124
 
8087
8125
  // The four tetrahedron vertices published by Narukawa, in latitude-longitude
8088
8126
  // order. The extra precision preserves the regular tetrahedron to about 1e-9
@@ -8097,10 +8135,10 @@
8097
8135
  // D3 Imago's vertex-oriented tetrahedral block. Each entry contains the
8098
8136
  // spherical center, local meridian, planar rotation and planar center.
8099
8137
  var FACET_DEFS = [
8100
- [0, SQRT3, HALF_PI, 0, 0, -HALF_PI],
8101
- [0, -SQRT3, -ASIN_ONE_THIRD, 0, Math.PI, HALF_PI],
8102
- [3, 0, -ASIN_ONE_THIRD, 2 * Math.PI / 3, Math.PI, 5 * Math.PI / 6],
8103
- [-3, 0, -ASIN_ONE_THIRD, -2 * Math.PI / 3, Math.PI, Math.PI / 6]
8138
+ [0, SQRT3$1, HALF_PI, 0, 0, -HALF_PI],
8139
+ [0, -SQRT3$1, -ASIN_ONE_THIRD$1, 0, Math.PI, HALF_PI],
8140
+ [3, 0, -ASIN_ONE_THIRD$1, 2 * Math.PI / 3, Math.PI, 5 * Math.PI / 6],
8141
+ [-3, 0, -ASIN_ONE_THIRD$1, -2 * Math.PI / 3, Math.PI, Math.PI / 6]
8104
8142
  ];
8105
8143
 
8106
8144
  function registerNarukawa2022Projection(mproj) {
@@ -8111,10 +8149,10 @@
8111
8149
  }
8112
8150
 
8113
8151
  function getNarukawa2022Engine() {
8114
- if (!engines.default) {
8115
- engines.default = createNarukawa2022Engine();
8152
+ if (!engines$1.default) {
8153
+ engines$1.default = createNarukawa2022Engine();
8116
8154
  }
8117
- return engines.default;
8155
+ return engines$1.default;
8118
8156
  }
8119
8157
 
8120
8158
  function initNarukawa2022(P) {
@@ -8126,7 +8164,7 @@
8126
8164
  xy.x = p[0];
8127
8165
  xy.y = p[1];
8128
8166
  };
8129
- P.__projection_topology = engine.getTopology(P.lam0 * R2D$1);
8167
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$2);
8130
8168
  P.__projected_outline = engine.outline;
8131
8169
  }
8132
8170
 
@@ -8143,6 +8181,13 @@
8143
8181
  rotation: def[5]
8144
8182
  };
8145
8183
  });
8184
+ var rasterSectors = facets.reduce(function(memo, facet) {
8185
+ return memo.concat(getRawFacetSectorBoundaries(facets, facet));
8186
+ }, []);
8187
+ var rasterPieces = createNarukawaRasterPieces(facets, rasterSectors);
8188
+ var rasterPieceIndex = new Map(rasterPieces.map(function(piece) {
8189
+ return [piece.key, piece.id];
8190
+ }));
8146
8191
  var outline = [[
8147
8192
  [XMIN * EDGE_SCALE, YMIN * EDGE_SCALE],
8148
8193
  [XMAX * EDGE_SCALE, YMIN * EDGE_SCALE],
@@ -8155,6 +8200,7 @@
8155
8200
  forward: forward,
8156
8201
  inverse: inverse,
8157
8202
  outline: outline,
8203
+ rasterPieces: rasterPieces,
8158
8204
  getTopology: getTopology
8159
8205
  };
8160
8206
 
@@ -8188,6 +8234,41 @@
8188
8234
  }],
8189
8235
  findRegion: findRegion,
8190
8236
  findTransitionRegion: findRegion,
8237
+ raster_regions: rasterPieces.map(function(piece) {
8238
+ return {
8239
+ id: piece.id,
8240
+ facet: piece.facet,
8241
+ sector: piece.sector,
8242
+ source_region: piece.facet * 3 + piece.sector,
8243
+ projected_boundary: piece.boundary.map(function(p) {
8244
+ return [p[0] * EDGE_SCALE, p[1] * EDGE_SCALE];
8245
+ })
8246
+ };
8247
+ }),
8248
+ raster_source_regions: rasterSectors.map(function(sector) {
8249
+ return {
8250
+ id: sector.facet * 3 + sector.sector,
8251
+ source_region: sector.facet * 3 + sector.sector,
8252
+ facet: sector.facet,
8253
+ sector: sector.sector,
8254
+ boundary: sector.sphericalBoundary.map(function(p) {
8255
+ var q = fromCanonical(p[0], p[1], orientation);
8256
+ return [
8257
+ normalizeLongitude$2(q[0] * R2D$2 + lon0),
8258
+ q[1] * R2D$2
8259
+ ];
8260
+ })
8261
+ };
8262
+ }),
8263
+ raster_mesh_interval: 32,
8264
+ raster_cell_halo: false,
8265
+ fill_raster_mask: true,
8266
+ fill_raster_coverage: true,
8267
+ findRasterRegion: findRasterRegion,
8268
+ projectRasterRegion: projectRasterRegion,
8269
+ projectRasterSourceRegion: projectRasterSourceRegion,
8270
+ projectRasterSector: projectRasterSector,
8271
+ clipRasterRegionPolygon: clipRasterRegionPolygon,
8191
8272
  outline: outline.map(function(ring) {
8192
8273
  return ring.map(function(p) {
8193
8274
  return p.concat();
@@ -8196,30 +8277,422 @@
8196
8277
  };
8197
8278
 
8198
8279
  function findRegion(lon, lat) {
8199
- var lam = normalizeRadians((lon - lon0) * D2R$1);
8200
- return projectState(lam, lat * D2R$1).region;
8280
+ var lam = normalizeRadians((lon - lon0) * D2R$2);
8281
+ return projectState(lam, lat * D2R$2).region;
8201
8282
  }
8283
+
8284
+ function findRasterRegion(lon, lat) {
8285
+ var lam = normalizeRadians((lon - lon0) * D2R$2);
8286
+ var p = toCanonical(lam, lat * D2R$2, orientation);
8287
+ var facet = findForwardFacet(p[0], p[1], facets);
8288
+ var state = applyConditionalLayout(projectFacetRaw(p[0], p[1], facet), facet);
8289
+ return rasterPieceIndex.get(getRasterPieceKey(
8290
+ state.facet, state.sector, state.oobKey, state.folded, state.wrap
8291
+ ));
8292
+ }
8293
+
8294
+ function projectRasterRegion(lon, lat, regionId) {
8295
+ var piece = rasterPieces[regionId];
8296
+ var lam = normalizeRadians((lon - lon0) * D2R$2);
8297
+ var p = toCanonical(lam, lat * D2R$2, orientation);
8298
+ var facet = facets[piece.facet];
8299
+ var raw = projectFacetRaw(p[0], p[1], facet, piece.sector);
8300
+ var q = applyRasterPieceLayout(raw, facet, piece);
8301
+ return [q[0] * EDGE_SCALE, q[1] * EDGE_SCALE];
8302
+ }
8303
+
8304
+ function projectRasterSector(lon, lat, facetId, sector) {
8305
+ var lam = normalizeRadians((lon - lon0) * D2R$2);
8306
+ var p = toCanonical(lam, lat * D2R$2, orientation);
8307
+ var raw = projectFacetRaw(p[0], p[1], facets[facetId], sector);
8308
+ return [raw.x, raw.y];
8309
+ }
8310
+
8311
+ function projectRasterSourceRegion(lon, lat, sourceRegionId) {
8312
+ return projectRasterSector(
8313
+ lon, lat, Math.floor(sourceRegionId / 3), sourceRegionId % 3);
8314
+ }
8315
+
8316
+ function clipRasterRegionPolygon(vertices, regionId) {
8317
+ return clipRasterPiecePolygon(
8318
+ vertices, facets[rasterPieces[regionId].facet],
8319
+ rasterPieces[regionId]);
8320
+ }
8321
+ }
8322
+ }
8323
+
8324
+ function createNarukawaRasterPieces(facets, rasterSectors) {
8325
+ var pieces = [];
8326
+ facets.forEach(function(facet) {
8327
+ rasterSectors.filter(function(o) {
8328
+ return o.facet == facet.id;
8329
+ }).forEach(function(sectorData) {
8330
+ ['normal', 'xpos', 'xneg', 'ypos', 'yneg'].forEach(function(oobKey) {
8331
+ var oobPolygon = clipOobPolygon(sectorData.boundary, oobKey);
8332
+ if (oobPolygon.length < 3) return;
8333
+ oobPolygon = oobPolygon.map(function(p) {
8334
+ return applyOobTransform(p, facet, oobKey);
8335
+ });
8336
+ [0, 1].forEach(function(folded) {
8337
+ var foldedPolygon = clipPolygonAxis$1(oobPolygon, 0, 0, folded == 0);
8338
+ if (foldedPolygon.length < 3) return;
8339
+ foldedPolygon = foldedPolygon.map(function(p) {
8340
+ return applyFoldTransform(p, folded);
8341
+ });
8342
+ [0, 1].forEach(function(wrap) {
8343
+ var finalPolygon = foldedPolygon.map(function(p) {
8344
+ return [
8345
+ p[0] + LAYOUT_SHIFT + wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
8346
+ p[1] + 1.5
8347
+ ];
8348
+ });
8349
+ finalPolygon = clipRectangle(
8350
+ finalPolygon, XMIN, YMIN, XMAX, YMAX);
8351
+ if (finalPolygon.length < 3 ||
8352
+ Math.abs(getPlanarRingArea(finalPolygon)) < EPS$1) return;
8353
+ var id = pieces.length;
8354
+ pieces.push({
8355
+ id: id,
8356
+ key: getRasterPieceKey(
8357
+ facet.id, sectorData.sector, oobKey, folded, wrap),
8358
+ facet: facet.id,
8359
+ sector: sectorData.sector,
8360
+ oobKey: oobKey,
8361
+ folded: folded,
8362
+ wrap: wrap,
8363
+ boundary: finalPolygon.concat([finalPolygon[0].concat()])
8364
+ });
8365
+ });
8366
+ });
8367
+ });
8368
+ });
8369
+ });
8370
+ return pieces;
8371
+ }
8372
+
8373
+ function getRawFacetSectorBoundaries(facets, facet) {
8374
+ var corners = facets.filter(function(o) {
8375
+ return o.id != facet.id;
8376
+ }).map(function(o) {
8377
+ var v = radiansToVector(o.lon, o.lat);
8378
+ return vectorToRadians([-v[0], -v[1], -v[2]]);
8379
+ });
8380
+ corners.sort(function(a, b) {
8381
+ return obliquifySpherical(a[1], a[0], facet)[1] -
8382
+ obliquifySpherical(b[1], b[0], facet)[1];
8383
+ });
8384
+ var samples = [];
8385
+ for (var i = 0; i < corners.length; i++) {
8386
+ var edge = interpolateSphericalRadians(
8387
+ corners[i], corners[(i + 1) % corners.length], 0.05 * D2R$2);
8388
+ for (var j = 0; j < edge.length - 1; j++) {
8389
+ var p = edge[j];
8390
+ var q = projectFacetRaw(p[0], p[1], facet);
8391
+ samples.push({
8392
+ sector: q.sector,
8393
+ point: [q.x, q.y],
8394
+ spherical: p.concat()
8395
+ });
8396
+ }
8397
+ }
8398
+ return [0, 1, 2].map(function(sector) {
8399
+ var run = getLongestCircularSectorRun(samples, sector);
8400
+ var middle = getFarthestSphericalSample(
8401
+ run, [facet.lon, facet.lat]);
8402
+ return {
8403
+ facet: facet.id,
8404
+ sector: sector,
8405
+ sphericalBoundary: [
8406
+ [facet.lon, facet.lat],
8407
+ run[0].spherical,
8408
+ middle.spherical,
8409
+ run[run.length - 1].spherical,
8410
+ [facet.lon, facet.lat]
8411
+ ],
8412
+ boundary: [[facet.x, facet.y]].concat(run.map(function(o) {
8413
+ return o.point;
8414
+ }))
8415
+ };
8416
+ });
8417
+ }
8418
+
8419
+ function getFarthestSphericalSample(samples, center) {
8420
+ var centerVector = radiansToVector(center[0], center[1]);
8421
+ var best = samples[0];
8422
+ var minDot = Infinity;
8423
+ samples.forEach(function(sample) {
8424
+ var v = radiansToVector(sample.spherical[0], sample.spherical[1]);
8425
+ var d = dot$1(centerVector, v);
8426
+ if (d < minDot) {
8427
+ minDot = d;
8428
+ best = sample;
8429
+ }
8430
+ });
8431
+ return best;
8432
+ }
8433
+
8434
+ function getLongestCircularSectorRun(samples, sector) {
8435
+ var runs = [];
8436
+ var run = [];
8437
+ for (var i = 0; i < samples.length * 2; i++) {
8438
+ var sample = samples[i % samples.length];
8439
+ if (sample.sector == sector) {
8440
+ run.push(sample);
8441
+ } else if (run.length) {
8442
+ runs.push(run);
8443
+ run = [];
8444
+ }
8445
+ }
8446
+ if (run.length) runs.push(run);
8447
+ runs.sort(function(a, b) { return b.length - a.length; });
8448
+ run = runs[0] || [];
8449
+ if (run.length > samples.length) run = run.slice(0, samples.length);
8450
+ return run;
8451
+ }
8452
+
8453
+ function applyRasterPieceLayout(raw, facet, piece) {
8454
+ var p = applyOobTransform([raw.x, raw.y], facet, piece.oobKey);
8455
+ p = applyFoldTransform(p, piece.folded);
8456
+ return [
8457
+ p[0] + LAYOUT_SHIFT + piece.wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
8458
+ p[1] + 1.5
8459
+ ];
8460
+ }
8461
+
8462
+ function clipRasterPiecePolygon(vertices, facet, piece) {
8463
+ var polygon = clipRasterOobPolygon(vertices, piece.oobKey);
8464
+ polygon = polygon.map(function(vertex) {
8465
+ var p = applyOobTransform([vertex.x, vertex.y], facet, piece.oobKey);
8466
+ return copyRasterVertex$1(vertex, p[0], p[1]);
8467
+ });
8468
+ polygon = clipRasterPolygonAxis$1(
8469
+ polygon, 'x', 0, piece.folded == 0);
8470
+ polygon = polygon.map(function(vertex) {
8471
+ var p = applyFoldTransform([vertex.x, vertex.y], piece.folded);
8472
+ return copyRasterVertex$1(vertex, p[0], p[1]);
8473
+ });
8474
+ polygon = polygon.map(function(vertex) {
8475
+ return copyRasterVertex$1(
8476
+ vertex,
8477
+ vertex.x + LAYOUT_SHIFT +
8478
+ piece.wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
8479
+ vertex.y + 1.5
8480
+ );
8481
+ });
8482
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', XMIN, true);
8483
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', XMAX, false);
8484
+ polygon = clipRasterPolygonAxis$1(polygon, 'y', YMIN, true);
8485
+ polygon = clipRasterPolygonAxis$1(polygon, 'y', YMAX, false);
8486
+ polygon.forEach(function(vertex) {
8487
+ vertex.x *= EDGE_SCALE;
8488
+ vertex.y *= EDGE_SCALE;
8489
+ });
8490
+ return polygon;
8491
+ }
8492
+
8493
+ function clipRasterOobPolygon(polygon, oobKey) {
8494
+ if (oobKey == 'xpos') {
8495
+ return clipRasterPolygonAxis$1(polygon, 'x', 3, true);
8496
+ }
8497
+ if (oobKey == 'xneg') {
8498
+ return clipRasterPolygonAxis$1(polygon, 'x', -3, false);
8499
+ }
8500
+ if (oobKey == 'ypos' || oobKey == 'yneg') {
8501
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', -3, true);
8502
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', 3, false);
8503
+ return clipRasterPolygonAxis$1(
8504
+ polygon, 'y', oobKey == 'ypos' ? SQRT3$1 : -SQRT3$1,
8505
+ oobKey == 'ypos');
8202
8506
  }
8507
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', -3, true);
8508
+ polygon = clipRasterPolygonAxis$1(polygon, 'x', 3, false);
8509
+ polygon = clipRasterPolygonAxis$1(polygon, 'y', -SQRT3$1, true);
8510
+ return clipRasterPolygonAxis$1(polygon, 'y', SQRT3$1, false);
8511
+ }
8512
+
8513
+ function clipRasterPolygonAxis$1(polygon, axis, value, keepGreater) {
8514
+ var output = [];
8515
+ if (polygon.length === 0) return output;
8516
+ var a = polygon[polygon.length - 1];
8517
+ var aInside = keepGreater ?
8518
+ a[axis] >= value - EPS$1 : a[axis] <= value + EPS$1;
8519
+ polygon.forEach(function(b) {
8520
+ var bInside = keepGreater ?
8521
+ b[axis] >= value - EPS$1 : b[axis] <= value + EPS$1;
8522
+ if (aInside != bInside) {
8523
+ var t = (value - a[axis]) / (b[axis] - a[axis]);
8524
+ var vertex = {
8525
+ x: a.x + (b.x - a.x) * t,
8526
+ y: a.y + (b.y - a.y) * t,
8527
+ sx: a.sx + (b.sx - a.sx) * t,
8528
+ sy: a.sy + (b.sy - a.sy) * t,
8529
+ lon: a.lon + (b.lon - a.lon) * t,
8530
+ lat: a.lat + (b.lat - a.lat) * t
8531
+ };
8532
+ vertex[axis] = value;
8533
+ output.push(vertex);
8534
+ }
8535
+ if (bInside) output.push(copyRasterVertex$1(b, b.x, b.y));
8536
+ a = b;
8537
+ aInside = bInside;
8538
+ });
8539
+ return output;
8540
+ }
8541
+
8542
+ function copyRasterVertex$1(vertex, x, y) {
8543
+ return {
8544
+ x: x,
8545
+ y: y,
8546
+ sx: vertex.sx,
8547
+ sy: vertex.sy,
8548
+ lon: vertex.lon,
8549
+ lat: vertex.lat
8550
+ };
8551
+ }
8552
+
8553
+ function applyOobTransform(p, facet, oobKey) {
8554
+ if (oobKey == 'xpos' || oobKey == 'xneg') {
8555
+ return [2 * facet.x - p[0], -p[1]];
8556
+ }
8557
+ if (oobKey == 'ypos') {
8558
+ return [-p[0], BLOCK_HEIGHT - p[1]];
8559
+ }
8560
+ if (oobKey == 'yneg') {
8561
+ return [-p[0], -BLOCK_HEIGHT - p[1]];
8562
+ }
8563
+ return p.concat();
8564
+ }
8565
+
8566
+ function applyFoldTransform(p, folded) {
8567
+ return folded ? [BLOCK_HEIGHT - p[1], p[0]] : [p[1], -p[0]];
8568
+ }
8569
+
8570
+ function clipOobPolygon(polygon, oobKey) {
8571
+ if (oobKey == 'xpos') return clipPolygonAxis$1(polygon, 0, 3, true);
8572
+ if (oobKey == 'xneg') return clipPolygonAxis$1(polygon, 0, -3, false);
8573
+ if (oobKey == 'ypos') {
8574
+ return clipPolygonAxis$1(
8575
+ clipPolygonAxis$1(
8576
+ clipPolygonAxis$1(polygon, 0, -3, true), 0, 3, false),
8577
+ 1, SQRT3$1, true);
8578
+ }
8579
+ if (oobKey == 'yneg') {
8580
+ return clipPolygonAxis$1(
8581
+ clipPolygonAxis$1(
8582
+ clipPolygonAxis$1(polygon, 0, -3, true), 0, 3, false),
8583
+ 1, -SQRT3$1, false);
8584
+ }
8585
+ return clipRectangle(polygon, -3, -SQRT3$1, 3, SQRT3$1);
8586
+ }
8587
+
8588
+ function clipRectangle(polygon, xmin, ymin, xmax, ymax) {
8589
+ polygon = clipPolygonAxis$1(polygon, 0, xmin, true);
8590
+ polygon = clipPolygonAxis$1(polygon, 0, xmax, false);
8591
+ polygon = clipPolygonAxis$1(polygon, 1, ymin, true);
8592
+ return clipPolygonAxis$1(polygon, 1, ymax, false);
8593
+ }
8594
+
8595
+ function clipPolygonAxis$1(polygon, axis, value, keepGreater) {
8596
+ var output = [];
8597
+ if (polygon.length === 0) return output;
8598
+ var a = polygon[polygon.length - 1];
8599
+ var aInside = keepGreater ? a[axis] >= value - EPS$1 : a[axis] <= value + EPS$1;
8600
+ polygon.forEach(function(b) {
8601
+ var bInside = keepGreater ? b[axis] >= value - EPS$1 : b[axis] <= value + EPS$1;
8602
+ if (aInside != bInside) {
8603
+ var t = (value - a[axis]) / (b[axis] - a[axis]);
8604
+ var p = [
8605
+ a[0] + (b[0] - a[0]) * t,
8606
+ a[1] + (b[1] - a[1]) * t
8607
+ ];
8608
+ p[axis] = value;
8609
+ output.push(p);
8610
+ }
8611
+ if (bInside) output.push(b.concat());
8612
+ a = b;
8613
+ aInside = bInside;
8614
+ });
8615
+ return output;
8616
+ }
8617
+
8618
+ function interpolateSphericalRadians(a, b, interval) {
8619
+ var av = radiansToVector(a[0], a[1]);
8620
+ var bv = radiansToVector(b[0], b[1]);
8621
+ var angle = Math.acos(clamp$2(dot$1(av, bv), -1, 1));
8622
+ var count = Math.max(1, Math.ceil(angle / interval));
8623
+ var sinAngle = Math.sin(angle);
8624
+ var points = [];
8625
+ for (var i = 0; i <= count; i++) {
8626
+ var t = i / count;
8627
+ var ka = Math.sin((1 - t) * angle) / sinAngle;
8628
+ var kb = Math.sin(t * angle) / sinAngle;
8629
+ points.push(vectorToRadians(normalizeVector([
8630
+ av[0] * ka + bv[0] * kb,
8631
+ av[1] * ka + bv[1] * kb,
8632
+ av[2] * ka + bv[2] * kb
8633
+ ])));
8634
+ }
8635
+ return points;
8636
+ }
8637
+
8638
+ function vectorToRadians(p) {
8639
+ return [
8640
+ Math.atan2(p[1], p[0]),
8641
+ Math.asin(clamp$2(p[2], -1, 1))
8642
+ ];
8643
+ }
8644
+
8645
+ function getPlanarRingArea(ring) {
8646
+ var area = 0;
8647
+ for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
8648
+ area += ring[j][0] * ring[i][1] - ring[i][0] * ring[j][1];
8649
+ }
8650
+ return area / 2;
8651
+ }
8652
+
8653
+ function getRasterPieceKey(facet, sector, oobKey, folded, wrap) {
8654
+ return [facet, sector, oobKey, folded, wrap].join(':');
8203
8655
  }
8204
8656
 
8205
8657
  function projectCanonical(lam, phi, facets) {
8206
8658
  var facet = findForwardFacet(lam, phi, facets);
8659
+ var state = projectFacetRaw(lam, phi, facet);
8660
+ return applyConditionalLayout(state, facet);
8661
+ }
8662
+
8663
+ function projectFacetRaw(lam, phi, facet, forcedSector) {
8207
8664
  var relative = obliquifySpherical(phi, lam, facet);
8208
- var sector = Math.floor((relative[1] + Math.PI / 3) / (2 * Math.PI / 3));
8665
+ var sector = forcedSector == null ?
8666
+ Math.floor((relative[1] + Math.PI / 3) / (2 * Math.PI / 3)) :
8667
+ forcedSector == 2 ? -1 : forcedSector;
8209
8668
  var base = sector * 2 * Math.PI / 3;
8210
8669
  var polar = narukawaFaceForward(relative[1] - base, relative[0]);
8211
8670
  var angle = polar[1] + facet.rotation + base / 2;
8212
8671
  var x = polar[0] * Math.cos(angle) + facet.x;
8213
8672
  var y = polar[0] * Math.sin(angle) + facet.y;
8673
+ return {
8674
+ x: x,
8675
+ y: y,
8676
+ facet: facet.id,
8677
+ sector: mod(sector, 3)
8678
+ };
8679
+ }
8680
+
8681
+ function applyConditionalLayout(raw, facet) {
8682
+ var x = raw.x;
8683
+ var y = raw.y;
8214
8684
  var oob = 0;
8685
+ var oobKey = 'normal';
8215
8686
  var folded = 0;
8216
8687
  var wrap = 0;
8217
8688
 
8218
- if (Math.abs(x) > 3 + EPS) {
8689
+ if (Math.abs(x) > 3 + EPS$1) {
8690
+ oobKey = x > 0 ? 'xpos' : 'xneg';
8219
8691
  x = 2 * facet.x - x;
8220
8692
  y = -y;
8221
8693
  oob = 1;
8222
- } else if (Math.abs(y) > SQRT3 + EPS) {
8694
+ } else if (Math.abs(y) > SQRT3$1 + EPS$1) {
8695
+ oobKey = y > 0 ? 'ypos' : 'yneg';
8223
8696
  x = -x;
8224
8697
  y = BLOCK_HEIGHT * Math.sign(y) - y;
8225
8698
  oob = 2;
@@ -8227,7 +8700,7 @@
8227
8700
 
8228
8701
  var qx = y;
8229
8702
  var qy = -x;
8230
- if (qy > EPS) {
8703
+ if (qy > EPS$1) {
8231
8704
  qx = BLOCK_HEIGHT - qx;
8232
8705
  qy = -qy;
8233
8706
  folded = 1;
@@ -8244,9 +8717,10 @@
8244
8717
  return {
8245
8718
  x: x,
8246
8719
  y: y,
8247
- facet: facet.id,
8248
- sector: mod(sector, 3),
8720
+ facet: raw.facet,
8721
+ sector: raw.sector,
8249
8722
  oob: oob,
8723
+ oobKey: oobKey,
8250
8724
  folded: folded,
8251
8725
  wrap: wrap
8252
8726
  };
@@ -8267,29 +8741,29 @@
8267
8741
  }
8268
8742
 
8269
8743
  function narukawaFaceForward(lam, phi) {
8270
- var a = lam - Math.asin(Math.sin(lam) / SQRT3);
8271
- var theta = Math.atan(2 * SQRT3 / Math.PI * a);
8272
- var denominator = 2 + SQRT2 * Math.tan(phi);
8744
+ var a = lam - Math.asin(Math.sin(lam) / SQRT3$1);
8745
+ var theta = Math.atan(2 * SQRT3$1 / Math.PI * a);
8746
+ var denominator = 2 + SQRT2$1 * Math.tan(phi);
8273
8747
  var q = denominator > 0 ? (2 + Math.cos(lam)) / denominator : 0;
8274
- var r = q * SQRT3 / Math.cos(theta);
8748
+ var r = q * SQRT3$1 / Math.cos(theta);
8275
8749
  return [r, theta];
8276
8750
  }
8277
8751
 
8278
8752
  function narukawaFaceInverse(r, theta) {
8279
- var target = Math.tan(theta) * Math.PI / (2 * SQRT3);
8753
+ var target = Math.tan(theta) * Math.PI / (2 * SQRT3$1);
8280
8754
  var lo = -Math.PI / 3;
8281
8755
  var hi = Math.PI / 3;
8282
8756
  var lam;
8283
8757
  for (var i = 0; i < 55; i++) {
8284
8758
  lam = (lo + hi) / 2;
8285
- var a = lam - Math.asin(Math.sin(lam) / SQRT3);
8759
+ var a = lam - Math.asin(Math.sin(lam) / SQRT3$1);
8286
8760
  if (a < target) lo = lam;
8287
8761
  else hi = lam;
8288
8762
  }
8289
8763
  lam = (lo + hi) / 2;
8290
- var q = r * Math.cos(theta) / SQRT3;
8291
- var phi = q < EPS ? HALF_PI :
8292
- Math.atan(((2 + Math.cos(lam)) / q - 2) / SQRT2);
8764
+ var q = r * Math.cos(theta) / SQRT3$1;
8765
+ var phi = q < EPS$1 ? HALF_PI :
8766
+ Math.atan(((2 + Math.cos(lam)) / q - 2) / SQRT2$1);
8293
8767
  return [phi, lam];
8294
8768
  }
8295
8769
 
@@ -8370,7 +8844,7 @@
8370
8844
  var theta0 = pole.meridian;
8371
8845
  var lat1;
8372
8846
  var lon1;
8373
- if (Math.abs(lat0 - HALF_PI) < EPS) {
8847
+ if (Math.abs(lat0 - HALF_PI) < EPS$1) {
8374
8848
  lat1 = lat;
8375
8849
  lon1 = lon - lon0;
8376
8850
  } else {
@@ -8381,7 +8855,7 @@
8381
8855
  1
8382
8856
  ));
8383
8857
  var denominator = Math.cos(lat1);
8384
- var value = denominator < EPS ? 1 :
8858
+ var value = denominator < EPS$1 ? 1 :
8385
8859
  (Math.cos(lat0) * Math.sin(lat) -
8386
8860
  Math.sin(lat0) * Math.cos(lat) * Math.cos(lon0 - lon)) /
8387
8861
  denominator;
@@ -8402,7 +8876,7 @@
8402
8876
  1
8403
8877
  ));
8404
8878
  var lonOut;
8405
- if (Math.abs(lat0 - HALF_PI) < EPS) {
8879
+ if (Math.abs(lat0 - HALF_PI) < EPS$1) {
8406
8880
  lonOut = lon + lon0;
8407
8881
  } else {
8408
8882
  var value = Math.sin(lat) / Math.cos(lat0) / Math.cos(latOut) -
@@ -8431,8 +8905,8 @@
8431
8905
  var y = edge[0][1] + (edge[1][1] - edge[0][1]) * t;
8432
8906
  var p = inverse(x * EDGE_SCALE, y * EDGE_SCALE);
8433
8907
  path.push([
8434
- normalizeLongitude$1(p[0] * R2D$1 + lon0),
8435
- p[1] * R2D$1
8908
+ normalizeLongitude$2(p[0] * R2D$2 + lon0),
8909
+ p[1] * R2D$2
8436
8910
  ]);
8437
8911
  }
8438
8912
  return memo.concat(splitPathAtAntimeridian$1(path));
@@ -8479,7 +8953,7 @@
8479
8953
  }
8480
8954
 
8481
8955
  function latLonToVector(p) {
8482
- return radiansToVector(p[1] * D2R$1, p[0] * D2R$1);
8956
+ return radiansToVector(p[1] * D2R$2, p[0] * D2R$2);
8483
8957
  }
8484
8958
 
8485
8959
  function radiansToVector(lam, phi) {
@@ -8522,7 +8996,7 @@
8522
8996
  return lam;
8523
8997
  }
8524
8998
 
8525
- function normalizeLongitude$1(lon) {
8999
+ function normalizeLongitude$2(lon) {
8526
9000
  while (lon > 180) lon -= 360;
8527
9001
  while (lon < -180) lon += 360;
8528
9002
  return lon;
@@ -8538,10 +9012,541 @@
8538
9012
  registerNarukawa2022Projection: registerNarukawa2022Projection
8539
9013
  });
8540
9014
 
9015
+ /*
9016
+ * Rectangular conformal tetrahedral projections based on L. P. Lee's
9017
+ * conformal face transform.
9018
+ *
9019
+ * Lee transform and tetrahedral net adapted from d3-geo-polygon:
9020
+ * Copyright 2017-2024 Mike Bostock, ISC license.
9021
+ * https://github.com/d3/d3-geo-polygon/blob/main/src/tetrahedralLee.js
9022
+ *
9023
+ * The rectangular layout below is derived from Markley's repeated-face
9024
+ * construction: four affine copies of the triangular Lee net are clipped to
9025
+ * a 4/sqrt(3) frame. See F. Landis Markley, "Tetrahedral Map Projection"
9026
+ * (2020), and https://blog.map-projections.net/lee-markley-calm-and-grieger.
9027
+ */
9028
+
9029
+
9030
+ var D2R$1 = Math.PI / 180;
9031
+ var R2D$1 = 180 / Math.PI;
9032
+ var SQRT2 = Math.sqrt(2);
9033
+ var SQRT3 = Math.sqrt(3);
9034
+ var ASIN_ONE_THIRD = Math.asin(1 / 3);
9035
+ var MARKLEY_LATITUDE = Math.acos(1 / 3) * 0.5 * R2D$1;
9036
+ var RECT_XMIN = -7;
9037
+ var RECT_XMAX = 1;
9038
+ var RECT_YMIN = -2 * SQRT3;
9039
+ var RECT_YMAX = 0;
9040
+ var EPS = 1e-12;
9041
+ var engines = {};
9042
+
9043
+ var TETRAHEDRON_VERTICES = [
9044
+ [0, 90],
9045
+ [-180, -ASIN_ONE_THIRD * R2D$1],
9046
+ [-60, -ASIN_ONE_THIRD * R2D$1],
9047
+ [60, -ASIN_ONE_THIRD * R2D$1]
9048
+ ];
9049
+
9050
+ var TETRAHEDRON_FACES = [
9051
+ [1, 2, 3],
9052
+ [0, 2, 1],
9053
+ [0, 3, 2],
9054
+ [0, 1, 3]
9055
+ ].map(function(face) {
9056
+ return face.map(function(i) {
9057
+ return TETRAHEDRON_VERTICES[i];
9058
+ });
9059
+ });
9060
+
9061
+ var LAYOUT_COPIES = [
9062
+ {id: 0, name: 'green', matrix: [1, 0, 0, 0, -1, 0]},
9063
+ {id: 1, name: 'red', matrix: [-1, 0, -4, 0, 1, 0]},
9064
+ {id: 2, name: 'blue', matrix: [1, 0, -8, 0, -1, 0]},
9065
+ {id: 3, name: 'orange', matrix: [-1, 0, 4, 0, 1, 0]}
9066
+ ];
9067
+
9068
+ function registerLeeTetrahedralProjections(mproj) {
9069
+ if (!mproj) return;
9070
+ register('markley', 'Markley conformal tetrahedral world map');
9071
+ register('calm', 'Conformal Authagraph-Like Map');
9072
+
9073
+ function register(id, name) {
9074
+ if (mproj.internal.pj_list[id]) return;
9075
+ mproj.pj_add(function(P) {
9076
+ initLeeTetrahedral(P, id);
9077
+ }, id, name);
9078
+ }
9079
+ }
9080
+
9081
+ function getLeeTetrahedralEngine(id) {
9082
+ id = id || 'markley';
9083
+ if (!engines[id]) {
9084
+ engines[id] = createLeeTetrahedralEngine(getProjectionRotation(id));
9085
+ }
9086
+ return engines[id];
9087
+ }
9088
+
9089
+ function initLeeTetrahedral(P, id) {
9090
+ var engine = getLeeTetrahedralEngine(id);
9091
+ P.es = 0;
9092
+ P.inv = null;
9093
+ P.fwd = function(lp, xy) {
9094
+ var p = engine.forward(lp.lam, lp.phi);
9095
+ xy.x = p[0];
9096
+ xy.y = p[1];
9097
+ };
9098
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$1);
9099
+ P.__projected_outline = engine.outline;
9100
+ }
9101
+
9102
+ function getProjectionRotation(id) {
9103
+ if (id == 'calm') {
9104
+ // Exact D3 Euler equivalent of MapDesigner's published CALM aspect:
9105
+ // latitude 77°, longitude 143°, central meridian -163°.
9106
+ return [
9107
+ 19.57956907750618,
9108
+ -12.42267097553935,
9109
+ 3.8615690020132067
9110
+ ];
9111
+ }
9112
+ // Markley's singularities are at ±35.26439°, in the oceans.
9113
+ return [115, MARKLEY_LATITUDE - 90, 180];
9114
+ }
9115
+
9116
+ function createLeeTetrahedralEngine(rotation) {
9117
+ var base = createPolyhedralProjection({
9118
+ faces: TETRAHEDRON_FACES,
9119
+ parents: [-1, 0, 0, 0],
9120
+ rotation: rotation,
9121
+ angle: 30,
9122
+ faceProjector: createLeeFaceProjector
9123
+ });
9124
+ var normalization = getBaseNormalization(base.outline);
9125
+ var baseTopology = base.getTopology(0);
9126
+ var sourceRegions = createSourceRegions(rotation);
9127
+ var pieces = createLayoutPieces(baseTopology.regions, normalization);
9128
+ var pieceIndex = new Map(pieces.map(function(piece) {
9129
+ return [getPieceKey(piece.face, piece.copy), piece.id];
9130
+ }));
9131
+ var outline = [[
9132
+ centerOutputPoint([RECT_XMIN, RECT_YMIN]),
9133
+ centerOutputPoint([RECT_XMAX, RECT_YMIN]),
9134
+ centerOutputPoint([RECT_XMAX, RECT_YMAX]),
9135
+ centerOutputPoint([RECT_XMIN, RECT_YMAX]),
9136
+ centerOutputPoint([RECT_XMIN, RECT_YMIN])
9137
+ ]];
9138
+
9139
+ return {
9140
+ forward: forward,
9141
+ outline: outline,
9142
+ getTopology: getTopology
9143
+ };
9144
+
9145
+ function forward(lam, phi) {
9146
+ var p = normalizeBasePoint(base.forward(lam, phi), normalization);
9147
+ var copy = getLayoutCopy(p);
9148
+ return centerOutputPoint(applyMatrix(copy.matrix, p));
9149
+ }
9150
+
9151
+ function getTopology(lon0) {
9152
+ var topology = base.getTopology(lon0);
9153
+ return {
9154
+ regions: pieces.map(copyProjectedPiece),
9155
+ seams: topology.seams.map(function(seam) {
9156
+ return {
9157
+ type: 'cut',
9158
+ faces: seam.faces,
9159
+ paths: seam.paths
9160
+ };
9161
+ }),
9162
+ findRegion: findRegion,
9163
+ findTransitionRegion: findRegion,
9164
+ projectRegion: projectRegion,
9165
+ raster_regions: pieces.map(copyRasterPiece),
9166
+ raster_source_regions: sourceRegions.map(function(region) {
9167
+ return {
9168
+ id: region.id,
9169
+ boundary: region.boundary.map(function(p) {
9170
+ return [
9171
+ normalizeLongitude$1(p[0] + lon0),
9172
+ p[1]
9173
+ ];
9174
+ })
9175
+ };
9176
+ }),
9177
+ raster_mesh_interval: 32,
9178
+ raster_cell_halo: false,
9179
+ fill_raster_mask: true,
9180
+ fill_raster_coverage: true,
9181
+ findRasterRegion: findRegion,
9182
+ projectRasterRegion: projectRegion,
9183
+ projectRasterSourceRegion: projectRasterSourceRegion,
9184
+ clipRasterRegionPolygon: clipRasterRegionPolygon,
9185
+ outline: outline.map(function(ring) {
9186
+ return ring.map(function(p) { return p.concat(); });
9187
+ })
9188
+ };
9189
+
9190
+ function findRegion(lon, lat) {
9191
+ var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
9192
+ var phi = lat * D2R$1;
9193
+ var face = base.findFace(lam, phi);
9194
+ var p = normalizeBasePoint(base.forwardFace(lam, phi, face), normalization);
9195
+ var copy = getLayoutCopy(p);
9196
+ return pieceIndex.get(getPieceKey(face, copy.id));
9197
+ }
9198
+
9199
+ function projectRegion(lon, lat, regionId) {
9200
+ var piece = pieces[regionId];
9201
+ var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
9202
+ var p = normalizeBasePoint(
9203
+ base.forwardFace(lam, lat * D2R$1, piece.face),
9204
+ normalization
9205
+ );
9206
+ return centerOutputPoint(applyMatrix(piece.matrix, p));
9207
+ }
9208
+
9209
+ function projectRasterSourceRegion(lon, lat, sourceRegionId) {
9210
+ var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
9211
+ return normalizeBasePoint(
9212
+ base.forwardFace(lam, lat * D2R$1, sourceRegionId),
9213
+ normalization
9214
+ );
9215
+ }
9216
+
9217
+ function clipRasterRegionPolygon(vertices, regionId) {
9218
+ var piece = pieces[regionId];
9219
+ var polygon = vertices.map(function(vertex) {
9220
+ var p = applyMatrix(piece.matrix, [vertex.x, vertex.y]);
9221
+ return copyRasterVertex(vertex, p[0], p[1]);
9222
+ });
9223
+ polygon = clipRasterPolygonAxis(polygon, 'x', RECT_XMIN, true);
9224
+ polygon = clipRasterPolygonAxis(polygon, 'x', RECT_XMAX, false);
9225
+ polygon = clipRasterPolygonAxis(polygon, 'y', RECT_YMIN, true);
9226
+ polygon = clipRasterPolygonAxis(polygon, 'y', RECT_YMAX, false);
9227
+ polygon.forEach(function(vertex) {
9228
+ var p = centerOutputPoint([vertex.x, vertex.y]);
9229
+ vertex.x = p[0];
9230
+ vertex.y = p[1];
9231
+ });
9232
+ return polygon;
9233
+ }
9234
+ }
9235
+ }
9236
+
9237
+ function createSourceRegions(rotation) {
9238
+ return TETRAHEDRON_FACES.map(function(face, id) {
9239
+ var boundary = face.map(function(p) {
9240
+ var q = rotateSphericalRadians(
9241
+ p[0] * D2R$1, p[1] * D2R$1, rotation, true);
9242
+ return [normalizeLongitude$1(q[0] * R2D$1), q[1] * R2D$1];
9243
+ });
9244
+ boundary.push(boundary[0].concat());
9245
+ return {id: id, boundary: boundary};
9246
+ });
9247
+ }
9248
+
9249
+ function createLayoutPieces(regions, normalization) {
9250
+ var pieces = [];
9251
+ regions.forEach(function(region) {
9252
+ var boundary = region.projected_boundary.map(function(p) {
9253
+ return normalizeBasePoint(p, normalization);
9254
+ });
9255
+ LAYOUT_COPIES.forEach(function(copy) {
9256
+ var polygon = boundary.map(function(p) {
9257
+ return applyMatrix(copy.matrix, p);
9258
+ });
9259
+ polygon = clipPolygonAxis(polygon, 0, RECT_XMIN, true);
9260
+ polygon = clipPolygonAxis(polygon, 0, RECT_XMAX, false);
9261
+ polygon = clipPolygonAxis(polygon, 1, RECT_YMIN, true);
9262
+ polygon = clipPolygonAxis(polygon, 1, RECT_YMAX, false);
9263
+ if (polygon.length < 3 || Math.abs(getRingArea$2(polygon)) < EPS) return;
9264
+ var id = pieces.length;
9265
+ pieces.push({
9266
+ id: id,
9267
+ face: region.id,
9268
+ source_region: region.id,
9269
+ copy: copy.id,
9270
+ matrix: copy.matrix,
9271
+ boundary: polygon.map(centerOutputPoint)
9272
+ });
9273
+ });
9274
+ });
9275
+ return pieces;
9276
+ }
9277
+
9278
+ function copyProjectedPiece(piece) {
9279
+ return {
9280
+ id: piece.id,
9281
+ source_region: piece.source_region,
9282
+ projected_boundary: closeRing$1(piece.boundary)
9283
+ };
9284
+ }
9285
+
9286
+ function copyRasterPiece(piece) {
9287
+ return {
9288
+ id: piece.id,
9289
+ source_region: piece.source_region,
9290
+ projected_boundary: closeRing$1(piece.boundary)
9291
+ };
9292
+ }
9293
+
9294
+ function closeRing$1(ring) {
9295
+ var copy = ring.map(function(p) { return p.concat(); });
9296
+ if (copy.length && !pointsEqual$1(copy[0], copy[copy.length - 1])) {
9297
+ copy.push(copy[0].concat());
9298
+ }
9299
+ return copy;
9300
+ }
9301
+
9302
+ function getLayoutCopy(p) {
9303
+ // The four transformed triangular nets tile the frame. These two straight
9304
+ // cuts select the unique copy containing a point from the base net.
9305
+ if (p[1] >= 0) return p[0] > 3 ? LAYOUT_COPIES[2] : LAYOUT_COPIES[0];
9306
+ return p[0] > 1 ? LAYOUT_COPIES[3] : LAYOUT_COPIES[1];
9307
+ }
9308
+
9309
+ function centerOutputPoint(p) {
9310
+ return [
9311
+ p[0] - (RECT_XMIN + RECT_XMAX) / 2,
9312
+ p[1] - (RECT_YMIN + RECT_YMAX) / 2
9313
+ ];
9314
+ }
9315
+
9316
+ function getBaseNormalization(outline) {
9317
+ var xmin = Infinity;
9318
+ var ymin = Infinity;
9319
+ var xmax = -Infinity;
9320
+ var ymax = -Infinity;
9321
+ outline.forEach(function(ring) {
9322
+ ring.forEach(function(p) {
9323
+ xmin = Math.min(xmin, p[0]);
9324
+ ymin = Math.min(ymin, p[1]);
9325
+ xmax = Math.max(xmax, p[0]);
9326
+ ymax = Math.max(ymax, p[1]);
9327
+ });
9328
+ });
9329
+ return {
9330
+ cx: (xmin + xmax) / 2,
9331
+ cy: (ymin + ymax) / 2,
9332
+ scale: 8 / (xmax - xmin)
9333
+ };
9334
+ }
9335
+
9336
+ function normalizeBasePoint(p, normalization) {
9337
+ return [
9338
+ (p[0] - normalization.cx) * normalization.scale,
9339
+ -(p[1] - normalization.cy) * normalization.scale
9340
+ ];
9341
+ }
9342
+
9343
+ function createLeeFaceProjector(face) {
9344
+ var c = face.centroid;
9345
+ var rotation = Math.abs(c[1]) == 90 ?
9346
+ [0, -c[1], -30] :
9347
+ [-c[0], -c[1], 30];
9348
+ return function(lam, phi) {
9349
+ var p = rotateSphericalRadians(lam, phi, rotation);
9350
+ var q = leeRaw(p[0], p[1]);
9351
+ return [q[0], -q[1]];
9352
+ };
9353
+ }
9354
+
9355
+ function leeRaw(lam, phi) {
9356
+ var w = [-0.5, SQRT3 / 2];
9357
+ var z = complexMultiply(stereographicRaw(lam, phi), [SQRT2, 0]);
9358
+ var powers = [0, 1, 2].map(function(i) {
9359
+ return complexPower(w, [i, 0]);
9360
+ });
9361
+ var sector = 0;
9362
+ for (var i = 1; i < powers.length; i++) {
9363
+ if (complexMultiply(z, powers[i])[0] >
9364
+ complexMultiply(z, powers[sector])[0]) sector = i;
9365
+ }
9366
+ var rot = powers[sector];
9367
+ var n = complexNorm(z);
9368
+ var h = [0, 0];
9369
+ var k = [0, 0];
9370
+
9371
+ if (n > 0.3) {
9372
+ var y = complexSubtract([1, 0], complexMultiply(rot, z));
9373
+ var w1 = 1.4021821053254548;
9374
+ var coefficients = [
9375
+ 1.15470053837925, 0.192450089729875, 0.0481125224324687,
9376
+ 0.010309826235529, 3.34114739114366e-4, -0.00150351632601465,
9377
+ -0.0012304417796231, -675190201960282e-18,
9378
+ -284084537293856e-18, -821205120500051e-19,
9379
+ -159257630018706e-20, 1.91691805888369e-5,
9380
+ 1.73095888028726e-5, 1.03865580818367e-5,
9381
+ 4.70614523937179e-6, 1.4413500104181e-6,
9382
+ 1.92757960170179e-8, -3.82869799649063e-7,
9383
+ -3.57526015225576e-7, -2.2175964844211e-7
9384
+ ];
9385
+ var g = [0, 0];
9386
+ for (i = coefficients.length - 1; i >= 0; i--) {
9387
+ g = complexAdd([coefficients[i], 0], complexMultiply(g, y));
9388
+ }
9389
+ k = complexSubtract([w1, 0], complexMultiply(complexPower(y, 0.5), g));
9390
+ k = complexMultiply(complexMultiply(k, rot), rot);
9391
+ }
9392
+
9393
+ if (n < 0.5) {
9394
+ var h0 = [1, 1 / 8, 3 / 56, 1 / 32, 35 / 1664, 63 / 4096, 231 / 19456];
9395
+ var z3 = complexPower(z, [3, 0]);
9396
+ for (i = h0.length - 1; i >= 0; i--) {
9397
+ h = complexAdd([h0[i], 0], complexMultiply(h, z3));
9398
+ }
9399
+ h = complexMultiply(h, z);
9400
+ }
9401
+
9402
+ if (n < 0.3) return h;
9403
+ if (n > 0.5) return k;
9404
+ var t = (n - 0.3) / 0.2;
9405
+ return complexAdd(
9406
+ complexMultiply(k, [t, 0]),
9407
+ complexMultiply(h, [1 - t, 0])
9408
+ );
9409
+ }
9410
+
9411
+ function stereographicRaw(lam, phi) {
9412
+ var cosPhi = Math.cos(phi);
9413
+ var k = 1 / (1 + cosPhi * Math.cos(lam));
9414
+ return [k * cosPhi * Math.sin(lam), k * Math.sin(phi)];
9415
+ }
9416
+
9417
+ function complexAdd(a, b) {
9418
+ return [a[0] + b[0], a[1] + b[1]];
9419
+ }
9420
+
9421
+ function complexSubtract(a, b) {
9422
+ return [a[0] - b[0], a[1] - b[1]];
9423
+ }
9424
+
9425
+ function complexMultiply(a, b) {
9426
+ return [a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]];
9427
+ }
9428
+
9429
+ function complexNorm(a) {
9430
+ return Math.hypot(a[0], a[1]);
9431
+ }
9432
+
9433
+ function complexPower(value, exponent) {
9434
+ var a = value[0];
9435
+ var b = value[1];
9436
+ var n = typeof exponent == 'number' ? [exponent, 0] : exponent;
9437
+ if (a === 0 && b === 0) return [0, 0];
9438
+ if (!n[1] && b === 0 && a >= 0) {
9439
+ return [Math.pow(a, n[0]), 0];
9440
+ }
9441
+ var arg = Math.atan2(b, a);
9442
+ var logNorm = Math.log(Math.hypot(a, b));
9443
+ var magnitude = Math.exp(n[0] * logNorm - n[1] * arg);
9444
+ var angle = n[1] * logNorm + n[0] * arg;
9445
+ return [magnitude * Math.cos(angle), magnitude * Math.sin(angle)];
9446
+ }
9447
+
9448
+ function applyMatrix(m, p) {
9449
+ return [
9450
+ m[0] * p[0] + m[1] * p[1] + m[2],
9451
+ m[3] * p[0] + m[4] * p[1] + m[5]
9452
+ ];
9453
+ }
9454
+
9455
+ function clipPolygonAxis(polygon, axis, value, keepGreater) {
9456
+ var output = [];
9457
+ if (!polygon.length) return output;
9458
+ var a = polygon[polygon.length - 1];
9459
+ var aInside = keepGreater ? a[axis] >= value - EPS : a[axis] <= value + EPS;
9460
+ polygon.forEach(function(b) {
9461
+ var bInside = keepGreater ? b[axis] >= value - EPS : b[axis] <= value + EPS;
9462
+ if (aInside != bInside) {
9463
+ var t = (value - a[axis]) / (b[axis] - a[axis]);
9464
+ var p = [
9465
+ a[0] + (b[0] - a[0]) * t,
9466
+ a[1] + (b[1] - a[1]) * t
9467
+ ];
9468
+ p[axis] = value;
9469
+ output.push(p);
9470
+ }
9471
+ if (bInside) output.push(b.concat());
9472
+ a = b;
9473
+ aInside = bInside;
9474
+ });
9475
+ return output;
9476
+ }
9477
+
9478
+ function clipRasterPolygonAxis(polygon, axis, value, keepGreater) {
9479
+ var output = [];
9480
+ if (!polygon.length) return output;
9481
+ var a = polygon[polygon.length - 1];
9482
+ var aInside = keepGreater ? a[axis] >= value - EPS : a[axis] <= value + EPS;
9483
+ polygon.forEach(function(b) {
9484
+ var bInside = keepGreater ? b[axis] >= value - EPS : b[axis] <= value + EPS;
9485
+ if (aInside != bInside) {
9486
+ var t = (value - a[axis]) / (b[axis] - a[axis]);
9487
+ var vertex = {
9488
+ x: a.x + (b.x - a.x) * t,
9489
+ y: a.y + (b.y - a.y) * t,
9490
+ sx: a.sx + (b.sx - a.sx) * t,
9491
+ sy: a.sy + (b.sy - a.sy) * t,
9492
+ lon: interpolateLongitude(a.lon, b.lon, t),
9493
+ lat: a.lat + (b.lat - a.lat) * t
9494
+ };
9495
+ vertex[axis] = value;
9496
+ output.push(vertex);
9497
+ }
9498
+ if (bInside) output.push(copyRasterVertex(b, b.x, b.y));
9499
+ a = b;
9500
+ aInside = bInside;
9501
+ });
9502
+ return output;
9503
+ }
9504
+
9505
+ function copyRasterVertex(vertex, x, y) {
9506
+ return {
9507
+ x: x,
9508
+ y: y,
9509
+ sx: vertex.sx,
9510
+ sy: vertex.sy,
9511
+ lon: vertex.lon,
9512
+ lat: vertex.lat
9513
+ };
9514
+ }
9515
+
9516
+ function interpolateLongitude(a, b, t) {
9517
+ var delta = b - a;
9518
+ if (delta > 180) delta -= 360;
9519
+ if (delta < -180) delta += 360;
9520
+ return normalizeLongitude$1(a + delta * t);
9521
+ }
9522
+
9523
+ function getRingArea$2(ring) {
9524
+ var area = 0;
9525
+ for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
9526
+ area += ring[j][0] * ring[i][1] - ring[i][0] * ring[j][1];
9527
+ }
9528
+ return area / 2;
9529
+ }
9530
+
9531
+ function getPieceKey(face, copy) {
9532
+ return face + ':' + copy;
9533
+ }
9534
+
9535
+ function pointsEqual$1(a, b) {
9536
+ return Math.abs(a[0] - b[0]) < EPS && Math.abs(a[1] - b[1]) < EPS;
9537
+ }
9538
+
9539
+ function normalizeLongitude$1(lon) {
9540
+ lon = (lon + 180) % 360;
9541
+ if (lon < 0) lon += 360;
9542
+ return lon - 180;
9543
+ }
9544
+
8541
9545
  var mproj$1 = require$1('mproj');
8542
9546
  registerDymaxionProjections(mproj$1);
8543
9547
  registerButterflyProjections(mproj$1);
8544
9548
  registerNarukawa2022Projection(mproj$1);
9549
+ registerLeeTetrahedralProjections(mproj$1);
8545
9550
 
8546
9551
  var asyncLoader = null;
8547
9552
 
@@ -45620,7 +46625,7 @@ ${svg}
45620
46625
 
45621
46626
  function stopIfBufferReachesPole(shape, dist) {
45622
46627
  var maxAbsLat = 0;
45623
- var angularDist = dist / R$3 * R2D$6;
46628
+ var angularDist = dist / R$3 * R2D$7;
45624
46629
  (shape || []).forEach(function(path) {
45625
46630
  latLngPathIter.init(path);
45626
46631
  while (latLngPathIter.hasNext()) {
@@ -47737,12 +48742,12 @@ ${svg}
47737
48742
  }
47738
48743
 
47739
48744
  function projectBufferPoint(x, y, spherical) {
47740
- return spherical ? [x * D2R$7 * R$3, Math.log(Math.tan(Math.PI / 4 + y * D2R$7 / 2)) * R$3] :
48745
+ return spherical ? [x * D2R$8 * R$3, Math.log(Math.tan(Math.PI / 4 + y * D2R$8 / 2)) * R$3] :
47741
48746
  [x, y];
47742
48747
  }
47743
48748
 
47744
48749
  function unprojectBufferPoint(x, y, spherical) {
47745
- return spherical ? [x / (D2R$7 * R$3), (2 * Math.atan(Math.exp(y / R$3)) - Math.PI / 2) / (D2R$7)] :
48750
+ return spherical ? [x / (D2R$8 * R$3), (2 * Math.atan(Math.exp(y / R$3)) - Math.PI / 2) / (D2R$8)] :
47746
48751
  [x, y];
47747
48752
  }
47748
48753
 
@@ -52413,7 +53418,7 @@ ${svg}
52413
53418
  var maxAbsLat = Math.max(Math.abs(bounds.ymin), Math.abs(bounds.ymax));
52414
53419
  var maxPositiveDistance = getMaxPositiveBufferDistance(lyr, dataset, opts);
52415
53420
  if (!(maxPositiveDistance > 0)) return false;
52416
- return maxAbsLat + maxPositiveDistance / R$3 * R2D$6 >= 90 - POLAR_BUFFER_MARGIN_DEGREES;
53421
+ return maxAbsLat + maxPositiveDistance / R$3 * R2D$7 >= 90 - POLAR_BUFFER_MARGIN_DEGREES;
52417
53422
  }
52418
53423
 
52419
53424
  function getMaxPositiveBufferDistance(lyr, dataset, opts) {
@@ -53665,7 +54670,7 @@ ${svg}
53665
54670
  }
53666
54671
 
53667
54672
  function getCoordinateDistance(distance, arcs) {
53668
- return arcs.isPlanar() ? distance : distance / R$3 * R2D$6;
54673
+ return arcs.isPlanar() ? distance : distance / R$3 * R2D$7;
53669
54674
  }
53670
54675
 
53671
54676
  // @shapeIndex: chunk-bounds index of the source shape (see buildShapeSegmentIndex)
@@ -54334,7 +55339,7 @@ ${svg}
54334
55339
  // depending on parameters
54335
55340
  if (inList(P, 'cassini,gnom,bertin1953,chamb,ob_tran,tpeqd,healpix,rhealpix,' +
54336
55341
  'ocea,omerc,tmerc,etmerc,nicol,dymaxion,dymaxion2,butterfly,butterfly2,' +
54337
- 'cahill_keyes,narukawa2022')) {
55342
+ 'cahill_keyes,narukawa2022,markley,calm')) {
54338
55343
  return false;
54339
55344
  }
54340
55345
  if (isAzimuthal(P)) {
@@ -54386,16 +55391,16 @@ ${svg}
54386
55391
  }
54387
55392
 
54388
55393
  function getRotationFunction2(rotation, inv) {
54389
- var a = (rotation[0] || 0) * D2R$7,
54390
- b = (rotation[1] || 0) * D2R$7,
54391
- c = (rotation[2] || 0) * D2R$7;
55394
+ var a = (rotation[0] || 0) * D2R$8,
55395
+ b = (rotation[1] || 0) * D2R$8,
55396
+ c = (rotation[2] || 0) * D2R$8;
54392
55397
  return function(p) {
54393
- p[0] *= D2R$7;
54394
- p[1] *= D2R$7;
55398
+ p[0] *= D2R$8;
55399
+ p[1] *= D2R$8;
54395
55400
  var rotate = inv ? rotatePointInv : rotatePoint;
54396
55401
  rotate(p, a, b, c);
54397
- p[0] *= R2D$6;
54398
- p[1] *= R2D$6;
55402
+ p[0] *= R2D$7;
55403
+ p[1] *= R2D$7;
54399
55404
  return p;
54400
55405
  };
54401
55406
  }
@@ -54875,7 +55880,19 @@ ${svg}
54875
55880
  type: o.type,
54876
55881
  coordinates: rotatePath(o.coordinates, lon0)
54877
55882
  };
54878
- })
55883
+ }),
55884
+ findRegion: function(lon, lat) {
55885
+ return findClassicRegion(defn, normalizeLongitude(lon - lon0), lat);
55886
+ },
55887
+ findTransitionRegion: function(lon, lat) {
55888
+ return findClassicRegion(defn, normalizeLongitude(lon - lon0), lat);
55889
+ },
55890
+ constrainRegionPoint: function(lon, lat, regionId) {
55891
+ return constrainClassicRegionPoint(defn, lon0, lon, lat, regionId);
55892
+ },
55893
+ getRegionBoundary: function(regionId) {
55894
+ return getClassicRegionBoundary(defn, lon0, regionId, 0.5);
55895
+ }
54879
55896
  };
54880
55897
  }
54881
55898
 
@@ -54905,6 +55922,68 @@ ${svg}
54905
55922
  };
54906
55923
  }
54907
55924
 
55925
+ function findClassicRegion(defn, lon, lat) {
55926
+ for (var i = 0; i < defn.regions.length; i++) {
55927
+ var region = defn.regions[i];
55928
+ var ring = region.boundary;
55929
+ if (lon >= ring[0][0] && lon <= ring[2][0] &&
55930
+ lat >= ring[0][1] && lat <= ring[2][1]) {
55931
+ return region.id;
55932
+ }
55933
+ }
55934
+ return null;
55935
+ }
55936
+
55937
+ function constrainClassicRegionPoint(defn, lon0, lon, lat, regionId) {
55938
+ var region = findRegionById(defn, regionId);
55939
+ if (!region) return null;
55940
+ var ring = region.boundary;
55941
+ var xmin = ring[0][0];
55942
+ var ymin = ring[0][1];
55943
+ var xmax = ring[2][0];
55944
+ var ymax = ring[2][1];
55945
+ var localLon = normalizeLongitude(lon - lon0);
55946
+ var x = Math.max(xmin, Math.min(xmax, localLon));
55947
+ var y = Math.max(ymin, Math.min(ymax, lat));
55948
+ var cx = (xmin + xmax) / 2;
55949
+ var cy = (ymin + ymax) / 2;
55950
+ var inset = 1e-8;
55951
+ if (x == xmin || x == xmax) x += (cx - x) * inset;
55952
+ if (y == ymin || y == ymax) y += (cy - y) * inset;
55953
+ return [normalizeLongitude(x + lon0), y];
55954
+ }
55955
+
55956
+ function getClassicRegionBoundary(defn, lon0, regionId, interval) {
55957
+ var region = findRegionById(defn, regionId);
55958
+ if (!region) return null;
55959
+ var ring = region.boundary;
55960
+ var corners = [ring[0], ring[1], ring[2], ring[3], ring[0]];
55961
+ var points = [];
55962
+ for (var i = 1; i < corners.length; i++) {
55963
+ var a = corners[i - 1];
55964
+ var b = corners[i];
55965
+ var n = Math.max(1, Math.ceil(Math.max(
55966
+ Math.abs(b[0] - a[0]),
55967
+ Math.abs(b[1] - a[1])
55968
+ ) / interval));
55969
+ for (var j = 0; j < n; j++) {
55970
+ points.push([
55971
+ normalizeLongitude(a[0] + (b[0] - a[0]) * j / n + lon0),
55972
+ a[1] + (b[1] - a[1]) * j / n
55973
+ ]);
55974
+ }
55975
+ }
55976
+ points.push(points[0].concat());
55977
+ return points;
55978
+ }
55979
+
55980
+ function findRegionById(defn, regionId) {
55981
+ for (var i = 0; i < defn.regions.length; i++) {
55982
+ if (defn.regions[i].id == regionId) return defn.regions[i];
55983
+ }
55984
+ return null;
55985
+ }
55986
+
54908
55987
  function cutSeam(coordinates) {
54909
55988
  return {
54910
55989
  type: 'cut',
@@ -55611,6 +56690,13 @@ ${svg}
55611
56690
 
55612
56691
  var DEFAULT_MESH_INTERVAL = 32;
55613
56692
  var DEFAULT_MAX_EDGE_FACTOR = 20;
56693
+ var DEFAULT_TOPOLOGY_MIN_CELL_SIZE = 0.5;
56694
+ var MAX_TOPOLOGY_SUBDIVISION_DEPTH = 12;
56695
+ var TOPOLOGY_SAMPLE_STEPS = 4;
56696
+ var TOPOLOGY_VERTEX_INSET = 1e-7;
56697
+ var PIECE_SAMPLE_STEPS = 4;
56698
+ var EXPANDED_FACET_MAX_EDGE_DEGREES = 2;
56699
+ var EXPANDED_FACET_MAX_CLIP_ERROR = 0.02;
55614
56700
 
55615
56701
  function projectRasterGridForward(raster, srcCRS, destCRS, optsArg) {
55616
56702
  var opts = optsArg || {};
@@ -55621,8 +56707,8 @@ ${svg}
55621
56707
  var mesh, bbox, outSize, outGrid;
55622
56708
  validateRasterGridForProjection(grid);
55623
56709
  timeStart(timing, 'mesh');
55624
- mesh = buildProjectedRasterMesh(grid, transform, interval);
55625
- classifyProjectedMeshCells(mesh, opts);
56710
+ mesh = buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts);
56711
+ classifyRasterMesh(mesh, opts);
55626
56712
  timeEnd(timing, 'mesh');
55627
56713
  bbox = opts.output_bbox || opts.outputBbox || getProjectedMeshBBox(mesh);
55628
56714
  if (!bbox) stop$1('Unable to project raster layer');
@@ -55630,12 +56716,17 @@ ${svg}
55630
56716
  outGrid = createProjectedRasterGrid(grid, raster, bbox, outSize.width, outSize.height, opts);
55631
56717
  timeStart(timing, 'rasterize');
55632
56718
  rasterizeProjectedMesh(grid, outGrid, mesh, getRasterProjectionSampleMethod(raster, opts));
56719
+ if (mesh.fillOutputCoverage) {
56720
+ fillProjectedRasterCoverage(outGrid);
56721
+ } else {
56722
+ fillIsolatedProjectedRasterHoles(outGrid);
56723
+ }
55633
56724
  timeEnd(timing, 'rasterize');
55634
56725
  if (timing) {
55635
56726
  timing.outputWidth = outGrid.width;
55636
56727
  timing.outputHeight = outGrid.height;
55637
56728
  timing.meshVertices = mesh.vertices.length;
55638
- timing.meshCells = mesh.cells.length;
56729
+ timing.meshCells = mesh.triangles ? mesh.triangles.length : mesh.cells.length;
55639
56730
  timing.meshSkippedCells = mesh.skippedCellCount;
55640
56731
  }
55641
56732
  return outGrid;
@@ -55672,17 +56763,34 @@ ${svg}
55672
56763
  var transform = getProjTransform2(srcCRS, destCRS);
55673
56764
  var mesh, bbox;
55674
56765
  validateRasterGridForProjection(grid);
55675
- mesh = buildProjectedRasterMesh(grid, transform, interval);
55676
- classifyProjectedMeshCells(mesh, opts);
56766
+ mesh = buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts);
56767
+ classifyRasterMesh(mesh, opts);
55677
56768
  bbox = getProjectedMeshBBox(mesh);
55678
56769
  return bbox;
55679
56770
  }
55680
56771
 
55681
56772
  function getProjectedRasterMeshBBox(mesh, optsArg) {
55682
- classifyProjectedMeshCells(mesh, optsArg || {});
56773
+ classifyRasterMesh(mesh, optsArg || {});
55683
56774
  return getProjectedMeshBBox(mesh);
55684
56775
  }
55685
56776
 
56777
+ function buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts) {
56778
+ var topology = getProjectionTopology(destCRS);
56779
+ if (topology && (topology.raster_source_regions ||
56780
+ topology.raster_spherical_regions)) {
56781
+ return buildExpandedFacetRasterMesh(
56782
+ grid, srcCRS, destCRS, interval, topology);
56783
+ }
56784
+ if (topology && (topology.projectRasterRegion ||
56785
+ topology.projectRegion || topology.constrainRegionPoint)) {
56786
+ return buildPiecewiseProjectedRasterMesh(grid, srcCRS, destCRS, interval, topology);
56787
+ }
56788
+ if (topology && (topology.findTransitionRegion || topology.findRegion)) {
56789
+ return buildTopologyAwareProjectedRasterMesh(grid, srcCRS, destCRS, interval, opts);
56790
+ }
56791
+ return buildProjectedRasterMesh(grid, transform, interval);
56792
+ }
56793
+
55686
56794
  function buildProjectedRasterMesh(grid, transform, interval) {
55687
56795
  var xs = getMeshStops(grid.width, interval);
55688
56796
  var ys = getMeshStops(grid.height, interval);
@@ -55699,6 +56807,494 @@ ${svg}
55699
56807
  };
55700
56808
  }
55701
56809
 
56810
+ function buildPiecewiseProjectedRasterMesh(grid, srcCRS, destCRS, interval, topology) {
56811
+ var wgs84 = parseCrsString$1('wgs84');
56812
+ var toGeographic = getProjTransform2(srcCRS, wgs84);
56813
+ var fromGeographic = getProjTransform2(wgs84, srcCRS);
56814
+ var toDestination = getProjTransform2(wgs84, destCRS);
56815
+ interval = Math.min(interval, topology.raster_mesh_interval || interval);
56816
+ var xs = getMeshStops(grid.width, interval);
56817
+ var ys = getMeshStops(grid.height, interval);
56818
+ var regions = topology.raster_regions || topology.regions;
56819
+ var mesh = {
56820
+ xs: xs,
56821
+ ys: ys,
56822
+ vertices: [],
56823
+ cells: [],
56824
+ topologyAware: true,
56825
+ subdivisionSkippedCellCount: 0,
56826
+ fillRegionMask: topology.fill_raster_mask,
56827
+ fillOutputCoverage: topology.fill_raster_coverage,
56828
+ projectedRegions: getProjectedRasterRegions(
56829
+ topology, regions, destCRS, toDestination)
56830
+ };
56831
+ var context = {
56832
+ grid: grid,
56833
+ topology: topology,
56834
+ destCRS: destCRS,
56835
+ toGeographic: toGeographic,
56836
+ fromGeographic: fromGeographic,
56837
+ toDestination: toDestination,
56838
+ findRegion: topology.findRasterRegion || topology.findRegion,
56839
+ projectRegion: topology.projectRasterRegion || topology.projectRegion,
56840
+ pieceHalo: topology.raster_cell_halo === false ? 0 : interval,
56841
+ mesh: mesh
56842
+ };
56843
+ for (var y = 0; y < ys.length - 1; y++) {
56844
+ for (var x = 0; x < xs.length - 1; x++) {
56845
+ appendPiecewiseMeshCells(context, xs[x], ys[y], xs[x + 1], ys[y + 1]);
56846
+ }
56847
+ }
56848
+ return mesh;
56849
+ }
56850
+
56851
+ function buildExpandedFacetRasterMesh(grid, srcCRS, destCRS, interval, topology) {
56852
+ var wgs84 = parseCrsString$1('wgs84');
56853
+ var fromGeographic = getProjTransform2(wgs84, srcCRS);
56854
+ var regions = topology.raster_regions;
56855
+ var mesh = {
56856
+ vertices: [],
56857
+ cells: [],
56858
+ triangles: [],
56859
+ topologyAware: true,
56860
+ subdivisionSkippedCellCount: 0,
56861
+ fillRegionMask: topology.fill_raster_mask,
56862
+ fillOutputCoverage: topology.fill_raster_coverage,
56863
+ projectedRegions: getProjectedRasterRegions(
56864
+ topology, regions, destCRS, getProjTransform2(wgs84, destCRS)),
56865
+ sourceWrapX: isLatLngCRS(srcCRS) &&
56866
+ Math.abs(grid.bbox[2] - grid.bbox[0] - 360) < 1e-3
56867
+ };
56868
+ var sourceRegions = topology.raster_source_regions ||
56869
+ topology.raster_spherical_regions;
56870
+ var piecesBySourceRegion = new Map();
56871
+ regions.forEach(function(region) {
56872
+ var key = getRasterSourceRegionKey(region);
56873
+ var pieces = piecesBySourceRegion.get(key) || [];
56874
+ pieces.push(region);
56875
+ piecesBySourceRegion.set(key, pieces);
56876
+ });
56877
+ var context = {
56878
+ grid: grid,
56879
+ topology: topology,
56880
+ destCRS: destCRS,
56881
+ fromGeographic: fromGeographic,
56882
+ mesh: mesh
56883
+ };
56884
+ sourceRegions.forEach(function(region) {
56885
+ var boundary = region.boundary;
56886
+ var pieces = piecesBySourceRegion.get(getRasterSourceRegionKey(region));
56887
+ var triangles = [];
56888
+ var end = pointsEqual2D(boundary[0], boundary[boundary.length - 1]) ?
56889
+ boundary.length - 1 : boundary.length;
56890
+ for (var i = 1; i < end - 1; i++) {
56891
+ triangles.push([boundary[0], boundary[i], boundary[i + 1]]);
56892
+ }
56893
+ triangles.forEach(function(triangle) {
56894
+ var depth = getSphericalTriangleSubdivisionDepth(
56895
+ triangle, EXPANDED_FACET_MAX_EDGE_DEGREES);
56896
+ subdivideSphericalRasterTriangle(
56897
+ context, triangle, region, pieces, depth);
56898
+ });
56899
+ });
56900
+ return mesh;
56901
+ }
56902
+
56903
+ function getRasterSourceRegionKey(region) {
56904
+ if (region.source_region != null) return String(region.source_region);
56905
+ if (region.facet != null && region.sector != null) {
56906
+ return region.facet + ':' + region.sector;
56907
+ }
56908
+ return String(region.id);
56909
+ }
56910
+
56911
+ function pointsEqual2D(a, b) {
56912
+ return a && b && Math.abs(a[0] - b[0]) < 1e-10 &&
56913
+ Math.abs(a[1] - b[1]) < 1e-10;
56914
+ }
56915
+
56916
+ function getSphericalTriangleSubdivisionDepth(triangle, maxDegrees) {
56917
+ var max = Math.max(
56918
+ sphericalPointDistance(triangle[0], triangle[1]),
56919
+ sphericalPointDistance(triangle[1], triangle[2]),
56920
+ sphericalPointDistance(triangle[2], triangle[0])
56921
+ );
56922
+ return Math.max(0, Math.ceil(Math.log(max / maxDegrees) / Math.LN2));
56923
+ }
56924
+
56925
+ function subdivideSphericalRasterTriangle(context, triangle, region, pieces, depth) {
56926
+ if (depth > 0) {
56927
+ var ab = sphericalPointMidpoint(triangle[0], triangle[1]);
56928
+ var bc = sphericalPointMidpoint(triangle[1], triangle[2]);
56929
+ var ca = sphericalPointMidpoint(triangle[2], triangle[0]);
56930
+ subdivideSphericalRasterTriangle(
56931
+ context, [triangle[0], ab, ca], region, pieces, depth - 1);
56932
+ subdivideSphericalRasterTriangle(
56933
+ context, [ab, triangle[1], bc], region, pieces, depth - 1);
56934
+ subdivideSphericalRasterTriangle(
56935
+ context, [ca, bc, triangle[2]], region, pieces, depth - 1);
56936
+ subdivideSphericalRasterTriangle(
56937
+ context, [ab, bc, ca], region, pieces, depth - 1);
56938
+ return;
56939
+ }
56940
+ var rawVertices = triangle.map(function(lonlat) {
56941
+ return projectSphericalRawVertex(context, lonlat, region);
56942
+ });
56943
+ normalizeWrappedTrianglePixels(
56944
+ rawVertices, context.grid.width, context.mesh.sourceWrapX);
56945
+ pieces.forEach(function(piece) {
56946
+ var polygon = context.topology.clipRasterRegionPolygon(
56947
+ rawVertices, piece.id);
56948
+ if (!rasterPiecePolygonIsAccurate(
56949
+ context.topology, polygon, piece.id)) return;
56950
+ polygon.forEach(function(vertex) {
56951
+ var p = scaleRawProjectionPoint(
56952
+ context.destCRS, [vertex.x, vertex.y]);
56953
+ vertex.x = p[0];
56954
+ vertex.y = p[1];
56955
+ });
56956
+ for (var i = 1; i < polygon.length - 1; i++) {
56957
+ var vertices = [polygon[0], polygon[i], polygon[i + 1]];
56958
+ context.mesh.vertices.push(vertices[0], vertices[1], vertices[2]);
56959
+ context.mesh.triangles.push({
56960
+ a: vertices[0],
56961
+ b: vertices[1],
56962
+ c: vertices[2],
56963
+ region: piece.id,
56964
+ valid: vertices.every(vertexIsValid)
56965
+ });
56966
+ }
56967
+ });
56968
+ }
56969
+
56970
+ function projectSphericalRawVertex(context, lonlat, region) {
56971
+ var sourceXY = context.fromGeographic(lonlat[0], lonlat[1]);
56972
+ var sourcePixel = sourceXY &&
56973
+ rasterMapXYToPixel(context.grid, sourceXY[0], sourceXY[1]);
56974
+ var p = context.topology.projectRasterSourceRegion ?
56975
+ context.topology.projectRasterSourceRegion(
56976
+ lonlat[0], lonlat[1], region.id) :
56977
+ context.topology.projectRasterSector(
56978
+ lonlat[0], lonlat[1], region.facet, region.sector);
56979
+ return {
56980
+ sx: sourcePixel ? sourcePixel[0] : NaN,
56981
+ sy: sourcePixel ? sourcePixel[1] : NaN,
56982
+ x: p && isFinite(p[0]) ? p[0] : NaN,
56983
+ y: p && isFinite(p[1]) ? p[1] : NaN,
56984
+ lon: lonlat[0],
56985
+ lat: lonlat[1]
56986
+ };
56987
+ }
56988
+
56989
+ function rasterPiecePolygonIsAccurate(topology, polygon, regionId) {
56990
+ // A triangle that crosses a forced sector discontinuity can yield invalid
56991
+ // interpolated clip vertices. Adjacent triangles cover the rejected sliver.
56992
+ return polygon.every(function(vertex) {
56993
+ var p = topology.projectRasterRegion(
56994
+ vertex.lon, vertex.lat, regionId);
56995
+ return p && Math.hypot(vertex.x - p[0], vertex.y - p[1]) <
56996
+ EXPANDED_FACET_MAX_CLIP_ERROR;
56997
+ });
56998
+ }
56999
+
57000
+ function normalizeWrappedTrianglePixels(vertices, width, wrap) {
57001
+ if (!wrap) return;
57002
+ var xmin = Math.min(vertices[0].sx, vertices[1].sx, vertices[2].sx);
57003
+ var xmax = Math.max(vertices[0].sx, vertices[1].sx, vertices[2].sx);
57004
+ if (xmax - xmin <= width / 2) return;
57005
+ vertices.forEach(function(vertex) {
57006
+ if (vertex.sx < width / 2) vertex.sx += width;
57007
+ });
57008
+ }
57009
+
57010
+ function sphericalPointMidpoint(a, b) {
57011
+ var av = lonLatToVector(a);
57012
+ var bv = lonLatToVector(b);
57013
+ return vectorToLonLat(normalizeVector3([
57014
+ av[0] + bv[0],
57015
+ av[1] + bv[1],
57016
+ av[2] + bv[2]
57017
+ ]));
57018
+ }
57019
+
57020
+ function sphericalPointDistance(a, b) {
57021
+ var av = lonLatToVector(a);
57022
+ var bv = lonLatToVector(b);
57023
+ return Math.acos(clamp$1(
57024
+ av[0] * bv[0] + av[1] * bv[1] + av[2] * bv[2], -1, 1
57025
+ )) * 180 / Math.PI;
57026
+ }
57027
+
57028
+ function lonLatToVector(p) {
57029
+ var lam = p[0] * Math.PI / 180;
57030
+ var phi = p[1] * Math.PI / 180;
57031
+ var cosPhi = Math.cos(phi);
57032
+ return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
57033
+ }
57034
+
57035
+ function vectorToLonLat(p) {
57036
+ return [
57037
+ Math.atan2(p[1], p[0]) * 180 / Math.PI,
57038
+ Math.asin(clamp$1(p[2], -1, 1)) * 180 / Math.PI
57039
+ ];
57040
+ }
57041
+
57042
+ function normalizeVector3(p) {
57043
+ var k = 1 / Math.hypot(p[0], p[1], p[2]);
57044
+ return [p[0] * k, p[1] * k, p[2] * k];
57045
+ }
57046
+
57047
+ function appendPiecewiseMeshCells(context, x0, y0, x1, y1) {
57048
+ getPieceRegionsInCell(context, x0, y0, x1, y1).forEach(function(regionId) {
57049
+ var v00 = projectPiecewiseMeshVertex(context, x0, y0, regionId);
57050
+ var v10 = projectPiecewiseMeshVertex(context, x1, y0, regionId);
57051
+ var v01 = projectPiecewiseMeshVertex(context, x0, y1, regionId);
57052
+ var v11 = projectPiecewiseMeshVertex(context, x1, y1, regionId);
57053
+ var cell = {
57054
+ v00: v00,
57055
+ v10: v10,
57056
+ v01: v01,
57057
+ v11: v11,
57058
+ region: regionId,
57059
+ valid: vertexIsValid(v00) && vertexIsValid(v10) &&
57060
+ vertexIsValid(v01) && vertexIsValid(v11)
57061
+ };
57062
+ context.mesh.vertices.push(v00, v10, v01, v11);
57063
+ context.mesh.cells.push(cell);
57064
+ });
57065
+ }
57066
+
57067
+ function getPieceRegionsInCell(context, x0, y0, x1, y1) {
57068
+ var ids = [];
57069
+ var halo = context.pieceHalo;
57070
+ samplePieceRegions(context, ids, x0, y0, x1, y1);
57071
+ if (halo > 0) {
57072
+ samplePieceRegions(
57073
+ context,
57074
+ ids,
57075
+ Math.max(0, x0 - halo),
57076
+ Math.max(0, y0 - halo),
57077
+ Math.min(context.grid.width, x1 + halo),
57078
+ Math.min(context.grid.height, y1 + halo)
57079
+ );
57080
+ }
57081
+ return ids;
57082
+ }
57083
+
57084
+ function samplePieceRegions(context, ids, x0, y0, x1, y1) {
57085
+ for (var iy = 0; iy <= PIECE_SAMPLE_STEPS; iy++) {
57086
+ for (var ix = 0; ix <= PIECE_SAMPLE_STEPS; ix++) {
57087
+ var px = x0 + (x1 - x0) * ix / PIECE_SAMPLE_STEPS;
57088
+ var py = y0 + (y1 - y0) * iy / PIECE_SAMPLE_STEPS;
57089
+ var xy = rasterPixelToMapXY(context.grid, px, py);
57090
+ var lonlat = context.toGeographic(xy[0], xy[1]);
57091
+ var id = lonlat && context.findRegion(lonlat[0], lonlat[1]);
57092
+ if (id != null && id !== -1 && ids.indexOf(id) == -1) ids.push(id);
57093
+ }
57094
+ }
57095
+ }
57096
+
57097
+ function projectPiecewiseMeshVertex(context, px, py, regionId) {
57098
+ var xy = rasterPixelToMapXY(context.grid, px, py);
57099
+ var lonlat = context.toGeographic(xy[0], xy[1]);
57100
+ var p, sourcePixel;
57101
+ if (!lonlat) return {sx: px, sy: py, x: NaN, y: NaN};
57102
+ if (context.projectRegion) {
57103
+ p = context.projectRegion(lonlat[0], lonlat[1], regionId);
57104
+ p = scaleRawProjectionPoint(context.destCRS, p);
57105
+ sourcePixel = [px, py];
57106
+ } else {
57107
+ lonlat = context.topology.constrainRegionPoint(lonlat[0], lonlat[1], regionId);
57108
+ xy = lonlat && context.fromGeographic(lonlat[0], lonlat[1]);
57109
+ p = lonlat && context.toDestination(lonlat[0], lonlat[1]);
57110
+ sourcePixel = xy && rasterMapXYToPixel(context.grid, xy[0], xy[1]);
57111
+ }
57112
+ return {
57113
+ sx: sourcePixel ? sourcePixel[0] : px,
57114
+ sy: sourcePixel ? sourcePixel[1] : py,
57115
+ x: p && isFinite(p[0]) ? p[0] : NaN,
57116
+ y: p && isFinite(p[1]) ? p[1] : NaN
57117
+ };
57118
+ }
57119
+
57120
+ function getProjectedRasterRegions(topology, regions, destCRS, toDestination) {
57121
+ return regions.map(function(region) {
57122
+ var boundary;
57123
+ if (region.projected_boundary) {
57124
+ boundary = region.projected_boundary.map(function(p) {
57125
+ return scaleRawProjectionPoint(destCRS, p);
57126
+ });
57127
+ } else {
57128
+ boundary = topology.getRegionBoundary(region.id).map(function(p) {
57129
+ var q = topology.constrainRegionPoint(p[0], p[1], region.id);
57130
+ return toDestination(q[0], q[1]);
57131
+ });
57132
+ }
57133
+ return {
57134
+ id: region.id,
57135
+ boundary: boundary
57136
+ };
57137
+ });
57138
+ }
57139
+
57140
+ function scaleRawProjectionPoint(P, p) {
57141
+ if (!p) return null;
57142
+ return [
57143
+ P.fr_meter * (P.a * p[0] + P.x0),
57144
+ P.fr_meter * (P.a * p[1] + P.y0)
57145
+ ];
57146
+ }
57147
+
57148
+ function buildTopologyAwareProjectedRasterMesh(grid, srcCRS, destCRS, interval, optsArg) {
57149
+ var opts = optsArg || {};
57150
+ var topology = getProjectionTopology(destCRS);
57151
+ var findRegion = topology && (topology.findTransitionRegion || topology.findRegion);
57152
+ var wgs84 = parseCrsString$1('wgs84');
57153
+ var toGeographic = getProjTransform2(srcCRS, wgs84);
57154
+ var toDestination = getProjTransform2(wgs84, destCRS);
57155
+ var xs = getMeshStops(grid.width, interval);
57156
+ var ys = getMeshStops(grid.height, interval);
57157
+ var minCellSize = opts.raster_topology_min_cell_size ||
57158
+ opts.rasterTopologyMinCellSize ||
57159
+ DEFAULT_TOPOLOGY_MIN_CELL_SIZE;
57160
+ var mesh = {
57161
+ xs: xs,
57162
+ ys: ys,
57163
+ vertices: [],
57164
+ cells: [],
57165
+ topologyAware: true,
57166
+ subdivisionSkippedCellCount: 0
57167
+ };
57168
+ var context = {
57169
+ grid: grid,
57170
+ findRegion: findRegion,
57171
+ toGeographic: toGeographic,
57172
+ toDestination: toDestination,
57173
+ minCellSize: Math.max(0.01, minCellSize),
57174
+ maxDepth: MAX_TOPOLOGY_SUBDIVISION_DEPTH,
57175
+ mesh: mesh
57176
+ };
57177
+ if (!findRegion) return buildProjectedRasterMesh(grid, getProjTransform2(srcCRS, destCRS), interval);
57178
+ for (var y = 0; y < ys.length - 1; y++) {
57179
+ for (var x = 0; x < xs.length - 1; x++) {
57180
+ addTopologyMeshCell(context, xs[x], ys[y], xs[x + 1], ys[y + 1], 0);
57181
+ }
57182
+ }
57183
+ return mesh;
57184
+ }
57185
+
57186
+ function addTopologyMeshCell(context, x0, y0, x1, y1, depth) {
57187
+ var classification = classifyTopologyCell(context, x0, y0, x1, y1);
57188
+ var width = x1 - x0;
57189
+ var height = y1 - y0;
57190
+ var splitX = width > context.minCellSize && depth < context.maxDepth;
57191
+ var splitY = height > context.minCellSize && depth < context.maxDepth;
57192
+ if (classification.mixed && (splitX || splitY)) {
57193
+ subdivideTopologyMeshCell(context, x0, y0, x1, y1, depth, splitX, splitY);
57194
+ return;
57195
+ }
57196
+ if (classification.region == null || classification.mixed) {
57197
+ context.mesh.subdivisionSkippedCellCount++;
57198
+ return;
57199
+ }
57200
+ appendTopologyMeshCell(context, x0, y0, x1, y1, classification.region);
57201
+ }
57202
+
57203
+ function subdivideTopologyMeshCell(context, x0, y0, x1, y1, depth, splitX, splitY) {
57204
+ var xm = splitX ? (x0 + x1) / 2 : x1;
57205
+ var ym = splitY ? (y0 + y1) / 2 : y1;
57206
+ addTopologyMeshCell(context, x0, y0, xm, ym, depth + 1);
57207
+ if (splitX) addTopologyMeshCell(context, xm, y0, x1, ym, depth + 1);
57208
+ if (splitY) addTopologyMeshCell(context, x0, ym, xm, y1, depth + 1);
57209
+ if (splitX && splitY) addTopologyMeshCell(context, xm, ym, x1, y1, depth + 1);
57210
+ }
57211
+
57212
+ function classifyTopologyCell(context, x0, y0, x1, y1) {
57213
+ var cx = (x0 + x1) / 2;
57214
+ var cy = (y0 + y1) / 2;
57215
+ var region = getTopologyRegionAtPixel(context, cx, cy);
57216
+ var mixed = false;
57217
+ for (var iy = 0; iy <= TOPOLOGY_SAMPLE_STEPS && !mixed; iy++) {
57218
+ for (var ix = 0; ix <= TOPOLOGY_SAMPLE_STEPS; ix++) {
57219
+ var px = x0 + (x1 - x0) * ix / TOPOLOGY_SAMPLE_STEPS;
57220
+ var py = y0 + (y1 - y0) * iy / TOPOLOGY_SAMPLE_STEPS;
57221
+ px += (cx - px) * TOPOLOGY_VERTEX_INSET;
57222
+ py += (cy - py) * TOPOLOGY_VERTEX_INSET;
57223
+ if (getTopologyRegionAtPixel(context, px, py) !== region) {
57224
+ mixed = true;
57225
+ break;
57226
+ }
57227
+ }
57228
+ }
57229
+ return {region: region, mixed: mixed};
57230
+ }
57231
+
57232
+ function getTopologyRegionAtPixel(context, px, py) {
57233
+ var xy = rasterPixelToMapXY(context.grid, px, py);
57234
+ var lonlat = context.toGeographic(xy[0], xy[1]);
57235
+ if (!lonlat) return null;
57236
+ return context.findRegion(lonlat[0], lonlat[1]);
57237
+ }
57238
+
57239
+ function appendTopologyMeshCell(context, x0, y0, x1, y1, region) {
57240
+ var cx = (x0 + x1) / 2;
57241
+ var cy = (y0 + y1) / 2;
57242
+ var v00 = projectTopologyMeshVertex(context, x0, y0, cx, cy);
57243
+ var v10 = projectTopologyMeshVertex(context, x1, y0, cx, cy);
57244
+ var v01 = projectTopologyMeshVertex(context, x0, y1, cx, cy);
57245
+ var v11 = projectTopologyMeshVertex(context, x1, y1, cx, cy);
57246
+ var cell = {
57247
+ v00: v00,
57248
+ v10: v10,
57249
+ v01: v01,
57250
+ v11: v11,
57251
+ region: region,
57252
+ valid: vertexIsValid(v00) && vertexIsValid(v10) &&
57253
+ vertexIsValid(v01) && vertexIsValid(v11)
57254
+ };
57255
+ context.mesh.vertices.push(v00, v10, v01, v11);
57256
+ context.mesh.cells.push(cell);
57257
+ }
57258
+
57259
+ function projectTopologyMeshVertex(context, px, py, cx, cy) {
57260
+ var insetX = px + (cx - px) * TOPOLOGY_VERTEX_INSET;
57261
+ var insetY = py + (cy - py) * TOPOLOGY_VERTEX_INSET;
57262
+ var xy = rasterPixelToMapXY(context.grid, insetX, insetY);
57263
+ var lonlat = context.toGeographic(xy[0], xy[1]);
57264
+ var p = lonlat && context.toDestination(lonlat[0], lonlat[1]);
57265
+ return {
57266
+ sx: px,
57267
+ sy: py,
57268
+ x: p && isFinite(p[0]) ? p[0] : NaN,
57269
+ y: p && isFinite(p[1]) ? p[1] : NaN
57270
+ };
57271
+ }
57272
+
57273
+ function classifyRasterMesh(mesh, opts) {
57274
+ if (mesh.topologyAware) {
57275
+ classifyTopologyMeshCells(mesh);
57276
+ } else {
57277
+ classifyProjectedMeshCells(mesh, opts);
57278
+ }
57279
+ }
57280
+
57281
+ function classifyTopologyMeshCells(mesh) {
57282
+ var filtered = 0;
57283
+ mesh.cells.forEach(function(cell) {
57284
+ cell.maxEdge = getCellMaxEdge(cell);
57285
+ if (!cell.valid) {
57286
+ cell.valid = false;
57287
+ filtered++;
57288
+ }
57289
+ });
57290
+ // Topology-aware cells never span projection branches. Do not apply the
57291
+ // regular mesh's median-edge outlier filter here: adaptive subdivision
57292
+ // creates many small boundary cells that would make valid interior cells
57293
+ // appear to be outliers.
57294
+ mesh.maxEdge = Infinity;
57295
+ mesh.skippedCellCount = mesh.subdivisionSkippedCellCount + filtered;
57296
+ }
57297
+
55702
57298
  function classifyProjectedMeshCells(mesh, opts) {
55703
57299
  var cols = mesh.xs.length;
55704
57300
  var cells = [];
@@ -55882,17 +57478,41 @@ ${svg}
55882
57478
  ];
55883
57479
  }
55884
57480
 
57481
+ function rasterMapXYToPixel(grid, x, y) {
57482
+ var t = grid.transform;
57483
+ if (t) {
57484
+ return [
57485
+ (x - t[2]) / t[0],
57486
+ (y - t[5]) / t[4]
57487
+ ];
57488
+ }
57489
+ return [
57490
+ (x - grid.bbox[0]) / (grid.bbox[2] - grid.bbox[0]) * grid.width,
57491
+ (grid.bbox[3] - y) / (grid.bbox[3] - grid.bbox[1]) * grid.height
57492
+ ];
57493
+ }
57494
+
55885
57495
  function getProjectedMeshBBox(mesh) {
55886
57496
  var xmin = Infinity, ymin = Infinity, xmax = -Infinity, ymax = -Infinity;
55887
- mesh.cells.forEach(function(cell) {
55888
- if (!cell.valid) return;
55889
- [cell.v00, cell.v10, cell.v01, cell.v11].forEach(function(p) {
55890
- if (p.x < xmin) xmin = p.x;
55891
- if (p.x > xmax) xmax = p.x;
55892
- if (p.y < ymin) ymin = p.y;
55893
- if (p.y > ymax) ymax = p.y;
57497
+ if (mesh.projectedRegions) {
57498
+ mesh.projectedRegions.forEach(function(region) {
57499
+ region.boundary.forEach(expand);
55894
57500
  });
55895
- });
57501
+ } else {
57502
+ mesh.cells.forEach(function(cell) {
57503
+ if (!cell.valid) return;
57504
+ [cell.v00, cell.v10, cell.v01, cell.v11].forEach(expand);
57505
+ });
57506
+ }
57507
+ function expand(p) {
57508
+ if (!p) return;
57509
+ var x = Array.isArray(p) ? p[0] : p.x;
57510
+ var y = Array.isArray(p) ? p[1] : p.y;
57511
+ if (x < xmin) xmin = x;
57512
+ if (x > xmax) xmax = x;
57513
+ if (y < ymin) ymin = y;
57514
+ if (y > ymax) ymax = y;
57515
+ }
55896
57516
  return xmin < Infinity && xmax > xmin && ymax > ymin ? [xmin, ymin, xmax, ymax] : null;
55897
57517
  }
55898
57518
 
@@ -55985,14 +57605,151 @@ ${svg}
55985
57605
  }
55986
57606
 
55987
57607
  function rasterizeProjectedMesh(srcGrid, destGrid, mesh, sampleMethod) {
57608
+ var regionData = mesh.projectedRegions ?
57609
+ createProjectedRegionMask(
57610
+ destGrid, mesh.projectedRegions, mesh.fillRegionMask) :
57611
+ null;
57612
+ (mesh.triangles || []).forEach(function(triangle) {
57613
+ if (!triangle.valid) return;
57614
+ var regionValue = regionData && regionData.values.get(triangle.region);
57615
+ rasterizeProjectedTriangle(
57616
+ srcGrid, destGrid, triangle.a, triangle.b, triangle.c,
57617
+ sampleMethod, regionData && regionData.mask, regionValue,
57618
+ mesh.sourceWrapX
57619
+ );
57620
+ });
55988
57621
  mesh.cells.forEach(function(cell) {
55989
57622
  if (!cell.valid) return;
55990
- rasterizeProjectedTriangle(srcGrid, destGrid, cell.v00, cell.v10, cell.v11, sampleMethod);
55991
- rasterizeProjectedTriangle(srcGrid, destGrid, cell.v00, cell.v11, cell.v01, sampleMethod);
57623
+ var regionValue = regionData && regionData.values.get(cell.region);
57624
+ rasterizeProjectedTriangle(
57625
+ srcGrid, destGrid, cell.v00, cell.v10, cell.v11,
57626
+ sampleMethod, regionData && regionData.mask, regionValue, false
57627
+ );
57628
+ rasterizeProjectedTriangle(
57629
+ srcGrid, destGrid, cell.v00, cell.v11, cell.v01,
57630
+ sampleMethod, regionData && regionData.mask, regionValue, false
57631
+ );
57632
+ });
57633
+ }
57634
+
57635
+ function fillIsolatedProjectedRasterHoles(grid) {
57636
+ var holes = [];
57637
+ var width = grid.width;
57638
+ var height = grid.height;
57639
+ var coverage = grid.coverage;
57640
+ for (var y = 1; y < height - 1; y++) {
57641
+ for (var x = 1; x < width - 1; x++) {
57642
+ var i = y * width + x;
57643
+ if (!coverage[i] &&
57644
+ coverage[i - 1] && coverage[i + 1] &&
57645
+ coverage[i - width] && coverage[i + width]) {
57646
+ holes.push(i);
57647
+ }
57648
+ }
57649
+ }
57650
+ holes.forEach(function(i) {
57651
+ var src = (i - 1) * grid.bands;
57652
+ var dest = i * grid.bands;
57653
+ for (var band = 0; band < grid.bands; band++) {
57654
+ grid.samples[dest + band] = grid.samples[src + band];
57655
+ }
57656
+ coverage[i] = 1;
55992
57657
  });
55993
57658
  }
55994
57659
 
55995
- function rasterizeProjectedTriangle(srcGrid, destGrid, a, b, c, sampleMethod) {
57660
+ function fillProjectedRasterCoverage(grid) {
57661
+ // Used only for layouts whose projected outline fills the output rectangle.
57662
+ var width = grid.width;
57663
+ var height = grid.height;
57664
+ var coverage = grid.coverage;
57665
+ for (var y = 0; y < height; y++) {
57666
+ var row = y * width;
57667
+ var source = -1;
57668
+ for (var x = 0; x < width; x++) {
57669
+ var i = row + x;
57670
+ if (coverage[i]) {
57671
+ source = i;
57672
+ } else if (source >= 0) {
57673
+ copyProjectedRasterPixel(grid, source, i);
57674
+ }
57675
+ }
57676
+ source = -1;
57677
+ for (x = width - 1; x >= 0; x--) {
57678
+ i = row + x;
57679
+ if (coverage[i]) {
57680
+ source = i;
57681
+ } else if (source >= 0) {
57682
+ copyProjectedRasterPixel(grid, source, i);
57683
+ }
57684
+ }
57685
+ }
57686
+ }
57687
+
57688
+ function copyProjectedRasterPixel(grid, sourceIndex, destIndex) {
57689
+ var source = sourceIndex * grid.bands;
57690
+ var dest = destIndex * grid.bands;
57691
+ for (var band = 0; band < grid.bands; band++) {
57692
+ grid.samples[dest + band] = grid.samples[source + band];
57693
+ }
57694
+ grid.coverage[destIndex] = 1;
57695
+ }
57696
+
57697
+ function createProjectedRegionMask(grid, regions, fill) {
57698
+ var mask = new Uint8Array(grid.width * grid.height);
57699
+ var values = new Map();
57700
+ regions.forEach(function(region, i) {
57701
+ var value = i + 1;
57702
+ values.set(region.id, value);
57703
+ rasterizeRegionMask(grid, mask, region.boundary, value);
57704
+ });
57705
+ if (fill) fillRegionMask(mask, grid.width, grid.height);
57706
+ return {mask: mask, values: values};
57707
+ }
57708
+
57709
+ function fillRegionMask(mask, width, height) {
57710
+ for (var y = 0; y < height; y++) {
57711
+ var row = y * width;
57712
+ var value = 0;
57713
+ for (var x = 0; x < width; x++) {
57714
+ if (mask[row + x]) value = mask[row + x];
57715
+ else if (value) mask[row + x] = value;
57716
+ }
57717
+ value = 0;
57718
+ for (x = width - 1; x >= 0; x--) {
57719
+ if (mask[row + x]) value = mask[row + x];
57720
+ else if (value) mask[row + x] = value;
57721
+ }
57722
+ }
57723
+ }
57724
+
57725
+ function rasterizeRegionMask(grid, mask, boundary, value) {
57726
+ var ring = boundary.map(function(p) {
57727
+ return mapXYToRasterPixel(grid, p[0], p[1]);
57728
+ });
57729
+ var ymin = Math.max(0, Math.floor(Math.min.apply(null, ring.map(function(p) { return p[1]; }))));
57730
+ var ymax = Math.min(grid.height - 1, Math.ceil(Math.max.apply(null, ring.map(function(p) { return p[1]; }))));
57731
+ var intersections = [];
57732
+ for (var y = ymin; y <= ymax; y++) {
57733
+ var py = y + 0.5;
57734
+ intersections.length = 0;
57735
+ for (var i = 1; i < ring.length; i++) {
57736
+ var a = ring[i - 1];
57737
+ var b = ring[i];
57738
+ if ((a[1] > py) == (b[1] > py)) continue;
57739
+ intersections.push(a[0] + (py - a[1]) * (b[0] - a[0]) / (b[1] - a[1]));
57740
+ }
57741
+ intersections.sort(function(a, b) { return a - b; });
57742
+ for (var j = 1; j < intersections.length; j += 2) {
57743
+ var x0 = Math.max(0, Math.ceil(intersections[j - 1] - 0.5));
57744
+ var x1 = Math.min(grid.width - 1, Math.floor(intersections[j] - 0.5));
57745
+ for (var x = x0; x <= x1; x++) {
57746
+ mask[y * grid.width + x] = value;
57747
+ }
57748
+ }
57749
+ }
57750
+ }
57751
+
57752
+ function rasterizeProjectedTriangle(srcGrid, destGrid, a, b, c, sampleMethod, regionMask, regionValue, sourceWrapX) {
55996
57753
  var bbox, x0, x1, y0, y1, det, w1, w2, w3, sx, sy, ap, bp, cp;
55997
57754
  if (!vertexIsValid(a) || !vertexIsValid(b) || !vertexIsValid(c)) return;
55998
57755
  ap = vertexToDestPixel(destGrid, a);
@@ -56004,13 +57761,15 @@ ${svg}
56004
57761
  x0 = bbox[0]; y0 = bbox[1]; x1 = bbox[2]; y1 = bbox[3];
56005
57762
  for (var y = y0; y <= y1; y++) {
56006
57763
  for (var x = x0; x <= x1; x++) {
57764
+ if (regionMask && regionMask[y * destGrid.width + x] != regionValue) continue;
56007
57765
  w1 = edgeFunction(bp, cp, x + 0.5, y + 0.5) / det;
56008
57766
  w2 = edgeFunction(cp, ap, x + 0.5, y + 0.5) / det;
56009
57767
  w3 = 1 - w1 - w2;
56010
57768
  if (w1 < -1e-9 || w2 < -1e-9 || w3 < -1e-9) continue;
56011
57769
  sx = w1 * a.sx + w2 * b.sx + w3 * c.sx;
56012
57770
  sy = w1 * a.sy + w2 * b.sy + w3 * c.sy;
56013
- copyRasterSample(srcGrid, destGrid, sx, sy, x, y, sampleMethod);
57771
+ copyRasterSample(
57772
+ srcGrid, destGrid, sx, sy, x, y, sampleMethod, sourceWrapX);
56014
57773
  }
56015
57774
  }
56016
57775
  }
@@ -56042,16 +57801,18 @@ ${svg}
56042
57801
  ];
56043
57802
  }
56044
57803
 
56045
- function copyRasterSample(srcGrid, destGrid, sx, sy, dx, dy, sampleMethod) {
57804
+ function copyRasterSample(srcGrid, destGrid, sx, sy, dx, dy, sampleMethod, wrapX) {
56046
57805
  if (sampleMethod == 'bilinear') {
56047
- copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy);
57806
+ copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX);
56048
57807
  } else {
56049
- copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy);
57808
+ copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX);
56050
57809
  }
56051
57810
  }
56052
57811
 
56053
- function copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy) {
56054
- var srcX = clamp$1(Math.floor(sx), 0, srcGrid.width - 1);
57812
+ function copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX) {
57813
+ var srcX = wrapX ?
57814
+ modulo(Math.floor(sx), srcGrid.width) :
57815
+ clamp$1(Math.floor(sx), 0, srcGrid.width - 1);
56055
57816
  var srcY = clamp$1(Math.floor(sy), 0, srcGrid.height - 1);
56056
57817
  var src = (srcY * srcGrid.width + srcX) * srcGrid.bands;
56057
57818
  var dest = (dy * destGrid.width + dx) * destGrid.bands;
@@ -56063,10 +57824,14 @@ ${svg}
56063
57824
  if (destGrid.coverage) destGrid.coverage[dy * destGrid.width + dx] = 1;
56064
57825
  }
56065
57826
 
56066
- function copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy) {
56067
- var srcX = clamp$1(Math.floor(sx - 0.5), 0, srcGrid.width - 1);
57827
+ function copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX) {
57828
+ if (wrapX) sx = modulo(sx, srcGrid.width);
57829
+ var srcX = wrapX ?
57830
+ modulo(Math.floor(sx - 0.5), srcGrid.width) :
57831
+ clamp$1(Math.floor(sx - 0.5), 0, srcGrid.width - 1);
56068
57832
  var srcY = clamp$1(Math.floor(sy - 0.5), 0, srcGrid.height - 1);
56069
- var srcX2 = clamp$1(srcX + 1, 0, srcGrid.width - 1);
57833
+ var srcX2 = wrapX ? (srcX + 1) % srcGrid.width :
57834
+ clamp$1(srcX + 1, 0, srcGrid.width - 1);
56070
57835
  var srcY2 = clamp$1(srcY + 1, 0, srcGrid.height - 1);
56071
57836
  var tx = clamp$1(sx - 0.5 - srcX, 0, 1);
56072
57837
  var ty = clamp$1(sy - 0.5 - srcY, 0, 1);
@@ -56178,9 +57943,14 @@ ${svg}
56178
57943
  return val < min ? min : val > max ? max : val;
56179
57944
  }
56180
57945
 
57946
+ function modulo(val, base) {
57947
+ return (val % base + base) % base;
57948
+ }
57949
+
56181
57950
  var RasterReprojection = /*#__PURE__*/Object.freeze({
56182
57951
  __proto__: null,
56183
57952
  buildProjectedRasterMesh: buildProjectedRasterMesh,
57953
+ buildTopologyAwareProjectedRasterMesh: buildTopologyAwareProjectedRasterMesh,
56184
57954
  getProjectedRasterGridBBox: getProjectedRasterGridBBox,
56185
57955
  getProjectedRasterMeshBBox: getProjectedRasterMeshBBox,
56186
57956
  projectRasterGridForward: projectRasterGridForward
@@ -56331,9 +58101,6 @@ ${svg}
56331
58101
  if (isProjectedCRS(src) && !isInvertibleCRS(src)) {
56332
58102
  stop$1('Unable to project from a coordinate system that has no inverse transform');
56333
58103
  }
56334
- if (isInterruptedProjection(dest) && dataset.layers.some(layerHasRaster)) {
56335
- stop$1('Raster reprojection is not currently supported for interrupted projections');
56336
- }
56337
58104
  var proj = getProjTransform2(src, dest); // v2 returns null points instead of throwing an error
56338
58105
  var badArcs = 0;
56339
58106
  var badPoints = 0;
@@ -60733,7 +62500,7 @@ ${svg}
60733
62500
  // Isometric ("Mercator-stretched") latitude in degrees-in; returns +/-Infinity at
60734
62501
  // the poles.
60735
62502
  function isometricLatitude(latDeg) {
60736
- return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$7 / 2));
62503
+ return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$8 / 2));
60737
62504
  }
60738
62505
 
60739
62506
  // Rhumb-line (loxodrome) interpolation, fraction k of the way from A to B.
@@ -60758,9 +62525,9 @@ ${svg}
60758
62525
  // Rhumb-line distance in meters, using the raw longitude delta (so a full-parallel
60759
62526
  // sweep returns the parallel's length rather than 0).
60760
62527
  function rhumbDistance(a, b) {
60761
- var phi1 = a[1] * D2R$7, phi2 = b[1] * D2R$7;
62528
+ var phi1 = a[1] * D2R$8, phi2 = b[1] * D2R$8;
60762
62529
  var dPhi = phi2 - phi1;
60763
- var dLambda = (b[0] - a[0]) * D2R$7; // raw
62530
+ var dLambda = (b[0] - a[0]) * D2R$8; // raw
60764
62531
  var dPsi = Math.log(Math.tan(Math.PI / 4 + phi2 / 2) / Math.tan(Math.PI / 4 + phi1 / 2));
60765
62532
  var q = Math.abs(dPsi) > 1e-12 ? dPhi / dPsi : Math.cos(phi1);
60766
62533
  return Math.sqrt(dPhi * dPhi + q * q * dLambda * dLambda) * R$3;
@@ -71096,7 +72863,7 @@ ${svg}
71096
72863
  return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
71097
72864
  }
71098
72865
 
71099
- var version = "0.7.46";
72866
+ var version = "0.7.47";
71100
72867
 
71101
72868
  // Parse command line args into commands and run them
71102
72869
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.