mapshaper 0.5.111 → 0.5.112

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.5.111";
3
+ var VERSION = "0.5.112";
4
4
 
5
5
 
6
6
  var utils = /*#__PURE__*/Object.freeze({
@@ -14078,9 +14078,27 @@
14078
14078
  polyline: utils.arrayToIndex(commonProperties.concat('stroke-linecap', 'stroke-linejoin')),
14079
14079
  point: utils.arrayToIndex(commonProperties.concat('fill', 'r')),
14080
14080
  label: utils.arrayToIndex(commonProperties.concat(
14081
- 'fill,r,font-family,font-size,text-anchor,font-weight,font-style,letter-spacing,dominant-baseline'.split(',')))
14081
+ 'fill,font-family,font-size,text-anchor,font-weight,font-style,letter-spacing,dominant-baseline'.split(',')))
14082
14082
  };
14083
14083
 
14084
+ // symType: point, polygon, polyline, label
14085
+ function applyStyleAttributes(svgObj, symType, rec, filter) {
14086
+ var fields = findPropertiesBySymbolGeom(Object.keys(rec || {}), symType);
14087
+ for (var i=0, n=fields.length; i<n; i++) {
14088
+ if (filter && !filter(fields[i])) continue;
14089
+ setAttribute(svgObj, fields[i], rec[fields[i]]);
14090
+ }
14091
+ }
14092
+
14093
+ function setAttribute(obj, k, v) {
14094
+ if (!obj.properties) obj.properties = {};
14095
+ obj.properties[k] = v;
14096
+ if (k == 'stroke-dasharray' && v) {
14097
+ // kludge for cleaner dashes... make butt the default?
14098
+ obj.properties['stroke-linecap'] = 'butt';
14099
+ }
14100
+ }
14101
+
14084
14102
  function isSupportedSvgStyleProperty(name) {
14085
14103
  return name in stylePropertyTypes;
14086
14104
  }
@@ -14236,6 +14254,7 @@
14236
14254
 
14237
14255
  var SvgProperties = /*#__PURE__*/Object.freeze({
14238
14256
  __proto__: null,
14257
+ applyStyleAttributes: applyStyleAttributes,
14239
14258
  isSupportedSvgStyleProperty: isSupportedSvgStyleProperty,
14240
14259
  findPropertiesBySymbolGeom: findPropertiesBySymbolGeom,
14241
14260
  getSymbolDataAccessor: getSymbolDataAccessor,
@@ -14249,7 +14268,69 @@
14249
14268
  isSvgColor: isSvgColor
14250
14269
  });
14251
14270
 
14252
- var symbolRenderers = {};
14271
+ function toLabelString(val) {
14272
+ if (val || val === 0 || val === false) return String(val);
14273
+ return '';
14274
+ }
14275
+
14276
+ // Kludge for applying fill and other styles to a <text> element
14277
+ // (for rendering labels in the GUI with the dot in Canvas, not SVG)
14278
+ function renderStyledLabel(rec) {
14279
+ var o = renderLabel(rec);
14280
+ applyStyleAttributes(o, 'label', rec);
14281
+ return o;
14282
+ }
14283
+
14284
+ function renderLabel(rec) {
14285
+ var line = toLabelString(rec['label-text']);
14286
+ var morelines, obj;
14287
+ // Accepting \n (two chars) as an alternative to the newline character
14288
+ // (sometimes, '\n' is not converted to newline, e.g. in a Makefile)
14289
+ // Also accepting <br>
14290
+ var newline = /\n|\\n|<br>/i;
14291
+ var dx = rec.dx || 0;
14292
+ var dy = rec.dy || 0;
14293
+ var properties = {
14294
+ // using x, y instead of dx, dy for shift, because Illustrator doesn't apply
14295
+ // dx value when importing text with text-anchor=end
14296
+ y: dy,
14297
+ x: dx
14298
+ };
14299
+ if (newline.test(line)) {
14300
+ morelines = line.split(newline);
14301
+ line = morelines.shift();
14302
+ }
14303
+ obj = {
14304
+ tag: 'text',
14305
+ value: line,
14306
+ properties: properties
14307
+ };
14308
+ if (morelines) {
14309
+ // multiline label
14310
+ obj.children = [];
14311
+ morelines.forEach(function(line) {
14312
+ var tspan = {
14313
+ tag: 'tspan',
14314
+ value: line,
14315
+ properties: {
14316
+ x: dx,
14317
+ dy: rec['line-height'] || '1.1em'
14318
+ }
14319
+ };
14320
+ obj.children.push(tspan);
14321
+ });
14322
+ }
14323
+ return obj;
14324
+ }
14325
+
14326
+ var SvgLabels = /*#__PURE__*/Object.freeze({
14327
+ __proto__: null,
14328
+ renderStyledLabel: renderStyledLabel,
14329
+ renderLabel: renderLabel
14330
+ });
14331
+
14332
+ // convert data records (properties like svg-symbol, label-text, fill, r) to svg symbols
14333
+
14253
14334
 
