mapshaper 0.5.110 → 0.5.113
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 +14 -0
- package/mapshaper.js +780 -581
- package/package.json +1 -1
- package/www/index.html +3 -0
- package/www/mapshaper-gui.js +94 -27
- package/www/mapshaper.js +780 -581
- package/www/page.css +26 -18
package/mapshaper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
|
|
3
|
-
var VERSION = "0.5.
|
|
3
|
+
var VERSION = "0.5.113";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var utils = /*#__PURE__*/Object.freeze({
|
|
@@ -2725,21 +2725,30 @@
|
|
|
2725
2725
|
message(utils.format("Snapped %s point%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
2726
2726
|
}
|
|
2727
2727
|
|
|
2728
|
+
function snapCoordsByInterval(arcs, snapDist) {
|
|
2729
|
+
if (snapDist > 0 === false) return 0;
|
|
2730
|
+
var ids = getCoordinateIds(arcs);
|
|
2731
|
+
return snapCoordsInternal(ids, arcs, snapDist);
|
|
2732
|
+
}
|
|
2733
|
+
|
|
2734
|
+
function snapEndpointsByInterval(arcs, snapDist) {
|
|
2735
|
+
if (snapDist > 0 === false) return 0;
|
|
2736
|
+
var ids = getEndpointIds(arcs);
|
|
2737
|
+
return snapCoordsInternal(ids, arcs, snapDist);
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2728
2740
|
// Snap together points within a small threshold
|
|
2729
2741
|
//
|
|
2730
|
-
function
|
|
2742
|
+
function snapCoordsInternal(ids, arcs, snapDist) {
|
|
2731
2743
|
var snapCount = 0,
|
|
2732
|
-
|
|
2733
|
-
|
|
2744
|
+
n = ids.length,
|
|
2745
|
+
data = arcs.getVertexData();
|
|
2734
2746
|
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
for (var i=0, n=ids.length; i<n; i++) {
|
|
2741
|
-
snapCount += snapPoint(i, snapDist, ids, data.xx, data.yy);
|
|
2742
|
-
}
|
|
2747
|
+
quicksortIds(data.xx, ids, 0, n-1);
|
|
2748
|
+
|
|
2749
|
+
// Consider: speed up sorting -- try bucket sort as first pass.
|
|
2750
|
+
for (var i=0; i<n; i++) {
|
|
2751
|
+
snapCount += snapPoint(i, snapDist, ids, data.xx, data.yy);
|
|
2743
2752
|
}
|
|
2744
2753
|
return snapCount;
|
|
2745
2754
|
|
|
@@ -2765,13 +2774,25 @@
|
|
|
2765
2774
|
}
|
|
2766
2775
|
}
|
|
2767
2776
|
|
|
2768
|
-
function
|
|
2769
|
-
var
|
|
2777
|
+
function getCoordinateIds(arcs) {
|
|
2778
|
+
var data = arcs.getVertexData(),
|
|
2779
|
+
n = data.xx.length,
|
|
2770
2780
|
ids = new Uint32Array(n);
|
|
2771
2781
|
for (var i=0; i<n; i++) {
|
|
2772
2782
|
ids[i] = i;
|
|
2773
2783
|
}
|
|
2774
|
-
|
|
2784
|
+
return ids;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
function getEndpointIds(arcs) {
|
|
2788
|
+
var i = 0;
|
|
2789
|
+
var ids = [];
|
|
2790
|
+
var data = arcs.getVertexData();
|
|
2791
|
+
data.nn.forEach(function(n) {
|
|
2792
|
+
if (n > 0 === false) return;
|
|
2793
|
+
ids.push(i, i+n-1);
|
|
2794
|
+
i += n;
|
|
2795
|
+
});
|
|
2775
2796
|
return ids;
|
|
2776
2797
|
}
|
|
2777
2798
|
|
|
@@ -2871,7 +2892,9 @@
|
|
|
2871
2892
|
getHighPrecisionSnapInterval: getHighPrecisionSnapInterval,
|
|
2872
2893
|
snapCoords: snapCoords,
|
|
2873
2894
|
snapCoordsByInterval: snapCoordsByInterval,
|
|
2874
|
-
|
|
2895
|
+
snapEndpointsByInterval: snapEndpointsByInterval,
|
|
2896
|
+
getCoordinateIds: getCoordinateIds,
|
|
2897
|
+
getEndpointIds: getEndpointIds
|
|
2875
2898
|
});
|
|
2876
2899
|
|
|
2877
2900
|
// Find the intersection between two 2D segments
|
|
@@ -9500,6 +9523,140 @@
|
|
|
9500
9523
|
};
|
|
9501
9524
|
}
|
|
9502
9525
|
|
|
9526
|
+
// convert targets from [{layers: [...], dataset: <>}, ...] format to
|
|
9527
|
+
// [{layer: <>, dataset: <>}, ...] format
|
|
9528
|
+
function expandCommandTargets(targets) {
|
|
9529
|
+
return targets.reduce(function(memo, target) {
|
|
9530
|
+
target.layers.forEach(function(lyr) {
|
|
9531
|
+
memo.push({layer: lyr, dataset: target.dataset});
|
|
9532
|
+
});
|
|
9533
|
+
return memo;
|
|
9534
|
+
}, []);
|
|
9535
|
+
}
|
|
9536
|
+
|
|
9537
|
+
|
|
9538
|
+
function findCommandTargets(layers, pattern, type) {
|
|
9539
|
+
var targets = [];
|
|
9540
|
+
var matches = findMatchingLayers(layers, pattern, true);
|
|
9541
|
+
if (type) {
|
|
9542
|
+
matches = matches.filter(function(o) {return o.layer.geometry_type == type;});
|
|
9543
|
+
}
|
|
9544
|
+
// assign target_id to matched layers
|
|
9545
|
+
// (kludge so layers can be sorted in the order that they match; used by -o command)
|
|
9546
|
+
layers.forEach(function(o) {o.layer.target_id = -1;});
|
|
9547
|
+
matches.forEach(function(o, i) {o.layer.target_id = i;});
|
|
9548
|
+
return groupLayersByDataset(matches);
|
|
9549
|
+
}
|
|
9550
|
+
|
|
9551
|
+
// arr: array of {layer: <>, dataset: <>} objects
|
|
9552
|
+
function groupLayersByDataset(arr) {
|
|
9553
|
+
var datasets = [];
|
|
9554
|
+
var targets = [];
|
|
9555
|
+
arr.forEach(function(o) {
|
|
9556
|
+
var i = datasets.indexOf(o.dataset);
|
|
9557
|
+
if (i == -1) {
|
|
9558
|
+
datasets.push(o.dataset);
|
|
9559
|
+
targets.push({layers: [o.layer], dataset: o.dataset});
|
|
9560
|
+
} else {
|
|
9561
|
+
targets[i].layers.push(o.layer);
|
|
9562
|
+
}
|
|
9563
|
+
});
|
|
9564
|
+
return targets;
|
|
9565
|
+
}
|
|
9566
|
+
|
|
9567
|
+
// layers: array of {layer: <>, dataset: <>} objects
|
|
9568
|
+
// pattern: is a layer identifier or a comma-sep. list of identifiers.
|
|
9569
|
+
// An identifier is a literal name, a pattern containing "*" wildcard or
|
|
9570
|
+
// a 1-based index (1..n)
|
|
9571
|
+
function findMatchingLayers(layers, pattern, throws) {
|
|
9572
|
+
var matchedLayers = [];
|
|
9573
|
+
var unmatchedIds = [];
|
|
9574
|
+
var index = {};
|
|
9575
|
+
pattern.split(',').forEach(function(subpattern, i) {
|
|
9576
|
+
var test = getLayerMatch(subpattern);
|
|
9577
|
+
var matched = false;
|
|
9578
|
+
layers.forEach(function(o, layerId) {
|
|
9579
|
+
// if (matchedLayers.indexOf(lyr) > -1) return; // performance bottleneck with 1000s of layers
|
|
9580
|
+
if (layerId in index) {
|
|
9581
|
+
matched = true;
|
|
9582
|
+
} else if (test(o.layer, layerId + 1)) { // layers are 1-indexed
|
|
9583
|
+
matchedLayers.push(o);
|
|
9584
|
+
index[layerId] = true;
|
|
9585
|
+
matched = true;
|
|
9586
|
+
}
|
|
9587
|
+
});
|
|
9588
|
+
if (matched == false) {
|
|
9589
|
+
unmatchedIds.push(subpattern);
|
|
9590
|
+
}
|
|
9591
|
+
});
|
|
9592
|
+
if (throws && unmatchedIds.length) {
|
|
9593
|
+
stop(utils.format('Missing layer%s: %s', unmatchedIds.length == 1 ? '' : 's', unmatchedIds.join(',')));
|
|
9594
|
+
}
|
|
9595
|
+
return matchedLayers;
|
|
9596
|
+
}
|
|
9597
|
+
|
|
9598
|
+
function getLayerMatch(pattern) {
|
|
9599
|
+
var isIndex = utils.isInteger(Number(pattern));
|
|
9600
|
+
var nameRxp = isIndex ? null : utils.wildcardToRegExp(pattern);
|
|
9601
|
+
return function(lyr, i) {
|
|
9602
|
+
return isIndex ? String(i) == pattern : nameRxp.test(lyr.name || '');
|
|
9603
|
+
};
|
|
9604
|
+
}
|
|
9605
|
+
|
|
9606
|
+
function countTargetLayers(targets) {
|
|
9607
|
+
return targets.reduce(function(memo, target) {
|
|
9608
|
+
return memo + target.layers.length;
|
|
9609
|
+
}, 0);
|
|
9610
|
+
}
|
|
9611
|
+
|
|
9612
|
+
// get an identifier for a layer that can be used in a target= option
|
|
9613
|
+
// (returns name if layer has a unique name, or a numerical id)
|
|
9614
|
+
function getLayerTargetId(catalog, lyr) {
|
|
9615
|
+
var nameCount = 0,
|
|
9616
|
+
name = lyr.name,
|
|
9617
|
+
id;
|
|
9618
|
+
catalog.getLayers().forEach(function(o, i) {
|
|
9619
|
+
if (lyr.name && o.layer.name == lyr.name) nameCount++;
|
|
9620
|
+
if (lyr == o.layer) id = String(i + 1);
|
|
9621
|
+
});
|
|
9622
|
+
if (!id) error('Layer not found');
|
|
9623
|
+
return nameCount == 1 ? lyr.name : id;
|
|
9624
|
+
}
|
|
9625
|
+
|
|
9626
|
+
var TargetUtils = /*#__PURE__*/Object.freeze({
|
|
9627
|
+
__proto__: null,
|
|
9628
|
+
expandCommandTargets: expandCommandTargets,
|
|
9629
|
+
findCommandTargets: findCommandTargets,
|
|
9630
|
+
groupLayersByDataset: groupLayersByDataset,
|
|
9631
|
+
findMatchingLayers: findMatchingLayers,
|
|
9632
|
+
getLayerMatch: getLayerMatch,
|
|
9633
|
+
countTargetLayers: countTargetLayers,
|
|
9634
|
+
getLayerTargetId: getLayerTargetId
|
|
9635
|
+
});
|
|
9636
|
+
|
|
9637
|
+
function getNullLayerProxy(targets) {
|
|
9638
|
+
var obj = {};
|
|
9639
|
+
var n = countTargetLayers(targets);
|
|
9640
|
+
var getters = {
|
|
9641
|
+
name: error,
|
|
9642
|
+
data: error,
|
|
9643
|
+
type: error,
|
|
9644
|
+
size: error,
|
|
9645
|
+
empty: error,
|
|
9646
|
+
bbox: error
|
|
9647
|
+
};
|
|
9648
|
+
addGetters(obj, getters);
|
|
9649
|
+
obj.field_exists = error;
|
|
9650
|
+
obj.field_type = error;
|
|
9651
|
+
obj.field_includes = error;
|
|
9652
|
+
return obj;
|
|
9653
|
+
function error() {
|
|
9654
|
+
throw Error(`This expression requires a single target layer; Received ${n} layers.`);
|
|
9655
|
+
}
|
|
9656
|
+
}
|
|
9657
|
+
|
|
9658
|
+
|
|
9659
|
+
|
|
9503
9660
|
// Returns an object representing a layer in a JS expression
|
|
9504
9661
|
function getLayerProxy(lyr, arcs) {
|
|
9505
9662
|
var obj = {};
|
|
@@ -9509,10 +9666,10 @@
|
|
|
9509
9666
|
data: records,
|
|
9510
9667
|
type: lyr.geometry_type,
|
|
9511
9668
|
size: getFeatureCount(lyr),
|
|
9512
|
-
empty: getFeatureCount(lyr) === 0
|
|
9669
|
+
empty: getFeatureCount(lyr) === 0,
|
|
9670
|
+
bbox: getBBoxGetter(obj, lyr, arcs)
|
|
9513
9671
|
};
|
|
9514
9672
|
addGetters(obj, getters);
|
|
9515
|
-
addBBoxGetter(obj, lyr, arcs);
|
|
9516
9673
|
obj.field_exists = function(name) {
|
|
9517
9674
|
return lyr.data && lyr.data.fieldExists(name) ? true : false;
|
|
9518
9675
|
};
|
|
@@ -9541,16 +9698,14 @@
|
|
|
9541
9698
|
return ctx;
|
|
9542
9699
|
}
|
|
9543
9700
|
|
|
9544
|
-
function
|
|
9701
|
+
function getBBoxGetter(obj, lyr, arcs) {
|
|
9545
9702
|
var bbox;
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
bbox = getBBox$1(lyr, arcs);
|
|
9550
|
-
}
|
|
9551
|
-
return bbox;
|
|
9703
|
+
return function() {
|
|
9704
|
+
if (!bbox) {
|
|
9705
|
+
bbox = getBBox$1(lyr, arcs);
|
|
9552
9706
|
}
|
|
9553
|
-
|
|
9707
|
+
return bbox;
|
|
9708
|
+
};
|
|
9554
9709
|
}
|
|
9555
9710
|
|
|
9556
9711
|
function getBBox$1(lyr, arcs) {
|
|
@@ -13589,6 +13744,14 @@
|
|
|
13589
13744
|
return p.length > 2 && p[2] == 'C';
|
|
13590
13745
|
}
|
|
13591
13746
|
|
|
13747
|
+
function stringifyPolygonCoords(coords) {
|
|
13748
|
+
var parts = [];
|
|
13749
|
+
for (var i=0; i<coords.length; i++) {
|
|
13750
|
+
parts.push(stringifyLineStringCoords(coords[i]) + ' Z');
|
|
13751
|
+
}
|
|
13752
|
+
return parts.length > 0 ? parts.join(' ') : '';
|
|
13753
|
+
}
|
|
13754
|
+
|
|
13592
13755
|
function stringifyLineStringCoords(coords) {
|
|
13593
13756
|
if (coords.length === 0) return '';
|
|
13594
13757
|
var d = 'M';
|
|
@@ -13619,6 +13782,7 @@
|
|
|
13619
13782
|
|
|
13620
13783
|
var SvgPathUtils = /*#__PURE__*/Object.freeze({
|
|
13621
13784
|
__proto__: null,
|
|
13785
|
+
stringifyPolygonCoords: stringifyPolygonCoords,
|
|
13622
13786
|
stringifyLineStringCoords: stringifyLineStringCoords
|
|
13623
13787
|
});
|
|
13624
13788
|
|
|
@@ -13886,6 +14050,7 @@
|
|
|
13886
14050
|
'stroke-dasharray': 'dasharray',
|
|
13887
14051
|
'stroke-width': 'number',
|
|
13888
14052
|
'stroke-opacity': 'number',
|
|
14053
|
+
'stroke-miterlimit': 'number',
|
|
13889
14054
|
'fill-opacity': 'number',
|
|
13890
14055
|
'text-anchor': null
|
|
13891
14056
|
};
|
|
@@ -13920,12 +14085,30 @@
|
|
|
13920
14085
|
|
|
13921
14086
|
var propertiesBySymbolType = {
|
|
13922
14087
|
polygon: utils.arrayToIndex(commonProperties.concat('fill', 'fill-pattern')),
|
|
13923
|
-
polyline: utils.arrayToIndex(commonProperties.concat('stroke-linecap', 'stroke-linejoin')),
|
|
14088
|
+
polyline: utils.arrayToIndex(commonProperties.concat('stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit')),
|
|
13924
14089
|
point: utils.arrayToIndex(commonProperties.concat('fill', 'r')),
|
|
13925
14090
|
label: utils.arrayToIndex(commonProperties.concat(
|
|
13926
|
-
'fill,
|
|
14091
|
+
'fill,font-family,font-size,text-anchor,font-weight,font-style,letter-spacing,dominant-baseline'.split(',')))
|
|
13927
14092
|
};
|
|
13928
14093
|
|
|
14094
|
+
// symType: point, polygon, polyline, label
|
|
14095
|
+
function applyStyleAttributes(svgObj, symType, rec, filter) {
|
|
14096
|
+
var fields = findPropertiesBySymbolGeom(Object.keys(rec || {}), symType);
|
|
14097
|
+
for (var i=0, n=fields.length; i<n; i++) {
|
|
14098
|
+
if (filter && !filter(fields[i])) continue;
|
|
14099
|
+
setAttribute(svgObj, fields[i], rec[fields[i]]);
|
|
14100
|
+
}
|
|
14101
|
+
}
|
|
14102
|
+
|
|
14103
|
+
function setAttribute(obj, k, v) {
|
|
14104
|
+
if (!obj.properties) obj.properties = {};
|
|
14105
|
+
obj.properties[k] = v;
|
|
14106
|
+
if (k == 'stroke-dasharray' && v) {
|
|
14107
|
+
// kludge for cleaner dashes... make butt the default?
|
|
14108
|
+
obj.properties['stroke-linecap'] = 'butt';
|
|
14109
|
+
}
|
|
14110
|
+
}
|
|
14111
|
+
|
|
13929
14112
|
function isSupportedSvgStyleProperty(name) {
|
|
13930
14113
|
return name in stylePropertyTypes;
|
|
13931
14114
|
}
|
|
@@ -14081,6 +14264,7 @@
|
|
|
14081
14264
|
|
|
14082
14265
|
var SvgProperties = /*#__PURE__*/Object.freeze({
|
|
14083
14266
|
__proto__: null,
|
|
14267
|
+
applyStyleAttributes: applyStyleAttributes,
|
|
14084
14268
|
isSupportedSvgStyleProperty: isSupportedSvgStyleProperty,
|
|
14085
14269
|
findPropertiesBySymbolGeom: findPropertiesBySymbolGeom,
|
|
14086
14270
|
getSymbolDataAccessor: getSymbolDataAccessor,
|
|
@@ -14094,7 +14278,69 @@
|
|
|
14094
14278
|
isSvgColor: isSvgColor
|
|
14095
14279
|
});
|
|
14096
14280
|
|
|
14097
|
-
|
|
14281
|
+
function toLabelString(val) {
|
|
14282
|
+
if (val || val === 0 || val === false) return String(val);
|
|
14283
|
+
return '';
|
|
14284
|
+
}
|
|
14285
|
+
|
|
14286
|
+
// Kludge for applying fill and other styles to a <text> element
|
|
14287
|
+
// (for rendering labels in the GUI with the dot in Canvas, not SVG)
|
|
14288
|
+
function renderStyledLabel(rec) {
|
|
14289
|
+
var o = renderLabel(rec);
|
|
14290
|
+
applyStyleAttributes(o, 'label', rec);
|
|
14291
|
+
return o;
|
|
14292
|
+
}
|
|
14293
|
+
|
|
14294
|
+
function renderLabel(rec) {
|
|
14295
|
+
var line = toLabelString(rec['label-text']);
|
|
14296
|
+
var morelines, obj;
|
|
14297
|
+
// Accepting \n (two chars) as an alternative to the newline character
|
|
14298
|
+
// (sometimes, '\n' is not converted to newline, e.g. in a Makefile)
|
|
14299
|
+
// Also accepting <br>
|
|
14300
|
+
var newline = /\n|\\n|<br>/i;
|
|
14301
|
+
var dx = rec.dx || 0;
|
|
14302
|
+
var dy = rec.dy || 0;
|
|
14303
|
+
var properties = {
|
|
14304
|
+
// using x, y instead of dx, dy for shift, because Illustrator doesn't apply
|
|
14305
|
+
// dx value when importing text with text-anchor=end
|
|
14306
|
+
y: dy,
|
|
14307
|
+
x: dx
|
|
14308
|
+
};
|
|
14309
|
+
if (newline.test(line)) {
|
|
14310
|
+
morelines = line.split(newline);
|
|
14311
|
+
line = morelines.shift();
|
|
14312
|
+
}
|
|
14313
|
+
obj = {
|
|
14314
|
+
tag: 'text',
|
|
14315
|
+
value: line,
|
|
14316
|
+
properties: properties
|
|
14317
|
+
};
|
|
14318
|
+
if (morelines) {
|
|
14319
|
+
// multiline label
|
|
14320
|
+
obj.children = [];
|
|
14321
|
+
morelines.forEach(function(line) {
|
|
14322
|
+
var tspan = {
|
|
14323
|
+
tag: 'tspan',
|
|
14324
|
+
value: line,
|
|
14325
|
+
properties: {
|
|
14326
|
+
x: dx,
|
|
14327
|
+
dy: rec['line-height'] || '1.1em'
|
|
14328
|
+
}
|
|
14329
|
+
};
|
|
14330
|
+
obj.children.push(tspan);
|
|
14331
|
+
});
|
|
14332
|
+
}
|
|
14333
|
+
return obj;
|
|
14334
|
+
}
|
|
14335
|
+
|
|
14336
|
+
var SvgLabels = /*#__PURE__*/Object.freeze({
|
|
14337
|
+
__proto__: null,
|
|
14338
|
+
renderStyledLabel: renderStyledLabel,
|
|
14339
|
+
renderLabel: renderLabel
|
|
14340
|
+
});
|
|
14341
|
+
|
|
14342
|
+
// convert data records (properties like svg-symbol, label-text, fill, r) to svg symbols
|
|
14343
|
+
|
|
14098
14344
|
|
|
14099
14345
|
function getTransform(xy, scale) {
|
|
14100
14346
|
var str = 'translate(' + roundToTenths(xy[0]) + ' ' + roundToTenths(xy[1]) + ')';
|
|
@@ -14104,27 +14350,197 @@
|
|
|
14104
14350
|
return str;
|
|
14105
14351
|
}
|
|
14106
14352
|
|
|
14107
|
-
var
|
|
14353
|
+
var symbolRenderers = {
|
|
14354
|
+
line: line,
|
|
14355
|
+
polygon: polygon,
|
|
14356
|
+
polyline: polyline,
|
|
14357
|
+
circle: circle,
|
|
14358
|
+
square: square,
|
|
14359
|
+
image: image,
|
|
14360
|
+
group: group,
|
|
14361
|
+
label: label
|
|
14362
|
+
};
|
|
14363
|
+
|
|
14364
|
+
// render label and/or point symbol
|
|
14365
|
+
function renderPoint(rec) {
|
|
14366
|
+
var children = [];
|
|
14367
|
+
// var halfSize = rec.r || 0; // radius or half of symbol size
|
|
14368
|
+
if (featureHasSvgSymbol(rec)) {
|
|
14369
|
+
children.push(renderSymbol(rec));
|
|
14370
|
+
}
|
|
14371
|
+
if (featureHasLabel(rec)) {
|
|
14372
|
+
children.push(renderStyledLabel(rec));
|
|
14373
|
+
}
|
|
14374
|
+
var o = children.length > 1 ? {tag: 'g', children: children} : children[0];
|
|
14375
|
+
if (!o) return null;
|
|
14376
|
+
o.properties = o.properties || {};
|
|
14377
|
+
return o;
|
|
14378
|
+
}
|
|
14379
|
+
|
|
14380
|
+
function renderSymbol(d) {
|
|
14381
|
+
if (d['svg-symbol']) {
|
|
14382
|
+
return renderComplexSymbol(d['svg-symbol']);
|
|
14383
|
+
}
|
|
14384
|
+
if (d.r > 0) {
|
|
14385
|
+
return circle(d);
|
|
14386
|
+
}
|
|
14387
|
+
return empty();
|
|
14388
|
+
}
|
|
14389
|
+
|
|
14390
|
+
function renderComplexSymbol(sym, x, y) {
|
|
14391
|
+
if (utils.isString(sym)) {
|
|
14392
|
+
sym = JSON.parse(sym);
|
|
14393
|
+
}
|
|
14394
|
+
if (sym.tag) {
|
|
14395
|
+
// symbol appears to already use mapshaper's svg notation... pass through
|
|
14396
|
+
return sym;
|
|
14397
|
+
}
|
|
14398
|
+
var renderer = symbolRenderers[sym.type];
|
|
14399
|
+
if (!renderer) {
|
|
14400
|
+
message(sym.type ? 'Unknown symbol type: ' + sym.type : 'Symbol is missing a type property');
|
|
14401
|
+
return empty();
|
|
14402
|
+
}
|
|
14403
|
+
var o = renderer(sym, x || 0, y || 0);
|
|
14404
|
+
if (sym.opacity) {
|
|
14405
|
+
o.properties.opacity = sym.opacity;
|
|
14406
|
+
}
|
|
14407
|
+
return o;
|
|
14408
|
+
}
|
|
14409
|
+
|
|
14410
|
+
function empty() {
|
|
14411
|
+
return {tag: 'g', properties: {}, children: []};
|
|
14412
|
+
}
|
|
14413
|
+
|
|
14414
|
+
function circle(d, x, y) {
|
|
14415
|
+
var o = {
|
|
14416
|
+
tag: 'circle',
|
|
14417
|
+
properties: {
|
|
14418
|
+
cx: x || 0,
|
|
14419
|
+
cy: y || 0
|
|
14420
|
+
}
|
|
14421
|
+
};
|
|
14422
|
+
applyStyleAttributes(o, 'point', d);
|
|
14423
|
+
return o;
|
|
14424
|
+
}
|
|
14425
|
+
|
|
14426
|
+
function label(d, x, y) {
|
|
14427
|
+
var o = renderStyledLabel(d);
|
|
14428
|
+
if (x || y) {
|
|
14429
|
+
o.properties.x = x || 0;
|
|
14430
|
+
o.properties.y = y || 0;
|
|
14431
|
+
}
|
|
14432
|
+
return o;
|
|
14433
|
+
}
|
|
14434
|
+
|
|
14435
|
+
function image(d, x, y) {
|
|
14436
|
+
var w = d.width || 20,
|
|
14437
|
+
h = d.height || 20;
|
|
14438
|
+
var o = {
|
|
14439
|
+
tag: 'image',
|
|
14440
|
+
properties: {
|
|
14441
|
+
width: w,
|
|
14442
|
+
height: h,
|
|
14443
|
+
x: (x || 0) - w / 2,
|
|
14444
|
+
y: (y || 0) - h / 2,
|
|
14445
|
+
href: d.href || ''
|
|
14446
|
+
}
|
|
14447
|
+
};
|
|
14448
|
+
return o;
|
|
14449
|
+
}
|
|
14450
|
+
|
|
14451
|
+
function square(d, x, y) {
|
|
14452
|
+
var r = d.r || 0;
|
|
14453
|
+
var o = {
|
|
14454
|
+
tag: 'rect',
|
|
14455
|
+
properties: {
|
|
14456
|
+
x: x - r,
|
|
14457
|
+
y: y - r,
|
|
14458
|
+
width: r * 2,
|
|
14459
|
+
height: r * 2
|
|
14460
|
+
}
|
|
14461
|
+
};
|
|
14462
|
+
applyStyleAttributes(o, 'point', d);
|
|
14463
|
+
return o;
|
|
14464
|
+
}
|
|
14465
|
+
|
|
14466
|
+
function line(d, x, y) {
|
|
14467
|
+
var coords, o;
|
|
14468
|
+
coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
|
|
14469
|
+
o = importLineString(coords);
|
|
14470
|
+
applyStyleAttributes(o, 'polyline', d);
|
|
14471
|
+
return o;
|
|
14472
|
+
}
|
|
14473
|
+
|
|
14474
|
+
// polyline coords are like GeoJSON MultiLineString coords: an array of 0 or more paths
|
|
14475
|
+
function polyline(d, x, y) {
|
|
14476
|
+
var coords = d.coordinates || [];
|
|
14477
|
+
var o = importMultiLineString(coords);
|
|
14478
|
+
applyStyleAttributes(o, 'polyline', d);
|
|
14479
|
+
return o;
|
|
14480
|
+
}
|
|
14481
|
+
|
|
14482
|
+
// polygon coords are an array of rings (and holes), like flattened MultiPolygon coords
|
|
14483
|
+
function polygon(d, x, y) {
|
|
14484
|
+
var coords = d.coordinates || [];
|
|
14485
|
+
var o = importPolygon(coords);
|
|
14486
|
+
applyStyleAttributes(o, 'polygon', d);
|
|
14487
|
+
return o;
|
|
14488
|
+
}
|
|
14489
|
+
|
|
14490
|
+
function group(d, x, y) {
|
|
14491
|
+
var parts = (d.parts || []).map(function(o) {
|
|
14492
|
+
var sym = renderComplexSymbol(o, x, y);
|
|
14493
|
+
if (d.chained) {
|
|
14494
|
+
//if (o.chained) {
|
|
14495
|
+
x += (o.dx || 0);
|
|
14496
|
+
y += (o.dy || 0);
|
|
14497
|
+
}
|
|
14498
|
+
return sym;
|
|
14499
|
+
});
|
|
14500
|
+
if (parts.length == 1) return parts[0];
|
|
14501
|
+
return {
|
|
14502
|
+
tag: 'g',
|
|
14503
|
+
children: parts
|
|
14504
|
+
};
|
|
14505
|
+
}
|
|
14506
|
+
|
|
14507
|
+
var SvgSymbols = /*#__PURE__*/Object.freeze({
|
|
14108
14508
|
__proto__: null,
|
|
14509
|
+
getTransform: getTransform,
|
|
14109
14510
|
symbolRenderers: symbolRenderers,
|
|
14110
|
-
|
|
14511
|
+
renderPoint: renderPoint
|
|
14111
14512
|
});
|
|
14112
14513
|
|
|
14514
|
+
var geojsonImporters = {
|
|
14515
|
+
Point: importPoint,
|
|
14516
|
+
Polygon: importPolygon,
|
|
14517
|
+
LineString: importLineString,
|
|
14518
|
+
MultiPoint: importMultiPoint,
|
|
14519
|
+
MultiLineString: importMultiLineString,
|
|
14520
|
+
MultiPolygon: importMultiPolygon
|
|
14521
|
+
};
|
|
14522
|
+
|
|
14113
14523
|
function importGeoJSONFeatures(features, opts) {
|
|
14114
14524
|
opts = opts || {};
|
|
14115
14525
|
return features.map(function(obj, i) {
|
|
14116
14526
|
var geom = obj.type == 'Feature' ? obj.geometry : obj; // could be null
|
|
14117
14527
|
var geomType = geom && geom.type;
|
|
14528
|
+
var msType = GeoJSON.translateGeoJSONType(geomType);
|
|
14529
|
+
var d = obj.properties || {};
|
|
14118
14530
|
var svgObj = null;
|
|
14119
14531
|
if (geomType && geom.coordinates) {
|
|
14120
|
-
svgObj = geojsonImporters[geomType](geom.coordinates,
|
|
14532
|
+
svgObj = geojsonImporters[geomType](geom.coordinates, d);
|
|
14121
14533
|
}
|
|
14122
14534
|
if (!svgObj) {
|
|
14123
14535
|
return {tag: 'g'}; // empty element
|
|
14124
|
-
}
|
|
14125
|
-
|
|
14126
|
-
if (
|
|
14127
|
-
|
|
14536
|
+
} else if (msType == 'polyline' || msType == 'polygon') {
|
|
14537
|
+
applyStyleAttributes(svgObj, msType, d);
|
|
14538
|
+
} else if (msType == 'point' && isSimpleCircle(d)) {
|
|
14539
|
+
// kludge -- maintains bw compatibility/passes tests -- style attributes
|
|
14540
|
+
// are applied to the <g> container, 'r' property is applied to circle
|
|
14541
|
+
applyStyleAttributes(svgObj, msType, d, simpleCircleFilter);
|
|
14542
|
+
} else {
|
|
14543
|
+
// other point symbols: attributes are complicated, added downstream
|
|
14128
14544
|
}
|
|
14129
14545
|
if ('id' in obj) {
|
|
14130
14546
|
if (!svgObj.properties) {
|
|
@@ -14136,34 +14552,37 @@
|
|
|
14136
14552
|
});
|
|
14137
14553
|
}
|
|
14138
14554
|
|
|
14139
|
-
function
|
|
14140
|
-
|
|
14141
|
-
if (
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14555
|
+
function importPoint(coords, rec) {
|
|
14556
|
+
rec = rec || {};
|
|
14557
|
+
if (isSimpleCircle(rec)) {
|
|
14558
|
+
return {
|
|
14559
|
+
tag: 'circle',
|
|
14560
|
+
properties: {
|
|
14561
|
+
cx: coords[0],
|
|
14562
|
+
cy: coords[1],
|
|
14563
|
+
r: rec.r
|
|
14564
|
+
}
|
|
14565
|
+
};
|
|
14147
14566
|
}
|
|
14567
|
+
var o = renderPoint(rec, coords);
|
|
14568
|
+
if (o) o.properties.transform = getTransform(coords);
|
|
14569
|
+
return o;
|
|
14148
14570
|
}
|
|
14149
14571
|
|
|
14150
|
-
function
|
|
14151
|
-
|
|
14152
|
-
// assigned by importPoint()
|
|
14153
|
-
} else {
|
|
14154
|
-
if (!obj.properties) obj.properties = {};
|
|
14155
|
-
obj.properties[k] = v;
|
|
14156
|
-
if (k == 'stroke-dasharray' && v) {
|
|
14157
|
-
// kludge for cleaner dashes... make butt the default?
|
|
14158
|
-
obj.properties['stroke-linecap'] = 'butt';
|
|
14159
|
-
}
|
|
14160
|
-
}
|
|
14572
|
+
function simpleCircleFilter(k) {
|
|
14573
|
+
return k != 'r';
|
|
14161
14574
|
}
|
|
14162
14575
|
|
|
14163
|
-
|
|
14576
|
+
// just a dot, no label or icon
|
|
14577
|
+
function isSimpleCircle(rec) {
|
|
14578
|
+
return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text']);
|
|
14579
|
+
}
|
|
14580
|
+
|
|
14581
|
+
function importMultiPoint(coords, rec) {
|
|
14164
14582
|
var children = [], p;
|
|
14165
14583
|
for (var i=0; i<coords.length; i++) {
|
|
14166
|
-
p = importPoint(coords[i], rec
|
|
14584
|
+
p = importPoint(coords[i], rec);
|
|
14585
|
+
if (!p) continue;
|
|
14167
14586
|
if (p.tag == 'g' && p.children) {
|
|
14168
14587
|
children = children.concat(p.children);
|
|
14169
14588
|
} else {
|
|
@@ -14173,18 +14592,6 @@
|
|
|
14173
14592
|
return children.length > 0 ? {tag: 'g', children: children} : null;
|
|
14174
14593
|
}
|
|
14175
14594
|
|
|
14176
|
-
function importMultiPath(coords, importer) {
|
|
14177
|
-
var o;
|
|
14178
|
-
for (var i=0; i<coords.length; i++) {
|
|
14179
|
-
if (i === 0) {
|
|
14180
|
-
o = importer(coords[i]);
|
|
14181
|
-
} else {
|
|
14182
|
-
o.properties.d += ' ' + importer(coords[i]).properties.d;
|
|
14183
|
-
}
|
|
14184
|
-
}
|
|
14185
|
-
return o;
|
|
14186
|
-
}
|
|
14187
|
-
|
|
14188
14595
|
function importLineString(coords) {
|
|
14189
14596
|
var d = stringifyLineStringCoords(coords);
|
|
14190
14597
|
return {
|
|
@@ -14193,7 +14600,6 @@
|
|
|
14193
14600
|
};
|
|
14194
14601
|
}
|
|
14195
14602
|
|
|
14196
|
-
|
|
14197
14603
|
function importMultiLineString(coords) {
|
|
14198
14604
|
var d = coords.map(stringifyLineStringCoords).join(' ');
|
|
14199
14605
|
return {
|
|
@@ -14202,180 +14608,38 @@
|
|
|
14202
14608
|
};
|
|
14203
14609
|
}
|
|
14204
14610
|
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
function importStyledLabel(rec, p) {
|
|
14208
|
-
var o = importLabel(rec, p);
|
|
14209
|
-
applyStyleAttributes(o, 'Point', rec);
|
|
14210
|
-
return o;
|
|
14211
|
-
}
|
|
14212
|
-
|
|
14213
|
-
function toLabelString(val) {
|
|
14214
|
-
if (val || val === 0 || val === false) return String(val);
|
|
14215
|
-
return '';
|
|
14611
|
+
function importMultiPolygon(coords) {
|
|
14612
|
+
return importPolygon(flattenMultiPolygonCoords(coords));
|
|
14216
14613
|
}
|
|
14217
14614
|
|
|
14218
|
-
function
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
// (sometimes, '\n' is not converted to newline, e.g. in a Makefile)
|
|
14223
|
-
// Also accepting <br>
|
|
14224
|
-
var newline = /\n|\\n|<br>/i;
|
|
14225
|
-
var dx = rec.dx || 0;
|
|
14226
|
-
var dy = rec.dy || 0;
|
|
14227
|
-
var properties = {
|
|
14228
|
-
// using x, y instead of dx, dy for shift, because Illustrator doesn't apply
|
|
14229
|
-
// dx value when importing text with text-anchor=end
|
|
14230
|
-
y: dy,
|
|
14231
|
-
x: dx
|
|
14232
|
-
};
|
|
14233
|
-
if (p) {
|
|
14234
|
-
properties.transform = getTransform(p);
|
|
14235
|
-
}
|
|
14236
|
-
if (newline.test(line)) {
|
|
14237
|
-
morelines = line.split(newline);
|
|
14238
|
-
line = morelines.shift();
|
|
14239
|
-
}
|
|
14240
|
-
obj = {
|
|
14241
|
-
tag: 'text',
|
|
14242
|
-
value: line,
|
|
14243
|
-
properties: properties
|
|
14244
|
-
};
|
|
14245
|
-
if (morelines) {
|
|
14246
|
-
// multiline label
|
|
14247
|
-
obj.children = [];
|
|
14248
|
-
morelines.forEach(function(line) {
|
|
14249
|
-
var tspan = {
|
|
14250
|
-
tag: 'tspan',
|
|
14251
|
-
value: line,
|
|
14252
|
-
properties: {
|
|
14253
|
-
x: dx,
|
|
14254
|
-
dy: rec['line-height'] || '1.1em'
|
|
14255
|
-
}
|
|
14256
|
-
};
|
|
14257
|
-
obj.children.push(tspan);
|
|
14258
|
-
});
|
|
14259
|
-
}
|
|
14260
|
-
return obj;
|
|
14261
|
-
}
|
|
14262
|
-
|
|
14263
|
-
function getEmptySymbol() {
|
|
14264
|
-
return {tag: 'g', properties: {}, children: []};
|
|
14265
|
-
}
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
function renderSymbol(d, x, y) {
|
|
14269
|
-
var renderer = symbolRenderers[d.type];
|
|
14270
|
-
if (!renderer) {
|
|
14271
|
-
stop(d.type ? 'Unknown symbol type: ' + d.type : 'Symbol is missing a type property');
|
|
14272
|
-
}
|
|
14273
|
-
return renderer(d, x || 0, y || 0);
|
|
14615
|
+
function flattenMultiPolygonCoords(coords) {
|
|
14616
|
+
return coords.reduce(function(memo, poly) {
|
|
14617
|
+
return memo.concat(poly);
|
|
14618
|
+
}, []);
|
|
14274
14619
|
}
|
|
14275
14620
|
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
var
|
|
14279
|
-
|
|
14280
|
-
return getEmptySymbol();
|
|
14281
|
-
}
|
|
14282
|
-
if (utils.isString(d)) {
|
|
14283
|
-
d = JSON.parse(d);
|
|
14284
|
-
}
|
|
14285
|
-
return {
|
|
14286
|
-
tag: 'g',
|
|
14621
|
+
function importPolygon(coords) {
|
|
14622
|
+
if (coords.length === 0) return null;
|
|
14623
|
+
var o = {
|
|
14624
|
+
tag: 'path',
|
|
14287
14625
|
properties: {
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
},
|
|
14291
|
-
children: renderSymbol(d)
|
|
14626
|
+
d: stringifyPolygonCoords(coords)
|
|
14627
|
+
}
|
|
14292
14628
|
};
|
|
14293
|
-
}
|
|
14294
|
-
|
|
14295
|
-
function importPoint(coords, rec, layerOpts) {
|
|
14296
|
-
rec = rec || {};
|
|
14297
|
-
if ('svg-symbol' in rec) {
|
|
14298
|
-
return importSymbol(rec['svg-symbol'], coords);
|
|
14299
|
-
}
|
|
14300
|
-
return importStandardPoint(coords, rec, layerOpts || {});
|
|
14301
|
-
}
|
|
14302
|
-
|
|
14303
|
-
function importPolygon(coords) {
|
|
14304
|
-
var d, o;
|
|
14305
|
-
for (var i=0; i<coords.length; i++) {
|
|
14306
|
-
d = o ? o.properties.d + ' ' : '';
|
|
14307
|
-
o = importLineString(coords[i]);
|
|
14308
|
-
o.properties.d = d + o.properties.d + ' Z';
|
|
14309
|
-
}
|
|
14310
14629
|
if (coords.length > 1) {
|
|
14311
14630
|
o.properties['fill-rule'] = 'evenodd'; // support polygons with holes
|
|
14312
14631
|
}
|
|
14313
14632
|
return o;
|
|
14314
14633
|
}
|
|
14315
14634
|
|
|
14316
|
-
function importStandardPoint(coords, rec, layerOpts) {
|
|
14317
|
-
var isLabel = 'label-text' in rec;
|
|
14318
|
-
var symbolType = layerOpts.point_symbol || '';
|
|
14319
|
-
var children = [];
|
|
14320
|
-
var halfSize = rec.r || 0; // radius or half of symbol size
|
|
14321
|
-
var p;
|
|
14322
|
-
// if not a label, create a symbol even without a size
|
|
14323
|
-
// (circle radius can be set via CSS)
|
|
14324
|
-
if (halfSize > 0 || !isLabel) {
|
|
14325
|
-
if (symbolType == 'square') {
|
|
14326
|
-
p = {
|
|
14327
|
-
tag: 'rect',
|
|
14328
|
-
properties: {
|
|
14329
|
-
x: coords[0] - halfSize,
|
|
14330
|
-
y: coords[1] - halfSize,
|
|
14331
|
-
width: halfSize * 2,
|
|
14332
|
-
height: halfSize * 2
|
|
14333
|
-
}};
|
|
14334
|
-
} else { // default is circle
|
|
14335
|
-
p = {
|
|
14336
|
-
tag: 'circle',
|
|
14337
|
-
properties: {
|
|
14338
|
-
cx: coords[0],
|
|
14339
|
-
cy: coords[1]
|
|
14340
|
-
}};
|
|
14341
|
-
if (halfSize > 0) {
|
|
14342
|
-
p.properties.r = halfSize;
|
|
14343
|
-
}
|
|
14344
|
-
}
|
|
14345
|
-
children.push(p);
|
|
14346
|
-
}
|
|
14347
|
-
if (isLabel) {
|
|
14348
|
-
children.push(importLabel(rec, coords));
|
|
14349
|
-
}
|
|
14350
|
-
return children.length > 1 ? {tag: 'g', children: children} : children[0];
|
|
14351
|
-
}
|
|
14352
|
-
|
|
14353
|
-
var geojsonImporters = {
|
|
14354
|
-
Point: importPoint,
|
|
14355
|
-
Polygon: importPolygon,
|
|
14356
|
-
LineString: importLineString,
|
|
14357
|
-
MultiPoint: function(coords, rec, opts) {
|
|
14358
|
-
return importMultiPoint(coords, rec, opts);
|
|
14359
|
-
},
|
|
14360
|
-
MultiLineString: function(coords) {
|
|
14361
|
-
return importMultiPath(coords, importLineString);
|
|
14362
|
-
},
|
|
14363
|
-
MultiPolygon: function(coords) {
|
|
14364
|
-
return importMultiPath(coords, importPolygon);
|
|
14365
|
-
}
|
|
14366
|
-
};
|
|
14367
|
-
|
|
14368
14635
|
var GeojsonToSvg = /*#__PURE__*/Object.freeze({
|
|
14369
14636
|
__proto__: null,
|
|
14370
14637
|
importGeoJSONFeatures: importGeoJSONFeatures,
|
|
14371
|
-
|
|
14638
|
+
importPoint: importPoint,
|
|
14372
14639
|
importLineString: importLineString,
|
|
14373
14640
|
importMultiLineString: importMultiLineString,
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
renderSymbol: renderSymbol,
|
|
14377
|
-
importSymbol: importSymbol,
|
|
14378
|
-
importPoint: importPoint,
|
|
14641
|
+
importMultiPolygon: importMultiPolygon,
|
|
14642
|
+
flattenMultiPolygonCoords: flattenMultiPolygonCoords,
|
|
14379
14643
|
importPolygon: importPolygon
|
|
14380
14644
|
});
|
|
14381
14645
|
|
|
@@ -14834,6 +15098,7 @@
|
|
|
14834
15098
|
return svg;
|
|
14835
15099
|
}
|
|
14836
15100
|
|
|
15101
|
+
// href: A URL or a local path
|
|
14837
15102
|
// TODO: download SVG files asynchronously
|
|
14838
15103
|
// (currently, files are downloaded synchronously, which is obviously undesirable)
|
|
14839
15104
|
//
|
|
@@ -14841,7 +15106,7 @@
|
|
|
14841
15106
|
var content;
|
|
14842
15107
|
if (href.indexOf('http') === 0) {
|
|
14843
15108
|
content = fetchFileSync(href);
|
|
14844
|
-
} else if (require('fs').existsSync(href)) {
|
|
15109
|
+
} else if (require('fs').existsSync(href)) {
|
|
14845
15110
|
content = require('fs').readFileSync(href, 'utf8');
|
|
14846
15111
|
} else {
|
|
14847
15112
|
stop("Invalid SVG location:", href);
|
|
@@ -14916,15 +15181,25 @@
|
|
|
14916
15181
|
convertPropertiesToDefinitions(obj, defs);
|
|
14917
15182
|
return stringify(obj);
|
|
14918
15183
|
}).join('\n');
|
|
15184
|
+
|
|
14919
15185
|
if (defs.length > 0) {
|
|
14920
15186
|
svg = '<defs>\n' + utils.pluck(defs, 'svg').join('') + '</defs>\n' + svg;
|
|
14921
15187
|
}
|
|
15188
|
+
|
|
14922
15189
|
if (svg.includes('xlink:')) {
|
|
14923
15190
|
namespace += ' xmlns:xlink="http://www.w3.org/1999/xlink"';
|
|
14924
15191
|
}
|
|
15192
|
+
|
|
15193
|
+
// default line style properties
|
|
14925
15194
|
var capStyle = opts.default_linecap || 'round';
|
|
15195
|
+
var lineProps = `stroke-linecap="${capStyle}" stroke-linejoin="round"`;
|
|
15196
|
+
if (svg.includes('stroke-linejoin="miter"')) {
|
|
15197
|
+
// the default limit in Illustrator seems to be 10 -- too large for mapping
|
|
15198
|
+
// (Mapbox uses 2 as the default in their styles)
|
|
15199
|
+
lineProps += ' stroke-miterlimit="2"';
|
|
15200
|
+
}
|
|
14926
15201
|
var template = `<?xml version="1.0"?>
|
|
14927
|
-
<svg ${namespace} version="1.2" baseProfile="tiny" width="%d" height="%d" viewBox="%s %s %s %s"
|
|
15202
|
+
<svg ${namespace} version="1.2" baseProfile="tiny" width="%d" height="%d" viewBox="%s %s %s %s" ${lineProps}>${style}
|
|
14928
15203
|
${svg}
|
|
14929
15204
|
</svg>`;
|
|
14930
15205
|
svg = utils.format(template,size[0], size[1], 0, 0, size[0], size[1]);
|
|
@@ -15090,6 +15365,15 @@ ${svg}
|
|
|
15090
15365
|
return layerObj;
|
|
15091
15366
|
}
|
|
15092
15367
|
|
|
15368
|
+
function featureHasSvgSymbol(d) {
|
|
15369
|
+
return !!(d && (d['svg-symbol'] || d.r));
|
|
15370
|
+
}
|
|
15371
|
+
|
|
15372
|
+
function featureHasLabel(d) {
|
|
15373
|
+
var text = d && d['label-text'];
|
|
15374
|
+
return text || text === 0; // accept numerical 0 as label text
|
|
15375
|
+
}
|
|
15376
|
+
|
|
15093
15377
|
function layerHasSvgSymbols(lyr) {
|
|
15094
15378
|
return lyr.geometry_type == 'point' && lyr.data && lyr.data.fieldExists('svg-symbol');
|
|
15095
15379
|
}
|
|
@@ -15109,6 +15393,8 @@ ${svg}
|
|
|
15109
15393
|
validateSvgDataFields: validateSvgDataFields,
|
|
15110
15394
|
exportDataAttributesForSVG: exportDataAttributesForSVG,
|
|
15111
15395
|
getEmptyLayerForSVG: getEmptyLayerForSVG,
|
|
15396
|
+
featureHasSvgSymbol: featureHasSvgSymbol,
|
|
15397
|
+
featureHasLabel: featureHasLabel,
|
|
15112
15398
|
layerHasSvgSymbols: layerHasSvgSymbols,
|
|
15113
15399
|
layerHasLabels: layerHasLabels
|
|
15114
15400
|
});
|
|
@@ -17169,116 +17455,6 @@ ${svg}
|
|
|
17169
17455
|
formatVersionedFileName: formatVersionedFileName
|
|
17170
17456
|
});
|
|
17171
17457
|
|
|
17172
|
-
// convert targets from [{layers: [...], dataset: <>}, ...] format to
|
|
17173
|
-
// [{layer: <>, dataset: <>}, ...] format
|
|
17174
|
-
function expandCommandTargets(targets) {
|
|
17175
|
-
return targets.reduce(function(memo, target) {
|
|
17176
|
-
target.layers.forEach(function(lyr) {
|
|
17177
|
-
memo.push({layer: lyr, dataset: target.dataset});
|
|
17178
|
-
});
|
|
17179
|
-
return memo;
|
|
17180
|
-
}, []);
|
|
17181
|
-
}
|
|
17182
|
-
|
|
17183
|
-
function findCommandTargets(layers, pattern, type) {
|
|
17184
|
-
var targets = [];
|
|
17185
|
-
var matches = findMatchingLayers(layers, pattern, true);
|
|
17186
|
-
if (type) {
|
|
17187
|
-
matches = matches.filter(function(o) {return o.layer.geometry_type == type;});
|
|
17188
|
-
}
|
|
17189
|
-
// assign target_id to matched layers
|
|
17190
|
-
// (kludge so layers can be sorted in the order that they match; used by -o command)
|
|
17191
|
-
layers.forEach(function(o) {o.layer.target_id = -1;});
|
|
17192
|
-
matches.forEach(function(o, i) {o.layer.target_id = i;});
|
|
17193
|
-
return groupLayersByDataset(matches);
|
|
17194
|
-
}
|
|
17195
|
-
|
|
17196
|
-
// arr: array of {layer: <>, dataset: <>} objects
|
|
17197
|
-
function groupLayersByDataset(arr) {
|
|
17198
|
-
var datasets = [];
|
|
17199
|
-
var targets = [];
|
|
17200
|
-
arr.forEach(function(o) {
|
|
17201
|
-
var i = datasets.indexOf(o.dataset);
|
|
17202
|
-
if (i == -1) {
|
|
17203
|
-
datasets.push(o.dataset);
|
|
17204
|
-
targets.push({layers: [o.layer], dataset: o.dataset});
|
|
17205
|
-
} else {
|
|
17206
|
-
targets[i].layers.push(o.layer);
|
|
17207
|
-
}
|
|
17208
|
-
});
|
|
17209
|
-
return targets;
|
|
17210
|
-
}
|
|
17211
|
-
|
|
17212
|
-
// layers: array of {layer: <>, dataset: <>} objects
|
|
17213
|
-
// pattern: is a layer identifier or a comma-sep. list of identifiers.
|
|
17214
|
-
// An identifier is a literal name, a pattern containing "*" wildcard or
|
|
17215
|
-
// a 1-based index (1..n)
|
|
17216
|
-
function findMatchingLayers(layers, pattern, throws) {
|
|
17217
|
-
var matchedLayers = [];
|
|
17218
|
-
var unmatchedIds = [];
|
|
17219
|
-
var index = {};
|
|
17220
|
-
pattern.split(',').forEach(function(subpattern, i) {
|
|
17221
|
-
var test = getLayerMatch(subpattern);
|
|
17222
|
-
var matched = false;
|
|
17223
|
-
layers.forEach(function(o, layerId) {
|
|
17224
|
-
// if (matchedLayers.indexOf(lyr) > -1) return; // performance bottleneck with 1000s of layers
|
|
17225
|
-
if (layerId in index) {
|
|
17226
|
-
matched = true;
|
|
17227
|
-
} else if (test(o.layer, layerId + 1)) { // layers are 1-indexed
|
|
17228
|
-
matchedLayers.push(o);
|
|
17229
|
-
index[layerId] = true;
|
|
17230
|
-
matched = true;
|
|
17231
|
-
}
|
|
17232
|
-
});
|
|
17233
|
-
if (matched == false) {
|
|
17234
|
-
unmatchedIds.push(subpattern);
|
|
17235
|
-
}
|
|
17236
|
-
});
|
|
17237
|
-
if (throws && unmatchedIds.length) {
|
|
17238
|
-
stop(utils.format('Missing layer%s: %s', unmatchedIds.length == 1 ? '' : 's', unmatchedIds.join(',')));
|
|
17239
|
-
}
|
|
17240
|
-
return matchedLayers;
|
|
17241
|
-
}
|
|
17242
|
-
|
|
17243
|
-
function getLayerMatch(pattern) {
|
|
17244
|
-
var isIndex = utils.isInteger(Number(pattern));
|
|
17245
|
-
var nameRxp = isIndex ? null : utils.wildcardToRegExp(pattern);
|
|
17246
|
-
return function(lyr, i) {
|
|
17247
|
-
return isIndex ? String(i) == pattern : nameRxp.test(lyr.name || '');
|
|
17248
|
-
};
|
|
17249
|
-
}
|
|
17250
|
-
|
|
17251
|
-
function countTargetLayers(targets) {
|
|
17252
|
-
return targets.reduce(function(memo, target) {
|
|
17253
|
-
return memo + target.layers.length;
|
|
17254
|
-
}, 0);
|
|
17255
|
-
}
|
|
17256
|
-
|
|
17257
|
-
// get an identifier for a layer that can be used in a target= option
|
|
17258
|
-
// (returns name if layer has a unique name, or a numerical id)
|
|
17259
|
-
function getLayerTargetId(catalog, lyr) {
|
|
17260
|
-
var nameCount = 0,
|
|
17261
|
-
name = lyr.name,
|
|
17262
|
-
id;
|
|
17263
|
-
catalog.getLayers().forEach(function(o, i) {
|
|
17264
|
-
if (lyr.name && o.layer.name == lyr.name) nameCount++;
|
|
17265
|
-
if (lyr == o.layer) id = String(i + 1);
|
|
17266
|
-
});
|
|
17267
|
-
if (!id) error('Layer not found');
|
|
17268
|
-
return nameCount == 1 ? lyr.name : id;
|
|
17269
|
-
}
|
|
17270
|
-
|
|
17271
|
-
var TargetUtils = /*#__PURE__*/Object.freeze({
|
|
17272
|
-
__proto__: null,
|
|
17273
|
-
expandCommandTargets: expandCommandTargets,
|
|
17274
|
-
findCommandTargets: findCommandTargets,
|
|
17275
|
-
groupLayersByDataset: groupLayersByDataset,
|
|
17276
|
-
findMatchingLayers: findMatchingLayers,
|
|
17277
|
-
getLayerMatch: getLayerMatch,
|
|
17278
|
-
countTargetLayers: countTargetLayers,
|
|
17279
|
-
getLayerTargetId: getLayerTargetId
|
|
17280
|
-
});
|
|
17281
|
-
|
|
17282
17458
|
function readFirstChars(reader, n) {
|
|
17283
17459
|
return bufferToString(reader.readSync(0, Math.min(n || 1000, reader.size())));
|
|
17284
17460
|
}
|
|
@@ -20154,6 +20330,10 @@ ${svg}
|
|
|
20154
20330
|
DEFAULT: true,
|
|
20155
20331
|
type: 'distance'
|
|
20156
20332
|
})
|
|
20333
|
+
.option('endpoints', {
|
|
20334
|
+
describe: 'only snap together the endpoints of lines',
|
|
20335
|
+
type: 'flag'
|
|
20336
|
+
})
|
|
20157
20337
|
.option('precision', {
|
|
20158
20338
|
describe: 'round all coordinates to a given decimal precision (e.g. 0.000001)',
|
|
20159
20339
|
type: 'number'
|
|
@@ -20297,14 +20477,21 @@ ${svg}
|
|
|
20297
20477
|
.option('stroke', {})
|
|
20298
20478
|
.option('stroke-width', {})
|
|
20299
20479
|
.option('fill', {
|
|
20300
|
-
describe: 'symbol fill color'
|
|
20480
|
+
describe: 'symbol fill color (filled symbols only)'
|
|
20301
20481
|
})
|
|
20302
|
-
.option('
|
|
20303
|
-
describe: '
|
|
20482
|
+
.option('stroke', {
|
|
20483
|
+
describe: 'symbol line color (linear symbols only)'
|
|
20484
|
+
})
|
|
20485
|
+
.option('stroke-width', {
|
|
20486
|
+
describe: 'symbol line width (linear symbols only)'
|
|
20487
|
+
})
|
|
20488
|
+
.option('geographic', {
|
|
20489
|
+
old_alias: 'polygons',
|
|
20490
|
+
describe: 'make geographic shapes instead of SVG objects',
|
|
20304
20491
|
type: 'flag'
|
|
20305
20492
|
})
|
|
20306
20493
|
.option('pixel-scale', {
|
|
20307
|
-
describe: 'set symbol scale in meters
|
|
20494
|
+
describe: 'set symbol scale in meters per pixel (geographic option)',
|
|
20308
20495
|
type: 'number',
|
|
20309
20496
|
})
|
|
20310
20497
|
// .option('flipped', {
|
|
@@ -20341,6 +20528,9 @@ ${svg}
|
|
|
20341
20528
|
.option('radii', {
|
|
20342
20529
|
describe: '(ring) comma-sep. list of concentric radii, ascending order'
|
|
20343
20530
|
})
|
|
20531
|
+
.option('arrow-style', {
|
|
20532
|
+
describe: '(arrow) options: stick, standard (default is standard)'
|
|
20533
|
+
})
|
|
20344
20534
|
.option('length', {
|
|
20345
20535
|
old_alias: 'arrow-length',
|
|
20346
20536
|
describe: '(arrow) length of arrow in pixels'
|
|
@@ -20695,16 +20885,16 @@ ${svg}
|
|
|
20695
20885
|
var ifOpts = {
|
|
20696
20886
|
expression: {
|
|
20697
20887
|
DEFAULT: true,
|
|
20698
|
-
describe: 'JS expression
|
|
20699
|
-
},
|
|
20700
|
-
empty: {
|
|
20701
|
-
describe: 'run if layer is empty',
|
|
20702
|
-
type: 'flag'
|
|
20703
|
-
},
|
|
20704
|
-
'not-empty': {
|
|
20705
|
-
describe: 'run if layer is not empty',
|
|
20706
|
-
type: 'flag'
|
|
20888
|
+
describe: 'JS expression'
|
|
20707
20889
|
},
|
|
20890
|
+
// empty: {
|
|
20891
|
+
// describe: 'run if layer is empty',
|
|
20892
|
+
// type: 'flag'
|
|
20893
|
+
// },
|
|
20894
|
+
// 'not-empty': {
|
|
20895
|
+
// describe: 'run if layer is not empty',
|
|
20896
|
+
// type: 'flag'
|
|
20897
|
+
// },
|
|
20708
20898
|
layer: {
|
|
20709
20899
|
describe: 'name or id of layer to test (default is current target)'
|
|
20710
20900
|
},
|
|
@@ -34689,13 +34879,27 @@ ${svg}
|
|
|
34689
34879
|
return job.control || (job.control = {});
|
|
34690
34880
|
}
|
|
34691
34881
|
|
|
34692
|
-
function compileIfCommandExpression(expr, catalog,
|
|
34693
|
-
var
|
|
34882
|
+
function compileIfCommandExpression(expr, catalog, opts) {
|
|
34883
|
+
var targetId = opts.layer || opts.target || null;
|
|
34884
|
+
var targets = catalog.findCommandTargets(targetId);
|
|
34885
|
+
var isSingle = targets.length == 1 && targets[0].layers.length == 1;
|
|
34886
|
+
if (targets.length === 0 && targetId) {
|
|
34887
|
+
stop('Layer not found:', targetId);
|
|
34888
|
+
}
|
|
34889
|
+
var ctx;
|
|
34890
|
+
if (isSingle) {
|
|
34891
|
+
ctx = getLayerProxy(targets[0].layers[0], targets[0].dataset.arcs, opts);
|
|
34892
|
+
} else {
|
|
34893
|
+
ctx = getNullLayerProxy(targets);
|
|
34894
|
+
}
|
|
34694
34895
|
var exprOpts = Object.assign({returns: true}, opts);
|
|
34695
34896
|
var func = compileExpressionToFunction(expr, exprOpts);
|
|
34696
34897
|
|
|
34697
|
-
|
|
34698
|
-
|
|
34898
|
+
// @geoType: optional geometry type (polygon, polyline, point, null);
|
|
34899
|
+
ctx.layer_exists = function(name, geoType) {
|
|
34900
|
+
var targets = catalog.findCommandTargets(name, geoType);
|
|
34901
|
+
if (targets.length === 0) return false;
|
|
34902
|
+
return true;
|
|
34699
34903
|
};
|
|
34700
34904
|
|
|
34701
34905
|
ctx.file_exists = function(file) {
|
|
@@ -34754,49 +34958,28 @@ ${svg}
|
|
|
34754
34958
|
return ['if','elif','else','endif'].includes(cmd);
|
|
34755
34959
|
}
|
|
34756
34960
|
|
|
34757
|
-
function
|
|
34758
|
-
var targ = getTargetLayer(catalog, opts);
|
|
34961
|
+
function test(catalog, opts) {
|
|
34962
|
+
// var targ = getTargetLayer(catalog, opts);
|
|
34759
34963
|
if (opts.expression) {
|
|
34760
|
-
return compileIfCommandExpression(opts.expression, catalog,
|
|
34761
|
-
}
|
|
34762
|
-
if (opts.empty) {
|
|
34763
|
-
return layerIsEmpty(targ.layer);
|
|
34764
|
-
}
|
|
34765
|
-
if (opts.not_empty) {
|
|
34766
|
-
return !layerIsEmpty(targ.layer);
|
|
34964
|
+
return compileIfCommandExpression(opts.expression, catalog, opts)();
|
|
34767
34965
|
}
|
|
34966
|
+
// if (opts.empty) {
|
|
34967
|
+
// return layerIsEmpty(targ.layer);
|
|
34968
|
+
// }
|
|
34969
|
+
// if (opts.not_empty) {
|
|
34970
|
+
// return !layerIsEmpty(targ.layer);
|
|
34971
|
+
// }
|
|
34768
34972
|
return true;
|
|
34769
34973
|
}
|
|
34770
34974
|
|
|
34771
34975
|
function evaluateIf(job, opts) {
|
|
34772
|
-
if (!blockWasActive(job) &&
|
|
34976
|
+
if (!blockWasActive(job) && test(job.catalog, opts)) {
|
|
34773
34977
|
enterActiveBranch(job);
|
|
34774
34978
|
} else {
|
|
34775
34979
|
enterInactiveBranch(job);
|
|
34776
34980
|
}
|
|
34777
34981
|
}
|
|
34778
34982
|
|
|
34779
|
-
// layerId: optional layer identifier
|
|
34780
|
-
//
|
|
34781
|
-
function getTargetLayer(catalog, opts) {
|
|
34782
|
-
var layerId = opts.layer || opts.target;
|
|
34783
|
-
var targets = catalog.findCommandTargets(layerId);
|
|
34784
|
-
if (targets.length === 0) {
|
|
34785
|
-
if (layerId) {
|
|
34786
|
-
stop('Layer not found:', layerId);
|
|
34787
|
-
} else {
|
|
34788
|
-
stop('Missing a target layer.');
|
|
34789
|
-
}
|
|
34790
|
-
}
|
|
34791
|
-
if (targets.length > 1 || targets[0].layers.length > 1) {
|
|
34792
|
-
stop('Command requires a single target layer.');
|
|
34793
|
-
}
|
|
34794
|
-
return {
|
|
34795
|
-
layer: targets[0].layers[0],
|
|
34796
|
-
dataset: targets[0].dataset
|
|
34797
|
-
};
|
|
34798
|
-
}
|
|
34799
|
-
|
|
34800
34983
|
cmd.ignore = function(targetLayer, dataset, opts) {
|
|
34801
34984
|
if (opts.empty && layerIsEmpty(targetLayer)) {
|
|
34802
34985
|
interrupt('Layer is empty, stopping processing');
|
|
@@ -37238,72 +37421,6 @@ ${svg}
|
|
|
37238
37421
|
}
|
|
37239
37422
|
};
|
|
37240
37423
|
|
|
37241
|
-
symbolRenderers.circle = function(d, x, y) {
|
|
37242
|
-
var o = importPoint([x, y], d, {});
|
|
37243
|
-
applyStyleAttributes(o, 'Point', d);
|
|
37244
|
-
return [o];
|
|
37245
|
-
};
|
|
37246
|
-
|
|
37247
|
-
symbolRenderers.label = function(d, x, y) {
|
|
37248
|
-
var o = importStyledLabel(d, [x, y]);
|
|
37249
|
-
return [o];
|
|
37250
|
-
};
|
|
37251
|
-
|
|
37252
|
-
symbolRenderers.image = function(d, x, y) {
|
|
37253
|
-
var w = d.width || 20,
|
|
37254
|
-
h = d.height || 20;
|
|
37255
|
-
var o = {
|
|
37256
|
-
tag: 'image',
|
|
37257
|
-
properties: {
|
|
37258
|
-
width: w,
|
|
37259
|
-
height: h,
|
|
37260
|
-
x: x - w / 2,
|
|
37261
|
-
y: y - h / 2,
|
|
37262
|
-
href: d.href || ''
|
|
37263
|
-
}
|
|
37264
|
-
};
|
|
37265
|
-
return [o];
|
|
37266
|
-
};
|
|
37267
|
-
|
|
37268
|
-
symbolRenderers.square = function(d, x, y) {
|
|
37269
|
-
var o = importPoint([x, y], d, {point_symbol: 'square'});
|
|
37270
|
-
applyStyleAttributes(o, 'Point', d);
|
|
37271
|
-
return [o];
|
|
37272
|
-
};
|
|
37273
|
-
|
|
37274
|
-
symbolRenderers.line = function(d, x, y) {
|
|
37275
|
-
var coords, o;
|
|
37276
|
-
coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
|
|
37277
|
-
o = importLineString(coords);
|
|
37278
|
-
applyStyleAttributes(o, 'LineString', d);
|
|
37279
|
-
return [o];
|
|
37280
|
-
};
|
|
37281
|
-
|
|
37282
|
-
symbolRenderers.polyline = function(d, x, y) {
|
|
37283
|
-
var coords = d.coordinates || [];
|
|
37284
|
-
var o = importMultiLineString(coords);
|
|
37285
|
-
applyStyleAttributes(o, 'LineString', d);
|
|
37286
|
-
return [o];
|
|
37287
|
-
};
|
|
37288
|
-
|
|
37289
|
-
symbolRenderers.polygon = function(d, x, y) {
|
|
37290
|
-
var coords = d.coordinates || [];
|
|
37291
|
-
var o = importPolygon(coords);
|
|
37292
|
-
applyStyleAttributes(o, 'Polygon', d);
|
|
37293
|
-
return [o];
|
|
37294
|
-
};
|
|
37295
|
-
|
|
37296
|
-
symbolRenderers.group = function(d, x, y) {
|
|
37297
|
-
return (d.parts || []).reduce(function(memo, o) {
|
|
37298
|
-
var sym = renderSymbol(o, x, y);
|
|
37299
|
-
if (d.chained) {
|
|
37300
|
-
x += (o.dx || 0);
|
|
37301
|
-
y += (o.dy || 0);
|
|
37302
|
-
}
|
|
37303
|
-
return memo.concat(sym);
|
|
37304
|
-
}, []);
|
|
37305
|
-
};
|
|
37306
|
-
|
|
37307
37424
|
cmd.scalebar = function(catalog, opts) {
|
|
37308
37425
|
var frame = findFrameDataset(catalog);
|
|
37309
37426
|
var obj, lyr;
|
|
@@ -37387,7 +37504,7 @@ ${svg}
|
|
|
37387
37504
|
// so I'm using 'hanging' and 'auto', which seem to be well supported.
|
|
37388
37505
|
// downside: requires a kludgy multiplier to calculate scalebar height (see above)
|
|
37389
37506
|
};
|
|
37390
|
-
var labelObj = symbolRenderers.label(labelOpts, anchorX, anchorY)
|
|
37507
|
+
var labelObj = symbolRenderers.label(labelOpts, anchorX, anchorY);
|
|
37391
37508
|
var g = {
|
|
37392
37509
|
tag: 'g',
|
|
37393
37510
|
children: [barObj, labelObj],
|
|
@@ -38490,7 +38607,12 @@ ${svg}
|
|
|
38490
38607
|
interval = getHighPrecisionSnapInterval(arcBounds.toArray());
|
|
38491
38608
|
}
|
|
38492
38609
|
arcs.flatten(); // bake in any simplification
|
|
38493
|
-
if (interval > 0) {
|
|
38610
|
+
if (interval > 0 && opts.endpoints) {
|
|
38611
|
+
// snaps line endpoints together
|
|
38612
|
+
// TODO: also snap endpoints to line segments to remove undershoots and overshoots
|
|
38613
|
+
snapCount = snapEndpointsByInterval(arcs, interval);
|
|
38614
|
+
message(utils.format("Snapped %s endpoint%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
38615
|
+
} else if (interval > 0) {
|
|
38494
38616
|
snapCount = snapCoordsByInterval(arcs, interval);
|
|
38495
38617
|
message(utils.format("Snapped %s point%s", snapCount, utils.pluralSuffix(snapCount)));
|
|
38496
38618
|
}
|
|
@@ -38633,6 +38755,19 @@ ${svg}
|
|
|
38633
38755
|
|
|
38634
38756
|
var roundCoord = getRoundingFunction(0.01);
|
|
38635
38757
|
|
|
38758
|
+
function getSymbolFillColor(d) {
|
|
38759
|
+
return d.fill || 'magenta';
|
|
38760
|
+
}
|
|
38761
|
+
|
|
38762
|
+
function getSymbolStrokeColor(d) {
|
|
38763
|
+
return d.stroke || d.fill || 'magenta';
|
|
38764
|
+
}
|
|
38765
|
+
|
|
38766
|
+
function getSymbolRadius(d) {
|
|
38767
|
+
if (d.radius === 0 || d.length === 0 || d.r === 0) return 0;
|
|
38768
|
+
return d.radius || d.length || d.r || 5; // use a default value
|
|
38769
|
+
}
|
|
38770
|
+
|
|
38636
38771
|
function forEachSymbolCoord(coords, cb) {
|
|
38637
38772
|
var isPoint = coords && utils.isNumber(coords[0]);
|
|
38638
38773
|
var isNested = !isPoint && coords && Array.isArray(coords[0]);
|
|
@@ -38701,57 +38836,104 @@ ${svg}
|
|
|
38701
38836
|
points.push(p2);
|
|
38702
38837
|
}
|
|
38703
38838
|
|
|
38704
|
-
|
|
38705
|
-
|
|
38706
|
-
|
|
38707
|
-
// var curve = d['arrow-stem-curve'] || 0;
|
|
38708
|
-
// var unscaledHeadWidth = d['arrow-head-width'] || 9;
|
|
38709
|
-
// var unscaledHeadLen = getHeadLength(unscaledHeadWidth, headAngle);
|
|
38710
|
-
// var scale = getScale(totalLen, unscaledHeadLen, minStemRatio);
|
|
38711
|
-
// var headWidth = unscaledHeadWidth * scale;
|
|
38712
|
-
// var headLen = unscaledHeadLen * scale;
|
|
38713
|
-
// var tip = getStickArrowTip(totalLen, curve);
|
|
38714
|
-
// var stem = [[0, 0], tip.concat()];
|
|
38715
|
-
// if (curve) {
|
|
38716
|
-
// addBezierArcControlPoints(stem, curve);
|
|
38717
|
-
// }
|
|
38718
|
-
// if (!headLen) return [stem];
|
|
38719
|
-
// var head = [addPoints([-headWidth / 2, -headLen], tip), tip.concat(), addPoints([headWidth / 2, -headLen], tip)];
|
|
38839
|
+
function getStickArrowCoords(d) {
|
|
38840
|
+
return getArrowCoords(d, 'stick');
|
|
38841
|
+
}
|
|
38720
38842
|
|
|
38721
|
-
|
|
38722
|
-
|
|
38723
|
-
|
|
38724
|
-
// }
|
|
38843
|
+
function getFilledArrowCoords(d) {
|
|
38844
|
+
return getArrowCoords(d, 'standard');
|
|
38845
|
+
}
|
|
38725
38846
|
|
|
38726
|
-
|
|
38727
|
-
|
|
38728
|
-
|
|
38729
|
-
|
|
38730
|
-
|
|
38731
|
-
|
|
38732
|
-
|
|
38847
|
+
function getArrowCoords(d, style) {
|
|
38848
|
+
var stickArrow = style == 'stick',
|
|
38849
|
+
// direction = d.rotation || d.direction || 0,
|
|
38850
|
+
direction = d.direction || 0, // rotation is an independent parameter
|
|
38851
|
+
stemTaper = d['stem-taper'] || 0,
|
|
38852
|
+
curvature = d['stem-curve'] || 0,
|
|
38853
|
+
size = calcArrowSize(d, stickArrow);
|
|
38854
|
+
if (!size) return null;
|
|
38855
|
+
var stemLen = size.stemLen,
|
|
38856
|
+
headLen = size.headLen,
|
|
38857
|
+
headDx = size.headWidth / 2,
|
|
38858
|
+
stemDx = size.stemWidth / 2,
|
|
38859
|
+
baseDx = stemDx * (1 - stemTaper),
|
|
38860
|
+
head, stem, coords, dx, dy;
|
|
38733
38861
|
|
|
38734
|
-
|
|
38735
|
-
|
|
38736
|
-
|
|
38862
|
+
if (curvature) {
|
|
38863
|
+
// make curved stem
|
|
38864
|
+
if (direction > 0) curvature = -curvature;
|
|
38865
|
+
var theta = Math.abs(curvature) / 180 * Math.PI;
|
|
38866
|
+
var sign = curvature > 0 ? 1 : -1;
|
|
38867
|
+
var ax = baseDx * Math.cos(theta); // rotate arrow base
|
|
38868
|
+
var ay = baseDx * Math.sin(theta) * -sign;
|
|
38869
|
+
dx = stemLen * Math.sin(theta / 2) * sign;
|
|
38870
|
+
dy = stemLen * Math.cos(theta / 2);
|
|
38871
|
+
|
|
38872
|
+
if (stickArrow) {
|
|
38873
|
+
stem = getCurvedStemCoords(-ax, -ay, dx, dy, theta);
|
|
38874
|
+
} else {
|
|
38875
|
+
var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy, theta);
|
|
38876
|
+
var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy, theta);
|
|
38877
|
+
stem = leftStem.concat(rightStem.reverse());
|
|
38878
|
+
}
|
|
38879
|
+
|
|
38880
|
+
} else {
|
|
38881
|
+
// make straight stem
|
|
38882
|
+
dx = 0;
|
|
38883
|
+
dy = stemLen;
|
|
38884
|
+
if (stickArrow) {
|
|
38885
|
+
stem = [[0, 0], [0, stemLen]];
|
|
38886
|
+
} else {
|
|
38887
|
+
stem = [[-baseDx, 0], [baseDx, 0]];
|
|
38888
|
+
}
|
|
38889
|
+
}
|
|
38890
|
+
|
|
38891
|
+
if (stickArrow) {
|
|
38892
|
+
// make stick arrow
|
|
38893
|
+
head = [[-headDx + dx, stemLen - headLen], [dx, stemLen], [headDx + dx, stemLen - headLen]];
|
|
38894
|
+
coords = [stem, head]; // MultiLineString coords
|
|
38895
|
+
} else {
|
|
38896
|
+
// make filled arrow
|
|
38897
|
+
// coordinates go counter clockwise, starting from the leftmost head coordinate
|
|
38898
|
+
head = [[stemDx + dx, dy], [headDx + dx, dy],
|
|
38899
|
+
[dx, headLen + dy], [-headDx + dx, dy], [-stemDx + dx, dy]];
|
|
38900
|
+
coords = stem.concat(head);
|
|
38901
|
+
coords.push(stem[0].concat()); // closed path
|
|
38902
|
+
coords = [coords]; // Polygon coords
|
|
38903
|
+
}
|
|
38904
|
+
|
|
38905
|
+
if (d.anchor == 'end') {
|
|
38906
|
+
scaleAndShiftCoords(coords, 1, [-dx, -dy - headLen]);
|
|
38907
|
+
} else if (d.anchor == 'middle') {
|
|
38908
|
+
// shift midpoint away from the head a bit for a more balanced placement
|
|
38909
|
+
// scaleAndShiftCoords(coords, 1, [-dx/2, (-dy - headLen)/2]);
|
|
38910
|
+
scaleAndShiftCoords(coords, 1, [-dx * 0.5, -dy * 0.5 - headLen * 0.25]);
|
|
38911
|
+
}
|
|
38912
|
+
|
|
38913
|
+
rotateCoords(coords, direction);
|
|
38914
|
+
if (d.flipped) {
|
|
38915
|
+
flipY(coords);
|
|
38916
|
+
}
|
|
38917
|
+
return coords;
|
|
38918
|
+
}
|
|
38737
38919
|
|
|
38738
38920
|
function calcStraightArrowCoords(stemLen, headLen, stemDx, headDx, baseDx) {
|
|
38739
38921
|
return [[baseDx, 0], [stemDx, stemLen], [headDx, stemLen], [0, stemLen + headLen],
|
|
38740
38922
|
[-headDx, stemLen], [-stemDx, stemLen], [-baseDx, 0], [baseDx, 0]];
|
|
38741
38923
|
}
|
|
38742
38924
|
|
|
38743
|
-
function calcArrowSize(d) {
|
|
38925
|
+
function calcArrowSize(d, stickArrow) {
|
|
38744
38926
|
// don't display arrows with negative length
|
|
38745
38927
|
var totalLen = Math.max(d.radius || d.length || d.r || 0, 0),
|
|
38746
38928
|
scale = 1,
|
|
38747
38929
|
o = initArrowSize(d); // calc several parameters
|
|
38748
38930
|
|
|
38749
|
-
if (totalLen
|
|
38931
|
+
if (totalLen >= 0) {
|
|
38750
38932
|
scale = calcScale(totalLen, o.headLen, d);
|
|
38751
38933
|
o.stemWidth *= scale;
|
|
38752
38934
|
o.headWidth *= scale;
|
|
38753
38935
|
o.headLen *= scale;
|
|
38754
|
-
o.stemLen = totalLen - o.headLen;
|
|
38936
|
+
o.stemLen = stickArrow ? totalLen : totalLen - o.headLen;
|
|
38755
38937
|
}
|
|
38756
38938
|
|
|
38757
38939
|
if (o.headWidth < o.stemWidth) {
|
|
@@ -38772,7 +38954,7 @@ ${svg}
|
|
|
38772
38954
|
} else if (stemLen + headLen > totalLen) {
|
|
38773
38955
|
scale = totalLen / (stemLen + headLen);
|
|
38774
38956
|
}
|
|
38775
|
-
return scale;
|
|
38957
|
+
return scale || 0;
|
|
38776
38958
|
}
|
|
38777
38959
|
|
|
38778
38960
|
function initArrowSize(d) {
|
|
@@ -38802,56 +38984,6 @@ ${svg}
|
|
|
38802
38984
|
return 1 / Math.tan(Math.PI * headAngle / 180 / 2) / 2;
|
|
38803
38985
|
}
|
|
38804
38986
|
|
|
38805
|
-
function getFilledArrowCoords(d) {
|
|
38806
|
-
var direction = d.rotation || d.direction || 0,
|
|
38807
|
-
stemTaper = d['stem-taper'] || 0,
|
|
38808
|
-
curvature = d['stem-curve'] || 0,
|
|
38809
|
-
size = calcArrowSize(d);
|
|
38810
|
-
if (!size) return null;
|
|
38811
|
-
var stemLen = size.stemLen,
|
|
38812
|
-
headLen = size.headLen,
|
|
38813
|
-
headDx = size.headWidth / 2,
|
|
38814
|
-
stemDx = size.stemWidth / 2,
|
|
38815
|
-
baseDx = stemDx * (1 - stemTaper),
|
|
38816
|
-
head, stem, coords, dx, dy;
|
|
38817
|
-
|
|
38818
|
-
if (curvature) {
|
|
38819
|
-
if (direction > 0) curvature = -curvature;
|
|
38820
|
-
var theta = Math.abs(curvature) / 180 * Math.PI;
|
|
38821
|
-
var sign = curvature > 0 ? 1 : -1;
|
|
38822
|
-
var ax = baseDx * Math.cos(theta); // rotate arrow base
|
|
38823
|
-
var ay = baseDx * Math.sin(theta) * -sign;
|
|
38824
|
-
dx = stemLen * Math.sin(theta / 2) * sign;
|
|
38825
|
-
dy = stemLen * Math.cos(theta / 2);
|
|
38826
|
-
var leftStem = getCurvedStemCoords(-ax, -ay, -stemDx + dx, dy, theta);
|
|
38827
|
-
var rightStem = getCurvedStemCoords(ax, ay, stemDx + dx, dy, theta);
|
|
38828
|
-
stem = leftStem.concat(rightStem.reverse());
|
|
38829
|
-
|
|
38830
|
-
} else {
|
|
38831
|
-
dx = 0;
|
|
38832
|
-
dy = stemLen;
|
|
38833
|
-
stem = [[-baseDx, 0], [baseDx, 0], [baseDx, 0]];
|
|
38834
|
-
}
|
|
38835
|
-
|
|
38836
|
-
// coordinates go counter clockwise, starting from the leftmost head coordinate
|
|
38837
|
-
head = [[stemDx + dx, dy], [headDx + dx, dy],
|
|
38838
|
-
[dx, headLen + dy], [-headDx + dx, dy], [-stemDx + dx, dy]];
|
|
38839
|
-
|
|
38840
|
-
coords = stem.concat(head);
|
|
38841
|
-
if (d.anchor == 'end') {
|
|
38842
|
-
scaleAndShiftCoords(coords, 1, [-dx, -dy - headLen]);
|
|
38843
|
-
} else if (d.anchor == 'middle') {
|
|
38844
|
-
// shift midpoint away from the head a bit for a more balanced placement
|
|
38845
|
-
// scaleAndShiftCoords(coords, 1, [-dx/2, (-dy - headLen)/2]);
|
|
38846
|
-
scaleAndShiftCoords(coords, 1, [-dx * 0.5, -dy * 0.5 - headLen * 0.25]);
|
|
38847
|
-
}
|
|
38848
|
-
|
|
38849
|
-
rotateCoords(coords, direction);
|
|
38850
|
-
if (d.flipped) {
|
|
38851
|
-
flipY(coords);
|
|
38852
|
-
}
|
|
38853
|
-
return [coords];
|
|
38854
|
-
}
|
|
38855
38987
|
|
|
38856
38988
|
// ax, ay: point on the base
|
|
38857
38989
|
// bx, by: point on the stem
|
|
@@ -38887,8 +39019,19 @@ ${svg}
|
|
|
38887
39019
|
return coords;
|
|
38888
39020
|
}
|
|
38889
39021
|
|
|
39022
|
+
function makeCircleSymbol(d, opts) {
|
|
39023
|
+
var radius = getSymbolRadius(d);
|
|
39024
|
+
// TODO: remove duplication with svg-symbols.js
|
|
39025
|
+
if (+opts.scale) radius *= +opts.scale;
|
|
39026
|
+
return {
|
|
39027
|
+
type: 'circle',
|
|
39028
|
+
fill: getSymbolFillColor(d),
|
|
39029
|
+
r: radius
|
|
39030
|
+
};
|
|
39031
|
+
}
|
|
39032
|
+
|
|
38890
39033
|
function getPolygonCoords(d) {
|
|
38891
|
-
var radius = d
|
|
39034
|
+
var radius = getSymbolRadius(d),
|
|
38892
39035
|
sides = +d.sides || getSidesByType(d.type),
|
|
38893
39036
|
rotated = sides % 2 == 1,
|
|
38894
39037
|
coords = [],
|
|
@@ -38925,7 +39068,7 @@ ${svg}
|
|
|
38925
39068
|
}
|
|
38926
39069
|
|
|
38927
39070
|
function getStarCoords(d) {
|
|
38928
|
-
var radius = d
|
|
39071
|
+
var radius = getSymbolRadius(d),
|
|
38929
39072
|
points = d.points || d.sides && d.sides / 2 || 5,
|
|
38930
39073
|
sides = points * 2,
|
|
38931
39074
|
minorRadius = getMinorRadius(points) * radius,
|
|
@@ -38970,6 +39113,35 @@ ${svg}
|
|
|
38970
39113
|
return 180 - centerAngle;
|
|
38971
39114
|
}
|
|
38972
39115
|
|
|
39116
|
+
// Returns a svg-symbol object
|
|
39117
|
+
function makeRingSymbol(d, opts) {
|
|
39118
|
+
var scale = +opts.scale || 1;
|
|
39119
|
+
var radii = parseRings(d.radii || '2').map(function(r) { return r * scale; });
|
|
39120
|
+
var solidCenter = utils.isOdd(radii.length);
|
|
39121
|
+
var color = getSymbolFillColor(d);
|
|
39122
|
+
var parts = [];
|
|
39123
|
+
if (solidCenter) {
|
|
39124
|
+
parts.push({
|
|
39125
|
+
type: 'circle',
|
|
39126
|
+
fill: color,
|
|
39127
|
+
r: radii.shift()
|
|
39128
|
+
});
|
|
39129
|
+
}
|
|
39130
|
+
for (var i=0; i<radii.length; i+= 2) {
|
|
39131
|
+
parts.push({
|
|
39132
|
+
type: 'circle',
|
|
39133
|
+
fill: 'none', // TODO remove default black fill so this is not needed
|
|
39134
|
+
stroke: color,
|
|
39135
|
+
'stroke-width': roundToTenths(radii[i+1] - radii[i]),
|
|
39136
|
+
r: roundToTenths(radii[i+1] * 0.5 + radii[i] * 0.5)
|
|
39137
|
+
});
|
|
39138
|
+
}
|
|
39139
|
+
return {
|
|
39140
|
+
type: 'group',
|
|
39141
|
+
parts: parts
|
|
39142
|
+
};
|
|
39143
|
+
}
|
|
39144
|
+
|
|
38973
39145
|
// Returns GeoJSON MultiPolygon coords
|
|
38974
39146
|
function getRingCoords(d) {
|
|
38975
39147
|
var radii = parseRings(d.radii || '2');
|
|
@@ -39001,13 +39173,36 @@ ${svg}
|
|
|
39001
39173
|
return utils.uniq(arr);
|
|
39002
39174
|
}
|
|
39003
39175
|
|
|
39176
|
+
// Returns an svg-symbol data object for one symbol
|
|
39177
|
+
function makePathSymbol(coords, properties, geojsonType) {
|
|
39178
|
+
var sym;
|
|
39179
|
+
if (geojsonType == 'MultiPolygon' || geojsonType == 'Polygon') {
|
|
39180
|
+
sym = {
|
|
39181
|
+
type: 'polygon',
|
|
39182
|
+
fill: getSymbolFillColor(properties),
|
|
39183
|
+
coordinates: geojsonType == 'Polygon' ? coords : flattenMultiPolygonCoords(coords)
|
|
39184
|
+
};
|
|
39185
|
+
} else if (geojsonType == 'LineString' || geojsonType == 'MultiLineString') {
|
|
39186
|
+
sym = {
|
|
39187
|
+
type: 'polyline',
|
|
39188
|
+
stroke: getSymbolStrokeColor(properties),
|
|
39189
|
+
'stroke-width': properties['stroke-width'] || 2,
|
|
39190
|
+
coordinates: geojsonType == 'LineString' ? [coords] : coords
|
|
39191
|
+
};
|
|
39192
|
+
} else {
|
|
39193
|
+
error('Unsupported type:', geojsonType);
|
|
39194
|
+
}
|
|
39195
|
+
roundCoordsForSVG(sym.coordinates);
|
|
39196
|
+
return sym;
|
|
39197
|
+
}
|
|
39198
|
+
|
|
39004
39199
|
// TODO: refactor to remove duplication in mapshaper-svg-style.js
|
|
39005
39200
|
cmd.symbols = function(inputLyr, dataset, opts) {
|
|
39006
39201
|
requireSinglePointLayer(inputLyr);
|
|
39007
39202
|
var lyr = opts.no_replace ? copyLayer(inputLyr) : inputLyr;
|
|
39008
|
-
var
|
|
39203
|
+
var shapeMode = !!opts.geographic;
|
|
39009
39204
|
var metersPerPx;
|
|
39010
|
-
if (
|
|
39205
|
+
if (shapeMode) {
|
|
39011
39206
|
requireProjectedDataset(dataset);
|
|
39012
39207
|
metersPerPx = opts.pixel_scale || getMetersPerPixel(lyr, dataset);
|
|
39013
39208
|
}
|
|
@@ -39017,9 +39212,24 @@ ${svg}
|
|
|
39017
39212
|
if (!shp) return null;
|
|
39018
39213
|
var d = getSymbolData(i);
|
|
39019
39214
|
var rec = records[i] || {};
|
|
39215
|
+
|
|
39216
|
+
// non-polygon symbols
|
|
39217
|
+
if (!shapeMode && d.type == 'circle') {
|
|
39218
|
+
rec['svg-symbol'] = makeCircleSymbol(d, opts);
|
|
39219
|
+
return;
|
|
39220
|
+
}
|
|
39221
|
+
if (!shapeMode && d.type == 'ring') {
|
|
39222
|
+
rec['svg-symbol'] = makeRingSymbol(d, opts);
|
|
39223
|
+
return;
|
|
39224
|
+
}
|
|
39225
|
+
|
|
39020
39226
|
var geojsonType = 'Polygon';
|
|
39021
39227
|
var coords;
|
|
39022
|
-
|
|
39228
|
+
// these symbols get converted to polygon shapes
|
|
39229
|
+
if (d.type == 'arrow' && opts.arrow_style == 'stick') {
|
|
39230
|
+
coords = getStickArrowCoords(d);
|
|
39231
|
+
geojsonType = 'MultiLineString';
|
|
39232
|
+
} else if (d.type == 'arrow') {
|
|
39023
39233
|
coords = getFilledArrowCoords(d);
|
|
39024
39234
|
} else if (d.type == 'ring') {
|
|
39025
39235
|
coords = getRingCoords(d);
|
|
@@ -39031,23 +39241,24 @@ ${svg}
|
|
|
39031
39241
|
}
|
|
39032
39242
|
if (!coords) return null;
|
|
39033
39243
|
rotateCoords(coords, +d.rotation || 0);
|
|
39034
|
-
if (!
|
|
39244
|
+
if (!shapeMode) {
|
|
39035
39245
|
flipY(coords);
|
|
39036
39246
|
}
|
|
39037
39247
|
if (+opts.scale) {
|
|
39038
39248
|
scaleAndShiftCoords(coords, +opts.scale, [0, 0]);
|
|
39039
39249
|
}
|
|
39040
|
-
if (
|
|
39250
|
+
if (shapeMode) {
|
|
39041
39251
|
scaleAndShiftCoords(coords, metersPerPx, shp[0]);
|
|
39042
|
-
if (d.
|
|
39252
|
+
if (d.fill) rec.fill = d.fill;
|
|
39253
|
+
if (d.stroke) rec.stroke = d.stroke;
|
|
39043
39254
|
return createGeometry(coords, geojsonType);
|
|
39044
39255
|
} else {
|
|
39045
|
-
rec['svg-symbol'] =
|
|
39256
|
+
rec['svg-symbol'] = makePathSymbol(coords, d, geojsonType);
|
|
39046
39257
|
}
|
|
39047
39258
|
});
|
|
39048
39259
|
|
|
39049
39260
|
var outputLyr, dataset2;
|
|
39050
|
-
if (
|
|
39261
|
+
if (shapeMode) {
|
|
39051
39262
|
dataset2 = importGeometries(geometries, records);
|
|
39052
39263
|
outputLyr = mergeOutputLayerIntoDataset(inputLyr, dataset, dataset2, opts);
|
|
39053
39264
|
outputLyr.data = lyr.data;
|
|
@@ -39081,31 +39292,10 @@ ${svg}
|
|
|
39081
39292
|
}
|
|
39082
39293
|
|
|
39083
39294
|
function getMetersPerPixel(lyr, dataset) {
|
|
39084
|
-
|
|
39085
|
-
// TODO: handle single point, no extent
|
|
39086
39295
|
var bounds = getLayerBounds(lyr);
|
|
39087
|
-
|
|
39088
|
-
|
|
39089
|
-
|
|
39090
|
-
// Returns an svg-symbol data object for one symbol
|
|
39091
|
-
function makeSvgPolygonSymbol(coords, properties, geojsonType) {
|
|
39092
|
-
if (geojsonType == 'MultiPolygon') {
|
|
39093
|
-
coords = convertMultiPolygonCoords(coords);
|
|
39094
|
-
} else if (geojsonType != 'Polygon') {
|
|
39095
|
-
error('Unsupported type:', geojsonType);
|
|
39096
|
-
}
|
|
39097
|
-
roundCoordsForSVG(coords);
|
|
39098
|
-
return {
|
|
39099
|
-
type: 'polygon',
|
|
39100
|
-
coordinates: coords,
|
|
39101
|
-
fill: properties.fill || 'magenta'
|
|
39102
|
-
};
|
|
39103
|
-
}
|
|
39104
|
-
|
|
39105
|
-
function convertMultiPolygonCoords(coords) {
|
|
39106
|
-
return coords.reduce(function(memo, poly) {
|
|
39107
|
-
return memo.concat(poly);
|
|
39108
|
-
}, []);
|
|
39296
|
+
// TODO: need a better way to handle a single point with no extent
|
|
39297
|
+
var extent = bounds.width() || bounds.height() || 1000;
|
|
39298
|
+
return extent / 800;
|
|
39109
39299
|
}
|
|
39110
39300
|
|
|
39111
39301
|
var Symbols = /*#__PURE__*/Object.freeze({
|
|
@@ -39510,6 +39700,19 @@ ${svg}
|
|
|
39510
39700
|
return [lyr1, lyr2];
|
|
39511
39701
|
}
|
|
39512
39702
|
|
|
39703
|
+
function commandAcceptsMultipleTargetDatasets(name) {
|
|
39704
|
+
return name == 'rotate' || name == 'info' || name == 'proj' ||
|
|
39705
|
+
name == 'drop' || name == 'target' || name == 'if' || name == 'elif' ||
|
|
39706
|
+
name == 'else' || name == 'endif';
|
|
39707
|
+
}
|
|
39708
|
+
|
|
39709
|
+
function commandAcceptsEmptyTarget(name) {
|
|
39710
|
+
return name == 'graticule' || name == 'i' || name == 'help' ||
|
|
39711
|
+
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39712
|
+
name == 'include' || name == 'print' || name == 'if' || name == 'elif' ||
|
|
39713
|
+
name == 'else' || name == 'endif';
|
|
39714
|
+
}
|
|
39715
|
+
|
|
39513
39716
|
function runCommand(command, job, cb) {
|
|
39514
39717
|
var name = command.name,
|
|
39515
39718
|
opts = command.options,
|
|
@@ -39531,7 +39734,6 @@ ${svg}
|
|
|
39531
39734
|
job.startCommand(command);
|
|
39532
39735
|
|
|
39533
39736
|
try { // catch errors from synchronous functions
|
|
39534
|
-
|
|
39535
39737
|
T$1.start();
|
|
39536
39738
|
|
|
39537
39739
|
if (name == 'rename-layers') {
|
|
@@ -39546,13 +39748,11 @@ ${svg}
|
|
|
39546
39748
|
// TODO: check that combine_layers is only used w/ GeoJSON output
|
|
39547
39749
|
targets = job.catalog.findCommandTargets(opts.target || opts.combine_layers && '*');
|
|
39548
39750
|
|
|
39549
|
-
} else if (name
|
|
39550
|
-
// these commands accept multiple target datasets
|
|
39751
|
+
} else if (commandAcceptsMultipleTargetDatasets(name)) {
|
|
39551
39752
|
targets = job.catalog.findCommandTargets(opts.target);
|
|
39552
39753
|
|
|
39553
39754
|
} else {
|
|
39554
39755
|
targets = job.catalog.findCommandTargets(opts.target);
|
|
39555
|
-
|
|
39556
39756
|
// special case to allow -merge-layers and -union to combine layers from multiple datasets
|
|
39557
39757
|
// TODO: support multi-dataset targets for other commands
|
|
39558
39758
|
if (targets.length > 1 && (name == 'merge-layers' || name == 'union')) {
|
|
@@ -39576,9 +39776,7 @@ ${svg}
|
|
|
39576
39776
|
stop(utils.format('Missing target: %s\nAvailable layers: %s',
|
|
39577
39777
|
opts.target, getFormattedLayerList(job.catalog)));
|
|
39578
39778
|
}
|
|
39579
|
-
if (!(name
|
|
39580
|
-
name == 'point-grid' || name == 'shape' || name == 'rectangle' ||
|
|
39581
|
-
name == 'include' || name == 'print')) {
|
|
39779
|
+
if (!commandAcceptsEmptyTarget(name)) {
|
|
39582
39780
|
throw new UserError("No data is available");
|
|
39583
39781
|
}
|
|
39584
39782
|
}
|
|
@@ -40606,7 +40804,8 @@ ${svg}
|
|
|
40606
40804
|
// export only functions called by the GUI.
|
|
40607
40805
|
|
|
40608
40806
|
var internal = {};
|
|
40609
|
-
|
|
40807
|
+
|
|
40808
|
+
internal.svg = Object.assign({}, SvgStringify, SvgPathUtils, GeojsonToSvg, SvgLabels, SvgSymbols);
|
|
40610
40809
|
|
|
40611
40810
|
// Assign functions and objects exported from modules to the 'internal' namespace
|
|
40612
40811
|
// to maintain compatibility with tests and to expose (some of) them to the GUI.
|