mapshaper 0.6.66 → 0.6.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mapshaper.js +306 -209
- package/package.json +1 -1
- package/www/mapshaper-gui.js +336 -197
- package/www/mapshaper.js +306 -209
- package/www/page.css +4 -3
package/mapshaper.js
CHANGED
|
@@ -13397,10 +13397,11 @@
|
|
|
13397
13397
|
|
|
13398
13398
|
// str: display size in px, pt or in
|
|
13399
13399
|
// using: 72pt per inch, 1pt per pixel.
|
|
13400
|
-
function parseSizeParam(
|
|
13401
|
-
var
|
|
13402
|
-
|
|
13403
|
-
|
|
13400
|
+
function parseSizeParam(p) {
|
|
13401
|
+
var str = String(p),
|
|
13402
|
+
num = parseFloat(str),
|
|
13403
|
+
units = /px|pix/.test(str) && 'px' || /pt|point/.test(str) && 'pt' ||
|
|
13404
|
+
/in/.test(str) && 'in' || !isNaN(+str) && 'px' || null;
|
|
13404
13405
|
if (isNaN(num) || !units) {
|
|
13405
13406
|
stop('Invalid size:', str);
|
|
13406
13407
|
}
|
|
@@ -14725,6 +14726,9 @@
|
|
|
14725
14726
|
bounds: function() {
|
|
14726
14727
|
return shapeBounds().toArray();
|
|
14727
14728
|
},
|
|
14729
|
+
bbox: function() {
|
|
14730
|
+
return shapeBounds().toArray();
|
|
14731
|
+
},
|
|
14728
14732
|
height: function() {
|
|
14729
14733
|
return shapeBounds().height();
|
|
14730
14734
|
},
|
|
@@ -17322,9 +17326,10 @@
|
|
|
17322
17326
|
}
|
|
17323
17327
|
|
|
17324
17328
|
function getGapRemovalMessage(removed, retained, areaLabel) {
|
|
17329
|
+
var tot = removed + retained;
|
|
17325
17330
|
if (removed > 0 === false) return '';
|
|
17326
|
-
return utils.format('Removed %,d
|
|
17327
|
-
removed,
|
|
17331
|
+
return utils.format('Removed %,d of %,d sliver%s using %s',
|
|
17332
|
+
removed, tot, utils.pluralSuffix(tot), areaLabel);
|
|
17328
17333
|
}
|
|
17329
17334
|
|
|
17330
17335
|
function dissolvePolygonGroups2(groups, lyr, dataset, opts) {
|
|
@@ -18228,7 +18233,7 @@
|
|
|
18228
18233
|
var frameLyr = findFrameLayerInDataset(dataset);
|
|
18229
18234
|
var frameData;
|
|
18230
18235
|
if (frameLyr) {
|
|
18231
|
-
frameData = getFrameLayerData(frameLyr, dataset);
|
|
18236
|
+
frameData = getFrameLayerData(frameLyr, dataset.arcs);
|
|
18232
18237
|
} else {
|
|
18233
18238
|
frameData = calcFrameData(dataset, exportOpts);
|
|
18234
18239
|
}
|
|
@@ -18237,8 +18242,8 @@
|
|
|
18237
18242
|
}
|
|
18238
18243
|
|
|
18239
18244
|
|
|
18240
|
-
function getFrameLayerData(lyr,
|
|
18241
|
-
var bounds = getLayerBounds(lyr,
|
|
18245
|
+
function getFrameLayerData(lyr, arcs) {
|
|
18246
|
+
var bounds = getLayerBounds(lyr, arcs);
|
|
18242
18247
|
var d = lyr.data.getReadOnlyRecordAt(0);
|
|
18243
18248
|
var w = d.width || 800;
|
|
18244
18249
|
var h = w * bounds.height() / bounds.width();
|
|
@@ -18250,10 +18255,6 @@
|
|
|
18250
18255
|
};
|
|
18251
18256
|
}
|
|
18252
18257
|
|
|
18253
|
-
// export function getFrameLayerData(lyr) {
|
|
18254
|
-
// return lyr.data && lyr.data.getReadOnlyRecordAt(0);
|
|
18255
|
-
// }
|
|
18256
|
-
|
|
18257
18258
|
|
|
18258
18259
|
function calcFrameData(dataset, opts) {
|
|
18259
18260
|
var bounds;
|
|
@@ -18287,31 +18288,34 @@
|
|
|
18287
18288
|
|
|
18288
18289
|
|
|
18289
18290
|
// @lyr dataset layer
|
|
18290
|
-
function isFrameLayer(lyr,
|
|
18291
|
+
function isFrameLayer(lyr, arcs) {
|
|
18291
18292
|
return getFurnitureLayerType(lyr) == 'frame' &&
|
|
18292
|
-
layerIsRectangle(lyr,
|
|
18293
|
+
layerIsRectangle(lyr, arcs);
|
|
18293
18294
|
}
|
|
18294
18295
|
|
|
18295
18296
|
function findFrameLayerInDataset(dataset) {
|
|
18296
18297
|
return utils.find(dataset.layers, function(lyr) {
|
|
18297
|
-
return isFrameLayer(lyr, dataset);
|
|
18298
|
+
return isFrameLayer(lyr, dataset.arcs);
|
|
18298
18299
|
});
|
|
18299
18300
|
}
|
|
18300
18301
|
|
|
18302
|
+
// TODO: handle multiple frames in catalog
|
|
18301
18303
|
function findFrameDataset(catalog) {
|
|
18302
|
-
var target =
|
|
18303
|
-
|
|
18304
|
-
});
|
|
18305
|
-
return target ? target.dataset : null;
|
|
18304
|
+
var target = findFrame(catalog);
|
|
18305
|
+
return target && target.dataset || null;
|
|
18306
18306
|
}
|
|
18307
18307
|
|
|
18308
18308
|
function findFrameLayer(catalog) {
|
|
18309
|
-
var target =
|
|
18310
|
-
return isFrameLayer(o.layer, o.dataset);
|
|
18311
|
-
});
|
|
18309
|
+
var target = findFrame(catalog);
|
|
18312
18310
|
return target && target.layer || null;
|
|
18313
18311
|
}
|
|
18314
18312
|
|
|
18313
|
+
function findFrame(catalog) {
|
|
18314
|
+
return utils.find(catalog.getLayers(), function(o) {
|
|
18315
|
+
return isFrameLayer(o.layer, o.dataset.arcs);
|
|
18316
|
+
});
|
|
18317
|
+
}
|
|
18318
|
+
|
|
18315
18319
|
function getFrameLayerBounds(lyr) {
|
|
18316
18320
|
return new Bounds(getFurnitureLayerData(lyr).bbox);
|
|
18317
18321
|
}
|
|
@@ -18445,10 +18449,13 @@
|
|
|
18445
18449
|
var FrameData = /*#__PURE__*/Object.freeze({
|
|
18446
18450
|
__proto__: null,
|
|
18447
18451
|
getFrameData: getFrameData,
|
|
18452
|
+
getFrameLayerData: getFrameLayerData,
|
|
18448
18453
|
getFrameSize: getFrameSize,
|
|
18454
|
+
isFrameLayer: isFrameLayer,
|
|
18449
18455
|
findFrameLayerInDataset: findFrameLayerInDataset,
|
|
18450
18456
|
findFrameDataset: findFrameDataset,
|
|
18451
18457
|
findFrameLayer: findFrameLayer,
|
|
18458
|
+
findFrame: findFrame,
|
|
18452
18459
|
getFrameLayerBounds: getFrameLayerBounds,
|
|
18453
18460
|
getMapFrameMetersPerPixel: getMapFrameMetersPerPixel,
|
|
18454
18461
|
calcOutputSizeInPixels: calcOutputSizeInPixels,
|
|
@@ -18888,6 +18895,7 @@
|
|
|
18888
18895
|
'font-family': null,
|
|
18889
18896
|
'font-size': null,
|
|
18890
18897
|
'font-style': null,
|
|
18898
|
+
'font-stretch': null,
|
|
18891
18899
|
'font-weight': null,
|
|
18892
18900
|
'label-text': null, // leaving this null
|
|
18893
18901
|
'letter-spacing': 'measure',
|
|
@@ -18937,7 +18945,7 @@
|
|
|
18937
18945
|
polyline: utils.arrayToIndex(commonProperties.concat('stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit')),
|
|
18938
18946
|
point: utils.arrayToIndex(commonProperties.concat('fill', 'r')),
|
|
18939
18947
|
label: utils.arrayToIndex(commonProperties.concat(
|
|
18940
|
-
'fill,font-family,font-size,text-anchor,font-weight,font-style,letter-spacing,dominant-baseline'.split(',')))
|
|
18948
|
+
'fill,font-family,font-size,text-anchor,font-weight,font-style,font-stretch,letter-spacing,dominant-baseline'.split(',')))
|
|
18941
18949
|
};
|
|
18942
18950
|
|
|
18943
18951
|
// symType: point, polygon, polyline, label
|
|
@@ -19270,12 +19278,12 @@
|
|
|
19270
19278
|
// Kludge for applying fill and other styles to a <text> element
|
|
19271
19279
|
// (for rendering labels in the GUI with the dot in Canvas, not SVG)
|
|
19272
19280
|
function renderStyledLabel(rec) {
|
|
19273
|
-
var o = renderLabel(rec);
|
|
19281
|
+
var o = renderLabel$1(rec);
|
|
19274
19282
|
applyStyleAttributes(o, 'label', rec);
|
|
19275
19283
|
return o;
|
|
19276
19284
|
}
|
|
19277
19285
|
|
|
19278
|
-
function renderLabel(rec) {
|
|
19286
|
+
function renderLabel$1(rec) {
|
|
19279
19287
|
var line = toLabelString(rec['label-text']);
|
|
19280
19288
|
var morelines, obj;
|
|
19281
19289
|
// Accepting \n (two chars) as an alternative to the newline character
|
|
@@ -19320,7 +19328,7 @@
|
|
|
19320
19328
|
var SvgLabels = /*#__PURE__*/Object.freeze({
|
|
19321
19329
|
__proto__: null,
|
|
19322
19330
|
renderStyledLabel: renderStyledLabel,
|
|
19323
|
-
renderLabel: renderLabel
|
|
19331
|
+
renderLabel: renderLabel$1
|
|
19324
19332
|
});
|
|
19325
19333
|
|
|
19326
19334
|
// convert data records (properties like svg-symbol, label-text, fill, r) to svg symbols
|
|
@@ -19532,13 +19540,64 @@
|
|
|
19532
19540
|
};
|
|
19533
19541
|
}
|
|
19534
19542
|
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
|
|
19539
|
-
|
|
19540
|
-
|
|
19543
|
+
function renderScalebar(d, frame) {
|
|
19544
|
+
if (!frame.crs) {
|
|
19545
|
+
message('Unable to render scalebar: unknown CRS.');
|
|
19546
|
+
return [];
|
|
19547
|
+
}
|
|
19548
|
+
if (frame.width > 0 === false) {
|
|
19549
|
+
return [];
|
|
19550
|
+
}
|
|
19551
|
+
|
|
19552
|
+
var opts = getScalebarOpts(d);
|
|
19553
|
+
var metersPerPx = getMapFrameMetersPerPixel(frame);
|
|
19554
|
+
var frameWidthPx = frame.width;
|
|
19555
|
+
var labels = d.label ? d.label.split(',') : null;
|
|
19556
|
+
var label1 = labels && labels[0] || null;
|
|
19557
|
+
var props1 = parseScalebarLabel(label1 || getAutoScalebarLabel(frameWidthPx, metersPerPx, 'mile'));
|
|
19558
|
+
var label2 = opts.style == 'b' && labels && labels[1] || null;
|
|
19559
|
+
var props2, length2;
|
|
19560
|
+
|
|
19561
|
+
if (props1.km > 0 === false) {
|
|
19562
|
+
message('Unusable scalebar label:', label1);
|
|
19563
|
+
return [];
|
|
19564
|
+
}
|
|
19565
|
+
|
|
19566
|
+
var length1 = Math.round(props1.km / metersPerPx * 1000);
|
|
19567
|
+
if (length1 > 0 === false) {
|
|
19568
|
+
stop("Null scalebar length");
|
|
19569
|
+
}
|
|
19570
|
+
|
|
19571
|
+
if (label2) {
|
|
19572
|
+
props2 = parseScalebarLabel(label2);
|
|
19573
|
+
length2 = Math.round(props2.km / metersPerPx * 1000);
|
|
19574
|
+
if (length2 > length1) {
|
|
19575
|
+
stop("First part of a dual-unit scalebar must be longer than the second part.");
|
|
19576
|
+
}
|
|
19577
|
+
}
|
|
19578
|
+
|
|
19579
|
+
var barPos = getScalebarPosition(opts);
|
|
19580
|
+
var labelPos = getLabelPosition(opts);
|
|
19581
|
+
var dx = barPos.xpos == 'right' ? frameWidthPx - length1 - opts.margin : opts.margin;
|
|
19582
|
+
var dy = barPos.ypos == 'bottom' ? frame.height - opts.margin : opts.margin;
|
|
19583
|
+
|
|
19584
|
+
// vshift to adjust for height above or below the baseline
|
|
19585
|
+
var labelHeight = Math.round(opts.label_offset + opts.tic_length + opts.font_size * 0.8 + opts.bar_width / 2);
|
|
19586
|
+
var bareHeight = Math.round(opts.bar_width / 2);
|
|
19587
|
+
var topHeight = labelPos.ypos == 'top' || label2 ? labelHeight : bareHeight;
|
|
19588
|
+
var bottomHeight = labelPos.ypos == 'bottom' || label2 ? labelHeight : bareHeight;
|
|
19589
|
+
if (barPos.ypos == 'top') {
|
|
19590
|
+
dy += topHeight;
|
|
19591
|
+
} else {
|
|
19592
|
+
dy -= bottomHeight;
|
|
19593
|
+
}
|
|
19594
|
+
|
|
19595
|
+
var g = renderAsSvg(length1, label1, length2, label2, opts);
|
|
19596
|
+
g.properties = {
|
|
19597
|
+
transform: 'translate(' + dx + ' ' + dy + ')'
|
|
19541
19598
|
};
|
|
19599
|
+
|
|
19600
|
+
return [g];
|
|
19542
19601
|
}
|
|
19543
19602
|
|
|
19544
19603
|
var styleOpts = {
|
|
@@ -19565,105 +19624,112 @@
|
|
|
19565
19624
|
return Object.assign({}, defaultOpts, styleOpts[style], d, {style: style});
|
|
19566
19625
|
}
|
|
19567
19626
|
|
|
19568
|
-
|
|
19569
|
-
|
|
19570
|
-
|
|
19571
|
-
|
|
19627
|
+
function renderAsSvg(length, text, length2, text2, opts) {
|
|
19628
|
+
var labelPart = renderLabel(text, length, opts);
|
|
19629
|
+
var zeroLabelPart = renderLabel('0', length, Object.assign({flipx: true}, opts));
|
|
19630
|
+
var barPart = renderBar(length, length2, opts);
|
|
19631
|
+
var parts = opts.style == 'b' ? [zeroLabelPart, labelPart, barPart] : [labelPart, barPart];
|
|
19632
|
+
if (text2) {
|
|
19633
|
+
parts.push(renderLabel(text2, length2, Object.assign({flipy: true}, opts)));
|
|
19634
|
+
parts.push(renderLabel('0', length2, Object.assign({flipx: true, flipy: true}, opts)));
|
|
19635
|
+
}
|
|
19636
|
+
return {
|
|
19637
|
+
tag: 'g',
|
|
19638
|
+
children: parts
|
|
19639
|
+
};
|
|
19572
19640
|
}
|
|
19573
19641
|
|
|
19574
|
-
|
|
19575
|
-
|
|
19576
|
-
var
|
|
19577
|
-
|
|
19578
|
-
|
|
19579
|
-
|
|
19580
|
-
|
|
19581
|
-
|
|
19582
|
-
|
|
19642
|
+
// TODO: generalize to other kinds of furniture as they are developed
|
|
19643
|
+
function getScalebarPosition(opts) {
|
|
19644
|
+
var pos = opts.position || 'top-left';
|
|
19645
|
+
return {
|
|
19646
|
+
ypos: pos.includes('top') ? 'top' : 'bottom',
|
|
19647
|
+
xpos: pos.includes('left') ? 'left' : 'right'
|
|
19648
|
+
};
|
|
19649
|
+
}
|
|
19650
|
+
|
|
19651
|
+
function renderLabel(text, length, opts) {
|
|
19652
|
+
var labelPos = getLabelPosition(opts);
|
|
19653
|
+
var anchorX = length * labelPos.kx + labelPos.dx;
|
|
19654
|
+
var bottomLabelY = opts.bar_width + opts.tic_length + opts.label_offset;
|
|
19655
|
+
var topLabelY = -opts.label_offset - opts.tic_length;
|
|
19656
|
+
var anchorY = labelPos.ypos == 'top' ? topLabelY : bottomLabelY;
|
|
19583
19657
|
var labelOpts = {
|
|
19584
19658
|
'label-text': text,
|
|
19585
19659
|
'font-size': opts.font_size,
|
|
19586
|
-
'text-anchor':
|
|
19587
|
-
'dominant-baseline':
|
|
19660
|
+
'text-anchor': labelPos.anchor,
|
|
19661
|
+
'dominant-baseline': labelPos.ypos == 'top' ? 'auto' : 'hanging'
|
|
19588
19662
|
//// 'dominant-baseline': labelPos == 'top' ? 'text-after-edge' : 'text-before-edge'
|
|
19589
19663
|
// 'text-after-edge' is buggy in Safari and unsupported by Illustrator,
|
|
19590
19664
|
// so I'm using 'hanging' and 'auto', which seem to be well supported.
|
|
19591
19665
|
// downside: requires a kludgy multiplier to calculate scalebar height (see above)
|
|
19592
19666
|
};
|
|
19593
|
-
|
|
19594
|
-
|
|
19595
|
-
var zeroLabel = symbolRenderers.label(zeroOpts, -xOff, anchorY);
|
|
19667
|
+
return symbolRenderers.label(labelOpts, anchorX, anchorY);
|
|
19668
|
+
}
|
|
19596
19669
|
|
|
19597
|
-
|
|
19598
|
-
var
|
|
19599
|
-
var
|
|
19600
|
-
var
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
if (opts.tic_length > 0) {
|
|
19605
|
-
coords = [[0, y2], [0, y], [length, y], [length, y2]];
|
|
19670
|
+
function getLabelPosition(opts) {
|
|
19671
|
+
var pos = opts.label_position;
|
|
19672
|
+
var ypos = pos.includes('bottom') && 'bottom' || 'top';
|
|
19673
|
+
var dx = 0;
|
|
19674
|
+
var xpos;
|
|
19675
|
+
if (opts.style == 'a') {
|
|
19676
|
+
xpos = pos.includes('center') && 'center' || pos.includes('right') && 'right' || 'left';
|
|
19606
19677
|
} else {
|
|
19607
|
-
|
|
19678
|
+
xpos = 'right'; // style b
|
|
19679
|
+
}
|
|
19680
|
+
if (opts.flipx) {
|
|
19681
|
+
xpos = xpos == 'left' && 'right' || xpos == 'right' && 'left' || xpos;
|
|
19682
|
+
}
|
|
19683
|
+
if (opts.flipy) {
|
|
19684
|
+
ypos = ypos == 'top' && 'bottom' || ypos == 'bottom' && 'top' || ypos;
|
|
19685
|
+
}
|
|
19686
|
+
if (opts.style == 'b') {
|
|
19687
|
+
dx = xpos == 'left' && -opts.font_size / 4 || xpos == 'right' && opts.font_size / 4 || 0;
|
|
19608
19688
|
}
|
|
19609
|
-
var barPart = importLineString(coords);
|
|
19610
|
-
Object.assign(barPart.properties, {
|
|
19611
|
-
stroke: 'black',
|
|
19612
|
-
fill: 'none',
|
|
19613
|
-
'stroke-width': opts.bar_width,
|
|
19614
|
-
'stroke-linecap': 'butt',
|
|
19615
|
-
'stroke-linejoin': 'miter'
|
|
19616
|
-
});
|
|
19617
|
-
var parts = opts.style == 'b' ? [zeroLabel, labelPart, barPart] : [labelPart, barPart];
|
|
19618
19689
|
return {
|
|
19619
|
-
|
|
19620
|
-
|
|
19690
|
+
xpos,
|
|
19691
|
+
ypos,
|
|
19692
|
+
dx,
|
|
19693
|
+
kx: xpos == 'right' && 1 || xpos == 'center' && 0.5 || 0,
|
|
19694
|
+
anchor: xpos == 'center' && 'middle' || xpos == 'left' && 'start' || 'end'
|
|
19621
19695
|
};
|
|
19622
19696
|
}
|
|
19623
19697
|
|
|
19624
|
-
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
19631
|
-
|
|
19632
|
-
|
|
19633
|
-
var opts = getScalebarOpts(d);
|
|
19634
|
-
var metersPerPx = getMapFrameMetersPerPixel(frame);
|
|
19635
|
-
var frameWidthPx = frame.width;
|
|
19636
|
-
var unit = d.label ? parseScalebarUnits(d.label) : 'mile';
|
|
19637
|
-
var number = d.label ? parseScalebarNumber(d.label) : null;
|
|
19638
|
-
var label = number && unit ? d.label : getAutoScalebarLabel(frameWidthPx, metersPerPx, unit);
|
|
19639
|
-
|
|
19640
|
-
var scalebarKm = parseScalebarLabelToKm(label);
|
|
19641
|
-
if (scalebarKm > 0 === false) {
|
|
19642
|
-
message('Unusable scalebar label:', label);
|
|
19643
|
-
return [];
|
|
19698
|
+
// length1: length of main bar
|
|
19699
|
+
// length2: length of optional second distance (assumes that length2 <= length1)
|
|
19700
|
+
function getStyleBCoords(length1, length2, opts) {
|
|
19701
|
+
var coords = [];
|
|
19702
|
+
var labelPos = getLabelPosition(opts);
|
|
19703
|
+
var y = opts.tic_length + opts.bar_width / 2;
|
|
19704
|
+
if (labelPos.ypos == "top") {
|
|
19705
|
+
y = -y;
|
|
19644
19706
|
}
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
19648
|
-
|
|
19707
|
+
coords.push([[0, y], [0, 0], [length1, 0], [length1, y]]);
|
|
19708
|
+
if (length2 > 0) {
|
|
19709
|
+
coords.push([[0, 0], [0, -y]]);
|
|
19710
|
+
coords.push([[length2, 0], [length2, -y]]);
|
|
19649
19711
|
}
|
|
19712
|
+
return coords;
|
|
19713
|
+
}
|
|
19650
19714
|
|
|
19651
|
-
|
|
19652
|
-
|
|
19653
|
-
|
|
19654
|
-
var
|
|
19655
|
-
if (opts.
|
|
19656
|
-
|
|
19715
|
+
// length: length of scale bar in px
|
|
19716
|
+
// length2: length of optional dual-units portion of the scalebar
|
|
19717
|
+
function renderBar(length, length2, opts) {
|
|
19718
|
+
var coords;
|
|
19719
|
+
if (opts.style == 'b') {
|
|
19720
|
+
coords = getStyleBCoords(length, length2, opts);
|
|
19657
19721
|
} else {
|
|
19658
|
-
|
|
19722
|
+
coords = [[[0, 0], [length, 0]]];
|
|
19659
19723
|
}
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19664
|
-
|
|
19665
|
-
|
|
19666
|
-
|
|
19724
|
+
var bar = importMultiLineString(coords);
|
|
19725
|
+
Object.assign(bar.properties, {
|
|
19726
|
+
stroke: 'black',
|
|
19727
|
+
fill: 'none',
|
|
19728
|
+
'stroke-width': opts.bar_width,
|
|
19729
|
+
'stroke-linecap': 'butt',
|
|
19730
|
+
'stroke-linejoin': 'miter'
|
|
19731
|
+
});
|
|
19732
|
+
return bar;
|
|
19667
19733
|
}
|
|
19668
19734
|
|
|
19669
19735
|
// unit: 'km' || 'mile'
|
|
@@ -19697,6 +19763,20 @@
|
|
|
19697
19763
|
return units == 'mile' ? value * 1.60934 : value;
|
|
19698
19764
|
}
|
|
19699
19765
|
|
|
19766
|
+
function parseScalebarLabel(label) {
|
|
19767
|
+
var num = label ? parseScalebarNumber(label) : null;
|
|
19768
|
+
var units = label ? parseScalebarUnits(label) : 'mile';
|
|
19769
|
+
var km = NaN;
|
|
19770
|
+
if (units && num) {
|
|
19771
|
+
km = units == 'mile' ? num * 1.60934 : num;
|
|
19772
|
+
}
|
|
19773
|
+
return {
|
|
19774
|
+
number: num,
|
|
19775
|
+
units: units,
|
|
19776
|
+
km: km
|
|
19777
|
+
};
|
|
19778
|
+
}
|
|
19779
|
+
|
|
19700
19780
|
function parseScalebarUnits(str) {
|
|
19701
19781
|
var isMiles = /miles?$/.test(str.toLowerCase());
|
|
19702
19782
|
var isKm = /(k\.m\.|km|kilometers?|kilometres?)$/.test(str.toLowerCase());
|
|
@@ -19725,84 +19805,9 @@
|
|
|
19725
19805
|
parseScalebarLabelToKm: parseScalebarLabelToKm
|
|
19726
19806
|
});
|
|
19727
19807
|
|
|
19728
|
-
cmd.frame = function(catalog, source, opts) {
|
|
19729
|
-
var size, bounds, tmp, dataset;
|
|
19730
|
-
if (+opts.width > 0 === false && +opts.pixels > 0 === false) {
|
|
19731
|
-
stop("Missing a width or area");
|
|
19732
|
-
}
|
|
19733
|
-
if (opts.width && opts.height) {
|
|
19734
|
-
opts = utils.extend({}, opts);
|
|
19735
|
-
// Height is a string containing either a number or a
|
|
19736
|
-
// comma-sep. pair of numbers (range); here we convert height to
|
|
19737
|
-
// an aspect-ratio parameter for the rectangle() function
|
|
19738
|
-
opts.aspect_ratio = getAspectRatioArg(opts.width, opts.height);
|
|
19739
|
-
// TODO: currently returns max,min aspect ratio, should return in min,max order
|
|
19740
|
-
// (rectangle() function should handle max,min argument correctly now anyway)
|
|
19741
|
-
}
|
|
19742
|
-
tmp = cmd.rectangle(source, opts);
|
|
19743
|
-
bounds = getDatasetBounds(tmp);
|
|
19744
|
-
if (probablyDecimalDegreeBounds(bounds)) {
|
|
19745
|
-
stop('Frames require projected, not geographical coordinates');
|
|
19746
|
-
} else if (!getDatasetCRS(tmp)) {
|
|
19747
|
-
message('Warning: missing projection data. Assuming coordinates are meters and k (scale factor) is 1');
|
|
19748
|
-
}
|
|
19749
|
-
size = getFrameSize(bounds, opts);
|
|
19750
|
-
if (size[0] > 0 === false) {
|
|
19751
|
-
stop('Missing a valid frame width');
|
|
19752
|
-
}
|
|
19753
|
-
if (size[1] > 0 === false) {
|
|
19754
|
-
stop('Missing a valid frame height');
|
|
19755
|
-
}
|
|
19756
|
-
dataset = {info: {}, layers:[{
|
|
19757
|
-
name: opts.name || 'frame',
|
|
19758
|
-
data: new DataTable([{
|
|
19759
|
-
width: size[0],
|
|
19760
|
-
height: size[1],
|
|
19761
|
-
bbox: bounds.toArray(),
|
|
19762
|
-
type: 'frame'
|
|
19763
|
-
}])
|
|
19764
|
-
}]};
|
|
19765
|
-
catalog.addDataset(dataset);
|
|
19766
|
-
};
|
|
19767
|
-
|
|
19768
|
-
|
|
19769
|
-
// Convert width and height args to aspect ratio arg for the rectangle() function
|
|
19770
|
-
function getAspectRatioArg(widthArg, heightArg) {
|
|
19771
|
-
// heightArg is a string containing either a number or a
|
|
19772
|
-
// comma-sep. pair of numbers (range);
|
|
19773
|
-
return heightArg.split(',').map(function(opt) {
|
|
19774
|
-
var height = Number(opt),
|
|
19775
|
-
width = Number(widthArg);
|
|
19776
|
-
if (!opt) return '';
|
|
19777
|
-
return width / height;
|
|
19778
|
-
}).reverse().join(',');
|
|
19779
|
-
}
|
|
19780
|
-
|
|
19781
|
-
|
|
19782
|
-
function renderFrame(d) {
|
|
19783
|
-
var lineWidth = 1,
|
|
19784
|
-
// inset stroke by half of line width
|
|
19785
|
-
off = lineWidth / 2,
|
|
19786
|
-
obj = importPolygon([[[off, off], [off, d.height - off],
|
|
19787
|
-
[d.width - off, d.height - off],
|
|
19788
|
-
[d.width - off, off], [off, off]]]);
|
|
19789
|
-
utils.extend(obj.properties, {
|
|
19790
|
-
fill: 'none',
|
|
19791
|
-
stroke: d.stroke || 'black',
|
|
19792
|
-
'stroke-width': d['stroke-width'] || lineWidth
|
|
19793
|
-
});
|
|
19794
|
-
return [obj];
|
|
19795
|
-
}
|
|
19796
|
-
|
|
19797
|
-
var Frame = /*#__PURE__*/Object.freeze({
|
|
19798
|
-
__proto__: null,
|
|
19799
|
-
getAspectRatioArg: getAspectRatioArg,
|
|
19800
|
-
renderFrame: renderFrame
|
|
19801
|
-
});
|
|
19802
|
-
|
|
19803
19808
|
var furnitureRenderers = {
|
|
19804
|
-
scalebar: renderScalebar
|
|
19805
|
-
frame: renderFrame
|
|
19809
|
+
scalebar: renderScalebar
|
|
19810
|
+
// frame: renderFrame
|
|
19806
19811
|
};
|
|
19807
19812
|
|
|
19808
19813
|
// @lyr a layer in a dataset
|
|
@@ -25185,15 +25190,15 @@ ${svg}
|
|
|
25185
25190
|
.validate(validateProjOpts);
|
|
25186
25191
|
|
|
25187
25192
|
parser.command('rectangle')
|
|
25188
|
-
.describe('create a rectangle from a bbox or target layer
|
|
25193
|
+
.describe('create a rectangle from a bbox or target layer')
|
|
25189
25194
|
.option('bbox', {
|
|
25190
25195
|
describe: 'rectangle coordinates (xmin,ymin,xmax,ymax)',
|
|
25191
25196
|
type: 'bbox'
|
|
25192
25197
|
})
|
|
25193
25198
|
.option('offset', offsetOpt)
|
|
25194
25199
|
.option('width', {
|
|
25195
|
-
|
|
25196
|
-
type: 'number'
|
|
25200
|
+
describe: 'set width of map in pixels, use rectangle as frame'
|
|
25201
|
+
// type: 'number' // use string, to allow units (e.g. in, px, pt)
|
|
25197
25202
|
})
|
|
25198
25203
|
.option('aspect-ratio', aspectRatioOpt)
|
|
25199
25204
|
.option('source', {
|
|
@@ -25470,7 +25475,10 @@ ${svg}
|
|
|
25470
25475
|
.option('font-style', {
|
|
25471
25476
|
describe: 'CSS font style property of labels (e.g. italic)'
|
|
25472
25477
|
})
|
|
25473
|
-
|
|
25478
|
+
.option('font-stretch', {
|
|
25479
|
+
describe: 'CSS font stretch property of labels (e.g. condensed)'
|
|
25480
|
+
})
|
|
25481
|
+
.option('letter-spacing', {
|
|
25474
25482
|
describe: 'CSS letter-spacing property of labels'
|
|
25475
25483
|
})
|
|
25476
25484
|
.option('line-height', {
|
|
@@ -25762,20 +25770,20 @@ ${svg}
|
|
|
25762
25770
|
describe: 'frame coordinates (xmin,ymin,xmax,ymax)',
|
|
25763
25771
|
type: 'bbox'
|
|
25764
25772
|
})
|
|
25765
|
-
.option('offset', offsetOpt)
|
|
25773
|
+
// .option('offset', offsetOpt)
|
|
25766
25774
|
.option('width', {
|
|
25767
|
-
describe: '
|
|
25768
|
-
})
|
|
25769
|
-
.option('height', {
|
|
25770
|
-
describe: 'pixel height of output (may be a range)'
|
|
25771
|
-
})
|
|
25772
|
-
.option('pixels', {
|
|
25773
|
-
describe: 'area of output in pixels (alternative to width and height)',
|
|
25774
|
-
type: 'number'
|
|
25775
|
-
})
|
|
25776
|
-
.option('source', {
|
|
25777
|
-
describe: 'name of layer to enclose'
|
|
25775
|
+
describe: 'width of output (default is 800px)'
|
|
25778
25776
|
})
|
|
25777
|
+
// .option('height', {
|
|
25778
|
+
// describe: 'pixel height of output (may be a range)'
|
|
25779
|
+
// })
|
|
25780
|
+
// .option('pixels', {
|
|
25781
|
+
// describe: 'area of output in pixels (alternative to width and height)',
|
|
25782
|
+
// type: 'number'
|
|
25783
|
+
// })
|
|
25784
|
+
// .option('source', {
|
|
25785
|
+
// describe: 'name of layer to enclose'
|
|
25786
|
+
// })
|
|
25779
25787
|
.option('name', nameOpt);
|
|
25780
25788
|
|
|
25781
25789
|
parser.command('fuzzy-join')
|
|
@@ -25889,7 +25897,11 @@ ${svg}
|
|
|
25889
25897
|
describe: 'e.g. bottom-right (default is top-left)'
|
|
25890
25898
|
})
|
|
25891
25899
|
.option('label-position', {
|
|
25892
|
-
describe: 'top
|
|
25900
|
+
describe: 'top, bottom, top-center (style a), etc'
|
|
25901
|
+
})
|
|
25902
|
+
.option('dual-units', {
|
|
25903
|
+
// describe: 'display both metric and imperial units',
|
|
25904
|
+
type: 'flag'
|
|
25893
25905
|
})
|
|
25894
25906
|
.option('margin', {
|
|
25895
25907
|
describe: 'offset in pixels from edge of map',
|
|
@@ -37774,6 +37786,79 @@ ${svg}
|
|
|
37774
37786
|
return parsed[0];
|
|
37775
37787
|
}
|
|
37776
37788
|
|
|
37789
|
+
cmd.frame = function(catalog, source, opts) {
|
|
37790
|
+
var size, bounds, tmp, dataset;
|
|
37791
|
+
if (+opts.width > 0 === false && +opts.pixels > 0 === false) {
|
|
37792
|
+
stop("Missing a width or area");
|
|
37793
|
+
}
|
|
37794
|
+
if (opts.width && opts.height) {
|
|
37795
|
+
opts = utils.extend({}, opts);
|
|
37796
|
+
// Height is a string containing either a number or a
|
|
37797
|
+
// comma-sep. pair of numbers (range); here we convert height to
|
|
37798
|
+
// an aspect-ratio parameter for the rectangle() function
|
|
37799
|
+
opts.aspect_ratio = getAspectRatioArg(opts.width, opts.height);
|
|
37800
|
+
// TODO: currently returns max,min aspect ratio, should return in min,max order
|
|
37801
|
+
// (rectangle() function should handle max,min argument correctly now anyway)
|
|
37802
|
+
}
|
|
37803
|
+
tmp = cmd.rectangle(source, opts);
|
|
37804
|
+
bounds = getDatasetBounds(tmp);
|
|
37805
|
+
if (probablyDecimalDegreeBounds(bounds)) {
|
|
37806
|
+
stop('Frames require projected, not geographical coordinates');
|
|
37807
|
+
} else if (!getDatasetCRS(tmp)) {
|
|
37808
|
+
message('Warning: missing projection data. Assuming coordinates are meters and k (scale factor) is 1');
|
|
37809
|
+
}
|
|
37810
|
+
size = getFrameSize(bounds, opts);
|
|
37811
|
+
if (size[0] > 0 === false) {
|
|
37812
|
+
stop('Missing a valid frame width');
|
|
37813
|
+
}
|
|
37814
|
+
if (size[1] > 0 === false) {
|
|
37815
|
+
stop('Missing a valid frame height');
|
|
37816
|
+
}
|
|
37817
|
+
dataset = {info: {}, layers:[{
|
|
37818
|
+
name: opts.name || 'frame',
|
|
37819
|
+
data: new DataTable([{
|
|
37820
|
+
width: size[0],
|
|
37821
|
+
height: size[1],
|
|
37822
|
+
bbox: bounds.toArray(),
|
|
37823
|
+
type: 'frame'
|
|
37824
|
+
}])
|
|
37825
|
+
}]};
|
|
37826
|
+
catalog.addDataset(dataset);
|
|
37827
|
+
};
|
|
37828
|
+
|
|
37829
|
+
|
|
37830
|
+
// Convert width and height args to aspect ratio arg for the rectangle() function
|
|
37831
|
+
function getAspectRatioArg(widthArg, heightArg) {
|
|
37832
|
+
// heightArg is a string containing either a number or a
|
|
37833
|
+
// comma-sep. pair of numbers (range);
|
|
37834
|
+
return heightArg.split(',').map(function(opt) {
|
|
37835
|
+
var height = Number(opt),
|
|
37836
|
+
width = Number(widthArg);
|
|
37837
|
+
if (!opt) return '';
|
|
37838
|
+
return width / height;
|
|
37839
|
+
}).reverse().join(',');
|
|
37840
|
+
}
|
|
37841
|
+
|
|
37842
|
+
// export function renderFrame(d) {
|
|
37843
|
+
// var lineWidth = 1,
|
|
37844
|
+
// // inset stroke by half of line width
|
|
37845
|
+
// off = lineWidth / 2,
|
|
37846
|
+
// obj = importPolygon([[[off, off], [off, d.height - off],
|
|
37847
|
+
// [d.width - off, d.height - off],
|
|
37848
|
+
// [d.width - off, off], [off, off]]]);
|
|
37849
|
+
// utils.extend(obj.properties, {
|
|
37850
|
+
// fill: 'none',
|
|
37851
|
+
// stroke: d.stroke || 'black',
|
|
37852
|
+
// 'stroke-width': d['stroke-width'] || lineWidth
|
|
37853
|
+
// });
|
|
37854
|
+
// return [obj];
|
|
37855
|
+
// }
|
|
37856
|
+
|
|
37857
|
+
var Frame = /*#__PURE__*/Object.freeze({
|
|
37858
|
+
__proto__: null,
|
|
37859
|
+
getAspectRatioArg: getAspectRatioArg
|
|
37860
|
+
});
|
|
37861
|
+
|
|
37777
37862
|
cmd.filterIslands = function(lyr, dataset, optsArg) {
|
|
37778
37863
|
var opts = utils.extend({sliver_control: 0}, optsArg); // no sliver control
|
|
37779
37864
|
var arcs = dataset.arcs;
|
|
@@ -38540,6 +38625,13 @@ ${svg}
|
|
|
38540
38625
|
// Create rectangles around one or more target layers
|
|
38541
38626
|
//
|
|
38542
38627
|
cmd.rectangle2 = function(target, opts) {
|
|
38628
|
+
// if target layer is a rectangle and we're applying frame properties,
|
|
38629
|
+
// turn the target into a frame instead of creating a new rectangle
|
|
38630
|
+
if (target.layers.length == 1 && opts.width &&
|
|
38631
|
+
layerIsRectangle(target.layers[0], target.dataset.arcs)) {
|
|
38632
|
+
applyFrameProperties(target.layers[0], opts);
|
|
38633
|
+
return;
|
|
38634
|
+
}
|
|
38543
38635
|
var datasets = target.layers.map(function(lyr) {
|
|
38544
38636
|
var dataset = cmd.rectangle({layer: lyr, dataset: target.dataset}, opts);
|
|
38545
38637
|
setOutputLayerName(dataset.layers[0], lyr, null, opts);
|
|
@@ -38569,16 +38661,21 @@ ${svg}
|
|
|
38569
38661
|
properties: {},
|
|
38570
38662
|
geometry: bboxToPolygon(bounds.toArray(), opts)
|
|
38571
38663
|
};
|
|
38572
|
-
if (opts.width > 0) {
|
|
38573
|
-
feature.properties.width = opts.width;
|
|
38574
|
-
feature.properties.type = 'frame';
|
|
38575
|
-
}
|
|
38576
38664
|
var dataset = importGeoJSON(feature, {});
|
|
38665
|
+
applyFrameProperties(dataset.layers[0], opts);
|
|
38577
38666
|
dataset.layers[0].name = opts.name || 'rectangle';
|
|
38578
38667
|
setDatasetCrsInfo(dataset, crsInfo);
|
|
38579
38668
|
return dataset;
|
|
38580
38669
|
};
|
|
38581
38670
|
|
|
38671
|
+
function applyFrameProperties(lyr, opts) {
|
|
38672
|
+
if (!opts.width) return;
|
|
38673
|
+
if (!lyr.data) initDataTable(lyr);
|
|
38674
|
+
var d = lyr.data.getRecords()[0] || {};
|
|
38675
|
+
d.width = parseSizeParam(opts.width);
|
|
38676
|
+
d.type = 'frame';
|
|
38677
|
+
}
|
|
38678
|
+
|
|
38582
38679
|
function applyRectangleOptions(bounds, crs, opts) {
|
|
38583
38680
|
var isGeoBox = probablyDecimalDegreeBounds(bounds);
|
|
38584
38681
|
if (opts.offset) {
|
|
@@ -45207,7 +45304,7 @@ ${svg}
|
|
|
45207
45304
|
});
|
|
45208
45305
|
}
|
|
45209
45306
|
|
|
45210
|
-
var version = "0.6.
|
|
45307
|
+
var version = "0.6.68";
|
|
45211
45308
|
|
|
45212
45309
|
// Parse command line args into commands and run them
|
|
45213
45310
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|