mapshaper 0.6.62 → 0.6.65
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 +506 -390
- package/package.json +1 -1
- package/www/mapshaper-gui.js +119 -7
- package/www/mapshaper.js +506 -390
- package/www/page.css +9 -0
package/www/mapshaper.js
CHANGED
|
@@ -4122,6 +4122,30 @@
|
|
|
4122
4122
|
}
|
|
4123
4123
|
};
|
|
4124
4124
|
|
|
4125
|
+
// TODO: make this stricter (could give false positive on some degenerate paths)
|
|
4126
|
+
function pathIsRectangle(ids, arcs) {
|
|
4127
|
+
var bbox = arcs.getSimpleShapeBounds(ids).toArray();
|
|
4128
|
+
var iter = arcs.getShapeIter(ids);
|
|
4129
|
+
while (iter.hasNext()) {
|
|
4130
|
+
if (iter.x != bbox[0] && iter.x != bbox[2] ||
|
|
4131
|
+
iter.y != bbox[1] && iter.y != bbox[3]) {
|
|
4132
|
+
return false;
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
return true;
|
|
4136
|
+
}
|
|
4137
|
+
|
|
4138
|
+
function bboxToCoords(bbox) {
|
|
4139
|
+
return [[bbox[0], bbox[1]], [bbox[0], bbox[3]], [bbox[2], bbox[3]],
|
|
4140
|
+
[bbox[2], bbox[1]], [bbox[0], bbox[1]]];
|
|
4141
|
+
}
|
|
4142
|
+
|
|
4143
|
+
var RectangleGeom = /*#__PURE__*/Object.freeze({
|
|
4144
|
+
__proto__: null,
|
|
4145
|
+
pathIsRectangle: pathIsRectangle,
|
|
4146
|
+
bboxToCoords: bboxToCoords
|
|
4147
|
+
});
|
|
4148
|
+
|
|
4125
4149
|
// Insert a column of values into a (new or existing) data field
|
|
4126
4150
|
function insertFieldValues(lyr, fieldName, values) {
|
|
4127
4151
|
var size = getFeatureCount(lyr) || values.length,
|
|
@@ -4162,6 +4186,15 @@
|
|
|
4162
4186
|
return lyr.geometry_type == 'point' && layerHasNonNullShapes(lyr);
|
|
4163
4187
|
}
|
|
4164
4188
|
|
|
4189
|
+
function layerOnlyHasRectangles(lyr, arcs) {
|
|
4190
|
+
if (!layerHasPaths(lyr)) return false;
|
|
4191
|
+
if (countMultiPartFeatures(lyr) > 0) return false;
|
|
4192
|
+
return lyr.shapes.every(function(shp) {
|
|
4193
|
+
if (!shp) return true;
|
|
4194
|
+
return pathIsRectangle(shp[0], arcs);
|
|
4195
|
+
});
|
|
4196
|
+
}
|
|
4197
|
+
|
|
4165
4198
|
function layerHasNonNullShapes(lyr) {
|
|
4166
4199
|
return utils.some(lyr.shapes || [], function(shp) {
|
|
4167
4200
|
return !!shp;
|
|
@@ -4405,6 +4438,7 @@
|
|
|
4405
4438
|
layerHasGeometry: layerHasGeometry,
|
|
4406
4439
|
layerHasPaths: layerHasPaths,
|
|
4407
4440
|
layerHasPoints: layerHasPoints,
|
|
4441
|
+
layerOnlyHasRectangles: layerOnlyHasRectangles,
|
|
4408
4442
|
layerHasNonNullShapes: layerHasNonNullShapes,
|
|
4409
4443
|
deleteFeatureById: deleteFeatureById,
|
|
4410
4444
|
transformPointsInLayer: transformPointsInLayer,
|
|
@@ -5002,10 +5036,10 @@
|
|
|
5002
5036
|
// x, y: a point location in projected coordinates
|
|
5003
5037
|
// Returns k, the ratio of coordinate distance to distance on the ground
|
|
5004
5038
|
function getScaleFactorAtXY(x, y, crs) {
|
|
5005
|
-
var dist = 1;
|
|
5039
|
+
var dist = 1 / crs.to_meter;
|
|
5006
5040
|
var lp = mproj.pj_inv_deg({x: x, y: y}, crs);
|
|
5007
5041
|
var lp2 = mproj.pj_inv_deg({x: x + dist, y: y}, crs);
|
|
5008
|
-
var k =
|
|
5042
|
+
var k = 1 / geom.greatCircleDistance(lp.lam, lp.phi, lp2.lam, lp2.phi);
|
|
5009
5043
|
return k;
|
|
5010
5044
|
}
|
|
5011
5045
|
|
|
@@ -11058,7 +11092,7 @@
|
|
|
11058
11092
|
// File looks like an importable file type
|
|
11059
11093
|
// name: filename or path
|
|
11060
11094
|
function looksLikeImportableFile(name) {
|
|
11061
|
-
return !!guessInputFileType(name);
|
|
11095
|
+
return !!guessInputFileType(name) || isImportableAsBinary(name);
|
|
11062
11096
|
}
|
|
11063
11097
|
|
|
11064
11098
|
// File looks like a directly readable data file type
|
|
@@ -13419,7 +13453,7 @@
|
|
|
13419
13453
|
|
|
13420
13454
|
// Accepts a single value or a list of four values. List order is l,b,t,r
|
|
13421
13455
|
function convertFourSides(opt, crs, bounds) {
|
|
13422
|
-
var arr = opt.split(',');
|
|
13456
|
+
var arr = opt.includes(',') ? opt.split(',') : opt.split(' ');
|
|
13423
13457
|
if (arr.length == 1) {
|
|
13424
13458
|
arr = [arr[0], arr[0], arr[0], arr[0]];
|
|
13425
13459
|
} else if (arr.length != 4) {
|
|
@@ -19407,99 +19441,136 @@
|
|
|
19407
19441
|
}
|
|
19408
19442
|
|
|
19409
19443
|
// TODO: generalize to other kinds of furniture as they are developed
|
|
19410
|
-
function getScalebarPosition(
|
|
19411
|
-
var
|
|
19412
|
-
|
|
19413
|
-
|
|
19414
|
-
|
|
19415
|
-
hoffs: 10
|
|
19444
|
+
function getScalebarPosition(opts) {
|
|
19445
|
+
var pos = opts.position || 'top-left';
|
|
19446
|
+
return {
|
|
19447
|
+
valign: pos.includes('top') ? 'top' : 'bottom',
|
|
19448
|
+
halign: pos.includes('left') ? 'left' : 'right'
|
|
19416
19449
|
};
|
|
19417
|
-
|
|
19418
|
-
|
|
19450
|
+
}
|
|
19451
|
+
|
|
19452
|
+
var styleOpts = {
|
|
19453
|
+
a: {
|
|
19454
|
+
bar_width: 3,
|
|
19455
|
+
tic_length: 0
|
|
19456
|
+
},
|
|
19457
|
+
b: {
|
|
19458
|
+
bar_width: 1,
|
|
19459
|
+
tic_length: 5
|
|
19419
19460
|
}
|
|
19420
|
-
|
|
19421
|
-
|
|
19461
|
+
};
|
|
19462
|
+
|
|
19463
|
+
var defaultOpts = {
|
|
19464
|
+
position: 'top-left',
|
|
19465
|
+
label_position: 'top',
|
|
19466
|
+
label_offset: 4,
|
|
19467
|
+
font_size: 12,
|
|
19468
|
+
margin: 12
|
|
19469
|
+
};
|
|
19470
|
+
|
|
19471
|
+
function getScalebarOpts(d) {
|
|
19472
|
+
var style = d.style == 'b' || d.style == 'B' ? 'b' : 'a';
|
|
19473
|
+
return Object.assign({}, defaultOpts, styleOpts[style], d, {style: style});
|
|
19474
|
+
}
|
|
19475
|
+
|
|
19476
|
+
// approximate pixel height of the scalebar
|
|
19477
|
+
function getScalebarHeight(opts) {
|
|
19478
|
+
return Math.round(opts.bar_width + opts.label_offset +
|
|
19479
|
+
opts.tic_length + opts.font_size * 0.8);
|
|
19480
|
+
}
|
|
19481
|
+
|
|
19482
|
+
function renderAsSvg(length, text, opts) {
|
|
19483
|
+
// label part
|
|
19484
|
+
var xOff = opts.style == 'b' ? Math.round(opts.font_size / 4) : 0;
|
|
19485
|
+
var alignLeft = opts.style == 'a' && opts.position.includes('left');
|
|
19486
|
+
var anchorX = alignLeft ? -xOff : length + xOff;
|
|
19487
|
+
var anchorY = opts.bar_width + + opts.tic_length + opts.label_offset;
|
|
19488
|
+
if (opts.label_position == 'top') {
|
|
19489
|
+
anchorY = -opts.label_offset - opts.tic_length;
|
|
19422
19490
|
}
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
|
|
19491
|
+
var labelOpts = {
|
|
19492
|
+
'label-text': text,
|
|
19493
|
+
'font-size': opts.font_size,
|
|
19494
|
+
'text-anchor': alignLeft ? 'start': 'end',
|
|
19495
|
+
'dominant-baseline': opts.label_position == 'top' ? 'auto' : 'hanging'
|
|
19496
|
+
//// 'dominant-baseline': labelPos == 'top' ? 'text-after-edge' : 'text-before-edge'
|
|
19497
|
+
// 'text-after-edge' is buggy in Safari and unsupported by Illustrator,
|
|
19498
|
+
// so I'm using 'hanging' and 'auto', which seem to be well supported.
|
|
19499
|
+
// downside: requires a kludgy multiplier to calculate scalebar height (see above)
|
|
19500
|
+
};
|
|
19501
|
+
var labelPart = symbolRenderers.label(labelOpts, anchorX, anchorY);
|
|
19502
|
+
var zeroOpts = Object.assign({}, labelOpts, {'label-text': '0', 'text-anchor': 'start'});
|
|
19503
|
+
var zeroLabel = symbolRenderers.label(zeroOpts, -xOff, anchorY);
|
|
19504
|
+
|
|
19505
|
+
// bar part
|
|
19506
|
+
var y = 0;
|
|
19507
|
+
var y2 = opts.tic_length + opts.bar_width / 2;
|
|
19508
|
+
var coords;
|
|
19509
|
+
if (opts.label_position == "top") {
|
|
19510
|
+
y2 = -y2;
|
|
19426
19511
|
}
|
|
19427
|
-
if (
|
|
19428
|
-
|
|
19429
|
-
|
|
19512
|
+
if (opts.tic_length > 0) {
|
|
19513
|
+
coords = [[0, y2], [0, y], [length, y], [length, y2]];
|
|
19514
|
+
} else {
|
|
19515
|
+
coords = [[0, y], [length, y]];
|
|
19430
19516
|
}
|
|
19431
|
-
|
|
19517
|
+
var barPart = importLineString(coords);
|
|
19518
|
+
Object.assign(barPart.properties, {
|
|
19519
|
+
stroke: 'black',
|
|
19520
|
+
fill: 'none',
|
|
19521
|
+
'stroke-width': opts.bar_width,
|
|
19522
|
+
'stroke-linecap': 'butt',
|
|
19523
|
+
'stroke-linejoin': 'miter'
|
|
19524
|
+
});
|
|
19525
|
+
var parts = opts.style == 'b' ? [zeroLabel, labelPart, barPart] : [labelPart, barPart];
|
|
19526
|
+
return {
|
|
19527
|
+
tag: 'g',
|
|
19528
|
+
children: parts
|
|
19529
|
+
};
|
|
19432
19530
|
}
|
|
19433
19531
|
|
|
19434
19532
|
function renderScalebar(d, frame) {
|
|
19435
|
-
|
|
19533
|
+
if (!frame.crs) {
|
|
19534
|
+
message('Unable to render scalebar: unknown CRS.');
|
|
19535
|
+
return [];
|
|
19536
|
+
}
|
|
19537
|
+
if (frame.width > 0 === false) {
|
|
19538
|
+
return [];
|
|
19539
|
+
}
|
|
19540
|
+
|
|
19541
|
+
var opts = getScalebarOpts(d);
|
|
19436
19542
|
var metersPerPx = getMapFrameMetersPerPixel(frame);
|
|
19437
19543
|
var frameWidthPx = frame.width;
|
|
19438
19544
|
var unit = d.label ? parseScalebarUnits(d.label) : 'mile';
|
|
19439
19545
|
var number = d.label ? parseScalebarNumber(d.label) : null;
|
|
19440
19546
|
var label = number && unit ? d.label : getAutoScalebarLabel(frameWidthPx, metersPerPx, unit);
|
|
19441
|
-
var scalebarKm = parseScalebarLabelToKm(label);
|
|
19442
|
-
var barHeight = 3;
|
|
19443
|
-
var labelOffs = 4;
|
|
19444
|
-
var fontSize = +d.font_size || 12;
|
|
19445
|
-
var width = Math.round(scalebarKm / metersPerPx * 1000);
|
|
19446
|
-
var height = Math.round(barHeight + labelOffs + fontSize * 0.8);
|
|
19447
|
-
var labelPos = d.label_position == 'top' ? 'top' : 'bottom';
|
|
19448
|
-
var anchorX = pos.halign == 'left' ? 0 : width;
|
|
19449
|
-
var anchorY = barHeight + labelOffs;
|
|
19450
|
-
var dx = pos.halign == 'right' ? frameWidthPx - width - pos.hoffs : pos.hoffs;
|
|
19451
|
-
var dy = pos.valign == 'bottom' ? frame.height - height - pos.voffs : pos.voffs;
|
|
19452
19547
|
|
|
19548
|
+
var scalebarKm = parseScalebarLabelToKm(label);
|
|
19453
19549
|
if (scalebarKm > 0 === false) {
|
|
19454
19550
|
message('Unusable scalebar label:', label);
|
|
19455
19551
|
return [];
|
|
19456
19552
|
}
|
|
19457
19553
|
|
|
19458
|
-
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19462
|
-
if (!frame.crs) {
|
|
19463
|
-
message('Unable to render scalebar: unknown CRS.');
|
|
19464
|
-
return [];
|
|
19554
|
+
var width = Math.round(scalebarKm / metersPerPx * 1000);
|
|
19555
|
+
if (width > 0 === false) {
|
|
19556
|
+
stop("Null scalebar length");
|
|
19465
19557
|
}
|
|
19466
19558
|
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19559
|
+
var pos = getScalebarPosition(opts);
|
|
19560
|
+
var height = getScalebarHeight(opts);
|
|
19561
|
+
var dx = pos.halign == 'right' ? frameWidthPx - width - opts.margin : opts.margin;
|
|
19562
|
+
var dy = pos.valign == 'bottom' ? frame.height - height - opts.margin : opts.margin;
|
|
19563
|
+
if (opts.label_position == 'top') {
|
|
19564
|
+
dy += Math.round(opts.label_offset + opts.tic_length + opts.font_size * 0.8 + opts.bar_width / 2);
|
|
19565
|
+
} else {
|
|
19566
|
+
dy += Math.round(opts.bar_width / 2);
|
|
19470
19567
|
}
|
|
19471
19568
|
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
19475
|
-
var barObj = {
|
|
19476
|
-
tag: 'rect',
|
|
19477
|
-
properties: {
|
|
19478
|
-
fill: 'black',
|
|
19479
|
-
x: 0,
|
|
19480
|
-
y: 0,
|
|
19481
|
-
width: width,
|
|
19482
|
-
height: barHeight
|
|
19483
|
-
}
|
|
19484
|
-
};
|
|
19485
|
-
var labelOpts = {
|
|
19486
|
-
'label-text': label,
|
|
19487
|
-
'font-size': fontSize,
|
|
19488
|
-
'text-anchor': pos.halign == 'left' ? 'start': 'end',
|
|
19489
|
-
'dominant-baseline': labelPos == 'top' ? 'auto' : 'hanging'
|
|
19490
|
-
//// 'dominant-baseline': labelPos == 'top' ? 'text-after-edge' : 'text-before-edge'
|
|
19491
|
-
// 'text-after-edge' is buggy in Safari and unsupported by Illustrator,
|
|
19492
|
-
// so I'm using 'hanging' and 'auto', which seem to be well supported.
|
|
19493
|
-
// downside: requires a kludgy multiplier to calculate scalebar height (see above)
|
|
19494
|
-
};
|
|
19495
|
-
var labelObj = symbolRenderers.label(labelOpts, anchorX, anchorY);
|
|
19496
|
-
var g = {
|
|
19497
|
-
tag: 'g',
|
|
19498
|
-
children: [barObj, labelObj],
|
|
19499
|
-
properties: {
|
|
19500
|
-
transform: 'translate(' + dx + ' ' + dy + ')'
|
|
19501
|
-
}
|
|
19569
|
+
var g = renderAsSvg(width, label, opts);
|
|
19570
|
+
g.properties = {
|
|
19571
|
+
transform: 'translate(' + dx + ' ' + dy + ')'
|
|
19502
19572
|
};
|
|
19573
|
+
|
|
19503
19574
|
return [g];
|
|
19504
19575
|
}
|
|
19505
19576
|
|
|
@@ -25691,13 +25762,33 @@ ${svg}
|
|
|
25691
25762
|
DEFAULT: true,
|
|
25692
25763
|
describe: 'distance label, e.g. "35 miles"'
|
|
25693
25764
|
})
|
|
25694
|
-
.option('
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
.option('
|
|
25698
|
-
|
|
25699
|
-
|
|
25700
|
-
.option('
|
|
25765
|
+
.option('style', {
|
|
25766
|
+
describe: 'two options: a or b'
|
|
25767
|
+
})
|
|
25768
|
+
.option('font-size', {
|
|
25769
|
+
type: 'number'
|
|
25770
|
+
})
|
|
25771
|
+
.option('tic-length', {
|
|
25772
|
+
describe: 'length of tic marks (style b)',
|
|
25773
|
+
type: 'number'
|
|
25774
|
+
})
|
|
25775
|
+
.option('bar-width', {
|
|
25776
|
+
describe: 'line width of bar',
|
|
25777
|
+
type: 'number'
|
|
25778
|
+
})
|
|
25779
|
+
.option('label-offset', {
|
|
25780
|
+
type: 'number'
|
|
25781
|
+
})
|
|
25782
|
+
.option('position', {
|
|
25783
|
+
describe: 'e.g. bottom-right (default is top-left)'
|
|
25784
|
+
})
|
|
25785
|
+
.option('label-position', {
|
|
25786
|
+
describe: 'top or bottom'
|
|
25787
|
+
})
|
|
25788
|
+
.option('margin', {
|
|
25789
|
+
describe: 'offset in pixels from edge of map',
|
|
25790
|
+
type: 'number'
|
|
25791
|
+
});
|
|
25701
25792
|
|
|
25702
25793
|
parser.command('shape')
|
|
25703
25794
|
.describe('create a polyline or polygon from coordinates')
|
|
@@ -35673,11 +35764,285 @@ ${svg}
|
|
|
35673
35764
|
};
|
|
35674
35765
|
}
|
|
35675
35766
|
|
|
35767
|
+
var MAX_RULE_LEN = 50;
|
|
35768
|
+
|
|
35769
|
+
cmd.info = function(targets, opts) {
|
|
35770
|
+
var layers = expandCommandTargets(targets);
|
|
35771
|
+
var arr = layers.map(function(o) {
|
|
35772
|
+
return getLayerInfo(o.layer, o.dataset);
|
|
35773
|
+
});
|
|
35774
|
+
|
|
35775
|
+
if (opts.save_to) {
|
|
35776
|
+
var output = [{
|
|
35777
|
+
filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
|
|
35778
|
+
content: JSON.stringify(arr, null, 2)
|
|
35779
|
+
}];
|
|
35780
|
+
writeFiles(output, opts);
|
|
35781
|
+
}
|
|
35782
|
+
if (opts.to_layer) {
|
|
35783
|
+
return {
|
|
35784
|
+
info: {},
|
|
35785
|
+
layers: [{
|
|
35786
|
+
name: opts.name || 'info',
|
|
35787
|
+
data: new DataTable(arr)
|
|
35788
|
+
}]
|
|
35789
|
+
};
|
|
35790
|
+
}
|
|
35791
|
+
message(formatInfo(arr));
|
|
35792
|
+
};
|
|
35793
|
+
|
|
35794
|
+
cmd.printInfo = cmd.info; // old name
|
|
35795
|
+
|
|
35796
|
+
function getLayerInfo(lyr, dataset) {
|
|
35797
|
+
var n = getFeatureCount(lyr);
|
|
35798
|
+
var o = {
|
|
35799
|
+
layer_name: lyr.name,
|
|
35800
|
+
geometry_type: lyr.geometry_type,
|
|
35801
|
+
feature_count: n,
|
|
35802
|
+
null_shape_count: 0,
|
|
35803
|
+
null_data_count: lyr.data ? countNullRecords(lyr.data.getRecords()) : n
|
|
35804
|
+
};
|
|
35805
|
+
if (lyr.shapes && lyr.shapes.length > 0) {
|
|
35806
|
+
o.null_shape_count = countNullShapes(lyr.shapes);
|
|
35807
|
+
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
35808
|
+
o.proj4 = getProjInfo(dataset);
|
|
35809
|
+
}
|
|
35810
|
+
o.source_file = getLayerSourceFile(lyr, dataset) || null;
|
|
35811
|
+
o.attribute_data = getAttributeTableInfo(lyr);
|
|
35812
|
+
return o;
|
|
35813
|
+
}
|
|
35814
|
+
|
|
35815
|
+
// i: (optional) record index
|
|
35816
|
+
function getAttributeTableInfo(lyr, i) {
|
|
35817
|
+
if (!lyr.data || lyr.data.size() === 0 || lyr.data.getFields().length === 0) {
|
|
35818
|
+
return null;
|
|
35819
|
+
}
|
|
35820
|
+
var fields = applyFieldOrder(lyr.data.getFields(), 'ascending');
|
|
35821
|
+
var valueName = i === undefined ? 'first_value' : 'value';
|
|
35822
|
+
return fields.map(function(fname) {
|
|
35823
|
+
return {
|
|
35824
|
+
field: fname,
|
|
35825
|
+
[valueName]: lyr.data.getReadOnlyRecordAt(i || 0)[fname]
|
|
35826
|
+
};
|
|
35827
|
+
});
|
|
35828
|
+
}
|
|
35829
|
+
|
|
35830
|
+
function formatInfo(arr) {
|
|
35831
|
+
var str = '';
|
|
35832
|
+
arr.forEach(function(info, i) {
|
|
35833
|
+
var title = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
35834
|
+
var tableStr = formatAttributeTableInfo(info.attribute_data);
|
|
35835
|
+
var tableWidth = measureLongestLine(tableStr);
|
|
35836
|
+
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
35837
|
+
str += '\n';
|
|
35838
|
+
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
35839
|
+
str += title + '\n';
|
|
35840
|
+
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
35841
|
+
str += formatLayerInfo(info);
|
|
35842
|
+
str += tableStr;
|
|
35843
|
+
});
|
|
35844
|
+
return str;
|
|
35845
|
+
}
|
|
35846
|
+
|
|
35847
|
+
function formatLayerInfo(data) {
|
|
35848
|
+
var str = '';
|
|
35849
|
+
str += "Type: " + (data.geometry_type || "tabular data") + "\n";
|
|
35850
|
+
str += utils.format("Records: %,d\n",data.feature_count);
|
|
35851
|
+
if (data.null_shape_count > 0) {
|
|
35852
|
+
str += utils.format("Nulls: %'d", data.null_shape_count) + "\n";
|
|
35853
|
+
}
|
|
35854
|
+
if (data.geometry_type && data.feature_count > data.null_shape_count) {
|
|
35855
|
+
str += "Bounds: " + data.bbox.join(',') + "\n";
|
|
35856
|
+
str += "CRS: " + data.proj4 + "\n";
|
|
35857
|
+
}
|
|
35858
|
+
str += "Source: " + (data.source_file || 'n/a') + "\n";
|
|
35859
|
+
return str;
|
|
35860
|
+
}
|
|
35861
|
+
|
|
35862
|
+
function formatAttributeTableInfo(arr) {
|
|
35863
|
+
if (!arr) return "Attribute data: [none]\n";
|
|
35864
|
+
var header = "\nAttribute data\n";
|
|
35865
|
+
var valKey = 'first_value' in arr[0] ? 'first_value' : 'value';
|
|
35866
|
+
var vals = [];
|
|
35867
|
+
var fields = [];
|
|
35868
|
+
arr.forEach(function(o) {
|
|
35869
|
+
fields.push(o.field);
|
|
35870
|
+
vals.push(o[valKey]);
|
|
35871
|
+
});
|
|
35872
|
+
var maxIntegralChars = vals.reduce(function(max, val) {
|
|
35873
|
+
if (utils.isNumber(val)) {
|
|
35874
|
+
max = Math.max(max, countIntegralChars(val));
|
|
35875
|
+
}
|
|
35876
|
+
return max;
|
|
35877
|
+
}, 0);
|
|
35878
|
+
var col1Arr = ['Field'].concat(fields);
|
|
35879
|
+
var col2Arr = vals.reduce(function(memo, val) {
|
|
35880
|
+
memo.push(formatTableValue(val, maxIntegralChars));
|
|
35881
|
+
return memo;
|
|
35882
|
+
}, [valKey == 'first_value' ? 'First value' : 'Value']);
|
|
35883
|
+
var col1Chars = maxChars(col1Arr);
|
|
35884
|
+
var col2Chars = maxChars(col2Arr);
|
|
35885
|
+
var sepStr = (utils.rpad('', col1Chars + 2, '-') + '+' +
|
|
35886
|
+
utils.rpad('', col2Chars + 2, '-')).substr(0, MAX_RULE_LEN);
|
|
35887
|
+
var sepLine = sepStr + '\n';
|
|
35888
|
+
var table = '';
|
|
35889
|
+
col1Arr.forEach(function(col1, i) {
|
|
35890
|
+
var w = stringDisplayWidth(col1);
|
|
35891
|
+
table += ' ' + col1 + utils.rpad('', col1Chars - w, ' ') + ' | ' +
|
|
35892
|
+
col2Arr[i] + '\n';
|
|
35893
|
+
if (i === 0) table += sepLine; // separator after first line
|
|
35894
|
+
});
|
|
35895
|
+
return header + sepLine + table + sepLine;
|
|
35896
|
+
}
|
|
35897
|
+
|
|
35898
|
+
function measureLongestLine(str) {
|
|
35899
|
+
return Math.max.apply(null, str.split('\n').map(function(line) {return stringDisplayWidth(line);}));
|
|
35900
|
+
}
|
|
35901
|
+
|
|
35902
|
+
function stringDisplayWidth(str) {
|
|
35903
|
+
var w = 0;
|
|
35904
|
+
for (var i = 0, n=str.length; i < n; i++) {
|
|
35905
|
+
w += charDisplayWidth(str.charCodeAt(i));
|
|
35906
|
+
}
|
|
35907
|
+
return w;
|
|
35908
|
+
}
|
|
35909
|
+
|
|
35910
|
+
// see https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
|
35911
|
+
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
35912
|
+
function charDisplayWidth(c) {
|
|
35913
|
+
if (c >= 0x1100 &&
|
|
35914
|
+
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
35915
|
+
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
35916
|
+
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
35917
|
+
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
35918
|
+
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
35919
|
+
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
35920
|
+
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
35921
|
+
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
35922
|
+
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
35923
|
+
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
35924
|
+
return 1;
|
|
35925
|
+
}
|
|
35926
|
+
|
|
35927
|
+
// TODO: consider polygons with zero area or other invalid geometries
|
|
35928
|
+
function countNullShapes(shapes) {
|
|
35929
|
+
var count = 0;
|
|
35930
|
+
for (var i=0; i<shapes.length; i++) {
|
|
35931
|
+
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
35932
|
+
}
|
|
35933
|
+
return count;
|
|
35934
|
+
}
|
|
35935
|
+
|
|
35936
|
+
function countNullRecords(records) {
|
|
35937
|
+
var count = 0;
|
|
35938
|
+
for (var i=0; i<records.length; i++) {
|
|
35939
|
+
if (!records[i]) count++;
|
|
35940
|
+
}
|
|
35941
|
+
return count;
|
|
35942
|
+
}
|
|
35943
|
+
|
|
35944
|
+
function maxChars(arr) {
|
|
35945
|
+
return arr.reduce(function(memo, str) {
|
|
35946
|
+
var w = stringDisplayWidth(str);
|
|
35947
|
+
return w > memo ? w : memo;
|
|
35948
|
+
}, 0);
|
|
35949
|
+
}
|
|
35950
|
+
|
|
35951
|
+
function formatString(str) {
|
|
35952
|
+
var replacements = {
|
|
35953
|
+
'\n': '\\n',
|
|
35954
|
+
'\r': '\\r',
|
|
35955
|
+
'\t': '\\t'
|
|
35956
|
+
};
|
|
35957
|
+
var cleanChar = function(c) {
|
|
35958
|
+
// convert newlines and carriage returns
|
|
35959
|
+
// TODO: better handling of non-printing chars
|
|
35960
|
+
return c in replacements ? replacements[c] : '';
|
|
35961
|
+
};
|
|
35962
|
+
str = str.replace(/[\r\t\n]/g, cleanChar);
|
|
35963
|
+
return "'" + str + "'";
|
|
35964
|
+
}
|
|
35965
|
+
|
|
35966
|
+
function countIntegralChars(val) {
|
|
35967
|
+
return utils.isNumber(val) ? (utils.formatNumber(val) + '.').indexOf('.') : 0;
|
|
35968
|
+
}
|
|
35969
|
+
|
|
35970
|
+
function formatTableValue(val, integralChars) {
|
|
35971
|
+
var str;
|
|
35972
|
+
if (utils.isNumber(val)) {
|
|
35973
|
+
str = utils.lpad("", integralChars - countIntegralChars(val), ' ') +
|
|
35974
|
+
utils.formatNumber(val);
|
|
35975
|
+
} else if (utils.isString(val)) {
|
|
35976
|
+
str = formatString(val);
|
|
35977
|
+
} else if (utils.isDate(val)) {
|
|
35978
|
+
str = utils.formatDateISO(val) + ' (Date)';
|
|
35979
|
+
} else if (utils.isObject(val)) { // if {} or [], display JSON
|
|
35980
|
+
str = JSON.stringify(val);
|
|
35981
|
+
} else {
|
|
35982
|
+
str = String(val);
|
|
35983
|
+
}
|
|
35984
|
+
|
|
35985
|
+
if (typeof str != 'string') {
|
|
35986
|
+
// e.g. JSON.stringify converts functions to undefined
|
|
35987
|
+
str = '[' + (typeof val) + ']';
|
|
35988
|
+
}
|
|
35989
|
+
|
|
35990
|
+
return str;
|
|
35991
|
+
}
|
|
35992
|
+
|
|
35993
|
+
var Info = /*#__PURE__*/Object.freeze({
|
|
35994
|
+
__proto__: null,
|
|
35995
|
+
getLayerInfo: getLayerInfo,
|
|
35996
|
+
getAttributeTableInfo: getAttributeTableInfo,
|
|
35997
|
+
formatAttributeTableInfo: formatAttributeTableInfo,
|
|
35998
|
+
formatTableValue: formatTableValue
|
|
35999
|
+
});
|
|
36000
|
+
|
|
36001
|
+
// import { importGeoJSON } from '../geojson/geojson-import';
|
|
36002
|
+
|
|
36003
|
+
|
|
36004
|
+
function addTargetProxies(targets, ctx) {
|
|
36005
|
+
if (targets && targets.length > 0) {
|
|
36006
|
+
var proxies = expandCommandTargets(targets).reduce(function(memo, target) {
|
|
36007
|
+
var proxy = getTargetProxy(target);
|
|
36008
|
+
memo.push(proxy);
|
|
36009
|
+
// index targets by layer name too
|
|
36010
|
+
if (target.layer.name) {
|
|
36011
|
+
memo[target.layer.name] = proxy;
|
|
36012
|
+
}
|
|
36013
|
+
return memo;
|
|
36014
|
+
}, []);
|
|
36015
|
+
Object.defineProperty(ctx, 'targets', {value: proxies});
|
|
36016
|
+
if (proxies.length == 1) {
|
|
36017
|
+
Object.defineProperty(ctx, 'target', {value: proxies[0]});
|
|
36018
|
+
}
|
|
36019
|
+
}
|
|
36020
|
+
}
|
|
36021
|
+
|
|
36022
|
+
function getTargetProxy(target) {
|
|
36023
|
+
var proxy = getLayerInfo(target.layer, target.dataset); // layer_name, feature_count etc
|
|
36024
|
+
proxy.layer = target.layer;
|
|
36025
|
+
proxy.dataset = target.dataset;
|
|
36026
|
+
addGetters(proxy, {
|
|
36027
|
+
// export as an object, not a string or buffer
|
|
36028
|
+
geojson: getGeoJSON
|
|
36029
|
+
});
|
|
36030
|
+
|
|
36031
|
+
function getGeoJSON() {
|
|
36032
|
+
var features = exportLayerAsGeoJSON(target.layer, target.dataset, {rfc7946: true}, true);
|
|
36033
|
+
return {
|
|
36034
|
+
type: 'FeatureCollection',
|
|
36035
|
+
features: features
|
|
36036
|
+
};
|
|
36037
|
+
}
|
|
36038
|
+
|
|
36039
|
+
return proxy;
|
|
36040
|
+
}
|
|
36041
|
+
|
|
35676
36042
|
function compileIfCommandExpression(expr, catalog, opts) {
|
|
35677
36043
|
return compileLayerExpression(expr, catalog, opts);
|
|
35678
36044
|
}
|
|
35679
36045
|
|
|
35680
|
-
|
|
35681
36046
|
function compileLayerExpression(expr, catalog, opts) {
|
|
35682
36047
|
var targetId = opts.layer || opts.target || null;
|
|
35683
36048
|
var targets = catalog.findCommandTargets(targetId);
|
|
@@ -35693,6 +36058,10 @@ ${svg}
|
|
|
35693
36058
|
} else {
|
|
35694
36059
|
ctx = getNullLayerProxy(targets);
|
|
35695
36060
|
}
|
|
36061
|
+
|
|
36062
|
+
// add target/targets proxies, for consistency with the -run command
|
|
36063
|
+
addTargetProxies(targets, ctx);
|
|
36064
|
+
|
|
35696
36065
|
ctx.global = defs; // TODO: remove duplication with mapshaper.expressions.mjs
|
|
35697
36066
|
var func = compileExpressionToFunction(expr, opts);
|
|
35698
36067
|
|
|
@@ -38142,8 +38511,7 @@ ${svg}
|
|
|
38142
38511
|
|
|
38143
38512
|
function convertBboxToGeoJSON(bbox, optsArg) {
|
|
38144
38513
|
var opts = optsArg || {};
|
|
38145
|
-
var coords =
|
|
38146
|
-
[bbox[2], bbox[1]], [bbox[0], bbox[1]]];
|
|
38514
|
+
var coords = bboxToCoords(bbox);
|
|
38147
38515
|
if (opts.interval > 0) {
|
|
38148
38516
|
coords = densifyPathByInterval(coords, opts.interval);
|
|
38149
38517
|
}
|
|
@@ -39328,58 +39696,73 @@ ${svg}
|
|
|
39328
39696
|
print(str);
|
|
39329
39697
|
};
|
|
39330
39698
|
|
|
39331
|
-
function resetControlFlow(job) {
|
|
39332
|
-
job.control = null;
|
|
39333
|
-
}
|
|
39334
|
-
|
|
39335
39699
|
function stopJob(job) {
|
|
39336
|
-
|
|
39700
|
+
job.stopped = true;
|
|
39337
39701
|
}
|
|
39338
39702
|
|
|
39339
39703
|
function jobIsStopped(job) {
|
|
39340
|
-
return
|
|
39704
|
+
return job.stopped === true;
|
|
39341
39705
|
}
|
|
39342
39706
|
|
|
39343
39707
|
function inControlBlock(job) {
|
|
39344
|
-
return
|
|
39708
|
+
return getStack(job).length > 0;
|
|
39709
|
+
}
|
|
39710
|
+
|
|
39711
|
+
function enterBlock(job) {
|
|
39712
|
+
var stack = getStack(job);
|
|
39713
|
+
// skip over a block if it is inside an inactive branch
|
|
39714
|
+
stack.push({
|
|
39715
|
+
active: false,
|
|
39716
|
+
complete: !inActiveBranch(job)
|
|
39717
|
+
});
|
|
39718
|
+
}
|
|
39719
|
+
|
|
39720
|
+
function leaveBlock(job) {
|
|
39721
|
+
var stack = getStack(job);
|
|
39722
|
+
stack.pop();
|
|
39345
39723
|
}
|
|
39346
39724
|
|
|
39347
39725
|
function enterActiveBranch(job) {
|
|
39348
|
-
var
|
|
39349
|
-
|
|
39350
|
-
|
|
39351
|
-
state.complete = true;
|
|
39726
|
+
var block = getCurrentBlock(job);
|
|
39727
|
+
block.active = true;
|
|
39728
|
+
block.complete = true;
|
|
39352
39729
|
}
|
|
39353
39730
|
|
|
39354
39731
|
function enterInactiveBranch(job) {
|
|
39355
|
-
var
|
|
39356
|
-
|
|
39357
|
-
|
|
39732
|
+
var block = getCurrentBlock(job);
|
|
39733
|
+
block.active = false;
|
|
39734
|
+
}
|
|
39735
|
+
|
|
39736
|
+
function blockIsComplete(job) {
|
|
39737
|
+
var block = getCurrentBlock(job);
|
|
39738
|
+
return block.complete;
|
|
39358
39739
|
}
|
|
39359
39740
|
|
|
39360
|
-
function
|
|
39361
|
-
|
|
39741
|
+
function getCurrentBlock(job) {
|
|
39742
|
+
var stack = getStack(job);
|
|
39743
|
+
return stack[stack.length-1];
|
|
39362
39744
|
}
|
|
39363
39745
|
|
|
39746
|
+
// A branch is considered to be active if it and all its parents are active
|
|
39747
|
+
// (Main branch is considered to be active)
|
|
39364
39748
|
function inActiveBranch(job) {
|
|
39365
|
-
|
|
39749
|
+
var stack = getStack(job);
|
|
39750
|
+
return stack.length === 0 || stack.every(block => block.active);
|
|
39366
39751
|
}
|
|
39367
39752
|
|
|
39368
|
-
function
|
|
39369
|
-
|
|
39753
|
+
function getStack(job) {
|
|
39754
|
+
job.control = job.control || {stack: []};
|
|
39755
|
+
return job.control.stack;
|
|
39370
39756
|
}
|
|
39371
39757
|
|
|
39372
39758
|
function skipCommand(cmdName, job) {
|
|
39373
|
-
// allow all control commands to run
|
|
39374
39759
|
if (jobIsStopped(job)) return true;
|
|
39375
39760
|
if (isControlFlowCommand(cmdName)) return false;
|
|
39376
|
-
return
|
|
39761
|
+
return !inActiveBranch(job);
|
|
39377
39762
|
}
|
|
39378
39763
|
|
|
39379
39764
|
cmd.if = function(job, opts) {
|
|
39380
|
-
|
|
39381
|
-
stop('Nested -if commands are not supported.');
|
|
39382
|
-
}
|
|
39765
|
+
enterBlock(job);
|
|
39383
39766
|
evaluateIf(job, opts);
|
|
39384
39767
|
};
|
|
39385
39768
|
|
|
@@ -39394,7 +39777,7 @@ ${svg}
|
|
|
39394
39777
|
if (!inControlBlock(job)) {
|
|
39395
39778
|
stop('-else command must be preceded by an -if command.');
|
|
39396
39779
|
}
|
|
39397
|
-
if (
|
|
39780
|
+
if (blockIsComplete(job)) {
|
|
39398
39781
|
enterInactiveBranch(job);
|
|
39399
39782
|
} else {
|
|
39400
39783
|
enterActiveBranch(job);
|
|
@@ -39405,7 +39788,7 @@ ${svg}
|
|
|
39405
39788
|
if (!inControlBlock(job)) {
|
|
39406
39789
|
stop('-endif command must be preceded by an -if command.');
|
|
39407
39790
|
}
|
|
39408
|
-
|
|
39791
|
+
leaveBlock(job);
|
|
39409
39792
|
};
|
|
39410
39793
|
|
|
39411
39794
|
function isControlFlowCommand(cmd) {
|
|
@@ -39413,21 +39796,14 @@ ${svg}
|
|
|
39413
39796
|
}
|
|
39414
39797
|
|
|
39415
39798
|
function test(catalog, opts) {
|
|
39416
|
-
// var targ = getTargetLayer(catalog, opts);
|
|
39417
39799
|
if (opts.expression) {
|
|
39418
39800
|
return compileIfCommandExpression(opts.expression, catalog, opts)();
|
|
39419
39801
|
}
|
|
39420
|
-
// if (opts.empty) {
|
|
39421
|
-
// return layerIsEmpty(targ.layer);
|
|
39422
|
-
// }
|
|
39423
|
-
// if (opts.not_empty) {
|
|
39424
|
-
// return !layerIsEmpty(targ.layer);
|
|
39425
|
-
// }
|
|
39426
39802
|
return true;
|
|
39427
39803
|
}
|
|
39428
39804
|
|
|
39429
39805
|
function evaluateIf(job, opts) {
|
|
39430
|
-
if (!
|
|
39806
|
+
if (!blockIsComplete(job) && test(job.catalog, opts)) {
|
|
39431
39807
|
enterActiveBranch(job);
|
|
39432
39808
|
} else {
|
|
39433
39809
|
enterInactiveBranch(job);
|
|
@@ -39472,240 +39848,6 @@ ${svg}
|
|
|
39472
39848
|
utils.extend(getStashedVar('defs'), obj);
|
|
39473
39849
|
};
|
|
39474
39850
|
|
|
39475
|
-
var MAX_RULE_LEN = 50;
|
|
39476
|
-
|
|
39477
|
-
cmd.info = function(targets, opts) {
|
|
39478
|
-
var layers = expandCommandTargets(targets);
|
|
39479
|
-
var arr = layers.map(function(o) {
|
|
39480
|
-
return getLayerInfo(o.layer, o.dataset);
|
|
39481
|
-
});
|
|
39482
|
-
|
|
39483
|
-
if (opts.save_to) {
|
|
39484
|
-
var output = [{
|
|
39485
|
-
filename: opts.save_to + (opts.save_to.endsWith('.json') ? '' : '.json'),
|
|
39486
|
-
content: JSON.stringify(arr, null, 2)
|
|
39487
|
-
}];
|
|
39488
|
-
writeFiles(output, opts);
|
|
39489
|
-
}
|
|
39490
|
-
if (opts.to_layer) {
|
|
39491
|
-
return {
|
|
39492
|
-
info: {},
|
|
39493
|
-
layers: [{
|
|
39494
|
-
name: opts.name || 'info',
|
|
39495
|
-
data: new DataTable(arr)
|
|
39496
|
-
}]
|
|
39497
|
-
};
|
|
39498
|
-
}
|
|
39499
|
-
message(formatInfo(arr));
|
|
39500
|
-
};
|
|
39501
|
-
|
|
39502
|
-
cmd.printInfo = cmd.info; // old name
|
|
39503
|
-
|
|
39504
|
-
function getLayerInfo(lyr, dataset) {
|
|
39505
|
-
var n = getFeatureCount(lyr);
|
|
39506
|
-
var o = {
|
|
39507
|
-
layer_name: lyr.name,
|
|
39508
|
-
geometry_type: lyr.geometry_type,
|
|
39509
|
-
feature_count: n,
|
|
39510
|
-
null_shape_count: 0,
|
|
39511
|
-
null_data_count: lyr.data ? countNullRecords(lyr.data.getRecords()) : n
|
|
39512
|
-
};
|
|
39513
|
-
if (lyr.shapes && lyr.shapes.length > 0) {
|
|
39514
|
-
o.null_shape_count = countNullShapes(lyr.shapes);
|
|
39515
|
-
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
39516
|
-
o.proj4 = getProjInfo(dataset);
|
|
39517
|
-
}
|
|
39518
|
-
o.source_file = getLayerSourceFile(lyr, dataset) || null;
|
|
39519
|
-
o.attribute_data = getAttributeTableInfo(lyr);
|
|
39520
|
-
return o;
|
|
39521
|
-
}
|
|
39522
|
-
|
|
39523
|
-
// i: (optional) record index
|
|
39524
|
-
function getAttributeTableInfo(lyr, i) {
|
|
39525
|
-
if (!lyr.data || lyr.data.size() === 0 || lyr.data.getFields().length === 0) {
|
|
39526
|
-
return null;
|
|
39527
|
-
}
|
|
39528
|
-
var fields = applyFieldOrder(lyr.data.getFields(), 'ascending');
|
|
39529
|
-
var valueName = i === undefined ? 'first_value' : 'value';
|
|
39530
|
-
return fields.map(function(fname) {
|
|
39531
|
-
return {
|
|
39532
|
-
field: fname,
|
|
39533
|
-
[valueName]: lyr.data.getReadOnlyRecordAt(i || 0)[fname]
|
|
39534
|
-
};
|
|
39535
|
-
});
|
|
39536
|
-
}
|
|
39537
|
-
|
|
39538
|
-
function formatInfo(arr) {
|
|
39539
|
-
var str = '';
|
|
39540
|
-
arr.forEach(function(info, i) {
|
|
39541
|
-
var title = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
39542
|
-
var tableStr = formatAttributeTableInfo(info.attribute_data);
|
|
39543
|
-
var tableWidth = measureLongestLine(tableStr);
|
|
39544
|
-
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
39545
|
-
str += '\n';
|
|
39546
|
-
str += utils.lpad('', ruleLen, '=') + '\n';
|
|
39547
|
-
str += title + '\n';
|
|
39548
|
-
str += utils.lpad('', ruleLen, '-') + '\n';
|
|
39549
|
-
str += formatLayerInfo(info);
|
|
39550
|
-
str += tableStr;
|
|
39551
|
-
});
|
|
39552
|
-
return str;
|
|
39553
|
-
}
|
|
39554
|
-
|
|
39555
|
-
function formatLayerInfo(data) {
|
|
39556
|
-
var str = '';
|
|
39557
|
-
str += "Type: " + (data.geometry_type || "tabular data") + "\n";
|
|
39558
|
-
str += utils.format("Records: %,d\n",data.feature_count);
|
|
39559
|
-
if (data.null_shape_count > 0) {
|
|
39560
|
-
str += utils.format("Nulls: %'d", data.null_shape_count) + "\n";
|
|
39561
|
-
}
|
|
39562
|
-
if (data.geometry_type && data.feature_count > data.null_shape_count) {
|
|
39563
|
-
str += "Bounds: " + data.bbox.join(',') + "\n";
|
|
39564
|
-
str += "CRS: " + data.proj4 + "\n";
|
|
39565
|
-
}
|
|
39566
|
-
str += "Source: " + (data.source_file || 'n/a') + "\n";
|
|
39567
|
-
return str;
|
|
39568
|
-
}
|
|
39569
|
-
|
|
39570
|
-
function formatAttributeTableInfo(arr) {
|
|
39571
|
-
if (!arr) return "Attribute data: [none]\n";
|
|
39572
|
-
var header = "\nAttribute data\n";
|
|
39573
|
-
var valKey = 'first_value' in arr[0] ? 'first_value' : 'value';
|
|
39574
|
-
var vals = [];
|
|
39575
|
-
var fields = [];
|
|
39576
|
-
arr.forEach(function(o) {
|
|
39577
|
-
fields.push(o.field);
|
|
39578
|
-
vals.push(o[valKey]);
|
|
39579
|
-
});
|
|
39580
|
-
var maxIntegralChars = vals.reduce(function(max, val) {
|
|
39581
|
-
if (utils.isNumber(val)) {
|
|
39582
|
-
max = Math.max(max, countIntegralChars(val));
|
|
39583
|
-
}
|
|
39584
|
-
return max;
|
|
39585
|
-
}, 0);
|
|
39586
|
-
var col1Arr = ['Field'].concat(fields);
|
|
39587
|
-
var col2Arr = vals.reduce(function(memo, val) {
|
|
39588
|
-
memo.push(formatTableValue(val, maxIntegralChars));
|
|
39589
|
-
return memo;
|
|
39590
|
-
}, [valKey == 'first_value' ? 'First value' : 'Value']);
|
|
39591
|
-
var col1Chars = maxChars(col1Arr);
|
|
39592
|
-
var col2Chars = maxChars(col2Arr);
|
|
39593
|
-
var sepStr = (utils.rpad('', col1Chars + 2, '-') + '+' +
|
|
39594
|
-
utils.rpad('', col2Chars + 2, '-')).substr(0, MAX_RULE_LEN);
|
|
39595
|
-
var sepLine = sepStr + '\n';
|
|
39596
|
-
var table = '';
|
|
39597
|
-
col1Arr.forEach(function(col1, i) {
|
|
39598
|
-
var w = stringDisplayWidth(col1);
|
|
39599
|
-
table += ' ' + col1 + utils.rpad('', col1Chars - w, ' ') + ' | ' +
|
|
39600
|
-
col2Arr[i] + '\n';
|
|
39601
|
-
if (i === 0) table += sepLine; // separator after first line
|
|
39602
|
-
});
|
|
39603
|
-
return header + sepLine + table + sepLine;
|
|
39604
|
-
}
|
|
39605
|
-
|
|
39606
|
-
function measureLongestLine(str) {
|
|
39607
|
-
return Math.max.apply(null, str.split('\n').map(function(line) {return stringDisplayWidth(line);}));
|
|
39608
|
-
}
|
|
39609
|
-
|
|
39610
|
-
function stringDisplayWidth(str) {
|
|
39611
|
-
var w = 0;
|
|
39612
|
-
for (var i = 0, n=str.length; i < n; i++) {
|
|
39613
|
-
w += charDisplayWidth(str.charCodeAt(i));
|
|
39614
|
-
}
|
|
39615
|
-
return w;
|
|
39616
|
-
}
|
|
39617
|
-
|
|
39618
|
-
// see https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
|
39619
|
-
// this is a simplified version, focusing on double-width CJK chars and ignoring nonprinting etc chars
|
|
39620
|
-
function charDisplayWidth(c) {
|
|
39621
|
-
if (c >= 0x1100 &&
|
|
39622
|
-
(c <= 0x115f || c == 0x2329 || c == 0x232a ||
|
|
39623
|
-
(c >= 0x2e80 && c <= 0xa4cf && c != 0x303f) || /* CJK ... Yi */
|
|
39624
|
-
(c >= 0xac00 && c <= 0xd7a3) || /* Hangul Syllables */
|
|
39625
|
-
(c >= 0xf900 && c <= 0xfaff) || /* CJK Compatibility Ideographs */
|
|
39626
|
-
(c >= 0xfe10 && c <= 0xfe19) || /* Vertical forms */
|
|
39627
|
-
(c >= 0xfe30 && c <= 0xfe6f) || /* CJK Compatibility Forms */
|
|
39628
|
-
(c >= 0xff00 && c <= 0xff60) || /* Fullwidth Forms */
|
|
39629
|
-
(c >= 0xffe0 && c <= 0xffe6) ||
|
|
39630
|
-
(c >= 0x20000 && c <= 0x2fffd) ||
|
|
39631
|
-
(c >= 0x30000 && c <= 0x3fffd))) return 2;
|
|
39632
|
-
return 1;
|
|
39633
|
-
}
|
|
39634
|
-
|
|
39635
|
-
// TODO: consider polygons with zero area or other invalid geometries
|
|
39636
|
-
function countNullShapes(shapes) {
|
|
39637
|
-
var count = 0;
|
|
39638
|
-
for (var i=0; i<shapes.length; i++) {
|
|
39639
|
-
if (!shapes[i] || shapes[i].length === 0) count++;
|
|
39640
|
-
}
|
|
39641
|
-
return count;
|
|
39642
|
-
}
|
|
39643
|
-
|
|
39644
|
-
function countNullRecords(records) {
|
|
39645
|
-
var count = 0;
|
|
39646
|
-
for (var i=0; i<records.length; i++) {
|
|
39647
|
-
if (!records[i]) count++;
|
|
39648
|
-
}
|
|
39649
|
-
return count;
|
|
39650
|
-
}
|
|
39651
|
-
|
|
39652
|
-
function maxChars(arr) {
|
|
39653
|
-
return arr.reduce(function(memo, str) {
|
|
39654
|
-
var w = stringDisplayWidth(str);
|
|
39655
|
-
return w > memo ? w : memo;
|
|
39656
|
-
}, 0);
|
|
39657
|
-
}
|
|
39658
|
-
|
|
39659
|
-
function formatString(str) {
|
|
39660
|
-
var replacements = {
|
|
39661
|
-
'\n': '\\n',
|
|
39662
|
-
'\r': '\\r',
|
|
39663
|
-
'\t': '\\t'
|
|
39664
|
-
};
|
|
39665
|
-
var cleanChar = function(c) {
|
|
39666
|
-
// convert newlines and carriage returns
|
|
39667
|
-
// TODO: better handling of non-printing chars
|
|
39668
|
-
return c in replacements ? replacements[c] : '';
|
|
39669
|
-
};
|
|
39670
|
-
str = str.replace(/[\r\t\n]/g, cleanChar);
|
|
39671
|
-
return "'" + str + "'";
|
|
39672
|
-
}
|
|
39673
|
-
|
|
39674
|
-
function countIntegralChars(val) {
|
|
39675
|
-
return utils.isNumber(val) ? (utils.formatNumber(val) + '.').indexOf('.') : 0;
|
|
39676
|
-
}
|
|
39677
|
-
|
|
39678
|
-
function formatTableValue(val, integralChars) {
|
|
39679
|
-
var str;
|
|
39680
|
-
if (utils.isNumber(val)) {
|
|
39681
|
-
str = utils.lpad("", integralChars - countIntegralChars(val), ' ') +
|
|
39682
|
-
utils.formatNumber(val);
|
|
39683
|
-
} else if (utils.isString(val)) {
|
|
39684
|
-
str = formatString(val);
|
|
39685
|
-
} else if (utils.isDate(val)) {
|
|
39686
|
-
str = utils.formatDateISO(val) + ' (Date)';
|
|
39687
|
-
} else if (utils.isObject(val)) { // if {} or [], display JSON
|
|
39688
|
-
str = JSON.stringify(val);
|
|
39689
|
-
} else {
|
|
39690
|
-
str = String(val);
|
|
39691
|
-
}
|
|
39692
|
-
|
|
39693
|
-
if (typeof str != 'string') {
|
|
39694
|
-
// e.g. JSON.stringify converts functions to undefined
|
|
39695
|
-
str = '[' + (typeof val) + ']';
|
|
39696
|
-
}
|
|
39697
|
-
|
|
39698
|
-
return str;
|
|
39699
|
-
}
|
|
39700
|
-
|
|
39701
|
-
var Info = /*#__PURE__*/Object.freeze({
|
|
39702
|
-
__proto__: null,
|
|
39703
|
-
getLayerInfo: getLayerInfo,
|
|
39704
|
-
getAttributeTableInfo: getAttributeTableInfo,
|
|
39705
|
-
formatAttributeTableInfo: formatAttributeTableInfo,
|
|
39706
|
-
formatTableValue: formatTableValue
|
|
39707
|
-
});
|
|
39708
|
-
|
|
39709
39851
|
// TODO: make sure that the inlay shapes and data are not shared
|
|
39710
39852
|
cmd.inlay = function(targetLayers, src, targetDataset, opts) {
|
|
39711
39853
|
var mergedDataset = mergeLayersForOverlay(targetLayers, targetDataset, src, opts);
|
|
@@ -42022,49 +42164,13 @@ ${svg}
|
|
|
42022
42164
|
}, {});
|
|
42023
42165
|
}
|
|
42024
42166
|
|
|
42025
|
-
// import { importGeoJSON } from '../geojson/geojson-import';
|
|
42026
|
-
|
|
42027
|
-
function getTargetProxy(target) {
|
|
42028
|
-
var proxy = getLayerInfo(target.layer, target.dataset); // layer_name, feature_count etc
|
|
42029
|
-
proxy.layer = target.layer;
|
|
42030
|
-
proxy.dataset = target.dataset;
|
|
42031
|
-
addGetters(proxy, {
|
|
42032
|
-
// export as an object, not a string or buffer
|
|
42033
|
-
geojson: getGeoJSON
|
|
42034
|
-
});
|
|
42035
|
-
|
|
42036
|
-
function getGeoJSON() {
|
|
42037
|
-
var features = exportLayerAsGeoJSON(target.layer, target.dataset, {rfc7946: true}, true);
|
|
42038
|
-
return {
|
|
42039
|
-
type: 'FeatureCollection',
|
|
42040
|
-
features: features
|
|
42041
|
-
};
|
|
42042
|
-
}
|
|
42043
|
-
|
|
42044
|
-
return proxy;
|
|
42045
|
-
}
|
|
42046
|
-
|
|
42047
42167
|
// Support for evaluating expressions embedded in curly-brace templates
|
|
42048
42168
|
|
|
42049
42169
|
// Returns: a string (e.g. a command string used by the -run command)
|
|
42050
42170
|
async function evalTemplateExpression(expression, targets, ctx) {
|
|
42051
42171
|
ctx = ctx || getBaseContext();
|
|
42052
42172
|
// TODO: throw an error if target is used when there are multiple targets
|
|
42053
|
-
|
|
42054
|
-
var proxies = expandCommandTargets(targets).reduce(function(memo, target) {
|
|
42055
|
-
var proxy = getTargetProxy(target);
|
|
42056
|
-
memo.push(proxy);
|
|
42057
|
-
// index targets by layer name too
|
|
42058
|
-
if (target.layer.name) {
|
|
42059
|
-
memo[target.layer.name] = proxy;
|
|
42060
|
-
}
|
|
42061
|
-
return memo;
|
|
42062
|
-
}, []);
|
|
42063
|
-
Object.defineProperty(ctx, 'targets', {value: proxies});
|
|
42064
|
-
if (proxies.length == 1) {
|
|
42065
|
-
Object.defineProperty(ctx, 'target', {value: proxies[0]});
|
|
42066
|
-
}
|
|
42067
|
-
}
|
|
42173
|
+
addTargetProxies(targets, ctx);
|
|
42068
42174
|
// Add global functions and data to the expression context
|
|
42069
42175
|
// (e.g. functions imported via the -require command)
|
|
42070
42176
|
var globals = getStashedVar('defs') || {};
|
|
@@ -42113,7 +42219,12 @@ ${svg}
|
|
|
42113
42219
|
function applyReplacements(template, replacements) {
|
|
42114
42220
|
var parts = parseTemplateParts(template);
|
|
42115
42221
|
return parts.reduce(function(memo, s, i) {
|
|
42116
|
-
|
|
42222
|
+
if (i % 2 == 1) {
|
|
42223
|
+
memo += replacements.length ? replacements.shift() : '';
|
|
42224
|
+
} else {
|
|
42225
|
+
memo += s;
|
|
42226
|
+
}
|
|
42227
|
+
return memo;
|
|
42117
42228
|
}, '');
|
|
42118
42229
|
}
|
|
42119
42230
|
|
|
@@ -44550,6 +44661,10 @@ ${svg}
|
|
|
44550
44661
|
return done(null);
|
|
44551
44662
|
}
|
|
44552
44663
|
|
|
44664
|
+
if (name == 'comment') {
|
|
44665
|
+
return done(null);
|
|
44666
|
+
}
|
|
44667
|
+
|
|
44553
44668
|
if (!job) job = new Job();
|
|
44554
44669
|
job.startCommand(command);
|
|
44555
44670
|
|
|
@@ -44978,7 +45093,7 @@ ${svg}
|
|
|
44978
45093
|
});
|
|
44979
45094
|
}
|
|
44980
45095
|
|
|
44981
|
-
var version = "0.6.
|
|
45096
|
+
var version = "0.6.65";
|
|
44982
45097
|
|
|
44983
45098
|
// Parse command line args into commands and run them
|
|
44984
45099
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
|
@@ -45720,6 +45835,7 @@ ${svg}
|
|
|
45720
45835
|
Projections,
|
|
45721
45836
|
ProjectionParams,
|
|
45722
45837
|
Rectangle,
|
|
45838
|
+
RectangleGeom,
|
|
45723
45839
|
Rounding,
|
|
45724
45840
|
RunCommands,
|
|
45725
45841
|
Scalebar,
|