mapshaper 0.6.49 → 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/mapshaper.js +464 -137
- package/package.json +1 -1
- package/www/mapshaper-gui.js +14 -9
- package/www/mapshaper.js +464 -137
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
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
|
|
|
@@ -24344,6 +24344,19 @@ ${svg}
|
|
|
24344
24344
|
.option('name', nameOpt);
|
|
24345
24345
|
|
|
24346
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
|
+
|
|
24347
24360
|
parser.command('grid')
|
|
24348
24361
|
.describe('create a grid of square or hexagonal polygons')
|
|
24349
24362
|
.option('type', {
|
|
@@ -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);
|
|
@@ -40970,129 +41423,6 @@ ${svg}
|
|
|
40970
41423
|
r2sq * Math.acos(d2/r2) - d2 * Math.sqrt(r2sq - d2 * d2);
|
|
40971
41424
|
}
|
|
40972
41425
|
|
|
40973
|
-
function getAlignedGridBounds(bbox, interval) {
|
|
40974
|
-
var xx = getAlignedRange(bbox[0], bbox[2], interval);
|
|
40975
|
-
var yy = getAlignedRange(bbox[1], bbox[3], interval);
|
|
40976
|
-
return [xx[0], yy[0], xx[1], yy[1]];
|
|
40977
|
-
}
|
|
40978
|
-
|
|
40979
|
-
function getCenteredGridBounds(bbox, interval) {
|
|
40980
|
-
var xx = getCenteredRange(bbox[0], bbox[2], interval);
|
|
40981
|
-
var yy = getCenteredRange(bbox[1], bbox[3], interval);
|
|
40982
|
-
return [xx[0], yy[0], xx[1], yy[1]];
|
|
40983
|
-
}
|
|
40984
|
-
|
|
40985
|
-
// grid boundaries includes the origin
|
|
40986
|
-
// (this way, grids calculated from different sets of points will all align)
|
|
40987
|
-
function getAlignedRange(minCoord, maxCoord, interval) {
|
|
40988
|
-
var idx = Math.floor(minCoord / interval) - 1;
|
|
40989
|
-
var idx2 = Math.ceil(maxCoord / interval) + 1;
|
|
40990
|
-
return [idx * interval, idx2 * interval];
|
|
40991
|
-
}
|
|
40992
|
-
|
|
40993
|
-
function getCenteredRange(minCoord, maxCoord, interval) {
|
|
40994
|
-
var w = maxCoord - minCoord;
|
|
40995
|
-
var w2 = Math.ceil(w / interval) * interval;
|
|
40996
|
-
var pad = (w2 - w) / 2 + interval;
|
|
40997
|
-
return [minCoord - pad, maxCoord + pad];
|
|
40998
|
-
}
|
|
40999
|
-
|
|
41000
|
-
// TODO: Use this function for other grid-based commands
|
|
41001
|
-
function getSquareGridMaker(bbox, interval, opts) {
|
|
41002
|
-
var extent = opts && opts.aligned ?
|
|
41003
|
-
getAlignedGridBounds(bbox, interval) :
|
|
41004
|
-
getCenteredGridBounds(bbox, interval);
|
|
41005
|
-
var xmin = extent[0];
|
|
41006
|
-
var ymin = extent[1];
|
|
41007
|
-
var w = extent[2] - xmin;
|
|
41008
|
-
var h = extent[3] - ymin;
|
|
41009
|
-
var cols = Math.round(w / interval);
|
|
41010
|
-
var rows = Math.round(h / interval);
|
|
41011
|
-
function cells() {
|
|
41012
|
-
return cols * rows;
|
|
41013
|
-
}
|
|
41014
|
-
function pointToCol(xy) {
|
|
41015
|
-
var dx = xy[0] - xmin;
|
|
41016
|
-
return Math.floor(dx / w * cols);
|
|
41017
|
-
}
|
|
41018
|
-
function pointToRow(xy) {
|
|
41019
|
-
var dy = xy[1] - ymin;
|
|
41020
|
-
return Math.floor(dy / h * rows);
|
|
41021
|
-
}
|
|
41022
|
-
function colRowToIdx(c, r) {
|
|
41023
|
-
if (c < 0 || r < 0 || c >= cols || r >= rows) return -1;
|
|
41024
|
-
return r * cols + c;
|
|
41025
|
-
}
|
|
41026
|
-
function pointToIdx(xy) {
|
|
41027
|
-
var c = pointToCol(xy);
|
|
41028
|
-
var r = pointToRow(xy);
|
|
41029
|
-
return colRowToIdx(c, r);
|
|
41030
|
-
}
|
|
41031
|
-
function idxToCol(i) {
|
|
41032
|
-
return i % cols;
|
|
41033
|
-
}
|
|
41034
|
-
function idxToRow(i) {
|
|
41035
|
-
return Math.floor(i / cols);
|
|
41036
|
-
}
|
|
41037
|
-
function idxToPoint(idx) {
|
|
41038
|
-
var x = xmin + (idxToCol(idx) + 0.5) * interval;
|
|
41039
|
-
var y = ymin + (idxToRow(idx) + 0.5) * interval;
|
|
41040
|
-
return [x, y];
|
|
41041
|
-
}
|
|
41042
|
-
function idxToBBox(idx) {
|
|
41043
|
-
var c = idxToCol(idx);
|
|
41044
|
-
var r = idxToRow(idx);
|
|
41045
|
-
return [
|
|
41046
|
-
xmin + c * interval, ymin + r * interval,
|
|
41047
|
-
xmin + (c + 1) * interval, ymin + (r + 1) * interval
|
|
41048
|
-
];
|
|
41049
|
-
}
|
|
41050
|
-
|
|
41051
|
-
function makeCellPolygon(idx, opts) {
|
|
41052
|
-
var coords = opts.circles ?
|
|
41053
|
-
makeCircleCoords(idx, opts) :
|
|
41054
|
-
makeCellCoords(idx, opts);
|
|
41055
|
-
return {
|
|
41056
|
-
type: 'Polygon',
|
|
41057
|
-
coordinates: [coords]
|
|
41058
|
-
};
|
|
41059
|
-
}
|
|
41060
|
-
|
|
41061
|
-
function makeCellCoords(idx, opts) {
|
|
41062
|
-
var bbox = idxToBBox(idx);
|
|
41063
|
-
var margin = opts.interval * (opts.cell_margin || 0);
|
|
41064
|
-
var a = bbox[0] + margin,
|
|
41065
|
-
b = bbox[1] + margin,
|
|
41066
|
-
c = bbox[2] - margin,
|
|
41067
|
-
d = bbox[3] - margin;
|
|
41068
|
-
return [[a, b],[a, d],[c, d],[c, b],[a, b]];
|
|
41069
|
-
}
|
|
41070
|
-
|
|
41071
|
-
function makeCircleCoords(idx, opts) {
|
|
41072
|
-
var center = idxToPoint(idx);
|
|
41073
|
-
var margin = opts.cell_margin > 0 ? opts.cell_margin : 1e-6;
|
|
41074
|
-
var radius = opts.interval / 2 * (1 - margin);
|
|
41075
|
-
var vertices = opts.vertices || 20;
|
|
41076
|
-
return getPointBufferCoordinates(center, radius, vertices, getPlanarSegmentEndpoint);
|
|
41077
|
-
}
|
|
41078
|
-
|
|
41079
|
-
return {
|
|
41080
|
-
// size,
|
|
41081
|
-
// pointToCol,
|
|
41082
|
-
// pointToRow,
|
|
41083
|
-
// makeCellCoords,
|
|
41084
|
-
// makeCircleCoords,
|
|
41085
|
-
cells,
|
|
41086
|
-
colRowToIdx,
|
|
41087
|
-
pointToIdx,
|
|
41088
|
-
idxToCol,
|
|
41089
|
-
idxToRow,
|
|
41090
|
-
idxToBBox,
|
|
41091
|
-
idxToPoint,
|
|
41092
|
-
makeCellPolygon
|
|
41093
|
-
};
|
|
41094
|
-
}
|
|
41095
|
-
|
|
41096
41426
|
// Returns a function that receives a cell index and returns indices of points
|
|
41097
41427
|
// within a given distance of the cell.
|
|
41098
41428
|
function getGridToPointIndex(points, grid, radius) {
|
|
@@ -41107,6 +41437,7 @@ ${svg}
|
|
|
41107
41437
|
bboxIndex.add.apply(bboxIndex, bbox);
|
|
41108
41438
|
});
|
|
41109
41439
|
bboxIndex.finish();
|
|
41440
|
+
|
|
41110
41441
|
return function(i) {
|
|
41111
41442
|
if (!gridIndex.hasId(i)) {
|
|
41112
41443
|
return empty;
|
|
@@ -41117,7 +41448,6 @@ ${svg}
|
|
|
41117
41448
|
};
|
|
41118
41449
|
}
|
|
41119
41450
|
|
|
41120
|
-
|
|
41121
41451
|
// TODO: support spherical coords
|
|
41122
41452
|
function getPointBounds(p, radius) {
|
|
41123
41453
|
return [p[0] - radius, p[1] - radius, p[0] + radius, p[1] + radius];
|
|
@@ -41125,18 +41455,12 @@ ${svg}
|
|
|
41125
41455
|
|
|
41126
41456
|
function addPointToGridIndex(p, index, grid, addNeighbors) {
|
|
41127
41457
|
var i = grid.pointToIdx(p);
|
|
41128
|
-
var c = grid.
|
|
41129
|
-
var r = grid.idxToRow(i);
|
|
41458
|
+
var [c, r] = grid.idxToColRow(i);
|
|
41130
41459
|
addCellToGridIndex(c, r, grid, index);
|
|
41131
41460
|
if (addNeighbors) {
|
|
41132
|
-
|
|
41133
|
-
|
|
41134
|
-
|
|
41135
|
-
addCellToGridIndex(c, r+1, grid, index);
|
|
41136
|
-
addCellToGridIndex(c, r-1, grid, index);
|
|
41137
|
-
addCellToGridIndex(c-1, r+1, grid, index);
|
|
41138
|
-
addCellToGridIndex(c-1, r, grid, index);
|
|
41139
|
-
addCellToGridIndex(c-1, r-1, grid, index);
|
|
41461
|
+
grid.forEachNeighbor(c, r, function(c, r) {
|
|
41462
|
+
addCellToGridIndex(c, r, grid, index);
|
|
41463
|
+
});
|
|
41140
41464
|
}
|
|
41141
41465
|
}
|
|
41142
41466
|
|
|
@@ -44032,6 +44356,9 @@ ${svg}
|
|
|
44032
44356
|
} else if (name == 'grid') {
|
|
44033
44357
|
outputDataset = cmd.polygonGrid(targetLayers, targetDataset, opts);
|
|
44034
44358
|
|
|
44359
|
+
} else if (name == 'grid2') {
|
|
44360
|
+
outputDataset = cmd.polygonGrid2(targetLayers, targetDataset, opts);
|
|
44361
|
+
|
|
44035
44362
|
} else if (name == 'help') {
|
|
44036
44363
|
// placing help command here to handle errors from invalid command names
|
|
44037
44364
|
cmd.printHelp(command.options);
|