mapshaper 0.6.51 → 0.6.53

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.51";
3
+ var VERSION = "0.6.53";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -14574,6 +14574,18 @@
14574
14574
  return merged[0];
14575
14575
  }
14576
14576
 
14577
+ cmd.calc = function(layers, arcs, opts) {
14578
+ var arr = layers.map(lyr => applyCalcExpression(lyr, arcs, opts));
14579
+ if (!opts.to_layer) return null;
14580
+ return {
14581
+ info: {},
14582
+ layers: [{
14583
+ name: opts.name || 'info',
14584
+ data: new DataTable(arr)
14585
+ }]
14586
+ };
14587
+ };
14588
+
14577
14589
  // Calculate an expression across a group of features, print and return the result
14578
14590
  // Supported functions include sum(), average(), max(), min(), median(), count()
14579
14591
  // Functions receive an expression to be applied to each feature (like the -each command)
@@ -14581,9 +14593,9 @@
14581
14593
  // opts.expression Expression to evaluate
14582
14594
  // opts.where Optional filter expression (see -filter command)
14583
14595
  //
14584
- cmd.calc = function(lyr, arcs, opts) {
14596
+ function applyCalcExpression(lyr, arcs, opts) {
14585
14597
  var msg = opts.expression,
14586
- result, compiled, defs;
14598
+ result, compiled, defs, d;
14587
14599
  if (opts.where) {
14588
14600
  // TODO: implement no_replace option for filter() instead of this
14589
14601
  lyr = getLayerSelection(lyr, arcs, opts);
@@ -14594,9 +14606,17 @@
14594
14606
  defs = getStashedVar('defs');
14595
14607
  compiled = compileCalcExpression(lyr, arcs, opts.expression);
14596
14608
  result = compiled(null, defs);
14597
- message(msg + ": " + result);
14598
- return result;
14599
- };
14609
+ if (!opts.to_layer) {
14610
+ message(msg + ": " + result);
14611
+ }
14612
+ d = {
14613
+ expression: opts.expression,
14614
+ value: result
14615
+ };
14616
+ if (opts.where) d.where = opts.where;
14617
+ if (lyr.name) d.layer_name = lyr.name;
14618
+ return d;
14619
+ }
14600
14620
 
14601
14621
  function evalCalcExpression(lyr, arcs, exp) {
14602
14622
  return compileCalcExpression(lyr, arcs, exp)();
@@ -14806,6 +14826,7 @@
14806
14826
 
14807
14827
  var Calc = /*#__PURE__*/Object.freeze({
14808
14828
  __proto__: null,
14829
+ applyCalcExpression: applyCalcExpression,
14809
14830
  evalCalcExpression: evalCalcExpression,
14810
14831
  compileCalcExpression: compileCalcExpression
14811
14832
  });
@@ -23379,9 +23400,17 @@ ${svg}
23379
23400
  alias: '+',
23380
23401
  type: 'flag',
23381
23402
  label: '+, no-replace', // show alias as primary option
23382
- // describe: 'retain the original layer(s) instead of replacing'
23383
23403
  describe: 'retain both input and output layer(s)'
23384
23404
  },
23405
+ nameOpt2 = { // for -calc and -info
23406
+ describe: 'name the output layer'
23407
+ },
23408
+ noReplaceOpt2 = { // for -calc and -info
23409
+ alias: '+',
23410
+ type: 'flag',
23411
+ label: '+',
23412
+ describe: 'save output to a new layer'
23413
+ },
23385
23414
  noSnapOpt = {
23386
23415
  // describe: 'don't snap points before applying command'
23387
23416
  type: 'flag'
@@ -23674,14 +23703,14 @@ ${svg}
23674
23703
  .option('geojson-type', {
23675
23704
  describe: '[GeoJSON] FeatureCollection, GeometryCollection or Feature'
23676
23705
  })
23677
- .option('ndjson', {
23678
- describe: '[GeoJSON/JSON] output newline-delimited features or records',
23679
- type: 'flag'
23680
- })
23681
23706
  .option('hoist', {
23682
23707
  describe: '[GeoJSON] move properties to the root level of each Feature',
23683
23708
  type: 'strings'
23684
23709
  })
23710
+ .option('ndjson', {
23711
+ describe: '[GeoJSON/JSON] output newline-delimited features or records',
23712
+ type: 'flag'
23713
+ })
23685
23714
  .option('width', {
23686
23715
  describe: '[SVG/TopoJSON] pixel width of output (SVG default is 800)',
23687
23716
  type: 'number'
@@ -23836,10 +23865,6 @@ ${svg}
23836
23865
  describe: 'a pair of values (0-100) for limiting a color ramp',
23837
23866
  type: 'numbers'
23838
23867
  })
23839
- .option('range', {
23840
- // describe: 'a pair of numbers defining the effective data range',
23841
- type: 'numbers'
23842
- })
23843
23868
  .option('null-value', {
23844
23869
  describe: 'value (or color) to use for invalid or missing data'
23845
23870
  })
@@ -23866,6 +23891,11 @@ ${svg}
23866
23891
  describe: 'user-defined sequential class breaks',
23867
23892
  type: 'numbers'
23868
23893
  })
