mapshaper 0.6.38 → 0.6.39
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 +164 -43
- package/package.json +1 -1
- package/www/mapshaper-gui.js +18 -41
- package/www/mapshaper.js +164 -43
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.39";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
get rtrim () { return rtrim; },
|
|
66
66
|
get addThousandsSep () { return addThousandsSep; },
|
|
67
67
|
get numToStr () { return numToStr; },
|
|
68
|
-
get formatNumber () { return formatNumber; },
|
|
68
|
+
get formatNumber () { return formatNumber$1; },
|
|
69
69
|
get formatIntlNumber () { return formatIntlNumber; },
|
|
70
70
|
get formatNumberForDisplay () { return formatNumberForDisplay; },
|
|
71
71
|
get shuffle () { return shuffle; },
|
|
@@ -649,12 +649,12 @@
|
|
|
649
649
|
return decimals >= 0 ? num.toFixed(decimals) : String(num);
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
function formatNumber(val) {
|
|
652
|
+
function formatNumber$1(val) {
|
|
653
653
|
return val + '';
|
|
654
654
|
}
|
|
655
655
|
|
|
656
656
|
function formatIntlNumber(val) {
|
|
657
|
-
var str = formatNumber(val);
|
|
657
|
+
var str = formatNumber$1(val);
|
|
658
658
|
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
659
659
|
}
|
|
660
660
|
|
|
@@ -1247,7 +1247,8 @@
|
|
|
1247
1247
|
|
|
1248
1248
|
// Handle an error caused by invalid input or misuse of API
|
|
1249
1249
|
function stop() {
|
|
1250
|
-
_stop.apply(null, utils.toArray(arguments));
|
|
1250
|
+
// _stop.apply(null, utils.toArray(arguments));
|
|
1251
|
+
_stop.apply(null, messageArgs(arguments));
|
|
1251
1252
|
}
|
|
1252
1253
|
|
|
1253
1254
|
function interrupt() {
|
|
@@ -4670,12 +4671,11 @@
|
|
|
4670
4671
|
albersusa: AlbersUSA
|
|
4671
4672
|
};
|
|
4672
4673
|
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
if (!asyncLoader) return done();
|
|
4676
|
-
asyncLoader(opts, done);
|
|
4674
|
+
async function initProjLibrary(opts) {
|
|
4675
|
+
if (asyncLoader) await asyncLoader(opts);
|
|
4677
4676
|
}
|
|
4678
4677
|
|
|
4678
|
+
// used by web UI to support loading projection assets asyncronously
|
|
4679
4679
|
function setProjectionLoader(loader) {
|
|
4680
4680
|
asyncLoader = loader;
|
|
4681
4681
|
}
|
|
@@ -13115,6 +13115,105 @@
|
|
|
13115
13115
|
});
|
|
13116
13116
|
}
|
|
13117
13117
|
|
|
13118
|
+
// Parse a formatted value in DMS DM or D to a numeric value. Returns NaN if unparsable.
|
|
13119
|
+
// Delimiters: degrees: D|d|°; minutes: '; seconds: "
|
|
13120
|
+
function parseDMS(str, fmt) {
|
|
13121
|
+
var defaultRxp = /^(?<prefix>[nsew+-]?)(?<d>[0-9.]+)[d°]? ?(?<m>[0-9.]*)['′]? ?(?<s>[0-9.]*)["″]? ?(?<suffix>[nsew]?)$/i;
|
|
13122
|
+
var rxp = fmt ? getParseRxp(fmt) : defaultRxp;
|
|
13123
|
+
var match = rxp.exec(str.trim());
|
|
13124
|
+
var d = NaN;
|
|
13125
|
+
var deg, min, sec;
|
|
13126
|
+
if (match) {
|
|
13127
|
+
deg = match.groups.d || '0';
|
|
13128
|
+
min = match.groups.m || '0';
|
|
13129
|
+
sec = match.groups.s || '0';
|
|
13130
|
+
d = (+deg) + (+min) / 60 + (+sec) / 3600;
|
|
13131
|
+
if (/[sw-]/i.test(match.groups.prefix || '') || /[sw]/i.test(match.groups.suffix || '')) {
|
|
13132
|
+
d = -d;
|
|
13133
|
+
}
|
|
13134
|
+
}
|
|
13135
|
+
return d;
|
|
13136
|
+
}
|
|
13137
|
+
|
|
13138
|
+
var cache$1 = {};
|
|
13139
|
+
|
|
13140
|
+
function getParseRxp(fmt) {
|
|
13141
|
+
if (fmt in cache$1) return cache$1[fmt];
|
|
13142
|
+
var rxp = fmt;
|
|
13143
|
+
rxp = rxp.replace('[-]', '(?<prefix>-)?'); // optional -
|
|
13144
|
+
rxp = rxp.replace(/\[[NSEW, +-]{2,}\]/, '(?<prefix>$&)');
|
|
13145
|
+
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13146
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13147
|
+
if (g2) s += `\\.[0-9]+`;
|
|
13148
|
+
return `(?<m>${s})`;
|
|
13149
|
+
});
|
|
13150
|
+
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13151
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13152
|
+
if (g2) s += `\\.[0-9]+`;
|
|
13153
|
+
return `(?<s>${s})`;
|
|
13154
|
+
});
|
|
13155
|
+
rxp = rxp.replace(/D+/, '(?<d>[0-9]+)');
|
|
13156
|
+
rxp = '^' + rxp + '$';
|
|
13157
|
+
try {
|
|
13158
|
+
// TODO: make sure all DMS codes have been matched
|
|
13159
|
+
cache$1[fmt] = new RegExp(rxp);
|
|
13160
|
+
} catch(e) {
|
|
13161
|
+
stop('Invalid DMS format string:', fmt);
|
|
13162
|
+
}
|
|
13163
|
+
return cache$1[fmt];
|
|
13164
|
+
}
|
|
13165
|
+
|
|
13166
|
+
function formatNumber(val, integers, decimals) {
|
|
13167
|
+
var str = val.toFixed(decimals);
|
|
13168
|
+
var parts = str.split('.');
|
|
13169
|
+
if (parts.length > 0) {
|
|
13170
|
+
parts[0] = parts[0].padStart(integers, '0');
|
|
13171
|
+
str = parts.join('.');
|
|
13172
|
+
}
|
|
13173
|
+
return str;
|
|
13174
|
+
}
|
|
13175
|
+
|
|
13176
|
+
function getDecimals(fmt) {
|
|
13177
|
+
var match = /S\.(S+)/.exec(fmt) || /M\.(M+)/.exec(fmt) || null;
|
|
13178
|
+
return match ? match[1].length : 0;
|
|
13179
|
+
}
|
|
13180
|
+
|
|
13181
|
+
// TODO: support DD.DDDDD
|
|
13182
|
+
function formatDMS(coord, fmt) {
|
|
13183
|
+
if (!fmt) fmt = '[-]D°M\'S.SSS';
|
|
13184
|
+
var str = fmt;
|
|
13185
|
+
var dstr, mstr, sstr;
|
|
13186
|
+
var match = /(D+)[^M]*(M+)[^S[\]]*(S+)?/.exec(fmt);
|
|
13187
|
+
if (!match) {
|
|
13188
|
+
stop('Invalid DMS format string:', fmt);
|
|
13189
|
+
}
|
|
13190
|
+
var gotSeconds = !!match[3];
|
|
13191
|
+
var decimals = getDecimals(fmt);
|
|
13192
|
+
var integers = gotSeconds ? match[3].length : match[2].length;
|
|
13193
|
+
var RES = Math.pow(10, decimals);
|
|
13194
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13195
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13196
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13197
|
+
if (gotSeconds) {
|
|
13198
|
+
r = Math.floor(r / (RES * 60));
|
|
13199
|
+
sstr = lastPart;
|
|
13200
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13201
|
+
} else {
|
|
13202
|
+
r = Math.floor(r / RES);
|
|
13203
|
+
mstr = lastPart;
|
|
13204
|
+
sstr = '';
|
|
13205
|
+
}
|
|
13206
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13207
|
+
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13208
|
+
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13209
|
+
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13210
|
+
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13211
|
+
str = str.replace(/D+/, dstr);
|
|
13212
|
+
str = str.replace(/M+(\.M+)?/, mstr);
|
|
13213
|
+
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13214
|
+
return str;
|
|
13215
|
+
}
|
|
13216
|
+
|
|
13118
13217
|
function cleanExpression(exp) {
|
|
13119
13218
|
// workaround for problem in GNU Make v4: end-of-line backslashes inside
|
|
13120
13219
|
// quoted strings are left in the string (other shell environments remove them)
|
|
@@ -13126,7 +13225,9 @@
|
|
|
13126
13225
|
round: roundToDigits2,
|
|
13127
13226
|
int_median: interpolated_median,
|
|
13128
13227
|
sprintf: utils.format,
|
|
13129
|
-
blend: blend
|
|
13228
|
+
blend: blend,
|
|
13229
|
+
format_dms: formatDMS,
|
|
13230
|
+
parse_dms: parseDMS
|
|
13130
13231
|
});
|
|
13131
13232
|
}
|
|
13132
13233
|
|
|
@@ -22791,7 +22892,6 @@ ${svg}
|
|
|
22791
22892
|
|
|
22792
22893
|
this.getHelpMessage = function(cmdName) {
|
|
22793
22894
|
var helpCommands, singleCommand, lines;
|
|
22794
|
-
|
|
22795
22895
|
if (cmdName) {
|
|
22796
22896
|
singleCommand = findCommandDefn(cmdName, getCommands());
|
|
22797
22897
|
if (!singleCommand) {
|
|
@@ -22910,10 +23010,6 @@ ${svg}
|
|
|
22910
23010
|
}
|
|
22911
23011
|
};
|
|
22912
23012
|
|
|
22913
|
-
this.printHelp = function(command) {
|
|
22914
|
-
print(this.getHelpMessage(command));
|
|
22915
|
-
};
|
|
22916
|
-
|
|
22917
23013
|
function getCommands() {
|
|
22918
23014
|
return _commands.map(function(cmd) {
|
|
22919
23015
|
return cmd.done();
|
|
@@ -23633,7 +23729,7 @@ ${svg}
|
|
|
23633
23729
|
type: 'flag'
|
|
23634
23730
|
})
|
|
23635
23731
|
.option('other', {
|
|
23636
|
-
describe: 'default color for categorical scheme (
|
|
23732
|
+
describe: 'default color for categorical scheme (default is nodata color)'
|
|
23637
23733
|
})
|
|
23638
23734
|
.option('nodata', {
|
|
23639
23735
|
describe: 'color to use for invalid or missing data (default is white)'
|
|
@@ -24561,7 +24657,7 @@ ${svg}
|
|
|
24561
24657
|
parser.command('symbols')
|
|
24562
24658
|
.describe('symbolize points as arrows, circles, stars, polygons, etc.')
|
|
24563
24659
|
.option('type', {
|
|
24564
|
-
describe: '
|
|
24660
|
+
describe: 'types: arrow, circle, square, star, polygon, ring'
|
|
24565
24661
|
})
|
|
24566
24662
|
.option('stroke', {})
|
|
24567
24663
|
.option('stroke-width', {})
|
|
@@ -24575,8 +24671,7 @@ ${svg}
|
|
|
24575
24671
|
describe: 'symbol line width (linear symbols only)'
|
|
24576
24672
|
})
|
|
24577
24673
|
.option('opacity', {
|
|
24578
|
-
describe: 'symbol opacity'
|
|
24579
|
-
type: 'number'
|
|
24674
|
+
describe: 'symbol opacity'
|
|
24580
24675
|
})
|
|
24581
24676
|
.option('geographic', {
|
|
24582
24677
|
old_alias: 'polygons',
|
|
@@ -24678,7 +24773,6 @@ ${svg}
|
|
|
24678
24773
|
.option('no-replace', noReplaceOpt);
|
|
24679
24774
|
// .option('name', nameOpt);
|
|
24680
24775
|
|
|
24681
|
-
|
|
24682
24776
|
parser.command('target')
|
|
24683
24777
|
.describe('set active layer (or layers)')
|
|
24684
24778
|
.option('target', {
|
|
@@ -24688,6 +24782,14 @@ ${svg}
|
|
|
24688
24782
|
.option('type', {
|
|
24689
24783
|
describe: 'type of layer to target (polygon|polyline|point)'
|
|
24690
24784
|
})
|
|
24785
|
+
// .option('combine', {
|
|
24786
|
+
// type: 'flag',
|
|
24787
|
+
// describe: 'place all targeted layers in one dataset together with any associated layers'
|
|
24788
|
+
// })
|
|
24789
|
+
// .option('isolate', {
|
|
24790
|
+
// type: 'flag',
|
|
24791
|
+
// describe: 'place all targeted layers in one dataset exclusive of associated layers'
|
|
24792
|
+
// })
|
|
24691
24793
|
.option('name', {
|
|
24692
24794
|
describe: 'rename the target layer'
|
|
24693
24795
|
});
|
|
@@ -38520,6 +38622,11 @@ ${svg}
|
|
|
38520
38622
|
};
|
|
38521
38623
|
}
|
|
38522
38624
|
|
|
38625
|
+
cmd.printHelp = function(opts) {
|
|
38626
|
+
var str = getOptionParser().getHelpMessage(opts.command);
|
|
38627
|
+
print(str);
|
|
38628
|
+
};
|
|
38629
|
+
|
|
38523
38630
|
function resetControlFlow(job) {
|
|
38524
38631
|
job.control = null;
|
|
38525
38632
|
}
|
|
@@ -39159,25 +39266,6 @@ ${svg}
|
|
|
39159
39266
|
};
|
|
39160
39267
|
}
|
|
39161
39268
|
|
|
39162
|
-
// Parse a formatted value in DMS DM or D to a numeric value. Returns NaN if unparsable.
|
|
39163
|
-
// Delimiters: degrees: D|d|°; minutes: '; seconds: "
|
|
39164
|
-
function parseDMS(str) {
|
|
39165
|
-
var rxp = /^([nsew+-]?)([0-9.]+)[d°]? ?([0-9.]*)['′]? ?([0-9.]*)["″]? ?([nsew]?)$/i;
|
|
39166
|
-
var match = rxp.exec(str.trim());
|
|
39167
|
-
var d = NaN;
|
|
39168
|
-
var deg, min, sec;
|
|
39169
|
-
if (match) {
|
|
39170
|
-
deg = match[2] || '0';
|
|
39171
|
-
min = match[3] || '0';
|
|
39172
|
-
sec = match[4] || '0';
|
|
39173
|
-
d = (+deg) + (+min) / 60 + (+sec) / 3600;
|
|
39174
|
-
if (/[sw-]/i.test(match[1]) || /[sw]/i.test(match[5])) {
|
|
39175
|
-
d = -d;
|
|
39176
|
-
}
|
|
39177
|
-
}
|
|
39178
|
-
return d;
|
|
39179
|
-
}
|
|
39180
|
-
|
|
39181
39269
|
function findNearestVertices(p, shp, arcs) {
|
|
39182
39270
|
var p2 = findNearestVertex(p[0], p[1], shp, arcs);
|
|
39183
39271
|
return findVertexIds(p2.x, p2.y, arcs);
|
|
@@ -42827,9 +42915,41 @@ ${svg}
|
|
|
42827
42915
|
// TODO: improve this
|
|
42828
42916
|
targets[0].layers[0].name = opts.name;
|
|
42829
42917
|
}
|
|
42918
|
+
if (opts.combine) {
|
|
42919
|
+
targets = combineTargets(targets, catalog);
|
|
42920
|
+
} else if (opts.isolate) {
|
|
42921
|
+
targets = isolateTargets(targets, catalog);
|
|
42922
|
+
}
|
|
42830
42923
|
catalog.setDefaultTargets(targets);
|
|
42831
42924
|
};
|
|
42832
42925
|
|
|
42926
|
+
function combineTargets(targets, catalog) {
|
|
42927
|
+
var datasets = [];
|
|
42928
|
+
var layers = [];
|
|
42929
|
+
targets.forEach(function(o) {
|
|
42930
|
+
datasets.push(o.dataset);
|
|
42931
|
+
catalog.removeDataset(o.dataset);
|
|
42932
|
+
layers = layers.concat(o.layers);
|
|
42933
|
+
});
|
|
42934
|
+
var combined = mergeDatasets(datasets);
|
|
42935
|
+
catalog.addDataset(combined);
|
|
42936
|
+
return [{
|
|
42937
|
+
dataset: combined,
|
|
42938
|
+
layers: layers
|
|
42939
|
+
}];
|
|
42940
|
+
}
|
|
42941
|
+
|
|
42942
|
+
function isolateTargets(targets, catalog) {
|
|
42943
|
+
var datasets = [];
|
|
42944
|
+
targets.forEach(function(o) {
|
|
42945
|
+
datasets.push(o.dataset);
|
|
42946
|
+
o.layers.forEach(function(lyr) {
|
|
42947
|
+
catalog.removeLayer(lyr, o.dataset);
|
|
42948
|
+
|
|
42949
|
+
});
|
|
42950
|
+
});
|
|
42951
|
+
}
|
|
42952
|
+
|
|
42833
42953
|
cmd.union = function(targetLayers, targetDataset, opts) {
|
|
42834
42954
|
if (targetLayers.length < 2) {
|
|
42835
42955
|
stop('Command requires at least two target layers');
|
|
@@ -43214,7 +43334,7 @@ ${svg}
|
|
|
43214
43334
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43215
43335
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43216
43336
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43217
|
-
name == 'else' || name == 'endif' || name == 'run';
|
|
43337
|
+
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43218
43338
|
}
|
|
43219
43339
|
|
|
43220
43340
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -43403,8 +43523,8 @@ ${svg}
|
|
|
43403
43523
|
job.catalog.addDataset(cmd.graticule(targetDataset, opts));
|
|
43404
43524
|
|
|
43405
43525
|
} else if (name == 'help') {
|
|
43406
|
-
// placing
|
|
43407
|
-
|
|
43526
|
+
// placing help command here to handle errors from invalid command names
|
|
43527
|
+
cmd.printHelp(command.options);
|
|
43408
43528
|
|
|
43409
43529
|
} else if (name == 'i') {
|
|
43410
43530
|
if (opts.replace) job.catalog = new Catalog(); // is this what we want?
|
|
@@ -43486,7 +43606,7 @@ ${svg}
|
|
|
43486
43606
|
cmd.print(command._.join(' '));
|
|
43487
43607
|
|
|
43488
43608
|
} else if (name == 'proj') {
|
|
43489
|
-
await
|
|
43609
|
+
await initProjLibrary(opts);
|
|
43490
43610
|
job.resumeCommand();
|
|
43491
43611
|
targets.forEach(function(targ) {
|
|
43492
43612
|
cmd.proj(targ.dataset, job.catalog, opts);
|
|
@@ -44321,6 +44441,7 @@ ${svg}
|
|
|
44321
44441
|
Heap,
|
|
44322
44442
|
NodeCollection,
|
|
44323
44443
|
parseDMS,
|
|
44444
|
+
formatDMS,
|
|
44324
44445
|
PathIndex,
|
|
44325
44446
|
PolygonIndex,
|
|
44326
44447
|
ShpReader,
|
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -2479,42 +2479,18 @@
|
|
|
2479
2479
|
});
|
|
2480
2480
|
}
|
|
2481
2481
|
|
|
2482
|
+
internal.setProjectionLoader(loadProjLibs);
|
|
2483
|
+
|
|
2482
2484
|
// load Proj.4 CRS definition files dynamically
|
|
2483
2485
|
//
|
|
2484
|
-
|
|
2486
|
+
async function loadProjLibs(opts) {
|
|
2485
2487
|
var mproj = require('mproj');
|
|
2486
2488
|
var libs = internal.findProjLibs([opts.init || '', opts.match || '', opts.crs || ''].join(' '));
|
|
2487
|
-
// skip loaded libs
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
function loadProjLibs(libs, done) {
|
|
2493
|
-
var mproj = require('mproj');
|
|
2494
|
-
var i = 0;
|
|
2495
|
-
next();
|
|
2496
|
-
|
|
2497
|
-
function next() {
|
|
2498
|
-
var libName = libs[i];
|
|
2499
|
-
var content, req;
|
|
2500
|
-
if (!libName) return done();
|
|
2501
|
-
req = new XMLHttpRequest();
|
|
2502
|
-
req.addEventListener('load', function(e) {
|
|
2503
|
-
if (req.status == 200) {
|
|
2504
|
-
content = req.response;
|
|
2505
|
-
}
|
|
2506
|
-
});
|
|
2507
|
-
req.addEventListener('loadend', function() {
|
|
2508
|
-
if (content) {
|
|
2509
|
-
mproj.internal.mproj_insert_libcache(libName, content);
|
|
2510
|
-
}
|
|
2511
|
-
// TODO: consider stopping with an error message if no content was loaded
|
|
2512
|
-
// (currently, a less specific error will occur when mapshaper tries to use the library)
|
|
2513
|
-
next();
|
|
2514
|
-
});
|
|
2515
|
-
req.open('GET', 'assets/' + libName);
|
|
2516
|
-
req.send();
|
|
2517
|
-
i++;
|
|
2489
|
+
libs = libs.filter(function(name) {return !mproj.internal.mproj_search_libcache(name);}); // skip loaded libs
|
|
2490
|
+
for (var libName of libs) {
|
|
2491
|
+
var content = await fetch('assets/' + libName).then(resp => resp.ok ? resp.text() : null);
|
|
2492
|
+
if (!content) stop$1(`Unable to load projection resource [${libName}]`);
|
|
2493
|
+
mproj.internal.mproj_insert_libcache(libName, content);
|
|
2518
2494
|
}
|
|
2519
2495
|
}
|
|
2520
2496
|
|
|
@@ -3371,7 +3347,10 @@
|
|
|
3371
3347
|
setDisplayProjection(gui, cmd);
|
|
3372
3348
|
} else {
|
|
3373
3349
|
line.hide(); // hide cursor while command is being run
|
|
3374
|
-
runMapshaperCommands(cmd, function(err) {
|
|
3350
|
+
runMapshaperCommands(cmd, function(err, flags) {
|
|
3351
|
+
if (flags) {
|
|
3352
|
+
gui.clearMode();
|
|
3353
|
+
}
|
|
3375
3354
|
if (err) {
|
|
3376
3355
|
onError(err);
|
|
3377
3356
|
}
|
|
@@ -3404,14 +3383,9 @@
|
|
|
3404
3383
|
}
|
|
3405
3384
|
}
|
|
3406
3385
|
if (flags) {
|
|
3407
|
-
// if the command may have changed data, and a tool with an edit mode is being used,
|
|
3408
|
-
// close the tool. (we may need a better way to allow the console and other tools
|
|
3409
|
-
// to be used at the same time).
|
|
3410
|
-
gui.clearMode();
|
|
3411
|
-
|
|
3412
3386
|
model.updated(flags); // info commands do not return flags
|
|
3413
3387
|
}
|
|
3414
|
-
done(err);
|
|
3388
|
+
done(err, flags);
|
|
3415
3389
|
});
|
|
3416
3390
|
}
|
|
3417
3391
|
|
|
@@ -5068,7 +5042,8 @@
|
|
|
5068
5042
|
|
|
5069
5043
|
// Handle an error caused by invalid input or misuse of API
|
|
5070
5044
|
function stop() {
|
|
5071
|
-
_stop.apply(null, utils.toArray(arguments));
|
|
5045
|
+
// _stop.apply(null, utils.toArray(arguments));
|
|
5046
|
+
_stop.apply(null, messageArgs(arguments));
|
|
5072
5047
|
}
|
|
5073
5048
|
|
|
5074
5049
|
function interrupt() {
|
|
@@ -7976,10 +7951,11 @@
|
|
|
7976
7951
|
hit.clearSelection();
|
|
7977
7952
|
});
|
|
7978
7953
|
|
|
7979
|
-
function runCommand(cmd) {
|
|
7954
|
+
function runCommand(cmd, turnOff) {
|
|
7980
7955
|
popup.hide();
|
|
7981
7956
|
if (gui.console) gui.console.runMapshaperCommands(cmd, function(err) {
|
|
7982
7957
|
reset();
|
|
7958
|
+
if (turnOff) gui.clearMode();
|
|
7983
7959
|
});
|
|
7984
7960
|
}
|
|
7985
7961
|
}
|
|
@@ -10311,6 +10287,7 @@
|
|
|
10311
10287
|
if (gui.console) {
|
|
10312
10288
|
gui.console.runMapshaperCommands(cmd, function(err) {
|
|
10313
10289
|
reset();
|
|
10290
|
+
gui.clearMode();
|
|
10314
10291
|
});
|
|
10315
10292
|
}
|
|
10316
10293
|
// reset(); // TODO: exit interactive mode
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.39";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
get rtrim () { return rtrim; },
|
|
66
66
|
get addThousandsSep () { return addThousandsSep; },
|
|
67
67
|
get numToStr () { return numToStr; },
|
|
68
|
-
get formatNumber () { return formatNumber; },
|
|
68
|
+
get formatNumber () { return formatNumber$1; },
|
|
69
69
|
get formatIntlNumber () { return formatIntlNumber; },
|
|
70
70
|
get formatNumberForDisplay () { return formatNumberForDisplay; },
|
|
71
71
|
get shuffle () { return shuffle; },
|
|
@@ -649,12 +649,12 @@
|
|
|
649
649
|
return decimals >= 0 ? num.toFixed(decimals) : String(num);
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
function formatNumber(val) {
|
|
652
|
+
function formatNumber$1(val) {
|
|
653
653
|
return val + '';
|
|
654
654
|
}
|
|
655
655
|
|
|
656
656
|
function formatIntlNumber(val) {
|
|
657
|
-
var str = formatNumber(val);
|
|
657
|
+
var str = formatNumber$1(val);
|
|
658
658
|
return '"' + str.replace('.', ',') + '"'; // need to quote if comma-delimited
|
|
659
659
|
}
|
|
660
660
|
|
|
@@ -1247,7 +1247,8 @@
|
|
|
1247
1247
|
|
|
1248
1248
|
// Handle an error caused by invalid input or misuse of API
|
|
1249
1249
|
function stop() {
|
|
1250
|
-
_stop.apply(null, utils.toArray(arguments));
|
|
1250
|
+
// _stop.apply(null, utils.toArray(arguments));
|
|
1251
|
+
_stop.apply(null, messageArgs(arguments));
|
|
1251
1252
|
}
|
|
1252
1253
|
|
|
1253
1254
|
function interrupt() {
|
|
@@ -4670,12 +4671,11 @@
|
|
|
4670
4671
|
albersusa: AlbersUSA
|
|
4671
4672
|
};
|
|
4672
4673
|
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
if (!asyncLoader) return done();
|
|
4676
|
-
asyncLoader(opts, done);
|
|
4674
|
+
async function initProjLibrary(opts) {
|
|
4675
|
+
if (asyncLoader) await asyncLoader(opts);
|
|
4677
4676
|
}
|
|
4678
4677
|
|
|
4678
|
+
// used by web UI to support loading projection assets asyncronously
|
|
4679
4679
|
function setProjectionLoader(loader) {
|
|
4680
4680
|
asyncLoader = loader;
|
|
4681
4681
|
}
|
|
@@ -13115,6 +13115,105 @@
|
|
|
13115
13115
|
});
|
|
13116
13116
|
}
|
|
13117
13117
|
|
|
13118
|
+
// Parse a formatted value in DMS DM or D to a numeric value. Returns NaN if unparsable.
|
|
13119
|
+
// Delimiters: degrees: D|d|°; minutes: '; seconds: "
|
|
13120
|
+
function parseDMS(str, fmt) {
|
|
13121
|
+
var defaultRxp = /^(?<prefix>[nsew+-]?)(?<d>[0-9.]+)[d°]? ?(?<m>[0-9.]*)['′]? ?(?<s>[0-9.]*)["″]? ?(?<suffix>[nsew]?)$/i;
|
|
13122
|
+
var rxp = fmt ? getParseRxp(fmt) : defaultRxp;
|
|
13123
|
+
var match = rxp.exec(str.trim());
|
|
13124
|
+
var d = NaN;
|
|
13125
|
+
var deg, min, sec;
|
|
13126
|
+
if (match) {
|
|
13127
|
+
deg = match.groups.d || '0';
|
|
13128
|
+
min = match.groups.m || '0';
|
|
13129
|
+
sec = match.groups.s || '0';
|
|
13130
|
+
d = (+deg) + (+min) / 60 + (+sec) / 3600;
|
|
13131
|
+
if (/[sw-]/i.test(match.groups.prefix || '') || /[sw]/i.test(match.groups.suffix || '')) {
|
|
13132
|
+
d = -d;
|
|
13133
|
+
}
|
|
13134
|
+
}
|
|
13135
|
+
return d;
|
|
13136
|
+
}
|
|
13137
|
+
|
|
13138
|
+
var cache$1 = {};
|
|
13139
|
+
|
|
13140
|
+
function getParseRxp(fmt) {
|
|
13141
|
+
if (fmt in cache$1) return cache$1[fmt];
|
|
13142
|
+
var rxp = fmt;
|
|
13143
|
+
rxp = rxp.replace('[-]', '(?<prefix>-)?'); // optional -
|
|
13144
|
+
rxp = rxp.replace(/\[[NSEW, +-]{2,}\]/, '(?<prefix>$&)');
|
|
13145
|
+
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13146
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13147
|
+
if (g2) s += `\\.[0-9]+`;
|
|
13148
|
+
return `(?<m>${s})`;
|
|
13149
|
+
});
|
|
13150
|
+
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13151
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13152
|
+
if (g2) s += `\\.[0-9]+`;
|
|
13153
|
+
return `(?<s>${s})`;
|
|
13154
|
+
});
|
|
13155
|
+
rxp = rxp.replace(/D+/, '(?<d>[0-9]+)');
|
|
13156
|
+
rxp = '^' + rxp + '$';
|
|
13157
|
+
try {
|
|
13158
|
+
// TODO: make sure all DMS codes have been matched
|
|
13159
|
+
cache$1[fmt] = new RegExp(rxp);
|
|
13160
|
+
} catch(e) {
|
|
13161
|
+
stop('Invalid DMS format string:', fmt);
|
|
13162
|
+
}
|
|
13163
|
+
return cache$1[fmt];
|
|
13164
|
+
}
|
|
13165
|
+
|
|
13166
|
+
function formatNumber(val, integers, decimals) {
|
|
13167
|
+
var str = val.toFixed(decimals);
|
|
13168
|
+
var parts = str.split('.');
|
|
13169
|
+
if (parts.length > 0) {
|
|
13170
|
+
parts[0] = parts[0].padStart(integers, '0');
|
|
13171
|
+
str = parts.join('.');
|
|
13172
|
+
}
|
|
13173
|
+
return str;
|
|
13174
|
+
}
|
|
13175
|
+
|
|
13176
|
+
function getDecimals(fmt) {
|
|
13177
|
+
var match = /S\.(S+)/.exec(fmt) || /M\.(M+)/.exec(fmt) || null;
|
|
13178
|
+
return match ? match[1].length : 0;
|
|
13179
|
+
}
|
|
13180
|
+
|
|
13181
|
+
// TODO: support DD.DDDDD
|
|
13182
|
+
function formatDMS(coord, fmt) {
|
|
13183
|
+
if (!fmt) fmt = '[-]D°M\'S.SSS';
|
|
13184
|
+
var str = fmt;
|
|
13185
|
+
var dstr, mstr, sstr;
|
|
13186
|
+
var match = /(D+)[^M]*(M+)[^S[\]]*(S+)?/.exec(fmt);
|
|
13187
|
+
if (!match) {
|
|
13188
|
+
stop('Invalid DMS format string:', fmt);
|
|
13189
|
+
}
|
|
13190
|
+
var gotSeconds = !!match[3];
|
|
13191
|
+
var decimals = getDecimals(fmt);
|
|
13192
|
+
var integers = gotSeconds ? match[3].length : match[2].length;
|
|
13193
|
+
var RES = Math.pow(10, decimals);
|
|
13194
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13195
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13196
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13197
|
+
if (gotSeconds) {
|
|
13198
|
+
r = Math.floor(r / (RES * 60));
|
|
13199
|
+
sstr = lastPart;
|
|
13200
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13201
|
+
} else {
|
|
13202
|
+
r = Math.floor(r / RES);
|
|
13203
|
+
mstr = lastPart;
|
|
13204
|
+
sstr = '';
|
|
13205
|
+
}
|
|
13206
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13207
|
+
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13208
|
+
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13209
|
+
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13210
|
+
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13211
|
+
str = str.replace(/D+/, dstr);
|
|
13212
|
+
str = str.replace(/M+(\.M+)?/, mstr);
|
|
13213
|
+
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13214
|
+
return str;
|
|
13215
|
+
}
|
|
13216
|
+
|
|
13118
13217
|
function cleanExpression(exp) {
|
|
13119
13218
|
// workaround for problem in GNU Make v4: end-of-line backslashes inside
|
|
13120
13219
|
// quoted strings are left in the string (other shell environments remove them)
|
|
@@ -13126,7 +13225,9 @@
|
|
|
13126
13225
|
round: roundToDigits2,
|
|
13127
13226
|
int_median: interpolated_median,
|
|
13128
13227
|
sprintf: utils.format,
|
|
13129
|
-
blend: blend
|
|
13228
|
+
blend: blend,
|
|
13229
|
+
format_dms: formatDMS,
|
|
13230
|
+
parse_dms: parseDMS
|
|
13130
13231
|
});
|
|
13131
13232
|
}
|
|
13132
13233
|
|
|
@@ -22791,7 +22892,6 @@ ${svg}
|
|
|
22791
22892
|
|
|
22792
22893
|
this.getHelpMessage = function(cmdName) {
|
|
22793
22894
|
var helpCommands, singleCommand, lines;
|
|
22794
|
-
|
|
22795
22895
|
if (cmdName) {
|
|
22796
22896
|
singleCommand = findCommandDefn(cmdName, getCommands());
|
|
22797
22897
|
if (!singleCommand) {
|
|
@@ -22910,10 +23010,6 @@ ${svg}
|
|
|
22910
23010
|
}
|
|
22911
23011
|
};
|
|
22912
23012
|
|
|
22913
|
-
this.printHelp = function(command) {
|
|
22914
|
-
print(this.getHelpMessage(command));
|
|
22915
|
-
};
|
|
22916
|
-
|
|
22917
23013
|
function getCommands() {
|
|
22918
23014
|
return _commands.map(function(cmd) {
|
|
22919
23015
|
return cmd.done();
|
|
@@ -23633,7 +23729,7 @@ ${svg}
|
|
|
23633
23729
|
type: 'flag'
|
|
23634
23730
|
})
|
|
23635
23731
|
.option('other', {
|
|
23636
|
-
describe: 'default color for categorical scheme (
|
|
23732
|
+
describe: 'default color for categorical scheme (default is nodata color)'
|
|
23637
23733
|
})
|
|
23638
23734
|
.option('nodata', {
|
|
23639
23735
|
describe: 'color to use for invalid or missing data (default is white)'
|
|
@@ -24561,7 +24657,7 @@ ${svg}
|
|
|
24561
24657
|
parser.command('symbols')
|
|
24562
24658
|
.describe('symbolize points as arrows, circles, stars, polygons, etc.')
|
|
24563
24659
|
.option('type', {
|
|
24564
|
-
describe: '
|
|
24660
|
+
describe: 'types: arrow, circle, square, star, polygon, ring'
|
|
24565
24661
|
})
|
|
24566
24662
|
.option('stroke', {})
|
|
24567
24663
|
.option('stroke-width', {})
|
|
@@ -24575,8 +24671,7 @@ ${svg}
|
|
|
24575
24671
|
describe: 'symbol line width (linear symbols only)'
|
|
24576
24672
|
})
|
|
24577
24673
|
.option('opacity', {
|
|
24578
|
-
describe: 'symbol opacity'
|
|
24579
|
-
type: 'number'
|
|
24674
|
+
describe: 'symbol opacity'
|
|
24580
24675
|
})
|
|
24581
24676
|
.option('geographic', {
|
|
24582
24677
|
old_alias: 'polygons',
|
|
@@ -24678,7 +24773,6 @@ ${svg}
|
|
|
24678
24773
|
.option('no-replace', noReplaceOpt);
|
|
24679
24774
|
// .option('name', nameOpt);
|
|
24680
24775
|
|
|
24681
|
-
|
|
24682
24776
|
parser.command('target')
|
|
24683
24777
|
.describe('set active layer (or layers)')
|
|
24684
24778
|
.option('target', {
|
|
@@ -24688,6 +24782,14 @@ ${svg}
|
|
|
24688
24782
|
.option('type', {
|
|
24689
24783
|
describe: 'type of layer to target (polygon|polyline|point)'
|
|
24690
24784
|
})
|
|
24785
|
+
// .option('combine', {
|
|
24786
|
+
// type: 'flag',
|
|
24787
|
+
// describe: 'place all targeted layers in one dataset together with any associated layers'
|
|
24788
|
+
// })
|
|
24789
|
+
// .option('isolate', {
|
|
24790
|
+
// type: 'flag',
|
|
24791
|
+
// describe: 'place all targeted layers in one dataset exclusive of associated layers'
|
|
24792
|
+
// })
|
|
24691
24793
|
.option('name', {
|
|
24692
24794
|
describe: 'rename the target layer'
|
|
24693
24795
|
});
|
|
@@ -38520,6 +38622,11 @@ ${svg}
|
|
|
38520
38622
|
};
|
|
38521
38623
|
}
|
|
38522
38624
|
|
|
38625
|
+
cmd.printHelp = function(opts) {
|
|
38626
|
+
var str = getOptionParser().getHelpMessage(opts.command);
|
|
38627
|
+
print(str);
|
|
38628
|
+
};
|
|
38629
|
+
|
|
38523
38630
|
function resetControlFlow(job) {
|
|
38524
38631
|
job.control = null;
|
|
38525
38632
|
}
|
|
@@ -39159,25 +39266,6 @@ ${svg}
|
|
|
39159
39266
|
};
|
|
39160
39267
|
}
|
|
39161
39268
|
|
|
39162
|
-
// Parse a formatted value in DMS DM or D to a numeric value. Returns NaN if unparsable.
|
|
39163
|
-
// Delimiters: degrees: D|d|°; minutes: '; seconds: "
|
|
39164
|
-
function parseDMS(str) {
|
|
39165
|
-
var rxp = /^([nsew+-]?)([0-9.]+)[d°]? ?([0-9.]*)['′]? ?([0-9.]*)["″]? ?([nsew]?)$/i;
|
|
39166
|
-
var match = rxp.exec(str.trim());
|
|
39167
|
-
var d = NaN;
|
|
39168
|
-
var deg, min, sec;
|
|
39169
|
-
if (match) {
|
|
39170
|
-
deg = match[2] || '0';
|
|
39171
|
-
min = match[3] || '0';
|
|
39172
|
-
sec = match[4] || '0';
|
|
39173
|
-
d = (+deg) + (+min) / 60 + (+sec) / 3600;
|
|
39174
|
-
if (/[sw-]/i.test(match[1]) || /[sw]/i.test(match[5])) {
|
|
39175
|
-
d = -d;
|
|
39176
|
-
}
|
|
39177
|
-
}
|
|
39178
|
-
return d;
|
|
39179
|
-
}
|
|
39180
|
-
|
|
39181
39269
|
function findNearestVertices(p, shp, arcs) {
|
|
39182
39270
|
var p2 = findNearestVertex(p[0], p[1], shp, arcs);
|
|
39183
39271
|
return findVertexIds(p2.x, p2.y, arcs);
|
|
@@ -42827,9 +42915,41 @@ ${svg}
|
|
|
42827
42915
|
// TODO: improve this
|
|
42828
42916
|
targets[0].layers[0].name = opts.name;
|
|
42829
42917
|
}
|
|
42918
|
+
if (opts.combine) {
|
|
42919
|
+
targets = combineTargets(targets, catalog);
|
|
42920
|
+
} else if (opts.isolate) {
|
|
42921
|
+
targets = isolateTargets(targets, catalog);
|
|
42922
|
+
}
|
|
42830
42923
|
catalog.setDefaultTargets(targets);
|
|
42831
42924
|
};
|
|
42832
42925
|
|
|
42926
|
+
function combineTargets(targets, catalog) {
|
|
42927
|
+
var datasets = [];
|
|
42928
|
+
var layers = [];
|
|
42929
|
+
targets.forEach(function(o) {
|
|
42930
|
+
datasets.push(o.dataset);
|
|
42931
|
+
catalog.removeDataset(o.dataset);
|
|
42932
|
+
layers = layers.concat(o.layers);
|
|
42933
|
+
});
|
|
42934
|
+
var combined = mergeDatasets(datasets);
|
|
42935
|
+
catalog.addDataset(combined);
|
|
42936
|
+
return [{
|
|
42937
|
+
dataset: combined,
|
|
42938
|
+
layers: layers
|
|
42939
|
+
}];
|
|
42940
|
+
}
|
|
42941
|
+
|
|
42942
|
+
function isolateTargets(targets, catalog) {
|
|
42943
|
+
var datasets = [];
|
|
42944
|
+
targets.forEach(function(o) {
|
|
42945
|
+
datasets.push(o.dataset);
|
|
42946
|
+
o.layers.forEach(function(lyr) {
|
|
42947
|
+
catalog.removeLayer(lyr, o.dataset);
|
|
42948
|
+
|
|
42949
|
+
});
|
|
42950
|
+
});
|
|
42951
|
+
}
|
|
42952
|
+
|
|
42833
42953
|
cmd.union = function(targetLayers, targetDataset, opts) {
|
|
42834
42954
|
if (targetLayers.length < 2) {
|
|
42835
42955
|
stop('Command requires at least two target layers');
|
|
@@ -43214,7 +43334,7 @@ ${svg}
|
|
|
43214
43334
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43215
43335
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43216
43336
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43217
|
-
name == 'else' || name == 'endif' || name == 'run';
|
|
43337
|
+
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43218
43338
|
}
|
|
43219
43339
|
|
|
43220
43340
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -43403,8 +43523,8 @@ ${svg}
|
|
|
43403
43523
|
job.catalog.addDataset(cmd.graticule(targetDataset, opts));
|
|
43404
43524
|
|
|
43405
43525
|
} else if (name == 'help') {
|
|
43406
|
-
// placing
|
|
43407
|
-
|
|
43526
|
+
// placing help command here to handle errors from invalid command names
|
|
43527
|
+
cmd.printHelp(command.options);
|
|
43408
43528
|
|
|
43409
43529
|
} else if (name == 'i') {
|
|
43410
43530
|
if (opts.replace) job.catalog = new Catalog(); // is this what we want?
|
|
@@ -43486,7 +43606,7 @@ ${svg}
|
|
|
43486
43606
|
cmd.print(command._.join(' '));
|
|
43487
43607
|
|
|
43488
43608
|
} else if (name == 'proj') {
|
|
43489
|
-
await
|
|
43609
|
+
await initProjLibrary(opts);
|
|
43490
43610
|
job.resumeCommand();
|
|
43491
43611
|
targets.forEach(function(targ) {
|
|
43492
43612
|
cmd.proj(targ.dataset, job.catalog, opts);
|
|
@@ -44321,6 +44441,7 @@ ${svg}
|
|
|
44321
44441
|
Heap,
|
|
44322
44442
|
NodeCollection,
|
|
44323
44443
|
parseDMS,
|
|
44444
|
+
formatDMS,
|
|
44324
44445
|
PathIndex,
|
|
44325
44446
|
PolygonIndex,
|
|
44326
44447
|
ShpReader,
|