mapshaper 0.6.38 → 0.6.40
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 +183 -47
- package/package.json +1 -1
- package/www/index.html +11 -3
- package/www/mapshaper-gui.js +24 -45
- package/www/mapshaper.js +183 -47
- package/www/page.css +3 -11
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.40";
|
|
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,110 @@
|
|
|
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
|
+
// TODO: validate that if there are degree decimals, there are no M or S codes
|
|
13146
|
+
rxp = rxp.replace(/D+(\.D+)?/, (m, g1) => {
|
|
13147
|
+
var s = '[0-9]+';
|
|
13148
|
+
if (g1) s += `\\.[0-9]+`;
|
|
13149
|
+
return `(?<d>${s})`;
|
|
13150
|
+
});
|
|
13151
|
+
// TODO: validate that if there are minutes decimals, there are no S codes
|
|
13152
|
+
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13153
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13154
|
+
if (g2) s += '\\.[0-9]+';
|
|
13155
|
+
return `(?<m>${s})`;
|
|
13156
|
+
});
|
|
13157
|
+
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13158
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13159
|
+
if (g2) s += '\\.[0-9]+';
|
|
13160
|
+
return `(?<s>${s})`;
|
|
13161
|
+
});
|
|
13162
|
+
rxp = '^' + rxp + '$';
|
|
13163
|
+
try {
|
|
13164
|
+
// TODO: make sure all DMS codes have been matched
|
|
13165
|
+
cache$1[fmt] = new RegExp(rxp);
|
|
13166
|
+
} catch(e) {
|
|
13167
|
+
stop('Invalid DMS format string:', fmt);
|
|
13168
|
+
}
|
|
13169
|
+
return cache$1[fmt];
|
|
13170
|
+
}
|
|
13171
|
+
|
|
13172
|
+
function formatNumber(val, integers, decimals) {
|
|
13173
|
+
var str = val.toFixed(decimals);
|
|
13174
|
+
var parts = str.split('.');
|
|
13175
|
+
if (parts.length > 0) {
|
|
13176
|
+
parts[0] = parts[0].padStart(integers, '0');
|
|
13177
|
+
str = parts.join('.');
|
|
13178
|
+
}
|
|
13179
|
+
return str;
|
|
13180
|
+
}
|
|
13181
|
+
|
|
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
|
+
var gotSeconds = match && !!match[3];
|
|
13188
|
+
var gotMinutes = match && !!match[2];
|
|
13189
|
+
if (!match || gotSeconds && !gotMinutes) {
|
|
13190
|
+
stop('Invalid DMS format string:', fmt);
|
|
13191
|
+
}
|
|
13192
|
+
var integers = gotSeconds && match[3].length || gotMinutes && match[2].length || match[1].length;
|
|
13193
|
+
var decimalRxp = gotSeconds && /S\.(S+)/ || gotMinutes && /M\.(M+)/ || /D\.(D+)/;
|
|
13194
|
+
var decimals = decimalRxp.test(fmt) ? decimalRxp.exec(fmt)[1].length : 0;
|
|
13195
|
+
if (gotMinutes) {
|
|
13196
|
+
var RES = Math.pow(10, decimals);
|
|
13197
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13198
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13199
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13200
|
+
if (gotSeconds) {
|
|
13201
|
+
r = Math.floor(r / (RES * 60));
|
|
13202
|
+
sstr = lastPart;
|
|
13203
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13204
|
+
} else {
|
|
13205
|
+
r = Math.floor(r / RES);
|
|
13206
|
+
mstr = lastPart;
|
|
13207
|
+
}
|
|
13208
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13209
|
+
} else {
|
|
13210
|
+
dstr = Math.abs(coord).toFixed(decimals);
|
|
13211
|
+
}
|
|
13212
|
+
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13213
|
+
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13214
|
+
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13215
|
+
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13216
|
+
str = str.replace(/D+(\.D+)?/, dstr);
|
|
13217
|
+
if (gotMinutes) str = str.replace(/M+(\.M+)?/, mstr);
|
|
13218
|
+
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13219
|
+
return str;
|
|
13220
|
+
}
|
|
13221
|
+
|
|
13118
13222
|
function cleanExpression(exp) {
|
|
13119
13223
|
// workaround for problem in GNU Make v4: end-of-line backslashes inside
|
|
13120
13224
|
// quoted strings are left in the string (other shell environments remove them)
|
|
@@ -13126,7 +13230,9 @@
|
|
|
13126
13230
|
round: roundToDigits2,
|
|
13127
13231
|
int_median: interpolated_median,
|
|
13128
13232
|
sprintf: utils.format,
|
|
13129
|
-
blend: blend
|
|
13233
|
+
blend: blend,
|
|
13234
|
+
format_dms: formatDMS,
|
|
13235
|
+
parse_dms: parseDMS
|
|
13130
13236
|
});
|
|
13131
13237
|
}
|
|
13132
13238
|
|
|
@@ -17598,12 +17704,18 @@
|
|
|
17598
17704
|
}
|
|
17599
17705
|
|
|
17600
17706
|
function calcFrameData(dataset, opts) {
|
|
17601
|
-
var bounds
|
|
17602
|
-
|
|
17707
|
+
var bounds;
|
|
17708
|
+
if (opts.svg_bbox) {
|
|
17709
|
+
bounds = new Bounds(opts.svg_bbox);
|
|
17710
|
+
opts = Object.assign({margin: 0}, opts); // prevent default pixel margin around content
|
|
17711
|
+
} else {
|
|
17712
|
+
bounds = getDatasetBounds(dataset);
|
|
17713
|
+
}
|
|
17714
|
+
var pixBounds = calcOutputSizeInPixels(bounds, opts);
|
|
17603
17715
|
return {
|
|
17604
17716
|
bbox: bounds.toArray(),
|
|
17605
|
-
width: Math.round(
|
|
17606
|
-
height: Math.round(
|
|
17717
|
+
width: Math.round(pixBounds.width()),
|
|
17718
|
+
height: Math.round(pixBounds.height()) || 1,
|
|
17607
17719
|
type: 'frame'
|
|
17608
17720
|
};
|
|
17609
17721
|
}
|
|
@@ -22791,7 +22903,6 @@ ${svg}
|
|
|
22791
22903
|
|
|
22792
22904
|
this.getHelpMessage = function(cmdName) {
|
|
22793
22905
|
var helpCommands, singleCommand, lines;
|
|
22794
|
-
|
|
22795
22906
|
if (cmdName) {
|
|
22796
22907
|
singleCommand = findCommandDefn(cmdName, getCommands());
|
|
22797
22908
|
if (!singleCommand) {
|
|
@@ -22910,10 +23021,6 @@ ${svg}
|
|
|
22910
23021
|
}
|
|
22911
23022
|
};
|
|
22912
23023
|
|
|
22913
|
-
this.printHelp = function(command) {
|
|
22914
|
-
print(this.getHelpMessage(command));
|
|
22915
|
-
};
|
|
22916
|
-
|
|
22917
23024
|
function getCommands() {
|
|
22918
23025
|
return _commands.map(function(cmd) {
|
|
22919
23026
|
return cmd.done();
|
|
@@ -23343,6 +23450,10 @@ ${svg}
|
|
|
23343
23450
|
describe: '[SVG] source units per pixel (alternative to width= option)',
|
|
23344
23451
|
type: 'number'
|
|
23345
23452
|
})
|
|
23453
|
+
.option('svg-bbox', {
|
|
23454
|
+
describe: '[SVG] bounding box of SVG map in projected map units',
|
|
23455
|
+
type: 'bbox'
|
|
23456
|
+
})
|
|
23346
23457
|
.option('point-symbol', {
|
|
23347
23458
|
describe: '[SVG] circle or square (default is circle)'
|
|
23348
23459
|
})
|
|
@@ -23633,7 +23744,7 @@ ${svg}
|
|
|
23633
23744
|
type: 'flag'
|
|
23634
23745
|
})
|
|
23635
23746
|
.option('other', {
|
|
23636
|
-
describe: 'default color for categorical scheme (
|
|
23747
|
+
describe: 'default color for categorical scheme (default is nodata color)'
|
|
23637
23748
|
})
|
|
23638
23749
|
.option('nodata', {
|
|
23639
23750
|
describe: 'color to use for invalid or missing data (default is white)'
|
|
@@ -24561,7 +24672,7 @@ ${svg}
|
|
|
24561
24672
|
parser.command('symbols')
|
|
24562
24673
|
.describe('symbolize points as arrows, circles, stars, polygons, etc.')
|
|
24563
24674
|
.option('type', {
|
|
24564
|
-
describe: '
|
|
24675
|
+
describe: 'types: arrow, circle, square, star, polygon, ring'
|
|
24565
24676
|
})
|
|
24566
24677
|
.option('stroke', {})
|
|
24567
24678
|
.option('stroke-width', {})
|
|
@@ -24575,8 +24686,7 @@ ${svg}
|
|
|
24575
24686
|
describe: 'symbol line width (linear symbols only)'
|
|
24576
24687
|
})
|
|
24577
24688
|
.option('opacity', {
|
|
24578
|
-
describe: 'symbol opacity'
|
|
24579
|
-
type: 'number'
|
|
24689
|
+
describe: 'symbol opacity'
|
|
24580
24690
|
})
|
|
24581
24691
|
.option('geographic', {
|
|
24582
24692
|
old_alias: 'polygons',
|
|
@@ -24678,7 +24788,6 @@ ${svg}
|
|
|
24678
24788
|
.option('no-replace', noReplaceOpt);
|
|
24679
24789
|
// .option('name', nameOpt);
|
|
24680
24790
|
|
|
24681
|
-
|
|
24682
24791
|
parser.command('target')
|
|
24683
24792
|
.describe('set active layer (or layers)')
|
|
24684
24793
|
.option('target', {
|
|
@@ -24688,6 +24797,14 @@ ${svg}
|
|
|
24688
24797
|
.option('type', {
|
|
24689
24798
|
describe: 'type of layer to target (polygon|polyline|point)'
|
|
24690
24799
|
})
|
|
24800
|
+
// .option('combine', {
|
|
24801
|
+
// type: 'flag',
|
|
24802
|
+
// describe: 'place all targeted layers in one dataset together with any associated layers'
|
|
24803
|
+
// })
|
|
24804
|
+
// .option('isolate', {
|
|
24805
|
+
// type: 'flag',
|
|
24806
|
+
// describe: 'place all targeted layers in one dataset exclusive of associated layers'
|
|
24807
|
+
// })
|
|
24691
24808
|
.option('name', {
|
|
24692
24809
|
describe: 'rename the target layer'
|
|
24693
24810
|
});
|
|
@@ -38520,6 +38637,11 @@ ${svg}
|
|
|
38520
38637
|
};
|
|
38521
38638
|
}
|
|
38522
38639
|
|
|
38640
|
+
cmd.printHelp = function(opts) {
|
|
38641
|
+
var str = getOptionParser().getHelpMessage(opts.command);
|
|
38642
|
+
print(str);
|
|
38643
|
+
};
|
|
38644
|
+
|
|
38523
38645
|
function resetControlFlow(job) {
|
|
38524
38646
|
job.control = null;
|
|
38525
38647
|
}
|
|
@@ -39159,25 +39281,6 @@ ${svg}
|
|
|
39159
39281
|
};
|
|
39160
39282
|
}
|
|
39161
39283
|
|
|
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
39284
|
function findNearestVertices(p, shp, arcs) {
|
|
39182
39285
|
var p2 = findNearestVertex(p[0], p[1], shp, arcs);
|
|
39183
39286
|
return findVertexIds(p2.x, p2.y, arcs);
|
|
@@ -42827,9 +42930,41 @@ ${svg}
|
|
|
42827
42930
|
// TODO: improve this
|
|
42828
42931
|
targets[0].layers[0].name = opts.name;
|
|
42829
42932
|
}
|
|
42933
|
+
if (opts.combine) {
|
|
42934
|
+
targets = combineTargets(targets, catalog);
|
|
42935
|
+
} else if (opts.isolate) {
|
|
42936
|
+
targets = isolateTargets(targets, catalog);
|
|
42937
|
+
}
|
|
42830
42938
|
catalog.setDefaultTargets(targets);
|
|
42831
42939
|
};
|
|
42832
42940
|
|
|
42941
|
+
function combineTargets(targets, catalog) {
|
|
42942
|
+
var datasets = [];
|
|
42943
|
+
var layers = [];
|
|
42944
|
+
targets.forEach(function(o) {
|
|
42945
|
+
datasets.push(o.dataset);
|
|
42946
|
+
catalog.removeDataset(o.dataset);
|
|
42947
|
+
layers = layers.concat(o.layers);
|
|
42948
|
+
});
|
|
42949
|
+
var combined = mergeDatasets(datasets);
|
|
42950
|
+
catalog.addDataset(combined);
|
|
42951
|
+
return [{
|
|
42952
|
+
dataset: combined,
|
|
42953
|
+
layers: layers
|
|
42954
|
+
}];
|
|
42955
|
+
}
|
|
42956
|
+
|
|
42957
|
+
function isolateTargets(targets, catalog) {
|
|
42958
|
+
var datasets = [];
|
|
42959
|
+
targets.forEach(function(o) {
|
|
42960
|
+
datasets.push(o.dataset);
|
|
42961
|
+
o.layers.forEach(function(lyr) {
|
|
42962
|
+
catalog.removeLayer(lyr, o.dataset);
|
|
42963
|
+
|
|
42964
|
+
});
|
|
42965
|
+
});
|
|
42966
|
+
}
|
|
42967
|
+
|
|
42833
42968
|
cmd.union = function(targetLayers, targetDataset, opts) {
|
|
42834
42969
|
if (targetLayers.length < 2) {
|
|
42835
42970
|
stop('Command requires at least two target layers');
|
|
@@ -43214,7 +43349,7 @@ ${svg}
|
|
|
43214
43349
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43215
43350
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43216
43351
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43217
|
-
name == 'else' || name == 'endif' || name == 'run';
|
|
43352
|
+
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43218
43353
|
}
|
|
43219
43354
|
|
|
43220
43355
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -43403,8 +43538,8 @@ ${svg}
|
|
|
43403
43538
|
job.catalog.addDataset(cmd.graticule(targetDataset, opts));
|
|
43404
43539
|
|
|
43405
43540
|
} else if (name == 'help') {
|
|
43406
|
-
// placing
|
|
43407
|
-
|
|
43541
|
+
// placing help command here to handle errors from invalid command names
|
|
43542
|
+
cmd.printHelp(command.options);
|
|
43408
43543
|
|
|
43409
43544
|
} else if (name == 'i') {
|
|
43410
43545
|
if (opts.replace) job.catalog = new Catalog(); // is this what we want?
|
|
@@ -43486,7 +43621,7 @@ ${svg}
|
|
|
43486
43621
|
cmd.print(command._.join(' '));
|
|
43487
43622
|
|
|
43488
43623
|
} else if (name == 'proj') {
|
|
43489
|
-
await
|
|
43624
|
+
await initProjLibrary(opts);
|
|
43490
43625
|
job.resumeCommand();
|
|
43491
43626
|
targets.forEach(function(targ) {
|
|
43492
43627
|
cmd.proj(targ.dataset, job.catalog, opts);
|
|
@@ -44321,6 +44456,7 @@ ${svg}
|
|
|
44321
44456
|
Heap,
|
|
44322
44457
|
NodeCollection,
|
|
44323
44458
|
parseDMS,
|
|
44459
|
+
formatDMS,
|
|
44324
44460
|
PathIndex,
|
|
44325
44461
|
PolygonIndex,
|
|
44326
44462
|
ShpReader,
|
package/package.json
CHANGED
package/www/index.html
CHANGED
|
@@ -149,19 +149,27 @@
|
|
|
149
149
|
</div>
|
|
150
150
|
<div class="export-zip-option option-menu">
|
|
151
151
|
|
|
152
|
+
<div style="height:10px"></div>
|
|
153
|
+
|
|
152
154
|
</div>
|
|
153
155
|
<h4>File format</h4>
|
|
154
156
|
<div class="export-formats option-menu">
|
|
155
157
|
</div>
|
|
156
158
|
|
|
157
|
-
<div
|
|
159
|
+
<div style="height:10px"></div>
|
|
160
|
+
|
|
161
|
+
<div class="option-menu"><input type="text" class="text-input advanced-options" placeholder="command line options" />
|
|
158
162
|
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-o-output" target="_mapshaper_output_docs">
|
|
159
163
|
<div class="tip-button">?<div class="tip-anchor">
|
|
160
164
|
<div class="tip">Enter options from the command line interface for
|
|
161
165
|
the -o command. Examples: bbox no-quantization
|
|
162
166
|
precision=0.001. Click to see all options.</div></div></div></a>
|
|
163
|
-
|
|
164
167
|
</div>
|
|
168
|
+
|
|
169
|
+
<!-- <div class="option-menu">
|
|
170
|
+
<input id="ofile-name" class="text-input" type="text" placeholder="output file name" />
|
|
171
|
+
</div> -->
|
|
172
|
+
|
|
165
173
|
<!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
|
|
166
174
|
<div class="save-btn btn dialog-btn">Export</div>
|
|
167
175
|
<span id="save-preference"><input type="checkbox"/>choose directory</span>
|
|
@@ -288,7 +296,7 @@ apply to TopoJSON files.</div></div></div></div> -->
|
|
|
288
296
|
|
|
289
297
|
</div>
|
|
290
298
|
|
|
291
|
-
<div><input type="text" class="advanced-options" placeholder="import options" />
|
|
299
|
+
<div><input type="text" class="text-input advanced-options" placeholder="import options" />
|
|
292
300
|
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-i-input" target="_mapshaper_import_docs">
|
|
293
301
|
<div class="tip-button">?<div class="tip-anchor">
|
|
294
302
|
<div class="tip">Enter options from the command line
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -1265,7 +1265,6 @@
|
|
|
1265
1265
|
.onCancel(done);
|
|
1266
1266
|
}
|
|
1267
1267
|
|
|
1268
|
-
|
|
1269
1268
|
async function saveBlobToSelectedFile(filename, blob, done) {
|
|
1270
1269
|
// see: https://developer.chrome.com/articles/file-system-access/
|
|
1271
1270
|
// note: saving multiple files to a directory using showDirectoryPicker()
|
|
@@ -1427,7 +1426,6 @@
|
|
|
1427
1426
|
// }
|
|
1428
1427
|
|
|
1429
1428
|
snapshots.forEach(function(item, i) {
|
|
1430
|
-
var id = i + 1;
|
|
1431
1429
|
var line = El('div').appendTo(menu).addClass('save-menu-item');
|
|
1432
1430
|
El('span').appendTo(line).html(`<span class="save-item-label">#${item.number}</span> `);
|
|
1433
1431
|
// show snapshot size
|
|
@@ -1440,7 +1438,10 @@
|
|
|
1440
1438
|
var obj = await idb.get(item.id);
|
|
1441
1439
|
await internal.applyCompression(obj, {consume: true});
|
|
1442
1440
|
var buf = internal.pack(obj);
|
|
1443
|
-
|
|
1441
|
+
// choose output filename and directory every time
|
|
1442
|
+
// saveBlobToLocalFile('mapshaper_snapshot.msx', new Blob([buf]));
|
|
1443
|
+
var fileName = `snapshot-${String(item.number).padStart(2, '0')}.msx`;
|
|
1444
|
+
saveBlobToSelectedFile(fileName, new Blob([buf]), function() {});
|
|
1444
1445
|
}).text('export');
|
|
1445
1446
|
El('span').addClass('save-menu-btn').appendTo(line).on('click', async function(e) {
|
|
1446
1447
|
await removeSnapshotById(item.id);
|
|
@@ -2479,42 +2480,18 @@
|
|
|
2479
2480
|
});
|
|
2480
2481
|
}
|
|
2481
2482
|
|
|
2483
|
+
internal.setProjectionLoader(loadProjLibs);
|
|
2484
|
+
|
|
2482
2485
|
// load Proj.4 CRS definition files dynamically
|
|
2483
2486
|
//
|
|
2484
|
-
|
|
2487
|
+
async function loadProjLibs(opts) {
|
|
2485
2488
|
var mproj = require('mproj');
|
|
2486
2489
|
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++;
|
|
2490
|
+
libs = libs.filter(function(name) {return !mproj.internal.mproj_search_libcache(name);}); // skip loaded libs
|
|
2491
|
+
for (var libName of libs) {
|
|
2492
|
+
var content = await fetch('assets/' + libName).then(resp => resp.ok ? resp.text() : null);
|
|
2493
|
+
if (!content) stop$1(`Unable to load projection resource [${libName}]`);
|
|
2494
|
+
mproj.internal.mproj_insert_libcache(libName, content);
|
|
2518
2495
|
}
|
|
2519
2496
|
}
|
|
2520
2497
|
|
|
@@ -3371,7 +3348,10 @@
|
|
|
3371
3348
|
setDisplayProjection(gui, cmd);
|
|
3372
3349
|
} else {
|
|
3373
3350
|
line.hide(); // hide cursor while command is being run
|
|
3374
|
-
runMapshaperCommands(cmd, function(err) {
|
|
3351
|
+
runMapshaperCommands(cmd, function(err, flags) {
|
|
3352
|
+
if (flags) {
|
|
3353
|
+
gui.clearMode();
|
|
3354
|
+
}
|
|
3375
3355
|
if (err) {
|
|
3376
3356
|
onError(err);
|
|
3377
3357
|
}
|
|
@@ -3404,14 +3384,9 @@
|
|
|
3404
3384
|
}
|
|
3405
3385
|
}
|
|
3406
3386
|
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
3387
|
model.updated(flags); // info commands do not return flags
|
|
3413
3388
|
}
|
|
3414
|
-
done(err);
|
|
3389
|
+
done(err, flags);
|
|
3415
3390
|
});
|
|
3416
3391
|
}
|
|
3417
3392
|
|
|
@@ -3670,6 +3645,7 @@
|
|
|
3670
3645
|
var layersArr = [];
|
|
3671
3646
|
var toggleBtn = null; // checkbox <input> for toggling layer selection
|
|
3672
3647
|
var exportBtn = gui.container.findChild('.export-btn');
|
|
3648
|
+
var ofileName = gui.container.findChild('#ofile-name');
|
|
3673
3649
|
new SimpleButton(menu.findChild('.close2-btn')).on('click', gui.clearMode);
|
|
3674
3650
|
|
|
3675
3651
|
if (!GUI.exportIsSupported()) {
|
|
@@ -3755,7 +3731,7 @@
|
|
|
3755
3731
|
// done: function(string|Error|null)
|
|
3756
3732
|
async function exportMenuSelection(layers) {
|
|
3757
3733
|
var opts = getExportOpts();
|
|
3758
|
-
|
|
3734
|
+
// note: command line "target" option gets ignored
|
|
3759
3735
|
var files = await internal.exportTargetLayers(layers, opts);
|
|
3760
3736
|
gui.session.layersExported(getTargetLayerIds(), getExportOptsAsString());
|
|
3761
3737
|
await utils$1.promisify(internal.writeFiles)(files, opts);
|
|
@@ -5068,7 +5044,8 @@
|
|
|
5068
5044
|
|
|
5069
5045
|
// Handle an error caused by invalid input or misuse of API
|
|
5070
5046
|
function stop() {
|
|
5071
|
-
_stop.apply(null, utils.toArray(arguments));
|
|
5047
|
+
// _stop.apply(null, utils.toArray(arguments));
|
|
5048
|
+
_stop.apply(null, messageArgs(arguments));
|
|
5072
5049
|
}
|
|
5073
5050
|
|
|
5074
5051
|
function interrupt() {
|
|
@@ -7976,10 +7953,11 @@
|
|
|
7976
7953
|
hit.clearSelection();
|
|
7977
7954
|
});
|
|
7978
7955
|
|
|
7979
|
-
function runCommand(cmd) {
|
|
7956
|
+
function runCommand(cmd, turnOff) {
|
|
7980
7957
|
popup.hide();
|
|
7981
7958
|
if (gui.console) gui.console.runMapshaperCommands(cmd, function(err) {
|
|
7982
7959
|
reset();
|
|
7960
|
+
if (turnOff) gui.clearMode();
|
|
7983
7961
|
});
|
|
7984
7962
|
}
|
|
7985
7963
|
}
|
|
@@ -10311,6 +10289,7 @@
|
|
|
10311
10289
|
if (gui.console) {
|
|
10312
10290
|
gui.console.runMapshaperCommands(cmd, function(err) {
|
|
10313
10291
|
reset();
|
|
10292
|
+
gui.clearMode();
|
|
10314
10293
|
});
|
|
10315
10294
|
}
|
|
10316
10295
|
// 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.40";
|
|
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,110 @@
|
|
|
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
|
+
// TODO: validate that if there are degree decimals, there are no M or S codes
|
|
13146
|
+
rxp = rxp.replace(/D+(\.D+)?/, (m, g1) => {
|
|
13147
|
+
var s = '[0-9]+';
|
|
13148
|
+
if (g1) s += `\\.[0-9]+`;
|
|
13149
|
+
return `(?<d>${s})`;
|
|
13150
|
+
});
|
|
13151
|
+
// TODO: validate that if there are minutes decimals, there are no S codes
|
|
13152
|
+
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13153
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13154
|
+
if (g2) s += '\\.[0-9]+';
|
|
13155
|
+
return `(?<m>${s})`;
|
|
13156
|
+
});
|
|
13157
|
+
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13158
|
+
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13159
|
+
if (g2) s += '\\.[0-9]+';
|
|
13160
|
+
return `(?<s>${s})`;
|
|
13161
|
+
});
|
|
13162
|
+
rxp = '^' + rxp + '$';
|
|
13163
|
+
try {
|
|
13164
|
+
// TODO: make sure all DMS codes have been matched
|
|
13165
|
+
cache$1[fmt] = new RegExp(rxp);
|
|
13166
|
+
} catch(e) {
|
|
13167
|
+
stop('Invalid DMS format string:', fmt);
|
|
13168
|
+
}
|
|
13169
|
+
return cache$1[fmt];
|
|
13170
|
+
}
|
|
13171
|
+
|
|
13172
|
+
function formatNumber(val, integers, decimals) {
|
|
13173
|
+
var str = val.toFixed(decimals);
|
|
13174
|
+
var parts = str.split('.');
|
|
13175
|
+
if (parts.length > 0) {
|
|
13176
|
+
parts[0] = parts[0].padStart(integers, '0');
|
|
13177
|
+
str = parts.join('.');
|
|
13178
|
+
}
|
|
13179
|
+
return str;
|
|
13180
|
+
}
|
|
13181
|
+
|
|
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
|
+
var gotSeconds = match && !!match[3];
|
|
13188
|
+
var gotMinutes = match && !!match[2];
|
|
13189
|
+
if (!match || gotSeconds && !gotMinutes) {
|
|
13190
|
+
stop('Invalid DMS format string:', fmt);
|
|
13191
|
+
}
|
|
13192
|
+
var integers = gotSeconds && match[3].length || gotMinutes && match[2].length || match[1].length;
|
|
13193
|
+
var decimalRxp = gotSeconds && /S\.(S+)/ || gotMinutes && /M\.(M+)/ || /D\.(D+)/;
|
|
13194
|
+
var decimals = decimalRxp.test(fmt) ? decimalRxp.exec(fmt)[1].length : 0;
|
|
13195
|
+
if (gotMinutes) {
|
|
13196
|
+
var RES = Math.pow(10, decimals);
|
|
13197
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13198
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13199
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13200
|
+
if (gotSeconds) {
|
|
13201
|
+
r = Math.floor(r / (RES * 60));
|
|
13202
|
+
sstr = lastPart;
|
|
13203
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13204
|
+
} else {
|
|
13205
|
+
r = Math.floor(r / RES);
|
|
13206
|
+
mstr = lastPart;
|
|
13207
|
+
}
|
|
13208
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13209
|
+
} else {
|
|
13210
|
+
dstr = Math.abs(coord).toFixed(decimals);
|
|
13211
|
+
}
|
|
13212
|
+
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13213
|
+
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13214
|
+
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13215
|
+
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13216
|
+
str = str.replace(/D+(\.D+)?/, dstr);
|
|
13217
|
+
if (gotMinutes) str = str.replace(/M+(\.M+)?/, mstr);
|
|
13218
|
+
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13219
|
+
return str;
|
|
13220
|
+
}
|
|
13221
|
+
|
|
13118
13222
|
function cleanExpression(exp) {
|
|
13119
13223
|
// workaround for problem in GNU Make v4: end-of-line backslashes inside
|
|
13120
13224
|
// quoted strings are left in the string (other shell environments remove them)
|
|
@@ -13126,7 +13230,9 @@
|
|
|
13126
13230
|
round: roundToDigits2,
|
|
13127
13231
|
int_median: interpolated_median,
|
|
13128
13232
|
sprintf: utils.format,
|
|
13129
|
-
blend: blend
|
|
13233
|
+
blend: blend,
|
|
13234
|
+
format_dms: formatDMS,
|
|
13235
|
+
parse_dms: parseDMS
|
|
13130
13236
|
});
|
|
13131
13237
|
}
|
|
13132
13238
|
|
|
@@ -17598,12 +17704,18 @@
|
|
|
17598
17704
|
}
|
|
17599
17705
|
|
|
17600
17706
|
function calcFrameData(dataset, opts) {
|
|
17601
|
-
var bounds
|
|
17602
|
-
|
|
17707
|
+
var bounds;
|
|
17708
|
+
if (opts.svg_bbox) {
|
|
17709
|
+
bounds = new Bounds(opts.svg_bbox);
|
|
17710
|
+
opts = Object.assign({margin: 0}, opts); // prevent default pixel margin around content
|
|
17711
|
+
} else {
|
|
17712
|
+
bounds = getDatasetBounds(dataset);
|
|
17713
|
+
}
|
|
17714
|
+
var pixBounds = calcOutputSizeInPixels(bounds, opts);
|
|
17603
17715
|
return {
|
|
17604
17716
|
bbox: bounds.toArray(),
|
|
17605
|
-
width: Math.round(
|
|
17606
|
-
height: Math.round(
|
|
17717
|
+
width: Math.round(pixBounds.width()),
|
|
17718
|
+
height: Math.round(pixBounds.height()) || 1,
|
|
17607
17719
|
type: 'frame'
|
|
17608
17720
|
};
|
|
17609
17721
|
}
|
|
@@ -22791,7 +22903,6 @@ ${svg}
|
|
|
22791
22903
|
|
|
22792
22904
|
this.getHelpMessage = function(cmdName) {
|
|
22793
22905
|
var helpCommands, singleCommand, lines;
|
|
22794
|
-
|
|
22795
22906
|
if (cmdName) {
|
|
22796
22907
|
singleCommand = findCommandDefn(cmdName, getCommands());
|
|
22797
22908
|
if (!singleCommand) {
|
|
@@ -22910,10 +23021,6 @@ ${svg}
|
|
|
22910
23021
|
}
|
|
22911
23022
|
};
|
|
22912
23023
|
|
|
22913
|
-
this.printHelp = function(command) {
|
|
22914
|
-
print(this.getHelpMessage(command));
|
|
22915
|
-
};
|
|
22916
|
-
|
|
22917
23024
|
function getCommands() {
|
|
22918
23025
|
return _commands.map(function(cmd) {
|
|
22919
23026
|
return cmd.done();
|
|
@@ -23343,6 +23450,10 @@ ${svg}
|
|
|
23343
23450
|
describe: '[SVG] source units per pixel (alternative to width= option)',
|
|
23344
23451
|
type: 'number'
|
|
23345
23452
|
})
|
|
23453
|
+
.option('svg-bbox', {
|
|
23454
|
+
describe: '[SVG] bounding box of SVG map in projected map units',
|
|
23455
|
+
type: 'bbox'
|
|
23456
|
+
})
|
|
23346
23457
|
.option('point-symbol', {
|
|
23347
23458
|
describe: '[SVG] circle or square (default is circle)'
|
|
23348
23459
|
})
|
|
@@ -23633,7 +23744,7 @@ ${svg}
|
|
|
23633
23744
|
type: 'flag'
|
|
23634
23745
|
})
|
|
23635
23746
|
.option('other', {
|
|
23636
|
-
describe: 'default color for categorical scheme (
|
|
23747
|
+
describe: 'default color for categorical scheme (default is nodata color)'
|
|
23637
23748
|
})
|
|
23638
23749
|
.option('nodata', {
|
|
23639
23750
|
describe: 'color to use for invalid or missing data (default is white)'
|
|
@@ -24561,7 +24672,7 @@ ${svg}
|
|
|
24561
24672
|
parser.command('symbols')
|
|
24562
24673
|
.describe('symbolize points as arrows, circles, stars, polygons, etc.')
|
|
24563
24674
|
.option('type', {
|
|
24564
|
-
describe: '
|
|
24675
|
+
describe: 'types: arrow, circle, square, star, polygon, ring'
|
|
24565
24676
|
})
|
|
24566
24677
|
.option('stroke', {})
|
|
24567
24678
|
.option('stroke-width', {})
|
|
@@ -24575,8 +24686,7 @@ ${svg}
|
|
|
24575
24686
|
describe: 'symbol line width (linear symbols only)'
|
|
24576
24687
|
})
|
|
24577
24688
|
.option('opacity', {
|
|
24578
|
-
describe: 'symbol opacity'
|
|
24579
|
-
type: 'number'
|
|
24689
|
+
describe: 'symbol opacity'
|
|
24580
24690
|
})
|
|
24581
24691
|
.option('geographic', {
|
|
24582
24692
|
old_alias: 'polygons',
|
|
@@ -24678,7 +24788,6 @@ ${svg}
|
|
|
24678
24788
|
.option('no-replace', noReplaceOpt);
|
|
24679
24789
|
// .option('name', nameOpt);
|
|
24680
24790
|
|
|
24681
|
-
|
|
24682
24791
|
parser.command('target')
|
|
24683
24792
|
.describe('set active layer (or layers)')
|
|
24684
24793
|
.option('target', {
|
|
@@ -24688,6 +24797,14 @@ ${svg}
|
|
|
24688
24797
|
.option('type', {
|
|
24689
24798
|
describe: 'type of layer to target (polygon|polyline|point)'
|
|
24690
24799
|
})
|
|
24800
|
+
// .option('combine', {
|
|
24801
|
+
// type: 'flag',
|
|
24802
|
+
// describe: 'place all targeted layers in one dataset together with any associated layers'
|
|
24803
|
+
// })
|
|
24804
|
+
// .option('isolate', {
|
|
24805
|
+
// type: 'flag',
|
|
24806
|
+
// describe: 'place all targeted layers in one dataset exclusive of associated layers'
|
|
24807
|
+
// })
|
|
24691
24808
|
.option('name', {
|
|
24692
24809
|
describe: 'rename the target layer'
|
|
24693
24810
|
});
|
|
@@ -38520,6 +38637,11 @@ ${svg}
|
|
|
38520
38637
|
};
|
|
38521
38638
|
}
|
|
38522
38639
|
|
|
38640
|
+
cmd.printHelp = function(opts) {
|
|
38641
|
+
var str = getOptionParser().getHelpMessage(opts.command);
|
|
38642
|
+
print(str);
|
|
38643
|
+
};
|
|
38644
|
+
|
|
38523
38645
|
function resetControlFlow(job) {
|
|
38524
38646
|
job.control = null;
|
|
38525
38647
|
}
|
|
@@ -39159,25 +39281,6 @@ ${svg}
|
|
|
39159
39281
|
};
|
|
39160
39282
|
}
|
|
39161
39283
|
|
|
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
39284
|
function findNearestVertices(p, shp, arcs) {
|
|
39182
39285
|
var p2 = findNearestVertex(p[0], p[1], shp, arcs);
|
|
39183
39286
|
return findVertexIds(p2.x, p2.y, arcs);
|
|
@@ -42827,9 +42930,41 @@ ${svg}
|
|
|
42827
42930
|
// TODO: improve this
|
|
42828
42931
|
targets[0].layers[0].name = opts.name;
|
|
42829
42932
|
}
|
|
42933
|
+
if (opts.combine) {
|
|
42934
|
+
targets = combineTargets(targets, catalog);
|
|
42935
|
+
} else if (opts.isolate) {
|
|
42936
|
+
targets = isolateTargets(targets, catalog);
|
|
42937
|
+
}
|
|
42830
42938
|
catalog.setDefaultTargets(targets);
|
|
42831
42939
|
};
|
|
42832
42940
|
|
|
42941
|
+
function combineTargets(targets, catalog) {
|
|
42942
|
+
var datasets = [];
|
|
42943
|
+
var layers = [];
|
|
42944
|
+
targets.forEach(function(o) {
|
|
42945
|
+
datasets.push(o.dataset);
|
|
42946
|
+
catalog.removeDataset(o.dataset);
|
|
42947
|
+
layers = layers.concat(o.layers);
|
|
42948
|
+
});
|
|
42949
|
+
var combined = mergeDatasets(datasets);
|
|
42950
|
+
catalog.addDataset(combined);
|
|
42951
|
+
return [{
|
|
42952
|
+
dataset: combined,
|
|
42953
|
+
layers: layers
|
|
42954
|
+
}];
|
|
42955
|
+
}
|
|
42956
|
+
|
|
42957
|
+
function isolateTargets(targets, catalog) {
|
|
42958
|
+
var datasets = [];
|
|
42959
|
+
targets.forEach(function(o) {
|
|
42960
|
+
datasets.push(o.dataset);
|
|
42961
|
+
o.layers.forEach(function(lyr) {
|
|
42962
|
+
catalog.removeLayer(lyr, o.dataset);
|
|
42963
|
+
|
|
42964
|
+
});
|
|
42965
|
+
});
|
|
42966
|
+
}
|
|
42967
|
+
|
|
42833
42968
|
cmd.union = function(targetLayers, targetDataset, opts) {
|
|
42834
42969
|
if (targetLayers.length < 2) {
|
|
42835
42970
|
stop('Command requires at least two target layers');
|
|
@@ -43214,7 +43349,7 @@ ${svg}
|
|
|
43214
43349
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43215
43350
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43216
43351
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43217
|
-
name == 'else' || name == 'endif' || name == 'run';
|
|
43352
|
+
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43218
43353
|
}
|
|
43219
43354
|
|
|
43220
43355
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -43403,8 +43538,8 @@ ${svg}
|
|
|
43403
43538
|
job.catalog.addDataset(cmd.graticule(targetDataset, opts));
|
|
43404
43539
|
|
|
43405
43540
|
} else if (name == 'help') {
|
|
43406
|
-
// placing
|
|
43407
|
-
|
|
43541
|
+
// placing help command here to handle errors from invalid command names
|
|
43542
|
+
cmd.printHelp(command.options);
|
|
43408
43543
|
|
|
43409
43544
|
} else if (name == 'i') {
|
|
43410
43545
|
if (opts.replace) job.catalog = new Catalog(); // is this what we want?
|
|
@@ -43486,7 +43621,7 @@ ${svg}
|
|
|
43486
43621
|
cmd.print(command._.join(' '));
|
|
43487
43622
|
|
|
43488
43623
|
} else if (name == 'proj') {
|
|
43489
|
-
await
|
|
43624
|
+
await initProjLibrary(opts);
|
|
43490
43625
|
job.resumeCommand();
|
|
43491
43626
|
targets.forEach(function(targ) {
|
|
43492
43627
|
cmd.proj(targ.dataset, job.catalog, opts);
|
|
@@ -44321,6 +44456,7 @@ ${svg}
|
|
|
44321
44456
|
Heap,
|
|
44322
44457
|
NodeCollection,
|
|
44323
44458
|
parseDMS,
|
|
44459
|
+
formatDMS,
|
|
44324
44460
|
PathIndex,
|
|
44325
44461
|
PolygonIndex,
|
|
44326
44462
|
ShpReader,
|
package/www/page.css
CHANGED
|
@@ -242,10 +242,6 @@ body {
|
|
|
242
242
|
white-space: nowrap;
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
.export-options .option-menu .advanced-options {
|
|
246
|
-
width: 195px;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
245
|
/* --- Main area ------------- */
|
|
250
246
|
|
|
251
247
|
.main-area {
|
|
@@ -450,14 +446,14 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
450
446
|
|
|
451
447
|
/* --- Import screen -------------- */
|
|
452
448
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
width: 250px;
|
|
449
|
+
.option-menu .text-input {
|
|
450
|
+
width: 230px;
|
|
456
451
|
background: rgba(255, 255, 255, 0.4);
|
|
457
452
|
border: 1px solid #999;
|
|
458
453
|
padding: 0 3px;
|
|
459
454
|
height: 18px;
|
|
460
455
|
font-size: 13px;
|
|
456
|
+
margin: 0 0 5px 0;
|
|
461
457
|
}
|
|
462
458
|
|
|
463
459
|
#mshp-not-supported {
|
|
@@ -548,10 +544,6 @@ body.dragover #import-options-drop-area .drop-area {
|
|
|
548
544
|
font-size: 90%;
|
|
549
545
|
}
|
|
550
546
|
|
|
551
|
-
.option-menu {
|
|
552
|
-
padding: 0 0 9px 0;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
547
|
/*.option-menu input[type="radio"],
|
|
556
548
|
.option-menu input[type="checkbox"] */
|
|
557
549
|
.info-box input[type="radio"],
|