14254
14335
  function getTransform(xy, scale) {
14255
14336
  var str = 'translate(' + roundToTenths(xy[0]) + ' ' + roundToTenths(xy[1]) + ')';
@@ -14259,10 +14340,149 @@
14259
14340
  return str;
14260
14341
  }
14261
14342
 
14262
- var SvgCommon = /*#__PURE__*/Object.freeze({
14343
+ var symbolRenderers = {
14344
+ line: line,
14345
+ polygon: polygon,
14346
+ polyline: polyline,
14347
+ circle: circle,
14348
+ square: square,
14349
+ image: image,
14350
+ group: group,
14351
+ label: label
14352
+ };
14353
+
14354
+ // render label and/or point symbol
14355
+ function renderPoint(rec) {
14356
+ var children = [];
14357
+ // var halfSize = rec.r || 0; // radius or half of symbol size
14358
+ if (featureHasSvgSymbol(rec)) {
14359
+ children.push(renderSymbol(rec));
14360
+ }
14361
+ if (featureHasLabel(rec)) {
14362
+ children.push(renderStyledLabel(rec));
14363
+ }
14364
+ var o = children.length > 1 ? {tag: 'g', children: children} : children[0];
14365
+ if (!o) return null;
14366
+ o.properties = o.properties || {};
14367
+ return o;
14368
+ }
14369
+
14370
+ function renderSymbol(d) {
14371
+ if (d['svg-symbol']) {
14372
+ return renderComplexSymbol(d['svg-symbol']);
14373
+ }
14374
+ if (d.r > 0) {
14375
+ return circle(d);
14376
+ }
14377
+ return empty();
14378
+ }
14379
+
14380
+ function renderComplexSymbol(sym) {
14381
+ if (utils.isString(sym)) {
14382
+ sym = JSON.parse(sym);
14383
+ }
14384
+ var renderer = symbolRenderers[sym.type];
14385
+ if (!renderer) {
14386
+ message(sym.type ? 'Unknown symbol type: ' + sym.type : 'Symbol is missing a type property');
14387
+ return empty();
14388
+ }
14389
+ return renderer(sym, 0, 0);
14390
+ }
14391
+
14392
+ function empty() {
14393
+ return {tag: 'g', properties: {}, children: []};
14394
+ }
14395
+
14396
+ function circle(d, x, y) {
14397
+ var o = {
14398
+ tag: 'circle',
14399
+ properties: {
14400
+ cx: x || 0,
14401
+ cy: y || 0
14402
+ }
14403
+ };
14404
+ applyStyleAttributes(o, 'point', d);
14405
+ return o;
14406
+ }
14407
+
14408
+ function label(d, x, y) {
14409
+ return renderStyledLabel(d);
14410
+ }
14411
+
14412
+ function image(d, x, y) {
14413
+ var w = d.width || 20,
14414
+ h = d.height || 20;
14415
+ var o = {
14416
+ tag: 'image',
14417
+ properties: {
14418
+ width: w,
14419
+ height: h,
14420
+ x: x - w / 2,
14421
+ y: y - h / 2,
14422
+ href: d.href || ''
14423
+ }
14424
+ };
14425
+ return o;
14426
+ }
14427
+
14428
+ function square(d, x, y) {
14429
+ var r = d.r || 0;
14430
+ var o = {
14431
+ tag: 'rect',
14432
+ properties: {
14433
+ x: x - r,
14434
+ y: y - r,
14435
+ width: r * 2,
14436
+ height: r * 2
14437
+ }
14438
+ };
14439
+ applyStyleAttributes(o, 'point', d);
14440
+ return o;
14441
+ }
14442
+
14443
+ function line(d, x, y) {
14444
+ var coords, o;
14445
+ coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
14446
+ o = importLineString(coords);
14447
+ applyStyleAttributes(o, 'polyline', d);
14448
+ return o;
14449
+ }
14450
+
14451
+ function polyline(d, x, y) {
14452
+ var coords = d.coordinates || [];
14453
+ var o = importMultiLineString(coords);
14454
+ applyStyleAttributes(o, 'polyline', d);
14455
+ return o;
14456
+ }
14457
+
14458
+ function polygon(d, x, y) {
14459
+ var coords = d.coordinates || [];
14460
+ var o = importPolygon(coords);
14461
+ applyStyleAttributes(o, 'polygon', d);
14462
+ return o;
14463
+ }
14464
+
14465
+ function group(d, x, y) {
14466
+ var parts = (d.parts || []).reduce(function(memo, o) {
14467
+ var sym = renderSymbol(o, x, y);
14468
+ if (d.chained) {
14469
+ x += (o.dx || 0);
14470
+ y += (o.dy || 0);
14471
+ }
14472
+ return memo.concat(sym);
14473
+ }, []);
14474
+ if (parts.length == 1) return parts[0];
14475
+ return {
14476
+ tag: 'g',
14477
+ children: parts
14478
+ };
14479
+ }
14480
+
14481
+ var SvgSymbols = /*#__PURE__*/Object.freeze({
14263
14482
  __proto__: null,
14483
+ getTransform: getTransform,
14264
14484
  symbolRenderers: symbolRenderers,
14265
- getTransform: getTransform
14485
+ renderPoint: renderPoint
14266
14486
  });
14267
14487
 
14268
14488
  function importGeoJSONFeatures(features, opts) {
@@ -14270,16 +14490,22 @@
14270
14490
  return features.map(function(obj, i) {
14271
14491
  var geom = obj.type == 'Feature' ? obj.geometry : obj; // could be null
14272
14492
  var geomType = geom && geom.type;
14493
+ var msType = GeoJSON.translateGeoJSONType(geomType);
14494
+ var d = obj.properties || {};
14273
14495
  var svgObj = null;
14274
14496
  if (geomType && geom.coordinates) {
14275
- svgObj = geojsonImporters[geomType](geom.coordinates, obj.properties, opts);
14497
+ svgObj = geojsonImporters[geomType](geom.coordinates, d);
14276
14498
  }
14277
14499
  if (!svgObj) {
14278
14500
  return {tag: 'g'}; // empty element
14279
- }
14280
- // TODO: fix error caused by null svgObj (caused by e.g. MultiPolygon with [] coordinates)
14281
- if (obj.properties) {
14282
- applyStyleAttributes(svgObj, geomType, obj.properties);
14501
+ } else if (msType == 'polyline' || msType == 'polygon') {
14502
+ applyStyleAttributes(svgObj, msType, d);
14503
+ } else if (msType == 'point' && isSimpleCircle(d)) {
14504
+ // kludge -- maintains bw compatibility/passes tests -- style attributes
14505
+ // are applied to the <g> container, 'r' property is applied to circle
14506
+ applyStyleAttributes(svgObj, msType, d, simpleCircleFilter);
14507
+ } else {
14508
+ // other point symbols: attributes are complicated, added downstream
14283
14509
  }
14284
14510
  if ('id' in obj) {
14285
14511
  if (!svgObj.properties) {
@@ -14291,34 +14517,37 @@
14291
14517
  });
14292
14518
  }
14293
14519
 
14294
- function applyStyleAttributes(svgObj, geomType, rec) {
14295
- var symbolType = GeoJSON.translateGeoJSONType(geomType);
14296
- if (symbolType == 'point' && ('label-text' in rec)) {
14297
- symbolType = 'label';
14298
- }
14299
- var fields = findPropertiesBySymbolGeom(Object.keys(rec), symbolType);
14300
- for (var i=0, n=fields.length; i<n; i++) {
14301
- setAttribute(svgObj, fields[i], rec[fields[i]]);
14520
+ function importPoint(coords, rec) {
14521
+ rec = rec || {};
14522
+ if (isSimpleCircle(rec)) {
14523
+ return {
14524
+ tag: 'circle',
14525
+ properties: {
14526
+ cx: coords[0],
14527
+ cy: coords[1],
14528
+ r: rec.r
14529
+ }
14530
+ };
14302
14531
  }
14532
+ var o = renderPoint(rec, coords);
14533
+ if (o) o.properties.transform = getTransform(coords);
14534
+ return o;
14303
14535
  }
14304
14536
 
14305
- function setAttribute(obj, k, v) {
14306
- if (k == 'r') {
14307
- // assigned by importPoint()
14308
- } else {
14309
- if (!obj.properties) obj.properties = {};
14310
- obj.properties[k] = v;
14311
- if (k == 'stroke-dasharray' && v) {
14312
- // kludge for cleaner dashes... make butt the default?
14313
- obj.properties['stroke-linecap'] = 'butt';
14314
- }
14315
- }
14537
+ function simpleCircleFilter(k) {
14538
+ return k != 'r';
14539
+ }
14540
+
14541
+ // just a dot, no label or icon
14542
+ function isSimpleCircle(rec) {
14543
+ return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text']);
14316
14544
  }
14317
14545
 
14318
- function importMultiPoint(coords, rec, layerOpts) {
14546
+ function importMultiPoint(coords, rec) {
14319
14547
  var children = [], p;
14320
14548
  for (var i=0; i<coords.length; i++) {
14321
- p = importPoint(coords[i], rec, layerOpts);
14549
+ p = importPoint(coords[i], rec);
14550
+ if (!p) continue;
14322
14551
  if (p.tag == 'g' && p.children) {
14323
14552
  children = children.concat(p.children);
14324
14553
  } else {
@@ -14348,7 +14577,6 @@
14348
14577
  };
14349
14578
  }
14350
14579
 
14351
-
14352
14580
  function importMultiLineString(coords) {
14353
14581
  var d = coords.map(stringifyLineStringCoords).join(' ');
14354
14582
  return {
@@ -14357,104 +14585,6 @@
14357
14585
  };
14358
14586
  }
14359
14587
 
14360
- // Kludge for applying fill and other styles to a <text> element
14361
- // (for rendering labels in the GUI with the dot in Canvas, not SVG)
14362
- function importStyledLabel(rec, p) {
14363
- var o = importLabel(rec, p);
14364
- applyStyleAttributes(o, 'Point', rec);
14365
- return o;
14366
- }
14367
-
14368
- function toLabelString(val) {
14369
- if (val || val === 0 || val === false) return String(val);
14370
- return '';
14371
- }
14372
-
14373
- function importLabel(rec, p) {
14374
- var line = toLabelString(rec['label-text']);
14375
- var morelines, obj;
14376
- // Accepting \n (two chars) as an alternative to the newline character
14377
- // (sometimes, '\n' is not converted to newline, e.g. in a Makefile)
14378
- // Also accepting <br>
14379
- var newline = /\n|\\n|<br>/i;
14380
- var dx = rec.dx || 0;
14381
- var dy = rec.dy || 0;
14382
- var properties = {
14383
- // using x, y instead of dx, dy for shift, because Illustrator doesn't apply
14384
- // dx value when importing text with text-anchor=end
14385
- y: dy,
14386
- x: dx
14387
- };
14388
- if (p) {
14389
- properties.transform = getTransform(p);
14390
- }
14391
- if (newline.test(line)) {
14392
- morelines = line.split(newline);
14393
- line = morelines.shift();
14394
- }
14395
- obj = {
14396
- tag: 'text',
14397
- value: line,
14398
- properties: properties
14399
- };
14400
- if (morelines) {
14401
- // multiline label
14402
- obj.children = [];
14403
- morelines.forEach(function(line) {
14404
- var tspan = {
14405
- tag: 'tspan',
14406
- value: line,
14407
- properties: {
14408
- x: dx,
14409
- dy: rec['line-height'] || '1.1em'
14410
- }
14411
- };
14412
- obj.children.push(tspan);
14413
- });
14414
- }
14415
- return obj;
14416
- }
14417
-
14418
- function getEmptySymbol() {
14419
- return {tag: 'g', properties: {}, children: []};
14420
- }
14421
-
14422
-
14423
- function renderSymbol(d, x, y) {
14424
- var renderer = symbolRenderers[d.type];
14425
- if (!renderer) {
14426
- stop(d.type ? 'Unknown symbol type: ' + d.type : 'Symbol is missing a type property');
14427
- }
14428
- return renderer(d, x || 0, y || 0);
14429
- }
14430
-
14431
- // d: svg-symbol object from feature data object
14432
- function importSymbol(d, xy) {
14433
- var renderer;
14434
- if (!d) {
14435
- return getEmptySymbol();
14436
- }
14437
- if (utils.isString(d)) {
14438
- d = JSON.parse(d);
14439
- }
14440
- return {
14441
- tag: 'g',
14442
- properties: {
14443
- 'class': 'mapshaper-svg-symbol',
14444
- transform: xy ? getTransform(xy) : null
14445
- },
14446
- children: renderSymbol(d)
14447
- };
14448
- }
14449
-
14450
- function importPoint(coords, rec, layerOpts) {
14451
- rec = rec || {};
14452
- if ('svg-symbol' in rec) {
14453
- return importSymbol(rec['svg-symbol'], coords);
14454
- }
14455
- return importStandardPoint(coords, rec, layerOpts || {});
14456
- }
14457
-
14458
14588
  function importPolygon(coords) {
14459
14589
  var d, o;
14460
14590
  for (var i=0; i<coords.length; i++) {
@@ -14468,49 +14598,12 @@
14468
14598
  return o;
14469
14599
  }
14470
14600
 
14471
- function importStandardPoint(coords, rec, layerOpts) {
14472
- var isLabel = 'label-text' in rec;
14473
- var symbolType = layerOpts.point_symbol || '';
14474
- var children = [];
14475
- var halfSize = rec.r || 0; // radius or half of symbol size
14476
- var p;
14477
- // if not a label, create a symbol even without a size
14478
- // (circle radius can be set via CSS)
14479
- if (halfSize > 0 || !isLabel) {
14480
- if (symbolType == 'square') {
14481
- p = {
14482
- tag: 'rect',
14483
- properties: {
14484
- x: coords[0] - halfSize,
14485
- y: coords[1] - halfSize,
14486
- width: halfSize * 2,
14487
- height: halfSize * 2
14488
- }};
14489
- } else { // default is circle
14490
- p = {
14491
- tag: 'circle',
14492
- properties: {
14493
- cx: coords[0],
14494
- cy: coords[1]
14495
- }};
14496
- if (halfSize > 0) {
14497
- p.properties.r = halfSize;
14498
- }
14499
- }
14500
- children.push(p);
14501
- }
14502
- if (isLabel) {
14503
- children.push(importLabel(rec, coords));
14504
- }
14505
- return children.length > 1 ? {tag: 'g', children: children} : children[0];
14506
- }
14507
-
14508
14601
  var geojsonImporters = {
14509
14602
  Point: importPoint,
14510
14603
  Polygon: importPolygon,
14511
14604
  LineString: importLineString,
14512
- MultiPoint: function(coords, rec, opts) {
14513
- return importMultiPoint(coords, rec, opts);
14605
+ MultiPoint: function(coords, rec) {
14606
+ return importMultiPoint(coords, rec);
14514
14607
  },
14515
14608
  MultiLineString: function(coords) {
14516
14609
  return importMultiPath(coords, importLineString);
@@ -14523,14 +14616,9 @@
14523
14616
  var GeojsonToSvg = /*#__PURE__*/Object.freeze({
14524
14617
  __proto__: null,
14525
14618
  importGeoJSONFeatures: importGeoJSONFeatures,
14526
- applyStyleAttributes: applyStyleAttributes,
14619
+ importPoint: importPoint,
14527
14620
  importLineString: importLineString,
14528
14621
  importMultiLineString: importMultiLineString,
14529
- importStyledLabel: importStyledLabel,
14530
- importLabel: importLabel,
14531
- renderSymbol: renderSymbol,
14532
- importSymbol: importSymbol,
14533
- importPoint: importPoint,
14534
14622
  importPolygon: importPolygon
14535
14623
  });
14536
14624
 
@@ -15245,6 +15333,15 @@ ${svg}
15245
15333
  return layerObj;
15246
15334
  }
15247
15335
 
15336
+ function featureHasSvgSymbol(d) {
15337
+ return !!(d && (d['svg-symbol'] || d.r));
15338
+ }
15339
+
15340
+ function featureHasLabel(d) {
15341
+ var text = d && d['label-text'];
15342
+ return text || text === 0; // accept numerical 0 as label text
15343
+ }
15344
+
15248
15345
  function layerHasSvgSymbols(lyr) {
15249
15346
  return lyr.geometry_type == 'point' && lyr.data && lyr.data.fieldExists('svg-symbol');
15250
15347
  }
@@ -15264,6 +15361,8 @@ ${svg}
15264
15361
  validateSvgDataFields: validateSvgDataFields,
15265
15362
  exportDataAttributesForSVG: exportDataAttributesForSVG,
15266
15363
  getEmptyLayerForSVG: getEmptyLayerForSVG,
15364
+ featureHasSvgSymbol: featureHasSvgSymbol,
15365
+ featureHasLabel: featureHasLabel,
15267
15366
  layerHasSvgSymbols: layerHasSvgSymbols,
15268
15367
  layerHasLabels: layerHasLabels
15269
15368
  });
@@ -37280,72 +37379,6 @@ ${svg}
37280
37379
  }
37281
37380
  };
37282
37381
 
37283
- symbolRenderers.circle = function(d, x, y) {
37284
- var o = importPoint([x, y], d, {});
37285
- applyStyleAttributes(o, 'Point', d);
37286
- return [o];
37287
- };
37288
-
37289
- symbolRenderers.label = function(d, x, y) {
37290
- var o = importStyledLabel(d, [x, y]);
37291
- return [o];
37292
- };
37293
-
37294
- symbolRenderers.image = function(d, x, y) {
37295
- var w = d.width || 20,
37296
- h = d.height || 20;
37297
- var o = {
37298
- tag: 'image',
37299
- properties: {
37300
- width: w,
37301
- height: h,
37302
- x: x - w / 2,
37303
- y: y - h / 2,
37304
- href: d.href || ''
37305
- }
37306
- };
37307
- return [o];
37308
- };
37309
-
37310
- symbolRenderers.square = function(d, x, y) {
37311
- var o = importPoint([x, y], d, {point_symbol: 'square'});
37312
- applyStyleAttributes(o, 'Point', d);
37313
- return [o];
37314
- };
37315
-
37316
- symbolRenderers.line = function(d, x, y) {
37317
- var coords, o;
37318
- coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
37319
- o = importLineString(coords);
37320
- applyStyleAttributes(o, 'LineString', d);
37321
- return [o];
37322
- };
37323
-
37324
- symbolRenderers.polyline = function(d, x, y) {
37325
- var coords = d.coordinates || [];
37326
- var o = importMultiLineString(coords);
37327
- applyStyleAttributes(o, 'LineString', d);
37328
- return [o];
37329
- };
37330
-
37331
- symbolRenderers.polygon = function(d, x, y) {
37332
- var coords = d.coordinates || [];
37333
- var o = importPolygon(coords);
37334
- applyStyleAttributes(o, 'Polygon', d);
37335
- return [o];
37336
- };
37337
-
37338
- symbolRenderers.group = function(d, x, y) {
37339
- return (d.parts || []).reduce(function(memo, o) {
37340
- var sym = renderSymbol(o, x, y);
37341
- if (d.chained) {
37342
- x += (o.dx || 0);
37343
- y += (o.dy || 0);
37344
- }
37345
- return memo.concat(sym);
37346
- }, []);
37347
- };
37348
-
37349
37382
  cmd.scalebar = function(catalog, opts) {
37350
37383
  var frame = findFrameDataset(catalog);
37351
37384
  var obj, lyr;
@@ -37429,7 +37462,7 @@ ${svg}
37429
37462
  // so I'm using 'hanging' and 'auto', which seem to be well supported.
37430
37463
  // downside: requires a kludgy multiplier to calculate scalebar height (see above)
37431
37464
  };
37432
- var labelObj = symbolRenderers.label(labelOpts, anchorX, anchorY)[0];
37465
+ var labelObj = symbolRenderers.label(labelOpts, anchorX, anchorY);
37433
37466
  var g = {
37434
37467
  tag: 'g',
37435
37468
  children: [barObj, labelObj],
@@ -38680,6 +38713,15 @@ ${svg}
38680
38713
 
38681
38714
  var roundCoord = getRoundingFunction(0.01);
38682
38715
 
38716
+ function getSymbolColor(d) {
38717
+ return d.fill || 'magenta';
38718
+ }
38719
+
38720
+ function getSymbolRadius(d) {
38721
+ if (d.radius === 0 || d.length === 0 || d.r === 0) return 0;
38722
+ return d.radius || d.length || d.r || 5; // use a default value
38723
+ }
38724
+
38683
38725
  function forEachSymbolCoord(coords, cb) {
38684
38726
  var isPoint = coords && utils.isNumber(coords[0]);
38685
38727
  var isNested = !isPoint && coords && Array.isArray(coords[0]);
@@ -38934,8 +38976,19 @@ ${svg}
38934
38976
  return coords;
38935
38977
  }
38936
38978
 
38979
+ function makeCircleSymbol(d, opts) {
38980
+ var radius = getSymbolRadius(d);
38981
+ // TODO: remove duplicatoin with svg-symbols.js
38982
+ if (+opts.scale) radius *= +opts.scale;
38983
+ return {
38984
+ type: 'circle',
38985
+ fill: getSymbolColor(d),
38986
+ r: radius
38987
+ };
38988
+ }
38989
+
38937
38990
  function getPolygonCoords(d) {
38938
- var radius = d.radius || d.length || d.r,
38991
+ var radius = getSymbolRadius(d),
38939
38992
  sides = +d.sides || getSidesByType(d.type),
38940
38993
  rotated = sides % 2 == 1,
38941
38994
  coords = [],
@@ -38972,7 +39025,7 @@ ${svg}
38972
39025
  }
38973
39026
 
38974
39027
  function getStarCoords(d) {
38975
- var radius = d.radius || d.length || d.r,
39028
+ var radius = getSymbolRadius(d),
38976
39029
  points = d.points || d.sides && d.sides / 2 || 5,
38977
39030
  sides = points * 2,
38978
39031
  minorRadius = getMinorRadius(points) * radius,
@@ -39017,6 +39070,34 @@ ${svg}
39017
39070
  return 180 - centerAngle;
39018
39071
  }
39019
39072
 
39073
+ function makeRingSymbol(d, opts) {
39074
+ var scale = +opts.scale || 1;
39075
+ var radii = parseRings(d.radii || '2').map(function(r) { return r * scale; });
39076
+ var solidCenter = utils.isOdd(radii.length);
39077
+ var color = getSymbolColor(d);
39078
+ var parts = [];
39079
+ if (solidCenter) {
39080
+ parts.push({
39081
+ type: 'circle',
39082
+ fill: color,
39083
+ r: radii.shift()
39084
+ });
39085
+ }
39086
+ for (var i=0; i<radii.length; i+= 2) {
39087
+ parts.push({
39088
+ type: 'circle',
39089
+ fill: 'none', // TODO remove default black fill so this is not needed
39090
+ stroke: color,
39091
+ 'stroke-width': roundToTenths(radii[i+1] - radii[i]),
39092
+ r: roundToTenths(radii[i+1] * 0.5 + radii[i] * 0.5)
39093
+ });
39094
+ }
39095
+ return {
39096
+ type: 'group',
39097
+ parts: parts
39098
+ };
39099
+ }
39100
+
39020
39101
  // Returns GeoJSON MultiPolygon coords
39021
39102
  function getRingCoords(d) {
39022
39103
  var radii = parseRings(d.radii || '2');
@@ -39048,6 +39129,27 @@ ${svg}
39048
39129
  return utils.uniq(arr);
39049
39130
  }
39050
39131
 
39132
+ // Returns an svg-symbol data object for one symbol
39133
+ function makePolygonSymbol(coords, properties, geojsonType) {
39134
+ if (geojsonType == 'MultiPolygon') {
39135
+ coords = convertMultiPolygonCoords(coords);
39136
+ } else if (geojsonType != 'Polygon') {
39137
+ error('Unsupported type:', geojsonType);
39138
+ }
39139
+ roundCoordsForSVG(coords);
39140
+ return {
39141
+ type: 'polygon',
39142
+ coordinates: coords,
39143
+ fill: getSymbolColor(properties)
39144
+ };
39145
+ }
39146
+
39147
+ function convertMultiPolygonCoords(coords) {
39148
+ return coords.reduce(function(memo, poly) {
39149
+ return memo.concat(poly);
39150
+ }, []);
39151
+ }
39152
+
39051
39153
  // TODO: refactor to remove duplication in mapshaper-svg-style.js
39052
39154
  cmd.symbols = function(inputLyr, dataset, opts) {
39053
39155
  requireSinglePointLayer(inputLyr);
@@ -39064,8 +39166,20 @@ ${svg}
39064
39166
  if (!shp) return null;
39065
39167
  var d = getSymbolData(i);
39066
39168
  var rec = records[i] || {};
39169
+
39170
+ // non-polygon symbols
39171
+ if (!polygonMode && d.type == 'circle') {
39172
+ rec['svg-symbol'] = makeCircleSymbol(d, opts);
39173
+ return;
39174
+ }
39175
+ if (!polygonMode && d.type == 'ring') {
39176
+ rec['svg-symbol'] = makeRingSymbol(d, opts);
39177
+ return;
39178
+ }
39179
+
39067
39180
  var geojsonType = 'Polygon';
39068
39181
  var coords;
39182
+ // these symbols get converted to polygon shapes
39069
39183
  if (d.type == 'arrow') {
39070
39184
  coords = getFilledArrowCoords(d);
39071
39185
  } else if (d.type == 'ring') {
@@ -39089,7 +39203,7 @@ ${svg}
39089
39203
  if (d.tfill) rec.fill = d.fill;
39090
39204
  return createGeometry(coords, geojsonType);
39091
39205
  } else {
39092
- rec['svg-symbol'] = makeSvgPolygonSymbol(coords, d, geojsonType);
39206
+ rec['svg-symbol'] = makePolygonSymbol(coords, d, geojsonType);
39093
39207
  }
39094
39208
  });
39095
39209
 
@@ -39128,33 +39242,11 @@ ${svg}
39128
39242
  }
39129
39243
 
39130
39244
  function getMetersPerPixel(lyr, dataset) {
39131
-
39132
39245
  // TODO: handle single point, no extent
39133
39246
  var bounds = getLayerBounds(lyr);
39134
39247
  return bounds.width() / 800;
39135
39248
  }
39136
39249
 
39137
- // Returns an svg-symbol data object for one symbol
39138
- function makeSvgPolygonSymbol(coords, properties, geojsonType) {
39139
- if (geojsonType == 'MultiPolygon') {
39140
- coords = convertMultiPolygonCoords(coords);
39141
- } else if (geojsonType != 'Polygon') {
39142
- error('Unsupported type:', geojsonType);
39143
- }
39144
- roundCoordsForSVG(coords);
39145
- return {
39146
- type: 'polygon',
39147
- coordinates: coords,
39148
- fill: properties.fill || 'magenta'
39149
- };
39150
- }
39151
-
39152
- function convertMultiPolygonCoords(coords) {
39153
- return coords.reduce(function(memo, poly) {
39154
- return memo.concat(poly);
39155
- }, []);
39156
- }
39157
-
39158
39250
  var Symbols = /*#__PURE__*/Object.freeze({
39159
39251
  __proto__: null
39160
39252
  });
@@ -40661,7 +40753,8 @@ ${svg}
40661
40753
  // export only functions called by the GUI.
40662
40754
 
40663
40755
  var internal = {};
40664
- internal.svg = Object.assign({}, SvgCommon, SvgStringify, SvgPathUtils, GeojsonToSvg);
40756
+
40757
+ internal.svg = Object.assign({}, SvgStringify, SvgPathUtils, GeojsonToSvg, SvgLabels, SvgSymbols);
40665
40758
 
40666
40759
  // Assign functions and objects exported from modules to the 'internal' namespace
40667
40760
  // to maintain compatibility with tests and to expose (some of) them to the GUI.