mapshaper 0.6.117 → 0.6.118
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 +764 -177
- package/package.json +1 -1
- package/www/index.html +4 -0
- package/www/mapshaper-gui.js +214 -17
- package/www/mapshaper.js +764 -177
- package/www/page.css +12 -0
package/www/mapshaper.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
get expandoBuffer () { return expandoBuffer; },
|
|
20
20
|
get extend () { return extend$1; },
|
|
21
21
|
get extendBuffer () { return extendBuffer; },
|
|
22
|
-
get find () { return find; },
|
|
22
|
+
get find () { return find$1; },
|
|
23
23
|
get findMedian () { return findMedian; },
|
|
24
24
|
get findQuantile () { return findQuantile; },
|
|
25
25
|
get findRankByValue () { return findRankByValue; },
|
|
@@ -442,7 +442,7 @@
|
|
|
442
442
|
}, true);
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
-
function find(arr, test, ctx) {
|
|
445
|
+
function find$1(arr, test, ctx) {
|
|
446
446
|
var matches = arr.filter(test, ctx);
|
|
447
447
|
return matches.length === 0 ? null : matches[0];
|
|
448
448
|
}
|
|
@@ -6399,41 +6399,52 @@
|
|
|
6399
6399
|
};
|
|
6400
6400
|
}
|
|
6401
6401
|
|
|
6402
|
-
// Used for building topology
|
|
6402
|
+
// Used for building topology.
|
|
6403
|
+
//
|
|
6404
|
+
// Every arc is stored as a reference into some source coordinate arrays
|
|
6405
|
+
// (srcXX/srcYY) plus an inclusive [start..end] index range. The caller
|
|
6406
|
+
// decides which buffer to hand in: the shared xx/yy for normal arcs, or
|
|
6407
|
+
// a freshly-allocated merged buffer for split/wrap-around arcs. ArcIndex
|
|
6408
|
+
// doesn't care which — no sentinels, no special cases in its own code.
|
|
6403
6409
|
//
|
|
6404
6410
|
function ArcIndex(pointCount) {
|
|
6405
6411
|
var hashTableSize = Math.floor(pointCount * 0.25 + 1),
|
|
6406
6412
|
hash = getXYHash(hashTableSize),
|
|
6407
6413
|
hashTable = new Int32Array(hashTableSize),
|
|
6408
6414
|
chainIds = [],
|
|
6409
|
-
|
|
6415
|
+
arcSrcXX = [],
|
|
6416
|
+
arcSrcYY = [],
|
|
6417
|
+
arcStart = [],
|
|
6418
|
+
arcEnd = [],
|
|
6410
6419
|
arcPoints = 0;
|
|
6411
6420
|
|
|
6412
|
-
|
|
6421
|
+
initializeArray(hashTable, -1);
|
|
6413
6422
|
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6423
|
+
// Register an arc whose coordinates are `srcXX[start..end]`, `srcYY[start..end]`
|
|
6424
|
+
// (inclusive). Returns the new arc id.
|
|
6425
|
+
this.addArc = function(srcXX, srcYY, start, end) {
|
|
6426
|
+
var arcId = arcSrcXX.length,
|
|
6427
|
+
key = hash(srcXX[end], srcYY[end]);
|
|
6428
|
+
chainIds.push(hashTable[key]);
|
|
6419
6429
|
hashTable[key] = arcId;
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6430
|
+
arcSrcXX.push(srcXX);
|
|
6431
|
+
arcSrcYY.push(srcYY);
|
|
6432
|
+
arcStart.push(start);
|
|
6433
|
+
arcEnd.push(end);
|
|
6434
|
+
arcPoints += end - start + 1;
|
|
6423
6435
|
return arcId;
|
|
6424
6436
|
};
|
|
6425
6437
|
|
|
6426
|
-
// Look for a previously generated arc with the same sequence of coords, but
|
|
6427
|
-
// opposite direction. (This program uses the convention of CW for
|
|
6428
|
-
//
|
|
6438
|
+
// Look for a previously generated arc with the same sequence of coords, but
|
|
6439
|
+
// in the opposite direction. (This program uses the convention of CW for
|
|
6440
|
+
// space-enclosing rings, CCW for holes, so coincident boundaries should
|
|
6441
|
+
// contain the same points in reverse sequence.)
|
|
6429
6442
|
//
|
|
6430
6443
|
this.findDuplicateArc = function(xx, yy, start, end, getNext, getPrev) {
|
|
6431
|
-
// First, look for a reverse match
|
|
6432
6444
|
var arcId = findArcNeighbor(xx, yy, start, end, getNext);
|
|
6433
6445
|
if (arcId === null) {
|
|
6434
|
-
// Look for forward match
|
|
6435
|
-
//
|
|
6436
|
-
// Shapefiles sometimes have duplicate paths)
|
|
6446
|
+
// Look for forward match (abnormal topology, but we accept it because
|
|
6447
|
+
// in-the-wild Shapefiles sometimes have duplicate paths).
|
|
6437
6448
|
arcId = findArcNeighbor(xx, yy, end, start, getPrev);
|
|
6438
6449
|
} else {
|
|
6439
6450
|
arcId = ~arcId;
|
|
@@ -6445,17 +6456,14 @@
|
|
|
6445
6456
|
var next = getNext(start),
|
|
6446
6457
|
key = hash(xx[start], yy[start]),
|
|
6447
6458
|
arcId = hashTable[key],
|
|
6448
|
-
|
|
6449
|
-
|
|
6459
|
+
sx, sy, s, e;
|
|
6450
6460
|
while (arcId != -1) {
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
//
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
if (arcX[0] === xx[end] && arcX[len-1] === xx[start] && arcX[len-2] === xx[next] &&
|
|
6458
|
-
arcY[0] === yy[end] && arcY[len-1] === yy[start] && arcY[len-2] === yy[next]) {
|
|
6461
|
+
sx = arcSrcXX[arcId]; sy = arcSrcYY[arcId];
|
|
6462
|
+
s = arcStart[arcId]; e = arcEnd[arcId];
|
|
6463
|
+
// Check endpoints and one segment. A more rigorous match would compare
|
|
6464
|
+
// every segment, but that's slower and this is sufficient in practice.
|
|
6465
|
+
if (sx[s] === xx[end] && sx[e] === xx[start] && sx[e - 1] === xx[next] &&
|
|
6466
|
+
sy[s] === yy[end] && sy[e] === yy[start] && sy[e - 1] === yy[next]) {
|
|
6459
6467
|
return arcId;
|
|
6460
6468
|
}
|
|
6461
6469
|
arcId = chainIds[arcId];
|
|
@@ -6464,22 +6472,31 @@
|
|
|
6464
6472
|
}
|
|
6465
6473
|
|
|
6466
6474
|
this.getVertexData = function() {
|
|
6467
|
-
var
|
|
6468
|
-
|
|
6469
|
-
|
|
6475
|
+
var arcCount = arcSrcXX.length,
|
|
6476
|
+
destXX = new Float64Array(arcPoints),
|
|
6477
|
+
destYY = new Float64Array(arcPoints),
|
|
6478
|
+
nn = new Uint32Array(arcCount),
|
|
6470
6479
|
copied = 0,
|
|
6471
|
-
|
|
6472
|
-
for (
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6480
|
+
sx, sy, s, e, len, i;
|
|
6481
|
+
for (i = 0; i < arcCount; i++) {
|
|
6482
|
+
sx = arcSrcXX[i]; sy = arcSrcYY[i];
|
|
6483
|
+
s = arcStart[i]; e = arcEnd[i];
|
|
6484
|
+
len = e - s + 1;
|
|
6485
|
+
if (sx.subarray) {
|
|
6486
|
+
destXX.set(sx.subarray(s, e + 1), copied);
|
|
6487
|
+
destYY.set(sy.subarray(s, e + 1), copied);
|
|
6488
|
+
} else {
|
|
6489
|
+
for (var k = 0; k < len; k++) {
|
|
6490
|
+
destXX[copied + k] = sx[s + k];
|
|
6491
|
+
destYY[copied + k] = sy[s + k];
|
|
6492
|
+
}
|
|
6493
|
+
}
|
|
6477
6494
|
nn[i] = len;
|
|
6478
6495
|
copied += len;
|
|
6479
6496
|
}
|
|
6480
6497
|
return {
|
|
6481
|
-
xx:
|
|
6482
|
-
yy:
|
|
6498
|
+
xx: destXX,
|
|
6499
|
+
yy: destYY,
|
|
6483
6500
|
nn: nn
|
|
6484
6501
|
};
|
|
6485
6502
|
};
|
|
@@ -6578,18 +6595,15 @@
|
|
|
6578
6595
|
var pointCount = xx.length,
|
|
6579
6596
|
chainIds = initPointChains(xx, yy),
|
|
6580
6597
|
pathIds = initPathIds(pointCount, nn),
|
|
6598
|
+
pathIsRing = initPathIsRing(nn, xx, yy),
|
|
6599
|
+
isNode = computeIsNode(nn, xx, yy, chainIds, pathIds, pathIsRing),
|
|
6581
6600
|
index = new ArcIndex(pointCount),
|
|
6582
|
-
slice = usingTypedArrays() ? xx.subarray : Array.prototype.slice,
|
|
6583
6601
|
paths, retn;
|
|
6584
6602
|
paths = convertPaths(nn);
|
|
6585
6603
|
retn = index.getVertexData();
|
|
6586
6604
|
retn.paths = paths;
|
|
6587
6605
|
return retn;
|
|
6588
6606
|
|
|
6589
|
-
function usingTypedArrays() {
|
|
6590
|
-
return !!(xx.subarray && yy.subarray);
|
|
6591
|
-
}
|
|
6592
|
-
|
|
6593
6607
|
function convertPaths(nn) {
|
|
6594
6608
|
var paths = [],
|
|
6595
6609
|
pointId = 0,
|
|
@@ -6602,28 +6616,28 @@
|
|
|
6602
6616
|
return paths;
|
|
6603
6617
|
}
|
|
6604
6618
|
|
|
6619
|
+
// Fast neighbour lookups using the precomputed pathIsRing cache.
|
|
6620
|
+
// Used by findDuplicateArc (via addEdge/addSplitEdge) and by addRing.
|
|
6605
6621
|
function nextPoint(id) {
|
|
6606
6622
|
var partId = pathIds[id],
|
|
6607
6623
|
nextId = id + 1;
|
|
6608
6624
|
if (nextId < pointCount && pathIds[nextId] === partId) {
|
|
6609
|
-
return
|
|
6625
|
+
return nextId;
|
|
6610
6626
|
}
|
|
6611
|
-
|
|
6612
|
-
return sameXY(id, id - len + 1) ? id - len + 2 : -1;
|
|
6627
|
+
return pathIsRing[partId] ? id - nn[partId] + 2 : -1;
|
|
6613
6628
|
}
|
|
6614
6629
|
|
|
6615
6630
|
function prevPoint(id) {
|
|
6616
6631
|
var partId = pathIds[id],
|
|
6617
6632
|
prevId = id - 1;
|
|
6618
6633
|
if (prevId >= 0 && pathIds[prevId] === partId) {
|
|
6619
|
-
return
|
|
6634
|
+
return prevId;
|
|
6620
6635
|
}
|
|
6621
|
-
|
|
6622
|
-
return sameXY(id, id + len - 1) ? id + len - 2 : -1;
|
|
6636
|
+
return pathIsRing[partId] ? id + nn[partId] - 2 : -1;
|
|
6623
6637
|
}
|
|
6624
6638
|
|
|
6625
|
-
function
|
|
6626
|
-
return
|
|
6639
|
+
function pointIsArcEndpoint(id) {
|
|
6640
|
+
return isNode[id] === 1;
|
|
6627
6641
|
}
|
|
6628
6642
|
|
|
6629
6643
|
// Convert a non-topological path to one or more topological arcs
|
|
@@ -6666,49 +6680,9 @@
|
|
|
6666
6680
|
return arcIds;
|
|
6667
6681
|
}
|
|
6668
6682
|
|
|
6669
|
-
// Test if a point @id is an endpoint of a topological path
|
|
6670
|
-
function pointIsArcEndpoint(id) {
|
|
6671
|
-
var id2 = chainIds[id],
|
|
6672
|
-
prev = prevPoint(id),
|
|
6673
|
-
next = nextPoint(id),
|
|
6674
|
-
prev2, next2;
|
|
6675
|
-
if (prev == -1 || next == -1) {
|
|
6676
|
-
// @id is an endpoint if it is the start or end of an open path
|
|
6677
|
-
return true;
|
|
6678
|
-
}
|
|
6679
|
-
while (id != id2) {
|
|
6680
|
-
prev2 = prevPoint(id2);
|
|
6681
|
-
next2 = nextPoint(id2);
|
|
6682
|
-
if (prev2 == -1 || next2 == -1 || brokenEdge(prev, next, prev2, next2)) {
|
|
6683
|
-
// there is a discontinuity at @id -- point is arc endpoint
|
|
6684
|
-
return true;
|
|
6685
|
-
}
|
|
6686
|
-
id2 = chainIds[id2];
|
|
6687
|
-
}
|
|
6688
|
-
return false;
|
|
6689
|
-
}
|
|
6690
|
-
|
|
6691
|
-
// a and b are two vertices with the same x, y coordinates
|
|
6692
|
-
// test if the segments on either side of them are also identical
|
|
6693
|
-
function brokenEdge(aprev, anext, bprev, bnext) {
|
|
6694
|
-
var apx = xx[aprev],
|
|
6695
|
-
anx = xx[anext],
|
|
6696
|
-
bpx = xx[bprev],
|
|
6697
|
-
bnx = xx[bnext],
|
|
6698
|
-
apy = yy[aprev],
|
|
6699
|
-
any = yy[anext],
|
|
6700
|
-
bpy = yy[bprev],
|
|
6701
|
-
bny = yy[bnext];
|
|
6702
|
-
if (apx == bnx && anx == bpx && apy == bny && any == bpy ||
|
|
6703
|
-
apx == bpx && anx == bnx && apy == bpy && any == bny) {
|
|
6704
|
-
return false;
|
|
6705
|
-
}
|
|
6706
|
-
return true;
|
|
6707
|
-
}
|
|
6708
|
-
|
|
6709
6683
|
function mergeArcParts(src, startId, endId, startId2, endId2) {
|
|
6710
6684
|
var len = endId - startId + endId2 - startId2 + 2,
|
|
6711
|
-
ArrayClass =
|
|
6685
|
+
ArrayClass = src.subarray ? Float64Array : Array,
|
|
6712
6686
|
dest = new ArrayClass(len),
|
|
6713
6687
|
j = 0, i;
|
|
6714
6688
|
for (i=startId; i <= endId; i++) {
|
|
@@ -6723,8 +6697,12 @@
|
|
|
6723
6697
|
function addSplitEdge(start1, end1, start2, end2) {
|
|
6724
6698
|
var arcId = index.findDuplicateArc(xx, yy, start1, end2, nextPoint, prevPoint);
|
|
6725
6699
|
if (arcId === null) {
|
|
6726
|
-
|
|
6727
|
-
|
|
6700
|
+
// Coordinates for a split (wrap-around) edge don't form a contiguous
|
|
6701
|
+
// slice of xx/yy, so we build a standalone buffer and hand it to the
|
|
6702
|
+
// index as the arc's source.
|
|
6703
|
+
var mx = mergeArcParts(xx, start1, end1, start2, end2),
|
|
6704
|
+
my = mergeArcParts(yy, start1, end1, start2, end2);
|
|
6705
|
+
arcId = index.addArc(mx, my, 0, mx.length - 1);
|
|
6728
6706
|
}
|
|
6729
6707
|
return arcId;
|
|
6730
6708
|
}
|
|
@@ -6733,8 +6711,7 @@
|
|
|
6733
6711
|
// search for a matching edge that has already been generated
|
|
6734
6712
|
var arcId = index.findDuplicateArc(xx, yy, start, end, nextPoint, prevPoint);
|
|
6735
6713
|
if (arcId === null) {
|
|
6736
|
-
arcId = index.addArc(
|
|
6737
|
-
slice.call(yy, start, end + 1));
|
|
6714
|
+
arcId = index.addArc(xx, yy, start, end);
|
|
6738
6715
|
}
|
|
6739
6716
|
return arcId;
|
|
6740
6717
|
}
|
|
@@ -6777,6 +6754,87 @@
|
|
|
6777
6754
|
return pathIds;
|
|
6778
6755
|
}
|
|
6779
6756
|
|
|
6757
|
+
// Per-path flag: 1 if the path is a closed ring (first vertex coincides with
|
|
6758
|
+
// last vertex), else 0. Computed once so that prevPoint()/nextPoint() don't
|
|
6759
|
+
// need to call sameXY() at path boundaries.
|
|
6760
|
+
//
|
|
6761
|
+
function initPathIsRing(nn, xx, yy) {
|
|
6762
|
+
var pathCount = nn.length,
|
|
6763
|
+
pathIsRing = new Uint8Array(pathCount),
|
|
6764
|
+
pstart = 0, len;
|
|
6765
|
+
for (var p = 0; p < pathCount; p++) {
|
|
6766
|
+
len = nn[p];
|
|
6767
|
+
if (len > 1 &&
|
|
6768
|
+
xx[pstart] === xx[pstart + len - 1] &&
|
|
6769
|
+
yy[pstart] === yy[pstart + len - 1]) {
|
|
6770
|
+
pathIsRing[p] = 1;
|
|
6771
|
+
}
|
|
6772
|
+
pstart += len;
|
|
6773
|
+
}
|
|
6774
|
+
return pathIsRing;
|
|
6775
|
+
}
|
|
6776
|
+
|
|
6777
|
+
// Decide, for every point, whether it is a topological node (an arc
|
|
6778
|
+
// endpoint). Being a node is a property of the entire coincident-point
|
|
6779
|
+
// chain: all points sharing a location agree on the answer. So we walk
|
|
6780
|
+
// each chain at most once — O(n) total — instead of doing the walk
|
|
6781
|
+
// independently at every point (O(n * K), quadratic per chain).
|
|
6782
|
+
//
|
|
6783
|
+
// A chain's points are nodes iff:
|
|
6784
|
+
// - any member has a missing neighbour (open-path endpoint), or
|
|
6785
|
+
// - two members disagree on the unordered pair of neighbour coords.
|
|
6786
|
+
//
|
|
6787
|
+
function computeIsNode(nn, xx, yy, chainIds, pathIds, pathIsRing) {
|
|
6788
|
+
var n = xx.length,
|
|
6789
|
+
isNode = new Uint8Array(n),
|
|
6790
|
+
done = new Uint8Array(n);
|
|
6791
|
+
|
|
6792
|
+
function nextPoint(id) {
|
|
6793
|
+
var part = pathIds[id], nid = id + 1;
|
|
6794
|
+
if (nid < n && pathIds[nid] === part) return nid;
|
|
6795
|
+
return pathIsRing[part] ? id - nn[part] + 2 : -1;
|
|
6796
|
+
}
|
|
6797
|
+
|
|
6798
|
+
function prevPoint(id) {
|
|
6799
|
+
var part = pathIds[id], pid = id - 1;
|
|
6800
|
+
if (pid >= 0 && pathIds[pid] === part) return pid;
|
|
6801
|
+
return pathIsRing[part] ? id + nn[part] - 2 : -1;
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6804
|
+
for (var i = 0; i < n; i++) {
|
|
6805
|
+
if (done[i]) continue;
|
|
6806
|
+
var result = chainIsBroken(i);
|
|
6807
|
+
var id = i;
|
|
6808
|
+
do {
|
|
6809
|
+
isNode[id] = result;
|
|
6810
|
+
done[id] = 1;
|
|
6811
|
+
id = chainIds[id];
|
|
6812
|
+
} while (id !== i);
|
|
6813
|
+
}
|
|
6814
|
+
return isNode;
|
|
6815
|
+
|
|
6816
|
+
// Returns 1 if the chain containing `start` has any broken neighbour
|
|
6817
|
+
// signature (i.e. all members are nodes), else 0.
|
|
6818
|
+
function chainIsBroken(start) {
|
|
6819
|
+
var prev = prevPoint(start),
|
|
6820
|
+
next = nextPoint(start);
|
|
6821
|
+
if (prev === -1 || next === -1) return 1;
|
|
6822
|
+
var refPX = xx[prev], refPY = yy[prev],
|
|
6823
|
+
refNX = xx[next], refNY = yy[next];
|
|
6824
|
+
var id = chainIds[start];
|
|
6825
|
+
while (id !== start) {
|
|
6826
|
+
var p = prevPoint(id), q = nextPoint(id);
|
|
6827
|
+
if (p === -1 || q === -1) return 1;
|
|
6828
|
+
var px = xx[p], py = yy[p], qx = xx[q], qy = yy[q];
|
|
6829
|
+
var fwd = px === refPX && py === refPY && qx === refNX && qy === refNY;
|
|
6830
|
+
var rev = px === refNX && py === refNY && qx === refPX && qy === refPY;
|
|
6831
|
+
if (!fwd && !rev) return 1;
|
|
6832
|
+
id = chainIds[id];
|
|
6833
|
+
}
|
|
6834
|
+
return 0;
|
|
6835
|
+
}
|
|
6836
|
+
}
|
|
6837
|
+
|
|
6780
6838
|
function replaceArcIds(src, replacements) {
|
|
6781
6839
|
return src.map(function(shape) {
|
|
6782
6840
|
return replaceArcsInShape(shape, replacements);
|
|
@@ -18724,13 +18782,13 @@
|
|
|
18724
18782
|
// default is true iff layers contain attributes
|
|
18725
18783
|
return utils.some(layers, function(lyr) {
|
|
18726
18784
|
var fields = lyr.data ? lyr.data.getFields() : [];
|
|
18727
|
-
var haveData = useFeatureProperties(fields, opts);
|
|
18785
|
+
var haveData = useFeatureProperties$1(fields, opts);
|
|
18728
18786
|
var haveId = !!getIdField(fields, opts);
|
|
18729
18787
|
return haveData || haveId;
|
|
18730
18788
|
});
|
|
18731
18789
|
}
|
|
18732
18790
|
|
|
18733
|
-
function useFeatureProperties(fields, opts) {
|
|
18791
|
+
function useFeatureProperties$1(fields, opts) {
|
|
18734
18792
|
return !(opts.drop_table || opts.cut_table || fields.length === 0 ||
|
|
18735
18793
|
fields.length == 1 && fields[0] == GeoJSON.ID_FIELD);
|
|
18736
18794
|
}
|
|
@@ -18739,7 +18797,7 @@
|
|
|
18739
18797
|
var fields = table ? table.getFields() : [],
|
|
18740
18798
|
idField = getIdField(fields, opts),
|
|
18741
18799
|
properties, records;
|
|
18742
|
-
if (!useFeatureProperties(fields, opts)) {
|
|
18800
|
+
if (!useFeatureProperties$1(fields, opts)) {
|
|
18743
18801
|
return null;
|
|
18744
18802
|
}
|
|
18745
18803
|
records = table.getRecords();
|
|
@@ -24500,12 +24558,10 @@ ${svg}
|
|
|
24500
24558
|
}
|
|
24501
24559
|
|
|
24502
24560
|
async function exportLayerToGeoPackage(lyr, dataset, gpkg, opts) {
|
|
24503
|
-
var
|
|
24561
|
+
var fields, columns, tableName, targetSrs, state;
|
|
24504
24562
|
if (!lyr.geometry_type) return;
|
|
24505
|
-
|
|
24506
|
-
|
|
24507
|
-
if (features.length === 0) return;
|
|
24508
|
-
fields = inferFieldTypes(features);
|
|
24563
|
+
fields = inferFieldTypesFromLayer(lyr, dataset, opts);
|
|
24564
|
+
if (!fields) return;
|
|
24509
24565
|
tableName = getTableName(lyr.name);
|
|
24510
24566
|
columns = fields.map(function(field) {
|
|
24511
24567
|
return {
|
|
@@ -24522,8 +24578,11 @@ ${svg}
|
|
|
24522
24578
|
// GeoJSON is EPSG:4326 and reprojects unless given EPSG:4326 metadata.
|
|
24523
24579
|
// Mapshaper output coords are already in target CRS, so suppress reprojection.
|
|
24524
24580
|
var srs = getSourceSrsWithoutReprojection(featureDao && featureDao.srs, targetSrs);
|
|
24525
|
-
|
|
24526
|
-
|
|
24581
|
+
state = initLayerFeatureExportState(lyr, dataset, opts);
|
|
24582
|
+
var featureIndex = 0;
|
|
24583
|
+
for (var i = 0; i < state.count; i++) {
|
|
24584
|
+
var feat = exportFeatureAtIndex(state, i);
|
|
24585
|
+
if (!feat || !feat.geometry) continue;
|
|
24527
24586
|
var normalized = normalizeFeature(feat, fields);
|
|
24528
24587
|
try {
|
|
24529
24588
|
await gpkg.addGeoJSONFeatureToGeoPackageWithFeatureDaoAndSrs(
|
|
@@ -24533,8 +24592,9 @@ ${svg}
|
|
|
24533
24592
|
);
|
|
24534
24593
|
} catch (e) {
|
|
24535
24594
|
throw Error('GeoPackage insert failed at layer "' + tableName +
|
|
24536
|
-
'", feature ' +
|
|
24595
|
+
'", feature ' + featureIndex + ': ' + e.message);
|
|
24537
24596
|
}
|
|
24597
|
+
featureIndex++;
|
|
24538
24598
|
}
|
|
24539
24599
|
}
|
|
24540
24600
|
|
|
@@ -24561,9 +24621,11 @@ ${svg}
|
|
|
24561
24621
|
stop$1('Unable to export GeoPackage bytes');
|
|
24562
24622
|
}
|
|
24563
24623
|
|
|
24564
|
-
function
|
|
24624
|
+
function inferFieldTypesFromLayer(lyr, dataset, opts) {
|
|
24625
|
+
var sawFeature = false;
|
|
24565
24626
|
var index = {};
|
|
24566
|
-
|
|
24627
|
+
forEachLayerExportFeature(lyr, dataset, opts, function(feat) {
|
|
24628
|
+
sawFeature = true;
|
|
24567
24629
|
var props = feat.properties || {};
|
|
24568
24630
|
Object.keys(props).forEach(function(name) {
|
|
24569
24631
|
if (!isSupportedPropertyName(name)) return;
|
|
@@ -24577,11 +24639,79 @@ ${svg}
|
|
|
24577
24639
|
}
|
|
24578
24640
|
});
|
|
24579
24641
|
});
|
|
24642
|
+
if (!sawFeature) return null;
|
|
24580
24643
|
return Object.keys(index).map(function(name) {
|
|
24581
24644
|
return {name: name, type: index[name]};
|
|
24582
24645
|
});
|
|
24583
24646
|
}
|
|
24584
24647
|
|
|
24648
|
+
function forEachLayerExportFeature(lyr, dataset, opts, cb) {
|
|
24649
|
+
var state = initLayerFeatureExportState(lyr, dataset, opts);
|
|
24650
|
+
var featureIndex = 0;
|
|
24651
|
+
for (var i = 0; i < state.count; i++) {
|
|
24652
|
+
var feature = exportFeatureAtIndex(state, i);
|
|
24653
|
+
if (!feature || !feature.geometry) continue;
|
|
24654
|
+
cb(feature, featureIndex++, i);
|
|
24655
|
+
}
|
|
24656
|
+
}
|
|
24657
|
+
|
|
24658
|
+
function initLayerFeatureExportState(lyr, dataset, opts) {
|
|
24659
|
+
var records = lyr.data ? lyr.data.getRecords() : null;
|
|
24660
|
+
var fields = lyr.data ? lyr.data.getFields() : [];
|
|
24661
|
+
var shapes = lyr.shapes || null;
|
|
24662
|
+
if (records && shapes && records.length !== shapes.length) {
|
|
24663
|
+
stop$1('Mismatch between number of properties and number of shapes');
|
|
24664
|
+
}
|
|
24665
|
+
return {
|
|
24666
|
+
lyr: lyr,
|
|
24667
|
+
dataset: dataset,
|
|
24668
|
+
opts: opts || {},
|
|
24669
|
+
fields: fields,
|
|
24670
|
+
records: records,
|
|
24671
|
+
shapes: shapes,
|
|
24672
|
+
count: Math.max(records ? records.length : 0, shapes ? shapes.length : 0),
|
|
24673
|
+
idField: getIdField(fields, opts || {}),
|
|
24674
|
+
useProps: useFeatureProperties(fields, opts || {})
|
|
24675
|
+
};
|
|
24676
|
+
}
|
|
24677
|
+
|
|
24678
|
+
function exportFeatureAtIndex(state, i) {
|
|
24679
|
+
var shape = state.shapes ? state.shapes[i] : null;
|
|
24680
|
+
var geom = shape ? GeoJSON.exporters[state.lyr.geometry_type](shape, state.dataset.arcs, state.opts) : null;
|
|
24681
|
+
var rec = state.records ? state.records[i] : null;
|
|
24682
|
+
var props = null;
|
|
24683
|
+
if (state.useProps && rec) {
|
|
24684
|
+
if (state.idField == GeoJSON.ID_FIELD) {
|
|
24685
|
+
props = Object.assign({}, rec);
|
|
24686
|
+
delete props[state.idField];
|
|
24687
|
+
} else {
|
|
24688
|
+
props = rec;
|
|
24689
|
+
}
|
|
24690
|
+
}
|
|
24691
|
+
var feat = GeoJSON.toFeature(geom, props);
|
|
24692
|
+
if (state.idField && rec) {
|
|
24693
|
+
feat.id = state.idField in rec ? rec[state.idField] : null;
|
|
24694
|
+
}
|
|
24695
|
+
if (state.opts.no_null_props && !feat.properties) {
|
|
24696
|
+
feat.properties = {};
|
|
24697
|
+
}
|
|
24698
|
+
if (Array.isArray(state.opts.hoist) && feat.properties) {
|
|
24699
|
+
feat.properties = Object.assign({}, feat.properties);
|
|
24700
|
+
state.opts.hoist.forEach(function(field) {
|
|
24701
|
+
if (Object.prototype.hasOwnProperty.call(feat.properties, field)) {
|
|
24702
|
+
feat[field] = feat.properties[field];
|
|
24703
|
+
delete feat.properties[field];
|
|
24704
|
+
}
|
|
24705
|
+
});
|
|
24706
|
+
}
|
|
24707
|
+
return feat;
|
|
24708
|
+
}
|
|
24709
|
+
|
|
24710
|
+
function useFeatureProperties(fields, opts) {
|
|
24711
|
+
return !(opts.drop_table || opts.cut_table || fields.length === 0 ||
|
|
24712
|
+
fields.length == 1 && fields[0] == GeoJSON.ID_FIELD);
|
|
24713
|
+
}
|
|
24714
|
+
|
|
24585
24715
|
function inferValueType(value) {
|
|
24586
24716
|
if (value === null || value === undefined) return null;
|
|
24587
24717
|
if (value instanceof Date) return 'DATETIME';
|
|
@@ -24600,10 +24730,6 @@ ${svg}
|
|
|
24600
24730
|
}
|
|
24601
24731
|
|
|
24602
24732
|
function normalizeFeature(feature, fields) {
|
|
24603
|
-
fields.reduce(function(memo, field) {
|
|
24604
|
-
memo[field.name] = field.type;
|
|
24605
|
-
return memo;
|
|
24606
|
-
}, {});
|
|
24607
24733
|
var props = {};
|
|
24608
24734
|
fields.forEach(function(field) {
|
|
24609
24735
|
var value = feature.properties && Object.prototype.hasOwnProperty.call(feature.properties, field.name) ?
|
|
@@ -24622,11 +24748,8 @@ ${svg}
|
|
|
24622
24748
|
|
|
24623
24749
|
function getExportSrs(dataset) {
|
|
24624
24750
|
var info = dataset.info || {};
|
|
24625
|
-
var gpkgCrs = normalizeSrsForInsert(info.geopackage_crs);
|
|
24751
|
+
var gpkgCrs = resolveExportSrs(normalizeSrsForInsert(info.geopackage_crs), info.wkt1);
|
|
24626
24752
|
if (gpkgCrs) {
|
|
24627
|
-
if (!gpkgCrs.definition && info.wkt1) {
|
|
24628
|
-
gpkgCrs.definition = info.wkt1;
|
|
24629
|
-
}
|
|
24630
24753
|
return gpkgCrs;
|
|
24631
24754
|
}
|
|
24632
24755
|
var parsed = parseCrsString(info.crs_string);
|
|
@@ -24642,13 +24765,83 @@ ${svg}
|
|
|
24642
24765
|
if (info.wkt1) {
|
|
24643
24766
|
return buildCustomSrsFromWkt(info.wkt1);
|
|
24644
24767
|
}
|
|
24768
|
+
// If the dataset has an in-memory CRS object (e.g. set by -proj) but no
|
|
24769
|
+
// metadata source, derive a WKT1 definition from it so a projected CRS
|
|
24770
|
+
// isn't lost on round-trip.
|
|
24771
|
+
var derivedWkt = getWktFromDatasetCrs(dataset);
|
|
24772
|
+
if (derivedWkt) {
|
|
24773
|
+
return buildCustomSrsFromWkt(derivedWkt);
|
|
24774
|
+
}
|
|
24775
|
+
// Unknown CRS fallback:
|
|
24776
|
+
// - probable decimal-degree coordinates => allow WGS84 assumption
|
|
24777
|
+
// - otherwise use undefined cartesian CRS (null/unknown projection)
|
|
24778
|
+
if (probablyDecimalDegreeBounds(getDatasetBounds(dataset))) {
|
|
24779
|
+
return {
|
|
24780
|
+
srs_id: 4326,
|
|
24781
|
+
organization: 'EPSG',
|
|
24782
|
+
organization_coordsys_id: 4326
|
|
24783
|
+
};
|
|
24784
|
+
}
|
|
24645
24785
|
return {
|
|
24646
|
-
srs_id:
|
|
24647
|
-
|
|
24648
|
-
|
|
24786
|
+
srs_id: -1,
|
|
24787
|
+
srs_name: 'Undefined Cartesian SRS',
|
|
24788
|
+
organization: 'NONE',
|
|
24789
|
+
organization_coordsys_id: -1
|
|
24649
24790
|
};
|
|
24650
24791
|
}
|
|
24651
24792
|
|
|
24793
|
+
function getWktFromDatasetCrs(dataset) {
|
|
24794
|
+
// Only derive from an explicitly-set CRS object (e.g. from -proj).
|
|
24795
|
+
// This avoids building a custom SRS for lat/lon datasets that were
|
|
24796
|
+
// auto-defaulted to WGS84 by getDatasetCRS().
|
|
24797
|
+
var info = dataset && dataset.info;
|
|
24798
|
+
if (!info || !info.crs) return null;
|
|
24799
|
+
try {
|
|
24800
|
+
return crsToPrj(info.crs) || null;
|
|
24801
|
+
} catch (e) {
|
|
24802
|
+
return null;
|
|
24803
|
+
}
|
|
24804
|
+
}
|
|
24805
|
+
|
|
24806
|
+
function resolveExportSrs(srs, fallbackWkt) {
|
|
24807
|
+
if (!srs) return null;
|
|
24808
|
+
var out = Object.assign({}, srs);
|
|
24809
|
+
if (!out.definition && fallbackWkt) {
|
|
24810
|
+
out.definition = fallbackWkt;
|
|
24811
|
+
}
|
|
24812
|
+
if (out.srs_id == null && out.organization_coordsys_id != null) {
|
|
24813
|
+
out.srs_id = out.organization_coordsys_id;
|
|
24814
|
+
}
|
|
24815
|
+
if (out.srs_id == null) {
|
|
24816
|
+
var fromWkt = parseWktAuthority(out.definition);
|
|
24817
|
+
if (fromWkt) {
|
|
24818
|
+
out.srs_id = fromWkt.srs_id;
|
|
24819
|
+
if (!out.organization) out.organization = fromWkt.organization;
|
|
24820
|
+
if (out.organization_coordsys_id == null) {
|
|
24821
|
+
out.organization_coordsys_id = fromWkt.organization_coordsys_id;
|
|
24822
|
+
}
|
|
24823
|
+
}
|
|
24824
|
+
}
|
|
24825
|
+
if (out.srs_id == null && out.definition) {
|
|
24826
|
+
var custom = buildCustomSrsFromWkt(out.definition);
|
|
24827
|
+
out.srs_id = custom.srs_id;
|
|
24828
|
+
if (!out.srs_name) out.srs_name = custom.srs_name;
|
|
24829
|
+
if (!out.organization) out.organization = custom.organization;
|
|
24830
|
+
if (out.organization_coordsys_id == null) {
|
|
24831
|
+
out.organization_coordsys_id = custom.organization_coordsys_id;
|
|
24832
|
+
}
|
|
24833
|
+
if (!out.description) out.description = custom.description;
|
|
24834
|
+
}
|
|
24835
|
+
if (out.srs_id == null) return null;
|
|
24836
|
+
if (out.organization_coordsys_id == null) {
|
|
24837
|
+
out.organization_coordsys_id = out.srs_id;
|
|
24838
|
+
}
|
|
24839
|
+
if (!out.organization) {
|
|
24840
|
+
out.organization = 'NONE';
|
|
24841
|
+
}
|
|
24842
|
+
return out;
|
|
24843
|
+
}
|
|
24844
|
+
|
|
24652
24845
|
function parseCrsString(str) {
|
|
24653
24846
|
if (!str || typeof str != 'string') return null;
|
|
24654
24847
|
var match = str.match(/^([a-z]+):(\d+)$/i);
|
|
@@ -24740,9 +24933,10 @@ ${svg}
|
|
|
24740
24933
|
var geopackage = require$1('@ngageoint/geopackage');
|
|
24741
24934
|
var spatialReferenceSystem = new geopackage.SpatialReferenceSystem();
|
|
24742
24935
|
spatialReferenceSystem.srs_id = srs.srs_id;
|
|
24743
|
-
spatialReferenceSystem.srs_name = srs.srs_name || (srs.organization + ':' + srs.organization_coordsys_id);
|
|
24744
|
-
spatialReferenceSystem.organization = srs.organization;
|
|
24745
|
-
spatialReferenceSystem.organization_coordsys_id = srs.organization_coordsys_id
|
|
24936
|
+
spatialReferenceSystem.srs_name = srs.srs_name || (String(srs.organization || 'NONE') + ':' + srs.organization_coordsys_id);
|
|
24937
|
+
spatialReferenceSystem.organization = srs.organization || 'NONE';
|
|
24938
|
+
spatialReferenceSystem.organization_coordsys_id = srs.organization_coordsys_id != null ?
|
|
24939
|
+
srs.organization_coordsys_id : srs.srs_id;
|
|
24746
24940
|
spatialReferenceSystem.definition = srs.definition;
|
|
24747
24941
|
spatialReferenceSystem.description = srs.description || null;
|
|
24748
24942
|
gpkg.createSpatialReferenceSystem(spatialReferenceSystem);
|
|
@@ -24751,7 +24945,9 @@ ${svg}
|
|
|
24751
24945
|
function getSourceSrsWithoutReprojection(tableSrs, fallbackSrs) {
|
|
24752
24946
|
var target = normalizeSrsForInsert(tableSrs) || normalizeSrsForInsert(fallbackSrs);
|
|
24753
24947
|
return {
|
|
24754
|
-
srs_id
|
|
24948
|
+
// geopackage writer rejects negative srs_id for source metadata;
|
|
24949
|
+
// use 0 (undefined geographic) when target is undefined cartesian (-1).
|
|
24950
|
+
srs_id: target.srs_id < 0 ? 0 : target.srs_id,
|
|
24755
24951
|
organization: 'EPSG',
|
|
24756
24952
|
organization_coordsys_id: 4326
|
|
24757
24953
|
};
|
|
@@ -24828,18 +25024,21 @@ ${svg}
|
|
|
24828
25024
|
if (normalized.organization_coordsys_id == null && normalized.organizationCoordsysId != null) {
|
|
24829
25025
|
normalized.organization_coordsys_id = normalized.organizationCoordsysId;
|
|
24830
25026
|
}
|
|
24831
|
-
if (normalized.srs_id
|
|
24832
|
-
normalized.srs_id = normalized.
|
|
25027
|
+
if (normalized.srs_id != null) {
|
|
25028
|
+
normalized.srs_id = +normalized.srs_id;
|
|
25029
|
+
if (!Number.isFinite(normalized.srs_id)) {
|
|
25030
|
+
normalized.srs_id = null;
|
|
25031
|
+
}
|
|
24833
25032
|
}
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
normalized.organization = 'EPSG';
|
|
25033
|
+
if (normalized.organization) {
|
|
25034
|
+
normalized.organization = String(normalized.organization).toUpperCase();
|
|
24837
25035
|
}
|
|
24838
|
-
normalized.
|
|
24839
|
-
|
|
24840
|
-
normalized.organization_coordsys_id
|
|
25036
|
+
if (normalized.organization_coordsys_id != null) {
|
|
25037
|
+
normalized.organization_coordsys_id = +normalized.organization_coordsys_id;
|
|
25038
|
+
if (!Number.isFinite(normalized.organization_coordsys_id)) {
|
|
25039
|
+
normalized.organization_coordsys_id = null;
|
|
25040
|
+
}
|
|
24841
25041
|
}
|
|
24842
|
-
normalized.organization_coordsys_id = +normalized.organization_coordsys_id || 4326;
|
|
24843
25042
|
return normalized;
|
|
24844
25043
|
}
|
|
24845
25044
|
|
|
@@ -26869,6 +27068,10 @@ ${svg}
|
|
|
26869
27068
|
.option('name', {
|
|
26870
27069
|
describe: 'rename the imported layer(s)'
|
|
26871
27070
|
})
|
|
27071
|
+
.option('layers', {
|
|
27072
|
+
type: 'strings',
|
|
27073
|
+
describe: '[GPKG] comma-sep. list of layers to import'
|
|
27074
|
+
})
|
|
26872
27075
|
.option('geometry-type', {
|
|
26873
27076
|
// undocumented; GeoJSON import rejects all but one kind of geometry
|
|
26874
27077
|
// describe: '[GeoJSON] Import one kind of geometry (point|polygon|polyline)'
|
|
@@ -31463,24 +31666,35 @@ ${svg}
|
|
|
31463
31666
|
var geopackage = require$1('@ngageoint/geopackage');
|
|
31464
31667
|
var gpkg;
|
|
31465
31668
|
var datasets;
|
|
31466
|
-
var source;
|
|
31467
31669
|
var tmpPath = null;
|
|
31468
31670
|
|
|
31469
31671
|
if (!geopackage || !geopackage.GeoPackageAPI) {
|
|
31470
31672
|
stop$1('GeoPackage library is not loaded');
|
|
31471
31673
|
}
|
|
31472
31674
|
|
|
31473
|
-
|
|
31474
|
-
|
|
31475
|
-
|
|
31476
|
-
tmpPath = writeGeoPackageTempFile(content);
|
|
31477
|
-
source = tmpPath;
|
|
31478
|
-
} else {
|
|
31479
|
-
source = new Uint8Array(content);
|
|
31480
|
-
}
|
|
31481
|
-
gpkg = await geopackage.GeoPackageAPI.open(source);
|
|
31675
|
+
({gpkg, tmpPath} = await openGeoPackage(content, geopackage));
|
|
31676
|
+
var availableLayers;
|
|
31677
|
+
var filterApplied;
|
|
31482
31678
|
try {
|
|
31483
|
-
|
|
31679
|
+
try {
|
|
31680
|
+
({datasets, availableLayers, filterApplied} = readFeatureTableDatasets(gpkg, opts));
|
|
31681
|
+
} catch (e) {
|
|
31682
|
+
if (!runningInBrowser() && isLocalCsProjError(e)) {
|
|
31683
|
+
gpkg.close();
|
|
31684
|
+
if (tmpPath) {
|
|
31685
|
+
sanitizeGeoPackageCrsMetadata(tmpPath);
|
|
31686
|
+
} else if (utils.isString(content)) {
|
|
31687
|
+
tmpPath = copyGeoPackageTempFile(content);
|
|
31688
|
+
sanitizeGeoPackageCrsMetadata(tmpPath);
|
|
31689
|
+
} else {
|
|
31690
|
+
throw e;
|
|
31691
|
+
}
|
|
31692
|
+
gpkg = await geopackage.GeoPackageAPI.open(tmpPath);
|
|
31693
|
+
({datasets, availableLayers, filterApplied} = readFeatureTableDatasets(gpkg, opts));
|
|
31694
|
+
} else {
|
|
31695
|
+
throw e;
|
|
31696
|
+
}
|
|
31697
|
+
}
|
|
31484
31698
|
} finally {
|
|
31485
31699
|
gpkg.close();
|
|
31486
31700
|
removeTempGeoPackageFile(tmpPath);
|
|
@@ -31489,13 +31703,72 @@ ${svg}
|
|
|
31489
31703
|
if (datasets.length === 0) {
|
|
31490
31704
|
return {
|
|
31491
31705
|
layers: [{name: '', data: null}],
|
|
31492
|
-
info: {
|
|
31706
|
+
info: {
|
|
31707
|
+
_gpkg_available_layers: availableLayers,
|
|
31708
|
+
_gpkg_placeholder: !!filterApplied
|
|
31709
|
+
}
|
|
31493
31710
|
};
|
|
31494
31711
|
}
|
|
31495
31712
|
|
|
31496
31713
|
await initProjLib(datasets);
|
|
31714
|
+
var merged = mergeGeoPackageDatasets(datasets);
|
|
31715
|
+
var mergedArr = Array.isArray(merged) ? merged : [merged];
|
|
31716
|
+
mergedArr.forEach(function(ds) {
|
|
31717
|
+
ds.info = ds.info || {};
|
|
31718
|
+
ds.info._gpkg_available_layers = availableLayers;
|
|
31719
|
+
});
|
|
31720
|
+
return merged;
|
|
31721
|
+
}
|
|
31497
31722
|
|
|
31498
|
-
|
|
31723
|
+
async function openGeoPackage(content, geopackage) {
|
|
31724
|
+
var source;
|
|
31725
|
+
var tmpPath = null;
|
|
31726
|
+
if (utils.isString(content)) {
|
|
31727
|
+
if (!runningInBrowser()) {
|
|
31728
|
+
try {
|
|
31729
|
+
return {
|
|
31730
|
+
gpkg: await geopackage.GeoPackageAPI.open(content),
|
|
31731
|
+
tmpPath: null
|
|
31732
|
+
};
|
|
31733
|
+
} catch (e) {
|
|
31734
|
+
if (!isLocalCsProjError(e)) throw e;
|
|
31735
|
+
tmpPath = copyGeoPackageTempFile(content);
|
|
31736
|
+
sanitizeGeoPackageCrsMetadata(tmpPath);
|
|
31737
|
+
return {
|
|
31738
|
+
gpkg: await geopackage.GeoPackageAPI.open(tmpPath),
|
|
31739
|
+
tmpPath: tmpPath
|
|
31740
|
+
};
|
|
31741
|
+
}
|
|
31742
|
+
}
|
|
31743
|
+
source = content;
|
|
31744
|
+
} else if (!runningInBrowser()) {
|
|
31745
|
+
tmpPath = writeGeoPackageTempFile(content);
|
|
31746
|
+
try {
|
|
31747
|
+
return {
|
|
31748
|
+
gpkg: await geopackage.GeoPackageAPI.open(tmpPath),
|
|
31749
|
+
tmpPath: tmpPath
|
|
31750
|
+
};
|
|
31751
|
+
} catch (e) {
|
|
31752
|
+
if (!isLocalCsProjError(e)) throw e;
|
|
31753
|
+
sanitizeGeoPackageCrsMetadata(tmpPath);
|
|
31754
|
+
return {
|
|
31755
|
+
gpkg: await geopackage.GeoPackageAPI.open(tmpPath),
|
|
31756
|
+
tmpPath: tmpPath
|
|
31757
|
+
};
|
|
31758
|
+
}
|
|
31759
|
+
} else {
|
|
31760
|
+
source = new Uint8Array(content);
|
|
31761
|
+
}
|
|
31762
|
+
return {
|
|
31763
|
+
gpkg: await geopackage.GeoPackageAPI.open(source),
|
|
31764
|
+
tmpPath: null
|
|
31765
|
+
};
|
|
31766
|
+
}
|
|
31767
|
+
|
|
31768
|
+
function isLocalCsProjError(err) {
|
|
31769
|
+
var msg = err && err.message ? String(err.message) : '';
|
|
31770
|
+
return msg.includes("havn't handled \"_\" in keyword yet") ||
|
|
31771
|
+
msg.includes('LOCAL_CS');
|
|
31499
31772
|
}
|
|
31500
31773
|
|
|
31501
31774
|
function writeGeoPackageTempFile(content) {
|
|
@@ -31504,10 +31777,40 @@ ${svg}
|
|
|
31504
31777
|
var path = require$1('path');
|
|
31505
31778
|
var unique = Date.now() + '-' + process.pid + '-' + Math.random().toString(36).slice(2);
|
|
31506
31779
|
var tmpPath = path.join(os.tmpdir(), 'mapshaper-gpkg-import-' + unique + '.gpkg');
|
|
31507
|
-
|
|
31780
|
+
if (Buffer.isBuffer(content)) {
|
|
31781
|
+
fs.writeFileSync(tmpPath, content);
|
|
31782
|
+
} else if (content instanceof Uint8Array) {
|
|
31783
|
+
fs.writeFileSync(tmpPath, Buffer.from(content.buffer, content.byteOffset, content.byteLength));
|
|
31784
|
+
} else if (content instanceof ArrayBuffer) {
|
|
31785
|
+
fs.writeFileSync(tmpPath, Buffer.from(content));
|
|
31786
|
+
} else {
|
|
31787
|
+
fs.writeFileSync(tmpPath, Buffer.from(new Uint8Array(content)));
|
|
31788
|
+
}
|
|
31789
|
+
return tmpPath;
|
|
31790
|
+
}
|
|
31791
|
+
|
|
31792
|
+
function copyGeoPackageTempFile(filepath) {
|
|
31793
|
+
var fs = require$1('fs');
|
|
31794
|
+
var os = require$1('os');
|
|
31795
|
+
var path = require$1('path');
|
|
31796
|
+
var unique = Date.now() + '-' + process.pid + '-' + Math.random().toString(36).slice(2);
|
|
31797
|
+
var tmpPath = path.join(os.tmpdir(), 'mapshaper-gpkg-import-' + unique + '.gpkg');
|
|
31798
|
+
fs.copyFileSync(filepath, tmpPath);
|
|
31508
31799
|
return tmpPath;
|
|
31509
31800
|
}
|
|
31510
31801
|
|
|
31802
|
+
function sanitizeGeoPackageCrsMetadata(filepath) {
|
|
31803
|
+
var Database = require$1('better-sqlite3');
|
|
31804
|
+
var db = new Database(filepath);
|
|
31805
|
+
try {
|
|
31806
|
+
// GDAL may write LOCAL_CS definitions that proj4 can't parse.
|
|
31807
|
+
// Normalize to 'undefined' so GeoPackageAPI.open() won't throw.
|
|
31808
|
+
db.prepare("UPDATE gpkg_spatial_ref_sys SET definition = 'undefined' WHERE definition LIKE 'LOCAL_CS[%'").run();
|
|
31809
|
+
} finally {
|
|
31810
|
+
db.close();
|
|
31811
|
+
}
|
|
31812
|
+
}
|
|
31813
|
+
|
|
31511
31814
|
function removeTempGeoPackageFile(filepath) {
|
|
31512
31815
|
if (!filepath) return;
|
|
31513
31816
|
var fs = require$1('fs');
|
|
@@ -31526,13 +31829,207 @@ ${svg}
|
|
|
31526
31829
|
}
|
|
31527
31830
|
|
|
31528
31831
|
function readFeatureTableDatasets(gpkg, opts) {
|
|
31529
|
-
var
|
|
31530
|
-
|
|
31832
|
+
var selected = getSelectedGeoPackageLayers(opts);
|
|
31833
|
+
var availableLayers = gpkg.getFeatureTables() || [];
|
|
31834
|
+
var tables = filterGeoPackageTables(availableLayers, selected);
|
|
31835
|
+
var filterApplied = Array.isArray(selected) && selected.length > 0;
|
|
31836
|
+
var datasets = tables.map(function(table) {
|
|
31531
31837
|
return readFeatureTable(gpkg, table, opts);
|
|
31532
31838
|
});
|
|
31839
|
+
return {datasets: datasets, availableLayers: availableLayers, filterApplied: filterApplied};
|
|
31840
|
+
}
|
|
31841
|
+
|
|
31842
|
+
function getSelectedGeoPackageLayers(opts) {
|
|
31843
|
+
if (!opts) return null;
|
|
31844
|
+
return opts.gpkg_layers || opts.layers || null;
|
|
31845
|
+
}
|
|
31846
|
+
|
|
31847
|
+
function filterGeoPackageTables(tables, selected) {
|
|
31848
|
+
if (!Array.isArray(selected) || selected.length === 0) return tables;
|
|
31849
|
+
var index = selected.reduce(function(memo, name) {
|
|
31850
|
+
memo[name] = true;
|
|
31851
|
+
return memo;
|
|
31852
|
+
}, {});
|
|
31853
|
+
return tables.filter(function(name) {
|
|
31854
|
+
return !!index[name];
|
|
31855
|
+
});
|
|
31856
|
+
}
|
|
31857
|
+
|
|
31858
|
+
function mergeGeoPackageDatasets(datasets) {
|
|
31859
|
+
var groups = groupGeoPackageDatasets(datasets);
|
|
31860
|
+
var merged = groups.reduce(function(memo, group) {
|
|
31861
|
+
return memo.concat(mergeGeoPackageDatasetGroup(group));
|
|
31862
|
+
}, []);
|
|
31863
|
+
return merged.length == 1 ? merged[0] : merged;
|
|
31864
|
+
}
|
|
31865
|
+
|
|
31866
|
+
function mergeGeoPackageDatasetGroup(group) {
|
|
31867
|
+
var pathDatasets = [];
|
|
31868
|
+
var pointDatasets = [];
|
|
31869
|
+
var dataDatasets = [];
|
|
31870
|
+
|
|
31871
|
+
group.forEach(function(dataset) {
|
|
31872
|
+
var kind = getDatasetGeometryKind(dataset);
|
|
31873
|
+
if (kind == 'path') {
|
|
31874
|
+
pathDatasets.push(dataset);
|
|
31875
|
+
} else if (kind == 'point') {
|
|
31876
|
+
pointDatasets.push(dataset);
|
|
31877
|
+
} else {
|
|
31878
|
+
dataDatasets.push(dataset);
|
|
31879
|
+
}
|
|
31880
|
+
});
|
|
31881
|
+
|
|
31882
|
+
var output = [];
|
|
31883
|
+
if (dataDatasets.length > 0) {
|
|
31884
|
+
output.push(dataDatasets.length == 1 ? dataDatasets[0] : mergeDatasets(dataDatasets));
|
|
31885
|
+
}
|
|
31886
|
+
if (pointDatasets.length > 0) {
|
|
31887
|
+
output.push(pointDatasets.length == 1 ? pointDatasets[0] : mergeDatasets(pointDatasets));
|
|
31888
|
+
}
|
|
31889
|
+
if (pathDatasets.length > 0) {
|
|
31890
|
+
var groupedPaths = groupPathDatasetsBySharedArcs(pathDatasets);
|
|
31891
|
+
if (groupedPaths.mergedDataset) {
|
|
31892
|
+
output.push(groupedPaths.mergedDataset);
|
|
31893
|
+
} else {
|
|
31894
|
+
groupedPaths.components.forEach(function(component) {
|
|
31895
|
+
output.push(component.length == 1 ? component[0] : mergeDatasets(component));
|
|
31896
|
+
});
|
|
31897
|
+
}
|
|
31898
|
+
}
|
|
31899
|
+
return output;
|
|
31900
|
+
}
|
|
31901
|
+
|
|
31902
|
+
function groupGeoPackageDatasets(datasets) {
|
|
31903
|
+
var index = {};
|
|
31904
|
+
datasets.forEach(function(dataset) {
|
|
31905
|
+
var key = getGeoPackageDatasetGroupKey(dataset);
|
|
31906
|
+
if (!index[key]) index[key] = [];
|
|
31907
|
+
index[key].push(dataset);
|
|
31908
|
+
});
|
|
31909
|
+
return Object.keys(index).map(function(key) {
|
|
31910
|
+
return index[key];
|
|
31911
|
+
});
|
|
31912
|
+
}
|
|
31913
|
+
|
|
31914
|
+
function getGeoPackageDatasetGroupKey(dataset) {
|
|
31915
|
+
var info = dataset.info || {};
|
|
31916
|
+
var crs = info.geopackage_crs || null;
|
|
31917
|
+
if (isDataOnlyDataset(dataset)) {
|
|
31918
|
+
return 'data-only';
|
|
31919
|
+
}
|
|
31920
|
+
if (crs) {
|
|
31921
|
+
var org = normalizeCrsOrg(crs.organization);
|
|
31922
|
+
var code = normalizeNumericCode(crs.organization_coordsys_id);
|
|
31923
|
+
if (isTrustedCrsAuthority(org) && code !== null && !(org == 'NONE' && code <= 0)) {
|
|
31924
|
+
return 'crs:' + org + ':' + code;
|
|
31925
|
+
}
|
|
31926
|
+
if (isUsableWkt1Definition(crs.definition)) {
|
|
31927
|
+
return 'wkt:' + crs.definition;
|
|
31928
|
+
}
|
|
31929
|
+
}
|
|
31930
|
+
return probablyDecimalDegreeBounds(getDatasetBounds(dataset)) ?
|
|
31931
|
+
'unknown:unprojected' :
|
|
31932
|
+
'unknown:projected';
|
|
31933
|
+
}
|
|
31934
|
+
|
|
31935
|
+
function isDataOnlyDataset(dataset) {
|
|
31936
|
+
return (dataset.layers || []).every(function(lyr) {
|
|
31937
|
+
return !lyr.geometry_type;
|
|
31938
|
+
});
|
|
31939
|
+
}
|
|
31940
|
+
|
|
31941
|
+
function getDatasetGeometryKind(dataset) {
|
|
31942
|
+
if (isDataOnlyDataset(dataset)) return 'data';
|
|
31943
|
+
if (datasetHasPaths(dataset)) return 'path';
|
|
31944
|
+
var hasPoints = (dataset.layers || []).some(function(lyr) {
|
|
31945
|
+
return layerHasPoints(lyr);
|
|
31946
|
+
});
|
|
31947
|
+
return hasPoints ? 'point' : 'data';
|
|
31948
|
+
}
|
|
31949
|
+
|
|
31950
|
+
function groupPathDatasetsBySharedArcs(datasets) {
|
|
31951
|
+
if (datasets.length < 2) {
|
|
31952
|
+
return {
|
|
31953
|
+
mergedDataset: datasets[0] || null,
|
|
31954
|
+
components: []
|
|
31955
|
+
};
|
|
31956
|
+
}
|
|
31957
|
+
var copy = datasets.map(copyDatasetForExport);
|
|
31958
|
+
var merged = mergeDatasets(copy);
|
|
31959
|
+
if (!merged.arcs || merged.arcs.size() === 0) {
|
|
31960
|
+
return {
|
|
31961
|
+
mergedDataset: null,
|
|
31962
|
+
components: datasets.map(function(dataset) { return [dataset]; })
|
|
31963
|
+
};
|
|
31964
|
+
}
|
|
31965
|
+
buildTopology(merged);
|
|
31966
|
+
var parent = datasets.map(function(_, i) { return i; });
|
|
31967
|
+
var arcOwner = new Map();
|
|
31968
|
+
merged.layers.forEach(function(layer, layerIdx) {
|
|
31969
|
+
var seen = new Set();
|
|
31970
|
+
forEachArcId(layer.shapes || [], function(arcId) {
|
|
31971
|
+
seen.add(arcId < 0 ? ~arcId : arcId);
|
|
31972
|
+
});
|
|
31973
|
+
seen.forEach(function(absId) {
|
|
31974
|
+
if (!arcOwner.has(absId)) {
|
|
31975
|
+
arcOwner.set(absId, layerIdx);
|
|
31976
|
+
} else {
|
|
31977
|
+
union(parent, layerIdx, arcOwner.get(absId));
|
|
31978
|
+
}
|
|
31979
|
+
});
|
|
31980
|
+
});
|
|
31981
|
+
var components = {};
|
|
31982
|
+
datasets.forEach(function(dataset, i) {
|
|
31983
|
+
var root = find(parent, i);
|
|
31984
|
+
if (!components[root]) components[root] = [];
|
|
31985
|
+
components[root].push(dataset);
|
|
31986
|
+
});
|
|
31987
|
+
var grouped = Object.keys(components).map(function(key) {
|
|
31988
|
+
return components[key];
|
|
31989
|
+
});
|
|
31990
|
+
if (grouped.length == 1) {
|
|
31991
|
+
return {
|
|
31992
|
+
mergedDataset: merged,
|
|
31993
|
+
components: []
|
|
31994
|
+
};
|
|
31995
|
+
}
|
|
31996
|
+
return {
|
|
31997
|
+
mergedDataset: null,
|
|
31998
|
+
components: grouped
|
|
31999
|
+
};
|
|
32000
|
+
}
|
|
32001
|
+
|
|
32002
|
+
function find(parent, i) {
|
|
32003
|
+
var p = parent[i];
|
|
32004
|
+
if (p !== i) {
|
|
32005
|
+
parent[i] = find(parent, p);
|
|
32006
|
+
}
|
|
32007
|
+
return parent[i];
|
|
31533
32008
|
}
|
|
31534
32009
|
|
|
31535
|
-
function
|
|
32010
|
+
function union(parent, a, b) {
|
|
32011
|
+
var ra = find(parent, a);
|
|
32012
|
+
var rb = find(parent, b);
|
|
32013
|
+
if (ra !== rb) {
|
|
32014
|
+
parent[rb] = ra;
|
|
32015
|
+
}
|
|
32016
|
+
}
|
|
32017
|
+
|
|
32018
|
+
function normalizeNumericCode(val) {
|
|
32019
|
+
var n = +val;
|
|
32020
|
+
return Number.isFinite(n) ? n : null;
|
|
32021
|
+
}
|
|
32022
|
+
|
|
32023
|
+
function normalizeCrsOrg(org) {
|
|
32024
|
+
if (!org || org == 'undefined') return null;
|
|
32025
|
+
return String(org).toUpperCase();
|
|
32026
|
+
}
|
|
32027
|
+
|
|
32028
|
+
function isTrustedCrsAuthority(org) {
|
|
32029
|
+
return org == 'EPSG' || org == 'ESRI' || org == 'NONE';
|
|
32030
|
+
}
|
|
32031
|
+
|
|
32032
|
+
function convertOrgToProjString(crs) {
|
|
31536
32033
|
var org = crs.organization.toLowerCase();
|
|
31537
32034
|
if (org == 'epsg' || org == 'esri') {
|
|
31538
32035
|
return org + ':' + crs.organization_coordsys_id;
|
|
@@ -31560,14 +32057,25 @@ ${svg}
|
|
|
31560
32057
|
});
|
|
31561
32058
|
dataset.info = dataset.info || {};
|
|
31562
32059
|
dataset.info.geopackage_crs = crs;
|
|
31563
|
-
if (crs?.definition
|
|
32060
|
+
if (isUsableWkt1Definition(crs?.definition)) {
|
|
31564
32061
|
dataset.info.wkt1 = crs.definition;
|
|
31565
32062
|
} else if (crs?.organization && crs.organization !== 'undefined') {
|
|
31566
|
-
|
|
32063
|
+
var crsString = convertOrgToProjString(crs);
|
|
32064
|
+
if (crsString) {
|
|
32065
|
+
dataset.info.crs_string = crsString;
|
|
32066
|
+
}
|
|
31567
32067
|
}
|
|
31568
32068
|
return dataset;
|
|
31569
32069
|
}
|
|
31570
32070
|
|
|
32071
|
+
function isUsableWkt1Definition(defn) {
|
|
32072
|
+
if (!defn || defn === 'undefined') return false;
|
|
32073
|
+
// GDAL may emit LOCAL_CS["Undefined SRS", ...] for null CRS;
|
|
32074
|
+
// this is not a usable projected/geographic CRS for mapshaper.
|
|
32075
|
+
if (/^\s*LOCAL_CS\[/i.test(defn)) return false;
|
|
32076
|
+
return true;
|
|
32077
|
+
}
|
|
32078
|
+
|
|
31571
32079
|
function convertFeatureRow(featureRow) {
|
|
31572
32080
|
var feature = {
|
|
31573
32081
|
type: 'Feature',
|
|
@@ -31583,8 +32091,7 @@ ${svg}
|
|
|
31583
32091
|
// skip feature if geometry can't be parsed
|
|
31584
32092
|
return null;
|
|
31585
32093
|
}
|
|
31586
|
-
|
|
31587
|
-
var geomColName = featureRow.geometryColumn.name;
|
|
32094
|
+
var geomColName = featureRow.geometryColumn && featureRow.geometryColumn.name;
|
|
31588
32095
|
for (var key in featureRow.values) {
|
|
31589
32096
|
if (Object.prototype.hasOwnProperty.call(featureRow.values, key) &&
|
|
31590
32097
|
key !== geomColName) {
|
|
@@ -32363,6 +32870,11 @@ ${svg}
|
|
|
32363
32870
|
} else {
|
|
32364
32871
|
return importContent(obj, opts);
|
|
32365
32872
|
}
|
|
32873
|
+
if (Array.isArray(dataset)) {
|
|
32874
|
+
return dataset.map(function(ds) {
|
|
32875
|
+
return finalizeImportedDataset(ds, dataFmt, data, opts);
|
|
32876
|
+
});
|
|
32877
|
+
}
|
|
32366
32878
|
return finalizeImportedDataset(dataset, dataFmt, data, opts);
|
|
32367
32879
|
}
|
|
32368
32880
|
|
|
@@ -32564,12 +33076,18 @@ ${svg}
|
|
|
32564
33076
|
|
|
32565
33077
|
cmd.importFiles = async function(catalog, opts) {
|
|
32566
33078
|
var files = opts.files || [];
|
|
32567
|
-
var dataset;
|
|
33079
|
+
var dataset, datasets, target;
|
|
32568
33080
|
|
|
32569
33081
|
if (opts.stdin) {
|
|
32570
33082
|
dataset = await importFileAsync('/dev/stdin', opts);
|
|
32571
|
-
|
|
32572
|
-
|
|
33083
|
+
datasets = normalizeImportedDatasets(dataset);
|
|
33084
|
+
catalog.addDatasets(datasets);
|
|
33085
|
+
if (datasets.length > 1) {
|
|
33086
|
+
catalog.setDefaultTargets(datasets.map(function(ds) {
|
|
33087
|
+
return {dataset: ds, layers: ds.layers};
|
|
33088
|
+
}));
|
|
33089
|
+
}
|
|
33090
|
+
return normalizeImportedTarget(datasets);
|
|
32573
33091
|
}
|
|
32574
33092
|
|
|
32575
33093
|
if (files.length > 0 === false) {
|
|
@@ -32604,14 +33122,22 @@ ${svg}
|
|
|
32604
33122
|
} else {
|
|
32605
33123
|
dataset = await importFilesTogetherAsync(files, opts);
|
|
32606
33124
|
}
|
|
33125
|
+
datasets = normalizeImportedDatasets(dataset);
|
|
33126
|
+
datasets = validateAndCleanGpkgSelection(datasets, opts);
|
|
32607
33127
|
|
|
32608
33128
|
if (opts.merge_files && files.length > 1) {
|
|
32609
33129
|
// TODO: deprecate and remove this option (use -merge-layers cmd instead)
|
|
32610
|
-
|
|
33130
|
+
datasets[0].layers = cmd.mergeLayers(datasets[0].layers);
|
|
32611
33131
|
}
|
|
32612
33132
|
|
|
32613
|
-
catalog.
|
|
32614
|
-
|
|
33133
|
+
catalog.addDatasets(datasets);
|
|
33134
|
+
if (datasets.length > 1) {
|
|
33135
|
+
catalog.setDefaultTargets(datasets.map(function(ds) {
|
|
33136
|
+
return {dataset: ds, layers: ds.layers};
|
|
33137
|
+
}));
|
|
33138
|
+
}
|
|
33139
|
+
target = normalizeImportedTarget(datasets);
|
|
33140
|
+
return target;
|
|
32615
33141
|
};
|
|
32616
33142
|
|
|
32617
33143
|
// replace any JSON data objects with filenames and cache the data
|
|
@@ -32712,7 +33238,8 @@ ${svg}
|
|
|
32712
33238
|
|
|
32713
33239
|
cli.checkFileExists(path, cache);
|
|
32714
33240
|
|
|
32715
|
-
if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf'
|
|
33241
|
+
if ((fileType == 'shp' || fileType == 'json' || fileType == 'text' || fileType == 'dbf' ||
|
|
33242
|
+
fileType == 'gpkg') && !cached) {
|
|
32716
33243
|
// these file types are read incrementally
|
|
32717
33244
|
content = null;
|
|
32718
33245
|
|
|
@@ -32815,17 +33342,20 @@ ${svg}
|
|
|
32815
33342
|
// Import multiple files to a single dataset
|
|
32816
33343
|
function importFilesTogether(files, opts) {
|
|
32817
33344
|
var unbuiltTopology = false;
|
|
32818
|
-
var datasets = files.
|
|
33345
|
+
var datasets = files.reduce(function(memo, fname) {
|
|
32819
33346
|
// import without topology or snapping
|
|
32820
33347
|
var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
|
|
32821
|
-
var
|
|
33348
|
+
var imported = normalizeImportedDatasets(importFile(fname, importOpts));
|
|
32822
33349
|
// check if dataset contains non-topological paths
|
|
32823
33350
|
// TODO: may also need to rebuild topology if multiple topojson files are merged
|
|
32824
|
-
|
|
32825
|
-
|
|
32826
|
-
|
|
32827
|
-
|
|
32828
|
-
|
|
33351
|
+
imported.forEach(function(dataset) {
|
|
33352
|
+
if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
|
|
33353
|
+
unbuiltTopology = true;
|
|
33354
|
+
}
|
|
33355
|
+
memo.push(dataset);
|
|
33356
|
+
});
|
|
33357
|
+
return memo;
|
|
33358
|
+
}, []);
|
|
32829
33359
|
var combined = mergeDatasets(datasets);
|
|
32830
33360
|
// Build topology, if needed
|
|
32831
33361
|
// TODO: consider updating topology of TopoJSON files instead of concatenating arcs
|
|
@@ -32843,12 +33373,15 @@ ${svg}
|
|
|
32843
33373
|
for (var fname of files) {
|
|
32844
33374
|
// import without topology or snapping
|
|
32845
33375
|
var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
|
|
32846
|
-
var
|
|
32847
|
-
|
|
32848
|
-
|
|
32849
|
-
|
|
32850
|
-
|
|
33376
|
+
var imported = normalizeImportedDatasets(await importFileAsync(fname, importOpts));
|
|
33377
|
+
imported.forEach(function(dataset) {
|
|
33378
|
+
if (dataset.arcs && dataset.arcs.size() > 0 && dataset.info.input_formats[0] != 'topojson') {
|
|
33379
|
+
unbuiltTopology = true;
|
|
33380
|
+
}
|
|
33381
|
+
datasets.push(dataset);
|
|
33382
|
+
});
|
|
32851
33383
|
}
|
|
33384
|
+
datasets = validateAndCleanGpkgSelection(datasets, opts);
|
|
32852
33385
|
var combined = mergeDatasets(datasets);
|
|
32853
33386
|
if (unbuiltTopology && !opts.no_topology) {
|
|
32854
33387
|
cleanPathsAfterImport(combined, opts);
|
|
@@ -32857,6 +33390,60 @@ ${svg}
|
|
|
32857
33390
|
return combined;
|
|
32858
33391
|
}
|
|
32859
33392
|
|
|
33393
|
+
// Validate the GeoPackage layers= selection across all imported datasets,
|
|
33394
|
+
// remove any placeholder datasets produced by filter misses, and strip the
|
|
33395
|
+
// bookkeeping metadata attached by the GeoPackage importer.
|
|
33396
|
+
function validateAndCleanGpkgSelection(datasets, opts) {
|
|
33397
|
+
var availableSet = new Set();
|
|
33398
|
+
var importedSet = new Set();
|
|
33399
|
+
var sawGpkg = false;
|
|
33400
|
+
datasets.forEach(function(ds) {
|
|
33401
|
+
var info = ds && ds.info;
|
|
33402
|
+
if (!info || !Array.isArray(info._gpkg_available_layers)) return;
|
|
33403
|
+
sawGpkg = true;
|
|
33404
|
+
info._gpkg_available_layers.forEach(function(name) { availableSet.add(name); });
|
|
33405
|
+
if (!info._gpkg_placeholder) {
|
|
33406
|
+
(ds.layers || []).forEach(function(lyr) {
|
|
33407
|
+
if (lyr && lyr.name) importedSet.add(lyr.name);
|
|
33408
|
+
});
|
|
33409
|
+
}
|
|
33410
|
+
});
|
|
33411
|
+
if (sawGpkg && Array.isArray(opts.layers) && opts.layers.length > 0) {
|
|
33412
|
+
var missing = opts.layers.filter(function(name) {
|
|
33413
|
+
return !importedSet.has(name);
|
|
33414
|
+
});
|
|
33415
|
+
if (missing.length > 0) {
|
|
33416
|
+
stop$1(
|
|
33417
|
+
'Missing GeoPackage layer(s): ' + missing.join(', ') + '\n' +
|
|
33418
|
+
'Existing layers: ' + Array.from(availableSet).join(' ')
|
|
33419
|
+
);
|
|
33420
|
+
}
|
|
33421
|
+
}
|
|
33422
|
+
var cleaned = datasets.filter(function(ds) {
|
|
33423
|
+
return !(ds && ds.info && ds.info._gpkg_placeholder);
|
|
33424
|
+
});
|
|
33425
|
+
cleaned.forEach(function(ds) {
|
|
33426
|
+
if (ds && ds.info) {
|
|
33427
|
+
delete ds.info._gpkg_available_layers;
|
|
33428
|
+
delete ds.info._gpkg_placeholder;
|
|
33429
|
+
}
|
|
33430
|
+
});
|
|
33431
|
+
return cleaned;
|
|
33432
|
+
}
|
|
33433
|
+
|
|
33434
|
+
function normalizeImportedDatasets(datasetOrArray) {
|
|
33435
|
+
return Array.isArray(datasetOrArray) ? datasetOrArray : [datasetOrArray];
|
|
33436
|
+
}
|
|
33437
|
+
|
|
33438
|
+
function normalizeImportedTarget(datasets) {
|
|
33439
|
+
if (datasets.length == 1) return datasets[0];
|
|
33440
|
+
return {
|
|
33441
|
+
layers: datasets.reduce(function(memo, dataset) {
|
|
33442
|
+
return memo.concat(dataset.layers);
|
|
33443
|
+
}, [])
|
|
33444
|
+
};
|
|
33445
|
+
}
|
|
33446
|
+
|
|
32860
33447
|
function getUnsupportedFileMessage(path) {
|
|
32861
33448
|
var ext = getFileExtension(path);
|
|
32862
33449
|
var msg = 'Unable to import ' + path;
|
|
@@ -50192,7 +50779,7 @@ ${svg}
|
|
|
50192
50779
|
});
|
|
50193
50780
|
}
|
|
50194
50781
|
|
|
50195
|
-
var version = "0.6.
|
|
50782
|
+
var version = "0.6.118";
|
|
50196
50783
|
|
|
50197
50784
|
// Parse command line args into commands and run them
|
|
50198
50785
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|