23894
+ .option('outer-breaks', {
23895
+ describe: 'min,max breakpoints, to limit the effect of outliers',
23896
+ old_alias: 'range',
23897
+ type: 'numbers'
23898
+ })
23869
23899
  .option('classes', {
23870
23900
  describe: 'number of classes (can be inferred from other options)',
23871
23901
  type: 'integer'
@@ -23875,7 +23905,7 @@ ${svg}
23875
23905
  type: 'flag'
23876
23906
  })
23877
23907
  .option('continuous', {
23878
- describe: 'output continuous interpolated values (experimental)',
23908
+ describe: 'output interpolated values, for unclassed colors',
23879
23909
  type: 'flag'
23880
23910
  })
23881
23911
  .option('index-field', {
@@ -25276,8 +25306,8 @@ ${svg}
25276
25306
  type: 'flag'
25277
25307
  })
25278
25308
  .option('calc', calcOpt)
25279
- .option('name', nameOpt)
25280
25309
  .option('target', targetOpt)
25310
+ .option('name', nameOpt)
25281
25311
  .option('no-replace', noReplaceOpt);
25282
25312
 
25283
25313
  parser.command('require')
@@ -25437,7 +25467,9 @@ ${svg}
25437
25467
  describe: 'functions: sum() average() median() max() min() count()'
25438
25468
  })
25439
25469
  .option('where', whereOpt)
25440
- .option('target', targetOpt);
25470
+ .option('target', targetOpt)
25471
+ .option('to-layer', noReplaceOpt2)
25472
+ .option('name', nameOpt2);
25441
25473
 
25442
25474
  parser.command('colors')
25443
25475
  .describe('print list of color scheme names');
@@ -25467,7 +25499,9 @@ ${svg}
25467
25499
  .option('save-to', {
25468
25500
  describe: 'name of file to save info in JSON format'
25469
25501
  })
25470
- .option('target', targetOpt);
25502
+ .option('target', targetOpt)
25503
+ .option('to-layer', noReplaceOpt2)
25504
+ .option('name', nameOpt2);
25471
25505
 
25472
25506
  parser.command('inspect')
25473
25507
  .describe('print information about a feature')
@@ -28642,7 +28676,7 @@ ${svg}
28642
28676
  // Apply a command to an array of target layers
