mapshaper 0.6.39 → 0.6.41
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/bin/mapshaper-gui +1 -1
- package/mapshaper.js +112 -75
- package/package.json +1 -1
- package/www/index.html +11 -3
- package/www/mapshaper-gui.js +38 -36
- package/www/mapshaper.js +112 -75
- package/www/page.css +3 -11
package/bin/mapshaper-gui
CHANGED
|
@@ -9,7 +9,7 @@ var defaultPort = 5555,
|
|
|
9
9
|
.option('-q, --quick-view', 'load files with default options, bypassing import dialog')
|
|
10
10
|
.option('-s, --direct-save', 'save files outside the browser\'s download folder')
|
|
11
11
|
.option('-f, --force-save', 'allow overwriting input files with output files')
|
|
12
|
-
.option('-a, --display-all', 'turn on visibility of all layers')
|
|
12
|
+
.option('-a, --display-all', 'turn on initial visibility of all layers')
|
|
13
13
|
.option('-n, --name <name(s)>', 'rename input layer or layers')
|
|
14
14
|
.option('-c, --commands <string>', 'console commands to run initially')
|
|
15
15
|
.option('-t, --target <name>', 'name of layer to select initially')
|
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.41";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -10877,7 +10877,8 @@
|
|
|
10877
10877
|
pack: pack,
|
|
10878
10878
|
exportDatasetsToPack: exportDatasetsToPack,
|
|
10879
10879
|
applyCompression: applyCompression,
|
|
10880
|
-
exportDataset: exportDataset
|
|
10880
|
+
exportDataset: exportDataset,
|
|
10881
|
+
exportInfo: exportInfo
|
|
10881
10882
|
});
|
|
10882
10883
|
|
|
10883
10884
|
// Guess the type of a data file from file extension, or return null if not sure
|
|
@@ -13142,17 +13143,23 @@
|
|
|
13142
13143
|
var rxp = fmt;
|
|
13143
13144
|
rxp = rxp.replace('[-]', '(?<prefix>-)?'); // optional -
|
|
13144
13145
|
rxp = rxp.replace(/\[[NSEW, +-]{2,}\]/, '(?<prefix>$&)');
|
|
13146
|
+
// TODO: validate that if there are degree decimals, there are no M or S codes
|
|
13147
|
+
rxp = rxp.replace(/D+(\.D+)?/, (m, g1) => {
|
|
13148
|
+
var s = '[0-9]+';
|
|
13149
|
+
if (g1) s += `\\.[0-9]+`;
|
|
13150
|
+
return `(?<d>${s})`;
|
|
13151
|
+
});
|
|
13152
|
+
// TODO: validate that if there are minutes decimals, there are no S codes
|
|
13145
13153
|
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13146
13154
|
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13147
|
-
if (g2) s +=
|
|
13155
|
+
if (g2) s += '\\.[0-9]+';
|
|
13148
13156
|
return `(?<m>${s})`;
|
|
13149
13157
|
});
|
|
13150
13158
|
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13151
13159
|
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13152
|
-
if (g2) s +=
|
|
13160
|
+
if (g2) s += '\\.[0-9]+';
|
|
13153
13161
|
return `(?<s>${s})`;
|
|
13154
13162
|
});
|
|
13155
|
-
rxp = rxp.replace(/D+/, '(?<d>[0-9]+)');
|
|
13156
13163
|
rxp = '^' + rxp + '$';
|
|
13157
13164
|
try {
|
|
13158
13165
|
// TODO: make sure all DMS codes have been matched
|
|
@@ -13173,43 +13180,42 @@
|
|
|
13173
13180
|
return str;
|
|
13174
13181
|
}
|
|
13175
13182
|
|
|
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
13183
|
function formatDMS(coord, fmt) {
|
|
13183
13184
|
if (!fmt) fmt = '[-]D°M\'S.SSS';
|
|
13184
13185
|
var str = fmt;
|
|
13185
13186
|
var dstr, mstr, sstr;
|
|
13186
|
-
var match = /(D+)[^M]*(M+)[^S[\]]*(S+)?/.exec(fmt);
|
|
13187
|
-
|
|
13187
|
+
var match = /(D+)[^M]*(M+)?[^S[\]]*(S+)?/.exec(fmt);
|
|
13188
|
+
var gotSeconds = match && !!match[3];
|
|
13189
|
+
var gotMinutes = match && !!match[2];
|
|
13190
|
+
if (!match || gotSeconds && !gotMinutes) {
|
|
13188
13191
|
stop('Invalid DMS format string:', fmt);
|
|
13189
13192
|
}
|
|
13190
|
-
var
|
|
13191
|
-
var
|
|
13192
|
-
var
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13193
|
+
var integers = gotSeconds && match[3].length || gotMinutes && match[2].length || match[1].length;
|
|
13194
|
+
var decimalRxp = gotSeconds && /S\.(S+)/ || gotMinutes && /M\.(M+)/ || /D\.(D+)/;
|
|
13195
|
+
var decimals = decimalRxp.test(fmt) ? decimalRxp.exec(fmt)[1].length : 0;
|
|
13196
|
+
if (gotMinutes) {
|
|
13197
|
+
var RES = Math.pow(10, decimals);
|
|
13198
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13199
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13200
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13201
|
+
if (gotSeconds) {
|
|
13202
|
+
r = Math.floor(r / (RES * 60));
|
|
13203
|
+
sstr = lastPart;
|
|
13204
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13205
|
+
} else {
|
|
13206
|
+
r = Math.floor(r / RES);
|
|
13207
|
+
mstr = lastPart;
|
|
13208
|
+
}
|
|
13209
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13201
13210
|
} else {
|
|
13202
|
-
|
|
13203
|
-
mstr = lastPart;
|
|
13204
|
-
sstr = '';
|
|
13211
|
+
dstr = Math.abs(coord).toFixed(decimals);
|
|
13205
13212
|
}
|
|
13206
|
-
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13207
13213
|
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13208
13214
|
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13209
13215
|
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13210
13216
|
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13211
|
-
str = str.replace(/D
|
|
13212
|
-
str = str.replace(/M+(\.M+)?/, mstr);
|
|
13217
|
+
str = str.replace(/D+(\.D+)?/, dstr);
|
|
13218
|
+
if (gotMinutes) str = str.replace(/M+(\.M+)?/, mstr);
|
|
13213
13219
|
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13214
13220
|
return str;
|
|
13215
13221
|
}
|
|
@@ -17699,12 +17705,18 @@
|
|
|
17699
17705
|
}
|
|
17700
17706
|
|
|
17701
17707
|
function calcFrameData(dataset, opts) {
|
|
17702
|
-
var bounds
|
|
17703
|
-
|
|
17708
|
+
var bounds;
|
|
17709
|
+
if (opts.svg_bbox) {
|
|
17710
|
+
bounds = new Bounds(opts.svg_bbox);
|
|
17711
|
+
opts = Object.assign({margin: 0}, opts); // prevent default pixel margin around content
|
|
17712
|
+
} else {
|
|
17713
|
+
bounds = getDatasetBounds(dataset);
|
|
17714
|
+
}
|
|
17715
|
+
var pixBounds = calcOutputSizeInPixels(bounds, opts);
|
|
17704
17716
|
return {
|
|
17705
17717
|
bbox: bounds.toArray(),
|
|
17706
|
-
width: Math.round(
|
|
17707
|
-
height: Math.round(
|
|
17718
|
+
width: Math.round(pixBounds.width()),
|
|
17719
|
+
height: Math.round(pixBounds.height()) || 1,
|
|
17708
17720
|
type: 'frame'
|
|
17709
17721
|
};
|
|
17710
17722
|
}
|
|
@@ -23375,6 +23387,10 @@ ${svg}
|
|
|
23375
23387
|
describe: '[TopoJSON] export coordinates without quantization',
|
|
23376
23388
|
type: 'flag'
|
|
23377
23389
|
})
|
|
23390
|
+
.option('metadata', {
|
|
23391
|
+
// describe: '[TopoJSON] Add a metadata object containing CRS information',
|
|
23392
|
+
type: 'flag'
|
|
23393
|
+
})
|
|
23378
23394
|
.option('no-point-quantization', {
|
|
23379
23395
|
// describe: '[TopoJSON] export point coordinates without quantization',
|
|
23380
23396
|
type: 'flag'
|
|
@@ -23439,6 +23455,10 @@ ${svg}
|
|
|
23439
23455
|
describe: '[SVG] source units per pixel (alternative to width= option)',
|
|
23440
23456
|
type: 'number'
|
|
23441
23457
|
})
|
|
23458
|
+
.option('svg-bbox', {
|
|
23459
|
+
describe: '[SVG] bounding box of SVG map in projected map units',
|
|
23460
|
+
type: 'bbox'
|
|
23461
|
+
})
|
|
23442
23462
|
.option('point-symbol', {
|
|
23443
23463
|
describe: '[SVG] circle or square (default is circle)'
|
|
23444
23464
|
})
|
|
@@ -27547,6 +27567,7 @@ ${svg}
|
|
|
27547
27567
|
var separator = path.indexOf('/') > 0 ? '/' : '.';
|
|
27548
27568
|
var parts = path.split(separator);
|
|
27549
27569
|
var subpath, array, match;
|
|
27570
|
+
|
|
27550
27571
|
while (parts.length > 0) {
|
|
27551
27572
|
subpath = parts.shift();
|
|
27552
27573
|
match = arrayRxp.exec(subpath);
|
|
@@ -36229,31 +36250,6 @@ ${svg}
|
|
|
36229
36250
|
|
|
36230
36251
|
var externalCommands = {};
|
|
36231
36252
|
|
|
36232
|
-
cmd.external = function(opts) {
|
|
36233
|
-
// TODO: remove duplication with -require command
|
|
36234
|
-
var _module, moduleFile, moduleName;
|
|
36235
|
-
if (!opts.module) {
|
|
36236
|
-
stop('Missing required "module" parameter');
|
|
36237
|
-
}
|
|
36238
|
-
if (cli.isFile(opts.module)) {
|
|
36239
|
-
moduleFile = opts.module;
|
|
36240
|
-
} else if (cli.isFile(opts.module + '.js')) {
|
|
36241
|
-
moduleFile = opts.module + '.js';
|
|
36242
|
-
} else {
|
|
36243
|
-
moduleName = opts.module;
|
|
36244
|
-
}
|
|
36245
|
-
if (moduleFile) {
|
|
36246
|
-
moduleFile = require$1('path').join(process.cwd(), moduleFile);
|
|
36247
|
-
}
|
|
36248
|
-
try {
|
|
36249
|
-
_module = require$1(moduleFile || moduleName);
|
|
36250
|
-
_module(coreAPI);
|
|
36251
|
-
} catch(e) {
|
|
36252
|
-
// stop(e);
|
|
36253
|
-
stop('Unable to load external module:', e.message);
|
|
36254
|
-
}
|
|
36255
|
-
};
|
|
36256
|
-
|
|
36257
36253
|
cmd.registerCommand = function(name, params) {
|
|
36258
36254
|
var defn = {name: name, options: params.options || []};
|
|
36259
36255
|
// Add definitions of options common to all commands (TODO: remove duplication)
|
|
@@ -36263,13 +36259,25 @@ ${svg}
|
|
|
36263
36259
|
externalCommands[name] = defn;
|
|
36264
36260
|
};
|
|
36265
36261
|
|
|
36262
|
+
function isValidExternalCommand(defn) {
|
|
36263
|
+
try {
|
|
36264
|
+
validateExternalCommand(defn);
|
|
36265
|
+
return true;
|
|
36266
|
+
} catch(e) {}
|
|
36267
|
+
return false;
|
|
36268
|
+
}
|
|
36269
|
+
|
|
36266
36270
|
function validateExternalCommand(defn) {
|
|
36271
|
+
var targetTypes = ['layer', 'layers'];
|
|
36267
36272
|
if (typeof defn.command != 'function') {
|
|
36268
36273
|
stop('Expected "command" parameter function');
|
|
36269
36274
|
}
|
|
36270
36275
|
if (!defn.target) {
|
|
36271
36276
|
stop('Missing required "target" parameter');
|
|
36272
36277
|
}
|
|
36278
|
+
if (!targetTypes.includes(defn.target)) {
|
|
36279
|
+
stop('Unrecognized command target type:', defn.target);
|
|
36280
|
+
}
|
|
36273
36281
|
}
|
|
36274
36282
|
|
|
36275
36283
|
cmd.runExternalCommand = function(cmdOpts, catalog) {
|
|
@@ -40609,6 +40617,7 @@ ${svg}
|
|
|
40609
40617
|
return outputLayers;
|
|
40610
40618
|
};
|
|
40611
40619
|
|
|
40620
|
+
|
|
40612
40621
|
function getPolygonDataset(pointLyr, gridBBox, opts) {
|
|
40613
40622
|
var points = getPointsInLayer(pointLyr);
|
|
40614
40623
|
var cellSize = opts.interval;
|
|
@@ -40714,6 +40723,8 @@ ${svg}
|
|
|
40714
40723
|
return getPointBufferCoordinates(center, radius, 20, getPlanarSegmentEndpoint);
|
|
40715
40724
|
}
|
|
40716
40725
|
|
|
40726
|
+
// Returns a function that receives a cell index and returns indices of points
|
|
40727
|
+
// within a given distance of the cell.
|
|
40717
40728
|
function getPointIndex(points, grid, radius) {
|
|
40718
40729
|
var Flatbush = require$1('flatbush');
|
|
40719
40730
|
var gridIndex = new IdTestIndex(grid.cells());
|
|
@@ -40845,12 +40856,26 @@ ${svg}
|
|
|
40845
40856
|
xmin + (c + 1) * interval, ymin + (r + 1) * interval
|
|
40846
40857
|
];
|
|
40847
40858
|
}
|
|
40859
|
+
|
|
40848
40860
|
return {
|
|
40849
40861
|
size, cells, pointToCol, pointToRow, colRowToIdx, pointToIdx,
|
|
40850
40862
|
idxToCol, idxToRow, idxToBBox, idxToPoint
|
|
40851
40863
|
};
|
|
40852
40864
|
}
|
|
40853
40865
|
|
|
40866
|
+
var PointToGrid = /*#__PURE__*/Object.freeze({
|
|
40867
|
+
__proto__: null,
|
|
40868
|
+
getPointCircleRadius: getPointCircleRadius,
|
|
40869
|
+
calcCellProperties: calcCellProperties,
|
|
40870
|
+
calcWeights: calcWeights,
|
|
40871
|
+
twoCircleIntersection: twoCircleIntersection,
|
|
40872
|
+
makeCellPolygon: makeCellPolygon,
|
|
40873
|
+
getPointIndex: getPointIndex,
|
|
40874
|
+
getAlignedGridBounds: getAlignedGridBounds,
|
|
40875
|
+
getCenteredGridBounds: getCenteredGridBounds,
|
|
40876
|
+
getGridData: getGridData
|
|
40877
|
+
});
|
|
40878
|
+
|
|
40854
40879
|
function closeUndershoots(lyr, dataset, opts) {
|
|
40855
40880
|
var maxGapLen = opts.gap_tolerance ? convertIntervalParam(opts.gap_tolerance, getDatasetCRS(dataset)) : 0;
|
|
40856
40881
|
var arcs = dataset.arcs;
|
|
@@ -41165,8 +41190,16 @@ ${svg}
|
|
|
41165
41190
|
}
|
|
41166
41191
|
try {
|
|
41167
41192
|
mod = require$1(moduleFile || moduleName);
|
|
41193
|
+
if (typeof mod == 'function') {
|
|
41194
|
+
// -require now includes the functionality of the old -external command
|
|
41195
|
+
var retn = mod(api);
|
|
41196
|
+
if (retn && isValidExternalCommand(retn)) {
|
|
41197
|
+
cmd.registerCommand(retn.name, retn);
|
|
41198
|
+
}
|
|
41199
|
+
}
|
|
41168
41200
|
} catch(e) {
|
|
41169
|
-
stop(e);
|
|
41201
|
+
// stop(e);
|
|
41202
|
+
stop('Unable to load external module:', e.message);
|
|
41170
41203
|
}
|
|
41171
41204
|
if (moduleName || opts.alias) {
|
|
41172
41205
|
defs[opts.alias || moduleName] = mod;
|
|
@@ -43332,7 +43365,7 @@ ${svg}
|
|
|
43332
43365
|
}
|
|
43333
43366
|
|
|
43334
43367
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43335
|
-
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43368
|
+
return name == 'rotate' || name == 'info' || name == 'proj' || name == 'require' ||
|
|
43336
43369
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43337
43370
|
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43338
43371
|
}
|
|
@@ -43490,7 +43523,8 @@ ${svg}
|
|
|
43490
43523
|
outputLayers = applyCommandToEachLayer(cmd.explodeFeatures, targetLayers, arcs, opts);
|
|
43491
43524
|
|
|
43492
43525
|
} else if (name == 'external') {
|
|
43493
|
-
|
|
43526
|
+
// -require now incorporates -external
|
|
43527
|
+
cmd.require(targets, opts);
|
|
43494
43528
|
|
|
43495
43529
|
} else if (name == 'filter') {
|
|
43496
43530
|
outputLayers = applyCommandToEachLayer(cmd.filterFeatures, targetLayers, arcs, opts);
|
|
@@ -44115,14 +44149,6 @@ ${svg}
|
|
|
44115
44149
|
runAndRemoveInfoCommands: runAndRemoveInfoCommands
|
|
44116
44150
|
});
|
|
44117
44151
|
|
|
44118
|
-
// the mapshaper public api only has 4 functions
|
|
44119
|
-
var coreAPI = {
|
|
44120
|
-
runCommands,
|
|
44121
|
-
applyCommands,
|
|
44122
|
-
runCommandsXL,
|
|
44123
|
-
enableLogging
|
|
44124
|
-
};
|
|
44125
|
-
|
|
44126
44152
|
// Return an array containing points from a path iterator, clipped to a bounding box
|
|
44127
44153
|
// Currently using this function for clipping styled polygons in the GUI to speed up layer rendering.
|
|
44128
44154
|
// Artifacts along the edges make this unsuitable for clipping datasets
|
|
@@ -44519,6 +44545,7 @@ ${svg}
|
|
|
44519
44545
|
PixelTransform,
|
|
44520
44546
|
PointPolygonJoin,
|
|
44521
44547
|
Points,
|
|
44548
|
+
PointToGrid,
|
|
44522
44549
|
PointUtils,
|
|
44523
44550
|
PolygonDissolve,
|
|
44524
44551
|
PolygonDissolve2,
|
|
@@ -44566,16 +44593,26 @@ ${svg}
|
|
|
44566
44593
|
Zip
|
|
44567
44594
|
);
|
|
44568
44595
|
|
|
44569
|
-
//
|
|
44596
|
+
// the mapshaper public api only has 4 functions
|
|
44597
|
+
var api = {
|
|
44598
|
+
runCommands,
|
|
44599
|
+
applyCommands,
|
|
44600
|
+
runCommandsXL,
|
|
44601
|
+
enableLogging
|
|
44602
|
+
};
|
|
44570
44603
|
|
|
44571
|
-
|
|
44604
|
+
// Add some namespaces, for easier testability and
|
|
44605
|
+
// to expose internal functions to the web UI
|
|
44606
|
+
Object.assign(api, {
|
|
44572
44607
|
cli, cmd, geom, utils, internal,
|
|
44573
|
-
}
|
|
44608
|
+
});
|
|
44609
|
+
|
|
44610
|
+
// The entry point for the core mapshaper module
|
|
44574
44611
|
|
|
44575
44612
|
if (typeof module === "object" && module.exports) {
|
|
44576
|
-
module.exports =
|
|
44613
|
+
module.exports = api;
|
|
44577
44614
|
} else if (typeof window === "object" && window) {
|
|
44578
|
-
window.mapshaper =
|
|
44615
|
+
window.mapshaper = api;
|
|
44579
44616
|
}
|
|
44580
44617
|
|
|
44581
44618
|
})();
|
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);
|
|
@@ -1978,7 +1979,7 @@
|
|
|
1978
1979
|
var names = getFileNames(files);
|
|
1979
1980
|
var expanded = [];
|
|
1980
1981
|
if (files.length === 0) return;
|
|
1981
|
-
useQuickView =
|
|
1982
|
+
useQuickView = importTotal === 0 && (opts.quick_view || overQuickView);
|
|
1982
1983
|
try {
|
|
1983
1984
|
expanded = await expandFiles(files);
|
|
1984
1985
|
} catch(e) {
|
|
@@ -3644,6 +3645,7 @@
|
|
|
3644
3645
|
var layersArr = [];
|
|
3645
3646
|
var toggleBtn = null; // checkbox <input> for toggling layer selection
|
|
3646
3647
|
var exportBtn = gui.container.findChild('.export-btn');
|
|
3648
|
+
var ofileName = gui.container.findChild('#ofile-name');
|
|
3647
3649
|
new SimpleButton(menu.findChild('.close2-btn')).on('click', gui.clearMode);
|
|
3648
3650
|
|
|
3649
3651
|
if (!GUI.exportIsSupported()) {
|
|
@@ -3729,7 +3731,7 @@
|
|
|
3729
3731
|
// done: function(string|Error|null)
|
|
3730
3732
|
async function exportMenuSelection(layers) {
|
|
3731
3733
|
var opts = getExportOpts();
|
|
3732
|
-
|
|
3734
|
+
// note: command line "target" option gets ignored
|
|
3733
3735
|
var files = await internal.exportTargetLayers(layers, opts);
|
|
3734
3736
|
gui.session.layersExported(getTargetLayerIds(), getExportOptsAsString());
|
|
3735
3737
|
await utils$1.promisify(internal.writeFiles)(files, opts);
|
|
@@ -9169,6 +9171,10 @@
|
|
|
9169
9171
|
return calcBounds(_cx, _cy, _scale / (k || 1));
|
|
9170
9172
|
};
|
|
9171
9173
|
|
|
9174
|
+
this.getFullBounds = function() {
|
|
9175
|
+
return _fullBounds;
|
|
9176
|
+
};
|
|
9177
|
+
|
|
9172
9178
|
// Update the extent of 'full' zoom without navigating the current view
|
|
9173
9179
|
//
|
|
9174
9180
|
this.setFullBounds = function(fullBounds, strictBounds) {
|
|
@@ -9504,6 +9510,7 @@
|
|
|
9504
9510
|
canv.drawVertices(layer.shapes, arcs, style, filter);
|
|
9505
9511
|
}
|
|
9506
9512
|
}
|
|
9513
|
+
canv.clearStyles();
|
|
9507
9514
|
}
|
|
9508
9515
|
|
|
9509
9516
|
|
|
@@ -9564,6 +9571,11 @@
|
|
|
9564
9571
|
_pixelColor = getPixelColorFunction(),
|
|
9565
9572
|
_ext;
|
|
9566
9573
|
|
|
9574
|
+
_self.clearStyles = function() {
|
|
9575
|
+
_ctx.fillStyle = null;
|
|
9576
|
+
_ctx.strokeStyle = null;
|
|
9577
|
+
};
|
|
9578
|
+
|
|
9567
9579
|
_self.prep = function(extent) {
|
|
9568
9580
|
var w = extent.width(),
|
|
9569
9581
|
h = extent.height(),
|
|
@@ -10549,25 +10561,11 @@
|
|
|
10549
10561
|
|
|
10550
10562
|
|
|
10551
10563
|
function getDisplayBounds(lyr, arcs) {
|
|
10552
|
-
var
|
|
10553
|
-
|
|
10554
|
-
|
|
10555
|
-
|
|
10556
|
-
|
|
10557
|
-
lyrBounds = internal.getLayerBounds(lyr);
|
|
10558
|
-
if (lyrBounds && lyrBounds.hasBounds()) {
|
|
10559
|
-
if (lyrBounds.area() > 0 || !arcBounds.hasBounds()) {
|
|
10560
|
-
bounds = lyrBounds;
|
|
10561
|
-
} else {
|
|
10562
|
-
// if a point layer has no extent (e.g. contains only a single point),
|
|
10563
|
-
// then merge with arc bounds, to place the point in context.
|
|
10564
|
-
bounds = arcBounds.mergeBounds(lyrBounds);
|
|
10565
|
-
}
|
|
10566
|
-
}
|
|
10567
|
-
}
|
|
10568
|
-
|
|
10569
|
-
if (!bounds || !bounds.hasBounds()) { // empty layer
|
|
10570
|
-
bounds = new Bounds();
|
|
10564
|
+
var bounds = internal.getLayerBounds(lyr, arcs) || new Bounds();
|
|
10565
|
+
if (lyr.geometry_type == 'point' && arcs && bounds.hasBounds() && bounds.area() > 0 === false) {
|
|
10566
|
+
// if a point layer has no extent (e.g. contains only a single point),
|
|
10567
|
+
// then merge with arc bounds, to place the point in context.
|
|
10568
|
+
bounds = bounds.mergeBounds(arcs.getBounds());
|
|
10571
10569
|
}
|
|
10572
10570
|
return bounds;
|
|
10573
10571
|
}
|
|
@@ -10841,7 +10839,6 @@
|
|
|
10841
10839
|
_ext = new MapExtent(position),
|
|
10842
10840
|
_nav = new MapNav(gui, _ext, _mouse),
|
|
10843
10841
|
_visibleLayers = [], // cached visible map layers
|
|
10844
|
-
_fullBounds = null,
|
|
10845
10842
|
_hit,
|
|
10846
10843
|
_basemap,
|
|
10847
10844
|
_intersectionLyr, _activeLyr, _overlayLyr,
|
|
@@ -10949,8 +10946,8 @@
|
|
|
10949
10946
|
updateLayerStyles(getDrawableContentLayers()); // kludge to make sure all layers have styles
|
|
10950
10947
|
|
|
10951
10948
|
// Update map extent (also triggers redraw)
|
|
10952
|
-
projectMapExtent(_ext, oldCRS, this.getDisplayCRS(),
|
|
10953
|
-
|
|
10949
|
+
projectMapExtent(_ext, oldCRS, this.getDisplayCRS(), calcFullBounds());
|
|
10950
|
+
updateFullBounds();
|
|
10954
10951
|
};
|
|
10955
10952
|
|
|
10956
10953
|
// Refresh map display in response to data changes, layer selection, etc.
|
|
@@ -10993,28 +10990,27 @@
|
|
|
10993
10990
|
gui.dispatchEvent('popup-needs-refresh');
|
|
10994
10991
|
} else if (_hit) {
|
|
10995
10992
|
_hit.clearSelection();
|
|
10996
|
-
_hit.setLayer(_activeLyr);
|
|
10997
10993
|
}
|
|
10994
|
+
_hit.setLayer(_activeLyr); // need this every time, to support dynamic reprojection
|
|
10998
10995
|
|
|
10999
10996
|
updateVisibleMapLayers();
|
|
11000
|
-
fullBounds =
|
|
10997
|
+
fullBounds = calcFullBounds();
|
|
11001
10998
|
|
|
11002
|
-
if (!prevLyr ||
|
|
10999
|
+
if (!prevLyr || prevLyr.tabular || _activeLyr.tabular || isFrameView()) {
|
|
11003
11000
|
needReset = true;
|
|
11004
11001
|
} else {
|
|
11005
|
-
needReset = mapNeedsReset(fullBounds,
|
|
11002
|
+
needReset = mapNeedsReset(fullBounds, _ext.getFullBounds(), _ext.getBounds(), e.flags);
|
|
11006
11003
|
}
|
|
11007
11004
|
|
|
11008
11005
|
if (isFrameView()) {
|
|
11009
11006
|
_nav.setZoomFactor(0.05); // slow zooming way down to allow fine-tuning frame placement // 0.03
|
|
11010
|
-
_ext.setFrame(
|
|
11007
|
+
_ext.setFrame(calcFullBounds()); // TODO: remove redundancy with drawLayers()
|
|
11011
11008
|
needReset = true; // snap to frame extent
|
|
11012
11009
|
} else {
|
|
11013
11010
|
_nav.setZoomFactor(1);
|
|
11014
11011
|
}
|
|
11015
11012
|
_ext.setFullBounds(fullBounds, getStrictBounds()); // update 'home' button extent
|
|
11016
11013
|
|
|
11017
|
-
_fullBounds = fullBounds;
|
|
11018
11014
|
if (needReset) {
|
|
11019
11015
|
_ext.reset();
|
|
11020
11016
|
}
|
|
@@ -11115,12 +11111,17 @@
|
|
|
11115
11111
|
return null;
|
|
11116
11112
|
}
|
|
11117
11113
|
|
|
11118
|
-
function
|
|
11114
|
+
function updateFullBounds() {
|
|
11115
|
+
_ext.setFullBounds(calcFullBounds(), getStrictBounds());
|
|
11116
|
+
}
|
|
11117
|
+
|
|
11118
|
+
function calcFullBounds() {
|
|
11119
11119
|
if (isPreviewView()) {
|
|
11120
11120
|
return internal.getFrameLayerBounds(internal.findFrameLayer(model));
|
|
11121
11121
|
}
|
|
11122
11122
|
var b = new Bounds();
|
|
11123
|
-
getDrawableContentLayers()
|
|
11123
|
+
var layers = getDrawableContentLayers();
|
|
11124
|
+
layers.forEach(function(lyr) {
|
|
11124
11125
|
b.mergeBounds(lyr.bounds);
|
|
11125
11126
|
});
|
|
11126
11127
|
|
|
@@ -11265,6 +11266,7 @@
|
|
|
11265
11266
|
// (default) anything could have changed
|
|
11266
11267
|
function drawLayers2(action) {
|
|
11267
11268
|
var layersMayHaveChanged = !action;
|
|
11269
|
+
var fullBounds;
|
|
11268
11270
|
var contentLayers = getDrawableContentLayers();
|
|
11269
11271
|
var furnitureLayers = getDrawableFurnitureLayers();
|
|
11270
11272
|
if (!(_ext.width() > 0 && _ext.height() > 0)) {
|
|
@@ -11275,7 +11277,7 @@
|
|
|
11275
11277
|
if (layersMayHaveChanged) {
|
|
11276
11278
|
// kludge to handle layer visibility toggling
|
|
11277
11279
|
_ext.setFrame(isPreviewView() ? getFrameData() : null);
|
|
11278
|
-
|
|
11280
|
+
updateFullBounds();
|
|
11279
11281
|
updateLayerStyles(contentLayers);
|
|
11280
11282
|
updateLayerStackOrder(model.getLayers());// update menu_order property of all layers
|
|
11281
11283
|
}
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.41";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -10877,7 +10877,8 @@
|
|
|
10877
10877
|
pack: pack,
|
|
10878
10878
|
exportDatasetsToPack: exportDatasetsToPack,
|
|
10879
10879
|
applyCompression: applyCompression,
|
|
10880
|
-
exportDataset: exportDataset
|
|
10880
|
+
exportDataset: exportDataset,
|
|
10881
|
+
exportInfo: exportInfo
|
|
10881
10882
|
});
|
|
10882
10883
|
|
|
10883
10884
|
// Guess the type of a data file from file extension, or return null if not sure
|
|
@@ -13142,17 +13143,23 @@
|
|
|
13142
13143
|
var rxp = fmt;
|
|
13143
13144
|
rxp = rxp.replace('[-]', '(?<prefix>-)?'); // optional -
|
|
13144
13145
|
rxp = rxp.replace(/\[[NSEW, +-]{2,}\]/, '(?<prefix>$&)');
|
|
13146
|
+
// TODO: validate that if there are degree decimals, there are no M or S codes
|
|
13147
|
+
rxp = rxp.replace(/D+(\.D+)?/, (m, g1) => {
|
|
13148
|
+
var s = '[0-9]+';
|
|
13149
|
+
if (g1) s += `\\.[0-9]+`;
|
|
13150
|
+
return `(?<d>${s})`;
|
|
13151
|
+
});
|
|
13152
|
+
// TODO: validate that if there are minutes decimals, there are no S codes
|
|
13145
13153
|
rxp = rxp.replace(/(MM?)(\.M+)?/, (m, g1, g2) => {
|
|
13146
13154
|
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13147
|
-
if (g2) s +=
|
|
13155
|
+
if (g2) s += '\\.[0-9]+';
|
|
13148
13156
|
return `(?<m>${s})`;
|
|
13149
13157
|
});
|
|
13150
13158
|
rxp = rxp.replace(/(SS?)(\.S+)?/, (m, g1, g2) => {
|
|
13151
13159
|
var s = g1.length == 1 ? '[0-9]+' : '[0-9][0-9]';
|
|
13152
|
-
if (g2) s +=
|
|
13160
|
+
if (g2) s += '\\.[0-9]+';
|
|
13153
13161
|
return `(?<s>${s})`;
|
|
13154
13162
|
});
|
|
13155
|
-
rxp = rxp.replace(/D+/, '(?<d>[0-9]+)');
|
|
13156
13163
|
rxp = '^' + rxp + '$';
|
|
13157
13164
|
try {
|
|
13158
13165
|
// TODO: make sure all DMS codes have been matched
|
|
@@ -13173,43 +13180,42 @@
|
|
|
13173
13180
|
return str;
|
|
13174
13181
|
}
|
|
13175
13182
|
|
|
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
13183
|
function formatDMS(coord, fmt) {
|
|
13183
13184
|
if (!fmt) fmt = '[-]D°M\'S.SSS';
|
|
13184
13185
|
var str = fmt;
|
|
13185
13186
|
var dstr, mstr, sstr;
|
|
13186
|
-
var match = /(D+)[^M]*(M+)[^S[\]]*(S+)?/.exec(fmt);
|
|
13187
|
-
|
|
13187
|
+
var match = /(D+)[^M]*(M+)?[^S[\]]*(S+)?/.exec(fmt);
|
|
13188
|
+
var gotSeconds = match && !!match[3];
|
|
13189
|
+
var gotMinutes = match && !!match[2];
|
|
13190
|
+
if (!match || gotSeconds && !gotMinutes) {
|
|
13188
13191
|
stop('Invalid DMS format string:', fmt);
|
|
13189
13192
|
}
|
|
13190
|
-
var
|
|
13191
|
-
var
|
|
13192
|
-
var
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13193
|
+
var integers = gotSeconds && match[3].length || gotMinutes && match[2].length || match[1].length;
|
|
13194
|
+
var decimalRxp = gotSeconds && /S\.(S+)/ || gotMinutes && /M\.(M+)/ || /D\.(D+)/;
|
|
13195
|
+
var decimals = decimalRxp.test(fmt) ? decimalRxp.exec(fmt)[1].length : 0;
|
|
13196
|
+
if (gotMinutes) {
|
|
13197
|
+
var RES = Math.pow(10, decimals);
|
|
13198
|
+
var CONV = gotSeconds ? 3600 * RES : 60 * RES;
|
|
13199
|
+
var r = Math.floor(Math.abs(coord) * CONV + 0.5);
|
|
13200
|
+
var lastPart = formatNumber((r / RES) % 60, integers, decimals);
|
|
13201
|
+
if (gotSeconds) {
|
|
13202
|
+
r = Math.floor(r / (RES * 60));
|
|
13203
|
+
sstr = lastPart;
|
|
13204
|
+
mstr = String(r % 60).padStart(match[2].length, '0');
|
|
13205
|
+
} else {
|
|
13206
|
+
r = Math.floor(r / RES);
|
|
13207
|
+
mstr = lastPart;
|
|
13208
|
+
}
|
|
13209
|
+
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13201
13210
|
} else {
|
|
13202
|
-
|
|
13203
|
-
mstr = lastPart;
|
|
13204
|
-
sstr = '';
|
|
13211
|
+
dstr = Math.abs(coord).toFixed(decimals);
|
|
13205
13212
|
}
|
|
13206
|
-
dstr = String(Math.floor(r / 60)).padStart(match[1].length, '0');
|
|
13207
13213
|
str = str.replace(/\[-\]/, s => coord < 0 ? '-' : '');
|
|
13208
13214
|
str = str.replace(/\[[+-]+\]/, s => coord < 0 ? '-' : '+');
|
|
13209
13215
|
str = str.replace(/\[[NS, ]+\]/, s => coord < 0 ? 'S' : 'N');
|
|
13210
13216
|
str = str.replace(/\[[EW, ]+\]/, s => coord < 0 ? 'W' : 'E');
|
|
13211
|
-
str = str.replace(/D
|
|
13212
|
-
str = str.replace(/M+(\.M+)?/, mstr);
|
|
13217
|
+
str = str.replace(/D+(\.D+)?/, dstr);
|
|
13218
|
+
if (gotMinutes) str = str.replace(/M+(\.M+)?/, mstr);
|
|
13213
13219
|
if (gotSeconds) str = str.replace(/S+(\.S+)?/, sstr);
|
|
13214
13220
|
return str;
|
|
13215
13221
|
}
|
|
@@ -17699,12 +17705,18 @@
|
|
|
17699
17705
|
}
|
|
17700
17706
|
|
|
17701
17707
|
function calcFrameData(dataset, opts) {
|
|
17702
|
-
var bounds
|
|
17703
|
-
|
|
17708
|
+
var bounds;
|
|
17709
|
+
if (opts.svg_bbox) {
|
|
17710
|
+
bounds = new Bounds(opts.svg_bbox);
|
|
17711
|
+
opts = Object.assign({margin: 0}, opts); // prevent default pixel margin around content
|
|
17712
|
+
} else {
|
|
17713
|
+
bounds = getDatasetBounds(dataset);
|
|
17714
|
+
}
|
|
17715
|
+
var pixBounds = calcOutputSizeInPixels(bounds, opts);
|
|
17704
17716
|
return {
|
|
17705
17717
|
bbox: bounds.toArray(),
|
|
17706
|
-
width: Math.round(
|
|
17707
|
-
height: Math.round(
|
|
17718
|
+
width: Math.round(pixBounds.width()),
|
|
17719
|
+
height: Math.round(pixBounds.height()) || 1,
|
|
17708
17720
|
type: 'frame'
|
|
17709
17721
|
};
|
|
17710
17722
|
}
|
|
@@ -23375,6 +23387,10 @@ ${svg}
|
|
|
23375
23387
|
describe: '[TopoJSON] export coordinates without quantization',
|
|
23376
23388
|
type: 'flag'
|
|
23377
23389
|
})
|
|
23390
|
+
.option('metadata', {
|
|
23391
|
+
// describe: '[TopoJSON] Add a metadata object containing CRS information',
|
|
23392
|
+
type: 'flag'
|
|
23393
|
+
})
|
|
23378
23394
|
.option('no-point-quantization', {
|
|
23379
23395
|
// describe: '[TopoJSON] export point coordinates without quantization',
|
|
23380
23396
|
type: 'flag'
|
|
@@ -23439,6 +23455,10 @@ ${svg}
|
|
|
23439
23455
|
describe: '[SVG] source units per pixel (alternative to width= option)',
|
|
23440
23456
|
type: 'number'
|
|
23441
23457
|
})
|
|
23458
|
+
.option('svg-bbox', {
|
|
23459
|
+
describe: '[SVG] bounding box of SVG map in projected map units',
|
|
23460
|
+
type: 'bbox'
|
|
23461
|
+
})
|
|
23442
23462
|
.option('point-symbol', {
|
|
23443
23463
|
describe: '[SVG] circle or square (default is circle)'
|
|
23444
23464
|
})
|
|
@@ -27547,6 +27567,7 @@ ${svg}
|
|
|
27547
27567
|
var separator = path.indexOf('/') > 0 ? '/' : '.';
|
|
27548
27568
|
var parts = path.split(separator);
|
|
27549
27569
|
var subpath, array, match;
|
|
27570
|
+
|
|
27550
27571
|
while (parts.length > 0) {
|
|
27551
27572
|
subpath = parts.shift();
|
|
27552
27573
|
match = arrayRxp.exec(subpath);
|
|
@@ -36229,31 +36250,6 @@ ${svg}
|
|
|
36229
36250
|
|
|
36230
36251
|
var externalCommands = {};
|
|
36231
36252
|
|
|
36232
|
-
cmd.external = function(opts) {
|
|
36233
|
-
// TODO: remove duplication with -require command
|
|
36234
|
-
var _module, moduleFile, moduleName;
|
|
36235
|
-
if (!opts.module) {
|
|
36236
|
-
stop('Missing required "module" parameter');
|
|
36237
|
-
}
|
|
36238
|
-
if (cli.isFile(opts.module)) {
|
|
36239
|
-
moduleFile = opts.module;
|
|
36240
|
-
} else if (cli.isFile(opts.module + '.js')) {
|
|
36241
|
-
moduleFile = opts.module + '.js';
|
|
36242
|
-
} else {
|
|
36243
|
-
moduleName = opts.module;
|
|
36244
|
-
}
|
|
36245
|
-
if (moduleFile) {
|
|
36246
|
-
moduleFile = require$1('path').join(process.cwd(), moduleFile);
|
|
36247
|
-
}
|
|
36248
|
-
try {
|
|
36249
|
-
_module = require$1(moduleFile || moduleName);
|
|
36250
|
-
_module(coreAPI);
|
|
36251
|
-
} catch(e) {
|
|
36252
|
-
// stop(e);
|
|
36253
|
-
stop('Unable to load external module:', e.message);
|
|
36254
|
-
}
|
|
36255
|
-
};
|
|
36256
|
-
|
|
36257
36253
|
cmd.registerCommand = function(name, params) {
|
|
36258
36254
|
var defn = {name: name, options: params.options || []};
|
|
36259
36255
|
// Add definitions of options common to all commands (TODO: remove duplication)
|
|
@@ -36263,13 +36259,25 @@ ${svg}
|
|
|
36263
36259
|
externalCommands[name] = defn;
|
|
36264
36260
|
};
|
|
36265
36261
|
|
|
36262
|
+
function isValidExternalCommand(defn) {
|
|
36263
|
+
try {
|
|
36264
|
+
validateExternalCommand(defn);
|
|
36265
|
+
return true;
|
|
36266
|
+
} catch(e) {}
|
|
36267
|
+
return false;
|
|
36268
|
+
}
|
|
36269
|
+
|
|
36266
36270
|
function validateExternalCommand(defn) {
|
|
36271
|
+
var targetTypes = ['layer', 'layers'];
|
|
36267
36272
|
if (typeof defn.command != 'function') {
|
|
36268
36273
|
stop('Expected "command" parameter function');
|
|
36269
36274
|
}
|
|
36270
36275
|
if (!defn.target) {
|
|
36271
36276
|
stop('Missing required "target" parameter');
|
|
36272
36277
|
}
|
|
36278
|
+
if (!targetTypes.includes(defn.target)) {
|
|
36279
|
+
stop('Unrecognized command target type:', defn.target);
|
|
36280
|
+
}
|
|
36273
36281
|
}
|
|
36274
36282
|
|
|
36275
36283
|
cmd.runExternalCommand = function(cmdOpts, catalog) {
|
|
@@ -40609,6 +40617,7 @@ ${svg}
|
|
|
40609
40617
|
return outputLayers;
|
|
40610
40618
|
};
|
|
40611
40619
|
|
|
40620
|
+
|
|
40612
40621
|
function getPolygonDataset(pointLyr, gridBBox, opts) {
|
|
40613
40622
|
var points = getPointsInLayer(pointLyr);
|
|
40614
40623
|
var cellSize = opts.interval;
|
|
@@ -40714,6 +40723,8 @@ ${svg}
|
|
|
40714
40723
|
return getPointBufferCoordinates(center, radius, 20, getPlanarSegmentEndpoint);
|
|
40715
40724
|
}
|
|
40716
40725
|
|
|
40726
|
+
// Returns a function that receives a cell index and returns indices of points
|
|
40727
|
+
// within a given distance of the cell.
|
|
40717
40728
|
function getPointIndex(points, grid, radius) {
|
|
40718
40729
|
var Flatbush = require$1('flatbush');
|
|
40719
40730
|
var gridIndex = new IdTestIndex(grid.cells());
|
|
@@ -40845,12 +40856,26 @@ ${svg}
|
|
|
40845
40856
|
xmin + (c + 1) * interval, ymin + (r + 1) * interval
|
|
40846
40857
|
];
|
|
40847
40858
|
}
|
|
40859
|
+
|
|
40848
40860
|
return {
|
|
40849
40861
|
size, cells, pointToCol, pointToRow, colRowToIdx, pointToIdx,
|
|
40850
40862
|
idxToCol, idxToRow, idxToBBox, idxToPoint
|
|
40851
40863
|
};
|
|
40852
40864
|
}
|
|
40853
40865
|
|
|
40866
|
+
var PointToGrid = /*#__PURE__*/Object.freeze({
|
|
40867
|
+
__proto__: null,
|
|
40868
|
+
getPointCircleRadius: getPointCircleRadius,
|
|
40869
|
+
calcCellProperties: calcCellProperties,
|
|
40870
|
+
calcWeights: calcWeights,
|
|
40871
|
+
twoCircleIntersection: twoCircleIntersection,
|
|
40872
|
+
makeCellPolygon: makeCellPolygon,
|
|
40873
|
+
getPointIndex: getPointIndex,
|
|
40874
|
+
getAlignedGridBounds: getAlignedGridBounds,
|
|
40875
|
+
getCenteredGridBounds: getCenteredGridBounds,
|
|
40876
|
+
getGridData: getGridData
|
|
40877
|
+
});
|
|
40878
|
+
|
|
40854
40879
|
function closeUndershoots(lyr, dataset, opts) {
|
|
40855
40880
|
var maxGapLen = opts.gap_tolerance ? convertIntervalParam(opts.gap_tolerance, getDatasetCRS(dataset)) : 0;
|
|
40856
40881
|
var arcs = dataset.arcs;
|
|
@@ -41165,8 +41190,16 @@ ${svg}
|
|
|
41165
41190
|
}
|
|
41166
41191
|
try {
|
|
41167
41192
|
mod = require$1(moduleFile || moduleName);
|
|
41193
|
+
if (typeof mod == 'function') {
|
|
41194
|
+
// -require now includes the functionality of the old -external command
|
|
41195
|
+
var retn = mod(api);
|
|
41196
|
+
if (retn && isValidExternalCommand(retn)) {
|
|
41197
|
+
cmd.registerCommand(retn.name, retn);
|
|
41198
|
+
}
|
|
41199
|
+
}
|
|
41168
41200
|
} catch(e) {
|
|
41169
|
-
stop(e);
|
|
41201
|
+
// stop(e);
|
|
41202
|
+
stop('Unable to load external module:', e.message);
|
|
41170
41203
|
}
|
|
41171
41204
|
if (moduleName || opts.alias) {
|
|
41172
41205
|
defs[opts.alias || moduleName] = mod;
|
|
@@ -43332,7 +43365,7 @@ ${svg}
|
|
|
43332
43365
|
}
|
|
43333
43366
|
|
|
43334
43367
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43335
|
-
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43368
|
+
return name == 'rotate' || name == 'info' || name == 'proj' || name == 'require' ||
|
|
43336
43369
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43337
43370
|
name == 'else' || name == 'endif' || name == 'run' || name == 'i';
|
|
43338
43371
|
}
|
|
@@ -43490,7 +43523,8 @@ ${svg}
|
|
|
43490
43523
|
outputLayers = applyCommandToEachLayer(cmd.explodeFeatures, targetLayers, arcs, opts);
|
|
43491
43524
|
|
|
43492
43525
|
} else if (name == 'external') {
|
|
43493
|
-
|
|
43526
|
+
// -require now incorporates -external
|
|
43527
|
+
cmd.require(targets, opts);
|
|
43494
43528
|
|
|
43495
43529
|
} else if (name == 'filter') {
|
|
43496
43530
|
outputLayers = applyCommandToEachLayer(cmd.filterFeatures, targetLayers, arcs, opts);
|
|
@@ -44115,14 +44149,6 @@ ${svg}
|
|
|
44115
44149
|
runAndRemoveInfoCommands: runAndRemoveInfoCommands
|
|
44116
44150
|
});
|
|
44117
44151
|
|
|
44118
|
-
// the mapshaper public api only has 4 functions
|
|
44119
|
-
var coreAPI = {
|
|
44120
|
-
runCommands,
|
|
44121
|
-
applyCommands,
|
|
44122
|
-
runCommandsXL,
|
|
44123
|
-
enableLogging
|
|
44124
|
-
};
|
|
44125
|
-
|
|
44126
44152
|
// Return an array containing points from a path iterator, clipped to a bounding box
|
|
44127
44153
|
// Currently using this function for clipping styled polygons in the GUI to speed up layer rendering.
|
|
44128
44154
|
// Artifacts along the edges make this unsuitable for clipping datasets
|
|
@@ -44519,6 +44545,7 @@ ${svg}
|
|
|
44519
44545
|
PixelTransform,
|
|
44520
44546
|
PointPolygonJoin,
|
|
44521
44547
|
Points,
|
|
44548
|
+
PointToGrid,
|
|
44522
44549
|
PointUtils,
|
|
44523
44550
|
PolygonDissolve,
|
|
44524
44551
|
PolygonDissolve2,
|
|
@@ -44566,16 +44593,26 @@ ${svg}
|
|
|
44566
44593
|
Zip
|
|
44567
44594
|
);
|
|
44568
44595
|
|
|
44569
|
-
//
|
|
44596
|
+
// the mapshaper public api only has 4 functions
|
|
44597
|
+
var api = {
|
|
44598
|
+
runCommands,
|
|
44599
|
+
applyCommands,
|
|
44600
|
+
runCommandsXL,
|
|
44601
|
+
enableLogging
|
|
44602
|
+
};
|
|
44570
44603
|
|
|
44571
|
-
|
|
44604
|
+
// Add some namespaces, for easier testability and
|
|
44605
|
+
// to expose internal functions to the web UI
|
|
44606
|
+
Object.assign(api, {
|
|
44572
44607
|
cli, cmd, geom, utils, internal,
|
|
44573
|
-
}
|
|
44608
|
+
});
|
|
44609
|
+
|
|
44610
|
+
// The entry point for the core mapshaper module
|
|
44574
44611
|
|
|
44575
44612
|
if (typeof module === "object" && module.exports) {
|
|
44576
|
-
module.exports =
|
|
44613
|
+
module.exports = api;
|
|
44577
44614
|
} else if (typeof window === "object" && window) {
|
|
44578
|
-
window.mapshaper =
|
|
44615
|
+
window.mapshaper = api;
|
|
44579
44616
|
}
|
|
44580
44617
|
|
|
44581
44618
|
})();
|
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"],
|