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/CHANGELOG.md +5 -0
- package/mapshaper.js +361 -268
- package/package.json +1 -1
- package/www/mapshaper-gui.js +19 -16
- package/www/mapshaper.js +361 -268
package/www/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
14497
|
+
svgObj = geojsonImporters[geomType](geom.coordinates, d);
|
|
14276
14498
|
}
|
|
14277
14499
|
if (!svgObj) {
|
|
14278
14500
|
return {tag: 'g'}; // empty element
|
|
14279
|
-
}
|
|
14280
|
-
|
|
14281
|
-
if (
|
|
14282
|
-
|
|
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
|
|
14295
|
-
|
|
14296
|
-
if (
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
|
|
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
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
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
|
|
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
|
|
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
|
|
14513
|
-
return importMultiPoint(coords, rec
|
|
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
|
-
|
|
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)
|
|
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
|
|
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
|
|
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'] =
|
|
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
|
-
|
|
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.
|