28643
28677
  function applyCommandToEachLayer(func, targetLayers) {
28644
28678
  var args = utils.toArray(arguments).slice(2);
28645
- return targetLayers.reduce(function(memo, lyr) {
28679
+ var output = targetLayers.reduce(function(memo, lyr) {
28646
28680
  var result = func.apply(null, [lyr].concat(args));
28647
28681
  if (utils.isArray(result)) { // some commands return an array of layers
28648
28682
  memo = memo.concat(result);
@@ -28651,6 +28685,7 @@ ${svg}
28651
28685
  }
28652
28686
  return memo;
28653
28687
  }, []);
28688
+ return output.length > 0 ? output : null;
28654
28689
  }
28655
28690
 
28656
28691
  function applyCommandToEachTarget(func, targets) {
@@ -32100,23 +32135,22 @@ ${svg}
32100
32135
  }
32101
32136
 
32102
32137
  var ascending = getAscendingNumbers(dataValues);
32103
- if (opts.range) {
32104
- ascending = applyDataRange(ascending, opts.range);
32138
+ if (opts.outer_breaks) {
32139
+ ascending = applyDataRange(ascending, opts.outer_breaks);
32105
32140
  }
32106
32141
  var nullCount = dataValues.length - ascending.length;
32107
32142
  var minVal = ascending[0];
32108
32143
  var maxVal = ascending[ascending.length - 1];
32109
32144
 
32110
- // kludge
32111
- var clamp = opts.range ? function(val) {
32112
- if (val < opts.range[0]) val = opts.range[0];
32113
- if (val > opts.range[1]) val = opts.range[1];
32145
+ var clamp = opts.outer_breaks ? function(val) {
32146
+ if (val < opts.outer_breaks[0]) val = opts.outer_breaks[0];
32147
+ if (val > opts.outer_breaks[1]) val = opts.outer_breaks[1];
32114
32148
  return val;
32115
32149
  } : null;
32116
32150
 
32117
- if (opts.range) {
32118
- minVal = opts.range[0];
32119
- maxVal = opts.range[1];
32151
+ if (opts.outer_breaks) {
32152
+ minVal = opts.outer_breaks[0];
32153
+ maxVal = opts.outer_breaks[1];
32120
32154
  }
32121
32155
 
32122
32156
  if (numBreaks === 0) {
@@ -39150,7 +39184,7 @@ ${svg}
39150
39184
  var arr = layers.map(function(o) {
39151
39185
  return getLayerInfo(o.layer, o.dataset);
39152
39186
  });
39153
- message(formatInfo(arr));
39187
+
39154
39188
  if (opts.save_to) {
39155
39189
  var output = [{
39156
39190
  filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
@@ -39158,6 +39192,16 @@ ${svg}
39158
39192
  }];
39159
39193
  writeFiles(output, opts);
39160
39194
  }
39195
+ if (opts.to_layer) {
39196
+ return {
39197
+ info: {},
39198
+ layers: [{
39199
+ name: opts.name || 'info',
39200
+ data: new DataTable(arr)
39201
+ }]
39202
+ };
39203
+ }
39204
+ message(formatInfo(arr));
39161
39205
  };
39162
39206
 
39163
39207
  cmd.printInfo = cmd.info; // old name
@@ -44288,7 +44332,7 @@ ${svg}
44288
44332
  applyCommandToEachLayer(cmd.cluster, targetLayers, arcs, opts);
44289
44333
 
44290
44334
  } else if (name == 'calc') {
44291
- applyCommandToEachLayer(cmd.calc, targetLayers, arcs, opts);
44335
+ outputDataset = cmd.calc(targetLayers, arcs, opts);
44292
44336
 
44293
44337
  } else if (name == 'classify') {
44294
44338
  applyCommandToEachLayer(cmd.classify, targetLayers, targetDataset, opts);
@@ -44402,7 +44446,7 @@ ${svg}
44402
44446
  cmd.include(opts);
44403
44447
 
44404
44448
  } else if (name == 'info') {
44405
- cmd.info(targets, opts);
44449
+ outputDataset = cmd.info(targets, opts);
44406
44450
 
44407
44451
  } else if (name == 'inlay') {
44408
44452
  outputLayers = cmd.inlay(targetLayers, source, targetDataset, opts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.51",
3
+ "version": "0.6.53",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -76,7 +76,7 @@
76
76
  "mocha": {
77
77
  "reporter": "dot",
78
78
  "node-option": [
79
- "experimental-specifier-resolution=node"
79
+ "experimental-loader=./test/_loader.js"
80
80
  ],
81
81
  "check-leaks": true,
82
82
  "parallel": true,
package/www/mapshaper.js CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.51";
3
+ var VERSION = "0.6.53";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -14574,6 +14574,18 @@
14574
14574
  return merged[0];
14575
14575
  }
14576
14576
 
14577
+ cmd.calc = function(layers, arcs, opts) {
14578
+ var arr = layers.map(lyr => applyCalcExpression(lyr, arcs, opts));
14579
+ if (!opts.to_layer) return null;
14580
+ return {
14581
+ info: {},
14582
+ layers: [{
14583
+ name: opts.name || 'info',
14584
+ data: new DataTable(arr)
14585
+ }]
14586
+ };
14587
+ };
14588
+
14577
14589
  // Calculate an expression across a group of features, print and return the result
14578
14590
  // Supported functions include sum(), average(), max(), min(), median(), count()
14579
14591
  // Functions receive an expression to be applied to each feature (like the -each command)
@@ -14581,9 +14593,9 @@
14581
14593
  // opts.expression Expression to evaluate
14582
14594
  // opts.where Optional filter expression (see -filter command)
14583
14595
  //
14584
- cmd.calc = function(lyr, arcs, opts) {
14596
+ function applyCalcExpression(lyr, arcs, opts) {
14585
14597
  var msg = opts.expression,
14586
- result, compiled, defs;
14598
+ result, compiled, defs, d;
14587
14599
  if (opts.where) {
14588
14600
  // TODO: implement no_replace option for filter() instead of this
14589
14601
  lyr = getLayerSelection(lyr, arcs, opts);
@@ -14594,9 +14606,17 @@
14594
14606
  defs = getStashedVar('defs');
14595
14607
  compiled = compileCalcExpression(lyr, arcs, opts.expression);
14596
14608
  result = compiled(null, defs);
14597
- message(msg + ": " + result);
14598
- return result;
14599
- };
14609
+ if (!opts.to_layer) {
14610
+ message(msg + ": " + result);
14611
+ }
14612
+ d = {
14613
+ expression: opts.expression,
14614
+ value: result
14615
+ };
14616
+ if (opts.where) d.where = opts.where;
14617
+ if (lyr.name) d.layer_name = lyr.name;
14618
+ return d;
14619
+ }
14600
14620
 
14601
14621
  function evalCalcExpression(lyr, arcs, exp) {
14602
14622
  return compileCalcExpression(lyr, arcs, exp)();
@@ -14806,6 +14826,7 @@
14806
14826
 
14807
14827
  var Calc = /*#__PURE__*/Object.freeze({
14808
14828
  __proto__: null,
14829
+ applyCalcExpression: applyCalcExpression,
14809
14830
  evalCalcExpression: evalCalcExpression,
14810
14831
  compileCalcExpression: compileCalcExpression
14811
14832
  });
@@ -23379,9 +23400,17 @@ ${svg}
23379
23400
  alias: '+',
23380
23401
  type: 'flag',
23381
23402
  label: '+, no-replace', // show alias as primary option
23382
- // describe: 'retain the original layer(s) instead of replacing'
23383
23403
  describe: 'retain both input and output layer(s)'
23384
23404
  },
23405
+ nameOpt2 = { // for -calc and -info
23406
+ describe: 'name the output layer'
23407
+ },
23408
+ noReplaceOpt2 = { // for -calc and -info
23409
+ alias: '+',
23410
+ type: 'flag',
23411
+ label: '+',
23412
+ describe: 'save output to a new layer'
23413
+ },
23385
23414
  noSnapOpt = {
23386
23415
  // describe: 'don't snap points before applying command'
23387
23416
  type: 'flag'
@@ -23674,14 +23703,14 @@ ${svg}
23674
23703
  .option('geojson-type', {
23675
23704
  describe: '[GeoJSON] FeatureCollection, GeometryCollection or Feature'
23676
23705
  })
23677
- .option('ndjson', {
23678
- describe: '[GeoJSON/JSON] output newline-delimited features or records',
23679
- type: 'flag'
23680
- })
23681
23706
  .option('hoist', {
23682
23707
  describe: '[GeoJSON] move properties to the root level of each Feature',
23683
23708
  type: 'strings'
23684
23709
  })
23710
+ .option('ndjson', {
23711
+ describe: '[GeoJSON/JSON] output newline-delimited features or records',
23712
+ type: 'flag'
23713
+ })
23685
23714
  .option('width', {
23686
23715
  describe: '[SVG/TopoJSON] pixel width of output (SVG default is 800)',
23687
23716
  type: 'number'
@@ -23836,10 +23865,6 @@ ${svg}
23836
23865
  describe: 'a pair of values (0-100) for limiting a color ramp',
23837
23866
  type: 'numbers'
23838
23867
  })
23839
- .option('range', {
23840
- // describe: 'a pair of numbers defining the effective data range',
23841
- type: 'numbers'
23842
- })
23843
23868
  .option('null-value', {
23844
23869
  describe: 'value (or color) to use for invalid or missing data'
23845
23870
  })
@@ -23866,6 +23891,11 @@ ${svg}
23866
23891
  describe: 'user-defined sequential class breaks',
23867
23892
  type: 'numbers'
23868
23893
  })
23894
+ .option('outer-breaks', {
23895
+ describe: 'min,max breakpoints, to limit the effect of outliers',
23896
+ old_alias: 'range',
23897
+ type: 'numbers'
23898
+ })
23869
23899
  .option('classes', {
23870
23900
  describe: 'number of classes (can be inferred from other options)',
23871
23901
  type: 'integer'
@@ -23875,7 +23905,7 @@ ${svg}
23875
23905
  type: 'flag'
23876
23906
  })
23877
23907
  .option('continuous', {
23878
- describe: 'output continuous interpolated values (experimental)',
23908
+ describe: 'output interpolated values, for unclassed colors',
23879
23909
  type: 'flag'
23880
23910
  })
23881
23911
  .option('index-field', {
@@ -25276,8 +25306,8 @@ ${svg}
25276
25306
  type: 'flag'
25277
25307
  })
25278
25308
  .option('calc', calcOpt)
25279
- .option('name', nameOpt)
25280
25309
  .option('target', targetOpt)
25310
+ .option('name', nameOpt)
25281
25311
  .option('no-replace', noReplaceOpt);
25282
25312
 
25283
25313
  parser.command('require')
@@ -25437,7 +25467,9 @@ ${svg}
25437
25467
  describe: 'functions: sum() average() median() max() min() count()'
25438
25468
  })
25439
25469
  .option('where', whereOpt)
25440
- .option('target', targetOpt);
25470
+ .option('target', targetOpt)
25471
+ .option('to-layer', noReplaceOpt2)
25472
+ .option('name', nameOpt2);
25441
25473
 
25442
25474
  parser.command('colors')
25443
25475
  .describe('print list of color scheme names');
@@ -25467,7 +25499,9 @@ ${svg}
25467
25499
  .option('save-to', {
25468
25500
  describe: 'name of file to save info in JSON format'
25469
25501
  })
25470
- .option('target', targetOpt);
25502
+ .option('target', targetOpt)
25503
+ .option('to-layer', noReplaceOpt2)
25504
+ .option('name', nameOpt2);
25471
25505
 
25472
25506
  parser.command('inspect')
25473
25507
  .describe('print information about a feature')
@@ -28642,7 +28676,7 @@ ${svg}
28642
28676
  // Apply a command to an array of target layers
28643
28677
  function applyCommandToEachLayer(func, targetLayers) {
28644
28678
  var args = utils.toArray(arguments).slice(2);
28645
- return targetLayers.reduce(function(memo, lyr) {
28679
+ var output = targetLayers.reduce(function(memo, lyr) {
28646
28680
  var result = func.apply(null, [lyr].concat(args));
28647
28681
  if (utils.isArray(result)) { // some commands return an array of layers
28648
28682
  memo = memo.concat(result);
@@ -28651,6 +28685,7 @@ ${svg}
28651
28685
  }
28652
28686
  return memo;
28653
28687
  }, []);
28688
+ return output.length > 0 ? output : null;
28654
28689
  }
28655
28690
 
28656
28691
  function applyCommandToEachTarget(func, targets) {
@@ -32100,23 +32135,22 @@ ${svg}
32100
32135
  }
32101
32136
 
32102
32137
  var ascending = getAscendingNumbers(dataValues);
32103
- if (opts.range) {
32104
- ascending = applyDataRange(ascending, opts.range);
32138
+ if (opts.outer_breaks) {
32139
+ ascending = applyDataRange(ascending, opts.outer_breaks);
32105
32140
  }
32106
32141
  var nullCount = dataValues.length - ascending.length;
32107
32142
  var minVal = ascending[0];
32108
32143
  var maxVal = ascending[ascending.length - 1];
32109
32144
 
32110
- // kludge
32111
- var clamp = opts.range ? function(val) {
32112
- if (val < opts.range[0]) val = opts.range[0];
32113
- if (val > opts.range[1]) val = opts.range[1];
32145
+ var clamp = opts.outer_breaks ? function(val) {
32146
+ if (val < opts.outer_breaks[0]) val = opts.outer_breaks[0];
32147
+ if (val > opts.outer_breaks[1]) val = opts.outer_breaks[1];
32114
32148
  return val;
32115
32149
  } : null;
32116
32150
 
32117
- if (opts.range) {
32118
- minVal = opts.range[0];
32119
- maxVal = opts.range[1];
32151
+ if (opts.outer_breaks) {
32152
+ minVal = opts.outer_breaks[0];
32153
+ maxVal = opts.outer_breaks[1];
32120
32154
  }
32121
32155
 
32122
32156
  if (numBreaks === 0) {
@@ -39150,7 +39184,7 @@ ${svg}
39150
39184
  var arr = layers.map(function(o) {
39151
39185
  return getLayerInfo(o.layer, o.dataset);
39152
39186
  });
39153
- message(formatInfo(arr));
39187
+
39154
39188
  if (opts.save_to) {
39155
39189
  var output = [{
39156
39190
  filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
@@ -39158,6 +39192,16 @@ ${svg}
39158
39192
  }];
39159
39193
  writeFiles(output, opts);
39160
39194
  }
39195
+ if (opts.to_layer) {
39196
+ return {
39197
+ info: {},
39198
+ layers: [{
39199
+ name: opts.name || 'info',
39200
+ data: new DataTable(arr)
39201
+ }]
39202
+ };
39203
+ }
39204
+ message(formatInfo(arr));
39161
39205
  };
39162
39206
 
39163
39207
  cmd.printInfo = cmd.info; // old name
@@ -44288,7 +44332,7 @@ ${svg}
44288
44332
  applyCommandToEachLayer(cmd.cluster, targetLayers, arcs, opts);
44289
44333
 
44290
44334
  } else if (name == 'calc') {
44291
- applyCommandToEachLayer(cmd.calc, targetLayers, arcs, opts);
44335
+ outputDataset = cmd.calc(targetLayers, arcs, opts);
44292
44336
 
44293
44337
  } else if (name == 'classify') {
44294
44338
  applyCommandToEachLayer(cmd.classify, targetLayers, targetDataset, opts);
@@ -44402,7 +44446,7 @@ ${svg}
44402
44446
  cmd.include(opts);
44403
44447
 
44404
44448
  } else if (name == 'info') {
44405
- cmd.info(targets, opts);
44449
+ outputDataset = cmd.info(targets, opts);
44406
44450
 
44407
44451
  } else if (name == 'inlay') {
44408
44452
  outputLayers = cmd.inlay(targetLayers, source, targetDataset, opts);