mapshaper 0.6.35 → 0.6.37

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  (function () {
2
2
 
3
- var VERSION = "0.6.35";
3
+ var VERSION = "0.6.37";
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(shapeIds, bounds) {
5832
+ this.getMultiShapeBounds = function(shp, bounds) {
5833
5833
  bounds = bounds || new Bounds();
5834
- if (shapeIds) { // handle null shapes
5835
- for (var i=0, n=shapeIds.length; i<n; i++) {
5836
- this.getSimpleShapeBounds(shapeIds[i], bounds);
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;
@@ -19132,6 +19132,47 @@
19132
19132
  return str1;
19133
19133
  }
19134
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
+
19135
19176
  var cache = {};
19136
19177
  function fetchFileSync(url) {
19137
19178
  if (url in cache) return cache[url];
@@ -19149,8 +19190,8 @@
19149
19190
  if (obj.tag == 'path' && obj.properties['fill-pattern']) {
19150
19191
  convertFillPattern(obj.properties, defs);
19151
19192
  }
19152
- if (obj.tag == 'path' && obj.properties['fill-effect'] == 'sphere') {
19153
- convertSphereEffect(obj.properties, defs);
19193
+ if (obj.tag == 'path' && obj.properties['fill-effect']) {
19194
+ convertFillEffect(obj.properties, defs);
19154
19195
  }
19155
19196
  if (obj.tag == 'image') {
19156
19197
  if (/\.svg/.test(obj.properties.href || '')) {
@@ -19162,25 +19203,6 @@
19162
19203
  }
19163
19204
  }
19164
19205
 
19165
- function convertSphereEffect(obj, defs) {
19166
- var id = 'mapshaper_sphere_effect';
19167
- var href = `url(#${ id })`;
19168
- var svg =
19169
- `<radialGradient id="${id}" cx="0.5" cy="0.5" r=".56" fx="0.4" fy="0.35">
19170
- <stop offset=".35" stop-opacity="0"/>
19171
- <stop offset=".65" stop-opacity="0.1" />
19172
- <stop offset=".85" stop-opacity="0.45" />
19173
- <stop offset=".95" stop-opacity="1" />
19174
- </radialGradient>` ;
19175
- if (!utils.find(defs, function(o) { return o.id == id; })) {
19176
- defs.push({svg, id, href});
19177
- }
19178
- obj.fill = href;
19179
- if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
19180
- obj['fill-opacity'] = 0.35;
19181
- }
19182
- }
19183
-
19184
19206
  function convertSvgImage(obj, defs) {
19185
19207
  // Same-origin policy prevents embedding images in the web UI
19186
19208
  var href = obj.properties.href;
@@ -42324,7 +42346,7 @@ ${svg}
42324
42346
  headDx = size.headWidth / 2,
42325
42347
  stemDx = size.stemWidth / 2,
42326
42348
  baseDx = stemDx * (1 - stemTaper),
42327
- head, stem, coords, dx, dy;
42349
+ coords, dx, dy;
42328
42350
 
42329
42351
  if (curvature) {
42330
42352
  // make curved stem
@@ -42337,11 +42359,11 @@ ${svg}
42337
42359
  dy = stemLen * Math.cos(theta / 2);
42338
42360
 
42339
42361
  if (stickArrow) {
42340
- stem = getCurvedStemCoords(-ax, -ay, dx, dy);
42362
+ coords = getCurvedStemCoords(-ax, -ay, dx, dy);
42341
42363
  } else {
42342
42364
  var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy);
42343
42365
  var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy);
42344
- stem = leftStem.concat(rightStem.reverse());
42366
+ coords = leftStem.concat(rightStem.reverse());
42345
42367
  }
42346
42368
 
42347
42369
  } else {
@@ -42349,23 +42371,26 @@ ${svg}
42349
42371
  dx = 0;
42350
42372
  dy = stemLen;
42351
42373
  if (stickArrow) {
42352
- stem = [[0, 0], [0, stemLen]];
42374
+ coords = [[0, 0], [0, stemLen]];
42353
42375
  } else {
42354
- stem = [[-baseDx, 0], [baseDx, 0]];
42376
+ coords = [[-baseDx, 0], [baseDx, 0]];
42355
42377
  }
42356
42378
  }
42357
42379
 
42358
42380
  if (stickArrow) {
42359
42381
  // make stick arrow
42360
- head = [[-headDx + dx, stemLen - headLen], [dx, stemLen], [headDx + dx, stemLen - headLen]];
42361
- coords = [stem, head]; // MultiLineString coords
42382
+ coords = [coords]; // MultiLineString coords
42383
+ if (headLen > 0) {
42384
+ coords.push([[-headDx + dx, stemLen - headLen], [dx, stemLen], [headDx + dx, stemLen - headLen]]);
42385
+ }
42362
42386
  } else {
42363
42387
  // make filled arrow
42364
42388
  // coordinates go counter clockwise, starting from the leftmost head coordinate
42365
- head = [[stemDx + dx, dy], [headDx + dx, dy],
42366
- [dx, headLen + dy], [-headDx + dx, dy], [-stemDx + dx, dy]];
42367
- coords = stem.concat(head);
42368
- coords.push(stem[0].concat()); // closed path
42389
+ coords.push([stemDx + dx, dy]);
42390
+ if (headLen > 0) {
42391
+ coords.push([headDx + dx, dy], [dx, headLen + dy], [-headDx + dx, dy]);
42392
+ }
42393
+ coords.push([-stemDx + dx, dy], coords[0].concat()); // close path
42369
42394
  coords = [coords]; // Polygon coords
42370
42395
  }
42371
42396
 
@@ -42394,7 +42419,6 @@ ${svg}
42394
42419
  var totalLen = Math.max(d.radius || d.length || d.r || 0, 0),
42395
42420
  scale = 1,
42396
42421
  o = initArrowSize(d); // calc several parameters
42397
-
42398
42422
  if (totalLen >= 0) {
42399
42423
  scale = calcScale(totalLen, o.headLen, d);
42400
42424
  o.stemWidth *= scale;
@@ -42403,7 +42427,7 @@ ${svg}
42403
42427
  o.stemLen = stickArrow ? totalLen : totalLen - o.headLen;
42404
42428
  }
42405
42429
 
42406
- if (o.headWidth < o.stemWidth) {
42430
+ if (o.headWidth < o.stemWidth && o.headWidth > 0) {
42407
42431
  stop('Arrow head must be at least as wide as the stem.');
42408
42432
  }
42409
42433
  return o;
@@ -42432,14 +42456,18 @@ ${svg}
42432
42456
  headWidth: d['head-width'],
42433
42457
  headLen: d['head-length']
42434
42458
  };
42435
- if (!o.headWidth) {
42436
- if (o.headLen) {
42459
+ if (o.headWidth === 0) {
42460
+ o.headLen = 0;
42461
+ } else if (o.headWidth > 0 === false) {
42462
+ if (o.headLen > 0) {
42437
42463
  o.headWidth = o.headLen / sizeRatio;
42464
+ } else if (o.headLen === 0) {
42465
+ o.headWidth = 0;
42438
42466
  } else {
42439
42467
  o.headWidth = o.stemWidth * 3; // assumes stemWidth has been set
42440
42468
  }
42441
42469
  }
42442
- if (!o.headLen) {
42470
+ if (o.headLen >= 0 === false) {
42443
42471
  o.headLen = o.headWidth * sizeRatio;
42444
42472
  }
42445
42473
  return o;
@@ -43170,7 +43198,7 @@ ${svg}
43170
43198
  function commandAcceptsMultipleTargetDatasets(name) {
43171
43199
  return name == 'rotate' || name == 'info' || name == 'proj' ||
43172
43200
  name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
43173
- name == 'else' || name == 'endif';
43201
+ name == 'else' || name == 'endif' || name == 'run';
43174
43202
  }
43175
43203
 
43176
43204
  function commandAcceptsEmptyTarget(name) {
@@ -44396,6 +44424,7 @@ ${svg}
44396
44424
  Topology,
44397
44425
  Units,
44398
44426
  SvgHatch,
44427
+ SvgEffect,
44399
44428
  VertexUtils,
44400
44429
  Zip
44401
44430
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.6.35",
3
+ "version": "0.6.37",
4
4
  "description": "A tool for editing vector datasets for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -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, begin, draw, style) {
9578
- begin(_ctx, style);
9689
+ function drawPaths(shapes, beginPath, drawShape, style) {
9690
+ beginPath(_ctx, style);
9579
9691
  for (var i=0, n=shapes.length; i<n; i++) {
9580
- draw(shapes[i], _ctx);
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.fillOpacity >= 0) fo *= style.fillOpacity;
9934
- if (style.fillColor || style.fillPattern) {
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.35";
3
+ var VERSION = "0.6.37";
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(shapeIds, bounds) {
5832
+ this.getMultiShapeBounds = function(shp, bounds) {
5833
5833
  bounds = bounds || new Bounds();
5834
- if (shapeIds) { // handle null shapes
5835
- for (var i=0, n=shapeIds.length; i<n; i++) {
5836
- this.getSimpleShapeBounds(shapeIds[i], bounds);
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;
@@ -19132,6 +19132,47 @@
19132
19132
  return str1;
19133
19133
  }
19134
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
+
19135
19176
  var cache = {};
19136
19177
  function fetchFileSync(url) {
19137
19178
  if (url in cache) return cache[url];
@@ -19149,8 +19190,8 @@
19149
19190
  if (obj.tag == 'path' && obj.properties['fill-pattern']) {
19150
19191
  convertFillPattern(obj.properties, defs);
19151
19192
  }
19152
- if (obj.tag == 'path' && obj.properties['fill-effect'] == 'sphere') {
19153
- convertSphereEffect(obj.properties, defs);
19193
+ if (obj.tag == 'path' && obj.properties['fill-effect']) {
19194
+ convertFillEffect(obj.properties, defs);
19154
19195
  }
19155
19196
  if (obj.tag == 'image') {
19156
19197
  if (/\.svg/.test(obj.properties.href || '')) {
@@ -19162,25 +19203,6 @@
19162
19203
  }
19163
19204
  }
19164
19205
 
19165
- function convertSphereEffect(obj, defs) {
19166
- var id = 'mapshaper_sphere_effect';
19167
- var href = `url(#${ id })`;
19168
- var svg =
19169
- `<radialGradient id="${id}" cx="0.5" cy="0.5" r=".56" fx="0.4" fy="0.35">
19170
- <stop offset=".35" stop-opacity="0"/>
19171
- <stop offset=".65" stop-opacity="0.1" />
19172
- <stop offset=".85" stop-opacity="0.45" />
19173
- <stop offset=".95" stop-opacity="1" />
19174
- </radialGradient>` ;
19175
- if (!utils.find(defs, function(o) { return o.id == id; })) {
19176
- defs.push({svg, id, href});
19177
- }
19178
- obj.fill = href;
19179
- if ('opacity' in obj === false && 'fill-opacity' in obj === false) {
19180
- obj['fill-opacity'] = 0.35;
19181
- }
19182
- }
19183
-
19184
19206
  function convertSvgImage(obj, defs) {
19185
19207
  // Same-origin policy prevents embedding images in the web UI
19186
19208
  var href = obj.properties.href;
@@ -42324,7 +42346,7 @@ ${svg}
42324
42346
  headDx = size.headWidth / 2,
42325
42347
  stemDx = size.stemWidth / 2,
42326
42348
  baseDx = stemDx * (1 - stemTaper),
42327
- head, stem, coords, dx, dy;
42349
+ coords, dx, dy;
42328
42350
 
42329
42351
  if (curvature) {
42330
42352
  // make curved stem
@@ -42337,11 +42359,11 @@ ${svg}
42337
42359
  dy = stemLen * Math.cos(theta / 2);
42338
42360
 
42339
42361
  if (stickArrow) {
42340
- stem = getCurvedStemCoords(-ax, -ay, dx, dy);
42362
+ coords = getCurvedStemCoords(-ax, -ay, dx, dy);
42341
42363
  } else {
42342
42364
  var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy);
42343
42365
  var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy);
42344
- stem = leftStem.concat(rightStem.reverse());
42366
+ coords = leftStem.concat(rightStem.reverse());
42345
42367
  }
42346
42368
 
42347
42369
  } else {
@@ -42349,23 +42371,26 @@ ${svg}
42349
42371
  dx = 0;
42350
42372
  dy = stemLen;
42351
42373
  if (stickArrow) {
42352
- stem = [[0, 0], [0, stemLen]];
42374
+ coords = [[0, 0], [0, stemLen]];
42353
42375
  } else {
42354
- stem = [[-baseDx, 0], [baseDx, 0]];
42376
+ coords = [[-baseDx, 0], [baseDx, 0]];
42355
42377
  }
42356
42378
  }
42357
42379
 
42358
42380
  if (stickArrow) {
42359
42381
  // make stick arrow
42360
- head = [[-headDx + dx, stemLen - headLen], [dx, stemLen], [headDx + dx, stemLen - headLen]];
42361
- coords = [stem, head]; // MultiLineString coords
42382
+ coords = [coords]; // MultiLineString coords
42383
+ if (headLen > 0) {
42384
+ coords.push([[-headDx + dx, stemLen - headLen], [dx, stemLen], [headDx + dx, stemLen - headLen]]);
42385
+ }
42362
42386
  } else {
42363
42387
  // make filled arrow
42364
42388
  // coordinates go counter clockwise, starting from the leftmost head coordinate
42365
- head = [[stemDx + dx, dy], [headDx + dx, dy],
42366
- [dx, headLen + dy], [-headDx + dx, dy], [-stemDx + dx, dy]];
42367
- coords = stem.concat(head);
42368
- coords.push(stem[0].concat()); // closed path
42389
+ coords.push([stemDx + dx, dy]);
42390
+ if (headLen > 0) {
42391
+ coords.push([headDx + dx, dy], [dx, headLen + dy], [-headDx + dx, dy]);
42392
+ }
42393
+ coords.push([-stemDx + dx, dy], coords[0].concat()); // close path
42369
42394
  coords = [coords]; // Polygon coords
42370
42395
  }
42371
42396
 
@@ -42394,7 +42419,6 @@ ${svg}
42394
42419
  var totalLen = Math.max(d.radius || d.length || d.r || 0, 0),
42395
42420
  scale = 1,
42396
42421
  o = initArrowSize(d); // calc several parameters
42397
-
42398
42422
  if (totalLen >= 0) {
42399
42423
  scale = calcScale(totalLen, o.headLen, d);
42400
42424
  o.stemWidth *= scale;
@@ -42403,7 +42427,7 @@ ${svg}
42403
42427
  o.stemLen = stickArrow ? totalLen : totalLen - o.headLen;
42404
42428
  }
42405
42429
 
42406
- if (o.headWidth < o.stemWidth) {
42430
+ if (o.headWidth < o.stemWidth && o.headWidth > 0) {
42407
42431
  stop('Arrow head must be at least as wide as the stem.');
42408
42432
  }
42409
42433
  return o;
@@ -42432,14 +42456,18 @@ ${svg}
42432
42456
  headWidth: d['head-width'],
42433
42457
  headLen: d['head-length']
42434
42458
  };
42435
- if (!o.headWidth) {
42436
- if (o.headLen) {
42459
+ if (o.headWidth === 0) {
42460
+ o.headLen = 0;
42461
+ } else if (o.headWidth > 0 === false) {
42462
+ if (o.headLen > 0) {
42437
42463
  o.headWidth = o.headLen / sizeRatio;
42464
+ } else if (o.headLen === 0) {
42465
+ o.headWidth = 0;
42438
42466
  } else {
42439
42467
  o.headWidth = o.stemWidth * 3; // assumes stemWidth has been set
42440
42468
  }
42441
42469
  }
42442
- if (!o.headLen) {
42470
+ if (o.headLen >= 0 === false) {
42443
42471
  o.headLen = o.headWidth * sizeRatio;
42444
42472
  }
42445
42473
  return o;
@@ -43170,7 +43198,7 @@ ${svg}
43170
43198
  function commandAcceptsMultipleTargetDatasets(name) {
43171
43199
  return name == 'rotate' || name == 'info' || name == 'proj' ||
43172
43200
  name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
43173
- name == 'else' || name == 'endif';
43201
+ name == 'else' || name == 'endif' || name == 'run';
43174
43202
  }
43175
43203
 
43176
43204
  function commandAcceptsEmptyTarget(name) {
@@ -44396,6 +44424,7 @@ ${svg}
44396
44424
  Topology,
44397
44425
  Units,
44398
44426
  SvgHatch,
44427
+ SvgEffect,
44399
44428
  VertexUtils,
44400
44429
  Zip
44401
44430
  );