mapshaper 0.6.31 → 0.6.33
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 +109 -68
- package/package.json +1 -1
- package/www/index.html +14 -6
- package/www/mapshaper-gui.js +23 -18
- package/www/mapshaper.js +109 -68
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.33";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -11665,8 +11665,16 @@
|
|
|
11665
11665
|
}
|
|
11666
11666
|
cands.forEach(function(cand) {
|
|
11667
11667
|
var p = getTestPoint(cand.ids);
|
|
11668
|
-
var isEnclosed = b.containsPoint(p[0], p[1]) &&
|
|
11669
|
-
|
|
11668
|
+
var isEnclosed = b.containsPoint(p[0], p[1]) &&
|
|
11669
|
+
// added a bounds-in-bounds test to handle a case where the test point
|
|
11670
|
+
// fell along the shared boundary of two rings, but the rings did no overlap
|
|
11671
|
+
// (this gave a false positive for the enclosure test)
|
|
11672
|
+
// (for speed, the midpoint of an arc is used as the test point; this
|
|
11673
|
+
// works well in the typical case where rings to not share an edge.
|
|
11674
|
+
// Finding an internal test point would be better, we just need a fast
|
|
11675
|
+
// function to find internal points)
|
|
11676
|
+
b.contains(cand.bounds) &&
|
|
11677
|
+
(index ? index.pointInPolygon(p[0], p[1]) : geom.testPointInRing(p[0], p[1], pathIds, arcs));
|
|
11670
11678
|
if (isEnclosed) {
|
|
11671
11679
|
paths.push(cand.ids);
|
|
11672
11680
|
}
|
|
@@ -11674,6 +11682,7 @@
|
|
|
11674
11682
|
return paths.length > 0 ? paths : null;
|
|
11675
11683
|
};
|
|
11676
11684
|
|
|
11685
|
+
// return array of indexed paths within a given shape
|
|
11677
11686
|
this.findPathsInsideShape = function(shape) {
|
|
11678
11687
|
var paths = []; // list of enclosed paths
|
|
11679
11688
|
shape.forEach(function(ids) {
|
|
@@ -12075,7 +12084,6 @@
|
|
|
12075
12084
|
yy = coords.yy,
|
|
12076
12085
|
ids = nodes.getConnectedArcs(fromArcId),
|
|
12077
12086
|
toArcId = fromArcId; // initialize to fromArcId -- an error condition
|
|
12078
|
-
|
|
12079
12087
|
if (filter) {
|
|
12080
12088
|
ids = ids.filter(filter);
|
|
12081
12089
|
}
|
|
@@ -12104,14 +12112,12 @@
|
|
|
12104
12112
|
continue;
|
|
12105
12113
|
}
|
|
12106
12114
|
icand = arcs.indexOfVertex(candId, -2);
|
|
12107
|
-
|
|
12108
12115
|
if (toArcId == fromArcId) {
|
|
12109
12116
|
// first valid candidate
|
|
12110
12117
|
ito = icand;
|
|
12111
12118
|
toArcId = candId;
|
|
12112
12119
|
continue;
|
|
12113
12120
|
}
|
|
12114
|
-
|
|
12115
12121
|
code = chooseRighthandPath(fromX, fromY, nodeX, nodeY, xx[ito], yy[ito], xx[icand], yy[icand]);
|
|
12116
12122
|
if (code == 2) {
|
|
12117
12123
|
ito = icand;
|
|
@@ -12119,6 +12125,7 @@
|
|
|
12119
12125
|
}
|
|
12120
12126
|
}
|
|
12121
12127
|
|
|
12128
|
+
|
|
12122
12129
|
if (toArcId == fromArcId) {
|
|
12123
12130
|
// This shouldn't occur, assuming that other arcs are present
|
|
12124
12131
|
error("Pathfinder error");
|
|
@@ -12183,6 +12190,9 @@
|
|
|
12183
12190
|
chooseRighthandVector: chooseRighthandVector
|
|
12184
12191
|
});
|
|
12185
12192
|
|
|
12193
|
+
var FWD_USED = 0x8;
|
|
12194
|
+
var REV_USED = 0x80;
|
|
12195
|
+
|
|
12186
12196
|
function setBits(bits, arcBits, mask) {
|
|
12187
12197
|
return (bits & ~mask) | (arcBits & mask);
|
|
12188
12198
|
}
|
|
@@ -12210,6 +12220,16 @@
|
|
|
12210
12220
|
return bits & 7;
|
|
12211
12221
|
}
|
|
12212
12222
|
|
|
12223
|
+
function markPathsAsUsed(paths, routesArr) {
|
|
12224
|
+
forEachArcId(paths, function(arcId) {
|
|
12225
|
+
if (arcId < 0) {
|
|
12226
|
+
routesArr[~arcId] |= REV_USED;
|
|
12227
|
+
} else {
|
|
12228
|
+
routesArr[arcId] |= FWD_USED;
|
|
12229
|
+
}
|
|
12230
|
+
});
|
|
12231
|
+
}
|
|
12232
|
+
|
|
12213
12233
|
// Open arc pathways in a single shape or array of shapes
|
|
12214
12234
|
//
|
|
12215
12235
|
function openArcRoutes(paths, arcColl, routesArr, fwd, rev, dissolve, orBits) {
|
|
@@ -12400,6 +12420,7 @@
|
|
|
12400
12420
|
andBits: andBits,
|
|
12401
12421
|
setRouteBits: setRouteBits,
|
|
12402
12422
|
getRouteBits: getRouteBits,
|
|
12423
|
+
markPathsAsUsed: markPathsAsUsed,
|
|
12403
12424
|
openArcRoutes: openArcRoutes,
|
|
12404
12425
|
closeArcRoutes: closeArcRoutes,
|
|
12405
12426
|
getPathFinder: getPathFinder,
|
|
@@ -24840,13 +24861,12 @@ ${svg}
|
|
|
24840
24861
|
|
|
24841
24862
|
parser.command('run')
|
|
24842
24863
|
.describe('create commands on-the-fly and run them')
|
|
24843
|
-
.option('
|
|
24844
|
-
// TODO: remove this option
|
|
24845
|
-
})
|
|
24846
|
-
.option('commands', {
|
|
24864
|
+
.option('expression', {
|
|
24847
24865
|
DEFAULT: true,
|
|
24848
|
-
describe: '
|
|
24866
|
+
describe: 'JS expression to generate command(s)'
|
|
24849
24867
|
})
|
|
24868
|
+
// deprecated
|
|
24869
|
+
.option('commands', {alias_to: 'expression'})
|
|
24850
24870
|
.option('target', targetOpt);
|
|
24851
24871
|
|
|
24852
24872
|
parser.command('scalebar')
|
|
@@ -33402,7 +33422,7 @@ ${svg}
|
|
|
33402
33422
|
var clipArcTouches = 0;
|
|
33403
33423
|
var clipArcUses = 0;
|
|
33404
33424
|
var usedClipArcs = [];
|
|
33405
|
-
var
|
|
33425
|
+
var findPath = getPathFinder(nodes, useRoute, routeIsActive);
|
|
33406
33426
|
var dissolvePolygon = getPolygonDissolver(nodes);
|
|
33407
33427
|
|
|
33408
33428
|
// The following cleanup step is a performance bottleneck (it often takes longer than
|
|
@@ -33435,12 +33455,16 @@ ${svg}
|
|
|
33435
33455
|
return null;
|
|
33436
33456
|
});
|
|
33437
33457
|
|
|
33458
|
+
markPathsAsUsed(clippedShapes, routeFlags); // to help us find unused paths later
|
|
33459
|
+
|
|
33460
|
+
|
|
33438
33461
|
// add clip/erase polygons that are fully contained in a target polygon
|
|
33439
33462
|
// need to index only non-intersecting clip shapes
|
|
33440
33463
|
// (Intersecting shapes have one or more arcs that have been scanned)
|
|
33441
33464
|
|
|
33442
33465
|
// first, find shapes that do not intersect the target layer
|
|
33443
33466
|
// (these could be inside or outside the target polygons)
|
|
33467
|
+
|
|
33444
33468
|
var undividedClipShapes = findUndividedClipShapes(clipShapes);
|
|
33445
33469
|
|
|
33446
33470
|
closeArcRoutes(clipShapes, arcs, routeFlags, true, true); // not needed?
|
|
@@ -33469,7 +33493,7 @@ ${svg}
|
|
|
33469
33493
|
for (var i=0, n=ids.length; i<n; i++) {
|
|
33470
33494
|
clipArcTouches = 0;
|
|
33471
33495
|
clipArcUses = 0;
|
|
33472
|
-
path =
|
|
33496
|
+
path = findPath(ids[i]);
|
|
33473
33497
|
if (path) {
|
|
33474
33498
|
// if ring doesn't touch/intersect a clip/erase polygon, check if it is contained
|
|
33475
33499
|
// if (clipArcTouches === 0) {
|
|
@@ -33488,6 +33512,7 @@ ${svg}
|
|
|
33488
33512
|
}
|
|
33489
33513
|
});
|
|
33490
33514
|
|
|
33515
|
+
|
|
33491
33516
|
// Clear pathways of current target shape to hidden/closed
|
|
33492
33517
|
closeArcRoutes(shape, arcs, routeFlags, true, true, true);
|
|
33493
33518
|
// Also clear pathways of any clip arcs that were used
|
|
@@ -33558,8 +33583,9 @@ ${svg}
|
|
|
33558
33583
|
return usable;
|
|
33559
33584
|
}
|
|
33560
33585
|
|
|
33561
|
-
|
|
33562
|
-
//
|
|
33586
|
+
|
|
33587
|
+
// Filter a collection of shapes to exclude paths that incorporate parts of
|
|
33588
|
+
// clip/erase polygons and paths that are hidden (e.g. internal boundaries)
|
|
33563
33589
|
function findUndividedClipShapes(clipShapes) {
|
|
33564
33590
|
return clipShapes.map(function(shape) {
|
|
33565
33591
|
var usableParts = [];
|
|
@@ -33583,12 +33609,12 @@ ${svg}
|
|
|
33583
33609
|
});
|
|
33584
33610
|
}
|
|
33585
33611
|
|
|
33586
|
-
|
|
33587
|
-
// (not testing open/closed or visible/hidden)
|
|
33612
|
+
|
|
33588
33613
|
function arcIsUnused(id, flags) {
|
|
33589
33614
|
var abs = absArcId(id),
|
|
33590
33615
|
flag = flags[abs];
|
|
33591
|
-
return (flag &
|
|
33616
|
+
return (flag & 0x88) === 0;
|
|
33617
|
+
// return id < 0 ? (flag & 0x80) === 0 : (flag & 0x8) === 0;
|
|
33592
33618
|
}
|
|
33593
33619
|
|
|
33594
33620
|
function arcIsVisible(id, flags) {
|
|
@@ -33611,7 +33637,7 @@ ${svg}
|
|
|
33611
33637
|
enclosedPaths.forEach(function(ids) {
|
|
33612
33638
|
var path;
|
|
33613
33639
|
for (var j=0; j<ids.length; j++) {
|
|
33614
|
-
path =
|
|
33640
|
+
path = findPath(ids[j]);
|
|
33615
33641
|
if (path) {
|
|
33616
33642
|
dissolvedPaths.push(path);
|
|
33617
33643
|
}
|
|
@@ -34730,7 +34756,64 @@ ${svg}
|
|
|
34730
34756
|
};
|
|
34731
34757
|
}
|
|
34732
34758
|
|
|
34733
|
-
|
|
34759
|
+
function compileIfCommandExpression(expr, catalog, opts) {
|
|
34760
|
+
return compileLayerExpression(expr, catalog, opts);
|
|
34761
|
+
}
|
|
34762
|
+
|
|
34763
|
+
|
|
34764
|
+
function compileLayerExpression(expr, catalog, opts) {
|
|
34765
|
+
var targetId = opts.layer || opts.target || null;
|
|
34766
|
+
var targets = catalog.findCommandTargets(targetId);
|
|
34767
|
+
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
34768
|
+
if (targets.length === 0 && targetId) {
|
|
34769
|
+
stop('Layer not found:', targetId);
|
|
34770
|
+
}
|
|
34771
|
+
// var vars = getAssignedVars(exp);
|
|
34772
|
+
var defs = getStashedVar('defs') || {};
|
|
34773
|
+
|
|
34774
|
+
var ctx;
|
|
34775
|
+
if (isSingle) {
|
|
34776
|
+
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs);
|
|
34777
|
+
} else {
|
|
34778
|
+
ctx = getNullLayerProxy(targets);
|
|
34779
|
+
}
|
|
34780
|
+
ctx.global = defs; // TODO: remove duplication with mapshaper.expressions.mjs
|
|
34781
|
+
var exprOpts = Object.assign({returns: true}, opts);
|
|
34782
|
+
var func = compileExpressionToFunction(expr, exprOpts);
|
|
34783
|
+
|
|
34784
|
+
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
34785
|
+
ctx.layer_exists = function(name, geoType) {
|
|
34786
|
+
try {
|
|
34787
|
+
var targets = catalog.findCommandTargets(name, geoType);
|
|
34788
|
+
if (targets.length > 0) return true;
|
|
34789
|
+
} catch(e) {}
|
|
34790
|
+
return false;
|
|
34791
|
+
};
|
|
34792
|
+
|
|
34793
|
+
ctx.file_exists = function(file) {
|
|
34794
|
+
return cli.isFile(file);
|
|
34795
|
+
};
|
|
34796
|
+
|
|
34797
|
+
return function() {
|
|
34798
|
+
try {
|
|
34799
|
+
return func.call(ctx, defs, ctx);
|
|
34800
|
+
} catch(e) {
|
|
34801
|
+
// if (opts.quiet) throw e;
|
|
34802
|
+
stop(e.name, "in expression [" + expr + "]:", e.message);
|
|
34803
|
+
}
|
|
34804
|
+
};
|
|
34805
|
+
}
|
|
34806
|
+
|
|
34807
|
+
/*
|
|
34808
|
+
cmd.define_v2 = function(catalog, opts) {
|
|
34809
|
+
if (!opts.expression) {
|
|
34810
|
+
stop('Missing an assignment expression');
|
|
34811
|
+
}
|
|
34812
|
+
compileLayerExpression(opts.expression, catalog, opts)();
|
|
34813
|
+
};
|
|
34814
|
+
*/
|
|
34815
|
+
|
|
34816
|
+
cmd.define = function(catalog, opts) {
|
|
34734
34817
|
if (!opts.expression) {
|
|
34735
34818
|
stop('Missing an assignment expression');
|
|
34736
34819
|
}
|
|
@@ -38418,46 +38501,6 @@ ${svg}
|
|
|
38418
38501
|
return job.control || (job.control = {});
|
|
38419
38502
|
}
|
|
38420
38503
|
|
|
38421
|
-
function compileIfCommandExpression(expr, catalog, opts) {
|
|
38422
|
-
var targetId = opts.layer || opts.target || null;
|
|
38423
|
-
var targets = catalog.findCommandTargets(targetId);
|
|
38424
|
-
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
38425
|
-
if (targets.length === 0 && targetId) {
|
|
38426
|
-
stop('Layer not found:', targetId);
|
|
38427
|
-
}
|
|
38428
|
-
var ctx;
|
|
38429
|
-
if (isSingle) {
|
|
38430
|
-
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs);
|
|
38431
|
-
} else {
|
|
38432
|
-
ctx = getNullLayerProxy(targets);
|
|
38433
|
-
}
|
|
38434
|
-
ctx.global = getStashedVar('defs') || {}; // TODO: remove duplication with mapshaper.expressions.mjs
|
|
38435
|
-
var exprOpts = Object.assign({returns: true}, opts);
|
|
38436
|
-
var func = compileExpressionToFunction(expr, exprOpts);
|
|
38437
|
-
|
|
38438
|
-
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
38439
|
-
ctx.layer_exists = function(name, geoType) {
|
|
38440
|
-
try {
|
|
38441
|
-
var targets = catalog.findCommandTargets(name, geoType);
|
|
38442
|
-
if (targets.length > 0) return true;
|
|
38443
|
-
} catch(e) {}
|
|
38444
|
-
return false;
|
|
38445
|
-
};
|
|
38446
|
-
|
|
38447
|
-
ctx.file_exists = function(file) {
|
|
38448
|
-
return cli.isFile(file);
|
|
38449
|
-
};
|
|
38450
|
-
|
|
38451
|
-
return function() {
|
|
38452
|
-
try {
|
|
38453
|
-
return func.call(ctx, {}, ctx);
|
|
38454
|
-
} catch(e) {
|
|
38455
|
-
// if (opts.quiet) throw e;
|
|
38456
|
-
stop(e.name, "in expression [" + expr + "]:", e.message);
|
|
38457
|
-
}
|
|
38458
|
-
};
|
|
38459
|
-
}
|
|
38460
|
-
|
|
38461
38504
|
function skipCommand(cmdName, job) {
|
|
38462
38505
|
// allow all control commands to run
|
|
38463
38506
|
if (jobIsStopped(job)) return true;
|
|
@@ -40914,13 +40957,10 @@ ${svg}
|
|
|
40914
40957
|
|
|
40915
40958
|
cmd.run = function(job, targets, opts, cb) {
|
|
40916
40959
|
var commandStr, commands;
|
|
40917
|
-
if (opts.
|
|
40918
|
-
|
|
40919
|
-
}
|
|
40920
|
-
if (!opts.commands) {
|
|
40921
|
-
stop("Missing commands parameter");
|
|
40960
|
+
if (!opts.expression) {
|
|
40961
|
+
stop("Missing expression parameter");
|
|
40922
40962
|
}
|
|
40923
|
-
commandStr = runGlobalExpression(opts.
|
|
40963
|
+
commandStr = runGlobalExpression(opts.expression, targets);
|
|
40924
40964
|
if (commandStr) {
|
|
40925
40965
|
commands = parseCommands(commandStr);
|
|
40926
40966
|
runParsedCommands(commands, job, cb);
|
|
@@ -40937,6 +40977,8 @@ ${svg}
|
|
|
40937
40977
|
targetData = getRunCommandData(targets[0]);
|
|
40938
40978
|
Object.defineProperty(ctx, 'target', {value: targetData});
|
|
40939
40979
|
}
|
|
40980
|
+
// Add defined functions and data to the expression context
|
|
40981
|
+
// (Such as functions imported via the -require command)
|
|
40940
40982
|
utils.extend(ctx, getStashedVar('defs'));
|
|
40941
40983
|
try {
|
|
40942
40984
|
output = Function('ctx', 'with(ctx) {return (' + expression + ');}').call({}, ctx);
|
|
@@ -43220,7 +43262,7 @@ ${svg}
|
|
|
43220
43262
|
applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
|
|
43221
43263
|
|
|
43222
43264
|
} else if (name == 'define') {
|
|
43223
|
-
cmd.define(opts);
|
|
43265
|
+
cmd.define(job.catalog, opts);
|
|
43224
43266
|
|
|
43225
43267
|
} else if (name == 'dissolve') {
|
|
43226
43268
|
outputLayers = applyCommandToEachLayer(cmd.dissolve, targetLayers, arcs, opts);
|
|
@@ -43648,7 +43690,6 @@ ${svg}
|
|
|
43648
43690
|
|
|
43649
43691
|
// Unified function for processing calls to runCommands() and applyCommands()
|
|
43650
43692
|
function _runCommands(argv, opts, callback) {
|
|
43651
|
-
|
|
43652
43693
|
var outputArr = opts.output || null,
|
|
43653
43694
|
inputObj = opts.input,
|
|
43654
43695
|
commands;
|
package/package.json
CHANGED
package/www/index.html
CHANGED
|
@@ -154,9 +154,14 @@
|
|
|
154
154
|
<div class="export-formats option-menu">
|
|
155
155
|
</div>
|
|
156
156
|
|
|
157
|
-
<div class="option-menu"><input type="text" class="advanced-options" placeholder="command line options"
|
|
158
|
-
<
|
|
159
|
-
"
|
|
157
|
+
<div class="option-menu"><input type="text" class="advanced-options" placeholder="command line options" />
|
|
158
|
+
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-o-output" target="_mapshaper_output_docs">
|
|
159
|
+
<div class="tip-button">?<div class="tip-anchor">
|
|
160
|
+
<div class="tip">Enter options from the command line interface for
|
|
161
|
+
the -o command. Examples: bbox no-quantization
|
|
162
|
+
precision=0.001. Click to see all options.</div></div></div></a>
|
|
163
|
+
|
|
164
|
+
</div>
|
|
160
165
|
<!-- <div class="cancel-btn btn dialog-btn">Cancel</div> -->
|
|
161
166
|
<div class="save-btn btn dialog-btn">Export</div>
|
|
162
167
|
<span id="save-preference"><input type="checkbox"/>choose directory</span>
|
|
@@ -283,10 +288,13 @@ apply to TopoJSON files.</div></div></div></div> -->
|
|
|
283
288
|
|
|
284
289
|
</div>
|
|
285
290
|
|
|
286
|
-
<div><input type="text" class="advanced-options" placeholder="import options"
|
|
291
|
+
<div><input type="text" class="advanced-options" placeholder="import options" />
|
|
292
|
+
<a href="https://github.com/mbloch/mapshaper/wiki/Command-Reference#-i-input" target="_mapshaper_import_docs">
|
|
293
|
+
<div class="tip-button">?<div class="tip-anchor">
|
|
287
294
|
<div class="tip">Enter options from the command line
|
|
288
|
-
interface. Examples: <span id="import-option-examples">no-topology
|
|
289
|
-
encoding=big5</span
|
|
295
|
+
interface. Examples: <span id="import-option-examples">snap no-topology
|
|
296
|
+
encoding=big5</span>. Click to see all options.</div></div></div></div>
|
|
297
|
+
</a>
|
|
290
298
|
|
|
291
299
|
</div>
|
|
292
300
|
|
package/www/mapshaper-gui.js
CHANGED
|
@@ -1834,6 +1834,7 @@
|
|
|
1834
1834
|
var importCount = 0;
|
|
1835
1835
|
var importTotal = 0;
|
|
1836
1836
|
var overQuickView = false;
|
|
1837
|
+
var useQuickView = false;
|
|
1837
1838
|
var queuedFiles = [];
|
|
1838
1839
|
var manifestFiles = opts.files || [];
|
|
1839
1840
|
var catalog;
|
|
@@ -1863,21 +1864,17 @@
|
|
|
1863
1864
|
}
|
|
1864
1865
|
});
|
|
1865
1866
|
|
|
1866
|
-
function useQuickView() {
|
|
1867
|
-
return initialImport && (opts.quick_view || overQuickView);
|
|
1868
|
-
}
|
|
1869
|
-
|
|
1870
1867
|
function initDropArea(el, isQuick) {
|
|
1871
1868
|
var area = El(el)
|
|
1872
1869
|
.on('dragleave', onout)
|
|
1873
|
-
.on('dragover', onover)
|
|
1870
|
+
.on('dragover', function() {overQuickView = !!isQuick; onover();})
|
|
1874
1871
|
.on('mouseover', onover)
|
|
1875
1872
|
.on('mouseout', onout);
|
|
1876
1873
|
|
|
1877
1874
|
function onover() {
|
|
1878
|
-
overQuickView = !!isQuick;
|
|
1879
1875
|
area.addClass('dragover');
|
|
1880
1876
|
}
|
|
1877
|
+
|
|
1881
1878
|
function onout() {
|
|
1882
1879
|
overQuickView = false;
|
|
1883
1880
|
area.removeClass('dragover');
|
|
@@ -1981,6 +1978,7 @@
|
|
|
1981
1978
|
var names = getFileNames(files);
|
|
1982
1979
|
var expanded = [];
|
|
1983
1980
|
if (files.length === 0) return;
|
|
1981
|
+
useQuickView = importCount === 0 && (opts.quick_view || overQuickView);
|
|
1984
1982
|
try {
|
|
1985
1983
|
expanded = await expandFiles(files);
|
|
1986
1984
|
} catch(e) {
|
|
@@ -1995,7 +1993,7 @@
|
|
|
1995
1993
|
return;
|
|
1996
1994
|
}
|
|
1997
1995
|
gui.enterMode('import');
|
|
1998
|
-
if (useQuickView
|
|
1996
|
+
if (useQuickView) {
|
|
1999
1997
|
await importQueuedFiles();
|
|
2000
1998
|
} else {
|
|
2001
1999
|
gui.container.addClass('queued-files');
|
|
@@ -2091,7 +2089,7 @@
|
|
|
2091
2089
|
|
|
2092
2090
|
function readImportOpts() {
|
|
2093
2091
|
var importOpts;
|
|
2094
|
-
if (useQuickView
|
|
2092
|
+
if (useQuickView) {
|
|
2095
2093
|
importOpts = {}; // default opts using quickview
|
|
2096
2094
|
} else {
|
|
2097
2095
|
var freeform = El('#import-options .advanced-options').node().value;
|
|
@@ -4040,8 +4038,11 @@
|
|
|
4040
4038
|
}
|
|
4041
4039
|
|
|
4042
4040
|
function updateMenuBtn() {
|
|
4043
|
-
var
|
|
4044
|
-
|
|
4041
|
+
var lyrName = model.getActiveLayer().layer.name || '';
|
|
4042
|
+
var menuTitle = lyrName || '[unnamed layer]';
|
|
4043
|
+
var pageTitle = lyrName || 'mapshaper';
|
|
4044
|
+
btn.classed('active', 'true').findChild('.layer-name').html(menuTitle + " ▼");
|
|
4045
|
+
window.document.title = pageTitle;
|
|
4045
4046
|
}
|
|
4046
4047
|
|
|
4047
4048
|
function render() {
|
|
@@ -10174,12 +10175,12 @@
|
|
|
10174
10175
|
return action == 'hover' && _overlayCanv.visible();
|
|
10175
10176
|
}
|
|
10176
10177
|
|
|
10177
|
-
function drawCanvasLayer(
|
|
10178
|
-
if (!
|
|
10179
|
-
if (
|
|
10180
|
-
drawOutlineLayerToCanvas(
|
|
10178
|
+
function drawCanvasLayer(lyr, canv) {
|
|
10179
|
+
if (!lyr) return;
|
|
10180
|
+
if (lyr.style.type == 'outline') {
|
|
10181
|
+
drawOutlineLayerToCanvas(lyr, canv, ext);
|
|
10181
10182
|
} else {
|
|
10182
|
-
drawStyledLayerToCanvas(
|
|
10183
|
+
drawStyledLayerToCanvas(lyr, canv, ext);
|
|
10183
10184
|
}
|
|
10184
10185
|
}
|
|
10185
10186
|
|
|
@@ -11041,7 +11042,9 @@
|
|
|
11041
11042
|
} else {
|
|
11042
11043
|
_overlayLyr = null;
|
|
11043
11044
|
}
|
|
11044
|
-
|
|
11045
|
+
// 'hover' bypasses style creation in drawLayers2()... sometimes we need that
|
|
11046
|
+
// drawLayers('hover');
|
|
11047
|
+
drawLayers();
|
|
11045
11048
|
}
|
|
11046
11049
|
|
|
11047
11050
|
function getDisplayOptions() {
|
|
@@ -11056,12 +11059,14 @@
|
|
|
11056
11059
|
return flags.simplify_method || flags.simplify || flags.proj ||
|
|
11057
11060
|
flags.arc_count || flags.repair || flags.clip || flags.erase ||
|
|
11058
11061
|
flags.slice || flags.affine || flags.rectangle || flags.buffer ||
|
|
11059
|
-
flags.union || flags.mosaic || flags.snap || flags.clean || false;
|
|
11062
|
+
flags.union || flags.mosaic || flags.snap || flags.clean || flags.drop || false;
|
|
11060
11063
|
}
|
|
11061
11064
|
|
|
11062
11065
|
// Test if an update allows hover popup to stay open
|
|
11063
11066
|
function popupCanStayOpen(flags) {
|
|
11064
|
-
//
|
|
11067
|
+
// keeping popup open after -drop geometry causes problems...
|
|
11068
|
+
// // if (arcsMayHaveChanged(flags)) return false;
|
|
11069
|
+
if (arcsMayHaveChanged(flags)) return false;
|
|
11065
11070
|
if (flags.points || flags.proj) return false;
|
|
11066
11071
|
if (!flags.same_table) return false;
|
|
11067
11072
|
return true;
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.33";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -11665,8 +11665,16 @@
|
|
|
11665
11665
|
}
|
|
11666
11666
|
cands.forEach(function(cand) {
|
|
11667
11667
|
var p = getTestPoint(cand.ids);
|
|
11668
|
-
var isEnclosed = b.containsPoint(p[0], p[1]) &&
|
|
11669
|
-
|
|
11668
|
+
var isEnclosed = b.containsPoint(p[0], p[1]) &&
|
|
11669
|
+
// added a bounds-in-bounds test to handle a case where the test point
|
|
11670
|
+
// fell along the shared boundary of two rings, but the rings did no overlap
|
|
11671
|
+
// (this gave a false positive for the enclosure test)
|
|
11672
|
+
// (for speed, the midpoint of an arc is used as the test point; this
|
|
11673
|
+
// works well in the typical case where rings to not share an edge.
|
|
11674
|
+
// Finding an internal test point would be better, we just need a fast
|
|
11675
|
+
// function to find internal points)
|
|
11676
|
+
b.contains(cand.bounds) &&
|
|
11677
|
+
(index ? index.pointInPolygon(p[0], p[1]) : geom.testPointInRing(p[0], p[1], pathIds, arcs));
|
|
11670
11678
|
if (isEnclosed) {
|
|
11671
11679
|
paths.push(cand.ids);
|
|
11672
11680
|
}
|
|
@@ -11674,6 +11682,7 @@
|
|
|
11674
11682
|
return paths.length > 0 ? paths : null;
|
|
11675
11683
|
};
|
|
11676
11684
|
|
|
11685
|
+
// return array of indexed paths within a given shape
|
|
11677
11686
|
this.findPathsInsideShape = function(shape) {
|
|
11678
11687
|
var paths = []; // list of enclosed paths
|
|
11679
11688
|
shape.forEach(function(ids) {
|
|
@@ -12075,7 +12084,6 @@
|
|
|
12075
12084
|
yy = coords.yy,
|
|
12076
12085
|
ids = nodes.getConnectedArcs(fromArcId),
|
|
12077
12086
|
toArcId = fromArcId; // initialize to fromArcId -- an error condition
|
|
12078
|
-
|
|
12079
12087
|
if (filter) {
|
|
12080
12088
|
ids = ids.filter(filter);
|
|
12081
12089
|
}
|
|
@@ -12104,14 +12112,12 @@
|
|
|
12104
12112
|
continue;
|
|
12105
12113
|
}
|
|
12106
12114
|
icand = arcs.indexOfVertex(candId, -2);
|
|
12107
|
-
|
|
12108
12115
|
if (toArcId == fromArcId) {
|
|
12109
12116
|
// first valid candidate
|
|
12110
12117
|
ito = icand;
|
|
12111
12118
|
toArcId = candId;
|
|
12112
12119
|
continue;
|
|
12113
12120
|
}
|
|
12114
|
-
|
|
12115
12121
|
code = chooseRighthandPath(fromX, fromY, nodeX, nodeY, xx[ito], yy[ito], xx[icand], yy[icand]);
|
|
12116
12122
|
if (code == 2) {
|
|
12117
12123
|
ito = icand;
|
|
@@ -12119,6 +12125,7 @@
|
|
|
12119
12125
|
}
|
|
12120
12126
|
}
|
|
12121
12127
|
|
|
12128
|
+
|
|
12122
12129
|
if (toArcId == fromArcId) {
|
|
12123
12130
|
// This shouldn't occur, assuming that other arcs are present
|
|
12124
12131
|
error("Pathfinder error");
|
|
@@ -12183,6 +12190,9 @@
|
|
|
12183
12190
|
chooseRighthandVector: chooseRighthandVector
|
|
12184
12191
|
});
|
|
12185
12192
|
|
|
12193
|
+
var FWD_USED = 0x8;
|
|
12194
|
+
var REV_USED = 0x80;
|
|
12195
|
+
|
|
12186
12196
|
function setBits(bits, arcBits, mask) {
|
|
12187
12197
|
return (bits & ~mask) | (arcBits & mask);
|
|
12188
12198
|
}
|
|
@@ -12210,6 +12220,16 @@
|
|
|
12210
12220
|
return bits & 7;
|
|
12211
12221
|
}
|
|
12212
12222
|
|
|
12223
|
+
function markPathsAsUsed(paths, routesArr) {
|
|
12224
|
+
forEachArcId(paths, function(arcId) {
|
|
12225
|
+
if (arcId < 0) {
|
|
12226
|
+
routesArr[~arcId] |= REV_USED;
|
|
12227
|
+
} else {
|
|
12228
|
+
routesArr[arcId] |= FWD_USED;
|
|
12229
|
+
}
|
|
12230
|
+
});
|
|
12231
|
+
}
|
|
12232
|
+
|
|
12213
12233
|
// Open arc pathways in a single shape or array of shapes
|
|
12214
12234
|
//
|
|
12215
12235
|
function openArcRoutes(paths, arcColl, routesArr, fwd, rev, dissolve, orBits) {
|
|
@@ -12400,6 +12420,7 @@
|
|
|
12400
12420
|
andBits: andBits,
|
|
12401
12421
|
setRouteBits: setRouteBits,
|
|
12402
12422
|
getRouteBits: getRouteBits,
|
|
12423
|
+
markPathsAsUsed: markPathsAsUsed,
|
|
12403
12424
|
openArcRoutes: openArcRoutes,
|
|
12404
12425
|
closeArcRoutes: closeArcRoutes,
|
|
12405
12426
|
getPathFinder: getPathFinder,
|
|
@@ -24840,13 +24861,12 @@ ${svg}
|
|
|
24840
24861
|
|
|
24841
24862
|
parser.command('run')
|
|
24842
24863
|
.describe('create commands on-the-fly and run them')
|
|
24843
|
-
.option('
|
|
24844
|
-
// TODO: remove this option
|
|
24845
|
-
})
|
|
24846
|
-
.option('commands', {
|
|
24864
|
+
.option('expression', {
|
|
24847
24865
|
DEFAULT: true,
|
|
24848
|
-
describe: '
|
|
24866
|
+
describe: 'JS expression to generate command(s)'
|
|
24849
24867
|
})
|
|
24868
|
+
// deprecated
|
|
24869
|
+
.option('commands', {alias_to: 'expression'})
|
|
24850
24870
|
.option('target', targetOpt);
|
|
24851
24871
|
|
|
24852
24872
|
parser.command('scalebar')
|
|
@@ -33402,7 +33422,7 @@ ${svg}
|
|
|
33402
33422
|
var clipArcTouches = 0;
|
|
33403
33423
|
var clipArcUses = 0;
|
|
33404
33424
|
var usedClipArcs = [];
|
|
33405
|
-
var
|
|
33425
|
+
var findPath = getPathFinder(nodes, useRoute, routeIsActive);
|
|
33406
33426
|
var dissolvePolygon = getPolygonDissolver(nodes);
|
|
33407
33427
|
|
|
33408
33428
|
// The following cleanup step is a performance bottleneck (it often takes longer than
|
|
@@ -33435,12 +33455,16 @@ ${svg}
|
|
|
33435
33455
|
return null;
|
|
33436
33456
|
});
|
|
33437
33457
|
|
|
33458
|
+
markPathsAsUsed(clippedShapes, routeFlags); // to help us find unused paths later
|
|
33459
|
+
|
|
33460
|
+
|
|
33438
33461
|
// add clip/erase polygons that are fully contained in a target polygon
|
|
33439
33462
|
// need to index only non-intersecting clip shapes
|
|
33440
33463
|
// (Intersecting shapes have one or more arcs that have been scanned)
|
|
33441
33464
|
|
|
33442
33465
|
// first, find shapes that do not intersect the target layer
|
|
33443
33466
|
// (these could be inside or outside the target polygons)
|
|
33467
|
+
|
|
33444
33468
|
var undividedClipShapes = findUndividedClipShapes(clipShapes);
|
|
33445
33469
|
|
|
33446
33470
|
closeArcRoutes(clipShapes, arcs, routeFlags, true, true); // not needed?
|
|
@@ -33469,7 +33493,7 @@ ${svg}
|
|
|
33469
33493
|
for (var i=0, n=ids.length; i<n; i++) {
|
|
33470
33494
|
clipArcTouches = 0;
|
|
33471
33495
|
clipArcUses = 0;
|
|
33472
|
-
path =
|
|
33496
|
+
path = findPath(ids[i]);
|
|
33473
33497
|
if (path) {
|
|
33474
33498
|
// if ring doesn't touch/intersect a clip/erase polygon, check if it is contained
|
|
33475
33499
|
// if (clipArcTouches === 0) {
|
|
@@ -33488,6 +33512,7 @@ ${svg}
|
|
|
33488
33512
|
}
|
|
33489
33513
|
});
|
|
33490
33514
|
|
|
33515
|
+
|
|
33491
33516
|
// Clear pathways of current target shape to hidden/closed
|
|
33492
33517
|
closeArcRoutes(shape, arcs, routeFlags, true, true, true);
|
|
33493
33518
|
// Also clear pathways of any clip arcs that were used
|
|
@@ -33558,8 +33583,9 @@ ${svg}
|
|
|
33558
33583
|
return usable;
|
|
33559
33584
|
}
|
|
33560
33585
|
|
|
33561
|
-
|
|
33562
|
-
//
|
|
33586
|
+
|
|
33587
|
+
// Filter a collection of shapes to exclude paths that incorporate parts of
|
|
33588
|
+
// clip/erase polygons and paths that are hidden (e.g. internal boundaries)
|
|
33563
33589
|
function findUndividedClipShapes(clipShapes) {
|
|
33564
33590
|
return clipShapes.map(function(shape) {
|
|
33565
33591
|
var usableParts = [];
|
|
@@ -33583,12 +33609,12 @@ ${svg}
|
|
|
33583
33609
|
});
|
|
33584
33610
|
}
|
|
33585
33611
|
|
|
33586
|
-
|
|
33587
|
-
// (not testing open/closed or visible/hidden)
|
|
33612
|
+
|
|
33588
33613
|
function arcIsUnused(id, flags) {
|
|
33589
33614
|
var abs = absArcId(id),
|
|
33590
33615
|
flag = flags[abs];
|
|
33591
|
-
return (flag &
|
|
33616
|
+
return (flag & 0x88) === 0;
|
|
33617
|
+
// return id < 0 ? (flag & 0x80) === 0 : (flag & 0x8) === 0;
|
|
33592
33618
|
}
|
|
33593
33619
|
|
|
33594
33620
|
function arcIsVisible(id, flags) {
|
|
@@ -33611,7 +33637,7 @@ ${svg}
|
|
|
33611
33637
|
enclosedPaths.forEach(function(ids) {
|
|
33612
33638
|
var path;
|
|
33613
33639
|
for (var j=0; j<ids.length; j++) {
|
|
33614
|
-
path =
|
|
33640
|
+
path = findPath(ids[j]);
|
|
33615
33641
|
if (path) {
|
|
33616
33642
|
dissolvedPaths.push(path);
|
|
33617
33643
|
}
|
|
@@ -34730,7 +34756,64 @@ ${svg}
|
|
|
34730
34756
|
};
|
|
34731
34757
|
}
|
|
34732
34758
|
|
|
34733
|
-
|
|
34759
|
+
function compileIfCommandExpression(expr, catalog, opts) {
|
|
34760
|
+
return compileLayerExpression(expr, catalog, opts);
|
|
34761
|
+
}
|
|
34762
|
+
|
|
34763
|
+
|
|
34764
|
+
function compileLayerExpression(expr, catalog, opts) {
|
|
34765
|
+
var targetId = opts.layer || opts.target || null;
|
|
34766
|
+
var targets = catalog.findCommandTargets(targetId);
|
|
34767
|
+
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
34768
|
+
if (targets.length === 0 && targetId) {
|
|
34769
|
+
stop('Layer not found:', targetId);
|
|
34770
|
+
}
|
|
34771
|
+
// var vars = getAssignedVars(exp);
|
|
34772
|
+
var defs = getStashedVar('defs') || {};
|
|
34773
|
+
|
|
34774
|
+
var ctx;
|
|
34775
|
+
if (isSingle) {
|
|
34776
|
+
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs);
|
|
34777
|
+
} else {
|
|
34778
|
+
ctx = getNullLayerProxy(targets);
|
|
34779
|
+
}
|
|
34780
|
+
ctx.global = defs; // TODO: remove duplication with mapshaper.expressions.mjs
|
|
34781
|
+
var exprOpts = Object.assign({returns: true}, opts);
|
|
34782
|
+
var func = compileExpressionToFunction(expr, exprOpts);
|
|
34783
|
+
|
|
34784
|
+
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
34785
|
+
ctx.layer_exists = function(name, geoType) {
|
|
34786
|
+
try {
|
|
34787
|
+
var targets = catalog.findCommandTargets(name, geoType);
|
|
34788
|
+
if (targets.length > 0) return true;
|
|
34789
|
+
} catch(e) {}
|
|
34790
|
+
return false;
|
|
34791
|
+
};
|
|
34792
|
+
|
|
34793
|
+
ctx.file_exists = function(file) {
|
|
34794
|
+
return cli.isFile(file);
|
|
34795
|
+
};
|
|
34796
|
+
|
|
34797
|
+
return function() {
|
|
34798
|
+
try {
|
|
34799
|
+
return func.call(ctx, defs, ctx);
|
|
34800
|
+
} catch(e) {
|
|
34801
|
+
// if (opts.quiet) throw e;
|
|
34802
|
+
stop(e.name, "in expression [" + expr + "]:", e.message);
|
|
34803
|
+
}
|
|
34804
|
+
};
|
|
34805
|
+
}
|
|
34806
|
+
|
|
34807
|
+
/*
|
|
34808
|
+
cmd.define_v2 = function(catalog, opts) {
|
|
34809
|
+
if (!opts.expression) {
|
|
34810
|
+
stop('Missing an assignment expression');
|
|
34811
|
+
}
|
|
34812
|
+
compileLayerExpression(opts.expression, catalog, opts)();
|
|
34813
|
+
};
|
|
34814
|
+
*/
|
|
34815
|
+
|
|
34816
|
+
cmd.define = function(catalog, opts) {
|
|
34734
34817
|
if (!opts.expression) {
|
|
34735
34818
|
stop('Missing an assignment expression');
|
|
34736
34819
|
}
|
|
@@ -38418,46 +38501,6 @@ ${svg}
|
|
|
38418
38501
|
return job.control || (job.control = {});
|
|
38419
38502
|
}
|
|
38420
38503
|
|
|
38421
|
-
function compileIfCommandExpression(expr, catalog, opts) {
|
|
38422
|
-
var targetId = opts.layer || opts.target || null;
|
|
38423
|
-
var targets = catalog.findCommandTargets(targetId);
|
|
38424
|
-
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
38425
|
-
if (targets.length === 0 && targetId) {
|
|
38426
|
-
stop('Layer not found:', targetId);
|
|
38427
|
-
}
|
|
38428
|
-
var ctx;
|
|
38429
|
-
if (isSingle) {
|
|
38430
|
-
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs);
|
|
38431
|
-
} else {
|
|
38432
|
-
ctx = getNullLayerProxy(targets);
|
|
38433
|
-
}
|
|
38434
|
-
ctx.global = getStashedVar('defs') || {}; // TODO: remove duplication with mapshaper.expressions.mjs
|
|
38435
|
-
var exprOpts = Object.assign({returns: true}, opts);
|
|
38436
|
-
var func = compileExpressionToFunction(expr, exprOpts);
|
|
38437
|
-
|
|
38438
|
-
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
38439
|
-
ctx.layer_exists = function(name, geoType) {
|
|
38440
|
-
try {
|
|
38441
|
-
var targets = catalog.findCommandTargets(name, geoType);
|
|
38442
|
-
if (targets.length > 0) return true;
|
|
38443
|
-
} catch(e) {}
|
|
38444
|
-
return false;
|
|
38445
|
-
};
|
|
38446
|
-
|
|
38447
|
-
ctx.file_exists = function(file) {
|
|
38448
|
-
return cli.isFile(file);
|
|
38449
|
-
};
|
|
38450
|
-
|
|
38451
|
-
return function() {
|
|
38452
|
-
try {
|
|
38453
|
-
return func.call(ctx, {}, ctx);
|
|
38454
|
-
} catch(e) {
|
|
38455
|
-
// if (opts.quiet) throw e;
|
|
38456
|
-
stop(e.name, "in expression [" + expr + "]:", e.message);
|
|
38457
|
-
}
|
|
38458
|
-
};
|
|
38459
|
-
}
|
|
38460
|
-
|
|
38461
38504
|
function skipCommand(cmdName, job) {
|
|
38462
38505
|
// allow all control commands to run
|
|
38463
38506
|
if (jobIsStopped(job)) return true;
|
|
@@ -40914,13 +40957,10 @@ ${svg}
|
|
|
40914
40957
|
|
|
40915
40958
|
cmd.run = function(job, targets, opts, cb) {
|
|
40916
40959
|
var commandStr, commands;
|
|
40917
|
-
if (opts.
|
|
40918
|
-
|
|
40919
|
-
}
|
|
40920
|
-
if (!opts.commands) {
|
|
40921
|
-
stop("Missing commands parameter");
|
|
40960
|
+
if (!opts.expression) {
|
|
40961
|
+
stop("Missing expression parameter");
|
|
40922
40962
|
}
|
|
40923
|
-
commandStr = runGlobalExpression(opts.
|
|
40963
|
+
commandStr = runGlobalExpression(opts.expression, targets);
|
|
40924
40964
|
if (commandStr) {
|
|
40925
40965
|
commands = parseCommands(commandStr);
|
|
40926
40966
|
runParsedCommands(commands, job, cb);
|
|
@@ -40937,6 +40977,8 @@ ${svg}
|
|
|
40937
40977
|
targetData = getRunCommandData(targets[0]);
|
|
40938
40978
|
Object.defineProperty(ctx, 'target', {value: targetData});
|
|
40939
40979
|
}
|
|
40980
|
+
// Add defined functions and data to the expression context
|
|
40981
|
+
// (Such as functions imported via the -require command)
|
|
40940
40982
|
utils.extend(ctx, getStashedVar('defs'));
|
|
40941
40983
|
try {
|
|
40942
40984
|
output = Function('ctx', 'with(ctx) {return (' + expression + ');}').call({}, ctx);
|
|
@@ -43220,7 +43262,7 @@ ${svg}
|
|
|
43220
43262
|
applyCommandToEachLayer(cmd.dashlines, targetLayers, targetDataset, opts);
|
|
43221
43263
|
|
|
43222
43264
|
} else if (name == 'define') {
|
|
43223
|
-
cmd.define(opts);
|
|
43265
|
+
cmd.define(job.catalog, opts);
|
|
43224
43266
|
|
|
43225
43267
|
} else if (name == 'dissolve') {
|
|
43226
43268
|
outputLayers = applyCommandToEachLayer(cmd.dissolve, targetLayers, arcs, opts);
|
|
@@ -43648,7 +43690,6 @@ ${svg}
|
|
|
43648
43690
|
|
|
43649
43691
|
// Unified function for processing calls to runCommands() and applyCommands()
|
|
43650
43692
|
function _runCommands(argv, opts, callback) {
|
|
43651
|
-
|
|
43652
43693
|
var outputArr = opts.output || null,
|
|
43653
43694
|
inputObj = opts.input,
|
|
43654
43695
|
commands;
|