mapshaper 0.5.77 → 0.5.78
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 +4 -1
- package/mapshaper.js +230 -37
- package/package.json +2 -2
- package/www/mapshaper-gui.js +8 -9
- package/www/mapshaper.js +230 -37
- package/www/modules.js +21 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
v0.5.78
|
|
2
|
+
* Added support for reading and writing fixed-width text files.
|
|
3
|
+
|
|
1
4
|
v0.5.77
|
|
2
5
|
* Added -dashlines command (formerly -split-lines).
|
|
3
|
-
* Added support for joining polyline and
|
|
6
|
+
* Added support for joining polyline and polygon layers using point-method
|
|
4
7
|
|
|
5
8
|
v0.5.76
|
|
6
9
|
* Fixed bug in mapshaper-gui -q.
|
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.78";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
get initializeArray () { return initializeArray; },
|
|
53
53
|
get replaceArray () { return replaceArray; },
|
|
54
54
|
get repeatString () { return repeatString; },
|
|
55
|
+
get splitLines () { return splitLines; },
|
|
55
56
|
get pluralSuffix () { return pluralSuffix; },
|
|
56
57
|
get endsWith () { return endsWith; },
|
|
57
58
|
get lpad () { return lpad; },
|
|
@@ -61,7 +62,9 @@
|
|
|
61
62
|
get rtrim () { return rtrim; },
|
|
62
63
|
get addThousandsSep () { return addThousandsSep; },
|
|
63
64
|
get numToStr () { return numToStr; },
|
|
64
|
-
get formatNumber () { return formatNumber
|
|
65
|
+
get formatNumber () { return formatNumber; },
|
|
66
|
+
get formatIntlNumber () { return formatIntlNumber; },
|
|
67
|
+
get formatNumberForDisplay () { return formatNumberForDisplay; },
|
|
65
68
|
get shuffle () { return shuffle; },
|
|
66
69
|
get sortOn () { return sortOn; },
|
|
67
70
|
get genericSort () { return genericSort; },
|
|
@@ -532,6 +535,10 @@
|
|
|
532
535
|
return str;
|
|
533
536
|
}
|
|
534
537
|
|
|
538
|
+
function splitLines(str) {
|
|
539
|
+
return str.split(/\r?\n/);
|
|
540
|
+
}
|
|
541
|
+
|
|
535
542
|
function pluralSuffix(count) {
|
|
536
543
|
return count != 1 ? 's' : '';
|
|
537
544
|
}
|
|
@@ -584,7 +591,16 @@
|
|
|
584
591
|
return decimals >= 0 ? num.toFixed(decimals) : String(num);
|
|
585
592
|
}
|
|
586
593
|
|
|
587
|
-
function formatNumber
|
|
594
|
+
function formatNumber(val) {
|
|
595
|
+
return val + '';
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function formatIntlNumber(val) {
|
|
599
|
+
var str = formatNumber(val);
|
|
600
|
+
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function formatNumberForDisplay(num, decimals, nullStr, showPos) {
|
|
588
604
|
var fmt;
|
|
589
605
|
if (isNaN(num)) {
|
|
590
606
|
fmt = nullStr || '-';
|
|
@@ -862,7 +878,8 @@
|
|
|
862
878
|
str = str.toUpperCase();
|
|
863
879
|
}
|
|
864
880
|
else if (isNumber) {
|
|
865
|
-
str =
|
|
881
|
+
// str = formatNumberForDisplay(val, isInt ? 0 : decimals);
|
|
882
|
+
str = numToStr(val, decimals);
|
|
866
883
|
if (str[0] == '-') {
|
|
867
884
|
isNeg = true;
|
|
868
885
|
str = str.substr(1);
|
|
@@ -10296,6 +10313,12 @@
|
|
|
10296
10313
|
};
|
|
10297
10314
|
}
|
|
10298
10315
|
|
|
10316
|
+
/*
|
|
10317
|
+
|
|
10318
|
+
|
|
10319
|
+
|
|
10320
|
+
*/
|
|
10321
|
+
|
|
10299
10322
|
// TODO: use polygon pathfinder shared code
|
|
10300
10323
|
function collectPolylineArcs(ids, nodes, testArc, useArc) {
|
|
10301
10324
|
var parts = [];
|
|
@@ -11865,7 +11888,6 @@
|
|
|
11865
11888
|
});
|
|
11866
11889
|
|
|
11867
11890
|
// Map positive or negative integer ids to non-negative integer ids
|
|
11868
|
-
|
|
11869
11891
|
function IdLookupIndex(n, clearable) {
|
|
11870
11892
|
var fwdIndex = new Int32Array(n);
|
|
11871
11893
|
var revIndex = new Int32Array(n);
|
|
@@ -15565,6 +15587,139 @@ ${svg}
|
|
|
15565
15587
|
}];
|
|
15566
15588
|
}
|
|
15567
15589
|
|
|
15590
|
+
function exportRecordsAsFixedWidthString(fields, records, opts) {
|
|
15591
|
+
var rows = [], col;
|
|
15592
|
+
for (var i=0; i<fields.length; i++) {
|
|
15593
|
+
col = formatFixedWidthColumn(fields[i], records, opts);
|
|
15594
|
+
if (i === 0) {
|
|
15595
|
+
rows = col;
|
|
15596
|
+
} else for (var j=0; j<rows.length; j++) {
|
|
15597
|
+
rows[j] += ' ' + col[j];
|
|
15598
|
+
}
|
|
15599
|
+
}
|
|
15600
|
+
return rows.join('\n');
|
|
15601
|
+
}
|
|
15602
|
+
|
|
15603
|
+
function formatFixedWidthColumn(field, records, opts) {
|
|
15604
|
+
var arr = [],
|
|
15605
|
+
maxLen = field.length,
|
|
15606
|
+
n = records.length,
|
|
15607
|
+
i, val;
|
|
15608
|
+
arr.push(field);
|
|
15609
|
+
for (i=0; i<n; i++) {
|
|
15610
|
+
val = formatFixedWidthValue(records[i][field], opts);
|
|
15611
|
+
maxLen = Math.max(maxLen, val.length);
|
|
15612
|
+
arr.push(val);
|
|
15613
|
+
}
|
|
15614
|
+
for (i=0; i<arr.length; i++) {
|
|
15615
|
+
arr[i] = arr[i].padEnd(maxLen, ' ');
|
|
15616
|
+
}
|
|
15617
|
+
return arr;
|
|
15618
|
+
}
|
|
15619
|
+
|
|
15620
|
+
function formatFixedWidthValue(val, opts) {
|
|
15621
|
+
// TODO: remove duplication with mapshaper-delim-export.js
|
|
15622
|
+
var s;
|
|
15623
|
+
if (val == null) {
|
|
15624
|
+
s = '';
|
|
15625
|
+
} else if (utils.isString(val)) {
|
|
15626
|
+
s = val; // TODO: handle wide characters, newlines etc.
|
|
15627
|
+
} else if (utils.isNumber(val)) {
|
|
15628
|
+
s = opts.decimal_comma ? utils.formatIntlNumber(val) : utils.formatNumber(val);
|
|
15629
|
+
} else if (utils.isObject(val)) {
|
|
15630
|
+
s = JSON.stringify(val);
|
|
15631
|
+
} else {
|
|
15632
|
+
s = val + '';
|
|
15633
|
+
}
|
|
15634
|
+
return s;
|
|
15635
|
+
}
|
|
15636
|
+
|
|
15637
|
+
|
|
15638
|
+
function readFixedWidthRecords(reader, opts) {
|
|
15639
|
+
var str = reader.toString(opts.encoding || 'ascii');
|
|
15640
|
+
return readFixedWidthRecordsFromString(str, opts);
|
|
15641
|
+
}
|
|
15642
|
+
|
|
15643
|
+
function readFixedWidthRecordsFromString(str, ops) {
|
|
15644
|
+
var fields = parseFixedWidthInfo(str.substring(0, 2000));
|
|
15645
|
+
if (!fields) return [];
|
|
15646
|
+
var lines = utils.splitLines(str);
|
|
15647
|
+
if (lines[lines.length - 1] === '') lines.pop(); // handle newline at end of string
|
|
15648
|
+
var records = [];
|
|
15649
|
+
for (var i=1; i<lines.length; i++) {
|
|
15650
|
+
records.push(parseFixedWidthLine(lines[i], fields));
|
|
15651
|
+
}
|
|
15652
|
+
return records;
|
|
15653
|
+
}
|
|
15654
|
+
|
|
15655
|
+
function parseFixedWidthInfo(sample) {
|
|
15656
|
+
var lines = utils.splitLines(sample);
|
|
15657
|
+
if (lines.length > 2) lines.pop(); // remove possible partial line
|
|
15658
|
+
var n = getMaxLineLength(lines);
|
|
15659
|
+
var headerLine = lines[0];
|
|
15660
|
+
var colInfo = [];
|
|
15661
|
+
var colStart = 0;
|
|
15662
|
+
var inContent = false;
|
|
15663
|
+
var inHeader = false;
|
|
15664
|
+
var isContentChar, isHeaderChar, isColStart, colEnd;
|
|
15665
|
+
for (var i=0; i<=n; i++) {
|
|
15666
|
+
isHeaderChar = testContentChar(headerLine, i);
|
|
15667
|
+
isContentChar = !testEmptyCol(lines, i);
|
|
15668
|
+
isColStart = isHeaderChar && !inHeader;
|
|
15669
|
+
if (isColStart && inContent) {
|
|
15670
|
+
// all lines should have a space char in the position right before a header starts
|
|
15671
|
+
return null;
|
|
15672
|
+
}
|
|
15673
|
+
if (i == n || i > 0 && isColStart) {
|
|
15674
|
+
colEnd = i == n ? undefined : i-1;
|
|
15675
|
+
colInfo.push({
|
|
15676
|
+
name: readValue$1(headerLine, colStart, colEnd),
|
|
15677
|
+
end: colEnd,
|
|
15678
|
+
start: colStart
|
|
15679
|
+
});
|
|
15680
|
+
colStart = i;
|
|
15681
|
+
}
|
|
15682
|
+
inContent = isContentChar;
|
|
15683
|
+
inHeader = isHeaderChar;
|
|
15684
|
+
}
|
|
15685
|
+
return colInfo.length > 0 ? colInfo : null;
|
|
15686
|
+
}
|
|
15687
|
+
|
|
15688
|
+
function getMaxLineLength(lines) {
|
|
15689
|
+
var max = 0;
|
|
15690
|
+
for (var i=0; i<lines.length; i++) {
|
|
15691
|
+
max = Math.max(max, lines[i].length);
|
|
15692
|
+
}
|
|
15693
|
+
return max;
|
|
15694
|
+
}
|
|
15695
|
+
|
|
15696
|
+
function readValue$1(line, start, end) {
|
|
15697
|
+
return line.substring(start, end).trim();
|
|
15698
|
+
}
|
|
15699
|
+
|
|
15700
|
+
function parseFixedWidthLine(str, fields) {
|
|
15701
|
+
var obj = {}, field;
|
|
15702
|
+
for (var i=0; i<fields.length; i++) {
|
|
15703
|
+
field = fields[i];
|
|
15704
|
+
obj[field.name] = readValue$1(str, field.start, field.end);
|
|
15705
|
+
}
|
|
15706
|
+
return obj;
|
|
15707
|
+
}
|
|
15708
|
+
|
|
15709
|
+
function testContentChar(str, i) {
|
|
15710
|
+
return i < str.length && str[i] !== ' ';
|
|
15711
|
+
}
|
|
15712
|
+
|
|
15713
|
+
// return true iff all samples are blank at index i
|
|
15714
|
+
function testEmptyCol(samples, i) {
|
|
15715
|
+
var line;
|
|
15716
|
+
for (var j=0; j<samples.length; j++) {
|
|
15717
|
+
line = samples[j];
|
|
15718
|
+
if (testContentChar(line, i)) return false;
|
|
15719
|
+
}
|
|
15720
|
+
return true;
|
|
15721
|
+
}
|
|
15722
|
+
|
|
15568
15723
|
// Generate output content from a dataset object
|
|
15569
15724
|
function exportDelim(dataset, opts) {
|
|
15570
15725
|
var delim = getExportDelimiter(dataset.info, opts),
|
|
@@ -15586,6 +15741,9 @@ ${svg}
|
|
|
15586
15741
|
var encoding = opts.encoding || 'utf8';
|
|
15587
15742
|
var records = lyr.data.getRecords();
|
|
15588
15743
|
var fields = findFieldNames(records, opts.field_order);
|
|
15744
|
+
if (delim == ' ') {
|
|
15745
|
+
return exportRecordsAsFixedWidthString(fields, records, opts);
|
|
15746
|
+
}
|
|
15589
15747
|
var formatRow = getDelimRowFormatter(fields, delim, opts);
|
|
15590
15748
|
// exporting utf8 and ascii text as string by default (for now)
|
|
15591
15749
|
var exportAsString = encodingIsUtf8(encoding) && !opts.to_buffer &&
|
|
@@ -15643,15 +15801,6 @@ ${svg}
|
|
|
15643
15801
|
};
|
|
15644
15802
|
}
|
|
15645
15803
|
|
|
15646
|
-
function formatNumber$1(val) {
|
|
15647
|
-
return val + '';
|
|
15648
|
-
}
|
|
15649
|
-
|
|
15650
|
-
function formatIntlNumber(val) {
|
|
15651
|
-
var str = formatNumber$1(val);
|
|
15652
|
-
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
15653
|
-
}
|
|
15654
|
-
|
|
15655
15804
|
function getDelimValueFormatter(delim, opts) {
|
|
15656
15805
|
var dquoteRxp = new RegExp('["\n\r' + delim + ']');
|
|
15657
15806
|
var decimalComma = opts && opts.decimal_comma || false;
|
|
@@ -15668,7 +15817,7 @@ ${svg}
|
|
|
15668
15817
|
} else if (utils.isString(val)) {
|
|
15669
15818
|
s = formatString(val);
|
|
15670
15819
|
} else if (utils.isNumber(val)) {
|
|
15671
|
-
s = decimalComma ? formatIntlNumber(val) : formatNumber
|
|
15820
|
+
s = decimalComma ? utils.formatIntlNumber(val) : utils.formatNumber(val);
|
|
15672
15821
|
} else if (utils.isObject(val)) {
|
|
15673
15822
|
s = formatString(JSON.stringify(val));
|
|
15674
15823
|
} else {
|
|
@@ -15711,8 +15860,6 @@ ${svg}
|
|
|
15711
15860
|
__proto__: null,
|
|
15712
15861
|
exportDelim: exportDelim,
|
|
15713
15862
|
exportLayerAsDSV: exportLayerAsDSV,
|
|
15714
|
-
formatNumber: formatNumber$1,
|
|
15715
|
-
formatIntlNumber: formatIntlNumber,
|
|
15716
15863
|
getDelimValueFormatter: getDelimValueFormatter
|
|
15717
15864
|
});
|
|
15718
15865
|
|
|
@@ -17076,8 +17223,9 @@ ${svg}
|
|
|
17076
17223
|
//
|
|
17077
17224
|
// TODO: confirm compatibility with all supported encodings
|
|
17078
17225
|
function readDelimRecords(reader, delim, optsArg) {
|
|
17226
|
+
var opts = optsArg || {};
|
|
17227
|
+
if (delim == ' ') return readFixedWidthRecords(reader, opts);
|
|
17079
17228
|
var reader2 = new Reader2(reader),
|
|
17080
|
-
opts = optsArg || {},
|
|
17081
17229
|
headerStr = readLinesAsString(reader2, getDelimHeaderLines(opts), opts.encoding),
|
|
17082
17230
|
header = parseDelimHeaderSection(headerStr, delim, opts),
|
|
17083
17231
|
convertRowArr = getRowConverter(header.import_fields),
|
|
@@ -17100,6 +17248,7 @@ ${svg}
|
|
|
17100
17248
|
// for delimiter characters and newlines. Input size is limited by the maximum
|
|
17101
17249
|
// string size.
|
|
17102
17250
|
function readDelimRecordsFromString(str, delim, opts) {
|
|
17251
|
+
if (delim == ' ') return readFixedWidthRecordsFromString(str, opts);
|
|
17103
17252
|
var header = parseDelimHeaderSection(str, delim, opts);
|
|
17104
17253
|
if (header.import_fields.length === 0 || !header.remainder) return [];
|
|
17105
17254
|
var convert = getRowConverter(header.import_fields);
|
|
@@ -17503,7 +17652,7 @@ ${svg}
|
|
|
17503
17652
|
};
|
|
17504
17653
|
}
|
|
17505
17654
|
|
|
17506
|
-
var supportedDelimiters = ['|', '\t', ',', ';'];
|
|
17655
|
+
var supportedDelimiters = ['|', '\t', ',', ';', ' '];
|
|
17507
17656
|
|
|
17508
17657
|
function isSupportedDelimiter(d) {
|
|
17509
17658
|
return utils.contains(supportedDelimiters, d);
|
|
@@ -17864,9 +18013,21 @@ ${svg}
|
|
|
17864
18013
|
}
|
|
17865
18014
|
|
|
17866
18015
|
function cleanArgv(argv) {
|
|
17867
|
-
|
|
18016
|
+
// Note: original trim caused some quoted spaces to be removed
|
|
18017
|
+
// (e.g. bash shell seems to convert [delimiter=" "] to [delimiter= ],
|
|
18018
|
+
// which then got trimmed to [delimiter=] below)
|
|
18019
|
+
//// argv = argv.map(function(s) {return s.trim();}); // trim whitespace
|
|
18020
|
+
|
|
18021
|
+
// Updated: don't trim space from tokens like [delimeter= ]
|
|
18022
|
+
argv = argv.map(function(s) {
|
|
18023
|
+
if (!/= $/.test(s)) {
|
|
18024
|
+
s = s.trimEnd();
|
|
18025
|
+
}
|
|
18026
|
+
s = s.trimStart();
|
|
18027
|
+
return s;
|
|
18028
|
+
});
|
|
17868
18029
|
argv = argv.filter(function(s) {return s !== '';}); // remove empty tokens
|
|
17869
|
-
// removing trimQuotes() call... now, strings like 'name="Meg"' will no longer
|
|
18030
|
+
// Note: removing trimQuotes() call... now, strings like 'name="Meg"' will no longer
|
|
17870
18031
|
// be parsed the same way as name=Meg and name="Meg"
|
|
17871
18032
|
//// argv = argv.map(utils.trimQuotes); // remove one level of single or dbl quotes
|
|
17872
18033
|
return argv;
|
|
@@ -19191,6 +19352,10 @@ ${svg}
|
|
|
19191
19352
|
.option('keep-shapes', {
|
|
19192
19353
|
type: 'flag'
|
|
19193
19354
|
})
|
|
19355
|
+
.option('ids', {
|
|
19356
|
+
// describe: 'filter on a list of feature ids',
|
|
19357
|
+
type: 'numbers'
|
|
19358
|
+
})
|
|
19194
19359
|
.option('cleanup', {type: 'flag'}) // TODO: document
|
|
19195
19360
|
.option('name', nameOpt)
|
|
19196
19361
|
.option('target', targetOpt)
|
|
@@ -19759,6 +19924,11 @@ ${svg}
|
|
|
19759
19924
|
DEFAULT: true,
|
|
19760
19925
|
describe: 'expression or field for grouping features and naming split layers'
|
|
19761
19926
|
})
|
|
19927
|
+
.option('ids', {
|
|
19928
|
+
// used by gui history to split on selected features
|
|
19929
|
+
// describe: 'split on a list of feature ids',
|
|
19930
|
+
type: 'numbers'
|
|
19931
|
+
})
|
|
19762
19932
|
.option('apart', {
|
|
19763
19933
|
describe: 'save output layers to independent datasets',
|
|
19764
19934
|
type: 'flag'
|
|
@@ -31672,6 +31842,10 @@ ${svg}
|
|
|
31672
31842
|
filter = compileValueExpression(opts.expression, lyr, arcs);
|
|
31673
31843
|
}
|
|
31674
31844
|
|
|
31845
|
+
if (opts.ids) {
|
|
31846
|
+
filter = combineFilters(filter, getIdFilter(opts.ids));
|
|
31847
|
+
}
|
|
31848
|
+
|
|
31675
31849
|
if (opts.remove_empty) {
|
|
31676
31850
|
filter = combineFilters(filter, getNullGeometryFilter(lyr, arcs));
|
|
31677
31851
|
}
|
|
@@ -31730,6 +31904,13 @@ ${svg}
|
|
|
31730
31904
|
lyr.data = filteredRecords ? new DataTable(filteredRecords) : null;
|
|
31731
31905
|
}
|
|
31732
31906
|
|
|
31907
|
+
function getIdFilter(ids) {
|
|
31908
|
+
var set = new Set(ids);
|
|
31909
|
+
return function(i) {
|
|
31910
|
+
return set.has(i);
|
|
31911
|
+
};
|
|
31912
|
+
}
|
|
31913
|
+
|
|
31733
31914
|
function getNullGeometryFilter(lyr, arcs) {
|
|
31734
31915
|
var shapes = lyr.shapes;
|
|
31735
31916
|
if (lyr.geometry_type == 'polygon') {
|
|
@@ -34002,10 +34183,6 @@ ${svg}
|
|
|
34002
34183
|
|
|
34003
34184
|
|
|
34004
34185
|
|
|
34005
|
-
function formatNumber(val) {
|
|
34006
|
-
return val + '';
|
|
34007
|
-
}
|
|
34008
|
-
|
|
34009
34186
|
function maxChars(arr) {
|
|
34010
34187
|
return arr.reduce(function(memo, str) {
|
|
34011
34188
|
var w = stringDisplayWidth(str);
|
|
@@ -34029,14 +34206,14 @@ ${svg}
|
|
|
34029
34206
|
}
|
|
34030
34207
|
|
|
34031
34208
|
function countIntegralChars(val) {
|
|
34032
|
-
return utils.isNumber(val) ? (formatNumber(val) + '.').indexOf('.') : 0;
|
|
34209
|
+
return utils.isNumber(val) ? (utils.formatNumber(val) + '.').indexOf('.') : 0;
|
|
34033
34210
|
}
|
|
34034
34211
|
|
|
34035
34212
|
function formatTableValue(val, integralChars) {
|
|
34036
34213
|
var str;
|
|
34037
34214
|
if (utils.isNumber(val)) {
|
|
34038
34215
|
str = utils.lpad("", integralChars - countIntegralChars(val), ' ') +
|
|
34039
|
-
formatNumber(val);
|
|
34216
|
+
utils.formatNumber(val);
|
|
34040
34217
|
} else if (utils.isString(val)) {
|
|
34041
34218
|
str = formatString(val);
|
|
34042
34219
|
} else if (utils.isDate(val)) {
|
|
@@ -37408,13 +37585,20 @@ ${svg}
|
|
|
37408
37585
|
|
|
37409
37586
|
// @expression: optional field name or expression
|
|
37410
37587
|
//
|
|
37411
|
-
cmd.splitLayer = function(src, expression,
|
|
37412
|
-
var
|
|
37588
|
+
cmd.splitLayer = function(src, expression, optsArg) {
|
|
37589
|
+
var opts = optsArg || {},
|
|
37590
|
+
lyr0 = opts.no_replace ? copyLayer(src) : src,
|
|
37413
37591
|
properties = lyr0.data ? lyr0.data.getRecords() : null,
|
|
37414
37592
|
shapes = lyr0.shapes,
|
|
37415
37593
|
index = {},
|
|
37416
37594
|
splitLayers = [],
|
|
37417
|
-
namer
|
|
37595
|
+
namer;
|
|
37596
|
+
|
|
37597
|
+
if (opts.ids) {
|
|
37598
|
+
namer = getIdSplitFunction(opts.ids);
|
|
37599
|
+
} else {
|
|
37600
|
+
namer = getSplitNameFunction(lyr0, expression);
|
|
37601
|
+
}
|
|
37418
37602
|
|
|
37419
37603
|
// if (splitField) {
|
|
37420
37604
|
// internal.requireDataField(lyr0, splitField);
|
|
@@ -37446,15 +37630,24 @@ ${svg}
|
|
|
37446
37630
|
return splitLayers;
|
|
37447
37631
|
};
|
|
37448
37632
|
|
|
37633
|
+
function getIdSplitFunction(ids) {
|
|
37634
|
+
var set = new Set(ids);
|
|
37635
|
+
return function(i) {
|
|
37636
|
+
return set.has(i) ? '1' : '2';
|
|
37637
|
+
};
|
|
37638
|
+
}
|
|
37639
|
+
|
|
37640
|
+
function getDefaultSplitFunction(lyr) {
|
|
37641
|
+
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
37642
|
+
// like: split-1, split-2, ...
|
|
37643
|
+
return function(i) {
|
|
37644
|
+
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
37645
|
+
};
|
|
37646
|
+
}
|
|
37647
|
+
|
|
37449
37648
|
function getSplitNameFunction(lyr, exp) {
|
|
37450
37649
|
var compiled;
|
|
37451
|
-
if (!exp)
|
|
37452
|
-
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
37453
|
-
// like: split-1, split-2, ...
|
|
37454
|
-
return function(i) {
|
|
37455
|
-
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
37456
|
-
};
|
|
37457
|
-
}
|
|
37650
|
+
if (!exp) return getDefaultSplitFunction(lyr);
|
|
37458
37651
|
lyr = {name: lyr.name, data: lyr.data}; // remove shape info
|
|
37459
37652
|
compiled = compileValueExpression(exp, lyr, null);
|
|
37460
37653
|
return function(i) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mapshaper",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.78",
|
|
4
4
|
"description": "A tool for editing vector datasets for mapping and GIS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shapefile",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"geokdbush": "^1.1.0",
|
|
50
50
|
"iconv-lite": "0.4.24",
|
|
51
51
|
"kdbush": "^3.0.0",
|
|
52
|
-
"mproj": "0.0.
|
|
52
|
+
"mproj": "0.0.35",
|
|
53
53
|
"opn": "^5.3.0",
|
|
54
54
|
"rw": "~1.3.3",
|
|
55
55
|
"sync-request": "5.0.0",
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -1751,7 +1751,7 @@
|
|
|
1751
1751
|
else if (pct < 0.01) decimals = 3;
|
|
1752
1752
|
else if (pct < 1) decimals = 2;
|
|
1753
1753
|
else if (pct < 100) decimals = 1;
|
|
1754
|
-
return utils.
|
|
1754
|
+
return utils.formatNumberForDisplay(pct, decimals) + "%";
|
|
1755
1755
|
});
|
|
1756
1756
|
|
|
1757
1757
|
text.parser(function(s) {
|
|
@@ -5327,6 +5327,10 @@
|
|
|
5327
5327
|
hit.clearSelection();
|
|
5328
5328
|
}
|
|
5329
5329
|
|
|
5330
|
+
function getIdsOpt() {
|
|
5331
|
+
return hit.getSelectionIds().join(',');
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5330
5334
|
hit.on('change', function(e) {
|
|
5331
5335
|
if (e.mode != 'selection') return;
|
|
5332
5336
|
var ids = hit.getSelectionIds();
|
|
@@ -5341,18 +5345,17 @@
|
|
|
5341
5345
|
});
|
|
5342
5346
|
|
|
5343
5347
|
new SimpleButton(popup.findChild('.delete-btn')).on('click', function() {
|
|
5344
|
-
var cmd = '-filter
|
|
5348
|
+
var cmd = '-filter invert ids=' + getIdsOpt();
|
|
5345
5349
|
runCommand(cmd);
|
|
5346
5350
|
});
|
|
5347
5351
|
|
|
5348
5352
|
new SimpleButton(popup.findChild('.filter-btn')).on('click', function() {
|
|
5349
|
-
|
|
5350
|
-
var cmd = '-filter "$$set.has(this.id)"';
|
|
5353
|
+
var cmd = '-filter ids=' + getIdsOpt();
|
|
5351
5354
|
runCommand(cmd);
|
|
5352
5355
|
});
|
|
5353
5356
|
|
|
5354
5357
|
new SimpleButton(popup.findChild('.split-btn')).on('click', function() {
|
|
5355
|
-
var cmd = '-
|
|
5358
|
+
var cmd = '-split ids=' + getIdsOpt();
|
|
5356
5359
|
runCommand(cmd);
|
|
5357
5360
|
});
|
|
5358
5361
|
|
|
@@ -5361,10 +5364,6 @@
|
|
|
5361
5364
|
});
|
|
5362
5365
|
|
|
5363
5366
|
function runCommand(cmd) {
|
|
5364
|
-
// var defs = internal.getStateVar('defs');
|
|
5365
|
-
// defs.$$selection = utils.arrayToIndex(hit.getSelectionIds());
|
|
5366
|
-
var ids = JSON.stringify(hit.getSelectionIds());
|
|
5367
|
-
cmd = `-define "$$set = new Set(${ids})" ${cmd} -define "delete $$set"`;
|
|
5368
5367
|
popup.hide();
|
|
5369
5368
|
if (gui.console) gui.console.runMapshaperCommands(cmd, function(err) {
|
|
5370
5369
|
reset();
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.78";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
get initializeArray () { return initializeArray; },
|
|
53
53
|
get replaceArray () { return replaceArray; },
|
|
54
54
|
get repeatString () { return repeatString; },
|
|
55
|
+
get splitLines () { return splitLines; },
|
|
55
56
|
get pluralSuffix () { return pluralSuffix; },
|
|
56
57
|
get endsWith () { return endsWith; },
|
|
57
58
|
get lpad () { return lpad; },
|
|
@@ -61,7 +62,9 @@
|
|
|
61
62
|
get rtrim () { return rtrim; },
|
|
62
63
|
get addThousandsSep () { return addThousandsSep; },
|
|
63
64
|
get numToStr () { return numToStr; },
|
|
64
|
-
get formatNumber () { return formatNumber
|
|
65
|
+
get formatNumber () { return formatNumber; },
|
|
66
|
+
get formatIntlNumber () { return formatIntlNumber; },
|
|
67
|
+
get formatNumberForDisplay () { return formatNumberForDisplay; },
|
|
65
68
|
get shuffle () { return shuffle; },
|
|
66
69
|
get sortOn () { return sortOn; },
|
|
67
70
|
get genericSort () { return genericSort; },
|
|
@@ -532,6 +535,10 @@
|
|
|
532
535
|
return str;
|
|
533
536
|
}
|
|
534
537
|
|
|
538
|
+
function splitLines(str) {
|
|
539
|
+
return str.split(/\r?\n/);
|
|
540
|
+
}
|
|
541
|
+
|
|
535
542
|
function pluralSuffix(count) {
|
|
536
543
|
return count != 1 ? 's' : '';
|
|
537
544
|
}
|
|
@@ -584,7 +591,16 @@
|
|
|
584
591
|
return decimals >= 0 ? num.toFixed(decimals) : String(num);
|
|
585
592
|
}
|
|
586
593
|
|
|
587
|
-
function formatNumber
|
|
594
|
+
function formatNumber(val) {
|
|
595
|
+
return val + '';
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function formatIntlNumber(val) {
|
|
599
|
+
var str = formatNumber(val);
|
|
600
|
+
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
function formatNumberForDisplay(num, decimals, nullStr, showPos) {
|
|
588
604
|
var fmt;
|
|
589
605
|
if (isNaN(num)) {
|
|
590
606
|
fmt = nullStr || '-';
|
|
@@ -862,7 +878,8 @@
|
|
|
862
878
|
str = str.toUpperCase();
|
|
863
879
|
}
|
|
864
880
|
else if (isNumber) {
|
|
865
|
-
str =
|
|
881
|
+
// str = formatNumberForDisplay(val, isInt ? 0 : decimals);
|
|
882
|
+
str = numToStr(val, decimals);
|
|
866
883
|
if (str[0] == '-') {
|
|
867
884
|
isNeg = true;
|
|
868
885
|
str = str.substr(1);
|
|
@@ -10296,6 +10313,12 @@
|
|
|
10296
10313
|
};
|
|
10297
10314
|
}
|
|
10298
10315
|
|
|
10316
|
+
/*
|
|
10317
|
+
|
|
10318
|
+
|
|
10319
|
+
|
|
10320
|
+
*/
|
|
10321
|
+
|
|
10299
10322
|
// TODO: use polygon pathfinder shared code
|
|
10300
10323
|
function collectPolylineArcs(ids, nodes, testArc, useArc) {
|
|
10301
10324
|
var parts = [];
|
|
@@ -11865,7 +11888,6 @@
|
|
|
11865
11888
|
});
|
|
11866
11889
|
|
|
11867
11890
|
// Map positive or negative integer ids to non-negative integer ids
|
|
11868
|
-
|
|
11869
11891
|
function IdLookupIndex(n, clearable) {
|
|
11870
11892
|
var fwdIndex = new Int32Array(n);
|
|
11871
11893
|
var revIndex = new Int32Array(n);
|
|
@@ -15565,6 +15587,139 @@ ${svg}
|
|
|
15565
15587
|
}];
|
|
15566
15588
|
}
|
|
15567
15589
|
|
|
15590
|
+
function exportRecordsAsFixedWidthString(fields, records, opts) {
|
|
15591
|
+
var rows = [], col;
|
|
15592
|
+
for (var i=0; i<fields.length; i++) {
|
|
15593
|
+
col = formatFixedWidthColumn(fields[i], records, opts);
|
|
15594
|
+
if (i === 0) {
|
|
15595
|
+
rows = col;
|
|
15596
|
+
} else for (var j=0; j<rows.length; j++) {
|
|
15597
|
+
rows[j] += ' ' + col[j];
|
|
15598
|
+
}
|
|
15599
|
+
}
|
|
15600
|
+
return rows.join('\n');
|
|
15601
|
+
}
|
|
15602
|
+
|
|
15603
|
+
function formatFixedWidthColumn(field, records, opts) {
|
|
15604
|
+
var arr = [],
|
|
15605
|
+
maxLen = field.length,
|
|
15606
|
+
n = records.length,
|
|
15607
|
+
i, val;
|
|
15608
|
+
arr.push(field);
|
|
15609
|
+
for (i=0; i<n; i++) {
|
|
15610
|
+
val = formatFixedWidthValue(records[i][field], opts);
|
|
15611
|
+
maxLen = Math.max(maxLen, val.length);
|
|
15612
|
+
arr.push(val);
|
|
15613
|
+
}
|
|
15614
|
+
for (i=0; i<arr.length; i++) {
|
|
15615
|
+
arr[i] = arr[i].padEnd(maxLen, ' ');
|
|
15616
|
+
}
|
|
15617
|
+
return arr;
|
|
15618
|
+
}
|
|
15619
|
+
|
|
15620
|
+
function formatFixedWidthValue(val, opts) {
|
|
15621
|
+
// TODO: remove duplication with mapshaper-delim-export.js
|
|
15622
|
+
var s;
|
|
15623
|
+
if (val == null) {
|
|
15624
|
+
s = '';
|
|
15625
|
+
} else if (utils.isString(val)) {
|
|
15626
|
+
s = val; // TODO: handle wide characters, newlines etc.
|
|
15627
|
+
} else if (utils.isNumber(val)) {
|
|
15628
|
+
s = opts.decimal_comma ? utils.formatIntlNumber(val) : utils.formatNumber(val);
|
|
15629
|
+
} else if (utils.isObject(val)) {
|
|
15630
|
+
s = JSON.stringify(val);
|
|
15631
|
+
} else {
|
|
15632
|
+
s = val + '';
|
|
15633
|
+
}
|
|
15634
|
+
return s;
|
|
15635
|
+
}
|
|
15636
|
+
|
|
15637
|
+
|
|
15638
|
+
function readFixedWidthRecords(reader, opts) {
|
|
15639
|
+
var str = reader.toString(opts.encoding || 'ascii');
|
|
15640
|
+
return readFixedWidthRecordsFromString(str, opts);
|
|
15641
|
+
}
|
|
15642
|
+
|
|
15643
|
+
function readFixedWidthRecordsFromString(str, ops) {
|
|
15644
|
+
var fields = parseFixedWidthInfo(str.substring(0, 2000));
|
|
15645
|
+
if (!fields) return [];
|
|
15646
|
+
var lines = utils.splitLines(str);
|
|
15647
|
+
if (lines[lines.length - 1] === '') lines.pop(); // handle newline at end of string
|
|
15648
|
+
var records = [];
|
|
15649
|
+
for (var i=1; i<lines.length; i++) {
|
|
15650
|
+
records.push(parseFixedWidthLine(lines[i], fields));
|
|
15651
|
+
}
|
|
15652
|
+
return records;
|
|
15653
|
+
}
|
|
15654
|
+
|
|
15655
|
+
function parseFixedWidthInfo(sample) {
|
|
15656
|
+
var lines = utils.splitLines(sample);
|
|
15657
|
+
if (lines.length > 2) lines.pop(); // remove possible partial line
|
|
15658
|
+
var n = getMaxLineLength(lines);
|
|
15659
|
+
var headerLine = lines[0];
|
|
15660
|
+
var colInfo = [];
|
|
15661
|
+
var colStart = 0;
|
|
15662
|
+
var inContent = false;
|
|
15663
|
+
var inHeader = false;
|
|
15664
|
+
var isContentChar, isHeaderChar, isColStart, colEnd;
|
|
15665
|
+
for (var i=0; i<=n; i++) {
|
|
15666
|
+
isHeaderChar = testContentChar(headerLine, i);
|
|
15667
|
+
isContentChar = !testEmptyCol(lines, i);
|
|
15668
|
+
isColStart = isHeaderChar && !inHeader;
|
|
15669
|
+
if (isColStart && inContent) {
|
|
15670
|
+
// all lines should have a space char in the position right before a header starts
|
|
15671
|
+
return null;
|
|
15672
|
+
}
|
|
15673
|
+
if (i == n || i > 0 && isColStart) {
|
|
15674
|
+
colEnd = i == n ? undefined : i-1;
|
|
15675
|
+
colInfo.push({
|
|
15676
|
+
name: readValue$1(headerLine, colStart, colEnd),
|
|
15677
|
+
end: colEnd,
|
|
15678
|
+
start: colStart
|
|
15679
|
+
});
|
|
15680
|
+
colStart = i;
|
|
15681
|
+
}
|
|
15682
|
+
inContent = isContentChar;
|
|
15683
|
+
inHeader = isHeaderChar;
|
|
15684
|
+
}
|
|
15685
|
+
return colInfo.length > 0 ? colInfo : null;
|
|
15686
|
+
}
|
|
15687
|
+
|
|
15688
|
+
function getMaxLineLength(lines) {
|
|
15689
|
+
var max = 0;
|
|
15690
|
+
for (var i=0; i<lines.length; i++) {
|
|
15691
|
+
max = Math.max(max, lines[i].length);
|
|
15692
|
+
}
|
|
15693
|
+
return max;
|
|
15694
|
+
}
|
|
15695
|
+
|
|
15696
|
+
function readValue$1(line, start, end) {
|
|
15697
|
+
return line.substring(start, end).trim();
|
|
15698
|
+
}
|
|
15699
|
+
|
|
15700
|
+
function parseFixedWidthLine(str, fields) {
|
|
15701
|
+
var obj = {}, field;
|
|
15702
|
+
for (var i=0; i<fields.length; i++) {
|
|
15703
|
+
field = fields[i];
|
|
15704
|
+
obj[field.name] = readValue$1(str, field.start, field.end);
|
|
15705
|
+
}
|
|
15706
|
+
return obj;
|
|
15707
|
+
}
|
|
15708
|
+
|
|
15709
|
+
function testContentChar(str, i) {
|
|
15710
|
+
return i < str.length && str[i] !== ' ';
|
|
15711
|
+
}
|
|
15712
|
+
|
|
15713
|
+
// return true iff all samples are blank at index i
|
|
15714
|
+
function testEmptyCol(samples, i) {
|
|
15715
|
+
var line;
|
|
15716
|
+
for (var j=0; j<samples.length; j++) {
|
|
15717
|
+
line = samples[j];
|
|
15718
|
+
if (testContentChar(line, i)) return false;
|
|
15719
|
+
}
|
|
15720
|
+
return true;
|
|
15721
|
+
}
|
|
15722
|
+
|
|
15568
15723
|
// Generate output content from a dataset object
|
|
15569
15724
|
function exportDelim(dataset, opts) {
|
|
15570
15725
|
var delim = getExportDelimiter(dataset.info, opts),
|
|
@@ -15586,6 +15741,9 @@ ${svg}
|
|
|
15586
15741
|
var encoding = opts.encoding || 'utf8';
|
|
15587
15742
|
var records = lyr.data.getRecords();
|
|
15588
15743
|
var fields = findFieldNames(records, opts.field_order);
|
|
15744
|
+
if (delim == ' ') {
|
|
15745
|
+
return exportRecordsAsFixedWidthString(fields, records, opts);
|
|
15746
|
+
}
|
|
15589
15747
|
var formatRow = getDelimRowFormatter(fields, delim, opts);
|
|
15590
15748
|
// exporting utf8 and ascii text as string by default (for now)
|
|
15591
15749
|
var exportAsString = encodingIsUtf8(encoding) && !opts.to_buffer &&
|
|
@@ -15643,15 +15801,6 @@ ${svg}
|
|
|
15643
15801
|
};
|
|
15644
15802
|
}
|
|
15645
15803
|
|
|
15646
|
-
function formatNumber$1(val) {
|
|
15647
|
-
return val + '';
|
|
15648
|
-
}
|
|
15649
|
-
|
|
15650
|
-
function formatIntlNumber(val) {
|
|
15651
|
-
var str = formatNumber$1(val);
|
|
15652
|
-
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
15653
|
-
}
|
|
15654
|
-
|
|
15655
15804
|
function getDelimValueFormatter(delim, opts) {
|
|
15656
15805
|
var dquoteRxp = new RegExp('["\n\r' + delim + ']');
|
|
15657
15806
|
var decimalComma = opts && opts.decimal_comma || false;
|
|
@@ -15668,7 +15817,7 @@ ${svg}
|
|
|
15668
15817
|
} else if (utils.isString(val)) {
|
|
15669
15818
|
s = formatString(val);
|
|
15670
15819
|
} else if (utils.isNumber(val)) {
|
|
15671
|
-
s = decimalComma ? formatIntlNumber(val) : formatNumber
|
|
15820
|
+
s = decimalComma ? utils.formatIntlNumber(val) : utils.formatNumber(val);
|
|
15672
15821
|
} else if (utils.isObject(val)) {
|
|
15673
15822
|
s = formatString(JSON.stringify(val));
|
|
15674
15823
|
} else {
|
|
@@ -15711,8 +15860,6 @@ ${svg}
|
|
|
15711
15860
|
__proto__: null,
|
|
15712
15861
|
exportDelim: exportDelim,
|
|
15713
15862
|
exportLayerAsDSV: exportLayerAsDSV,
|
|
15714
|
-
formatNumber: formatNumber$1,
|
|
15715
|
-
formatIntlNumber: formatIntlNumber,
|
|
15716
15863
|
getDelimValueFormatter: getDelimValueFormatter
|
|
15717
15864
|
});
|
|
15718
15865
|
|
|
@@ -17076,8 +17223,9 @@ ${svg}
|
|
|
17076
17223
|
//
|
|
17077
17224
|
// TODO: confirm compatibility with all supported encodings
|
|
17078
17225
|
function readDelimRecords(reader, delim, optsArg) {
|
|
17226
|
+
var opts = optsArg || {};
|
|
17227
|
+
if (delim == ' ') return readFixedWidthRecords(reader, opts);
|
|
17079
17228
|
var reader2 = new Reader2(reader),
|
|
17080
|
-
opts = optsArg || {},
|
|
17081
17229
|
headerStr = readLinesAsString(reader2, getDelimHeaderLines(opts), opts.encoding),
|
|
17082
17230
|
header = parseDelimHeaderSection(headerStr, delim, opts),
|
|
17083
17231
|
convertRowArr = getRowConverter(header.import_fields),
|
|
@@ -17100,6 +17248,7 @@ ${svg}
|
|
|
17100
17248
|
// for delimiter characters and newlines. Input size is limited by the maximum
|
|
17101
17249
|
// string size.
|
|
17102
17250
|
function readDelimRecordsFromString(str, delim, opts) {
|
|
17251
|
+
if (delim == ' ') return readFixedWidthRecordsFromString(str, opts);
|
|
17103
17252
|
var header = parseDelimHeaderSection(str, delim, opts);
|
|
17104
17253
|
if (header.import_fields.length === 0 || !header.remainder) return [];
|
|
17105
17254
|
var convert = getRowConverter(header.import_fields);
|
|
@@ -17503,7 +17652,7 @@ ${svg}
|
|
|
17503
17652
|
};
|
|
17504
17653
|
}
|
|
17505
17654
|
|
|
17506
|
-
var supportedDelimiters = ['|', '\t', ',', ';'];
|
|
17655
|
+
var supportedDelimiters = ['|', '\t', ',', ';', ' '];
|
|
17507
17656
|
|
|
17508
17657
|
function isSupportedDelimiter(d) {
|
|
17509
17658
|
return utils.contains(supportedDelimiters, d);
|
|
@@ -17864,9 +18013,21 @@ ${svg}
|
|
|
17864
18013
|
}
|
|
17865
18014
|
|
|
17866
18015
|
function cleanArgv(argv) {
|
|
17867
|
-
|
|
18016
|
+
// Note: original trim caused some quoted spaces to be removed
|
|
18017
|
+
// (e.g. bash shell seems to convert [delimiter=" "] to [delimiter= ],
|
|
18018
|
+
// which then got trimmed to [delimiter=] below)
|
|
18019
|
+
//// argv = argv.map(function(s) {return s.trim();}); // trim whitespace
|
|
18020
|
+
|
|
18021
|
+
// Updated: don't trim space from tokens like [delimeter= ]
|
|
18022
|
+
argv = argv.map(function(s) {
|
|
18023
|
+
if (!/= $/.test(s)) {
|
|
18024
|
+
s = s.trimEnd();
|
|
18025
|
+
}
|
|
18026
|
+
s = s.trimStart();
|
|
18027
|
+
return s;
|
|
18028
|
+
});
|
|
17868
18029
|
argv = argv.filter(function(s) {return s !== '';}); // remove empty tokens
|
|
17869
|
-
// removing trimQuotes() call... now, strings like 'name="Meg"' will no longer
|
|
18030
|
+
// Note: removing trimQuotes() call... now, strings like 'name="Meg"' will no longer
|
|
17870
18031
|
// be parsed the same way as name=Meg and name="Meg"
|
|
17871
18032
|
//// argv = argv.map(utils.trimQuotes); // remove one level of single or dbl quotes
|
|
17872
18033
|
return argv;
|
|
@@ -19191,6 +19352,10 @@ ${svg}
|
|
|
19191
19352
|
.option('keep-shapes', {
|
|
19192
19353
|
type: 'flag'
|
|
19193
19354
|
})
|
|
19355
|
+
.option('ids', {
|
|
19356
|
+
// describe: 'filter on a list of feature ids',
|
|
19357
|
+
type: 'numbers'
|
|
19358
|
+
})
|
|
19194
19359
|
.option('cleanup', {type: 'flag'}) // TODO: document
|
|
19195
19360
|
.option('name', nameOpt)
|
|
19196
19361
|
.option('target', targetOpt)
|
|
@@ -19759,6 +19924,11 @@ ${svg}
|
|
|
19759
19924
|
DEFAULT: true,
|
|
19760
19925
|
describe: 'expression or field for grouping features and naming split layers'
|
|
19761
19926
|
})
|
|
19927
|
+
.option('ids', {
|
|
19928
|
+
// used by gui history to split on selected features
|
|
19929
|
+
// describe: 'split on a list of feature ids',
|
|
19930
|
+
type: 'numbers'
|
|
19931
|
+
})
|
|
19762
19932
|
.option('apart', {
|
|
19763
19933
|
describe: 'save output layers to independent datasets',
|
|
19764
19934
|
type: 'flag'
|
|
@@ -31672,6 +31842,10 @@ ${svg}
|
|
|
31672
31842
|
filter = compileValueExpression(opts.expression, lyr, arcs);
|
|
31673
31843
|
}
|
|
31674
31844
|
|
|
31845
|
+
if (opts.ids) {
|
|
31846
|
+
filter = combineFilters(filter, getIdFilter(opts.ids));
|
|
31847
|
+
}
|
|
31848
|
+
|
|
31675
31849
|
if (opts.remove_empty) {
|
|
31676
31850
|
filter = combineFilters(filter, getNullGeometryFilter(lyr, arcs));
|
|
31677
31851
|
}
|
|
@@ -31730,6 +31904,13 @@ ${svg}
|
|
|
31730
31904
|
lyr.data = filteredRecords ? new DataTable(filteredRecords) : null;
|
|
31731
31905
|
}
|
|
31732
31906
|
|
|
31907
|
+
function getIdFilter(ids) {
|
|
31908
|
+
var set = new Set(ids);
|
|
31909
|
+
return function(i) {
|
|
31910
|
+
return set.has(i);
|
|
31911
|
+
};
|
|
31912
|
+
}
|
|
31913
|
+
|
|
31733
31914
|
function getNullGeometryFilter(lyr, arcs) {
|
|
31734
31915
|
var shapes = lyr.shapes;
|
|
31735
31916
|
if (lyr.geometry_type == 'polygon') {
|
|
@@ -34002,10 +34183,6 @@ ${svg}
|
|
|
34002
34183
|
|
|
34003
34184
|
|
|
34004
34185
|
|
|
34005
|
-
function formatNumber(val) {
|
|
34006
|
-
return val + '';
|
|
34007
|
-
}
|
|
34008
|
-
|
|
34009
34186
|
function maxChars(arr) {
|
|
34010
34187
|
return arr.reduce(function(memo, str) {
|
|
34011
34188
|
var w = stringDisplayWidth(str);
|
|
@@ -34029,14 +34206,14 @@ ${svg}
|
|
|
34029
34206
|
}
|
|
34030
34207
|
|
|
34031
34208
|
function countIntegralChars(val) {
|
|
34032
|
-
return utils.isNumber(val) ? (formatNumber(val) + '.').indexOf('.') : 0;
|
|
34209
|
+
return utils.isNumber(val) ? (utils.formatNumber(val) + '.').indexOf('.') : 0;
|
|
34033
34210
|
}
|
|
34034
34211
|
|
|
34035
34212
|
function formatTableValue(val, integralChars) {
|
|
34036
34213
|
var str;
|
|
34037
34214
|
if (utils.isNumber(val)) {
|
|
34038
34215
|
str = utils.lpad("", integralChars - countIntegralChars(val), ' ') +
|
|
34039
|
-
formatNumber(val);
|
|
34216
|
+
utils.formatNumber(val);
|
|
34040
34217
|
} else if (utils.isString(val)) {
|
|
34041
34218
|
str = formatString(val);
|
|
34042
34219
|
} else if (utils.isDate(val)) {
|
|
@@ -37408,13 +37585,20 @@ ${svg}
|
|
|
37408
37585
|
|
|
37409
37586
|
// @expression: optional field name or expression
|
|
37410
37587
|
//
|
|
37411
|
-
cmd.splitLayer = function(src, expression,
|
|
37412
|
-
var
|
|
37588
|
+
cmd.splitLayer = function(src, expression, optsArg) {
|
|
37589
|
+
var opts = optsArg || {},
|
|
37590
|
+
lyr0 = opts.no_replace ? copyLayer(src) : src,
|
|
37413
37591
|
properties = lyr0.data ? lyr0.data.getRecords() : null,
|
|
37414
37592
|
shapes = lyr0.shapes,
|
|
37415
37593
|
index = {},
|
|
37416
37594
|
splitLayers = [],
|
|
37417
|
-
namer
|
|
37595
|
+
namer;
|
|
37596
|
+
|
|
37597
|
+
if (opts.ids) {
|
|
37598
|
+
namer = getIdSplitFunction(opts.ids);
|
|
37599
|
+
} else {
|
|
37600
|
+
namer = getSplitNameFunction(lyr0, expression);
|
|
37601
|
+
}
|
|
37418
37602
|
|
|
37419
37603
|
// if (splitField) {
|
|
37420
37604
|
// internal.requireDataField(lyr0, splitField);
|
|
@@ -37446,15 +37630,24 @@ ${svg}
|
|
|
37446
37630
|
return splitLayers;
|
|
37447
37631
|
};
|
|
37448
37632
|
|
|
37633
|
+
function getIdSplitFunction(ids) {
|
|
37634
|
+
var set = new Set(ids);
|
|
37635
|
+
return function(i) {
|
|
37636
|
+
return set.has(i) ? '1' : '2';
|
|
37637
|
+
};
|
|
37638
|
+
}
|
|
37639
|
+
|
|
37640
|
+
function getDefaultSplitFunction(lyr) {
|
|
37641
|
+
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
37642
|
+
// like: split-1, split-2, ...
|
|
37643
|
+
return function(i) {
|
|
37644
|
+
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
37645
|
+
};
|
|
37646
|
+
}
|
|
37647
|
+
|
|
37449
37648
|
function getSplitNameFunction(lyr, exp) {
|
|
37450
37649
|
var compiled;
|
|
37451
|
-
if (!exp)
|
|
37452
|
-
// if not splitting on an expression and layer is unnamed, name split-apart layers
|
|
37453
|
-
// like: split-1, split-2, ...
|
|
37454
|
-
return function(i) {
|
|
37455
|
-
return (lyr && lyr.name || 'split') + '-' + (i + 1);
|
|
37456
|
-
};
|
|
37457
|
-
}
|
|
37650
|
+
if (!exp) return getDefaultSplitFunction(lyr);
|
|
37458
37651
|
lyr = {name: lyr.name, data: lyr.data}; // remove shape info
|
|
37459
37652
|
compiled = compileValueExpression(exp, lyr, null);
|
|
37460
37653
|
return function(i) {
|
package/www/modules.js
CHANGED
|
@@ -12464,8 +12464,9 @@ function wkt_parse(str) {
|
|
|
12464
12464
|
// WKT format: http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#11
|
|
12465
12465
|
function wkt_unpack(str) {
|
|
12466
12466
|
var obj;
|
|
12467
|
-
// Convert WKT escaped
|
|
12468
|
-
str = str.replace(/""/g, '\\"');
|
|
12467
|
+
// Convert WKT escaped quotes to JSON escaped quotes
|
|
12468
|
+
// str = str.replace(/""/g, '\\"'); // BUGGY
|
|
12469
|
+
str = convert_wkt_quotes(str);
|
|
12469
12470
|
|
|
12470
12471
|
// Convert WKT entities to JSON arrays
|
|
12471
12472
|
str = str.replace(/([A-Z0-9]+)\[/g, '["$1",');
|
|
@@ -12487,6 +12488,23 @@ function wkt_unpack(str) {
|
|
|
12487
12488
|
return obj;
|
|
12488
12489
|
}
|
|
12489
12490
|
|
|
12491
|
+
// Convert WKT escaped quotes to JSON escaped quotes ("" -> \")
|
|
12492
|
+
function convert_wkt_quotes(str) {
|
|
12493
|
+
var c = 0;
|
|
12494
|
+
return str.replace(/"+/g, function(s) {
|
|
12495
|
+
var even = c % 2 == 0;
|
|
12496
|
+
c += s.length;
|
|
12497
|
+
// ordinary, unescaped quotes
|
|
12498
|
+
if (s == '"' || s == '""' && even) return s;
|
|
12499
|
+
// WKT-escaped quotes
|
|
12500
|
+
if (even) {
|
|
12501
|
+
return '"' + s.substring(1).replace(/""/g, '\\"');
|
|
12502
|
+
} else {
|
|
12503
|
+
return s.replace(/""/g, '\\"');
|
|
12504
|
+
}
|
|
12505
|
+
});
|
|
12506
|
+
}
|
|
12507
|
+
|
|
12490
12508
|
// Rearrange a subarray of a parsed WKT file for easier traversal
|
|
12491
12509
|
// E.g.
|
|
12492
12510
|
// ["WGS84", ...] to {NAME: "WGS84"}
|
|
@@ -21706,6 +21724,7 @@ api.internal = {
|
|
|
21706
21724
|
RAD_TO_DEG: RAD_TO_DEG,
|
|
21707
21725
|
wkt_parse: wkt_parse,
|
|
21708
21726
|
wkt_unpack: wkt_unpack,
|
|
21727
|
+
convert_wkt_quotes: convert_wkt_quotes,
|
|
21709
21728
|
wkt_to_proj4: wkt_to_proj4,
|
|
21710
21729
|
wkt_from_proj4: wkt_from_proj4,
|
|
21711
21730
|
wkt_make_projcs: wkt_make_projcs,
|