mapshaper 0.5.110 → 0.5.111
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/CHANGELOG.md +5 -0
- package/mapshaper.js +243 -188
- package/package.json +1 -1
- package/www/index.html +3 -0
- package/www/mapshaper-gui.js +63 -6
- package/www/mapshaper.js +243 -188
- package/www/page.css +26 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
v0.5.111
|
|
2
|
+
* Added -snap endpoints option, for snapping together line endpoints that don't quite meet.
|
|
3
|
+
* Added buttons to the basemaps menu.
|
|
4
|
+
* -if/-elif commands work (with limited functionality) with zero or multiple target layers.
|
|
5
|
+
|
|
1
6
|
v0.5.110
|
|
2
7
|
* Preliminary support for importing .kml files
|
|
3
8
|
* Support for .kmz files in the browser UI
|
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.111";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -2725,21 +2725,30 @@
|
|
|
2725
2725
|
message(utils.format("Snapped %s point%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
2726
2726
|
}
|
|
2727
2727
|
|
|
2728
|
+
function snapCoordsByInterval(arcs, snapDist) {
|
|
2729
|
+
if (snapDist > 0 === false) return 0;
|
|
2730
|
+
var ids = getCoordinateIds(arcs);
|
|
2731
|
+
return snapCoordsInternal(ids, arcs, snapDist);
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
function snapEndpointsByInterval(arcs, snapDist) {
|
|
2735
|
+
if (snapDist > 0 === false) return 0;
|
|
2736
|
+
var ids = getEndpointIds(arcs);
|
|
2737
|
+
return snapCoordsInternal(ids, arcs, snapDist);
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2728
2740
|
// Snap together points within a small threshold
|
|
2729
2741
|
//
|
|
2730
|
-
function
|
|
2742
|
+
function snapCoordsInternal(ids, arcs, snapDist) {
|
|
2731
2743
|
var snapCount = 0,
|
|
2732
|
-
|
|
2733
|
-
|
|
2744
|
+
n = ids.length,
|
|
2745
|
+
data = arcs.getVertexData();
|
|
2734
2746
|
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
for (var i=0, n=ids.length; i<n; i++) {
|
|
2741
|
-
snapCount += snapPoint(i, snapDist, ids, data.xx, data.yy);
|
|
2742
|
-
}
|
|
2747
|
+
quicksortIds(data.xx, ids, 0, n-1);
|
|
2748
|
+
|
|
2749
|
+
// Consider: speed up sorting -- try bucket sort as first pass.
|
|
2750
|
+
for (var i=0; i<n; i++) {
|
|
2751
|
+
snapCount += snapPoint(i, snapDist, ids, data.xx, data.yy);
|
|
2743
2752
|
}
|
|
2744
2753
|
return snapCount;
|
|
2745
2754
|
|
|
@@ -2765,13 +2774,25 @@
|
|
|
2765
2774
|
}
|
|
2766
2775
|
}
|
|
2767
2776
|
|
|
2768
|
-
function
|
|
2769
|
-
var
|
|
2777
|
+
function getCoordinateIds(arcs) {
|
|
2778
|
+
var data = arcs.getVertexData(),
|
|
2779
|
+
n = data.xx.length,
|
|
2770
2780
|
ids = new Uint32Array(n);
|
|
2771
2781
|
for (var i=0; i<n; i++) {
|
|
2772
2782
|
ids[i] = i;
|
|
2773
2783
|
}
|
|
2774
|
-
|
|
2784
|
+
return ids;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
function getEndpointIds(arcs) {
|
|
2788
|
+
var i = 0;
|
|
2789
|
+
var ids = [];
|
|
2790
|
+
var data = arcs.getVertexData();
|
|
2791
|
+
data.nn.forEach(function(n) {
|
|
2792
|
+
if (n > 0 === false) return;
|
|
2793
|
+
ids.push(i, i+n-1);
|
|
2794
|
+
i += n;
|
|
2795
|
+
});
|
|
2775
2796
|
return ids;
|
|
2776
2797
|
}
|
|
2777
2798
|
|
|
@@ -2871,7 +2892,9 @@
|
|
|
2871
2892
|
getHighPrecisionSnapInterval: getHighPrecisionSnapInterval,
|
|
2872
2893
|
snapCoords: snapCoords,
|
|
2873
2894
|
snapCoordsByInterval: snapCoordsByInterval,
|
|
2874
|
-
|
|
2895
|
+
snapEndpointsByInterval: snapEndpointsByInterval,
|
|
2896
|
+
getCoordinateIds: getCoordinateIds,
|
|
2897
|
+
getEndpointIds: getEndpointIds
|
|
2875
2898
|
});
|
|
2876
2899
|
|
|
2877
2900
|
// Find the intersection between two 2D segments
|
|
@@ -9500,6 +9523,140 @@
|
|
|
9500
9523
|
};
|
|
9501
9524
|
}
|
|
9502
9525
|
|
|
9526
|
+
// convert targets from [{layers: [...], dataset: <>}, ...] format to
|
|
9527
|
+
// [{layer: <>, dataset: <>}, ...] format
|
|
9528
|
+
function expandCommandTargets(targets) {
|
|
9529
|
+
return targets.reduce(function(memo, target) {
|
|
9530
|
+
target.layers.forEach(function(lyr) {
|
|
9531
|
+
memo.push({layer: lyr, dataset: target.dataset});
|
|
9532
|
+
});
|
|
9533
|
+
return memo;
|
|
9534
|
+
}, []);
|
|
9535
|
+
}
|
|
9536
|
+
|
|
9537
|
+
|
|
9538
|
+
function findCommandTargets(layers, pattern, type) {
|
|
9539
|
+
var targets = [];
|
|
9540
|
+
var matches = findMatchingLayers(layers, pattern, true);
|
|
9541
|
+
if (type) {
|
|
9542
|
+
matches = matches.filter(function(o) {return o.layer.geometry_type == type;});
|
|
9543
|
+
}
|
|
9544
|
+
// assign target_id to matched layers
|
|
9545
|
+
// (kludge so layers can be sorted in the order that they match; used by -o command)
|
|
9546
|
+
layers.forEach(function(o) {o.layer.target_id = -1;});
|
|
9547
|
+
matches.forEach(function(o, i) {o.layer.target_id = i;});
|
|
9548
|
+
return groupLayersByDataset(matches);
|
|
9549
|
+
}
|
|
9550
|
+
|
|
9551
|
+
// arr: array of {layer: <>, dataset: <>} objects
|
|
9552
|
+
function groupLayersByDataset(arr) {
|
|
9553
|
+
var datasets = [];
|
|
9554
|
+
var targets = [];
|
|
9555
|
+
arr.forEach(function(o) {
|
|
9556
|
+
var i = datasets.indexOf(o.dataset);
|
|
9557
|
+
if (i == -1) {
|
|
9558
|
+
datasets.push(o.dataset);
|
|
9559
|
+
targets.push({layers: [o.layer], dataset: o.dataset});
|
|
9560
|
+
} else {
|
|
9561
|
+
targets[i].layers.push(o.layer);
|
|
9562
|
+
}
|
|
9563
|
+
});
|
|
9564
|
+
return targets;
|
|
9565
|
+
}
|
|
9566
|
+
|
|
9567
|
+
// layers: array of {layer: <>, dataset: <>} objects
|
|
9568
|
+
// pattern: is a layer identifier or a comma-sep. list of identifiers.
|
|
9569
|
+
// An identifier is a literal name, a pattern containing "*" wildcard or
|
|
9570
|
+
// a 1-based index (1..n)
|
|
9571
|
+
function findMatchingLayers(layers, pattern, throws) {
|
|
9572
|
+
var matchedLayers = [];
|
|
9573
|
+
var unmatchedIds = [];
|
|
9574
|
+
var index = {};
|
|
9575
|
+
pattern.split(',').forEach(function(subpattern, i) {
|
|
9576
|
+
var test = getLayerMatch(subpattern);
|
|
9577
|
+
var matched = false;
|
|
9578
|
+
layers.forEach(function(o, layerId) {
|
|
9579
|
+
// if (matchedLayers.indexOf(lyr) > -1) return; // performance bottleneck with 1000s of layers
|
|
9580
|
+
if (layerId in index) {
|
|
9581
|
+
matched = true;
|
|
9582
|
+
} else if (test(o.layer, layerId + 1)) { // layers are 1-indexed
|
|
9583
|
+
matchedLayers.push(o);
|
|
9584
|
+
index[layerId] = true;
|
|
9585
|
+
matched = true;
|
|
9586
|
+
}
|
|
9587
|
+
});
|
|
9588
|
+
if (matched == false) {
|
|
9589
|
+
unmatchedIds.push(subpattern);
|
|
9590
|
+
}
|
|
9591
|
+
});
|
|
9592
|
+
if (throws && unmatchedIds.length) {
|
|
9593
|
+
stop(utils.format('Missing layer%s: %s', unmatchedIds.length == 1 ? '' : 's', unmatchedIds.join(',')));
|
|
9594
|
+
}
|
|
9595
|
+
return matchedLayers;
|
|
9596
|
+
}
|
|
9597
|
+
|
|
9598
|
+
function getLayerMatch(pattern) {
|
|
9599
|
+
var isIndex = utils.isInteger(Number(pattern));
|
|
9600
|
+
var nameRxp = isIndex ? null : utils.wildcardToRegExp(pattern);
|
|
9601
|
+
return function(lyr, i) {
|
|
9602
|
+
return isIndex ? String(i) == pattern : nameRxp.test(lyr.name || '');
|
|
9603
|
+
};
|
|
9604
|
+
}
|
|
9605
|
+
|
|
9606
|
+
function countTargetLayers(targets) {
|
|
9607
|
+
return targets.reduce(function(memo, target) {
|
|
9608
|
+
return memo + target.layers.length;
|
|
9609
|
+
}, 0);
|
|
9610
|
+
}
|
|
9611
|
+
|
|
9612
|
+
// get an identifier for a layer that can be used in a target= option
|
|
9613
|
+
// (returns name if layer has a unique name, or a numerical id)
|
|
9614
|
+
function getLayerTargetId(catalog, lyr) {
|
|
9615
|
+
var nameCount = 0,
|
|
9616
|
+
name = lyr.name,
|
|
9617
|
+
id;
|
|
9618
|
+
catalog.getLayers().forEach(function(o, i) {
|
|
9619
|
+
if (lyr.name && o.layer.name == lyr.name) nameCount++;
|
|
9620
|
+
if (lyr == o.layer) id = String(i + 1);
|
|
9621
|
+
});
|
|
9622
|
+
if (!id) error('Layer not found');
|
|
9623
|
+
return nameCount == 1 ? lyr.name : id;
|
|
9624
|
+
}
|
|
9625
|
+
|
|
9626
|
+
var TargetUtils = /*#__PURE__*/Object.freeze({
|
|
9627
|
+
__proto__: null,
|
|
9628
|
+
expandCommandTargets: expandCommandTargets,
|
|
9629
|
+
findCommandTargets: findCommandTargets,
|
|
9630
|
+
groupLayersByDataset: groupLayersByDataset,
|
|
9631
|
+
findMatchingLayers: findMatchingLayers,
|
|
9632
|
+
getLayerMatch: getLayerMatch,
|
|
9633
|
+
countTargetLayers: countTargetLayers,
|
|
9634
|
+
getLayerTargetId: getLayerTargetId
|
|
9635
|
+
});
|
|
9636
|
+
|
|
9637
|
+
function getNullLayerProxy(targets) {
|
|
9638
|
+
var obj = {};
|
|
9639
|
+
var n = countTargetLayers(targets);
|
|
9640
|
+
var getters = {
|
|
9641
|
+
name: error,
|
|
9642
|
+
data: error,
|
|
9643
|
+
type: error,
|
|
9644
|
+
size: error,
|
|
9645
|
+
empty: error,
|
|
9646
|
+
bbox: error
|
|
9647
|
+
};
|
|
9648
|
+
addGetters(obj, getters);
|
|
9649
|
+
obj.field_exists = error;
|
|
9650
|
+
obj.field_type = error;
|
|
9651
|
+
obj.field_includes = error;
|
|
9652
|
+
return obj;
|
|
9653
|
+
function error() {
|
|
9654
|
+
throw Error(`This expression requires a single target layer; Received ${n} layers.`);
|
|
9655
|
+
}
|
|
9656
|
+
}
|
|
9657
|
+
|
|
9658
|
+
|
|
9659
|
+
|
|
9503
9660
|
// Returns an object representing a layer in a JS expression
|
|
9504
9661
|
function getLayerProxy(lyr, arcs) {
|
|
9505
9662
|
var obj = {};
|
|
@@ -9509,10 +9666,10 @@
|
|
|
9509
9666
|
data: records,
|
|
9510
9667
|
type: lyr.geometry_type,
|
|
9511
9668
|
size: getFeatureCount(lyr),
|
|
9512
|
-
empty: getFeatureCount(lyr) === 0
|
|
9669
|
+
empty: getFeatureCount(lyr) === 0,
|
|
9670
|
+
bbox: getBBoxGetter(obj, lyr, arcs)
|
|
9513
9671
|
};
|
|
9514
9672
|
addGetters(obj, getters);
|
|
9515
|
-
addBBoxGetter(obj, lyr, arcs);
|
|
9516
9673
|
obj.field_exists = function(name) {
|
|
9517
9674
|
return lyr.data && lyr.data.fieldExists(name) ? true : false;
|
|
9518
9675
|
};
|
|
@@ -9541,16 +9698,14 @@
|
|
|
9541
9698
|
return ctx;
|
|
9542
9699
|
}
|
|
9543
9700
|
|
|
9544
|
-
function
|
|
9701
|
+
function getBBoxGetter(obj, lyr, arcs) {
|
|
9545
9702
|
var bbox;
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
bbox = getBBox$1(lyr, arcs);
|
|
9550
|
-
}
|
|
9551
|
-
return bbox;
|
|
9703
|
+
return function() {
|
|
9704
|
+
if (!bbox) {
|
|
9705
|
+
bbox = getBBox$1(lyr, arcs);
|
|
9552
9706
|
}
|
|
9553
|
-
|
|
9707
|
+
return bbox;
|
|
9708
|
+
};
|
|
9554
9709
|
}
|
|
9555
9710
|
|
|
9556
9711
|
function getBBox$1(lyr, arcs) {
|
|
@@ -17169,116 +17324,6 @@ ${svg}
|
|
|
17169
17324
|
formatVersionedFileName: formatVersionedFileName
|
|
17170
17325
|
});
|
|
17171
17326
|
|
|
17172
|
-
// convert targets from [{layers: [...], dataset: <>}, ...] format to
|
|
17173
|
-
// [{layer: <>, dataset: <>}, ...] format
|
|
17174
|
-
function expandCommandTargets(targets) {
|
|
17175
|
-
return targets.reduce(function(memo, target) {
|
|
17176
|
-
target.layers.forEach(function(lyr) {
|
|
17177
|
-
memo.push({layer: lyr, dataset: target.dataset});
|
|
17178
|
-
});
|
|
17179
|
-
return memo;
|
|
17180
|
-
}, []);
|
|
17181
|
-
}
|
|
17182
|
-
|
|
17183
|
-
function findCommandTargets(layers, pattern, type) {
|
|
17184
|
-
var targets = [];
|
|
17185
|
-
var matches = findMatchingLayers(layers, pattern, true);
|
|
17186
|
-
if (type) {
|
|
17187
|
-
matches = matches.filter(function(o) {return o.layer.geometry_type == type;});
|
|
17188
|
-
}
|
|
17189
|
-
// assign target_id to matched layers
|
|
17190
|
-
// (kludge so layers can be sorted in the order that they match; used by -o command)
|
|
17191
|
-
layers.forEach(function(o) {o.layer.target_id = -1;});
|
|
17192
|
-
matches.forEach(function(o, i) {o.layer.target_id = i;});
|
|
17193
|
-
return groupLayersByDataset(matches);
|
|
17194
|
-
}
|
|
17195
|
-
|
|
17196
|
-
// arr: array of {layer: <>, dataset: <>} objects
|
|
17197
|
-
function groupLayersByDataset(arr) {
|
|
17198
|
-
var datasets = [];
|
|
17199
|
-
var targets = [];
|
|
17200
|
-
arr.forEach(function(o) {
|
|
17201
|
-
var i = datasets.indexOf(o.dataset);
|
|
17202
|
-
if (i == -1) {
|
|
17203
|
-
datasets.push(o.dataset);
|
|
17204
|
-
targets.push({layers: [o.layer], dataset: o.dataset});
|
|
17205
|
-
} else {
|
|
17206
|
-
targets[i].layers.push(o.layer);
|
|
17207
|
-
}
|
|
17208
|
-
});
|
|
17209
|
-
return targets;
|
|
17210
|
-
}
|
|
17211
|
-
|
|
17212
|
-
// layers: array of {layer: <>, dataset: <>} objects
|
|
17213
|
-
// pattern: is a layer identifier or a comma-sep. list of identifiers.
|
|
17214
|
-
// An identifier is a literal name, a pattern containing "*" wildcard or
|
|
17215
|
-
// a 1-based index (1..n)
|
|
17216
|
-
function findMatchingLayers(layers, pattern, throws) {
|
|
17217
|
-
var matchedLayers = [];
|
|
17218
|
-
var unmatchedIds = [];
|
|
17219
|
-
var index = {};
|
|
17220
|
-
pattern.split(',').forEach(function(subpattern, i) {
|
|
17221
|
-
var test = getLayerMatch(subpattern);
|
|
17222
|
-
var matched = false;
|
|
17223
|
-
layers.forEach(function(o, layerId) {
|
|
17224
|
-
// if (matchedLayers.indexOf(lyr) > -1) return; // performance bottleneck with 1000s of layers
|
|
17225
|
-
if (layerId in index) {
|
|
17226
|
-
matched = true;
|
|
17227
|
-
} else if (test(o.layer, layerId + 1)) { // layers are 1-indexed
|
|
17228
|
-
matchedLayers.push(o);
|
|
17229
|
-
index[layerId] = true;
|
|
17230
|
-
matched = true;
|
|
17231
|
-
}
|
|
17232
|
-
});
|
|
17233
|
-
if (matched == false) {
|
|
17234
|
-
unmatchedIds.push(subpattern);
|
|
17235
|
-
}
|
|
17236
|
-
});
|
|
17237
|
-
if (throws && unmatchedIds.length) {
|
|
17238
|
-
stop(utils.format('Missing layer%s: %s', unmatchedIds.length == 1 ? '' : 's', unmatchedIds.join(',')));
|
|
17239
|
-
}
|
|
17240
|
-
return matchedLayers;
|
|
17241
|
-
}
|
|
17242
|
-
|
|
17243
|
-
function getLayerMatch(pattern) {
|
|
17244
|
-
var isIndex = utils.isInteger(Number(pattern));
|
|
17245
|
-
var nameRxp = isIndex ? null : utils.wildcardToRegExp(pattern);
|
|
17246
|
-
return function(lyr, i) {
|
|
17247
|
-
return isIndex ? String(i) == pattern : nameRxp.test(lyr.name || '');
|
|
17248
|
-
};
|
|
17249
|
-
}
|
|
17250
|
-
|
|
17251
|
-
function countTargetLayers(targets) {
|
|
17252
|
-
return targets.reduce(function(memo, target) {
|
|
17253
|
-
return memo + target.layers.length;
|
|
17254
|
-
}, 0);
|
|
17255
|
-
}
|
|
17256
|
-
|
|
17257
|
-
// get an identifier for a layer that can be used in a target= option
|
|
17258
|
-
// (returns name if layer has a unique name, or a numerical id)
|
|
17259
|
-
function getLayerTargetId(catalog, lyr) {
|
|
17260
|
-
var nameCount = 0,
|
|
17261
|
-
name = lyr.name,
|
|
17262
|
-
id;
|
|
17263
|
-
catalog.getLayers().forEach(function(o, i) {
|
|
17264
|
-
if (lyr.name && o.layer.name == lyr.name) nameCount++;
|
|
17265
|
-
if (lyr == o.layer) id = String(i + 1);
|
|
17266
|
-
});
|
|
17267
|
-
if (!id) error('Layer not found');
|
|
17268
|
-
return nameCount == 1 ? lyr.name : id;
|
|
17269
|
-
}
|
|
17270
|
-
|
|
17271
|
-
var TargetUtils = /*#__PURE__*/Object.freeze({
|
|
17272
|
-
__proto__: null,
|
|
17273
|
-
expandCommandTargets: expandCommandTargets,
|
|
17274
|
-
findCommandTargets: findCommandTargets,
|
|
17275
|
-
groupLayersByDataset: groupLayersByDataset,
|
|
17276
|
-
findMatchingLayers: findMatchingLayers,
|
|
17277
|
-
getLayerMatch: getLayerMatch,
|
|
17278
|
-
countTargetLayers: countTargetLayers,
|
|
17279
|
-
getLayerTargetId: getLayerTargetId
|
|
17280
|
-
});
|
|
17281
|
-
|
|
17282
17327
|
function readFirstChars(reader, n) {
|
|
17283
17328
|
return bufferToString(reader.readSync(0, Math.min(n || 1000, reader.size())));
|
|
17284
17329
|
}
|
|
@@ -20154,6 +20199,10 @@ ${svg}
|
|
|
20154
20199
|
DEFAULT: true,
|
|
20155
20200
|
type: 'distance'
|
|
20156
20201
|
})
|
|
20202
|
+
.option('endpoints', {
|
|
20203
|
+
describe: 'only snap together the endpoints of lines',
|
|
20204
|
+
type: 'flag'
|
|
20205
|
+
})
|
|
20157
20206
|
.option('precision', {
|
|
20158
20207
|
describe: 'round all coordinates to a given decimal precision (e.g. 0.000001)',
|
|
20159
20208
|
type: 'number'
|
|
@@ -20695,16 +20744,16 @@ ${svg}
|
|
|
20695
20744
|
var ifOpts = {
|
|
20696
20745
|
expression: {
|
|
20697
20746
|
DEFAULT: true,
|
|
20698
|
-
describe: 'JS expression
|
|
20699
|
-
},
|
|
20700
|
-
empty: {
|
|
20701
|
-
describe: 'run if layer is empty',
|
|
20702
|
-
type: 'flag'
|
|
20703
|
-
},
|
|
20704
|
-
'not-empty': {
|
|
20705
|
-
describe: 'run if layer is not empty',
|
|
20706
|
-
type: 'flag'
|
|
20747
|
+
describe: 'JS expression'
|
|
20707
20748
|
},
|
|
20749
|
+
// empty: {
|
|
20750
|
+
// describe: 'run if layer is empty',
|
|
20751
|
+
// type: 'flag'
|
|
20752
|
+
// },
|
|
20753
|
+
// 'not-empty': {
|
|
20754
|
+
// describe: 'run if layer is not empty',
|
|
20755
|
+
// type: 'flag'
|
|
20756
|
+
// },
|
|
20708
20757
|
layer: {
|
|
20709
20758
|
describe: 'name or id of layer to test (default is current target)'
|
|
20710
20759
|
},
|
|
@@ -34689,13 +34738,27 @@ ${svg}
|
|
|
34689
34738
|
return job.control || (job.control = {});
|
|
34690
34739
|
}
|
|
34691
34740
|
|
|
34692
|
-
function compileIfCommandExpression(expr, catalog,
|
|
34693
|
-
var
|
|
34741
|
+
function compileIfCommandExpression(expr, catalog, opts) {
|
|
34742
|
+
var targetId = opts.layer || opts.target || null;
|
|
34743
|
+
var targets = catalog.findCommandTargets(targetId);
|
|
34744
|
+
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
34745
|
+
if (targets.length === 0 && targetId) {
|
|
34746
|
+
stop('Layer not found:', targetId);
|
|
34747
|
+
}
|
|
34748
|
+
var ctx;
|
|
34749
|
+
if (isSingle) {
|
|
34750
|
+
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs, opts);
|
|
34751
|
+
} else {
|
|
34752
|
+
ctx = getNullLayerProxy(targets);
|
|
34753
|
+
}
|
|
34694
34754
|
var exprOpts = Object.assign({returns: true}, opts);
|
|
34695
34755
|
var func = compileExpressionToFunction(expr, exprOpts);
|
|
34696
34756
|
|
|
34697
|
-
|
|
34698
|
-
|
|
34757
|
+
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
34758
|
+
ctx.layer_exists = function(name, geoType) {
|
|
34759
|
+
var targets = catalog.findCommandTargets(name, geoType);
|
|
34760
|
+
if (targets.length === 0) return false;
|
|
34761
|
+
return true;
|
|
34699
34762
|
};
|
|
34700
34763
|
|
|
34701
34764
|
ctx.file_exists = function(file) {
|
|
@@ -34754,49 +34817,28 @@ ${svg}
|
|
|
34754
34817
|
return ['if','elif','else','endif'].includes(cmd);
|
|
34755
34818
|
}
|
|
34756
34819
|
|
|
34757
|
-
function
|
|
34758
|
-
var targ = getTargetLayer(catalog, opts);
|
|
34820
|
+
function test(catalog, opts) {
|
|
34821
|
+
// var targ = getTargetLayer(catalog, opts);
|
|
34759
34822
|
if (opts.expression) {
|
|
34760
|
-
return compileIfCommandExpression(opts.expression, catalog,
|
|
34761
|
-
}
|
|
34762
|
-
if (opts.empty) {
|
|
34763
|
-
return layerIsEmpty(targ.layer);
|
|
34764
|
-
}
|
|
34765
|
-
if (opts.not_empty) {
|
|
34766
|
-
return !layerIsEmpty(targ.layer);
|
|
34823
|
+
return compileIfCommandExpression(opts.expression, catalog, opts)();
|
|
34767
34824
|
}
|
|
34825
|
+
// if (opts.empty) {
|
|
34826
|
+
// return layerIsEmpty(targ.layer);
|
|
34827
|
+
// }
|
|
34828
|
+
// if (opts.not_empty) {
|
|
34829
|
+
// return !layerIsEmpty(targ.layer);
|
|
34830
|
+
// }
|
|
34768
34831
|
return true;
|
|
34769
34832
|
}
|
|
34770
34833
|
|
|
34771
34834
|
function evaluateIf(job, opts) {
|
|
34772
|
-
if (!blockWasActive(job) &&
|
|
34835
|
+
if (!blockWasActive(job) && test(job.catalog, opts)) {
|
|
34773
34836
|
enterActiveBranch(job);
|
|
34774
34837
|
} else {
|
|
34775
34838
|
enterInactiveBranch(job);
|
|
34776
34839
|
}
|
|
34777
34840
|
}
|
|
34778
34841
|
|
|
34779
|
-
// layerId: optional layer identifier
|
|
34780
|
-
//
|
|
34781
|
-
function getTargetLayer(catalog, opts) {
|
|
34782
|
-
var layerId = opts.layer || opts.target;
|
|
34783
|
-
var targets = catalog.findCommandTargets(layerId);
|
|
34784
|
-
if (targets.length === 0) {
|
|
34785
|
-
if (layerId) {
|
|
34786
|
-
stop('Layer not found:', layerId);
|
|
34787
|
-
} else {
|
|
34788
|
-
stop('Missing a target layer.');
|
|
34789
|
-
}
|
|
34790
|
-
}
|
|
34791
|
-
if (targets.length > 1 || targets[0].layers.length > 1) {
|
|
34792
|
-
stop('Command requires a single target layer.');
|
|
34793
|
-
}
|
|
34794
|
-
return {
|
|
34795
|
-
layer: targets[0].layers[0],
|
|
34796
|
-
dataset: targets[0].dataset
|
|
34797
|
-
};
|
|
34798
|
-
}
|
|
34799
|
-
|
|
34800
34842
|
cmd.ignore = function(targetLayer, dataset, opts) {
|
|
34801
34843
|
if (opts.empty && layerIsEmpty(targetLayer)) {
|
|
34802
34844
|
interrupt('Layer is empty, stopping processing');
|
|
@@ -38490,7 +38532,12 @@ ${svg}
|
|
|
38490
38532
|
interval = getHighPrecisionSnapInterval(arcBounds.toArray());
|
|
38491
38533
|
}
|
|
38492
38534
|
arcs.flatten(); // bake in any simplification
|
|
38493
|
-
if (interval > 0) {
|
|
38535
|
+
if (interval > 0 && opts.endpoints) {
|
|
38536
|
+
// snaps line endpoints together
|
|
38537
|
+
// TODO: also snap endpoints to line segments to remove undershoots and overshoots
|
|
38538
|
+
snapCount = snapEndpointsByInterval(arcs, interval);
|
|
38539
|
+
message(utils.format("Snapped %s endpoint%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
38540
|
+
} else if (interval > 0) {
|
|
38494
38541
|
snapCount = snapCoordsByInterval(arcs, interval);
|
|
38495
38542
|
message(utils.format("Snapped %s point%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
38496
38543
|
}
|
|
@@ -39510,6 +39557,19 @@ ${svg}
|
|
|
39510
39557
|
return [lyr1, lyr2];
|
|
39511
39558
|
}
|
|
39512
39559
|
|
|
39560
|
+
function commandAcceptsMultipleTargetDatasets(name) {
|
|
39561
|
+
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
39562
|
+
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
39563
|
+
name == 'else' || name == 'endif';
|
|
39564
|
+
}
|
|
39565
|
+
|
|
39566
|
+
function commandAcceptsEmptyTarget(name) {
|
|
39567
|
+
return name == 'graticule' || name == 'i' || name == 'help' ||
|
|
39568
|
+
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39569
|
+
name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
|
|
39570
|
+
name == 'else' || name == 'endif';
|
|
39571
|
+
}
|
|
39572
|
+
|
|
39513
39573
|
function runCommand(command, job, cb) {
|
|
39514
39574
|
var name = command.name,
|
|
39515
39575
|
opts = command.options,
|
|
@@ -39531,7 +39591,6 @@ ${svg}
|
|
|
39531
39591
|
job.startCommand(command);
|
|
39532
39592
|
|
|
39533
39593
|
try { // catch errors from synchronous functions
|
|
39534
|
-
|
|
39535
39594
|
T$1.start();
|
|
39536
39595
|
|
|
39537
39596
|
if (name == 'rename-layers') {
|
|
@@ -39546,13 +39605,11 @@ ${svg}
|
|
|
39546
39605
|
// TODO: check that combine_layers is only used w/ GeoJSON output
|
|
39547
39606
|
targets = job.catalog.findCommandTargets(opts.target || opts.combine_layers && '*');
|
|
39548
39607
|
|
|
39549
|
-
} else if (name
|
|
39550
|
-
// these commands accept multiple target datasets
|
|
39608
|
+
} else if (commandAcceptsMultipleTargetDatasets(name)) {
|
|
39551
39609
|
targets = job.catalog.findCommandTargets(opts.target);
|
|
39552
39610
|
|
|
39553
39611
|
} else {
|
|
39554
39612
|
targets = job.catalog.findCommandTargets(opts.target);
|
|
39555
|
-
|
|
39556
39613
|
// special case to allow -merge-layers and -union to combine layers from multiple datasets
|
|
39557
39614
|
// TODO: support multi-dataset targets for other commands
|
|
39558
39615
|
if (targets.length > 1 && (name == 'merge-layers' || name == 'union')) {
|
|
@@ -39576,9 +39633,7 @@ ${svg}
|
|
|
39576
39633
|
stop(utils.format('Missing target: %s\nAvailable layers: %s',
|
|
39577
39634
|
opts.target, getFormattedLayerList(job.catalog)));
|
|
39578
39635
|
}
|
|
39579
|
-
if (!(name
|
|
39580
|
-
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39581
|
-
name == 'include' || name == 'print')) {
|
|
39636
|
+
if (!commandAcceptsEmptyTarget(name)) {
|
|
39582
39637
|
throw new UserError("No data is available");
|
|
39583
39638
|
}
|
|
39584
39639
|
}
|
package/package.json
CHANGED
package/www/index.html
CHANGED
|
@@ -156,6 +156,9 @@
|
|
|
156
156
|
<div class="basemap-styles"></div>
|
|
157
157
|
<div>
|
|
158
158
|
<div class="close-btn btn dialog-btn">Close</div>
|
|
159
|
+
<div class="clear-btn btn dialog-btn disabled">Clear</div>
|
|
160
|
+
<div class="fade-btn btn dialog-btn disabled">Fade</div>
|
|
161
|
+
<!-- <div class="hide-btn btn dialog-btn disabled">Hide</div> -->
|
|
159
162
|
</div>
|
|
160
163
|
</div>
|
|
161
164
|
</div>
|