mapshaper 0.6.34 → 0.6.36
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 +59 -30
- package/package.json +1 -1
- package/www/mapshaper-gui.js +126 -83
- package/www/mapshaper.js +59 -30
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.36";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -5829,11 +5829,11 @@
|
|
|
5829
5829
|
};
|
|
5830
5830
|
|
|
5831
5831
|
// TODO: move this and similar methods out of ArcCollection
|
|
5832
|
-
this.getMultiShapeBounds = function(
|
|
5832
|
+
this.getMultiShapeBounds = function(shp, bounds) {
|
|
5833
5833
|
bounds = bounds || new Bounds();
|
|
5834
|
-
if (
|
|
5835
|
-
for (var i=0, n=
|
|
5836
|
-
this.getSimpleShapeBounds(
|
|
5834
|
+
if (shp) { // handle null shapes
|
|
5835
|
+
for (var i=0, n=shp.length; i<n; i++) {
|
|
5836
|
+
this.getSimpleShapeBounds(shp[i], bounds);
|
|
5837
5837
|
}
|
|
5838
5838
|
}
|
|
5839
5839
|
return bounds;
|
|
@@ -12719,7 +12719,7 @@
|
|
|
12719
12719
|
}
|
|
12720
12720
|
var sliverControl = opts.sliver_control >= 0 ? opts.sliver_control : 0; // 0 is default
|
|
12721
12721
|
var crs = getDatasetCRS(dataset);
|
|
12722
|
-
var threshold = areaArg ?
|
|
12722
|
+
var threshold = areaArg && areaArg != 'auto' ?
|
|
12723
12723
|
convertAreaParam(areaArg, crs) :
|
|
12724
12724
|
getDefaultSliverThreshold(lyr, dataset.arcs);
|
|
12725
12725
|
var filter = sliverControl > 0 ?
|
|
@@ -16653,7 +16653,8 @@
|
|
|
16653
16653
|
overlap_rule: opts.overlap_rule
|
|
16654
16654
|
};
|
|
16655
16655
|
var mosaicIndex = new MosaicIndex(lyr, nodes, mosaicOpts);
|
|
16656
|
-
|
|
16656
|
+
// gap fill doesn't work yet with overlapping shapes
|
|
16657
|
+
var fillGaps = !opts.allow_overlaps && (opts.sliver_control || opts.gap_fill_area);
|
|
16657
16658
|
var cleanupData, filterData;
|
|
16658
16659
|
if (fillGaps) {
|
|
16659
16660
|
var sliverOpts = utils.extend({sliver_control: 1}, opts);
|
|
@@ -16935,6 +16936,7 @@
|
|
|
16935
16936
|
|
|
16936
16937
|
function cleanPolygonLayerGeometry(lyr, dataset, opts) {
|
|
16937
16938
|
// clean polygons by apply the 'dissolve2' function to each feature
|
|
16939
|
+
opts = Object.assign({gap_fill_area: 'auto'}, opts);
|
|
16938
16940
|
var groups = lyr.shapes.map(function(shp, i) {
|
|
16939
16941
|
return [i];
|
|
16940
16942
|
});
|
|
@@ -19130,6 +19132,47 @@
|
|
|
19130
19132
|
return str1;
|
|
19131
19133
|
}
|
|
19132
19134
|
|
|
19135
|
+
function getSphereEffectParams() {
|
|
19136
|
+
return {
|
|
19137
|
+
cx: 0.5,
|
|
19138
|
+
cy: 0.5,
|
|
19139
|
+
r: 0.57,
|
|
19140
|
+
fx: 0.35,
|
|
19141
|
+
fy: 0.35,
|
|
19142
|
+
stops: [
|
|
19143
|
+
{offset: 0.3, opacity: 0},
|
|
19144
|
+
{offset: 0.6, opacity: 0.1},
|
|
19145
|
+
{offset: 0.78, opacity: 0.25},
|
|
19146
|
+
{offset: 0.87, opacity: 0.45},
|
|
19147
|
+
{offset: 0.95, opacity: 1}]
|
|
19148
|
+
};
|
|
19149
|
+
}
|
|
19150
|
+
|
|
19151
|
+
function convertFillEffect(obj, defs) {
|
|
19152
|
+
if (obj['fill-effect'] != 'sphere') return; // only "sphere" is supported
|
|
19153
|
+
var id = 'mapshaper_sphere_effect';
|
|
19154
|
+
var href = `url(#${ id })`;
|
|
19155
|
+
var params = getSphereEffectParams();
|
|
19156
|
+
var stops = params.stops.map(function(stop) {
|
|
19157
|
+
return `<stop offset="${stop.offset}" stop-opacity="${stop.opacity}"/>`;
|
|
19158
|
+
});
|
|
19159
|
+
var svg =
|
|
19160
|
+
`<radialGradient id="${id}" cx="${params.cx}" cy="${params.cy}" r="${params.r}" fx="${params.fx}" fy="${params.fy}">${stops.join('')}</radialGradient>` ;
|
|
19161
|
+
if (!utils.find(defs, function(o) { return o.id == id; })) {
|
|
19162
|
+
defs.push({svg, id, href});
|
|
19163
|
+
}
|
|
19164
|
+
obj.fill = href;
|
|
19165
|
+
if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
|
|
19166
|
+
obj['fill-opacity'] = 0.35;
|
|
19167
|
+
}
|
|
19168
|
+
}
|
|
19169
|
+
|
|
19170
|
+
var SvgEffect = /*#__PURE__*/Object.freeze({
|
|
19171
|
+
__proto__: null,
|
|
19172
|
+
getSphereEffectParams: getSphereEffectParams,
|
|
19173
|
+
convertFillEffect: convertFillEffect
|
|
19174
|
+
});
|
|
19175
|
+
|
|
19133
19176
|
var cache = {};
|
|
19134
19177
|
function fetchFileSync(url) {
|
|
19135
19178
|
if (url in cache) return cache[url];
|
|
@@ -19147,8 +19190,8 @@
|
|
|
19147
19190
|
if (obj.tag == 'path' && obj.properties['fill-pattern']) {
|
|
19148
19191
|
convertFillPattern(obj.properties, defs);
|
|
19149
19192
|
}
|
|
19150
|
-
if (obj.tag == 'path' && obj.properties['fill-effect']
|
|
19151
|
-
|
|
19193
|
+
if (obj.tag == 'path' && obj.properties['fill-effect']) {
|
|
19194
|
+
convertFillEffect(obj.properties, defs);
|
|
19152
19195
|
}
|
|
19153
19196
|
if (obj.tag == 'image') {
|
|
19154
19197
|
if (/\.svg/.test(obj.properties.href || '')) {
|
|
@@ -19160,25 +19203,6 @@
|
|
|
19160
19203
|
}
|
|
19161
19204
|
}
|
|
19162
19205
|
|
|
19163
|
-
function convertSphereEffect(obj, defs) {
|
|
19164
|
-
var id = 'mapshaper_sphere_effect';
|
|
19165
|
-
var href = `url(#${ id })`;
|
|
19166
|
-
var svg =
|
|
19167
|
-
`<radialGradient id="${id}" cx="0.5" cy="0.5" r=".56" fx="0.4" fy="0.35">
|
|
19168
|
-
<stop offset=".35" stop-opacity="0"/>
|
|
19169
|
-
<stop offset=".65" stop-opacity="0.1" />
|
|
19170
|
-
<stop offset=".85" stop-opacity="0.45" />
|
|
19171
|
-
<stop offset=".95" stop-opacity="1" />
|
|
19172
|
-
</radialGradient>` ;
|
|
19173
|
-
if (!utils.find(defs, function(o) { return o.id == id; })) {
|
|
19174
|
-
defs.push({svg, id, href});
|
|
19175
|
-
}
|
|
19176
|
-
obj.fill = href;
|
|
19177
|
-
if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
|
|
19178
|
-
obj['fill-opacity'] = 0.35;
|
|
19179
|
-
}
|
|
19180
|
-
}
|
|
19181
|
-
|
|
19182
19206
|
function convertSvgImage(obj, defs) {
|
|
19183
19207
|
// Same-origin policy prevents embedding images in the web UI
|
|
19184
19208
|
var href = obj.properties.href;
|
|
@@ -23698,7 +23722,10 @@ ${svg}
|
|
|
23698
23722
|
.option('calc', calcOpt)
|
|
23699
23723
|
.option('sum-fields', sumFieldsOpt)
|
|
23700
23724
|
.option('copy-fields', copyFieldsOpt)
|
|
23701
|
-
.option('gap-fill-area',
|
|
23725
|
+
.option('gap-fill-area', {
|
|
23726
|
+
describe: 'threshold for filling gaps, e.g. 1.5km2',
|
|
23727
|
+
type: 'area'
|
|
23728
|
+
})
|
|
23702
23729
|
.option('sliver-control', sliverControlOpt)
|
|
23703
23730
|
.option('allow-overlaps', {
|
|
23704
23731
|
describe: 'allow dissolved polygons to overlap (disables gap fill)',
|
|
@@ -40133,6 +40160,7 @@ ${svg}
|
|
|
40133
40160
|
};
|
|
40134
40161
|
|
|
40135
40162
|
if (opts.calc) {
|
|
40163
|
+
if (!lyr.data) initDataTable(lyr);
|
|
40136
40164
|
records2 = recombineDataRecords(lyr.data.getRecords(), mosaicIndex.getSourceIdsByTileId, mosaicShapes.length, opts);
|
|
40137
40165
|
lyr2.data = new DataTable(records2);
|
|
40138
40166
|
}
|
|
@@ -43164,7 +43192,7 @@ ${svg}
|
|
|
43164
43192
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43165
43193
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43166
43194
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43167
|
-
name == 'else' || name == 'endif';
|
|
43195
|
+
name == 'else' || name == 'endif' || name == 'run';
|
|
43168
43196
|
}
|
|
43169
43197
|
|
|
43170
43198
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -44390,6 +44418,7 @@ ${svg}
|
|
|
44390
44418
|
Topology,
|
|
44391
44419
|
Units,
|
|
44392
44420
|
SvgHatch,
|
|
44421
|
+
SvgEffect,
|
|
44393
44422
|
VertexUtils,
|
|
44394
44423
|
Zip
|
|
44395
44424
|
);
|
package/package.json
CHANGED
package/www/mapshaper-gui.js
CHANGED
|
@@ -9045,6 +9045,7 @@
|
|
|
9045
9045
|
r: 'radius',
|
|
9046
9046
|
'fill': 'fillColor',
|
|
9047
9047
|
'fill-pattern': 'fillPattern',
|
|
9048
|
+
'fill-effect': 'fillEffect',
|
|
9048
9049
|
'fill-opacity': 'fillOpacity',
|
|
9049
9050
|
'stroke': 'strokeColor',
|
|
9050
9051
|
'stroke-width': 'strokeWidth',
|
|
@@ -9359,6 +9360,117 @@
|
|
|
9359
9360
|
|
|
9360
9361
|
utils$1.inherit(MapExtent, EventDispatcher);
|
|
9361
9362
|
|
|
9363
|
+
var hatches = {}; // cached patterns
|
|
9364
|
+
|
|
9365
|
+
function getCanvasFillEffect(ctx, shp, arcs, ext, style) {
|
|
9366
|
+
var bounds = arcs.getMultiShapeBounds(shp);
|
|
9367
|
+
if (!bounds.hasBounds() || style.fillEffect != 'sphere') {
|
|
9368
|
+
return null;
|
|
9369
|
+
}
|
|
9370
|
+
bounds.transform(ext.getTransform(GUI.getPixelRatio()));
|
|
9371
|
+
bounds.fillOut(1); // convert to square
|
|
9372
|
+
var o = convertSvgSphereParams(bounds);
|
|
9373
|
+
var fill = ctx.createRadialGradient(o.x0, o.y0, o.r0, o.x1, o.y1, o.r1);
|
|
9374
|
+
o.stops.forEach(function(stop) {
|
|
9375
|
+
fill.addColorStop(stop.offset, stop.color);
|
|
9376
|
+
});
|
|
9377
|
+
return fill;
|
|
9378
|
+
}
|
|
9379
|
+
|
|
9380
|
+
function convertSvgSphereParams(bounds) {
|
|
9381
|
+
var bbox = bounds.toArray(),
|
|
9382
|
+
d = Math.max(bounds.width(), bounds.height()),
|
|
9383
|
+
cx = bounds.centerX(),
|
|
9384
|
+
cy = bounds.centerY(),
|
|
9385
|
+
o = internal.getSphereEffectParams();
|
|
9386
|
+
return {
|
|
9387
|
+
x0: bbox[0] + d * o.fx,
|
|
9388
|
+
y0: bbox[1] + d * o.fy,
|
|
9389
|
+
r0: 0,
|
|
9390
|
+
x1: bbox[0] + d * o.cx,
|
|
9391
|
+
y1: bbox[1] + d * o.cy,
|
|
9392
|
+
r1: d * o.r,
|
|
9393
|
+
stops: o.stops.map(function(stop) {
|
|
9394
|
+
return {offset: stop.offset, color: `rgba(0,0,0,${stop.opacity})`};
|
|
9395
|
+
})
|
|
9396
|
+
};
|
|
9397
|
+
}
|
|
9398
|
+
|
|
9399
|
+
|
|
9400
|
+
function getCanvasFillPattern(style) {
|
|
9401
|
+
var fill = hatches[style.fillPattern];
|
|
9402
|
+
if (fill === undefined) {
|
|
9403
|
+
fill = makePatternFill(style);
|
|
9404
|
+
hatches[style.fillPattern] = fill;
|
|
9405
|
+
}
|
|
9406
|
+
return fill || style.fill || '#000'; // use fill if hatches are invalid
|
|
9407
|
+
}
|
|
9408
|
+
|
|
9409
|
+
function makePatternFill(style) {
|
|
9410
|
+
var o = internal.parsePattern(style.fillPattern);
|
|
9411
|
+
if (!o) return null;
|
|
9412
|
+
var canv = document.createElement('canvas');
|
|
9413
|
+
var ctx = canv.getContext('2d');
|
|
9414
|
+
var res = GUI.getPixelRatio();
|
|
9415
|
+
var w = o.tileSize[0] * res;
|
|
9416
|
+
var h = o.tileSize[1] * res;
|
|
9417
|
+
canv.setAttribute('width', w);
|
|
9418
|
+
canv.setAttribute('height', h);
|
|
9419
|
+
if (o.background) {
|
|
9420
|
+
ctx.fillStyle = o.background;
|
|
9421
|
+
ctx.fillRect(0, 0, w, h);
|
|
9422
|
+
}
|
|
9423
|
+
if (o.type == 'dots' || o.type == 'squares') makeDotFill(o, ctx, res);
|
|
9424
|
+
if (o.type == 'dashes') makeDashFill(o, ctx, res);
|
|
9425
|
+
if (o.type == 'hatches') makeHatchFill(o, ctx, res);
|
|
9426
|
+
var pattern = ctx.createPattern(canv, 'repeat');
|
|
9427
|
+
if (o.rotation) {
|
|
9428
|
+
pattern.setTransform(new DOMMatrix('rotate(' + o.rotation + 'deg)'));
|
|
9429
|
+
}
|
|
9430
|
+
return pattern;
|
|
9431
|
+
}
|
|
9432
|
+
|
|
9433
|
+
function makeDashFill(o, ctx, res) {
|
|
9434
|
+
var x = 0;
|
|
9435
|
+
for (var i=0; i<o.colors.length; i++) {
|
|
9436
|
+
ctx.fillStyle = o.colors[i];
|
|
9437
|
+
ctx.fillRect(x, 0, o.width * res, o.dashes[0] * res);
|
|
9438
|
+
x += res * (o.spacing + o.width);
|
|
9439
|
+
}
|
|
9440
|
+
}
|
|
9441
|
+
|
|
9442
|
+
function makeDotFill(o, ctx, res) {
|
|
9443
|
+
var dotSize = o.size * res;
|
|
9444
|
+
var r = dotSize / 2;
|
|
9445
|
+
var n = o.colors.length;
|
|
9446
|
+
var dist = dotSize + o.spacing * res;
|
|
9447
|
+
var dots = n * n;
|
|
9448
|
+
var x = 0, y = 0;
|
|
9449
|
+
for (var i=0; i<dots; i++) {
|
|
9450
|
+
if (o.type == 'dots') ctx.beginPath();
|
|
9451
|
+
ctx.fillStyle = o.colors[(i + Math.floor(i / n)) % n];
|
|
9452
|
+
if (o.type == 'dots') {
|
|
9453
|
+
ctx.arc(x + r, y + r, r, 0, Math.PI * 2);
|
|
9454
|
+
} else {
|
|
9455
|
+
ctx.fillRect(x, y, dotSize, dotSize);
|
|
9456
|
+
}
|
|
9457
|
+
if (o.type == 'dots') ctx.fill();
|
|
9458
|
+
x = ((i + 1) % n) * dist;
|
|
9459
|
+
if (x == 0) y += dist;
|
|
9460
|
+
}
|
|
9461
|
+
}
|
|
9462
|
+
|
|
9463
|
+
function makeHatchFill(o, ctx, res) {
|
|
9464
|
+
var h = o.tileSize[1] * res;
|
|
9465
|
+
var w;
|
|
9466
|
+
for (var i=0, x=0; i<o.widths.length; i++) {
|
|
9467
|
+
w = o.widths[i] * res;
|
|
9468
|
+
ctx.fillStyle = o.colors[i];
|
|
9469
|
+
ctx.fillRect(x, 0, x + w, h);
|
|
9470
|
+
x += w;
|
|
9471
|
+
}
|
|
9472
|
+
}
|
|
9473
|
+
|
|
9362
9474
|
// TODO: consider moving this upstream
|
|
9363
9475
|
function getArcsForRendering(obj, ext) {
|
|
9364
9476
|
var dataset = obj.source.dataset;
|
|
@@ -9549,7 +9661,7 @@
|
|
|
9549
9661
|
shp = shapes[i];
|
|
9550
9662
|
if (!shp || filter && !filter(shp)) continue;
|
|
9551
9663
|
if (styler) styler(style, i);
|
|
9552
|
-
if (style.overlay || style.opacity < 1 || style.fillOpacity < 1 || style.strokeOpacity < 1) {
|
|
9664
|
+
if (style.overlay || style.opacity < 1 || style.fillOpacity < 1 || style.strokeOpacity < 1 || style.fillEffect) {
|
|
9553
9665
|
// don't batch shapes with opacity, in case they overlap
|
|
9554
9666
|
drawPaths([shp], startPath, draw, style);
|
|
9555
9667
|
continue;
|
|
@@ -9574,10 +9686,10 @@
|
|
|
9574
9686
|
});
|
|
9575
9687
|
};
|
|
9576
9688
|
|
|
9577
|
-
function drawPaths(shapes,
|
|
9578
|
-
|
|
9689
|
+
function drawPaths(shapes, beginPath, drawShape, style) {
|
|
9690
|
+
beginPath(_ctx, style);
|
|
9579
9691
|
for (var i=0, n=shapes.length; i<n; i++) {
|
|
9580
|
-
|
|
9692
|
+
drawShape(shapes[i], _ctx, style);
|
|
9581
9693
|
}
|
|
9582
9694
|
endPath(_ctx, style);
|
|
9583
9695
|
}
|
|
@@ -9863,7 +9975,10 @@
|
|
|
9863
9975
|
function getShapePencil(arcs, ext) {
|
|
9864
9976
|
var t = getScaledTransform(ext);
|
|
9865
9977
|
var iter = new internal.ShapeIter(arcs);
|
|
9866
|
-
return function(shp, ctx) {
|
|
9978
|
+
return function(shp, ctx, style) {
|
|
9979
|
+
if (style.fillEffect) {
|
|
9980
|
+
ctx.fillStyle = getCanvasFillEffect(ctx, shp, arcs, ext, style);
|
|
9981
|
+
}
|
|
9867
9982
|
for (var i=0, n=shp ? shp.length : 0; i<n; i++) {
|
|
9868
9983
|
iter.init(shp[i]);
|
|
9869
9984
|
// 0.2 trades visible seams for performance
|
|
@@ -9930,8 +10045,12 @@
|
|
|
9930
10045
|
var fo = style.opacity >= 0 ? style.opacity : 1,
|
|
9931
10046
|
so = fo;
|
|
9932
10047
|
if (style.strokeOpacity >= 0) so *= style.strokeOpacity;
|
|
9933
|
-
if (style.
|
|
9934
|
-
|
|
10048
|
+
if (style.fillColor || style.fillPattern || style.fillEffect) {
|
|
10049
|
+
if (style.fillOpacity >= 0) {
|
|
10050
|
+
fo *= style.fillOpacity;
|
|
10051
|
+
} else if (style.fillEffect && style.opacity >= 0 === false) {
|
|
10052
|
+
fo = 0.35; // kludge: default opacity of sphere effect
|
|
10053
|
+
}
|
|
9935
10054
|
ctx.globalAlpha = fo;
|
|
9936
10055
|
ctx.fill();
|
|
9937
10056
|
}
|
|
@@ -9947,82 +10066,6 @@
|
|
|
9947
10066
|
ctx.closePath();
|
|
9948
10067
|
}
|
|
9949
10068
|
|
|
9950
|
-
var hatches = {};
|
|
9951
|
-
|
|
9952
|
-
function getCanvasFillPattern(style) {
|
|
9953
|
-
var fill = hatches[style.fillPattern];
|
|
9954
|
-
if (fill === undefined) {
|
|
9955
|
-
fill = makePatternFill(style);
|
|
9956
|
-
hatches[style.fillPattern] = fill;
|
|
9957
|
-
}
|
|
9958
|
-
return fill || style.fill || '#000'; // use fill if hatches are invalid
|
|
9959
|
-
}
|
|
9960
|
-
|
|
9961
|
-
function makePatternFill(style) {
|
|
9962
|
-
var o = internal.parsePattern(style.fillPattern);
|
|
9963
|
-
if (!o) return null;
|
|
9964
|
-
var canv = document.createElement('canvas');
|
|
9965
|
-
var ctx = canv.getContext('2d');
|
|
9966
|
-
var res = GUI.getPixelRatio();
|
|
9967
|
-
var w = o.tileSize[0] * res;
|
|
9968
|
-
var h = o.tileSize[1] * res;
|
|
9969
|
-
canv.setAttribute('width', w);
|
|
9970
|
-
canv.setAttribute('height', h);
|
|
9971
|
-
if (o.background) {
|
|
9972
|
-
ctx.fillStyle = o.background;
|
|
9973
|
-
ctx.fillRect(0, 0, w, h);
|
|
9974
|
-
}
|
|
9975
|
-
if (o.type == 'dots' || o.type == 'squares') makeDotFill(o, ctx, res);
|
|
9976
|
-
if (o.type == 'dashes') makeDashFill(o, ctx, res);
|
|
9977
|
-
if (o.type == 'hatches') makeHatchFill(o, ctx, res);
|
|
9978
|
-
var pattern = ctx.createPattern(canv, 'repeat');
|
|
9979
|
-
if (o.rotation) {
|
|
9980
|
-
pattern.setTransform(new DOMMatrix('rotate(' + o.rotation + 'deg)'));
|
|
9981
|
-
}
|
|
9982
|
-
return pattern;
|
|
9983
|
-
}
|
|
9984
|
-
|
|
9985
|
-
function makeDashFill(o, ctx, res) {
|
|
9986
|
-
var x = 0;
|
|
9987
|
-
for (var i=0; i<o.colors.length; i++) {
|
|
9988
|
-
ctx.fillStyle = o.colors[i];
|
|
9989
|
-
ctx.fillRect(x, 0, o.width * res, o.dashes[0] * res);
|
|
9990
|
-
x += res * (o.spacing + o.width);
|
|
9991
|
-
}
|
|
9992
|
-
}
|
|
9993
|
-
|
|
9994
|
-
function makeDotFill(o, ctx, res) {
|
|
9995
|
-
var dotSize = o.size * res;
|
|
9996
|
-
var r = dotSize / 2;
|
|
9997
|
-
var n = o.colors.length;
|
|
9998
|
-
var dist = dotSize + o.spacing * res;
|
|
9999
|
-
var dots = n * n;
|
|
10000
|
-
var x = 0, y = 0;
|
|
10001
|
-
for (var i=0; i<dots; i++) {
|
|
10002
|
-
if (o.type == 'dots') ctx.beginPath();
|
|
10003
|
-
ctx.fillStyle = o.colors[(i + Math.floor(i / n)) % n];
|
|
10004
|
-
if (o.type == 'dots') {
|
|
10005
|
-
ctx.arc(x + r, y + r, r, 0, Math.PI * 2);
|
|
10006
|
-
} else {
|
|
10007
|
-
ctx.fillRect(x, y, dotSize, dotSize);
|
|
10008
|
-
}
|
|
10009
|
-
if (o.type == 'dots') ctx.fill();
|
|
10010
|
-
x = ((i + 1) % n) * dist;
|
|
10011
|
-
if (x == 0) y += dist;
|
|
10012
|
-
}
|
|
10013
|
-
}
|
|
10014
|
-
|
|
10015
|
-
function makeHatchFill(o, ctx, res) {
|
|
10016
|
-
var h = o.tileSize[1] * res;
|
|
10017
|
-
var w;
|
|
10018
|
-
for (var i=0, x=0; i<o.widths.length; i++) {
|
|
10019
|
-
w = o.widths[i] * res;
|
|
10020
|
-
ctx.fillStyle = o.colors[i];
|
|
10021
|
-
ctx.fillRect(x, 0, x + w, h);
|
|
10022
|
-
x += w;
|
|
10023
|
-
}
|
|
10024
|
-
}
|
|
10025
|
-
|
|
10026
10069
|
function getSvgFurnitureTransform(ext) {
|
|
10027
10070
|
var scale = ext.getSymbolScale();
|
|
10028
10071
|
var frame = ext.getFrame();
|
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.6.
|
|
3
|
+
var VERSION = "0.6.36";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -5829,11 +5829,11 @@
|
|
|
5829
5829
|
};
|
|
5830
5830
|
|
|
5831
5831
|
// TODO: move this and similar methods out of ArcCollection
|
|
5832
|
-
this.getMultiShapeBounds = function(
|
|
5832
|
+
this.getMultiShapeBounds = function(shp, bounds) {
|
|
5833
5833
|
bounds = bounds || new Bounds();
|
|
5834
|
-
if (
|
|
5835
|
-
for (var i=0, n=
|
|
5836
|
-
this.getSimpleShapeBounds(
|
|
5834
|
+
if (shp) { // handle null shapes
|
|
5835
|
+
for (var i=0, n=shp.length; i<n; i++) {
|
|
5836
|
+
this.getSimpleShapeBounds(shp[i], bounds);
|
|
5837
5837
|
}
|
|
5838
5838
|
}
|
|
5839
5839
|
return bounds;
|
|
@@ -12719,7 +12719,7 @@
|
|
|
12719
12719
|
}
|
|
12720
12720
|
var sliverControl = opts.sliver_control >= 0 ? opts.sliver_control : 0; // 0 is default
|
|
12721
12721
|
var crs = getDatasetCRS(dataset);
|
|
12722
|
-
var threshold = areaArg ?
|
|
12722
|
+
var threshold = areaArg && areaArg != 'auto' ?
|
|
12723
12723
|
convertAreaParam(areaArg, crs) :
|
|
12724
12724
|
getDefaultSliverThreshold(lyr, dataset.arcs);
|
|
12725
12725
|
var filter = sliverControl > 0 ?
|
|
@@ -16653,7 +16653,8 @@
|
|
|
16653
16653
|
overlap_rule: opts.overlap_rule
|
|
16654
16654
|
};
|
|
16655
16655
|
var mosaicIndex = new MosaicIndex(lyr, nodes, mosaicOpts);
|
|
16656
|
-
|
|
16656
|
+
// gap fill doesn't work yet with overlapping shapes
|
|
16657
|
+
var fillGaps = !opts.allow_overlaps && (opts.sliver_control || opts.gap_fill_area);
|
|
16657
16658
|
var cleanupData, filterData;
|
|
16658
16659
|
if (fillGaps) {
|
|
16659
16660
|
var sliverOpts = utils.extend({sliver_control: 1}, opts);
|
|
@@ -16935,6 +16936,7 @@
|
|
|
16935
16936
|
|
|
16936
16937
|
function cleanPolygonLayerGeometry(lyr, dataset, opts) {
|
|
16937
16938
|
// clean polygons by apply the 'dissolve2' function to each feature
|
|
16939
|
+
opts = Object.assign({gap_fill_area: 'auto'}, opts);
|
|
16938
16940
|
var groups = lyr.shapes.map(function(shp, i) {
|
|
16939
16941
|
return [i];
|
|
16940
16942
|
});
|
|
@@ -19130,6 +19132,47 @@
|
|
|
19130
19132
|
return str1;
|
|
19131
19133
|
}
|
|
19132
19134
|
|
|
19135
|
+
function getSphereEffectParams() {
|
|
19136
|
+
return {
|
|
19137
|
+
cx: 0.5,
|
|
19138
|
+
cy: 0.5,
|
|
19139
|
+
r: 0.57,
|
|
19140
|
+
fx: 0.35,
|
|
19141
|
+
fy: 0.35,
|
|
19142
|
+
stops: [
|
|
19143
|
+
{offset: 0.3, opacity: 0},
|
|
19144
|
+
{offset: 0.6, opacity: 0.1},
|
|
19145
|
+
{offset: 0.78, opacity: 0.25},
|
|
19146
|
+
{offset: 0.87, opacity: 0.45},
|
|
19147
|
+
{offset: 0.95, opacity: 1}]
|
|
19148
|
+
};
|
|
19149
|
+
}
|
|
19150
|
+
|
|
19151
|
+
function convertFillEffect(obj, defs) {
|
|
19152
|
+
if (obj['fill-effect'] != 'sphere') return; // only "sphere" is supported
|
|
19153
|
+
var id = 'mapshaper_sphere_effect';
|
|
19154
|
+
var href = `url(#${ id })`;
|
|
19155
|
+
var params = getSphereEffectParams();
|
|
19156
|
+
var stops = params.stops.map(function(stop) {
|
|
19157
|
+
return `<stop offset="${stop.offset}" stop-opacity="${stop.opacity}"/>`;
|
|
19158
|
+
});
|
|
19159
|
+
var svg =
|
|
19160
|
+
`<radialGradient id="${id}" cx="${params.cx}" cy="${params.cy}" r="${params.r}" fx="${params.fx}" fy="${params.fy}">${stops.join('')}</radialGradient>` ;
|
|
19161
|
+
if (!utils.find(defs, function(o) { return o.id == id; })) {
|
|
19162
|
+
defs.push({svg, id, href});
|
|
19163
|
+
}
|
|
19164
|
+
obj.fill = href;
|
|
19165
|
+
if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
|
|
19166
|
+
obj['fill-opacity'] = 0.35;
|
|
19167
|
+
}
|
|
19168
|
+
}
|
|
19169
|
+
|
|
19170
|
+
var SvgEffect = /*#__PURE__*/Object.freeze({
|
|
19171
|
+
__proto__: null,
|
|
19172
|
+
getSphereEffectParams: getSphereEffectParams,
|
|
19173
|
+
convertFillEffect: convertFillEffect
|
|
19174
|
+
});
|
|
19175
|
+
|
|
19133
19176
|
var cache = {};
|
|
19134
19177
|
function fetchFileSync(url) {
|
|
19135
19178
|
if (url in cache) return cache[url];
|
|
@@ -19147,8 +19190,8 @@
|
|
|
19147
19190
|
if (obj.tag == 'path' && obj.properties['fill-pattern']) {
|
|
19148
19191
|
convertFillPattern(obj.properties, defs);
|
|
19149
19192
|
}
|
|
19150
|
-
if (obj.tag == 'path' && obj.properties['fill-effect']
|
|
19151
|
-
|
|
19193
|
+
if (obj.tag == 'path' && obj.properties['fill-effect']) {
|
|
19194
|
+
convertFillEffect(obj.properties, defs);
|
|
19152
19195
|
}
|
|
19153
19196
|
if (obj.tag == 'image') {
|
|
19154
19197
|
if (/\.svg/.test(obj.properties.href || '')) {
|
|
@@ -19160,25 +19203,6 @@
|
|
|
19160
19203
|
}
|
|
19161
19204
|
}
|
|
19162
19205
|
|
|
19163
|
-
function convertSphereEffect(obj, defs) {
|
|
19164
|
-
var id = 'mapshaper_sphere_effect';
|
|
19165
|
-
var href = `url(#${ id })`;
|
|
19166
|
-
var svg =
|
|
19167
|
-
`<radialGradient id="${id}" cx="0.5" cy="0.5" r=".56" fx="0.4" fy="0.35">
|
|
19168
|
-
<stop offset=".35" stop-opacity="0"/>
|
|
19169
|
-
<stop offset=".65" stop-opacity="0.1" />
|
|
19170
|
-
<stop offset=".85" stop-opacity="0.45" />
|
|
19171
|
-
<stop offset=".95" stop-opacity="1" />
|
|
19172
|
-
</radialGradient>` ;
|
|
19173
|
-
if (!utils.find(defs, function(o) { return o.id == id; })) {
|
|
19174
|
-
defs.push({svg, id, href});
|
|
19175
|
-
}
|
|
19176
|
-
obj.fill = href;
|
|
19177
|
-
if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
|
|
19178
|
-
obj['fill-opacity'] = 0.35;
|
|
19179
|
-
}
|
|
19180
|
-
}
|
|
19181
|
-
|
|
19182
19206
|
function convertSvgImage(obj, defs) {
|
|
19183
19207
|
// Same-origin policy prevents embedding images in the web UI
|
|
19184
19208
|
var href = obj.properties.href;
|
|
@@ -23698,7 +23722,10 @@ ${svg}
|
|
|
23698
23722
|
.option('calc', calcOpt)
|
|
23699
23723
|
.option('sum-fields', sumFieldsOpt)
|
|
23700
23724
|
.option('copy-fields', copyFieldsOpt)
|
|
23701
|
-
.option('gap-fill-area',
|
|
23725
|
+
.option('gap-fill-area', {
|
|
23726
|
+
describe: 'threshold for filling gaps, e.g. 1.5km2',
|
|
23727
|
+
type: 'area'
|
|
23728
|
+
})
|
|
23702
23729
|
.option('sliver-control', sliverControlOpt)
|
|
23703
23730
|
.option('allow-overlaps', {
|
|
23704
23731
|
describe: 'allow dissolved polygons to overlap (disables gap fill)',
|
|
@@ -40133,6 +40160,7 @@ ${svg}
|
|
|
40133
40160
|
};
|
|
40134
40161
|
|
|
40135
40162
|
if (opts.calc) {
|
|
40163
|
+
if (!lyr.data) initDataTable(lyr);
|
|
40136
40164
|
records2 = recombineDataRecords(lyr.data.getRecords(), mosaicIndex.getSourceIdsByTileId, mosaicShapes.length, opts);
|
|
40137
40165
|
lyr2.data = new DataTable(records2);
|
|
40138
40166
|
}
|
|
@@ -43164,7 +43192,7 @@ ${svg}
|
|
|
43164
43192
|
function commandAcceptsMultipleTargetDatasets(name) {
|
|
43165
43193
|
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
43166
43194
|
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
43167
|
-
name == 'else' || name == 'endif';
|
|
43195
|
+
name == 'else' || name == 'endif' || name == 'run';
|
|
43168
43196
|
}
|
|
43169
43197
|
|
|
43170
43198
|
function commandAcceptsEmptyTarget(name) {
|
|
@@ -44390,6 +44418,7 @@ ${svg}
|
|
|
44390
44418
|
Topology,
|
|
44391
44419
|
Units,
|
|
44392
44420
|
SvgHatch,
|
|
44421
|
+
SvgEffect,
|
|
44393
44422
|
VertexUtils,
|
|
44394
44423
|
Zip
|
|
44395
44424
|
);
|