mapshaper 0.7.45 → 0.7.46

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.
package/mapshaper.js CHANGED
@@ -78,7 +78,7 @@
78
78
  return obj === Object(obj); // via underscore
79
79
  }
80
80
 
81
- function clamp$3(val, min, max) {
81
+ function clamp$4(val, min, max) {
82
82
  return val < min ? min : (val > max ? max : val);
83
83
  }
84
84
 
@@ -261,36 +261,6 @@
261
261
  };
262
262
  }
263
263
 
264
- // Call @iter on each member of an array (similar to Array#reduce(iter))
265
- // iter: function(memo, item, callback)
266
- // Call @done when all members have been processed or if an error occurs
267
- // done: function(err, memo)
268
- // @memo: Initial value
269
- //
270
- function reduceAsync(arr, memo, iter, done) {
271
- var call = typeof setImmediate == 'undefined' ? setTimeout : setImmediate;
272
- var i=0;
273
- next(null, memo);
274
-
275
- function next(err, memo) {
276
- // Detach next operation from call stack to prevent overflow
277
- // Don't use setTimeout(, 0) if setImmediate is available
278
- // (setTimeout() can introduce a long delay if previous operation was slow,
279
- // as of Node 0.10.32 -- a bug?)
280
- if (err) {
281
- return done(err, null);
282
- }
283
- call(function() {
284
- if (i < arr.length === false) {
285
- done(null, memo);
286
- } else {
287
- iter(memo, arr[i++], next);
288
- }
289
- }, 0);
290
- }
291
- }
292
-
293
-
294
264
  // Append elements of @src array to @dest array
