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.
@@ -1107,7 +1107,7 @@
1107
1107
 
1108
1108
  utils$1.inherit(Checkbox, EventDispatcher);
1109
1109
 
1110
- function SimpleButton(ref) {
1110
+ function xSimpleButton(ref) {
1111
1111
  var _el = El(ref),
1112
1112
  _self = this,
1113
1113
  _active = !_el.hasClass('disabled');
@@ -1134,7 +1134,31 @@
1134
1134
  }
1135
1135
  }
1136
1136
 
1137
- utils$1.inherit(SimpleButton, EventDispatcher);
1137
+ //utils.inherit(SimpleButton, EventDispatcher);
1138
+
1139
+ function SimpleButton(ref) {
1140
+ var _el = El(ref),
1141
+ _active = !_el.hasClass('disabled');
1142
+
1143
+ _el.active = function(a) {
1144
+ if (a === void 0) return _active;
1145
+ if (a !== _active) {
1146
+ _active = a;
1147
+ _el.toggleClass('disabled');
1148
+ }
1149
+ return _el;
1150
+ };
1151
+
1152
+ // this.node = function() {return _el.node();};
1153
+
1154
+ function isVisible() {
1155
+ var el = _el.node();
1156
+ return el.offsetParent !== null;
1157
+ }
1158
+ return _el;
1159
+ }
1160
+
1161
+ // utils.inherit(SimpleButton, EventDispatcher);
1138
1162
 
1139
1163
  // @cb function(<FileList>)
1140
1164
  function DropControl(gui, el, cb) {
@@ -9729,6 +9753,10 @@
9729
9753
 
9730
9754
  function Basemap(gui, ext) {
9731
9755
  var menu = gui.container.findChild('.basemap-options');
9756
+ // var hideBtn = new SimpleButton(menu.findChild('.hide-btn'));
9757
+ var fadeBtn = new SimpleButton(menu.findChild('.fade-btn'));
9758
+ var closeBtn = new SimpleButton(menu.findChild('.close-btn'));
9759
+ var clearBtn = new SimpleButton(menu.findChild('.clear-btn'));
9732
9760
  var list = menu.findChild('.basemap-styles');
9733
9761
  var container = gui.container.findChild('.basemap-container');
9734
9762
  var basemapBtn = gui.container.findChild('.basemap-btn');
@@ -9740,6 +9768,7 @@
9740
9768
  var map;
9741
9769
  var activeStyle;
9742
9770
  var loading = false;
9771
+ var faded = false;
9743
9772
 
9744
9773
  if (params) {
9745
9774
  init();
@@ -9750,11 +9779,35 @@
9750
9779
  function init() {
9751
9780
  gui.addMode('basemap', turnOn, turnOff, basemapBtn);
9752
9781
 
9753
- new SimpleButton(menu.findChild('.close-btn')).on('click', function() {
9782
+ closeBtn.on('click', function() {
9754
9783
  gui.clearMode();
9755
9784
  turnOff();
9756
9785
  });
9757
9786
 
9787
+ // hideBtn.on('mousedown', function() {
9788
+ // if (activeStyle) {
9789
+ // mapEl.css('visibility', 'hidden');
9790
+ // hidden = true;
9791
+ // }
9792
+ // })
9793
+ clearBtn.on('click', function() {
9794
+ if (activeStyle) {
9795
+ updateStyle(null);
9796
+ updateButtons();
9797
+ }
9798
+ });
9799
+ fadeBtn.on('click', function() {
9800
+ if (faded) {
9801
+ mapEl.css('opacity', 1);
9802
+ faded = false;
9803
+ fadeBtn.text('Fade');
9804
+ } else if (activeStyle) {
9805
+ mapEl.css('opacity', 0.35);
9806
+ faded = true;
9807
+ fadeBtn.text('Unfade');
9808
+ }
9809
+ });
9810
+
9758
9811
  gui.on('map_click', function() {
9759
9812
  // close menu if user click on the map
9760
9813
  if (gui.getMode() == 'basemap') gui.clearMode();
@@ -9777,13 +9830,14 @@
9777
9830
  // gui.state.dark_basemap = style && style.dark || false;
9778
9831
  if (!style) {
9779
9832
  gui.map.setDisplayCRS(null);
9780
- hide();
9833
+ refresh();
9781
9834
  } else if (map) {
9782
9835
  map.setStyle(style.url);
9783
9836
  refresh();
9784
9837
  } else {
9785
9838
  initMap();
9786
9839
  }
9840
+
9787
9841
  }
9788
9842
 
9789
9843
  function updateButtons() {
@@ -9893,12 +9947,15 @@
9893
9947
  }
9894
9948
 
9895
9949
  function refresh() {
9896
- if (!enabled() || !map || loading || !activeStyle) return;
9897
9950
  var crs = gui.map.getDisplayCRS();
9898
- if (!crsIsUsable(crs)) {
9951
+ var off = !crs || !enabled() || !map || loading || !activeStyle;
9952
+ fadeBtn.active(!off);
9953
+ clearBtn.active(!off);
9954
+ if (off) {
9899
9955
  hide();
9900
9956
  return;
9901
9957
  }
9958
+
9902
9959
  if (!internal.isWebMercator(crs)) {
9903
9960
  gui.map.setDisplayCRS(internal.getCRS('webmercator'));
9904
9961
  }
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.5.110";
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 snapCoordsByInterval(arcs, snapDist) {
2742
+ function snapCoordsInternal(ids, arcs, snapDist) {
2731
2743
  var snapCount = 0,
2732
- data = arcs.getVertexData(),
2733
- ids;
2744
+ n = ids.length,
2745
+ data = arcs.getVertexData();
2734
2746
 
2735
- if (snapDist > 0) {
2736
- // Get sorted coordinate ids
2737
- // Consider: speed up sorting -- try bucket sort as first pass.
2738
- //
2739
- ids = sortCoordinateIds(data.xx);
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 sortCoordinateIds(a) {
2769
- var n = a.length,
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
- quicksortIds(a, ids, 0, ids.length-1);
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
- sortCoordinateIds: sortCoordinateIds
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 addBBoxGetter(obj, lyr, arcs) {
9701
+ function getBBoxGetter(obj, lyr, arcs) {
9545
9702
  var bbox;
9546
- addGetters(obj, {
9547
- bbox: function() {
9548
- if (!bbox) {
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 targeting a single layer'
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, targ, opts) {
34693
- var ctx = getLayerProxy(targ.layer, targ.dataset.arcs, opts);
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
- ctx.layer_exists = function(name) {
34698
- return !!catalog.findSingleLayer(name);
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 testLayer(catalog, opts) {
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, targ, opts)();
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) && testLayer(job.catalog, opts)) {
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 == 'rotate' || name == 'info' || name == 'proj' || name == 'drop' || name == 'target') {
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 == 'graticule' || name == 'i' || name == 'help' ||
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
  }