mapshaper 0.6.48 → 0.6.50

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/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.48";
3
+ var VERSION = "0.6.50";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -18,7 +18,7 @@
18
18
  get isNonNegNumber () { return isNonNegNumber; },
19
19
  get isInteger () { return isInteger; },
20
20
  get isEven () { return isEven; },
21
- get isOdd () { return isOdd; },
21
+ get isOdd () { return isOdd$1; },
22
22
  get isString () { return isString; },
23
23
  get isDate () { return isDate; },
24
24
  get isBoolean () { return isBoolean; },
@@ -195,7 +195,7 @@
195
195
  return (obj % 2) === 0;
196
196
  }
197
197
 
198
- function isOdd(obj) {
198
+ function isOdd$1(obj) {
199
199
  return (obj % 2) === 1;
200
200
  }
201
201
 
@@ -17495,30 +17495,19 @@
17495
17495
  return feat;
17496
17496
  };
17497
17497
 
17498
- // switch to RFC 7946-compatible output (while retaining the original export function,
17499
- // so numerous tests will continue to work)
17500
- function exportGeoJSON2(dataset, opts) {
17501
- opts = utils.extend({}, opts);
17502
- opts.v2 = !opts.gj2008; // use RFC 7946 as the default
17503
- return exportGeoJSON(dataset, opts);
17504
- }
17505
-
17506
17498
  function exportGeoJSON(dataset, opts) {
17507
- opts = opts || {};
17499
+ opts = utils.extend({}, opts);
17500
+ opts.rfc7946 = !opts.gj2008; // use RFC 7946 as the default
17508
17501
  var extension = opts.extension || "json";
17509
17502
  var layerGroups, warn;
17510
17503
 
17511
17504
  // Apply coordinate precision
17512
- // rfc7946 flag is deprecated (default output is now RFC 7946 compatible)
17513
- // the flag is used here to preserve backwards compatibility
17514
- // (the rfc7946 flag applies a default precision threshold, even though rounding
17515
- // coordinates is only a recommendation, not a requirement of RFC 7946)
17516
- if (opts.precision || opts.rfc7946) {
17505
+ if (opts.precision) {
17517
17506
  dataset = copyDatasetForExport(dataset);
17518
17507
  setCoordinatePrecision(dataset, opts.precision || 0.000001);
17519
17508
  }
17520
17509
 
17521
- if (opts.v2 || opts.rfc7946) {
17510
+ if (opts.rfc7946) {
17522
17511
  warn = getRFC7946Warnings(dataset);
17523
17512
  if (warn) message(warn);
17524
17513
  }
@@ -17672,7 +17661,7 @@
17672
17661
  }
17673
17662
 
17674
17663
  if (opts.bbox) {
17675
- bbox = getDatasetBbox(dataset, opts.rfc7946 || opts.v2);
17664
+ bbox = getDatasetBbox(dataset, opts.rfc7946);
17676
17665
  if (bbox) {
17677
17666
  geojson.bbox = bbox;
17678
17667
  }
@@ -17772,7 +17761,7 @@
17772
17761
  var groups = groupPolygonRings(obj.pathData, arcs, opts.invert_y);
17773
17762
  // invert_y is used internally for SVG generation
17774
17763
  // mapshaper's internal winding order is the opposite of RFC 7946
17775
- var reverse = (opts.rfc7946 || opts.v2) && !opts.invert_y;
17764
+ var reverse = opts.rfc7946 && !opts.invert_y;
17776
17765
  var coords = groups.map(function(paths) {
17777
17766
  return paths.map(function(path) {
17778
17767
  if (reverse) path.points.reverse();
@@ -17886,7 +17875,6 @@
17886
17875
  var GeojsonExport = /*#__PURE__*/Object.freeze({
17887
17876
  __proto__: null,
17888
17877
  'default': GeoJSON,
17889
- exportGeoJSON2: exportGeoJSON2,
17890
17878
  exportGeoJSON: exportGeoJSON,
17891
17879
  exportLayerAsGeoJSON: exportLayerAsGeoJSON,
17892
17880
  getRFC7946Warnings: getRFC7946Warnings,
@@ -21775,7 +21763,7 @@ ${svg}
21775
21763
 
21776
21764
  var exporters = {
21777
21765
  // [PACKAGE_EXT]: exportPackedDatasets, // handled as a special case
21778
- geojson: exportGeoJSON2,
21766
+ geojson: exportGeoJSON,
21779
21767
  topojson: exportTopoJSON,
21780
21768
  shapefile: exportShapefile,
21781
21769
  dsv: exportDelim,
@@ -23678,13 +23666,6 @@ ${svg}
23678
23666
  // describe: 'pct of avg segment length for rounding (0.02 is default)',
23679
23667
  type: 'number'
23680
23668
  })
23681
- .option('rfc7946', {
23682
- // obsolete -- rfc 7946 compatible outptu is now the default.
23683
- // This option also rounds coordinates to 7 decimals. I'm retaining the
23684
- // option for backwards compatibility.
23685
- // describe: '[GeoJSON] follow RFC 7946 (CCW outer ring order, etc.)',
23686
- type: 'flag'
23687
- })
23688
23669
  // .option('winding', {
23689
23670
  // describe: '[GeoJSON] set polygon winding order (use CW with d3-geo)'
23690
23671
  // })
@@ -24363,6 +24344,19 @@ ${svg}
24363
24344
  .option('name', nameOpt);
24364
24345
 
24365
24346
 
24347
+ // for testing grid update
24348
+ parser.command('grid2')
24349
+ .option('type', {
24350
+ describe: 'square, hex or hex2 (default is square)'
24351
+ })
24352
+ .option('interval', {
24353
+ describe: 'side length (e.g. 500m, 12km)',
24354
+ type: 'distance'
24355
+ })
24356
+ .option('name', nameOpt)
24357
+ .option('target', targetOpt)
24358
+ .option('no-replace', noReplaceOpt);
24359
+
24366
24360
  parser.command('grid')
24367
24361
  .describe('create a grid of square or hexagonal polygons')
24368
24362
  .option('type', {
@@ -34841,7 +34835,7 @@ ${svg}
34841
34835
  // need to copy attribute to avoid circular references if geojson is assigned
34842
34836
  // to a data property.
34843
34837
  var copy = copyLayer(lyr);
34844
- var features = exportLayerAsGeoJSON(copy, dataset, {}, true);
34838
+ var features = exportLayerAsGeoJSON(copy, dataset, {rfc7946: true}, true);
34845
34839
  var features2 = [];
34846
34840
 
34847
34841
  api.get = function(i) {
@@ -39486,6 +39480,7 @@ ${svg}
39486
39480
  }
39487
39481
 
39488
39482
  function joinPolygonsViaMosaic(targetLyr, targetDataset, source, opts) {
39483
+ // merge source and target layers
39489
39484
  var mergedDataset = mergeLayersForOverlay([targetLyr], targetDataset, source, opts);
39490
39485
  var nodes = addIntersectionCuts(mergedDataset, opts);
39491
39486
  var sourceLyr = mergedDataset.layers.pop();
@@ -39495,6 +39490,7 @@ ${svg}
39495
39490
  geometry_type: 'polygon',
39496
39491
  shapes: targetLyr.shapes.concat(sourceLyr.shapes)
39497
39492
  };
39493
+ // make a mosaic from merged shapes of both layers
39498
39494
  var mosaicIndex = new MosaicIndex(mergedLyr, nodes, {flat: false});
39499
39495
 
39500
39496
  var joinOpts = utils.extend({}, opts);
@@ -39538,8 +39534,8 @@ ${svg}
39538
39534
  var mosaicRecords = mosaicShapes.map(function(tile, i) {
39539
39535
  var rec = {
39540
39536
  area: getShapeArea(tile, arcs),
39541
- weight: 0,
39542
- sourceId: -1
39537
+ weights: null,
39538
+ sourceIds: null
39543
39539
  };
39544
39540
  return rec;
39545
39541
  });
@@ -39549,32 +39545,49 @@ ${svg}
39549
39545
  sourceLyr.shapes.forEach(function(sourceShp, sourceId) {
39550
39546
  var tileIds = mosaicIndex.getTileIdsByShapeId(sourceId + destLen);
39551
39547
  var shapeArea = getShapeArea(sourceShp, arcs);
39552
- var tileRec;
39548
+ var tileRec, weight;
39553
39549
  for (var i=0; i<tileIds.length; i++) {
39554
39550
  tileRec = mosaicRecords[tileIds[i]];
39555
- if (tileRec.sourceId > -1) {
39556
- // overlap in source layer
39557
- continue;
39551
+ weight = tileRec.area / shapeArea;
39552
+ if (!tileRec.weights) {
39553
+ tileRec.weights = [];
39554
+ tileRec.sourceIds = [];
39558
39555
  }
39559
- tileRec.weight = tileRec.area / shapeArea;
39560
- tileRec.sourceId = sourceId;
39556
+ tileRec.weights.push(weight);
39557
+ tileRec.sourceIds.push(sourceId);
39561
39558
  }
39562
39559
  });
39563
39560
  return mosaicRecords;
39564
39561
  }
39565
39562
 
39566
39563
 
39564
+ // function getInterpolatedValue(field, tileRecords, sourceRecords) {
39565
+ // var value = 0, tileRec, sourceRec;
39566
+ // for (var i=0; i<tileRecords.length; i++) {
39567
+ // tileRec = tileRecords[i];
39568
+ // if (tileRec.sourceId == -1) continue;
39569
+
39570
+ // sourceRec = sourceRecords[tileRec.sourceId];
39571
+ // value += tileRec.weight * sourceRec[field];
39572
+ // }
39573
+ // return value;
39574
+ // }
39575
+
39567
39576
  function getInterpolatedValue(field, tileRecords, sourceRecords) {
39568
- var value = 0, tileRec, sourceRec;
39577
+ var value = 0, tileRec, sourceRec, sourceId;
39569
39578
  for (var i=0; i<tileRecords.length; i++) {
39570
39579
  tileRec = tileRecords[i];
39571
- if (tileRec.sourceId == -1) continue;
39572
- sourceRec = sourceRecords[tileRec.sourceId];
39573
- value += tileRec.weight * sourceRec[field];
39580
+ if (!tileRec.sourceIds) continue;
39581
+ for (var j=0; j<tileRec.sourceIds.length; j++) {
39582
+ sourceId = tileRec.sourceIds[j];
39583
+ sourceRec = sourceRecords[sourceId];
39584
+ value += tileRec.weights[j] * sourceRec[field];
39585
+ }
39574
39586
  }
39575
39587
  return value;
39576
39588
  }
39577
39589
 
39590
+
39578
39591
  function getIdConversionFunction(offset, length) {
39579
39592
  return function (mergedIds) {
39580
39593
  var ids = [], id;
@@ -40638,6 +40651,408 @@ ${svg}
40638
40651
  return [lyr2];
40639
40652
  };
40640
40653
 
40654
+ // Columns are vertical and rows are horizontal in the "flat-top" orientation;
40655
+ // columns are horizontal in the "pointy-top" orientation
40656
+ // Array indexes are column-first in both orientations
40657
+ // The 0,0 cell is in the bottom left corner
40658
+ // Currently the origin cell is always an "outie" (protruding); in the future
40659
+ // "innie" origin cells may be supported
40660
+
40661
+ // interval: side length in projected coordinates
40662
+ // bbox: bounding box of area to be enclosed by grid
40663
+ //
40664
+ function getHexGridMaker(bbox, interval, opts) {
40665
+ var flatTop = opts.type != 'hex2'; // hex2 is "pointy-top" orientation
40666
+ // origin cell (bottom left) may be "outie" or "innie" ... could be settable
40667
+ var outieOrigin = true;
40668
+ var minorInterval = interval * Math.sqrt(3) / 2;
40669
+ var _colCounts = _getColCounts(bbox, interval);
40670
+ var _rowCounts = _getRowCounts(bbox, interval);
40671
+ // coordinates of the center of the bottom left cell
40672
+ var _uOrigin = _getUOrigin();
40673
+ var _vOrigin = _getVOrigin();
40674
+
40675
+ function cells() {
40676
+ return _rowCounts[0] * _colCounts[0] + _rowCounts[1] * _colCounts[1];
40677
+ }
40678
+
40679
+ // a is col in flatTop orientation
40680
+ function colRowToIdx(col, row) {
40681
+ // fatCol: a pair of adjacent (offset) columns
40682
+ var fatColSize = _rowCounts[0] + _rowCounts[1];
40683
+ var fatColId = Math.floor(col / 2);
40684
+ var idx = fatColId * fatColSize;
40685
+ // oddCol: cell is in an odd-numbered column (or row)
40686
+ var oddCols = col % 2 == 1;
40687
+ if (oddCols) {
40688
+ idx += _rowCounts[1];
40689
+ }
40690
+ idx += row;
40691
+
40692
+ // check index bounds
40693
+ if (col < 0 || row < 0) error('negative grid index');
40694
+ if (oddCols && row >= _rowCounts[1] || !oddCols && row >= _rowCounts[0]) {
40695
+ error('out-of-bounds minor axis index');
40696
+ }
40697
+ if (oddCols && col >= _colCounts[1] || !oddCols && col >= _colCounts[0]) {
40698
+ error('out-of-bounds major axis index');
40699
+ }
40700
+ return idx;
40701
+ }
40702
+
40703
+ function pointToIdx(xy) {
40704
+ return flatTop ?
40705
+ _uvToIdx(xy[0], xy[1]) :
40706
+ _uvToIdx(xy[1], xy[0]);
40707
+ }
40708
+
40709
+ // Col,row numbering and array indexing are aligned (same for both flat-top and pointed-top orientations)
40710
+ function idxToColRow(id) {
40711
+ var fatColSize = _rowCounts[0] + _rowCounts[1];
40712
+ var fatColId = Math.floor(id / fatColSize);
40713
+ var col = fatColId * 2;
40714
+ var extra = id - fatColId * fatColSize;
40715
+ if (extra >= _rowCounts[0]) {
40716
+ col++;
40717
+ extra -= _rowCounts[0];
40718
+ }
40719
+ return [col, extra];
40720
+ }
40721
+
40722
+ function idxToBBox(id) {
40723
+ var bbox = _idxToBBox(id);
40724
+ return flatTop ? bbox: [bbox[1], bbox[0], bbox[3], bbox[2]];
40725
+ }
40726
+
40727
+ function makeCellPolygon(idx, opts) {
40728
+ var geom = {
40729
+ type: 'Polygon',
40730
+ coordinates: [_makeCellCoords(idx)]
40731
+ };
40732
+ if (!flatTop) {
40733
+ flipPolygonCoords(geom);
40734
+ }
40735
+ return geom;
40736
+ }
40737
+
40738
+ function forEachNeighbor(c, r, cb) {
40739
+ var rowShift;
40740
+ {
40741
+ rowShift = isOdd(c) ? 0 : -1;
40742
+ }
40743
+ cb(c, r+1);
40744
+ cb(c+1, r + rowShift + 1);
40745
+ cb(c+1, r + rowShift);
40746
+ cb(c, r-1);
40747
+ cb(c-1, r + rowShift + 1);
40748
+ }
40749
+
40750
+ // horizontal origin (x coord) in flat-top orientation
40751
+ function _getUOrigin() {
40752
+ var range = _getUAxisRange(bbox);
40753
+ var extent = range[1] - range[0];
40754
+ var cols = _colCounts[0] + _colCounts[1];
40755
+ var outerExtent = 1.5 * cols * interval + 0.5 * interval;
40756
+ var margin = (outerExtent - extent) / 2; // center data bbox within grid
40757
+ // origin is one side length to the right of the left boundary
40758
+ var origin = range[0] - margin + interval;
40759
+ return origin;
40760
+ }
40761
+
40762
+ // vertical origin (y coord) in flat-top orientation
40763
+ function _getVOrigin() {
40764
+ var range = _getVAxisRange(bbox);
40765
+ var extent = range[1] - range[0];
40766
+ var rows = _rowCounts[0] + _rowCounts[1];
40767
+ var outerExtent = (rows + 1) * minorInterval;
40768
+ var margin = (outerExtent - extent) / 2;
40769
+ var origin = range[0] - margin + minorInterval;
40770
+ return origin;
40771
+ }
40772
+
40773
+ function _getUAxisRange(bbox) {
40774
+ return flatTop ? [bbox[0], bbox[2]] : [bbox[1], bbox[3]];
40775
+ }
40776
+
40777
+ function _getVAxisRange(bbox) {
40778
+ return flatTop ? [bbox[1], bbox[3]] : [bbox[0], bbox[2]];
40779
+ }
40780
+
40781
+ function _uvToIdx(u, v) {
40782
+ var [c, r] = _uvToColRow(u, v);
40783
+ return colRowToIdx(c, r);
40784
+ }
40785
+
40786
+ // x, y are reversed in pointy-top orientation
40787
+ function _uvToColRow(u, v) {
40788
+ var left = _uOrigin - 1.5 * interval;
40789
+ var vOffs = 0 ;
40790
+ var bottom = _vOrigin - minorInterval + vOffs;
40791
+ var ui = Math.floor((u - left) / (1.5 * interval));
40792
+ var vi = Math.floor((v - bottom) / minorInterval);
40793
+ var cwBar = isOdd(ui) != isOdd(vi);
40794
+ var u1 = left + ui * 1.5 * interval + interval * 0.5;
40795
+ var u2 = u1 + interval * 0.5;
40796
+ var v1 = bottom + vi * minorInterval;
40797
+ var v2 = v1 + minorInterval;
40798
+ var orientation = cwBar ?
40799
+ orient2D(u1, v1, u2, v2, u, v) :
40800
+ orient2D(u2, v1, u1, v2, u, v);
40801
+ var colId = orientation > 0 ? ui - 1 : ui;
40802
+ var rowId = Math.floor(vi / 2);
40803
+ return [colId, rowId];
40804
+ }
40805
+
40806
+ function _idxToBBox(id) {
40807
+ var uv = _idxToPoint(id);
40808
+ return [
40809
+ uv[0] - interval,
40810
+ uv[1] - minorInterval,
40811
+ uv[0] + interval,
40812
+ uv[1] + minorInterval
40813
+ ];
40814
+ }
40815
+
40816
+ // center point of cell
40817
+ function idxToPoint(id) {
40818
+ var p = _idxToPoint(id);
40819
+ return flatTop ? p : flipPoint(p);
40820
+ }
40821
+
40822
+ function _isUpperCell(col) {
40823
+ return isOdd(col) || !outieOrigin ;
40824
+ }
40825
+
40826
+ function _idxToPoint(id) {
40827
+ var [c, r] = idxToColRow(id);
40828
+ return _colRowToPoint(c, r);
40829
+ }
40830
+
40831
+ function _colRowToPoint(c, r) {
40832
+ var vShift = isOdd(c) ? (minorInterval ) : 0;
40833
+ var u = _uOrigin + c * 1.5 * interval;
40834
+ var v = _vOrigin + vShift + r * minorInterval * 2;
40835
+ return [u, v];
40836
+ }
40837
+
40838
+ function _colRowToVertex(c, r, half) {
40839
+ var [u, v] = _colRowToPoint(c, r);
40840
+ return [u - (half ? interval : interval / 2), v - (half ? 0 : minorInterval)];
40841
+ }
40842
+
40843
+ function _makeCellCoords(idx) {
40844
+ var [c, r] = idxToColRow(idx);
40845
+ var rowOffs = _isUpperCell(c) ? 0 : -1;
40846
+ var v0 = _colRowToVertex(c, r, false);
40847
+ return [
40848
+ v0,
40849
+ _colRowToVertex(c, r, false),
40850
+ _colRowToVertex(c, r, true),
40851
+ _colRowToVertex(c, r + 1, false),
40852
+ _colRowToVertex(c + 1, r + 1 + rowOffs, true),
40853
+ _colRowToVertex(c + 1, r + 1 + rowOffs, false),
40854
+ _colRowToVertex(c + 1, r + rowOffs, true),
40855
+ v0
40856
+ ];
40857
+ }
40858
+
40859
+ function _getColCounts(bbox, interval) {
40860
+ var extent = flatTop ? bbox[2] - bbox[0] : bbox[3] - bbox[1];
40861
+ var n = Math.ceil((2 * extent + interval) / (3 * interval));
40862
+ var a = Math.ceil(n / 2);
40863
+ var b = Math.floor(n / 2);
40864
+ return [a, b] ;
40865
+ }
40866
+
40867
+ function _getRowCounts(bbox, interval) {
40868
+ var extent = flatTop ? bbox[3] - bbox[1] : bbox[2] - bbox[0];
40869
+ var n = Math.ceil(1 + 2 * extent / (interval * Math.sqrt(3)));
40870
+ var a = Math.ceil(n / 2);
40871
+ var b = Math.floor(n / 2);
40872
+ return [a, b] ;
40873
+ }
40874
+
40875
+ return {
40876
+ cells,
40877
+ colRowToIdx,
40878
+ idxToColRow,
40879
+ pointToIdx,
40880
+ idxToPoint,
40881
+ idxToBBox,
40882
+ makeCellPolygon,
40883
+ forEachNeighbor
40884
+ };
40885
+ }
40886
+
40887
+ function isOdd(int) {
40888
+ return int % 2 !== 0;
40889
+ }
40890
+
40891
+ function flipPolygonCoords(geom) {
40892
+ for (var i=0, n=geom ? geom.coordinates.length : 0; i<n; i++) {
40893
+ geom.coordinates[i].forEach(flipPoint);
40894
+ }
40895
+ }
40896
+
40897
+ function flipPoint(p) {
40898
+ p[1];
40899
+ p[1] = p[0];
40900
+ p[0] = p[1];
40901
+ return p;
40902
+ }
40903
+
40904
+ function getAlignedGridBounds(bbox, interval) {
40905
+ var xx = getAlignedRange(bbox[0], bbox[2], interval);
40906
+ var yy = getAlignedRange(bbox[1], bbox[3], interval);
40907
+ return [xx[0], yy[0], xx[1], yy[1]];
40908
+ }
40909
+
40910
+ function getCenteredGridBounds(bbox, interval) {
40911
+ var xx = getCenteredRange(bbox[0], bbox[2], interval);
40912
+ var yy = getCenteredRange(bbox[1], bbox[3], interval);
40913
+ return [xx[0], yy[0], xx[1], yy[1]];
40914
+ }
40915
+
40916
+ // grid boundaries includes the origin
40917
+ // (this way, grids calculated from different sets of points will all align)
40918
+ function getAlignedRange(minCoord, maxCoord, interval) {
40919
+ var idx = Math.floor(minCoord / interval) - 1;
40920
+ var idx2 = Math.ceil(maxCoord / interval) + 1;
40921
+ return [idx * interval, idx2 * interval];
40922
+ }
40923
+
40924
+ function getCenteredRange(minCoord, maxCoord, interval) {
40925
+ var w = maxCoord - minCoord;
40926
+ var w2 = Math.ceil(w / interval) * interval;
40927
+ var pad = (w2 - w) / 2 + interval;
40928
+ return [minCoord - pad, maxCoord + pad];
40929
+ }
40930
+
40931
+ // TODO: Use this function for other grid-based commands
40932
+ function getSquareGridMaker(bbox, interval, opts) {
40933
+ var extent = opts && opts.aligned ?
40934
+ getAlignedGridBounds(bbox, interval) :
40935
+ getCenteredGridBounds(bbox, interval);
40936
+ var xmin = extent[0];
40937
+ var ymin = extent[1];
40938
+ var w = extent[2] - xmin;
40939
+ var h = extent[3] - ymin;
40940
+ var cols = Math.round(w / interval);
40941
+ var rows = Math.round(h / interval);
40942
+ // var xmin = bbox[0] - interval;
40943
+ // var ymin = bbox[1] - interval;
40944
+ // var xmax = bbox[2] + interval;
40945
+ // var ymax = bbox[3] + interval;
40946
+ // var w = xmax - xmin;
40947
+ // var h = ymax - ymin;
40948
+ // var cols = Math.ceil(w / interval);
40949
+ // var rows = Math.ceil(h / interval);
40950
+
40951
+ // function size() {
40952
+ // return [cols, rows];
40953
+ // }
40954
+
40955
+ function cells() {
40956
+ return cols * rows;
40957
+ }
40958
+
40959
+ function pointToCol(xy) {
40960
+ var dx = xy[0] - xmin;
40961
+ return Math.floor(dx / w * cols);
40962
+ }
40963
+
40964
+ function pointToRow(xy) {
40965
+ var dy = xy[1] - ymin;
40966
+ return Math.floor(dy / h * rows);
40967
+ }
40968
+
40969
+ function colRowToIdx(c, r) {
40970
+ if (c < 0 || r < 0 || c >= cols || r >= rows) return -1;
40971
+ return r * cols + c;
40972
+ }
40973
+
40974
+ function pointToIdx(xy) {
40975
+ var c = pointToCol(xy);
40976
+ var r = pointToRow(xy);
40977
+ return colRowToIdx(c, r);
40978
+ }
40979
+
40980
+ function idxToColRow(i) {
40981
+ return [i % cols, Math.floor(i / cols)];
40982
+ }
40983
+
40984
+ function idxToPoint(idx) {
40985
+ var [c, r] = idxToColRow(idx);
40986
+ var x = xmin + (c + 0.5) * interval;
40987
+ var y = ymin + (r + 0.5) * interval;
40988
+ return [x, y];
40989
+ }
40990
+
40991
+ function idxToBBox(idx) {
40992
+ var cr = idxToColRow(idx);
40993
+ return [
40994
+ xmin + cr[0] * interval, ymin + cr[1] * interval,
40995
+ xmin + (cr[0] + 1) * interval, ymin + (cr[1] + 1) * interval
40996
+ ];
40997
+ }
40998
+
40999
+ function makeCellPolygon(idx, opts) {
41000
+ var coords = opts.circles ?
41001
+ makeCircleCoords(idx, opts) :
41002
+ makeCellCoords(idx, opts);
41003
+ return {
41004
+ type: 'Polygon',
41005
+ coordinates: [coords]
41006
+ };
41007
+ }
41008
+
41009
+ function makeCellCoords(idx, opts) {
41010
+ var bbox = idxToBBox(idx);
41011
+ var margin = opts.interval * (opts.cell_margin || 0);
41012
+ var a = bbox[0] + margin,
41013
+ b = bbox[1] + margin,
41014
+ c = bbox[2] - margin,
41015
+ d = bbox[3] - margin;
41016
+ return [[a, b],[a, d],[c, d],[c, b],[a, b]];
41017
+ }
41018
+
41019
+ function makeCircleCoords(idx, opts) {
41020
+ var center = idxToPoint(idx);
41021
+ var margin = opts.cell_margin > 0 ? opts.cell_margin : 1e-6;
41022
+ var radius = opts.interval / 2 * (1 - margin);
41023
+ var vertices = opts.vertices || 20;
41024
+ return getPointBufferCoordinates(center, radius, vertices, getPlanarSegmentEndpoint);
41025
+ }
41026
+
41027
+ function forEachNeighbor(c, r, cb) {
41028
+ cb(c+1, r+1);
41029
+ cb(c+1, r);
41030
+ cb(c+1, r-1);
41031
+ cb(c, r+1);
41032
+ cb(c, r-1);
41033
+ cb(c-1, r+1);
41034
+ cb(c-1, r);
41035
+ cb(c-1, r-1);
41036
+ }
41037
+
41038
+ return {
41039
+ // size,
41040
+ // pointToCol,
41041
+ // pointToRow,
41042
+ // makeCellCoords,
41043
+ // makeCircleCoords,
41044
+ cells,
41045
+ colRowToIdx,
41046
+ pointToIdx,
41047
+ idxToColRow,
41048
+ // idxToRow,
41049
+ idxToBBox,
41050
+ idxToPoint,
41051
+ makeCellPolygon,
41052
+ forEachNeighbor
41053
+ };
41054
+ }
41055
+
40641
41056
  cmd.polygonGrid = function(targetLayers, targetDataset, opts) {
40642
41057
  requireProjectedDataset(targetDataset);
40643
41058
  var params = getGridParams(targetLayers, targetDataset, opts);
@@ -40648,6 +41063,44 @@ ${svg}
40648
41063
  return gridDataset;
40649
41064
  };
40650
41065
 
41066
+
41067
+ // TODO: Update -point-grid command to use this function
41068
+ cmd.polygonGrid2 = function(targetLayers, targetDataset, opts) {
41069
+ requireProjectedDataset(targetDataset);
41070
+ var params = getGridParams(targetLayers, targetDataset, opts);
41071
+ // alignGridToBounds(geojson, params.bbox);
41072
+ var gridDataset = makeGridDataset2(params, opts);
41073
+ gridDataset.info = copyDatasetInfo(targetDataset.info);
41074
+ setOutputLayerName(gridDataset.layers[0], null, 'grid', opts);
41075
+ return gridDataset;
41076
+ };
41077
+
41078
+ function makeGridDataset2(params, opts) {
41079
+ var geojson, dataset, grid;
41080
+ if (params.type == 'square') {
41081
+ grid = getSquareGridMaker(params.bbox, params.interval, opts);
41082
+ } else if (params.type == 'hex') {
41083
+ grid = getHexGridMaker(params.bbox, params.interval, opts);
41084
+ } else {
41085
+ stop('Unsupported grid type');
41086
+ }
41087
+ var features = [];
41088
+ for (var i=0, n=grid.cells(); i<n; i++) {
41089
+ features.push({
41090
+ type: 'Feature',
41091
+ properties: null,
41092
+ geometry: grid.makeCellPolygon(i, opts)
41093
+ });
41094
+ }
41095
+ geojson = {
41096
+ type: 'FeatureCollection',
41097
+ features: features
41098
+ };
41099
+ dataset = importGeoJSON(geojson, {});
41100
+ buildTopology(dataset);
41101
+ return dataset;
41102
+ }
41103
+
40651
41104
  // TODO: Update -point-grid command to use this function
40652
41105
  cmd.pointGrid2 = function(targetLayers, targetDataset, opts) {
40653
41106
  var params = getGridParams(targetLayers, targetDataset, opts);
@@ -40955,6 +41408,67 @@ ${svg}
40955
41408
  return rowsArr;
40956
41409
  }
40957
41410
 
41411
+ // Source: https://diego.assencio.com/?index=8d6ca3d82151bad815f78addf9b5c1c6
41412
+ function twoCircleIntersection(c1, r1, c2, r2) {
41413
+ var d = distance2D(c1[0], c1[1], c2[0], c2[1]);
41414
+ if (d >= r1 + r2) return 0;
41415
+ var r1sq = r1 * r1,
41416
+ r2sq = r2 * r2,
41417
+ d1 = (r1sq - r2sq + d * d) / (2 * d),
41418
+ d2 = d - d1;
41419
+ if (d <= Math.abs(r1 - r2)) {
41420
+ return Math.PI * Math.min(r1sq, r2sq);
41421
+ }
41422
+ return r1sq * Math.acos(d1/r1) - d1 * Math.sqrt(r1sq - d1 * d1) +
41423
+ r2sq * Math.acos(d2/r2) - d2 * Math.sqrt(r2sq - d2 * d2);
41424
+ }
41425
+
41426
+ // Returns a function that receives a cell index and returns indices of points
41427
+ // within a given distance of the cell.
41428
+ function getGridToPointIndex(points, grid, radius) {
41429
+ var Flatbush = require('flatbush');
41430
+ var gridIndex = new IdTestIndex(grid.cells());
41431
+ var bboxIndex = new Flatbush(points.length);
41432
+ var empty = [];
41433
+ points.forEach(function(p) {
41434
+ var bbox = getPointBounds(p, radius);
41435
+ var addNeighbors = true; // TODO: only if radius is > 0?
41436
+ addPointToGridIndex(p, gridIndex, grid, addNeighbors);
41437
+ bboxIndex.add.apply(bboxIndex, bbox);
41438
+ });
41439
+ bboxIndex.finish();
41440
+
41441
+ return function(i) {
41442
+ if (!gridIndex.hasId(i)) {
41443
+ return empty;
41444
+ }
41445
+ var bbox = grid.idxToBBox(i);
41446
+ var indices = bboxIndex.search.apply(bboxIndex, bbox);
41447
+ return indices;
41448
+ };
41449
+ }
41450
+
41451
+ // TODO: support spherical coords
41452
+ function getPointBounds(p, radius) {
41453
+ return [p[0] - radius, p[1] - radius, p[0] + radius, p[1] + radius];
41454
+ }
41455
+
41456
+ function addPointToGridIndex(p, index, grid, addNeighbors) {
41457
+ var i = grid.pointToIdx(p);
41458
+ var [c, r] = grid.idxToColRow(i);
41459
+ addCellToGridIndex(c, r, grid, index);
41460
+ if (addNeighbors) {
41461
+ grid.forEachNeighbor(c, r, function(c, r) {
41462
+ addCellToGridIndex(c, r, grid, index);
41463
+ });
41464
+ }
41465
+ }
41466
+
41467
+ function addCellToGridIndex(c, r, grid, index) {
41468
+ var i = grid.colRowToIdx(c, r);
41469
+ if (i > -1) index.setId(i);
41470
+ }
41471
+
40958
41472
  cmd.pointToGrid = function(targetLayers, targetDataset, opts) {
40959
41473
  targetLayers.forEach(requirePointLayer);
40960
41474
  if (opts.interval > 0 === false) {
@@ -40986,13 +41500,12 @@ ${svg}
40986
41500
  return outputLayers;
40987
41501
  };
40988
41502
 
40989
-
40990
41503
  function getPolygonDataset(pointLyr, gridBBox, opts) {
40991
41504
  var points = getPointsInLayer(pointLyr);
40992
41505
  var cellSize = opts.interval;
40993
- var grid = getGridData(gridBBox, cellSize, opts);
41506
+ var grid = getSquareGridMaker(gridBBox, cellSize, opts);
40994
41507
  var pointCircleRadius = getPointCircleRadius(opts);
40995
- var findPointIdsByCellId = getPointIndex(points, grid, pointCircleRadius);
41508
+ var findPointIdsByCellId = getGridToPointIndex(points, grid, pointCircleRadius);
40996
41509
  var geojson = {
40997
41510
  type: 'FeatureCollection',
40998
41511
  features: []
@@ -41011,7 +41524,7 @@ ${svg}
41011
41524
  geojson.features.push({
41012
41525
  type: 'Feature',
41013
41526
  properties: d,
41014
- geometry: makeCellPolygon(i, grid, opts)
41527
+ geometry: grid.makeCellPolygon(i, opts)
41015
41528
  });
41016
41529
  }
41017
41530
  return importGeoJSON(geojson, {});
@@ -41052,202 +41565,19 @@ ${svg}
41052
41565
  return weights;
41053
41566
  }
41054
41567
 
41055
- // Source: https://diego.assencio.com/?index=8d6ca3d82151bad815f78addf9b5c1c6
41056
- function twoCircleIntersection(c1, r1, c2, r2) {
41057
- var d = distance2D(c1[0], c1[1], c2[0], c2[1]);
41058
- if (d >= r1 + r2) return 0;
41059
- var r1sq = r1 * r1,
41060
- r2sq = r2 * r2,
41061
- d1 = (r1sq - r2sq + d * d) / (2 * d),
41062
- d2 = d - d1;
41063
- if (d <= Math.abs(r1 - r2)) {
41064
- return Math.PI * Math.min(r1sq, r2sq);
41065
- }
41066
- return r1sq * Math.acos(d1/r1) - d1 * Math.sqrt(r1sq - d1 * d1) +
41067
- r2sq * Math.acos(d2/r2) - d2 * Math.sqrt(r2sq - d2 * d2);
41068
- }
41069
-
41070
- function makeCellPolygon(idx, grid, opts) {
41071
- var coords = opts.circles ?
41072
- makeCircleCoords(grid.idxToPoint(idx), opts) :
41073
- makeCellCoords(grid.idxToBBox(idx), opts);
41074
- return {
41075
- type: 'Polygon',
41076
- coordinates: [coords]
41077
- };
41078
- }
41079
-
41080
- function makeCellCoords(bbox, opts) {
41081
- var margin = opts.interval * (opts.cell_margin || 0);
41082
- var a = bbox[0] + margin,
41083
- b = bbox[1] + margin,
41084
- c = bbox[2] - margin,
41085
- d = bbox[3] - margin;
41086
- return [[a, b],[a, d],[c, d],[c, b],[a, b]];
41087
- }
41088
-
41089
- function makeCircleCoords(center, opts) {
41090
- var margin = opts.cell_margin > 0 ? opts.cell_margin : 1e-6;
41091
- var radius = opts.interval / 2 * (1 - margin);
41092
- var vertices = opts.vertices || 20;
41093
- return getPointBufferCoordinates(center, radius, vertices, getPlanarSegmentEndpoint);
41094
- }
41095
-
41096
- // Returns a function that receives a cell index and returns indices of points
41097
- // within a given distance of the cell.
41098
- function getPointIndex(points, grid, radius) {
41099
- var Flatbush = require$1('flatbush');
41100
- var gridIndex = new IdTestIndex(grid.cells());
41101
- var bboxIndex = new Flatbush(points.length);
41102
- var empty = [];
41103
- points.forEach(function(p) {
41104
- var bbox = getPointBounds(p, radius);
41105
- addPointToGridIndex(p, gridIndex, grid);
41106
- bboxIndex.add.apply(bboxIndex, bbox);
41107
- });
41108
- bboxIndex.finish();
41109
- return function(i) {
41110
- if (!gridIndex.hasId(i)) {
41111
- return empty;
41112
- }
41113
- var bbox = grid.idxToBBox(i);
41114
- var indices = bboxIndex.search.apply(bboxIndex, bbox);
41115
- return indices;
41116
- };
41117
- }
41118
-
41119
- function addPointToGridIndex(p, index, grid) {
41120
- var i = grid.pointToIdx(p);
41121
- var c = grid.idxToCol(i);
41122
- var r = grid.idxToRow(i);
41123
- addCellToGridIndex(c+1, r+1, grid, index);
41124
- addCellToGridIndex(c+1, r, grid, index);
41125
- addCellToGridIndex(c+1, r-1, grid, index);
41126
- addCellToGridIndex(c, r+1, grid, index);
41127
- addCellToGridIndex(c, r, grid, index);
41128
- addCellToGridIndex(c, r-1, grid, index);
41129
- addCellToGridIndex(c-1, r+1, grid, index);
41130
- addCellToGridIndex(c-1, r, grid, index);
41131
- addCellToGridIndex(c-1, r-1, grid, index);
41132
- }
41133
-
41134
- function addCellToGridIndex(c, r, grid, index) {
41135
- var i = grid.colRowToIdx(c, r);
41136
- if (i > -1) index.setId(i);
41137
- }
41138
-
41139
- // TODO: support spherical coords
41140
- function getPointBounds(p, radius) {
41141
- return [p[0] - radius, p[1] - radius, p[0] + radius, p[1] + radius];
41142
- }
41143
-
41144
- // grid boundaries includes the origin
41145
- // (this way, grids calculated from different sets of points will all align)
41146
- function getAlignedRange(minCoord, maxCoord, interval) {
41147
- var idx = Math.floor(minCoord / interval) - 1;
41148
- var idx2 = Math.ceil(maxCoord / interval) + 1;
41149
- return [idx * interval, idx2 * interval];
41150
- }
41151
-
41152
- function getCenteredRange(minCoord, maxCoord, interval) {
41153
- var w = maxCoord - minCoord;
41154
- var w2 = Math.ceil(w / interval) * interval;
41155
- var pad = (w2 - w) / 2 + interval;
41156
- return [minCoord - pad, maxCoord + pad];
41157
- }
41158
-
41159
- function getAlignedGridBounds(bbox, interval) {
41160
- var xx = getAlignedRange(bbox[0], bbox[2], interval);
41161
- var yy = getAlignedRange(bbox[1], bbox[3], interval);
41162
- return [xx[0], yy[0], xx[1], yy[1]];
41163
- }
41164
-
41165
- function getCenteredGridBounds(bbox, interval) {
41166
- var xx = getCenteredRange(bbox[0], bbox[2], interval);
41167
- var yy = getCenteredRange(bbox[1], bbox[3], interval);
41168
- return [xx[0], yy[0], xx[1], yy[1]];
41169
- }
41170
-
41171
- // TODO: Use this function for other grid-based commands
41172
- function getGridData(bbox, interval, opts) {
41173
- var extent = opts && opts.aligned ?
41174
- getAlignedGridBounds(bbox, interval) :
41175
- getCenteredGridBounds(bbox, interval);
41176
- var xmin = extent[0];
41177
- var ymin = extent[1];
41178
- var w = extent[2] - xmin;
41179
- var h = extent[3] - ymin;
41180
- var cols = Math.round(w / interval);
41181
- var rows = Math.round(h / interval);
41182
- // var xmin = bbox[0] - interval;
41183
- // var ymin = bbox[1] - interval;
41184
- // var xmax = bbox[2] + interval;
41185
- // var ymax = bbox[3] + interval;
41186
- // var w = xmax - xmin;
41187
- // var h = ymax - ymin;
41188
- // var cols = Math.ceil(w / interval);
41189
- // var rows = Math.ceil(h / interval);
41190
- function size() {
41191
- return [cols, rows];
41192
- }
41193
- function cells() {
41194
- return cols * rows;
41195
- }
41196
- function pointToCol(xy) {
41197
- var dx = xy[0] - xmin;
41198
- return Math.floor(dx / w * cols);
41199
- }
41200
- function pointToRow(xy) {
41201
- var dy = xy[1] - ymin;
41202
- return Math.floor(dy / h * rows);
41203
- }
41204
- function colRowToIdx(c, r) {
41205
- if (c < 0 || r < 0 || c >= cols || r >= rows) return -1;
41206
- return r * cols + c;
41207
- }
41208
- function pointToIdx(xy) {
41209
- var c = pointToCol(xy);
41210
- var r = pointToRow(xy);
41211
- return colRowToIdx(c, r);
41212
- }
41213
- function idxToCol(i) {
41214
- return i % cols;
41215
- }
41216
- function idxToRow(i) {
41217
- return Math.floor(i / cols);
41218
- }
41219
- function idxToPoint(idx) {
41220
- var x = xmin + (idxToCol(idx) + 0.5) * interval;
41221
- var y = ymin + (idxToRow(idx) + 0.5) * interval;
41222
- return [x, y];
41223
- }
41224
- function idxToBBox(idx) {
41225
- var c = idxToCol(idx);
41226
- var r = idxToRow(idx);
41227
- return [
41228
- xmin + c * interval, ymin + r * interval,
41229
- xmin + (c + 1) * interval, ymin + (r + 1) * interval
41230
- ];
41231
- }
41232
-
41233
- return {
41234
- size, cells, pointToCol, pointToRow, colRowToIdx, pointToIdx,
41235
- idxToCol, idxToRow, idxToBBox, idxToPoint
41236
- };
41237
- }
41568
+ // function getPointsByIndex(points, indices) {
41569
+ // var arr = [];
41570
+ // for (var i=0; i<indices.length; i++) {
41571
+ // arr.push(points[indices[i]]);
41572
+ // }
41573
+ // return arr;
41574
+ // }
41238
41575
 
41239
41576
  var PointToGrid = /*#__PURE__*/Object.freeze({
41240
41577
  __proto__: null,
41241
41578
  getPointCircleRadius: getPointCircleRadius,
41242
41579
  calcCellProperties: calcCellProperties,
41243
- calcWeights: calcWeights,
41244
- twoCircleIntersection: twoCircleIntersection,
41245
- makeCellPolygon: makeCellPolygon,
41246
- makeCircleCoords: makeCircleCoords,
41247
- getPointIndex: getPointIndex,
41248
- getAlignedGridBounds: getAlignedGridBounds,
41249
- getCenteredGridBounds: getCenteredGridBounds,
41250
- getGridData: getGridData
41580
+ calcWeights: calcWeights
41251
41581
  });
41252
41582
 
41253
41583
  function closeUndershoots(lyr, dataset, opts) {
@@ -41516,7 +41846,7 @@ ${svg}
41516
41846
  });
41517
41847
 
41518
41848
  function getGeoJSON() {
41519
- var features = exportLayerAsGeoJSON(lyr, target.dataset, {}, true);
41849
+ var features = exportLayerAsGeoJSON(lyr, target.dataset, {rfc7946: true}, true);
41520
41850
  return {
41521
41851
  type: 'FeatureCollection',
41522
41852
  features: features
@@ -44026,6 +44356,9 @@ ${svg}
44026
44356
  } else if (name == 'grid') {
44027
44357
  outputDataset = cmd.polygonGrid(targetLayers, targetDataset, opts);
44028
44358
 
44359
+ } else if (name == 'grid2') {
44360
+ outputDataset = cmd.polygonGrid2(targetLayers, targetDataset, opts);
44361
+
44029
44362
  } else if (name == 'help') {
44030
44363
  // placing help command here to handle errors from invalid command names
44031
44364
  cmd.printHelp(command.options);