mapshaper 0.6.23 → 0.6.24
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 +155 -109
- package/package.json +1 -1
- package/www/mapshaper-gui.js +42 -36
- package/www/mapshaper.js +155 -109
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.24";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -10620,7 +10620,8 @@
|
|
|
10620
10620
|
buf = new Uint8Array(buf);
|
|
10621
10621
|
}
|
|
10622
10622
|
opts = opts || {};
|
|
10623
|
-
var
|
|
10623
|
+
var gunzip$1 = runningInBrowser() ? utils.promisify(gunzip) : utils.promisify(require('zlib').gunzip);
|
|
10624
|
+
var out = await gunzip$1(buf, opts);
|
|
10624
10625
|
if (opts.filename && !isImportableAsBinary(opts.filename)) {
|
|
10625
10626
|
out = strFromU8(out);
|
|
10626
10627
|
}
|
|
@@ -10628,8 +10629,6 @@
|
|
|
10628
10629
|
}
|
|
10629
10630
|
|
|
10630
10631
|
function gunzipSync(buf, filename) {
|
|
10631
|
-
// TODO: use native module in Node
|
|
10632
|
-
// require('zlib').
|
|
10633
10632
|
if (buf instanceof ArrayBuffer) {
|
|
10634
10633
|
buf = new Uint8Array(buf);
|
|
10635
10634
|
}
|
|
@@ -10768,16 +10767,39 @@
|
|
|
10768
10767
|
// gui: (optional) gui instance
|
|
10769
10768
|
//
|
|
10770
10769
|
async function exportDatasetsToPack(datasets, opts) {
|
|
10771
|
-
|
|
10770
|
+
var obj = {
|
|
10772
10771
|
version: 1,
|
|
10773
10772
|
created: (new Date).toISOString(),
|
|
10774
|
-
datasets: await Promise.all(datasets.map(
|
|
10773
|
+
datasets: await Promise.all(datasets.map(exportDataset))
|
|
10775
10774
|
};
|
|
10775
|
+
if (opts.compact) {
|
|
10776
|
+
await applyCompression(obj);
|
|
10777
|
+
}
|
|
10778
|
+
return obj;
|
|
10779
|
+
}
|
|
10780
|
+
|
|
10781
|
+
async function applyCompression(obj, opts) {
|
|
10782
|
+
var promises = [];
|
|
10783
|
+
obj.datasets.forEach(d => {
|
|
10784
|
+
if (d.arcs) promises.push(compressArcs(d.arcs, opts));
|
|
10785
|
+
});
|
|
10786
|
+
await Promise.all(promises);
|
|
10787
|
+
}
|
|
10788
|
+
|
|
10789
|
+
async function compressArcs(obj, opts) {
|
|
10790
|
+
var gzipOpts = Object.assign({level: 1, consume: false}, opts);
|
|
10791
|
+
var promises = [gzipAsync(obj.nn, gzipOpts), gzipAsync(obj.xx, gzipOpts), gzipAsync(obj.yy, gzipOpts)];
|
|
10792
|
+
if (obj.zz) promises.push(gzipAsync(obj.zz, gzipOpts));
|
|
10793
|
+
var results = await Promise.all(promises);
|
|
10794
|
+
obj.nn = results.shift();
|
|
10795
|
+
obj.xx = results.shift();
|
|
10796
|
+
obj.yy = results.shift();
|
|
10797
|
+
if (obj.zz) obj.zz = results.shift();
|
|
10776
10798
|
}
|
|
10777
10799
|
|
|
10778
10800
|
async function exportDataset(dataset, opts) {
|
|
10779
10801
|
return {
|
|
10780
|
-
arcs: dataset.arcs ?
|
|
10802
|
+
arcs: dataset.arcs ? exportArcs(dataset.arcs) : null,
|
|
10781
10803
|
info: dataset.info ? exportInfo(dataset.info) : null,
|
|
10782
10804
|
layers: await Promise.all((dataset.layers || []).map(exportLayer))
|
|
10783
10805
|
};
|
|
@@ -10787,38 +10809,22 @@
|
|
|
10787
10809
|
return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
10788
10810
|
}
|
|
10789
10811
|
|
|
10790
|
-
|
|
10812
|
+
function exportArcs(arcs) {
|
|
10791
10813
|
var data = arcs.getVertexData();
|
|
10792
|
-
|
|
10814
|
+
return {
|
|
10793
10815
|
nn: typedArrayToBuffer(data.nn),
|
|
10794
10816
|
xx: typedArrayToBuffer(data.xx),
|
|
10795
10817
|
yy: typedArrayToBuffer(data.yy),
|
|
10796
10818
|
zz: data.zz ? typedArrayToBuffer(data.zz) : null,
|
|
10797
10819
|
zlimit: arcs.getRetainedInterval()
|
|
10798
10820
|
};
|
|
10799
|
-
|
|
10800
|
-
// gzipping typically sees about 70% compression on unrounded coordinates
|
|
10801
|
-
// -- possibly not worth the time
|
|
10802
|
-
if (opts.compact) {
|
|
10803
|
-
var gzipOpts = {level: 1, consume: false};
|
|
10804
|
-
var promises = [gzipAsync(obj.nn, gzipOpts), gzipAsync(obj.xx, gzipOpts), gzipAsync(obj.yy, gzipOpts)];
|
|
10805
|
-
if (obj.zz) promises.push(gzipAsync(obj.zz, gzipOpts));
|
|
10806
|
-
var results = await Promise.all(promises);
|
|
10807
|
-
obj.nn = results.shift();
|
|
10808
|
-
obj.xx = results.shift();
|
|
10809
|
-
obj.yy = results.shift();
|
|
10810
|
-
if (obj.zz) obj.zz = results.shift();
|
|
10811
|
-
}
|
|
10812
|
-
return obj;
|
|
10813
10821
|
}
|
|
10814
10822
|
|
|
10815
10823
|
async function exportLayer(lyr) {
|
|
10816
|
-
// console.time('table')
|
|
10817
10824
|
var data = null;
|
|
10818
10825
|
if (lyr.data) {
|
|
10819
10826
|
data = await exportTable2(lyr.data);
|
|
10820
10827
|
}
|
|
10821
|
-
// console.timeEnd('table')
|
|
10822
10828
|
return {
|
|
10823
10829
|
name: lyr.name || null,
|
|
10824
10830
|
geometry_type: lyr.geometry_type || null,
|
|
@@ -10845,6 +10851,7 @@
|
|
|
10845
10851
|
exportPackedDatasets: exportPackedDatasets,
|
|
10846
10852
|
pack: pack,
|
|
10847
10853
|
exportDatasetsToPack: exportDatasetsToPack,
|
|
10854
|
+
applyCompression: applyCompression,
|
|
10848
10855
|
exportDataset: exportDataset
|
|
10849
10856
|
});
|
|
10850
10857
|
|
|
@@ -24922,6 +24929,9 @@ ${svg}
|
|
|
24922
24929
|
|
|
24923
24930
|
parser.command('info')
|
|
24924
24931
|
.describe('print information about data layers')
|
|
24932
|
+
.option('save-to', {
|
|
24933
|
+
describe: 'name of file to save info in JSON format'
|
|
24934
|
+
})
|
|
24925
24935
|
.option('target', targetOpt);
|
|
24926
24936
|
|
|
24927
24937
|
parser.command('inspect')
|
|
@@ -27457,12 +27467,14 @@ ${svg}
|
|
|
27457
27467
|
// Import datasets contained in a BSON blob
|
|
27458
27468
|
// Return command target as a dataset
|
|
27459
27469
|
//
|
|
27460
|
-
async function
|
|
27461
|
-
|
|
27470
|
+
async function unpackSessionData(buf) {
|
|
27471
|
+
return restoreSessionData(unpack(buf, {}));
|
|
27472
|
+
}
|
|
27473
|
+
|
|
27474
|
+
async function restoreSessionData(obj) {
|
|
27462
27475
|
if (!isValidSession(obj)) {
|
|
27463
27476
|
stop('Invalid mapshaper session data object');
|
|
27464
27477
|
}
|
|
27465
|
-
|
|
27466
27478
|
var datasets = await Promise.all(obj.datasets.map(importDataset));
|
|
27467
27479
|
return Object.assign(obj, {datasets: datasets});
|
|
27468
27480
|
}
|
|
@@ -27539,7 +27551,8 @@ ${svg}
|
|
|
27539
27551
|
|
|
27540
27552
|
var Unpack = /*#__PURE__*/Object.freeze({
|
|
27541
27553
|
__proto__: null,
|
|
27542
|
-
|
|
27554
|
+
unpackSessionData: unpackSessionData,
|
|
27555
|
+
restoreSessionData: restoreSessionData
|
|
27543
27556
|
});
|
|
27544
27557
|
|
|
27545
27558
|
cmd.importFiles = async function(catalog, opts) {
|
|
@@ -27593,7 +27606,7 @@ ${svg}
|
|
|
27593
27606
|
|
|
27594
27607
|
async function importMshpFile(file, catalog, opts) {
|
|
27595
27608
|
var buf = cli.readFile(file, null, opts.input);
|
|
27596
|
-
var obj = await
|
|
27609
|
+
var obj = await unpackSessionData(buf);
|
|
27597
27610
|
obj.datasets.forEach(catalog.addDataset, catalog);
|
|
27598
27611
|
return obj.target;
|
|
27599
27612
|
}
|
|
@@ -38240,55 +38253,27 @@ ${svg}
|
|
|
38240
38253
|
|
|
38241
38254
|
var MAX_RULE_LEN = 50;
|
|
38242
38255
|
|
|
38243
|
-
cmd.
|
|
38244
|
-
var
|
|
38245
|
-
layers.
|
|
38246
|
-
|
|
38247
|
-
var tableStr = getAttributeTableInfo(o.layer);
|
|
38248
|
-
var tableWidth = measureLongestLine(tableStr);
|
|
38249
|
-
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
38250
|
-
str += '\n';
|
|
38251
|
-
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
38252
|
-
str += title + '\n';
|
|
38253
|
-
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
38254
|
-
str += getLayerInfo(o.layer, o.dataset);
|
|
38255
|
-
str += tableStr;
|
|
38256
|
+
cmd.info = function(targets, opts) {
|
|
38257
|
+
var layers = expandCommandTargets(targets);
|
|
38258
|
+
var arr = layers.map(function(o) {
|
|
38259
|
+
return getLayerInfo(o.layer, o.dataset);
|
|
38256
38260
|
});
|
|
38257
|
-
message(
|
|
38258
|
-
|
|
38259
|
-
|
|
38260
|
-
|
|
38261
|
-
|
|
38262
|
-
|
|
38263
|
-
|
|
38264
|
-
function stringDisplayWidth(str) {
|
|
38265
|
-
var w = 0;
|
|
38266
|
-
for (var i = 0, n=str.length; i < n; i++) {
|
|
38267
|
-
w += charDisplayWidth(str.charCodeAt(i));
|
|
38261
|
+
message(formatInfo(arr));
|
|
38262
|
+
if (opts.save_to) {
|
|
38263
|
+
var output = [{
|
|
38264
|
+
filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
|
|
38265
|
+
content: JSON.stringify(arr, null, 2)
|
|
38266
|
+
}];
|
|
38267
|
+
writeFiles(output, opts);
|
|
38268
38268
|
}
|
|
38269
|
-
|
|
38270
|
-
}
|
|
38269
|
+
};
|
|
38271
38270
|
|
|
38272
|
-
//
|
|
38273
|
-
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
38274
|
-
function charDisplayWidth(c) {
|
|
38275
|
-
if (c >= 0x1100 &&
|
|
38276
|
-
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
38277
|
-
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
38278
|
-
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
38279
|
-
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
38280
|
-
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
38281
|
-
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
38282
|
-
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
38283
|
-
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
38284
|
-
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
38285
|
-
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
38286
|
-
return 1;
|
|
38287
|
-
}
|
|
38271
|
+
cmd.printInfo = cmd.info; // old name
|
|
38288
38272
|
|
|
38289
|
-
function
|
|
38273
|
+
function getLayerInfo(lyr, dataset) {
|
|
38290
38274
|
var n = getFeatureCount(lyr);
|
|
38291
38275
|
var o = {
|
|
38276
|
+
layer_name: lyr.name,
|
|
38292
38277
|
geometry_type: lyr.geometry_type,
|
|
38293
38278
|
feature_count: n,
|
|
38294
38279
|
null_shape_count: 0,
|
|
@@ -38296,31 +38281,47 @@ ${svg}
|
|
|
38296
38281
|
};
|
|
38297
38282
|
if (lyr.shapes && lyr.shapes.length > 0) {
|
|
38298
38283
|
o.null_shape_count = countNullShapes(lyr.shapes);
|
|
38299
|
-
o.bbox =getLayerBounds(lyr, dataset.arcs).toArray();
|
|
38284
|
+
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
38300
38285
|
o.proj4 = getProjInfo(dataset);
|
|
38301
38286
|
}
|
|
38287
|
+
o.source_file = getLayerSourceFile(lyr, dataset) || null;
|
|
38288
|
+
o.attribute_data = getAttributeTableInfo(lyr);
|
|
38302
38289
|
return o;
|
|
38303
38290
|
}
|
|
38304
38291
|
|
|
38305
|
-
//
|
|
38306
|
-
function
|
|
38307
|
-
|
|
38308
|
-
|
|
38309
|
-
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
38292
|
+
// i: (optional) record index
|
|
38293
|
+
function getAttributeTableInfo(lyr, i) {
|
|
38294
|
+
if (!lyr.data || lyr.data.size() === 0 || lyr.data.getFields().length === 0) {
|
|
38295
|
+
return null;
|
|
38310
38296
|
}
|
|
38311
|
-
|
|
38297
|
+
var fields = applyFieldOrder(lyr.data.getFields(), 'ascending');
|
|
38298
|
+
var valueName = i === undefined ? 'first_value' : 'value';
|
|
38299
|
+
return fields.map(function(fname) {
|
|
38300
|
+
return {
|
|
38301
|
+
field: fname,
|
|
38302
|
+
[valueName]: lyr.data.getReadOnlyRecordAt(i || 0)[fname]
|
|
38303
|
+
};
|
|
38304
|
+
});
|
|
38312
38305
|
}
|
|
38313
38306
|
|
|
38314
|
-
function
|
|
38315
|
-
var
|
|
38316
|
-
|
|
38317
|
-
|
|
38318
|
-
|
|
38319
|
-
|
|
38307
|
+
function formatInfo(arr) {
|
|
38308
|
+
var str = '';
|
|
38309
|
+
arr.forEach(function(info, i) {
|
|
38310
|
+
var title = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
38311
|
+
var tableStr = formatAttributeTableInfo(info.attribute_data);
|
|
38312
|
+
var tableWidth = measureLongestLine(tableStr);
|
|
38313
|
+
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
38314
|
+
str += '\n';
|
|
38315
|
+
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
38316
|
+
str += title + '\n';
|
|
38317
|
+
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
38318
|
+
str += formatLayerInfo(info);
|
|
38319
|
+
str += tableStr;
|
|
38320
|
+
});
|
|
38321
|
+
return str;
|
|
38320
38322
|
}
|
|
38321
38323
|
|
|
38322
|
-
function
|
|
38323
|
-
var data = getLayerData(lyr, dataset);
|
|
38324
|
+
function formatLayerInfo(data) {
|
|
38324
38325
|
var str = '';
|
|
38325
38326
|
str += "Type: " + (data.geometry_type || "tabular data") + "\n";
|
|
38326
38327
|
str += utils.format("Records: %,d\n",data.feature_count);
|
|
@@ -38331,21 +38332,19 @@ ${svg}
|
|
|
38331
38332
|
str += "Bounds: " + data.bbox.join(',') + "\n";
|
|
38332
38333
|
str += "CRS: " + data.proj4 + "\n";
|
|
38333
38334
|
}
|
|
38334
|
-
str += "Source: " + (
|
|
38335
|
+
str += "Source: " + (data.source_file || 'n/a') + "\n";
|
|
38335
38336
|
return str;
|
|
38336
38337
|
}
|
|
38337
38338
|
|
|
38338
|
-
function
|
|
38339
|
-
if (!
|
|
38340
|
-
|
|
38341
|
-
|
|
38342
|
-
|
|
38343
|
-
|
|
38344
|
-
|
|
38345
|
-
|
|
38346
|
-
|
|
38347
|
-
var vals = fields.map(function(fname) {
|
|
38348
|
-
return data.getReadOnlyRecordAt(i || 0)[fname];
|
|
38339
|
+
function formatAttributeTableInfo(arr) {
|
|
38340
|
+
if (!arr) return "Attribute data: [none]\n";
|
|
38341
|
+
var header = "\nAttribute data\n";
|
|
38342
|
+
var valKey = 'first_value' in arr[0] ? 'first_value' : 'value';
|
|
38343
|
+
var vals = [];
|
|
38344
|
+
var fields = [];
|
|
38345
|
+
arr.forEach(function(o) {
|
|
38346
|
+
fields.push(o.field);
|
|
38347
|
+
vals.push(o[valKey]);
|
|
38349
38348
|
});
|
|
38350
38349
|
var maxIntegralChars = vals.reduce(function(max, val) {
|
|
38351
38350
|
if (utils.isNumber(val)) {
|
|
@@ -38357,20 +38356,66 @@ ${svg}
|
|
|
38357
38356
|
var col2Arr = vals.reduce(function(memo, val) {
|
|
38358
38357
|
memo.push(formatTableValue(val, maxIntegralChars));
|
|
38359
38358
|
return memo;
|
|
38360
|
-
}, [
|
|
38359
|
+
}, [valKey == 'first_value' ? 'First value' : 'Value']);
|
|
38361
38360
|
var col1Chars = maxChars(col1Arr);
|
|
38362
38361
|
var col2Chars = maxChars(col2Arr);
|
|
38363
38362
|
var sepStr = (utils.rpad('', col1Chars + 2, '-') + '+' +
|
|
38364
38363
|
utils.rpad('', col2Chars + 2, '-')).substr(0, MAX_RULE_LEN);
|
|
38365
38364
|
var sepLine = sepStr + '\n';
|
|
38366
|
-
var table =
|
|
38365
|
+
var table = '';
|
|
38367
38366
|
col1Arr.forEach(function(col1, i) {
|
|
38368
38367
|
var w = stringDisplayWidth(col1);
|
|
38369
38368
|
table += ' ' + col1 + utils.rpad('', col1Chars - w, ' ') + ' | ' +
|
|
38370
38369
|
col2Arr[i] + '\n';
|
|
38371
38370
|
if (i === 0) table += sepLine; // separator after first line
|
|
38372
38371
|
});
|
|
38373
|
-
return table + sepLine;
|
|
38372
|
+
return header + sepLine + table + sepLine;
|
|
38373
|
+
}
|
|
38374
|
+
|
|
38375
|
+
function measureLongestLine(str) {
|
|
38376
|
+
return Math.max.apply(null, str.split('\n').map(function(line) {return stringDisplayWidth(line);}));
|
|
38377
|
+
}
|
|
38378
|
+
|
|
38379
|
+
function stringDisplayWidth(str) {
|
|
38380
|
+
var w = 0;
|
|
38381
|
+
for (var i = 0, n=str.length; i < n; i++) {
|
|
38382
|
+
w += charDisplayWidth(str.charCodeAt(i));
|
|
38383
|
+
}
|
|
38384
|
+
return w;
|
|
38385
|
+
}
|
|
38386
|
+
|
|
38387
|
+
// see https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
|
38388
|
+
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
38389
|
+
function charDisplayWidth(c) {
|
|
38390
|
+
if (c >= 0x1100 &&
|
|
38391
|
+
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
38392
|
+
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
38393
|
+
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
38394
|
+
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
38395
|
+
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
38396
|
+
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
38397
|
+
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
38398
|
+
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
38399
|
+
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
38400
|
+
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
38401
|
+
return 1;
|
|
38402
|
+
}
|
|
38403
|
+
|
|
38404
|
+
// TODO: consider polygons with zero area or other invalid geometries
|
|
38405
|
+
function countNullShapes(shapes) {
|
|
38406
|
+
var count = 0;
|
|
38407
|
+
for (var i=0; i<shapes.length; i++) {
|
|
38408
|
+
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
38409
|
+
}
|
|
38410
|
+
return count;
|
|
38411
|
+
}
|
|
38412
|
+
|
|
38413
|
+
function countNullRecords(records) {
|
|
38414
|
+
var count = 0;
|
|
38415
|
+
for (var i=0; i<records.length; i++) {
|
|
38416
|
+
if (!records[i]) count++;
|
|
38417
|
+
}
|
|
38418
|
+
return count;
|
|
38374
38419
|
}
|
|
38375
38420
|
|
|
38376
38421
|
function maxChars(arr) {
|
|
@@ -38424,8 +38469,9 @@ ${svg}
|
|
|
38424
38469
|
|
|
38425
38470
|
var Info = /*#__PURE__*/Object.freeze({
|
|
38426
38471
|
__proto__: null,
|
|
38427
|
-
|
|
38472
|
+
getLayerInfo: getLayerInfo,
|
|
38428
38473
|
getAttributeTableInfo: getAttributeTableInfo,
|
|
38474
|
+
formatAttributeTableInfo: formatAttributeTableInfo,
|
|
38429
38475
|
formatTableValue: formatTableValue
|
|
38430
38476
|
});
|
|
38431
38477
|
|
|
@@ -38477,7 +38523,7 @@ ${svg}
|
|
|
38477
38523
|
function getFeatureInfo(id, lyr, arcs) {
|
|
38478
38524
|
var msg = "Feature " + id + '\n';
|
|
38479
38525
|
msg += getShapeInfo(id, lyr, arcs);
|
|
38480
|
-
msg += getAttributeTableInfo(lyr, id);
|
|
38526
|
+
msg += formatAttributeTableInfo(getAttributeTableInfo(lyr, id));
|
|
38481
38527
|
return msg;
|
|
38482
38528
|
}
|
|
38483
38529
|
|
|
@@ -40589,7 +40635,7 @@ ${svg}
|
|
|
40589
40635
|
|
|
40590
40636
|
function getRunCommandData(target) {
|
|
40591
40637
|
var lyr = target.layers[0];
|
|
40592
|
-
var data =
|
|
40638
|
+
var data = getLayerInfo(lyr, target.dataset);
|
|
40593
40639
|
data.layer = lyr;
|
|
40594
40640
|
data.dataset = target.dataset;
|
|
40595
40641
|
return data;
|
|
@@ -42939,7 +42985,7 @@ ${svg}
|
|
|
42939
42985
|
cmd.include(opts);
|
|
42940
42986
|
|
|
42941
42987
|
} else if (name == 'info') {
|
|
42942
|
-
cmd.
|
|
42988
|
+
cmd.info(targets, opts);
|
|
42943
42989
|
|
|
42944
42990
|
} else if (name == 'inlay') {
|
|
42945
42991
|
outputLayers = cmd.inlay(targetLayers, source, targetDataset, opts);
|
|
@@ -43305,13 +43351,13 @@ ${svg}
|
|
|
43305
43351
|
commands = runAndRemoveInfoCommands(commands);
|
|
43306
43352
|
if (commands.length === 0) return done(null);
|
|
43307
43353
|
|
|
43308
|
-
// add options to -i -o -join -clip -erase commands to bypass file i/o
|
|
43354
|
+
// add options to -i -o -join -clip -erase etc. commands to bypass file i/o
|
|
43309
43355
|
// TODO: find a less kludgy solution
|
|
43310
43356
|
commands.forEach(function(cmd) {
|
|
43311
43357
|
if (commandTakesFileInput(cmd.name) && inputObj) {
|
|
43312
43358
|
cmd.options.input = inputObj;
|
|
43313
43359
|
}
|
|
43314
|
-
if (cmd.name == 'o' &&
|
|
43360
|
+
if (outputArr && (cmd.name == 'o' || cmd.name == 'info' && cmd.options.save_to)) {
|
|
43315
43361
|
cmd.options.output = outputArr;
|
|
43316
43362
|
}
|
|
43317
43363
|
});
|
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -1437,7 +1437,9 @@
|
|
|
1437
1437
|
closeMenu(100);
|
|
1438
1438
|
}).text('restore');
|
|
1439
1439
|
El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
|
|
1440
|
-
var
|
|
1440
|
+
var obj = await idb.get(item.id);
|
|
1441
|
+
await internal.applyCompression(obj, {consume: true});
|
|
1442
|
+
var buf = internal.pack(obj);
|
|
1441
1443
|
saveBlobToLocalFile('mapshaper_snapshot.msx', new Blob([buf]));
|
|
1442
1444
|
}).text('export');
|
|
1443
1445
|
El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
|
|
@@ -1485,20 +1487,24 @@
|
|
|
1485
1487
|
}
|
|
1486
1488
|
|
|
1487
1489
|
async function saveSnapshot(gui) {
|
|
1488
|
-
var
|
|
1490
|
+
var obj = await captureSnapshot(gui);
|
|
1491
|
+
// storing an unpacked object is usually a bit faster (~20%)
|
|
1492
|
+
// note: we don't know the size of unpacked snapshot objects
|
|
1493
|
+
// obj = internal.pack(obj);
|
|
1489
1494
|
var entryId = String(++snapshotCount).padStart(3, '0');
|
|
1490
1495
|
var snapshotId = sessionId + '_' + entryId; // e.g. session_d89fw_001
|
|
1496
|
+
var size = obj.length;
|
|
1491
1497
|
var entry = {
|
|
1492
1498
|
created: Date.now(),
|
|
1493
1499
|
session: sessionId,
|
|
1494
1500
|
id: snapshotId,
|
|
1495
1501
|
name: snapshotCount + '.',
|
|
1496
1502
|
number: snapshotCount,
|
|
1497
|
-
size:
|
|
1498
|
-
display_size: formatSize(
|
|
1503
|
+
size: size,
|
|
1504
|
+
display_size: formatSize(size)
|
|
1499
1505
|
};
|
|
1500
1506
|
|
|
1501
|
-
await idb.set(entry.id,
|
|
1507
|
+
await idb.set(entry.id, obj);
|
|
1502
1508
|
await addToIndex(entry);
|
|
1503
1509
|
renderMenu();
|
|
1504
1510
|
}
|
|
@@ -1507,9 +1513,8 @@
|
|
|
1507
1513
|
function formatSize(bytes) {
|
|
1508
1514
|
var kb = Math.round(bytes / 1000);
|
|
1509
1515
|
var mb = (bytes / 1e6).toFixed(1);
|
|
1510
|
-
if (kb
|
|
1511
|
-
|
|
1512
|
-
}
|
|
1516
|
+
if (!kb) return '';
|
|
1517
|
+
if (kb < 990) return kb + 'kB';
|
|
1513
1518
|
return mb + 'MB';
|
|
1514
1519
|
}
|
|
1515
1520
|
|
|
@@ -1531,13 +1536,13 @@
|
|
|
1531
1536
|
}
|
|
1532
1537
|
|
|
1533
1538
|
async function restoreSnapshotById(id, gui) {
|
|
1534
|
-
var
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1539
|
+
var data;
|
|
1540
|
+
try {
|
|
1541
|
+
data = await internal.restoreSessionData(await idb.get(id));
|
|
1542
|
+
} catch(e) {
|
|
1543
|
+
console.error(e);
|
|
1544
|
+
stop$1('Snapshot is not available');
|
|
1538
1545
|
}
|
|
1539
|
-
var data = await internal.unpackSession(buf);
|
|
1540
|
-
buf = null;
|
|
1541
1546
|
gui.model.clear();
|
|
1542
1547
|
importDatasets(data.datasets, gui);
|
|
1543
1548
|
gui.clearMode();
|
|
@@ -1550,7 +1555,7 @@
|
|
|
1550
1555
|
if (buf instanceof ArrayBuffer) {
|
|
1551
1556
|
buf = new Uint8Array(buf);
|
|
1552
1557
|
}
|
|
1553
|
-
var data = await internal.
|
|
1558
|
+
var data = await internal.unpackSessionData(buf);
|
|
1554
1559
|
importDatasets(data.datasets, gui);
|
|
1555
1560
|
}
|
|
1556
1561
|
|
|
@@ -1573,7 +1578,7 @@
|
|
|
1573
1578
|
// console.timeEnd('msx')
|
|
1574
1579
|
delete lyr.active;
|
|
1575
1580
|
obj.gui = getGuiState(gui);
|
|
1576
|
-
return
|
|
1581
|
+
return obj;
|
|
1577
1582
|
}
|
|
1578
1583
|
|
|
1579
1584
|
// TODO: capture gui state information to allow restoring more of the UI
|
|
@@ -3040,22 +3045,12 @@
|
|
|
3040
3045
|
}
|
|
3041
3046
|
|
|
3042
3047
|
function getHistory() {
|
|
3043
|
-
|
|
3044
|
-
try {
|
|
3045
|
-
hist = JSON.parse(window.localStorage.getItem('console_history'));
|
|
3046
|
-
} catch(e) {
|
|
3047
|
-
}
|
|
3048
|
-
return hist && hist.length > 0 ? hist : [];
|
|
3048
|
+
return GUI.getSavedValue('console_history') || [];
|
|
3049
3049
|
}
|
|
3050
3050
|
|
|
3051
3051
|
function saveHistory() {
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
if (history.length) {
|
|
3055
|
-
window.localStorage.setItem('console_history', JSON.stringify(history.slice(-50)));
|
|
3056
|
-
}
|
|
3057
|
-
} catch(e) {
|
|
3058
|
-
}
|
|
3052
|
+
history = history.filter(Boolean); // TODO: fix condition that leaves a blank line on the history
|
|
3053
|
+
GUI.setSavedValue('console_history', history.slice(-100));
|
|
3059
3054
|
}
|
|
3060
3055
|
|
|
3061
3056
|
function toLog(str, cname) {
|
|
@@ -3678,7 +3673,13 @@
|
|
|
3678
3673
|
gui.addMode('export', turnOn, turnOff, exportBtn);
|
|
3679
3674
|
gui.keyboard.onMenuSubmit(menu, onExportClick);
|
|
3680
3675
|
if (window.showSaveFilePicker) {
|
|
3681
|
-
menu.findChild('#save-preference')
|
|
3676
|
+
menu.findChild('#save-preference')
|
|
3677
|
+
.css('display', 'inline-block')
|
|
3678
|
+
.findChild('input')
|
|
3679
|
+
.on('change', function() {
|
|
3680
|
+
GUI.setSavedValue('choose-save-dir', this.checked);
|
|
3681
|
+
})
|
|
3682
|
+
.attr('checked', GUI.getSavedValue('choose-save-dir') || false);
|
|
3682
3683
|
}
|
|
3683
3684
|
|
|
3684
3685
|
function turnOn() {
|
|
@@ -3702,8 +3703,6 @@
|
|
|
3702
3703
|
|
|
3703
3704
|
function onExportClick() {
|
|
3704
3705
|
var layers = getSelectedLayers();
|
|
3705
|
-
var chooseDir = menu.findChild('#save-preference input').node().checked;
|
|
3706
|
-
GUI.setSavedValue('choose-save-dir', chooseDir);
|
|
3707
3706
|
if (layers.length === 0) {
|
|
3708
3707
|
return gui.alert('No layers were selected');
|
|
3709
3708
|
}
|
|
@@ -9797,19 +9796,26 @@
|
|
|
9797
9796
|
bx = t.bx,
|
|
9798
9797
|
by = t.by;
|
|
9799
9798
|
var x, y, xp, yp;
|
|
9799
|
+
var count = 0;
|
|
9800
9800
|
if (!vec.hasNext()) return;
|
|
9801
|
-
x =
|
|
9802
|
-
y =
|
|
9801
|
+
x = round(vec.x * mx + bx);
|
|
9802
|
+
y = round(vec.y * my + by);
|
|
9803
9803
|
ctx.moveTo(x, y);
|
|
9804
9804
|
while (vec.hasNext()) {
|
|
9805
|
+
xp = x;
|
|
9806
|
+
yp = y;
|
|
9805
9807
|
x = round(vec.x * mx + bx);
|
|
9806
9808
|
y = round(vec.y * my + by);
|
|
9807
9809
|
if (x != xp || y != yp) {
|
|
9808
9810
|
ctx.lineTo(x, y);
|
|
9809
|
-
|
|
9810
|
-
yp = y;
|
|
9811
|
+
count++;
|
|
9811
9812
|
}
|
|
9812
9813
|
}
|
|
9814
|
+
if (count === 0) {
|
|
9815
|
+
// draw a tiny line if all coords round to the same location,
|
|
9816
|
+
// so tiny shapes with strokes will consistently be drawn as dots,
|
|
9817
|
+
ctx.lineTo(x + 0.1, y);
|
|
9818
|
+
}
|
|
9813
9819
|
}
|
|
9814
9820
|
|
|
9815
9821
|
function roundToPix(x) {
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.24";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -10620,7 +10620,8 @@
|
|
|
10620
10620
|
buf = new Uint8Array(buf);
|
|
10621
10621
|
}
|
|
10622
10622
|
opts = opts || {};
|
|
10623
|
-
var
|
|
10623
|
+
var gunzip$1 = runningInBrowser() ? utils.promisify(gunzip) : utils.promisify(require('zlib').gunzip);
|
|
10624
|
+
var out = await gunzip$1(buf, opts);
|
|
10624
10625
|
if (opts.filename && !isImportableAsBinary(opts.filename)) {
|
|
10625
10626
|
out = strFromU8(out);
|
|
10626
10627
|
}
|
|
@@ -10628,8 +10629,6 @@
|
|
|
10628
10629
|
}
|
|
10629
10630
|
|
|
10630
10631
|
function gunzipSync(buf, filename) {
|
|
10631
|
-
// TODO: use native module in Node
|
|
10632
|
-
// require('zlib').
|
|
10633
10632
|
if (buf instanceof ArrayBuffer) {
|
|
10634
10633
|
buf = new Uint8Array(buf);
|
|
10635
10634
|
}
|
|
@@ -10768,16 +10767,39 @@
|
|
|
10768
10767
|
// gui: (optional) gui instance
|
|
10769
10768
|
//
|
|
10770
10769
|
async function exportDatasetsToPack(datasets, opts) {
|
|
10771
|
-
|
|
10770
|
+
var obj = {
|
|
10772
10771
|
version: 1,
|
|
10773
10772
|
created: (new Date).toISOString(),
|
|
10774
|
-
datasets: await Promise.all(datasets.map(
|
|
10773
|
+
datasets: await Promise.all(datasets.map(exportDataset))
|
|
10775
10774
|
};
|
|
10775
|
+
if (opts.compact) {
|
|
10776
|
+
await applyCompression(obj);
|
|
10777
|
+
}
|
|
10778
|
+
return obj;
|
|
10779
|
+
}
|
|
10780
|
+
|
|
10781
|
+
async function applyCompression(obj, opts) {
|
|
10782
|
+
var promises = [];
|
|
10783
|
+
obj.datasets.forEach(d => {
|
|
10784
|
+
if (d.arcs) promises.push(compressArcs(d.arcs, opts));
|
|
10785
|
+
});
|
|
10786
|
+
await Promise.all(promises);
|
|
10787
|
+
}
|
|
10788
|
+
|
|
10789
|
+
async function compressArcs(obj, opts) {
|
|
10790
|
+
var gzipOpts = Object.assign({level: 1, consume: false}, opts);
|
|
10791
|
+
var promises = [gzipAsync(obj.nn, gzipOpts), gzipAsync(obj.xx, gzipOpts), gzipAsync(obj.yy, gzipOpts)];
|
|
10792
|
+
if (obj.zz) promises.push(gzipAsync(obj.zz, gzipOpts));
|
|
10793
|
+
var results = await Promise.all(promises);
|
|
10794
|
+
obj.nn = results.shift();
|
|
10795
|
+
obj.xx = results.shift();
|
|
10796
|
+
obj.yy = results.shift();
|
|
10797
|
+
if (obj.zz) obj.zz = results.shift();
|
|
10776
10798
|
}
|
|
10777
10799
|
|
|
10778
10800
|
async function exportDataset(dataset, opts) {
|
|
10779
10801
|
return {
|
|
10780
|
-
arcs: dataset.arcs ?
|
|
10802
|
+
arcs: dataset.arcs ? exportArcs(dataset.arcs) : null,
|
|
10781
10803
|
info: dataset.info ? exportInfo(dataset.info) : null,
|
|
10782
10804
|
layers: await Promise.all((dataset.layers || []).map(exportLayer))
|
|
10783
10805
|
};
|
|
@@ -10787,38 +10809,22 @@
|
|
|
10787
10809
|
return new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
10788
10810
|
}
|
|
10789
10811
|
|
|
10790
|
-
|
|
10812
|
+
function exportArcs(arcs) {
|
|
10791
10813
|
var data = arcs.getVertexData();
|
|
10792
|
-
|
|
10814
|
+
return {
|
|
10793
10815
|
nn: typedArrayToBuffer(data.nn),
|
|
10794
10816
|
xx: typedArrayToBuffer(data.xx),
|
|
10795
10817
|
yy: typedArrayToBuffer(data.yy),
|
|
10796
10818
|
zz: data.zz ? typedArrayToBuffer(data.zz) : null,
|
|
10797
10819
|
zlimit: arcs.getRetainedInterval()
|
|
10798
10820
|
};
|
|
10799
|
-
|
|
10800
|
-
// gzipping typically sees about 70% compression on unrounded coordinates
|
|
10801
|
-
// -- possibly not worth the time
|
|
10802
|
-
if (opts.compact) {
|
|
10803
|
-
var gzipOpts = {level: 1, consume: false};
|
|
10804
|
-
var promises = [gzipAsync(obj.nn, gzipOpts), gzipAsync(obj.xx, gzipOpts), gzipAsync(obj.yy, gzipOpts)];
|
|
10805
|
-
if (obj.zz) promises.push(gzipAsync(obj.zz, gzipOpts));
|
|
10806
|
-
var results = await Promise.all(promises);
|
|
10807
|
-
obj.nn = results.shift();
|
|
10808
|
-
obj.xx = results.shift();
|
|
10809
|
-
obj.yy = results.shift();
|
|
10810
|
-
if (obj.zz) obj.zz = results.shift();
|
|
10811
|
-
}
|
|
10812
|
-
return obj;
|
|
10813
10821
|
}
|
|
10814
10822
|
|
|
10815
10823
|
async function exportLayer(lyr) {
|
|
10816
|
-
// console.time('table')
|
|
10817
10824
|
var data = null;
|
|
10818
10825
|
if (lyr.data) {
|
|
10819
10826
|
data = await exportTable2(lyr.data);
|
|
10820
10827
|
}
|
|
10821
|
-
// console.timeEnd('table')
|
|
10822
10828
|
return {
|
|
10823
10829
|
name: lyr.name || null,
|
|
10824
10830
|
geometry_type: lyr.geometry_type || null,
|
|
@@ -10845,6 +10851,7 @@
|
|
|
10845
10851
|
exportPackedDatasets: exportPackedDatasets,
|
|
10846
10852
|
pack: pack,
|
|
10847
10853
|
exportDatasetsToPack: exportDatasetsToPack,
|
|
10854
|
+
applyCompression: applyCompression,
|
|
10848
10855
|
exportDataset: exportDataset
|
|
10849
10856
|
});
|
|
10850
10857
|
|
|
@@ -24922,6 +24929,9 @@ ${svg}
|
|
|
24922
24929
|
|
|
24923
24930
|
parser.command('info')
|
|
24924
24931
|
.describe('print information about data layers')
|
|
24932
|
+
.option('save-to', {
|
|
24933
|
+
describe: 'name of file to save info in JSON format'
|
|
24934
|
+
})
|
|
24925
24935
|
.option('target', targetOpt);
|
|
24926
24936
|
|
|
24927
24937
|
parser.command('inspect')
|
|
@@ -27457,12 +27467,14 @@ ${svg}
|
|
|
27457
27467
|
// Import datasets contained in a BSON blob
|
|
27458
27468
|
// Return command target as a dataset
|
|
27459
27469
|
//
|
|
27460
|
-
async function
|
|
27461
|
-
|
|
27470
|
+
async function unpackSessionData(buf) {
|
|
27471
|
+
return restoreSessionData(unpack(buf, {}));
|
|
27472
|
+
}
|
|
27473
|
+
|
|
27474
|
+
async function restoreSessionData(obj) {
|
|
27462
27475
|
if (!isValidSession(obj)) {
|
|
27463
27476
|
stop('Invalid mapshaper session data object');
|
|
27464
27477
|
}
|
|
27465
|
-
|
|
27466
27478
|
var datasets = await Promise.all(obj.datasets.map(importDataset));
|
|
27467
27479
|
return Object.assign(obj, {datasets: datasets});
|
|
27468
27480
|
}
|
|
@@ -27539,7 +27551,8 @@ ${svg}
|
|
|
27539
27551
|
|
|
27540
27552
|
var Unpack = /*#__PURE__*/Object.freeze({
|
|
27541
27553
|
__proto__: null,
|
|
27542
|
-
|
|
27554
|
+
unpackSessionData: unpackSessionData,
|
|
27555
|
+
restoreSessionData: restoreSessionData
|
|
27543
27556
|
});
|
|
27544
27557
|
|
|
27545
27558
|
cmd.importFiles = async function(catalog, opts) {
|
|
@@ -27593,7 +27606,7 @@ ${svg}
|
|
|
27593
27606
|
|
|
27594
27607
|
async function importMshpFile(file, catalog, opts) {
|
|
27595
27608
|
var buf = cli.readFile(file, null, opts.input);
|
|
27596
|
-
var obj = await
|
|
27609
|
+
var obj = await unpackSessionData(buf);
|
|
27597
27610
|
obj.datasets.forEach(catalog.addDataset, catalog);
|
|
27598
27611
|
return obj.target;
|
|
27599
27612
|
}
|
|
@@ -38240,55 +38253,27 @@ ${svg}
|
|
|
38240
38253
|
|
|
38241
38254
|
var MAX_RULE_LEN = 50;
|
|
38242
38255
|
|
|
38243
|
-
cmd.
|
|
38244
|
-
var
|
|
38245
|
-
layers.
|
|
38246
|
-
|
|
38247
|
-
var tableStr = getAttributeTableInfo(o.layer);
|
|
38248
|
-
var tableWidth = measureLongestLine(tableStr);
|
|
38249
|
-
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
38250
|
-
str += '\n';
|
|
38251
|
-
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
38252
|
-
str += title + '\n';
|
|
38253
|
-
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
38254
|
-
str += getLayerInfo(o.layer, o.dataset);
|
|
38255
|
-
str += tableStr;
|
|
38256
|
+
cmd.info = function(targets, opts) {
|
|
38257
|
+
var layers = expandCommandTargets(targets);
|
|
38258
|
+
var arr = layers.map(function(o) {
|
|
38259
|
+
return getLayerInfo(o.layer, o.dataset);
|
|
38256
38260
|
});
|
|
38257
|
-
message(
|
|
38258
|
-
|
|
38259
|
-
|
|
38260
|
-
|
|
38261
|
-
|
|
38262
|
-
|
|
38263
|
-
|
|
38264
|
-
function stringDisplayWidth(str) {
|
|
38265
|
-
var w = 0;
|
|
38266
|
-
for (var i = 0, n=str.length; i < n; i++) {
|
|
38267
|
-
w += charDisplayWidth(str.charCodeAt(i));
|
|
38261
|
+
message(formatInfo(arr));
|
|
38262
|
+
if (opts.save_to) {
|
|
38263
|
+
var output = [{
|
|
38264
|
+
filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
|
|
38265
|
+
content: JSON.stringify(arr, null, 2)
|
|
38266
|
+
}];
|
|
38267
|
+
writeFiles(output, opts);
|
|
38268
38268
|
}
|
|
38269
|
-
|
|
38270
|
-
}
|
|
38269
|
+
};
|
|
38271
38270
|
|
|
38272
|
-
//
|
|
38273
|
-
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
38274
|
-
function charDisplayWidth(c) {
|
|
38275
|
-
if (c >= 0x1100 &&
|
|
38276
|
-
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
38277
|
-
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
38278
|
-
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
38279
|
-
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
38280
|
-
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
38281
|
-
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
38282
|
-
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
38283
|
-
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
38284
|
-
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
38285
|
-
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
38286
|
-
return 1;
|
|
38287
|
-
}
|
|
38271
|
+
cmd.printInfo = cmd.info; // old name
|
|
38288
38272
|
|
|
38289
|
-
function
|
|
38273
|
+
function getLayerInfo(lyr, dataset) {
|
|
38290
38274
|
var n = getFeatureCount(lyr);
|
|
38291
38275
|
var o = {
|
|
38276
|
+
layer_name: lyr.name,
|
|
38292
38277
|
geometry_type: lyr.geometry_type,
|
|
38293
38278
|
feature_count: n,
|
|
38294
38279
|
null_shape_count: 0,
|
|
@@ -38296,31 +38281,47 @@ ${svg}
|
|
|
38296
38281
|
};
|
|
38297
38282
|
if (lyr.shapes && lyr.shapes.length > 0) {
|
|
38298
38283
|
o.null_shape_count = countNullShapes(lyr.shapes);
|
|
38299
|
-
o.bbox =getLayerBounds(lyr, dataset.arcs).toArray();
|
|
38284
|
+
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
38300
38285
|
o.proj4 = getProjInfo(dataset);
|
|
38301
38286
|
}
|
|
38287
|
+
o.source_file = getLayerSourceFile(lyr, dataset) || null;
|
|
38288
|
+
o.attribute_data = getAttributeTableInfo(lyr);
|
|
38302
38289
|
return o;
|
|
38303
38290
|
}
|
|
38304
38291
|
|
|
38305
|
-
//
|
|
38306
|
-
function
|
|
38307
|
-
|
|
38308
|
-
|
|
38309
|
-
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
38292
|
+
// i: (optional) record index
|
|
38293
|
+
function getAttributeTableInfo(lyr, i) {
|
|
38294
|
+
if (!lyr.data || lyr.data.size() === 0 || lyr.data.getFields().length === 0) {
|
|
38295
|
+
return null;
|
|
38310
38296
|
}
|
|
38311
|
-
|
|
38297
|
+
var fields = applyFieldOrder(lyr.data.getFields(), 'ascending');
|
|
38298
|
+
var valueName = i === undefined ? 'first_value' : 'value';
|
|
38299
|
+
return fields.map(function(fname) {
|
|
38300
|
+
return {
|
|
38301
|
+
field: fname,
|
|
38302
|
+
[valueName]: lyr.data.getReadOnlyRecordAt(i || 0)[fname]
|
|
38303
|
+
};
|
|
38304
|
+
});
|
|
38312
38305
|
}
|
|
38313
38306
|
|
|
38314
|
-
function
|
|
38315
|
-
var
|
|
38316
|
-
|
|
38317
|
-
|
|
38318
|
-
|
|
38319
|
-
|
|
38307
|
+
function formatInfo(arr) {
|
|
38308
|
+
var str = '';
|
|
38309
|
+
arr.forEach(function(info, i) {
|
|
38310
|
+
var title = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
38311
|
+
var tableStr = formatAttributeTableInfo(info.attribute_data);
|
|
38312
|
+
var tableWidth = measureLongestLine(tableStr);
|
|
38313
|
+
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
38314
|
+
str += '\n';
|
|
38315
|
+
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
38316
|
+
str += title + '\n';
|
|
38317
|
+
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
38318
|
+
str += formatLayerInfo(info);
|
|
38319
|
+
str += tableStr;
|
|
38320
|
+
});
|
|
38321
|
+
return str;
|
|
38320
38322
|
}
|
|
38321
38323
|
|
|
38322
|
-
function
|
|
38323
|
-
var data = getLayerData(lyr, dataset);
|
|
38324
|
+
function formatLayerInfo(data) {
|
|
38324
38325
|
var str = '';
|
|
38325
38326
|
str += "Type: " + (data.geometry_type || "tabular data") + "\n";
|
|
38326
38327
|
str += utils.format("Records: %,d\n",data.feature_count);
|
|
@@ -38331,21 +38332,19 @@ ${svg}
|
|
|
38331
38332
|
str += "Bounds: " + data.bbox.join(',') + "\n";
|
|
38332
38333
|
str += "CRS: " + data.proj4 + "\n";
|
|
38333
38334
|
}
|
|
38334
|
-
str += "Source: " + (
|
|
38335
|
+
str += "Source: " + (data.source_file || 'n/a') + "\n";
|
|
38335
38336
|
return str;
|
|
38336
38337
|
}
|
|
38337
38338
|
|
|
38338
|
-
function
|
|
38339
|
-
if (!
|
|
38340
|
-
|
|
38341
|
-
|
|
38342
|
-
|
|
38343
|
-
|
|
38344
|
-
|
|
38345
|
-
|
|
38346
|
-
|
|
38347
|
-
var vals = fields.map(function(fname) {
|
|
38348
|
-
return data.getReadOnlyRecordAt(i || 0)[fname];
|
|
38339
|
+
function formatAttributeTableInfo(arr) {
|
|
38340
|
+
if (!arr) return "Attribute data: [none]\n";
|
|
38341
|
+
var header = "\nAttribute data\n";
|
|
38342
|
+
var valKey = 'first_value' in arr[0] ? 'first_value' : 'value';
|
|
38343
|
+
var vals = [];
|
|
38344
|
+
var fields = [];
|
|
38345
|
+
arr.forEach(function(o) {
|
|
38346
|
+
fields.push(o.field);
|
|
38347
|
+
vals.push(o[valKey]);
|
|
38349
38348
|
});
|
|
38350
38349
|
var maxIntegralChars = vals.reduce(function(max, val) {
|
|
38351
38350
|
if (utils.isNumber(val)) {
|
|
@@ -38357,20 +38356,66 @@ ${svg}
|
|
|
38357
38356
|
var col2Arr = vals.reduce(function(memo, val) {
|
|
38358
38357
|
memo.push(formatTableValue(val, maxIntegralChars));
|
|
38359
38358
|
return memo;
|
|
38360
|
-
}, [
|
|
38359
|
+
}, [valKey == 'first_value' ? 'First value' : 'Value']);
|
|
38361
38360
|
var col1Chars = maxChars(col1Arr);
|
|
38362
38361
|
var col2Chars = maxChars(col2Arr);
|
|
38363
38362
|
var sepStr = (utils.rpad('', col1Chars + 2, '-') + '+' +
|
|
38364
38363
|
utils.rpad('', col2Chars + 2, '-')).substr(0, MAX_RULE_LEN);
|
|
38365
38364
|
var sepLine = sepStr + '\n';
|
|
38366
|
-
var table =
|
|
38365
|
+
var table = '';
|
|
38367
38366
|
col1Arr.forEach(function(col1, i) {
|
|
38368
38367
|
var w = stringDisplayWidth(col1);
|
|
38369
38368
|
table += ' ' + col1 + utils.rpad('', col1Chars - w, ' ') + ' | ' +
|
|
38370
38369
|
col2Arr[i] + '\n';
|
|
38371
38370
|
if (i === 0) table += sepLine; // separator after first line
|
|
38372
38371
|
});
|
|
38373
|
-
return table + sepLine;
|
|
38372
|
+
return header + sepLine + table + sepLine;
|
|
38373
|
+
}
|
|
38374
|
+
|
|
38375
|
+
function measureLongestLine(str) {
|
|
38376
|
+
return Math.max.apply(null, str.split('\n').map(function(line) {return stringDisplayWidth(line);}));
|
|
38377
|
+
}
|
|
38378
|
+
|
|
38379
|
+
function stringDisplayWidth(str) {
|
|
38380
|
+
var w = 0;
|
|
38381
|
+
for (var i = 0, n=str.length; i < n; i++) {
|
|
38382
|
+
w += charDisplayWidth(str.charCodeAt(i));
|
|
38383
|
+
}
|
|
38384
|
+
return w;
|
|
38385
|
+
}
|
|
38386
|
+
|
|
38387
|
+
// see https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
|
38388
|
+
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
38389
|
+
function charDisplayWidth(c) {
|
|
38390
|
+
if (c >= 0x1100 &&
|
|
38391
|
+
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
38392
|
+
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
38393
|
+
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
38394
|
+
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
38395
|
+
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
38396
|
+
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
38397
|
+
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
38398
|
+
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
38399
|
+
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
38400
|
+
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
38401
|
+
return 1;
|
|
38402
|
+
}
|
|
38403
|
+
|
|
38404
|
+
// TODO: consider polygons with zero area or other invalid geometries
|
|
38405
|
+
function countNullShapes(shapes) {
|
|
38406
|
+
var count = 0;
|
|
38407
|
+
for (var i=0; i<shapes.length; i++) {
|
|
38408
|
+
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
38409
|
+
}
|
|
38410
|
+
return count;
|
|
38411
|
+
}
|
|
38412
|
+
|
|
38413
|
+
function countNullRecords(records) {
|
|
38414
|
+
var count = 0;
|
|
38415
|
+
for (var i=0; i<records.length; i++) {
|
|
38416
|
+
if (!records[i]) count++;
|
|
38417
|
+
}
|
|
38418
|
+
return count;
|
|
38374
38419
|
}
|
|
38375
38420
|
|
|
38376
38421
|
function maxChars(arr) {
|
|
@@ -38424,8 +38469,9 @@ ${svg}
|
|
|
38424
38469
|
|
|
38425
38470
|
var Info = /*#__PURE__*/Object.freeze({
|
|
38426
38471
|
__proto__: null,
|
|
38427
|
-
|
|
38472
|
+
getLayerInfo: getLayerInfo,
|
|
38428
38473
|
getAttributeTableInfo: getAttributeTableInfo,
|
|
38474
|
+
formatAttributeTableInfo: formatAttributeTableInfo,
|
|
38429
38475
|
formatTableValue: formatTableValue
|
|
38430
38476
|
});
|
|
38431
38477
|
|
|
@@ -38477,7 +38523,7 @@ ${svg}
|
|
|
38477
38523
|
function getFeatureInfo(id, lyr, arcs) {
|
|
38478
38524
|
var msg = "Feature " + id + '\n';
|
|
38479
38525
|
msg += getShapeInfo(id, lyr, arcs);
|
|
38480
|
-
msg += getAttributeTableInfo(lyr, id);
|
|
38526
|
+
msg += formatAttributeTableInfo(getAttributeTableInfo(lyr, id));
|
|
38481
38527
|
return msg;
|
|
38482
38528
|
}
|
|
38483
38529
|
|
|
@@ -40589,7 +40635,7 @@ ${svg}
|
|
|
40589
40635
|
|
|
40590
40636
|
function getRunCommandData(target) {
|
|
40591
40637
|
var lyr = target.layers[0];
|
|
40592
|
-
var data =
|
|
40638
|
+
var data = getLayerInfo(lyr, target.dataset);
|
|
40593
40639
|
data.layer = lyr;
|
|
40594
40640
|
data.dataset = target.dataset;
|
|
40595
40641
|
return data;
|
|
@@ -42939,7 +42985,7 @@ ${svg}
|
|
|
42939
42985
|
cmd.include(opts);
|
|
42940
42986
|
|
|
42941
42987
|
} else if (name == 'info') {
|
|
42942
|
-
cmd.
|
|
42988
|
+
cmd.info(targets, opts);
|
|
42943
42989
|
|
|
42944
42990
|
} else if (name == 'inlay') {
|
|
42945
42991
|
outputLayers = cmd.inlay(targetLayers, source, targetDataset, opts);
|
|
@@ -43305,13 +43351,13 @@ ${svg}
|
|
|
43305
43351
|
commands = runAndRemoveInfoCommands(commands);
|
|
43306
43352
|
if (commands.length === 0) return done(null);
|
|
43307
43353
|
|
|
43308
|
-
// add options to -i -o -join -clip -erase commands to bypass file i/o
|
|
43354
|
+
// add options to -i -o -join -clip -erase etc. commands to bypass file i/o
|
|
43309
43355
|
// TODO: find a less kludgy solution
|
|
43310
43356
|
commands.forEach(function(cmd) {
|
|
43311
43357
|
if (commandTakesFileInput(cmd.name) && inputObj) {
|
|
43312
43358
|
cmd.options.input = inputObj;
|
|
43313
43359
|
}
|
|
43314
|
-
if (cmd.name == 'o' &&
|
|
43360
|
+
if (outputArr && (cmd.name == 'o' || cmd.name == 'info' && cmd.options.save_to)) {
|
|
43315
43361
|
cmd.options.output = outputArr;
|
|
43316
43362
|
}
|
|
43317
43363
|
});
|