295
265
  function merge$1(dest, src) {
296
266
  if (!isArray(dest) || !isArray(src)) {
@@ -751,7 +721,7 @@
751
721
  function findValueByRank(arr, rank) {
752
722
  if (!arr.length || rank < 1 || rank > arr.length) error$1("[findValueByRank()] invalid input");
753
723
 
754
- rank = clamp$3(rank | 0, 1, arr.length);
724
+ rank = clamp$4(rank | 0, 1, arr.length);
755
725
  var k = rank - 1, // conv. rank to array index
756
726
  n = arr.length,
757
727
  l = 0,
@@ -1125,7 +1095,7 @@
1125
1095
  // self-import and the resulting Rollup circular-dependency warning.
1126
1096
  var utils = {
1127
1097
  addThousandsSep, addslashes, arrayToIndex,
1128
- clamp: clamp$3, cleanNumericString, contains, copyElements, countValues, createBuffer,
1098
+ clamp: clamp$4, cleanNumericString, contains, copyElements, countValues, createBuffer,
1129
1099
  defaults, difference,
1130
1100
  endsWith, every, expandoBuffer, extend: extend$1, extendBuffer,
1131
1101
  find: find$1, findMedian, findQuantile, findRankByValue, findStringPrefix,
@@ -1145,7 +1115,7 @@
1145
1115
  parseIntlNumber, parseNumber: parseNumber$1, parseString, pickOne, pluck,
1146
1116
  pluralSuffix, promisify,
1147
1117
  quicksort: quicksort$1, quicksortPartition,
1148
- range, reduceAsync, regexEscape, reorderArray: reorderArray$1, repeat, repeatString,
1118
+ range, regexEscape, reorderArray: reorderArray$1, repeat, repeatString,
1149
1119
  replaceArray, rpad, rtrim,
1150
1120
  shuffle, some, sortArrayIndex, sortOn, splitLines, sum: sum$1,
1151
1121
  toArray: toArray$1, toBuffer, trim, trimQuotes,
@@ -2083,12 +2053,12 @@
2083
2053
  // TODO: remove this constant, use actual data from dataset CRS,
2084
2054
  // also consider using ellipsoidal formulas where greater accuracy might be important.
2085
2055
  var R$3 = WGS84.SEMIMAJOR_AXIS;
2086
- var D2R$6 = Math.PI / 180;
2087
- var R2D$5 = 180 / Math.PI;
2056
+ var D2R$7 = Math.PI / 180;
2057
+ var R2D$6 = 180 / Math.PI;
2088
2058
 
2089
2059
  // Equirectangular projection
2090
2060
  function degreesToMeters(deg) {
2091
- return deg * D2R$6 * R$3;
2061
+ return deg * D2R$7 * R$3;
2092
2062
  }
2093
2063
 
2094
2064
  function distance3D(ax, ay, az, bx, by, bz) {
@@ -2235,16 +2205,16 @@
2235
2205
 
2236
2206
  function xyzToLngLat(x, y, z, p) {
2237
2207
  var d = distance3D(0, 0, 0, x, y, z); // normalize
2238
- var lat = Math.asin(z / d) / D2R$6;
2239
- var lng = Math.atan2(y / d, x / d) / D2R$6;
2208
+ var lat = Math.asin(z / d) / D2R$7;
2209
+ var lng = Math.atan2(y / d, x / d) / D2R$7;
2240
2210
  p[0] = lng;
2241
2211
  p[1] = lat;
2242
2212
  }
2243
2213
 
2244
2214
  function lngLatToXYZ(lng, lat, p) {
2245
2215
  var cosLat;
2246
- lng *= D2R$6;
2247
- lat *= D2R$6;
2216
+ lng *= D2R$7;
2217
+ lat *= D2R$7;
2248
2218
  cosLat = Math.cos(lat);
2249
2219
  p[0] = Math.cos(lng) * cosLat * R$3;
2250
2220
  p[1] = Math.sin(lng) * cosLat * R$3;
@@ -2364,9 +2334,9 @@
2364
2334
 
2365
2335
  var Geom = /*#__PURE__*/Object.freeze({
2366
2336
  __proto__: null,
2367
- D2R: D2R$6,
2337
+ D2R: D2R$7,
2368
2338
  R: R$3,
2369
- R2D: R2D$5,
2339
+ R2D: R2D$6,
2370
2340
  bearing: bearing,
2371
2341
  bearing2D: bearing2D,
2372
2342
  containsBounds: containsBounds,
@@ -6294,9 +6264,9 @@
6294
6264
  * ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
6295
6265
  */
6296
6266
 
6297
- var D2R$5 = Math.PI / 180;
6298
- var R2D$4 = 180 / Math.PI;
6299
- var EPS$1 = 1e-12;
6267
+ var D2R$6 = Math.PI / 180;
6268
+ var R2D$5 = 180 / Math.PI;
6269
+ var EPS$2 = 1e-12;
6300
6270
 
6301
6271
  // Build a forward-only spherical polyhedral projection.
6302
6272
  //
@@ -6334,10 +6304,10 @@
6334
6304
  throw new Error('Invalid polyhedral face tree');
6335
6305
  }
6336
6306
  var childEdge = shared.map(function(p) {
6337
- return face.project(p[0] * D2R$5, p[1] * D2R$5);
6307
+ return face.project(p[0] * D2R$6, p[1] * D2R$6);
6338
6308
  });
6339
6309
  var parentEdge = shared.map(function(p) {
6340
- return parent.project(p[0] * D2R$5, p[1] * D2R$5);
6310
+ return parent.project(p[0] * D2R$6, p[1] * D2R$6);
6341
6311
  });
6342
6312
  face.transform = multiplyMatrices(
6343
6313
  parent.transform,
@@ -6348,12 +6318,12 @@
6348
6318
 
6349
6319
  var rootEdge = findLongestEdge(faces[0].coords);
6350
6320
  var rootPlanarEdge = rootEdge.map(function(p) {
6351
- return faces[0].project(p[0] * D2R$5, p[1] * D2R$5);
6321
+ return faces[0].project(p[0] * D2R$6, p[1] * D2R$6);
6352
6322
  });
6353
6323
  var sphericalEdgeLength = angularDistance(rootEdge[0], rootEdge[1]);
6354
6324
  var planarEdgeLength = distance2D(rootPlanarEdge[0], rootPlanarEdge[1]);
6355
6325
  var scale = sphericalEdgeLength / planarEdgeLength;
6356
- var planarAngle = (config.angle || 0) * D2R$5;
6326
+ var planarAngle = (config.angle || 0) * D2R$6;
6357
6327
  var edgeIndex = indexEdges(faces, attachedPairs);
6358
6328
  var outline = buildOutline(faces, attachedPairs).map(function(ring) {
6359
6329
  return ring.map(transformOutputPoint);
@@ -6383,9 +6353,9 @@
6383
6353
  var rotated = rotateRadians(
6384
6354
  lam,
6385
6355
  phi,
6386
- config.rotation[0] * D2R$5,
6387
- config.rotation[1] * D2R$5,
6388
- config.rotation[2] * D2R$5
6356
+ config.rotation[0] * D2R$6,
6357
+ config.rotation[1] * D2R$6,
6358
+ config.rotation[2] * D2R$6
6389
6359
  );
6390
6360
  var face = findFaceRotated(rotated[0], rotated[1]);
6391
6361
  if (!face) return null;
@@ -6401,9 +6371,9 @@
6401
6371
  var rotated = rotateRadians(
6402
6372
  lam,
6403
6373
  phi,
6404
- config.rotation[0] * D2R$5,
6405
- config.rotation[1] * D2R$5,
6406
- config.rotation[2] * D2R$5
6374
+ config.rotation[0] * D2R$6,
6375
+ config.rotation[1] * D2R$6,
6376
+ config.rotation[2] * D2R$6
6407
6377
  );
6408
6378
  var face = findFaceRotated(rotated[0], rotated[1]);
6409
6379
  return face ? face.id : -1;
@@ -6413,9 +6383,9 @@
6413
6383
  var rotated = rotateRadians(
6414
6384
  lam,
6415
6385
  phi,
6416
- config.rotation[0] * D2R$5,
6417
- config.rotation[1] * D2R$5,
6418
- config.rotation[2] * D2R$5
6386
+ config.rotation[0] * D2R$6,
6387
+ config.rotation[1] * D2R$6,
6388
+ config.rotation[2] * D2R$6
6419
6389
  );
6420
6390
  var face = findFaceRotated(rotated[0], rotated[1]);
6421
6391
  var region;
@@ -6432,7 +6402,7 @@
6432
6402
  faceId = config.findFace(lam, phi);
6433
6403
  return faceId >= 0 ? faces[faceId] : null;
6434
6404
  }
6435
- var p = radiansToVector(lam, phi);
6405
+ var p = radiansToVector$1(lam, phi);
6436
6406
  for (var i = 0; i < faces.length; i++) {
6437
6407
  if (faceContainsVector(faces[i], p)) return faces[i];
6438
6408
  }
@@ -6457,16 +6427,16 @@
6457
6427
  var seams = edgeIndex.map(function(edge) {
6458
6428
  var endpoints = edge.points.map(function(p) {
6459
6429
  var q = rotateRadians(
6460
- p[0] * D2R$5,
6461
- p[1] * D2R$5,
6462
- config.rotation[0] * D2R$5,
6463
- config.rotation[1] * D2R$5,
6464
- config.rotation[2] * D2R$5,
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,
6465
6435
  true
6466
6436
  );
6467
- return [normalizeLongitude$1(q[0] * R2D$4 + lon0), q[1] * R2D$4];
6437
+ return [normalizeLongitude$2(q[0] * R2D$5 + lon0), q[1] * R2D$5];
6468
6438
  });
6469
- var paths = splitPathAtAntimeridian$1(
6439
+ var paths = splitPathAtAntimeridian$2(
6470
6440
  interpolateGreatCircle(endpoints[0], endpoints[1], 0.05)
6471
6441
  );
6472
6442
  paths.forEach(function(path) {
@@ -6491,12 +6461,12 @@
6491
6461
  }),
6492
6462
  seams: seams,
6493
6463
  findRegion: function(lon, lat) {
6494
- var lam = normalizeLongitude$1(lon - lon0) * D2R$5;
6495
- return findFace(lam, lat * D2R$5);
6464
+ var lam = normalizeLongitude$2(lon - lon0) * D2R$6;
6465
+ return findFace(lam, lat * D2R$6);
6496
6466
  },
6497
6467
  findTransitionRegion: function(lon, lat) {
6498
- var lam = normalizeLongitude$1(lon - lon0) * D2R$5;
6499
- return findTransitionRegion(lam, lat * D2R$5);
6468
+ var lam = normalizeLongitude$2(lon - lon0) * D2R$6;
6469
+ return findTransitionRegion(lam, lat * D2R$6);
6500
6470
  },
6501
6471
  regionsAreAttached: function(a, b) {
6502
6472
  return regionPairs.get(pairKey(a, b)) === true;
@@ -6514,9 +6484,9 @@
6514
6484
  return rotateRadians(
6515
6485
  lam,
6516
6486
  phi,
6517
- (rotation[0] || 0) * D2R$5,
6518
- (rotation[1] || 0) * D2R$5,
6519
- (rotation[2] || 0) * D2R$5,
6487
+ (rotation[0] || 0) * D2R$6,
6488
+ (rotation[1] || 0) * D2R$6,
6489
+ (rotation[2] || 0) * D2R$6,
6520
6490
  invert
6521
6491
  );
6522
6492
  }
@@ -6525,7 +6495,7 @@
6525
6495
  var vectors = coords.map(function(p) {
6526
6496
  return degreesToVector$2(p[0], p[1]);
6527
6497
  });
6528
- var inside = normalizeVector$1(vectors.reduce(function(sum, p) {
6498
+ var inside = normalizeVector$2(vectors.reduce(function(sum, p) {
6529
6499
  sum[0] += p[0];
6530
6500
  sum[1] += p[1];
6531
6501
  sum[2] += p[2];
@@ -6535,10 +6505,10 @@
6535
6505
  for (var i = 0; i < vectors.length; i++) {
6536
6506
  var a = vectors[i];
6537
6507
  var b = vectors[(i + 1) % vectors.length];
6538
- var normal = cross$1(a, b);
6508
+ var normal = cross$2(a, b);
6539
6509
  edges.push({
6540
6510
  normal: normal,
6541
- sign: dot$1(normal, inside) < 0 ? -1 : 1
6511
+ sign: dot$2(normal, inside) < 0 ? -1 : 1
6542
6512
  });
6543
6513
  }
6544
6514
  return {
@@ -6553,7 +6523,7 @@
6553
6523
  function faceContainsVector(face, p) {
6554
6524
  for (var i = 0; i < face.edges.length; i++) {
6555
6525
  var edge = face.edges[i];
6556
- if (dot$1(edge.normal, p) * edge.sign < -EPS$1) return false;
6526
+ if (dot$2(edge.normal, p) * edge.sign < -EPS$2) return false;
6557
6527
  }
6558
6528
  return true;
6559
6529
  }
@@ -6589,8 +6559,8 @@
6589
6559
  var adjacent = findAdjacentFace(faces, face.id, a, b);
6590
6560
  if (adjacent >= 0 && attachedPairs.has(pairKey(face.id, adjacent))) continue;
6591
6561
  edges.push([
6592
- applyMatrix(face.transform, face.project(a[0] * D2R$5, a[1] * D2R$5)),
6593
- applyMatrix(face.transform, face.project(b[0] * D2R$5, b[1] * D2R$5))
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))
6594
6564
  ]);
6595
6565
  }
6596
6566
  });
@@ -6717,9 +6687,9 @@
6717
6687
  function rotateRadians(lam, phi, deltaLam, deltaPhi, deltaGamma, invert) {
6718
6688
  if (invert) {
6719
6689
  var inv = rotatePhiGamma$1(lam, phi, deltaPhi, deltaGamma, true);
6720
- return [normalizeRadians$1(inv[0] - deltaLam), inv[1]];
6690
+ return [normalizeRadians$2(inv[0] - deltaLam), inv[1]];
6721
6691
  }
6722
- lam = normalizeRadians$1(lam + deltaLam);
6692
+ lam = normalizeRadians$2(lam + deltaLam);
6723
6693
  return rotatePhiGamma$1(lam, phi, deltaPhi, deltaGamma, false);
6724
6694
  }
6725
6695
 
@@ -6739,28 +6709,28 @@
6739
6709
  return [
6740
6710
  Math.atan2(y * cosDeltaGamma + z * sinDeltaGamma,
6741
6711
  x * cosDeltaPhi + k * sinDeltaPhi),
6742
- Math.asin(clamp$2(k * cosDeltaPhi - x * sinDeltaPhi, -1, 1))
6712
+ Math.asin(clamp$3(k * cosDeltaPhi - x * sinDeltaPhi, -1, 1))
6743
6713
  ];
6744
6714
  }
6745
6715
  k = z * cosDeltaPhi + x * sinDeltaPhi;
6746
6716
  return [
6747
6717
  Math.atan2(y * cosDeltaGamma - k * sinDeltaGamma,
6748
6718
  x * cosDeltaPhi - z * sinDeltaPhi),
6749
- Math.asin(clamp$2(k * cosDeltaGamma + y * sinDeltaGamma, -1, 1))
6719
+ Math.asin(clamp$3(k * cosDeltaGamma + y * sinDeltaGamma, -1, 1))
6750
6720
  ];
6751
6721
  }
6752
6722
 
6753
6723
  function interpolateGreatCircle(a, b, interval) {
6754
6724
  var av = degreesToVector$2(a[0], a[1]);
6755
6725
  var bv = degreesToVector$2(b[0], b[1]);
6756
- var angle = Math.acos(clamp$2(dot$1(av, bv), -1, 1));
6757
- var n = Math.max(1, Math.ceil(angle * R2D$4 / interval));
6726
+ var angle = Math.acos(clamp$3(dot$2(av, bv), -1, 1));
6727
+ var n = Math.max(1, Math.ceil(angle * R2D$5 / interval));
6758
6728
  var sinAngle = Math.sin(angle);
6759
6729
  var points = [];
6760
6730
  for (var i = 0; i <= n; i++) {
6761
6731
  var t = i / n;
6762
6732
  var p;
6763
- if (sinAngle < EPS$1) {
6733
+ if (sinAngle < EPS$2) {
6764
6734
  p = av;
6765
6735
  } else {
6766
6736
  var ka = Math.sin((1 - t) * angle) / sinAngle;
@@ -6771,12 +6741,12 @@
6771
6741
  av[2] * ka + bv[2] * kb
6772
6742
  ];
6773
6743
  }
6774
- points.push(vectorToDegrees$2(normalizeVector$1(p)));
6744
+ points.push(vectorToDegrees$2(normalizeVector$2(p)));
6775
6745
  }
6776
6746
  return points;
6777
6747
  }
6778
6748
 
6779
- function splitPathAtAntimeridian$1(path) {
6749
+ function splitPathAtAntimeridian$2(path) {
6780
6750
  var paths = [];
6781
6751
  var part = [path[0]];
6782
6752
  for (var i = 1; i < path.length; i++) {
@@ -6812,32 +6782,32 @@
6812
6782
  }
6813
6783
 
6814
6784
  function angularDistance(a, b) {
6815
- return Math.acos(clamp$2(dot$1(degreesToVector$2(a[0], a[1]),
6785
+ return Math.acos(clamp$3(dot$2(degreesToVector$2(a[0], a[1]),
6816
6786
  degreesToVector$2(b[0], b[1])), -1, 1));
6817
6787
  }
6818
6788
 
6819
6789
  function degreesToVector$2(lon, lat) {
6820
- return radiansToVector(lon * D2R$5, lat * D2R$5);
6790
+ return radiansToVector$1(lon * D2R$6, lat * D2R$6);
6821
6791
  }
6822
6792
 
6823
- function radiansToVector(lam, phi) {
6793
+ function radiansToVector$1(lam, phi) {
6824
6794
  var cosPhi = Math.cos(phi);
6825
6795
  return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
6826
6796
  }
6827
6797
 
6828
6798
  function vectorToDegrees$2(p) {
6829
6799
  return [
6830
- Math.atan2(p[1], p[0]) * R2D$4,
6831
- Math.asin(clamp$2(p[2], -1, 1)) * R2D$4
6800
+ Math.atan2(p[1], p[0]) * R2D$5,
6801
+ Math.asin(clamp$3(p[2], -1, 1)) * R2D$5
6832
6802
  ];
6833
6803
  }
6834
6804
 
6835
- function normalizeVector$1(p) {
6836
- var k = 1 / Math.sqrt(dot$1(p, p));
6805
+ function normalizeVector$2(p) {
6806
+ var k = 1 / Math.sqrt(dot$2(p, p));
6837
6807
  return [p[0] * k, p[1] * k, p[2] * k];
6838
6808
  }
6839
6809
 
6840
- function cross$1(a, b) {
6810
+ function cross$2(a, b) {
6841
6811
  return [
6842
6812
  a[1] * b[2] - a[2] * b[1],
6843
6813
  a[2] * b[0] - a[0] * b[2],
@@ -6845,7 +6815,7 @@
6845
6815
  ];
6846
6816
  }
6847
6817
 
6848
- function dot$1(a, b) {
6818
+ function dot$2(a, b) {
6849
6819
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
6850
6820
  }
6851
6821
 
@@ -6856,7 +6826,7 @@
6856
6826
  }
6857
6827
 
6858
6828
  function sameSphericalPoint(a, b) {
6859
- return Math.abs(a[0] - b[0]) < EPS$1 && Math.abs(a[1] - b[1]) < EPS$1;
6829
+ return Math.abs(a[0] - b[0]) < EPS$2 && Math.abs(a[1] - b[1]) < EPS$2;
6860
6830
  }
6861
6831
 
6862
6832
  function pointsAlmostEqual(a, b) {
@@ -6877,19 +6847,19 @@
6877
6847
  return a < b ? a + '~' + b : b + '~' + a;
6878
6848
  }
6879
6849
 
6880
- function normalizeRadians$1(lam) {
6850
+ function normalizeRadians$2(lam) {
6881
6851
  while (lam > Math.PI) lam -= Math.PI * 2;
6882
6852
  while (lam < -Math.PI) lam += Math.PI * 2;
6883
6853
  return lam;
6884
6854
  }
6885
6855
 
6886
- function normalizeLongitude$1(lon) {
6856
+ function normalizeLongitude$2(lon) {
6887
6857
  while (lon > 180) lon -= 360;
6888
6858
  while (lon < -180) lon += 360;
6889
6859
  return lon;
6890
6860
  }
6891
6861
 
6892
- function clamp$2(val, min, max) {
6862
+ function clamp$3(val, min, max) {
6893
6863
  return Math.max(min, Math.min(max, val));
6894
6864
  }
6895
6865
 
@@ -6905,9 +6875,9 @@
6905
6875
  */
6906
6876
 
6907
6877
 
6908
- var D2R$4 = Math.PI / 180;
6909
- var R2D$3 = 180 / Math.PI;
6910
- var SQRT3 = Math.sqrt(3);
6878
+ var D2R$5 = Math.PI / 180;
6879
+ var R2D$4 = 180 / Math.PI;
6880
+ var SQRT3$1 = Math.sqrt(3);
6911
6881
  var GRAY_Z = Math.sqrt(5 + 2 * Math.sqrt(5)) / Math.sqrt(15);
6912
6882
  var GRAY_EL = Math.sqrt(8) / Math.sqrt(5 + Math.sqrt(5));
6913
6883
  var GRAY_DVE = Math.sqrt(3 + Math.sqrt(5)) / Math.sqrt(5 + Math.sqrt(5));
@@ -6919,7 +6889,7 @@
6919
6889
  6, 8, 10, 17, 21,
6920
6890
  16, 15, 19, 19
6921
6891
  ];
6922
- var engines$1 = {};
6892
+ var engines$2 = {};
6923
6893
 
6924
6894
  function registerDymaxionProjections(mproj) {
6925
6895
  // Some unit tests import source modules directly in an ESM context where
@@ -6938,9 +6908,9 @@
6938
6908
 
6939
6909
  function getDymaxionEngine(method) {
6940
6910
  method = method || 'fuller';
6941
- if (!engines$1[method]) {
6911
+ if (!engines$2[method]) {
6942
6912
  var data = createAiroceanFaces();
6943
- engines$1[method] = createPolyhedralProjection({
6913
+ engines$2[method] = createPolyhedralProjection({
6944
6914
  faces: data.faces,
6945
6915
  faceSites: data.sites,
6946
6916
  parents: PARENTS,
@@ -6951,7 +6921,7 @@
6951
6921
  createGrayFullerFaceProjector
6952
6922
  });
6953
6923
  }
6954
- return engines$1[method];
6924
+ return engines$2[method];
6955
6925
  }
6956
6926
 
6957
6927
  function initDymaxion(P, method) {
@@ -6967,12 +6937,12 @@
6967
6937
  xy.y = p[1];
6968
6938
  }
6969
6939
  };
6970
- P.__projection_topology = engine.getTopology(P.lam0 * R2D$3);
6940
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$4);
6971
6941
  P.__projected_outline = engine.outline;
6972
6942
  }
6973
6943
 
6974
6944
  function createAiroceanFaces() {
6975
- var theta = Math.atan(0.5) * R2D$3;
6945
+ var theta = Math.atan(0.5) * R2D$4;
6976
6946
  var vertices = [[0, 90], [0, -90]];
6977
6947
  var faces;
6978
6948
  var sites;
@@ -7069,10 +7039,10 @@
7069
7039
  var s = GRAY_Z / (cosPhi * Math.cos(lam));
7070
7040
  var x = cosPhi * Math.sin(lam) * s;
7071
7041
  var y = Math.sin(phi) * s;
7072
- var a1p = Math.atan2(2 * y / SQRT3 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7073
- var a2p = Math.atan2(x - y / SQRT3 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
7074
- var a3p = Math.atan2(GRAY_EL / 3 - x - y / SQRT3 - GRAY_EL / 2, GRAY_DVE);
7075
- return [SQRT3 * (a2p - a3p), 2 * a1p - a2p - a3p];
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];
7076
7046
  }
7077
7047
 
7078
7048
  function getSphericalCentroid(coords) {
@@ -7097,16 +7067,16 @@
7097
7067
  }
7098
7068
 
7099
7069
  function degreesToVector$1(p) {
7100
- var lam = p[0] * D2R$4;
7101
- var phi = p[1] * D2R$4;
7070
+ var lam = p[0] * D2R$5;
7071
+ var phi = p[1] * D2R$5;
7102
7072
  var cosPhi = Math.cos(phi);
7103
7073
  return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
7104
7074
  }
7105
7075
 
7106
7076
  function vectorToDegrees$1(p) {
7107
7077
  return [
7108
- Math.atan2(p[1], p[0]) * R2D$3,
7109
- Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$3
7078
+ Math.atan2(p[1], p[0]) * R2D$4,
7079
+ Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$4
7110
7080
  ];
7111
7081
  }
7112
7082
 
@@ -7154,8 +7124,8 @@
7154
7124
  * ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
7155
7125
  */
7156
7126
 
7157
- var D2R$3 = Math.PI / 180;
7158
- var R2D$2 = 180 / Math.PI;
7127
+ var D2R$4 = Math.PI / 180;
7128
+ var R2D$3 = 180 / Math.PI;
7159
7129
 
7160
7130
  function createCahillKeyesRaw(mg) {
7161
7131
  return createCahillKeyesTransform(mg, false);
@@ -7167,12 +7137,12 @@
7167
7137
 
7168
7138
  return function(lambda, phi) {
7169
7139
  if (faceOnly) {
7170
- var lon = lambda * R2D$2;
7140
+ var lon = lambda * R2D$3;
7171
7141
  var side = lon < 0 ? -1 : lon > 0 ? 1 : 0;
7172
- var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$2));
7142
+ var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$3));
7173
7143
  return [local[0], side * local[1]];
7174
7144
  }
7175
- var res = ll2mp(lambda * R2D$2, phi * R2D$2);
7145
+ var res = ll2mp(lambda * R2D$3, phi * R2D$3);
7176
7146
  var xy = mp2xy(res[0], res[1]);
7177
7147
  var p = [xy[0], res[2] * xy[1]];
7178
7148
  return mj2g(p, res[3]);
@@ -7190,7 +7160,7 @@
7190
7160
  CK.cos60 = 0.5;
7191
7161
  CK.pointM = [0, 0];
7192
7162
  CK.pointG = [CK.lengthMG, 0];
7193
- pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$3)];
7163
+ pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$4)];
7194
7164
  CK.pointA = [CK.lengthMA, 0];
7195
7165
  CK.pointB = lineIntersection(CK.pointM, 30, CK.pointA, 45);
7196
7166
  CK.lengthAG = distance(CK.pointA, CK.pointG);
@@ -7201,8 +7171,8 @@
7201
7171
  CK.pointD = interpolate(lengthMB, lengthMN, pointN, CK.pointM);
7202
7172
  CK.pointF = [CK.lengthMG, lengthNG - lengthMB];
7203
7173
  CK.pointE = [
7204
- pointN[0] - CK.lengthMA * Math.sin(30 * D2R$3),
7205
- pointN[1] - CK.lengthMA * Math.cos(30 * D2R$3)
7174
+ pointN[0] - CK.lengthMA * Math.sin(30 * D2R$4),
7175
+ pointN[1] - CK.lengthMA * Math.cos(30 * D2R$4)
7206
7176
  ];
7207
7177
  CK.lengthGF = distance(CK.pointG, CK.pointF);
7208
7178
  CK.lengthBD = distance(CK.pointB, CK.pointD);
@@ -7212,8 +7182,8 @@
7212
7182
  CK.lengthAP73 = CK.lengthMG - CK.lengthMA -
7213
7183
  CK.lengthParallel0to73At0 * 73;
7214
7184
  pointU = [
7215
- CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$3),
7216
- CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$3)
7185
+ CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$4),
7186
+ CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$4)
7217
7187
  ];
7218
7188
  CK.pointT = lineIntersection(pointU, -60, CK.pointB, 30);
7219
7189
 
@@ -7454,8 +7424,8 @@
7454
7424
 
7455
7425
  function radialPoint(origin, length, angle) {
7456
7426
  return [
7457
- origin[0] + length * Math.cos(angle * D2R$3),
7458
- origin[1] + length * Math.sin(angle * D2R$3)
7427
+ origin[0] + length * Math.cos(angle * D2R$4),
7428
+ origin[1] + length * Math.sin(angle * D2R$4)
7459
7429
  ];
7460
7430
  }
7461
7431
 
@@ -7472,8 +7442,8 @@
7472
7442
  -xy[0] * CK.sin60 - xy[1] * CK.cos60
7473
7443
  ];
7474
7444
  }
7475
- var cos = Math.cos(angle * D2R$3);
7476
- var sin = Math.sin(angle * D2R$3);
7445
+ var cos = Math.cos(angle * D2R$4);
7446
+ var sin = Math.sin(angle * D2R$4);
7477
7447
  return [xy[0] * cos - xy[1] * sin, xy[0] * sin + xy[1] * cos];
7478
7448
  }
7479
7449
  }
@@ -7494,8 +7464,8 @@
7494
7464
  }
7495
7465
 
7496
7466
  function lineIntersection(p1, slope1, p2, slope2) {
7497
- var m1 = Math.tan(slope1 * D2R$3);
7498
- var m2 = Math.tan(slope2 * D2R$3);
7467
+ var m1 = Math.tan(slope1 * D2R$4);
7468
+ var m2 = Math.tan(slope2 * D2R$4);
7499
7469
  var x = (m1 * p1[0] - m2 * p2[0] - p1[1] + p2[1]) / (m1 - m2);
7500
7470
  return [x, m1 * (x - p1[0]) + p1[1]];
7501
7471
  }
@@ -7523,8 +7493,8 @@
7523
7493
  return n > 0 ? Math.floor(n) : Math.ceil(n);
7524
7494
  }
7525
7495
 
7526
- var D2R$2 = Math.PI / 180;
7527
- var EPS = 1e-12;
7496
+ var D2R$3 = Math.PI / 180;
7497
+ var EPS$1 = 1e-12;
7528
7498
 
7529
7499
  // Create a smooth facet projection from any radial azimuthal projection.
7530
7500
  // The azimuthal coordinates are warped back to the gnomonic polygon along
@@ -7534,7 +7504,7 @@
7534
7504
  var center = options.planarCenter || getSphericalCenter(coords);
7535
7505
  var gnomonic = createGnomonicProjector(center);
7536
7506
  var planar = coords.map(function(p) {
7537
- return gnomonic(p[0] * D2R$2, p[1] * D2R$2);
7507
+ return gnomonic(p[0] * D2R$3, p[1] * D2R$3);
7538
7508
  });
7539
7509
  var edges = createNormalizedEdges(planar);
7540
7510
  var radial = createRadialFunction(
@@ -7553,7 +7523,7 @@
7553
7523
  function project(lam, phi) {
7554
7524
  var p = gnomonic(lam, phi);
7555
7525
  var r = Math.hypot(p[0], p[1]);
7556
- if (r < EPS) return [0, 0];
7526
+ if (r < EPS$1) return [0, 0];
7557
7527
  var c = Math.atan(r);
7558
7528
  var azimuthalRadius = radial(c) * radialScale;
7559
7529
  var boundaryWeight = getBoundaryWeight(p, edges, boundaryStrength);
@@ -7643,8 +7613,8 @@
7643
7613
 
7644
7614
  function getSphericalCenter(coords) {
7645
7615
  var sum = coords.reduce(function(memo, p) {
7646
- var lam = p[0] * D2R$2;
7647
- var phi = p[1] * D2R$2;
7616
+ var lam = p[0] * D2R$3;
7617
+ var phi = p[1] * D2R$3;
7648
7618
  var cosPhi = Math.cos(phi);
7649
7619
  memo[0] += Math.cos(lam) * cosPhi;
7650
7620
  memo[1] += Math.sin(lam) * cosPhi;
@@ -7652,8 +7622,8 @@
7652
7622
  return memo;
7653
7623
  }, [0, 0, 0]);
7654
7624
  return [
7655
- Math.atan2(sum[1], sum[0]) / D2R$2,
7656
- Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$2
7625
+ Math.atan2(sum[1], sum[0]) / D2R$3,
7626
+ Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$3
7657
7627
  ];
7658
7628
  }
7659
7629
 
@@ -7668,8 +7638,8 @@
7668
7638
  */
7669
7639
 
7670
7640
 
7671
- var D2R$1 = Math.PI / 180;
7672
- var R2D$1 = 180 / Math.PI;
7641
+ var D2R$2 = Math.PI / 180;
7642
+ var R2D$2 = 180 / Math.PI;
7673
7643
  var RADIAL_BOUNDARY_STRENGTH = 1;
7674
7644
  var OCTAHEDRON = createOctahedron();
7675
7645
  var BUTTERFLY_PARENTS = [-1, 0, 0, 1, 0, 1, 4, 5];
@@ -7678,7 +7648,7 @@
7678
7648
  butterfly2: -20,
7679
7649
  cahill_keyes: -20
7680
7650
  };
7681
- var engines = {};
7651
+ var engines$1 = {};
7682
7652
 
7683
7653
  function registerButterflyProjections(mproj) {
7684
7654
  if (!mproj) return;
@@ -7696,22 +7666,22 @@
7696
7666
 
7697
7667
  function getButterflyEngine(method) {
7698
7668
  var key = method == 'butterfly2' ? 'butterfly' : method;
7699
- if (!engines[key]) {
7669
+ if (!engines$1[key]) {
7700
7670
  if (key == 'cahill_keyes') {
7701
- engines[key] = createCahillKeyesEngine();
7671
+ engines$1[key] = createCahillKeyesEngine();
7702
7672
  } else if (key == 'butterfly') {
7703
- engines[key] = createButterflyEngine();
7673
+ engines$1[key] = createButterflyEngine();
7704
7674
  } else {
7705
7675
  throw new Error('Unknown butterfly projection: ' + method);
7706
7676
  }
7707
7677
  }
7708
- return engines[key];
7678
+ return engines$1[key];
7709
7679
  }
7710
7680
 
7711
7681
  function initButterfly(P, method) {
7712
7682
  var engine = getButterflyEngine(method);
7713
7683
  if (!P.params.lon_0) {
7714
- P.lam0 = DEFAULT_LON0[method] * D2R$1;
7684
+ P.lam0 = DEFAULT_LON0[method] * D2R$2;
7715
7685
  }
7716
7686
  P.es = 0;
7717
7687
  P.inv = null;
@@ -7724,7 +7694,7 @@
7724
7694
  xy.y = p[1];
7725
7695
  }
7726
7696
  };
7727
- P.__projection_topology = engine.getTopology(P.lam0 * R2D$1);
7697
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$2);
7728
7698
  if (engine.removeOutlineExtremeConnectors) {
7729
7699
  P.__remove_outline_extreme_connectors = true;
7730
7700
  }
@@ -7738,8 +7708,8 @@
7738
7708
  // Reuse the Cahill-Keyes polar incisions and 12-zone octant transform,
7739
7709
  // then unfold the faces with the butterfly attachment tree.
7740
7710
  var data = createTruncatedOctahedronFaces(
7741
- Math.cos(17 * D2R$1),
7742
- Math.sin(17 * D2R$1),
7711
+ Math.cos(17 * D2R$2),
7712
+ Math.sin(17 * D2R$2),
7743
7713
  BUTTERFLY_PARENTS
7744
7714
  );
7745
7715
  var faceRaw = createCahillKeyesFaceRaw(10000);
@@ -7752,9 +7722,9 @@
7752
7722
  findFace: createTruncatedFaceFinder(data.cornerNormals),
7753
7723
  faceProjector: function(face) {
7754
7724
  var baseId = face.id < 8 ? face.id : data.parents[face.id];
7755
- var center = faceCenters[baseId] * D2R$1;
7725
+ var center = faceCenters[baseId] * D2R$2;
7756
7726
  var raw = function(lam, phi) {
7757
- return faceRaw(normalizeRadians(lam - center), phi);
7727
+ return faceRaw(normalizeRadians$1(lam - center), phi);
7758
7728
  };
7759
7729
  return createNormalizedFacetProjector(face.coords, raw);
7760
7730
  }
@@ -7767,7 +7737,7 @@
7767
7737
  // Remove the global placement and scale of a raw facet while preserving its
7768
7738
  // internal shape. The polyhedral engine then controls how facets unfold.
7769
7739
  var points = coords.map(function(p) {
7770
- return raw(p[0] * D2R$1, p[1] * D2R$1);
7740
+ return raw(p[0] * D2R$2, p[1] * D2R$2);
7771
7741
  });
7772
7742
  var edge = 0;
7773
7743
  var maxLengthSq = -1;
@@ -7856,8 +7826,8 @@
7856
7826
 
7857
7827
  function createCahillKeyesEngine() {
7858
7828
  var data = createTruncatedOctahedronFaces(
7859
- Math.cos(17 * D2R$1),
7860
- Math.sin(17 * D2R$1),
7829
+ Math.cos(17 * D2R$2),
7830
+ Math.sin(17 * D2R$2),
7861
7831
  [-1, 3, 0, 2, 0, 1, 4, 5]
7862
7832
  );
7863
7833
  var raw = createCahillKeyesRaw(10000);
@@ -7898,10 +7868,10 @@
7898
7868
  var a = vectors[vectors.length - 1];
7899
7869
  vectors.forEach(function(b) {
7900
7870
  hexagon.push(
7901
- vectorToDegrees(normalizeVector(addScaledVectors(
7871
+ vectorToDegrees(normalizeVector$1(addScaledVectors(
7902
7872
  a, edgeWeight, b, vertexWeight
7903
7873
  ))),
7904
- vectorToDegrees(normalizeVector(addScaledVectors(
7874
+ vectorToDegrees(normalizeVector$1(addScaledVectors(
7905
7875
  b, edgeWeight, a, vertexWeight
7906
7876
  )))
7907
7877
  );
@@ -8002,7 +7972,7 @@
8002
7972
  }
8003
7973
 
8004
7974
  function planarAngle(p, project) {
8005
- var q = project(p[0] * D2R$1, p[1] * D2R$1);
7975
+ var q = project(p[0] * D2R$2, p[1] * D2R$2);
8006
7976
  return Math.atan2(q[1], q[0]);
8007
7977
  }
8008
7978
 
@@ -8036,16 +8006,16 @@
8036
8006
  }
8037
8007
 
8038
8008
  function degreesToVector(p) {
8039
- var lam = p[0] * D2R$1;
8040
- var phi = p[1] * D2R$1;
8009
+ var lam = p[0] * D2R$2;
8010
+ var phi = p[1] * D2R$2;
8041
8011
  var cosPhi = Math.cos(phi);
8042
8012
  return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
8043
8013
  }
8044
8014
 
8045
8015
  function vectorToDegrees(p) {
8046
8016
  return [
8047
- Math.atan2(p[1], p[0]) * R2D$1,
8048
- Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$1
8017
+ Math.atan2(p[1], p[0]) * R2D$2,
8018
+ Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$2
8049
8019
  ];
8050
8020
  }
8051
8021
 
@@ -8069,12 +8039,12 @@
8069
8039
  return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
8070
8040
  }
8071
8041
 
8072
- function normalizeVector(p) {
8042
+ function normalizeVector$1(p) {
8073
8043
  var k = 1 / Math.sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
8074
8044
  return [p[0] * k, p[1] * k, p[2] * k];
8075
8045
  }
8076
8046
 
8077
- function normalizeRadians(lam) {
8047
+ function normalizeRadians$1(lam) {
8078
8048
  return (lam + Math.PI * 3) % (Math.PI * 2) - Math.PI;
8079
8049
  }
8080
8050
 
@@ -8085,9 +8055,493 @@
8085
8055
  registerButterflyProjections: registerButterflyProjections
8086
8056
  });
8087
8057
 
8058
+ /*
8059
+ * Forward implementation of Hajime Narukawa's 2022 mathematical
8060
+ * approximation of the AuthaGraph construction.
8061
+ *
8062
+ * Facet formula:
8063
+ * H. Narukawa, "Formulation of AuthaGraph Map Projection" (2022)
8064
+ * https://www.jstage.jst.go.jp/article/jjca/60/1/60_1/_article/-char/en
8065
+ *
8066
+ * The rectangular facet routing follows the public Imago arrangement by
8067
+ * Justin Kunimune. The face transform itself uses Narukawa's published
8068
+ * equations, not Imago's power-law approximation.
8069
+ */
8070
+
8071
+ var D2R$1 = Math.PI / 180;
8072
+ var R2D$1 = 180 / Math.PI;
8073
+ 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);
8077
+ var EDGE_SCALE = Math.acos(-1 / 3) / 2;
8078
+ var XMIN = -2 * SQRT3;
8079
+ var XMAX = 2 * SQRT3;
8080
+ var YMIN = -1.5;
8081
+ var YMAX = 1.5;
8082
+ var BLOCK_HEIGHT = 2 * SQRT3;
8083
+ var LAYOUT_SHIFT = 1.16;
8084
+ var EPS = 1e-12;
8085
+ var engines = {};
8086
+
8087
+ // The four tetrahedron vertices published by Narukawa, in latitude-longitude
8088
+ // order. The extra precision preserves the regular tetrahedron to about 1e-9
8089
+ // in vector dot products.
8090
+ var GEOGRAPHIC_VERTICES = [
8091
+ [76.8810628, 149.4509913],
8092
+ [-27.9527772, 97.3570035],
8093
+ [-6.6370473, -18.8522325],
8094
+ [-22.9282364, -133.2827588]
8095
+ ];
8096
+
8097
+ // D3 Imago's vertex-oriented tetrahedral block. Each entry contains the
8098
+ // spherical center, local meridian, planar rotation and planar center.
8099
+ 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]
8104
+ ];
8105
+
8106
+ function registerNarukawa2022Projection(mproj) {
8107
+ if (!mproj || mproj.internal.pj_list.narukawa2022) return;
8108
+ mproj.pj_add(function(P) {
8109
+ initNarukawa2022(P);
8110
+ }, 'narukawa2022', 'Narukawa 2022 tetrahedral world map');
8111
+ }
8112
+
8113
+ function getNarukawa2022Engine() {
8114
+ if (!engines.default) {
8115
+ engines.default = createNarukawa2022Engine();
8116
+ }
8117
+ return engines.default;
8118
+ }
8119
+
8120
+ function initNarukawa2022(P) {
8121
+ var engine = getNarukawa2022Engine();
8122
+ P.es = 0;
8123
+ P.inv = null;
8124
+ P.fwd = function(lp, xy) {
8125
+ var p = engine.forward(lp.lam, lp.phi);
8126
+ xy.x = p[0];
8127
+ xy.y = p[1];
8128
+ };
8129
+ P.__projection_topology = engine.getTopology(P.lam0 * R2D$1);
8130
+ P.__projected_outline = engine.outline;
8131
+ }
8132
+
8133
+ function createNarukawa2022Engine() {
8134
+ var orientation = createPublishedOrientation();
8135
+ var facets = FACET_DEFS.map(function(def, i) {
8136
+ return {
8137
+ id: i,
8138
+ x: def[0],
8139
+ y: def[1],
8140
+ lat: def[2],
8141
+ lon: def[3],
8142
+ meridian: def[4],
8143
+ rotation: def[5]
8144
+ };
8145
+ });
8146
+ var outline = [[
8147
+ [XMIN * EDGE_SCALE, YMIN * EDGE_SCALE],
8148
+ [XMAX * EDGE_SCALE, YMIN * EDGE_SCALE],
8149
+ [XMAX * EDGE_SCALE, YMAX * EDGE_SCALE],
8150
+ [XMIN * EDGE_SCALE, YMAX * EDGE_SCALE],
8151
+ [XMIN * EDGE_SCALE, YMIN * EDGE_SCALE]
8152
+ ]];
8153
+
8154
+ return {
8155
+ forward: forward,
8156
+ inverse: inverse,
8157
+ outline: outline,
8158
+ getTopology: getTopology
8159
+ };
8160
+
8161
+ function forward(lam, phi) {
8162
+ var state = projectState(lam, phi);
8163
+ return [state.x * EDGE_SCALE, state.y * EDGE_SCALE];
8164
+ }
8165
+
8166
+ // Internal inverse used only for tracing the geographic rectangular cut.
8167
+ // P.inv remains null because the full Mapshaper inverse path is unsupported.
8168
+ function inverse(x, y) {
8169
+ var p = invertLayout(x / EDGE_SCALE, y / EDGE_SCALE, facets);
8170
+ if (!p) return null;
8171
+ return fromCanonical(p[0], p[1], orientation);
8172
+ }
8173
+
8174
+ function projectState(lam, phi) {
8175
+ var p = toCanonical(lam, phi, orientation);
8176
+ var state = projectCanonical(p[0], p[1], facets);
8177
+ state.region = encodeRegion(state);
8178
+ return state;
8179
+ }
8180
+
8181
+ function getTopology(lon0) {
8182
+ var paths = createCutPaths(inverse, lon0);
8183
+ return {
8184
+ regions: createRegionIndex(),
8185
+ seams: [{
8186
+ type: 'cut',
8187
+ paths: paths
8188
+ }],
8189
+ findRegion: findRegion,
8190
+ findTransitionRegion: findRegion,
8191
+ outline: outline.map(function(ring) {
8192
+ return ring.map(function(p) {
8193
+ return p.concat();
8194
+ });
8195
+ })
8196
+ };
8197
+
8198
+ function findRegion(lon, lat) {
8199
+ var lam = normalizeRadians((lon - lon0) * D2R$1);
8200
+ return projectState(lam, lat * D2R$1).region;
8201
+ }
8202
+ }
8203
+ }
8204
+
8205
+ function projectCanonical(lam, phi, facets) {
8206
+ var facet = findForwardFacet(lam, phi, facets);
8207
+ var relative = obliquifySpherical(phi, lam, facet);
8208
+ var sector = Math.floor((relative[1] + Math.PI / 3) / (2 * Math.PI / 3));
8209
+ var base = sector * 2 * Math.PI / 3;
8210
+ var polar = narukawaFaceForward(relative[1] - base, relative[0]);
8211
+ var angle = polar[1] + facet.rotation + base / 2;
8212
+ var x = polar[0] * Math.cos(angle) + facet.x;
8213
+ var y = polar[0] * Math.sin(angle) + facet.y;
8214
+ var oob = 0;
8215
+ var folded = 0;
8216
+ var wrap = 0;
8217
+
8218
+ if (Math.abs(x) > 3 + EPS) {
8219
+ x = 2 * facet.x - x;
8220
+ y = -y;
8221
+ oob = 1;
8222
+ } else if (Math.abs(y) > SQRT3 + EPS) {
8223
+ x = -x;
8224
+ y = BLOCK_HEIGHT * Math.sign(y) - y;
8225
+ oob = 2;
8226
+ }
8227
+
8228
+ var qx = y;
8229
+ var qy = -x;
8230
+ if (qy > EPS) {
8231
+ qx = BLOCK_HEIGHT - qx;
8232
+ qy = -qy;
8233
+ folded = 1;
8234
+ }
8235
+ qx += LAYOUT_SHIFT;
8236
+ if (qx < 0) {
8237
+ qx += 2 * BLOCK_HEIGHT;
8238
+ wrap = 1;
8239
+ }
8240
+ x = qx - BLOCK_HEIGHT;
8241
+ y = qy + 1.5;
8242
+ x = clamp$2(x, XMIN, XMAX);
8243
+ y = clamp$2(y, YMIN, YMAX);
8244
+ return {
8245
+ x: x,
8246
+ y: y,
8247
+ facet: facet.id,
8248
+ sector: mod(sector, 3),
8249
+ oob: oob,
8250
+ folded: folded,
8251
+ wrap: wrap
8252
+ };
8253
+ }
8254
+
8255
+ function findForwardFacet(lam, phi, facets) {
8256
+ var best = null;
8257
+ var bestLat = -Infinity;
8258
+ for (var i = 0; i < 4; i++) {
8259
+ var facet = facets[i];
8260
+ var relative = obliquifySpherical(phi, lam, facet);
8261
+ if (relative[0] > bestLat) {
8262
+ bestLat = relative[0];
8263
+ best = facet;
8264
+ }
8265
+ }
8266
+ return best;
8267
+ }
8268
+
8269
+ 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);
8273
+ var q = denominator > 0 ? (2 + Math.cos(lam)) / denominator : 0;
8274
+ var r = q * SQRT3 / Math.cos(theta);
8275
+ return [r, theta];
8276
+ }
8277
+
8278
+ function narukawaFaceInverse(r, theta) {
8279
+ var target = Math.tan(theta) * Math.PI / (2 * SQRT3);
8280
+ var lo = -Math.PI / 3;
8281
+ var hi = Math.PI / 3;
8282
+ var lam;
8283
+ for (var i = 0; i < 55; i++) {
8284
+ lam = (lo + hi) / 2;
8285
+ var a = lam - Math.asin(Math.sin(lam) / SQRT3);
8286
+ if (a < target) lo = lam;
8287
+ else hi = lam;
8288
+ }
8289
+ 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);
8293
+ return [phi, lam];
8294
+ }
8295
+
8296
+ function invertLayout(x, y, facets) {
8297
+ var qx = x + BLOCK_HEIGHT;
8298
+ var qy = y - 1.5;
8299
+ var normalizedX = (qx - LAYOUT_SHIFT) / BLOCK_HEIGHT;
8300
+ if (normalizedX > 1.5) normalizedX -= 2;
8301
+ if (normalizedX > 0.5) {
8302
+ normalizedX = 1 - normalizedX;
8303
+ qy *= -1;
8304
+ }
8305
+ x = -qy;
8306
+ y = normalizedX * BLOCK_HEIGHT;
8307
+
8308
+ var facet = findInverseFacet(x, y, facets);
8309
+ var dx = x - facet.x;
8310
+ var dy = y - facet.y;
8311
+ var r = Math.hypot(dx, dy);
8312
+ var theta = normalizeRadians(Math.atan2(dy, dx) - facet.rotation);
8313
+ var base = Math.floor((theta + Math.PI / 6) / (Math.PI / 3)) *
8314
+ Math.PI / 3;
8315
+ var relative = narukawaFaceInverse(r, theta - base);
8316
+ relative[1] += base * 2;
8317
+ var p = deobliquifySpherical(relative[0], relative[1], facet);
8318
+ return [p[1], p[0]];
8319
+ }
8320
+
8321
+ function findInverseFacet(x, y, facets) {
8322
+ var best = null;
8323
+ var minDistance = Infinity;
8324
+ facets.forEach(function(facet) {
8325
+ var d = Math.hypot(x - facet.x, y - facet.y);
8326
+ if (d < minDistance) {
8327
+ minDistance = d;
8328
+ best = facet;
8329
+ }
8330
+ });
8331
+ return best;
8332
+ }
8333
+
8334
+ function createPublishedOrientation() {
8335
+ // Match the D3 Imago arrangement: the third published vertex is the
8336
+ // canonical southern vertex at longitude zero.
8337
+ var north = latLonToVector(GEOGRAPHIC_VERTICES[0]);
8338
+ var south = latLonToVector(GEOGRAPHIC_VERTICES[2]);
8339
+ var tangent = normalizeVector(subtract(
8340
+ south,
8341
+ multiply(north, dot$1(south, north))
8342
+ ));
8343
+ var x = tangent;
8344
+ var y = cross$1(north, tangent);
8345
+ return {x: x, y: y, z: north};
8346
+ }
8347
+
8348
+ function toCanonical(lam, phi, orientation) {
8349
+ var v = radiansToVector(lam, phi);
8350
+ return [
8351
+ Math.atan2(dot$1(v, orientation.y), dot$1(v, orientation.x)),
8352
+ Math.asin(clamp$2(dot$1(v, orientation.z), -1, 1))
8353
+ ];
8354
+ }
8355
+
8356
+ function fromCanonical(lam, phi, orientation) {
8357
+ var v = radiansToVector(lam, phi);
8358
+ var p = [
8359
+ orientation.x[0] * v[0] + orientation.y[0] * v[1] + orientation.z[0] * v[2],
8360
+ orientation.x[1] * v[0] + orientation.y[1] * v[1] + orientation.z[1] * v[2],
8361
+ orientation.x[2] * v[0] + orientation.y[2] * v[1] + orientation.z[2] * v[2]
8362
+ ];
8363
+ return [Math.atan2(p[1], p[0]), Math.asin(clamp$2(p[2], -1, 1))];
8364
+ }
8365
+
8366
+ // Adapted from Justin Kunimune's Imago implementation.
8367
+ function obliquifySpherical(lat, lon, pole) {
8368
+ var lat0 = pole.lat;
8369
+ var lon0 = pole.lon;
8370
+ var theta0 = pole.meridian;
8371
+ var lat1;
8372
+ var lon1;
8373
+ if (Math.abs(lat0 - HALF_PI) < EPS) {
8374
+ lat1 = lat;
8375
+ lon1 = lon - lon0;
8376
+ } else {
8377
+ lat1 = Math.asin(clamp$2(
8378
+ Math.sin(lat0) * Math.sin(lat) +
8379
+ Math.cos(lat0) * Math.cos(lat) * Math.cos(lon0 - lon),
8380
+ -1,
8381
+ 1
8382
+ ));
8383
+ var denominator = Math.cos(lat1);
8384
+ var value = denominator < EPS ? 1 :
8385
+ (Math.cos(lat0) * Math.sin(lat) -
8386
+ Math.sin(lat0) * Math.cos(lat) * Math.cos(lon0 - lon)) /
8387
+ denominator;
8388
+ lon1 = Math.acos(clamp$2(value, -1, 1)) - Math.PI;
8389
+ if (Math.sin(lon - lon0) > 0) lon1 = -lon1;
8390
+ }
8391
+ return [lat1, normalizeRadians(lon1 - theta0)];
8392
+ }
8393
+
8394
+ function deobliquifySpherical(lat, lon, pole) {
8395
+ var lat0 = pole.lat;
8396
+ var lon0 = pole.lon;
8397
+ lon += pole.meridian;
8398
+ var latOut = Math.asin(clamp$2(
8399
+ Math.sin(lat0) * Math.sin(lat) -
8400
+ Math.cos(lat0) * Math.cos(lon) * Math.cos(lat),
8401
+ -1,
8402
+ 1
8403
+ ));
8404
+ var lonOut;
8405
+ if (Math.abs(lat0 - HALF_PI) < EPS) {
8406
+ lonOut = lon + lon0;
8407
+ } else {
8408
+ var value = Math.sin(lat) / Math.cos(lat0) / Math.cos(latOut) -
8409
+ Math.tan(lat0) * Math.tan(latOut);
8410
+ if (Math.sin(lon) > 0) lonOut = lon0 + Math.acos(clamp$2(value, -1, 1));
8411
+ else lonOut = lon0 - Math.acos(clamp$2(value, -1, 1));
8412
+ }
8413
+ return [latOut, normalizeRadians(lonOut)];
8414
+ }
8415
+
8416
+ function createCutPaths(inverse, lon0) {
8417
+ // The rectangular edges become moderately curved geographic seams. Sampling
8418
+ // at about 0.03 degrees prevents straight mask chords from missing crossings.
8419
+ var n = 6000;
8420
+ var epsilon = 1e-8;
8421
+ var edges = [
8422
+ [[XMIN + epsilon, YMIN], [XMIN + epsilon, YMAX]],
8423
+ [[XMIN, YMAX - epsilon], [XMAX, YMAX - epsilon]],
8424
+ [[XMIN, YMIN + epsilon], [XMAX, YMIN + epsilon]]
8425
+ ];
8426
+ var paths = edges.reduce(function(memo, edge) {
8427
+ var path = [];
8428
+ for (var i = 0; i <= n; i++) {
8429
+ var t = i / n;
8430
+ var x = edge[0][0] + (edge[1][0] - edge[0][0]) * t;
8431
+ var y = edge[0][1] + (edge[1][1] - edge[0][1]) * t;
8432
+ var p = inverse(x * EDGE_SCALE, y * EDGE_SCALE);
8433
+ path.push([
8434
+ normalizeLongitude$1(p[0] * R2D$1 + lon0),
8435
+ p[1] * R2D$1
8436
+ ]);
8437
+ }
8438
+ return memo.concat(splitPathAtAntimeridian$1(path));
8439
+ }, []);
8440
+ return paths.map(function(part) {
8441
+ part.mask_width = 4e-5;
8442
+ return part;
8443
+ });
8444
+ }
8445
+
8446
+ function splitPathAtAntimeridian$1(path) {
8447
+ var paths = [];
8448
+ var part = [path[0]];
8449
+ for (var i = 1; i < path.length; i++) {
8450
+ var a = path[i - 1];
8451
+ var b = path[i];
8452
+ if (Math.abs(a[0] - b[0]) > 180) {
8453
+ var adjusted = b[0] + (b[0] < a[0] ? 360 : -360);
8454
+ var edge = a[0] < 0 ? -180 : 180;
8455
+ var t = (edge - a[0]) / (adjusted - a[0]);
8456
+ var lat = a[1] + (b[1] - a[1]) * t;
8457
+ part.push([edge, lat]);
8458
+ paths.push(part);
8459
+ part = [[-edge, lat], b];
8460
+ } else {
8461
+ part.push(b);
8462
+ }
8463
+ }
8464
+ if (part.length > 1) paths.push(part);
8465
+ return paths;
8466
+ }
8467
+
8468
+ function encodeRegion(state) {
8469
+ return ((((state.facet * 3 + state.sector) * 3 + state.oob) * 2 +
8470
+ state.folded) * 2 + state.wrap);
8471
+ }
8472
+
8473
+ function createRegionIndex() {
8474
+ var regions = [];
8475
+ for (var i = 0; i < 144; i++) {
8476
+ regions.push({id: i});
8477
+ }
8478
+ return regions;
8479
+ }
8480
+
8481
+ function latLonToVector(p) {
8482
+ return radiansToVector(p[1] * D2R$1, p[0] * D2R$1);
8483
+ }
8484
+
8485
+ function radiansToVector(lam, phi) {
8486
+ var cosPhi = Math.cos(phi);
8487
+ return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
8488
+ }
8489
+
8490
+ function subtract(a, b) {
8491
+ return [a[0] - b[0], a[1] - b[1], a[2] - b[2]];
8492
+ }
8493
+
8494
+ function multiply(a, k) {
8495
+ return [a[0] * k, a[1] * k, a[2] * k];
8496
+ }
8497
+
8498
+ function normalizeVector(a) {
8499
+ var k = 1 / Math.hypot(a[0], a[1], a[2]);
8500
+ return multiply(a, k);
8501
+ }
8502
+
8503
+ function cross$1(a, b) {
8504
+ return [
8505
+ a[1] * b[2] - a[2] * b[1],
8506
+ a[2] * b[0] - a[0] * b[2],
8507
+ a[0] * b[1] - a[1] * b[0]
8508
+ ];
8509
+ }
8510
+
8511
+ function dot$1(a, b) {
8512
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
8513
+ }
8514
+
8515
+ function mod(a, n) {
8516
+ return (a % n + n) % n;
8517
+ }
8518
+
8519
+ function normalizeRadians(lam) {
8520
+ while (lam > Math.PI) lam -= 2 * Math.PI;
8521
+ while (lam < -Math.PI) lam += 2 * Math.PI;
8522
+ return lam;
8523
+ }
8524
+
8525
+ function normalizeLongitude$1(lon) {
8526
+ while (lon > 180) lon -= 360;
8527
+ while (lon < -180) lon += 360;
8528
+ return lon;
8529
+ }
8530
+
8531
+ function clamp$2(value, min, max) {
8532
+ return Math.max(min, Math.min(max, value));
8533
+ }
8534
+
8535
+ var Narukawa2022 = /*#__PURE__*/Object.freeze({
8536
+ __proto__: null,
8537
+ getNarukawa2022Engine: getNarukawa2022Engine,
8538
+ registerNarukawa2022Projection: registerNarukawa2022Projection
8539
+ });
8540
+
8088
8541
  var mproj$1 = require$1('mproj');
8089
8542
  registerDymaxionProjections(mproj$1);
8090
8543
  registerButterflyProjections(mproj$1);
8544
+ registerNarukawa2022Projection(mproj$1);
8091
8545
 
8092
8546
  var asyncLoader = null;
8093
8547
 
@@ -11075,7 +11529,7 @@
11075
11529
  function layerNameIsUnsafeFilename(name) {
11076
11530
  name = String(name);
11077
11531
  // path separators (directory traversal on any OS) or NUL
11078
- if (/[\/\\\0]/.test(name)) return true;
11532
+ if (/[/\\\0]/.test(name)) return true;
11079
11533
  // Windows drive-relative prefix, e.g. "C:foo" can write to another drive
11080
11534
  if (/^[A-Za-z]:/.test(name)) return true;
11081
11535
  return false;
@@ -40970,7 +41424,9 @@ ${svg}
40970
41424
  return finalizeImportedDataset(dataset, dataFmt, data, opts);
40971
41425
  }
40972
41426
 
40973
- async function importContentAsync(obj, opts) {
41427
+ // Canonical content import interface. Always resolves to an array because some
41428
+ // formats (notably GeoPackage) may contain datasets that cannot be merged.
41429
+ async function importDatasetsFromContent(obj, opts) {
40974
41430
  var dataset, dataFmt, data;
40975
41431
  opts = opts || {};
40976
41432
  if (obj.fgb) {
@@ -40994,14 +41450,16 @@ ${svg}
40994
41450
  data = obj[dataFmt];
40995
41451
  dataset = await importImageRaster(obj, opts);
40996
41452
  } else {
40997
- return importContent(obj, opts);
41453
+ return normalizeImportedDatasets$1(importContent(obj, opts));
40998
41454
  }
40999
- if (Array.isArray(dataset)) {
41000
- return dataset.map(function(ds) {
41001
- return finalizeImportedDataset(ds, dataFmt, data, opts);
41002
- });
41003
- }
41004
- return finalizeImportedDataset(dataset, dataFmt, data, opts);
41455
+ return normalizeImportedDatasets$1(dataset).map(function(ds) {
41456
+ return finalizeImportedDataset(ds, dataFmt, data, opts);
41457
+ });
41458
+ }
41459
+
41460
+ // Compatibility facade for callers that expect one dataset when possible.
41461
+ async function importContentAsync(obj, opts) {
41462
+ return denormalizeImportedDatasets$1(await importDatasetsFromContent(obj, opts));
41005
41463
  }
41006
41464
 
41007
41465
  // Deprecated (included for compatibility with older tests)
@@ -41012,6 +41470,14 @@ ${svg}
41012
41470
  return importContent(input, opts);
41013
41471
  }
41014
41472
 
41473
+ function normalizeImportedDatasets$1(datasetOrArray) {
41474
+ return Array.isArray(datasetOrArray) ? datasetOrArray : [datasetOrArray];
41475
+ }
41476
+
41477
+ function denormalizeImportedDatasets$1(datasets) {
41478
+ return datasets.length == 1 ? datasets[0] : datasets;
41479
+ }
41480
+
41015
41481
 
41016
41482
  function importShapefile(obj, opts) {
41017
41483
  var shpSrc = obj.shp.content || obj.shp.filename, // read from a file if (binary) content is missing
@@ -41094,6 +41560,7 @@ ${svg}
41094
41560
  __proto__: null,
41095
41561
  importContent: importContent,
41096
41562
  importContentAsync: importContentAsync,
41563
+ importDatasetsFromContent: importDatasetsFromContent,
41097
41564
  importFileContent: importFileContent
41098
41565
  });
41099
41566
 
@@ -41262,8 +41729,7 @@ ${svg}
41262
41729
  var dataset, datasets, target;
41263
41730
 
41264
41731
  if (opts.stdin) {
41265
- dataset = await importFileAsync('/dev/stdin', opts);
41266
- datasets = normalizeImportedDatasets(dataset);
41732
+ datasets = await importDatasetsFromFile('/dev/stdin', opts);
41267
41733
  catalog.addDatasets(datasets);
41268
41734
  if (datasets.length > 1) {
41269
41735
  catalog.setDefaultTargets(datasets.map(function(ds) {
@@ -41301,11 +41767,11 @@ ${svg}
41301
41767
  }
41302
41768
 
41303
41769
  if (files.length == 1) {
41304
- dataset = await importFileAsync(files[0], opts);
41770
+ datasets = await importDatasetsFromFile(files[0], opts);
41305
41771
  } else {
41306
41772
  dataset = await importFilesTogetherAsync(files, opts);
41773
+ datasets = [dataset];
41307
41774
  }
41308
- datasets = normalizeImportedDatasets(dataset);
41309
41775
  datasets = validateAndCleanGpkgSelection(datasets, opts);
41310
41776
 
41311
41777
  if (opts.merge_files && files.length > 1) {
@@ -41422,9 +41888,12 @@ ${svg}
41422
41888
  });
41423
41889
  }
41424
41890
 
41425
- // Let the web UI replace importFile() with a browser-friendly version
41891
+ // Let the web UI replace path-based imports with a browser-friendly resolver.
41426
41892
  function replaceImportFile(func) {
41427
41893
  _importFile = func;
41894
+ _importDatasetsFromFile = async function(path, opts) {
41895
+ return normalizeImportedDatasets(await func(path, opts));
41896
+ };
41428
41897
  }
41429
41898
 
41430
41899
  function importFile(path, opts) {
@@ -41432,69 +41901,29 @@ ${svg}
41432
41901
  }
41433
41902
 
41434
41903
  async function importFileAsync(path, opts) {
41435
- return _importFileAsync(path, opts);
41904
+ return denormalizeImportedDatasets(await importDatasetsFromFile(path, opts));
41436
41905
  }
41437
41906
 
41438
- var _importFile = function(path, opts) {
41439
- var fileType = guessInputFileType(path),
41440
- input = {},
41441
- encoding = opts && opts.encoding || null,
41442
- cache = opts && opts.input || null,
41443
- cached = cache && (path in cache),
41444
- content;
41445
-
41446
- cli.checkFileExists(path, cache);
41447
-
41448
- if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf' ||
41449
- fileType == 'gpkg') && !cached) {
41450
- // these file types are read incrementally
41451
- content = null;
41452
-
41453
- } else if (fileType && isSupportedBinaryInputType(path)) {
41454
- content = cli.readFile(path, null, cache);
41455
- if (utils.isString(content)) {
41456
- // Fix for issue #264 (applyCommands() input is file path instead of binary content)
41457
- stop$1('Expected binary content, received a string');
41458
- }
41459
-
41460
- } else if (fileType) { // string type, e.g. kml, geojson
41461
- content = cli.readFile(path, encoding || 'utf-8', cache);
41462
-
41463
- } else if (getFileExtension(path) == 'gz') {
41464
- var pathgz = path;
41465
- path = pathgz.replace(/\.gz$/, '');
41466
- fileType = guessInputFileType(path);
41467
- if (!fileType) {
41468
- stop$1('Unrecognized file type:', path);
41469
- }
41470
- content = gunzipSync(cli.readFile(pathgz, null, cache), path);
41471
-
41472
- } else { // type can't be inferred from filename -- try reading as text
41473
- content = cli.readFile(path, encoding || 'utf-8', cache);
41474
- fileType = guessInputContentType(content);
41475
- if (fileType == 'text' && content.indexOf('\ufffd') > -1) {
41476
- // invalidate string data that contains the 'replacement character'
41477
- fileType = null;
41478
- }
41479
- }
41907
+ // Canonical path import interface.
41908
+ async function importDatasetsFromFile(path, opts) {
41909
+ return _importDatasetsFromFile(path, opts);
41910
+ }
41480
41911
 
41481
- if (!fileType) {
41482
- stop$1(getUnsupportedFileMessage(path));
41483
- }
41484
- input[fileType] = {filename: path, content: content};
41485
- content = null; // for g.c.
41486
- if (fileType == 'shp' || fileType == 'dbf') {
41487
- readShapefileAuxFiles(path, input, cache);
41488
- } else if (isRasterImageInputType(fileType)) {
41489
- readRasterImageAuxFiles(path, input, cache);
41490
- }
41491
- if (fileType == 'shp' && !input.dbf) {
41492
- message(utils.format("[%s] .dbf file is missing - shapes imported without attribute data.", path));
41493
- }
41912
+ var _importFile = function(path, opts) {
41913
+ var input = prepareImportFile(path, opts);
41494
41914
  return importContent(input, opts);
41495
41915
  };
41496
41916
 
41497
- async function _importFileAsync(path, opts) {
41917
+ var _importDatasetsFromFile = async function(path, opts) {
41918
+ var input = prepareImportFile(path, opts);
41919
+ return importDatasetsFromContent(input, opts);
41920
+ };
41921
+
41922
+ // Read a file (or cache entry) and collect any sidecars into the normalized
41923
+ // content-group shape consumed by the content importers.
41924
+ // File acquisition is currently synchronous in both import paths; only some
41925
+ // format parsers require asynchronous work.
41926
+ function prepareImportFile(path, opts) {
41498
41927
  var fileType = guessInputFileType(path),
41499
41928
  input = {},
41500
41929
  encoding = opts && opts.encoding || null,
@@ -41504,7 +41933,8 @@ ${svg}
41504
41933
 
41505
41934
  cli.checkFileExists(path, cache);
41506
41935
 
41507
- if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf') && !cached) {
41936
+ if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf' ||
41937
+ fileType == 'gpkg') && !cached) {
41508
41938
  // these file types are read incrementally
41509
41939
  content = null;
41510
41940
 
@@ -41547,37 +41977,10 @@ ${svg}
41547
41977
  if (fileType == 'shp' && !input.dbf) {
41548
41978
  message(utils.format("[%s] .dbf file is missing - shapes imported without attribute data.", path));
41549
41979
  }
41550
- return fileType == 'gpkg' || fileType == 'fgb' || fileType == 'parquet' || fileType == 'geotiff' || isRasterImageInputType(fileType) ? importContentAsync(input, opts) : importContent(input, opts);
41551
- }
41552
-
41553
- // Import multiple files to a single dataset
41554
- function importFilesTogether(files, opts) {
41555
- var unbuiltTopology = false;
41556
- var datasets = files.reduce(function(memo, fname) {
41557
- // import without topology or snapping
41558
- var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
41559
- var imported = normalizeImportedDatasets(importFile(fname, importOpts));
41560
- // check if dataset contains non-topological paths
41561
- // TODO: may also need to rebuild topology if multiple topojson files are merged
41562
- imported.forEach(function(dataset) {
41563
- if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
41564
- unbuiltTopology = true;
41565
- }
41566
- memo.push(dataset);
41567
- });
41568
- return memo;
41569
- }, []);
41570
- var combined = mergeDatasets(datasets);
41571
- // Build topology, if needed
41572
- // TODO: consider updating topology of TopoJSON files instead of concatenating arcs
41573
- // (but problem of mismatched coordinates due to quantization in input files.)
41574
- if (unbuiltTopology && !opts.no_topology) {
41575
- cleanPathsAfterImport(combined, opts);
41576
- buildTopology(combined);
41577
- }
41578
- return combined;
41980
+ return input;
41579
41981
  }
41580
41982
 
41983
+ // Import multiple files to a single dataset.
41581
41984
  async function importFilesTogetherAsync(files, opts) {
41582
41985
  var unbuiltTopology = false;
41583
41986
  var datasets = [];
@@ -41585,7 +41988,7 @@ ${svg}
41585
41988
  for (var fname of files) {
41586
41989
  // import without topology or snapping
41587
41990
  var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
41588
- var imported = normalizeImportedDatasets(await importFileAsync(fname, importOpts));
41991
+ var imported = await importDatasetsFromFile(fname, importOpts);
41589
41992
  imported.forEach(function(dataset) {
41590
41993
  if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
41591
41994
  unbuiltTopology = true;
@@ -41647,6 +42050,10 @@ ${svg}
41647
42050
  return Array.isArray(datasetOrArray) ? datasetOrArray : [datasetOrArray];
41648
42051
  }
41649
42052
 
42053
+ function denormalizeImportedDatasets(datasets) {
42054
+ return datasets.length == 1 ? datasets[0] : datasets;
42055
+ }
42056
+
41650
42057
  function normalizeImportedTarget(datasets) {
41651
42058
  if (datasets.length == 1) return datasets[0];
41652
42059
  return {
@@ -41746,9 +42153,9 @@ ${svg}
41746
42153
 
41747
42154
  var FileImport = /*#__PURE__*/Object.freeze({
41748
42155
  __proto__: null,
42156
+ importDatasetsFromFile: importDatasetsFromFile,
41749
42157
  importFile: importFile,
41750
42158
  importFileAsync: importFileAsync,
41751
- importFilesTogether: importFilesTogether,
41752
42159
  importFilesTogetherAsync: importFilesTogetherAsync,
41753
42160
  replaceImportFile: replaceImportFile
41754
42161
  });
@@ -41778,31 +42185,37 @@ ${svg}
41778
42185
  return /[$][{]/.test(name);
41779
42186
  }
41780
42187
 
41781
- function findCommandSource(sourceName, catalog, opts) {
42188
+ async function findCommandSourceAsync(sourceName, catalog, opts) {
41782
42189
  var source = catalog.findSingleLayer(sourceName);
41783
- var sourceDataset;
42190
+ var sourceDatasets;
41784
42191
  if (!source) {
41785
- // assuming opts.source is a filename
41786
- // don't need to build topology, because:
41787
- // join -- don't need topology
41788
- // clip/erase -- topology is built later, when datasets are combined
41789
- sourceDataset = importFile(sourceName, utils.defaults({no_topology: true}, opts));
41790
- if (!sourceDataset) {
41791
- stop$1(utils.format('Unable to find source [%s]', sourceName));
41792
- } else if (sourceDataset.layers.length > 1) {
41793
- stop$1('Multiple-layer sources are not supported');
41794
- }
41795
- // mark as disposable to indicate that data can be mutated
41796
- source = {dataset: sourceDataset, layer: sourceDataset.layers[0], disposable: true};
42192
+ // Source-file topology is built later if it is needed by the command.
42193
+ sourceDatasets = await importDatasetsFromFile(sourceName, utils.defaults({no_topology: true}, opts));
42194
+ source = getImportedSource(sourceDatasets, sourceName);
41797
42195
  }
41798
42196
  return source;
41799
42197
  }
41800
42198
 
42199
+ function getImportedSource(sourceDatasets, sourceName) {
42200
+ if (sourceDatasets.length != 1) {
42201
+ if (sourceDatasets.length > 1) {
42202
+ stop$1('Multiple-dataset sources are not supported');
42203
+ }
42204
+ stop$1(utils.format('Unable to find source [%s]', sourceName));
42205
+ }
42206
+ var sourceDataset = sourceDatasets[0];
42207
+ if (sourceDataset.layers.length > 1) {
42208
+ stop$1('Multiple-layer sources are not supported');
42209
+ }
42210
+ // mark as disposable to indicate that data can be mutated
42211
+ return {dataset: sourceDataset, layer: sourceDataset.layers[0], disposable: true};
42212
+ }
42213
+
41801
42214
  var SourceUtils = /*#__PURE__*/Object.freeze({
41802
42215
  __proto__: null,
41803
42216
  convertInterpolatedName: convertInterpolatedName,
41804
42217
  convertSourceName: convertSourceName,
41805
- findCommandSource: findCommandSource
42218
+ findCommandSourceAsync: findCommandSourceAsync
41806
42219
  });
41807
42220
 
41808
42221
  // Catalog contains zero or more multi-layer datasets
@@ -43657,6 +44070,13 @@ ${svg}
43657
44070
  return new GeographicLib.Geodesic.Geodesic(P.a, f);
43658
44071
  }
43659
44072
 
44073
+ function getGeodesicDistanceFunction(P) {
44074
+ var geod = getGeodesic(P);
44075
+ return function(lng, lat, lng2, lat2) {
44076
+ return geod.Inverse(lat, lng, lat2, lng2).s12;
44077
+ };
44078
+ }
44079
+
43660
44080
  function interpolatePoint2D(ax, ay, bx, by, k) {
43661
44081
  var j = 1 - k;
43662
44082
  return [ax * j + bx * k, ay * j + by * k];
@@ -43759,6 +44179,7 @@ ${svg}
43759
44179
  bearingDegrees2D: bearingDegrees2D,
43760
44180
  getBearingFunction: getBearingFunction,
43761
44181
  getFastGeodeticSegmentFunction: getFastGeodeticSegmentFunction,
44182
+ getGeodesicDistanceFunction: getGeodesicDistanceFunction,
43762
44183
  getGeodeticSegmentFunction: getGeodeticSegmentFunction,
43763
44184
  getInterpolationFunction: getInterpolationFunction,
43764
44185
  getPlanarSegmentEndpoint: getPlanarSegmentEndpoint,
@@ -45199,7 +45620,7 @@ ${svg}
45199
45620
 
45200
45621
  function stopIfBufferReachesPole(shape, dist) {
45201
45622
  var maxAbsLat = 0;
45202
- var angularDist = dist / R$3 * R2D$5;
45623
+ var angularDist = dist / R$3 * R2D$6;
45203
45624
  (shape || []).forEach(function(path) {
45204
45625
  latLngPathIter.init(path);
45205
45626
  while (latLngPathIter.hasNext()) {
@@ -47316,12 +47737,12 @@ ${svg}
47316
47737
  }
47317
47738
 
47318
47739
  function projectBufferPoint(x, y, spherical) {
47319
- return spherical ? [x * D2R$6 * R$3, Math.log(Math.tan(Math.PI / 4 + y * D2R$6 / 2)) * R$3] :
47740
+ return spherical ? [x * D2R$7 * R$3, Math.log(Math.tan(Math.PI / 4 + y * D2R$7 / 2)) * R$3] :
47320
47741
  [x, y];
47321
47742
  }
47322
47743
 
47323
47744
  function unprojectBufferPoint(x, y, spherical) {
47324
- return spherical ? [x / (D2R$6 * R$3), (2 * Math.atan(Math.exp(y / R$3)) - Math.PI / 2) / (D2R$6)] :
47745
+ return spherical ? [x / (D2R$7 * R$3), (2 * Math.atan(Math.exp(y / R$3)) - Math.PI / 2) / (D2R$7)] :
47325
47746
  [x, y];
47326
47747
  }
47327
47748
 
@@ -51992,7 +52413,7 @@ ${svg}
51992
52413
  var maxAbsLat = Math.max(Math.abs(bounds.ymin), Math.abs(bounds.ymax));
51993
52414
  var maxPositiveDistance = getMaxPositiveBufferDistance(lyr, dataset, opts);
51994
52415
  if (!(maxPositiveDistance > 0)) return false;
51995
- return maxAbsLat + maxPositiveDistance / R$3 * R2D$5 >= 90 - POLAR_BUFFER_MARGIN_DEGREES;
52416
+ return maxAbsLat + maxPositiveDistance / R$3 * R2D$6 >= 90 - POLAR_BUFFER_MARGIN_DEGREES;
51996
52417
  }
51997
52418
 
51998
52419
  function getMaxPositiveBufferDistance(lyr, dataset, opts) {
@@ -53244,7 +53665,7 @@ ${svg}
53244
53665
  }
53245
53666
 
53246
53667
  function getCoordinateDistance(distance, arcs) {
53247
- return arcs.isPlanar() ? distance : distance / R$3 * R2D$5;
53668
+ return arcs.isPlanar() ? distance : distance / R$3 * R2D$6;
53248
53669
  }
53249
53670
 
53250
53671
  // @shapeIndex: chunk-bounds index of the source shape (see buildShapeSegmentIndex)
@@ -53913,7 +54334,7 @@ ${svg}
53913
54334
  // depending on parameters
53914
54335
  if (inList(P, 'cassini,gnom,bertin1953,chamb,ob_tran,tpeqd,healpix,rhealpix,' +
53915
54336
  'ocea,omerc,tmerc,etmerc,nicol,dymaxion,dymaxion2,butterfly,butterfly2,' +
53916
- 'cahill_keyes')) {
54337
+ 'cahill_keyes,narukawa2022')) {
53917
54338
  return false;
53918
54339
  }
53919
54340
  if (isAzimuthal(P)) {
@@ -53965,16 +54386,16 @@ ${svg}
53965
54386
  }
53966
54387
 
53967
54388
  function getRotationFunction2(rotation, inv) {
53968
- var a = (rotation[0] || 0) * D2R$6,
53969
- b = (rotation[1] || 0) * D2R$6,
53970
- c = (rotation[2] || 0) * D2R$6;
54389
+ var a = (rotation[0] || 0) * D2R$7,
54390
+ b = (rotation[1] || 0) * D2R$7,
54391
+ c = (rotation[2] || 0) * D2R$7;
53971
54392
  return function(p) {
53972
- p[0] *= D2R$6;
53973
- p[1] *= D2R$6;
54393
+ p[0] *= D2R$7;
54394
+ p[1] *= D2R$7;
53974
54395
  var rotate = inv ? rotatePointInv : rotatePoint;
53975
54396
  rotate(p, a, b, c);
53976
- p[0] *= R2D$5;
53977
- p[1] *= R2D$5;
54397
+ p[0] *= R2D$6;
54398
+ p[1] *= R2D$6;
53978
54399
  return p;
53979
54400
  };
53980
54401
  }
@@ -60312,7 +60733,7 @@ ${svg}
60312
60733
  // Isometric ("Mercator-stretched") latitude in degrees-in; returns +/-Infinity at
60313
60734
  // the poles.
60314
60735
  function isometricLatitude(latDeg) {
60315
- return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$6 / 2));
60736
+ return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$7 / 2));
60316
60737
  }
60317
60738
 
60318
60739
  // Rhumb-line (loxodrome) interpolation, fraction k of the way from A to B.
@@ -60337,9 +60758,9 @@ ${svg}
60337
60758
  // Rhumb-line distance in meters, using the raw longitude delta (so a full-parallel
60338
60759
  // sweep returns the parallel's length rather than 0).
60339
60760
  function rhumbDistance(a, b) {
60340
- var phi1 = a[1] * D2R$6, phi2 = b[1] * D2R$6;
60761
+ var phi1 = a[1] * D2R$7, phi2 = b[1] * D2R$7;
60341
60762
  var dPhi = phi2 - phi1;
60342
- var dLambda = (b[0] - a[0]) * D2R$6; // raw
60763
+ var dLambda = (b[0] - a[0]) * D2R$7; // raw
60343
60764
  var dPsi = Math.log(Math.tan(Math.PI / 4 + phi2 / 2) / Math.tan(Math.PI / 4 + phi1 / 2));
60344
60765
  var q = Math.abs(dPsi) > 1e-12 ? dPhi / dPsi : Math.cos(phi1);
60345
60766
  return Math.sqrt(dPhi * dPhi + q * q * dLambda * dLambda) * R$3;
@@ -67498,6 +67919,9 @@ ${svg}
67498
67919
  var commands;
67499
67920
  try {
67500
67921
  commands = parseCommands(commandStr);
67922
+ if (opts && opts.validate_commands) {
67923
+ opts.validate_commands(commands);
67924
+ }
67501
67925
  } catch(e) {
67502
67926
  e.message = 'Error in command file ' + file + ': ' + e.message;
67503
67927
  throw e;
@@ -67519,6 +67943,9 @@ ${svg}
67519
67943
  }
67520
67944
  if (c.name == 'run') {
67521
67945
  c.options._run_depth = depth;
67946
+ if (opts && opts.validate_commands) {
67947
+ c.options.validate_commands = opts.validate_commands;
67948
+ }
67522
67949
  }
67523
67950
  });
67524
67951
 
@@ -67556,6 +67983,9 @@ ${svg}
67556
67983
  ctx = getBaseContext();
67557
67984
  // io proxy adds ability to add datasets dynamically in a required function
67558
67985
  ctx.io = getIOProxy();
67986
+ if (opts.input) {
67987
+ Object.assign(ctx.io._cache, opts.input);
67988
+ }
67559
67989
  tmp = await evalTemplateExpression(opts.expression, targets, ctx);
67560
67990
  if (tmp && !utils.isString(tmp)) {
67561
67991
  stop$1('Expected a string containing mapshaper commands; received:', tmp);
@@ -67564,6 +67994,9 @@ ${svg}
67564
67994
  // truncate message (command might include a large GeoJSON string in an -i command)
67565
67995
  message(`command: [${truncateString(tmp, 150)}]`);
67566
67996
  commands = parseCommands(tmp);
67997
+ if (opts.validate_commands) {
67998
+ opts.validate_commands(commands);
67999
+ }
67567
68000
 
67568
68001
  // TODO: remove duplication with mapshaper-run-commands.mjs
67569
68002
  var outputArr = opts && opts.output || null;
@@ -67578,6 +68011,9 @@ ${svg}
67578
68011
  cmd.name == 'info' && cmd.options.save_to)) {
67579
68012
  cmd.options.output = outputArr;
67580
68013
  }
68014
+ if (cmd.name == 'run' && opts.validate_commands) {
68015
+ cmd.options.validate_commands = opts.validate_commands;
68016
+ }
67581
68017
  });
67582
68018
 
67583
68019
  await utils.promisify(runParsedCommands)(commands, job);
@@ -70114,7 +70550,7 @@ ${svg}
70114
70550
  if (Object.prototype.hasOwnProperty.call(command, '_sourceOverride')) {
70115
70551
  source = command._sourceOverride;
70116
70552
  } else if (opts.source) {
70117
- source = findCommandSource(convertSourceName(opts.source, targets), job.catalog, opts);
70553
+ source = await findCommandSourceAsync(convertSourceName(opts.source, targets), job.catalog, opts);
70118
70554
  }
70119
70555
 
70120
70556
  // identify command target/input (for postprocessing)
@@ -70520,7 +70956,7 @@ ${svg}
70520
70956
  var disposableSourceTargetIndex = -1;
70521
70957
 
70522
70958
  if (command.options.source && !sourceNameIsInterpolated(command.options.source)) {
70523
- source = resolveSourceForTargets(command, job, targets);
70959
+ source = await resolveSourceForTargets(command, job, targets);
70524
70960
  items = moveSourceTargetLast(items, source);
70525
70961
  disposableSourceTargetIndex = findLastDisposableSourceTarget(
70526
70962
  items,
@@ -70555,10 +70991,10 @@ ${svg}
70555
70991
  return job;
70556
70992
  }
70557
70993
 
70558
- function resolveSourceForTargets(command, job, targets) {
70994
+ async function resolveSourceForTargets(command, job, targets) {
70559
70995
  job.startCommand(command);
70560
70996
  try {
70561
- return findCommandSource(
70997
+ return await findCommandSourceAsync(
70562
70998
  convertSourceName(command.options.source, targets),
70563
70999
  job.catalog,
70564
71000
  command.options
@@ -70660,7 +71096,7 @@ ${svg}
70660
71096
  return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
70661
71097
  }
70662
71098
 
70663
- var version = "0.7.45";
71099
+ var version = "0.7.46";
70664
71100
 
70665
71101
  // Parse command line args into commands and run them
70666
71102
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
@@ -70690,7 +71126,6 @@ ${svg}
70690
71126
  if (err) {
70691
71127
  return callback(err);
70692
71128
  }
70693
- if (opts.legacy) return callback(null, toLegacyOutputFormat(outputArr));
70694
71129
  return callback(null, toOutputFormat(outputArr));
70695
71130
  });
70696
71131
  if (opts.promise) return opts.promise;
@@ -70732,9 +71167,6 @@ ${svg}
70732
71167
  opts.callback = arg1;
70733
71168
  } else if (utils.isFunction(arg2)) {
70734
71169
  opts.callback = arg2;
70735
- // identify legacy input format (used by some tests)
70736
- opts.legacy = arg1 && guessInputContentType(arg1) != null;
70737
- opts.input = arg1;
70738
71170
  } else {
70739
71171
  // if no callback, create a promise and a callback for resolving the promise
70740
71172
  opts.promise = new Promise(function(resolve, reject) {
@@ -70744,7 +71176,7 @@ ${svg}
70744
71176
  };
70745
71177
  });
70746
71178
  }
70747
- if (!opts.legacy && utils.isObject(arg1)) {
71179
+ if (utils.isObject(arg1)) {
70748
71180
  if (arg1.xl) {
70749
71181
  // options for runCommandsXL()
70750
71182
  opts.options = arg1;
@@ -70777,12 +71209,6 @@ ${svg}
70777
71209
  return callback(e);
70778
71210
  }
70779
71211
 
70780
- if (opts.legacy) {
70781
- message("Warning: deprecated input format");
70782
- commands = convertLegacyCommands(commands, inputObj);
70783
- inputObj = null;
70784
- }
70785
-
70786
71212
  if (commands.length === 0) {
70787
71213
  return callback(new UserError("No commands to run"));
70788
71214
  }
@@ -70819,13 +71245,22 @@ ${svg}
70819
71245
  // (e.g. `mapshaper *.shp batch-mode -o out.json` writing all inputs to the
70820
71246
  // same target on disk).
70821
71247
  var sharedOutputs = [];
70822
- utils.reduceAsync(batches, null, nextGroup, done);
71248
+ runBatches().then(function(job) {
71249
+ done(null, job);
71250
+ }, done);
70823
71251
 
70824
- function nextGroup(prevJob, commands, next) {
70825
- runParsedCommands(commands, new Job(null, {output_files: sharedOutputs}), function(err, job) {
70826
- err = handleNonFatalError(err);
70827
- next(err, job);
70828
- });
71252
+ async function runBatches() {
71253
+ var job;
71254
+ for (var batch of batches) {
71255
+ try {
71256
+ job = await runParsedCommands(batch, new Job(null, {output_files: sharedOutputs}));
71257
+ } catch (e) {
71258
+ var fatalError = handleNonFatalError(e);
71259
+ if (fatalError) throw fatalError;
71260
+ job = undefined;
71261
+ }
71262
+ }
71263
+ return job;
70829
71264
  }
70830
71265
 
70831
71266
  function done(err, job) {
@@ -70839,33 +71274,6 @@ ${svg}
70839
71274
  }
70840
71275
 
70841
71276
 
70842
- function toLegacyOutputFormat(arr) {
70843
- if (arr.length > 1) {
70844
- // Return an array if multiple files are output
70845
- return utils.pluck(arr, 'content');
70846
- }
70847
- if (arr.length == 1) {
70848
- // Return content if a single file is output
70849
- return arr[0].content;
70850
- }
70851
- return null;
70852
- }
70853
-
70854
- function convertLegacyCommands(arr, inputObj) {
70855
- var i = utils.find(arr, function(cmd) {return cmd.name == 'i';});
70856
- var o = utils.find(arr, function(cmd) {return cmd.name == 'o';});
70857
- if (!i) {
70858
- i = {name: 'i', options: {}};
70859
- arr.unshift(i);
70860
- }
70861
- i.options.files = ['__input__'];
70862
- i.options.input = {__input__: inputObj};
70863
- if (!o) {
70864
- arr.push({name: 'o', options: {}});
70865
- }
70866
- return arr;
70867
- }
70868
-
70869
71277
  // TODO: rewrite tests and remove this function
70870
71278
  function testCommands(argv, done) {
70871
71279
  _runCommands(argv, {}, function(err, job) {
@@ -70883,9 +71291,20 @@ ${svg}
70883
71291
  // Execute a sequence of parsed commands
70884
71292
  // @commands Array of parsed commands
70885
71293
  // @job: Job object containing previously imported data
70886
- // @done: function([error], [job])
71294
+ // @done: optional function([error], [job]); returns a Promise if omitted
70887
71295
  //
70888
71296
  function runParsedCommands(commands, job, done) {
71297
+ var promise = runParsedCommandsAsync(commands, job);
71298
+ if (done) {
71299
+ promise.then(function(job) {
71300
+ done(null, job);
71301
+ }, done);
71302
+ return;
71303
+ }
71304
+ return promise;
71305
+ }
71306
+
71307
+ async function runParsedCommandsAsync(commands, job) {
70889
71308
  if (!job) job = new Job();
70890
71309
  commands = readAndRemoveSettings(job, commands);
70891
71310
  if (!runningInBrowser()) {
@@ -70893,26 +71312,16 @@ ${svg}
70893
71312
  }
70894
71313
  commands = runAndRemoveInfoCommands(commands);
70895
71314
  if (commands.length === 0) {
70896
- return done(null);
71315
+ return;
70897
71316
  }
70898
71317
  // we're no longer using the same Job for all batches -- no reset needed
70899
71318
  // // resetting closes any unterminated -if blocks from a previous command sequence
70900
71319
  // resetControlFlow(job);
70901
- utils.reduceAsync(commands, job, nextCommand, done);
70902
-
70903
- function nextCommand(job, cmd, next) {
70904
- var resolved;
70905
- try {
70906
- resolved = maybeInterpolateCommand(cmd, job);
70907
- } catch(e) {
70908
- return next(e);
70909
- }
70910
- runCommand(resolved, job).then(function(result) {
70911
- next(null, result);
70912
- }).catch(function(e) {
70913
- next(e);
70914
- });
71320
+ for (var command of commands) {
71321
+ var resolved = maybeInterpolateCommand(command, job);
71322
+ job = await runCommand(resolved, job);
70915
71323
  }
71324
+ return job;
70916
71325
  }
70917
71326
 
70918
71327
  // Late-binding interpolation: just before each command runs, replace any
@@ -72526,6 +72935,7 @@ ${svg}
72526
72935
  CustomProjections,
72527
72936
  Dymaxion,
72528
72937
  ButterflyProjections,
72938
+ Narukawa2022,
72529
72939
  DataAggregation,
72530
72940
  DatasetUtils,
72531
72941
  DataUtils,