mapshaper 0.7.12 → 0.7.14
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 +1867 -119
- package/package.json +6 -2
- package/www/geotiff.js +26351 -0
- package/www/index.html +27 -29
- package/www/mapshaper-gui.js +2142 -336
- package/www/mapshaper.js +1867 -119
- package/www/page.css +254 -108
package/mapshaper.js
CHANGED
|
@@ -1443,6 +1443,10 @@
|
|
|
1443
1443
|
return layerHasPaths(lyr) || layerHasPoints(lyr);
|
|
1444
1444
|
}
|
|
1445
1445
|
|
|
1446
|
+
function layerHasRaster(lyr) {
|
|
1447
|
+
return !!(lyr && lyr.raster_type && lyr.raster);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1446
1450
|
function layerIsGeometric(lyr) {
|
|
1447
1451
|
return !!lyr.geometry_type; // only checks type, includes empty layers
|
|
1448
1452
|
}
|
|
@@ -4772,6 +4776,628 @@
|
|
|
4772
4776
|
pathIsRectangle: pathIsRectangle
|
|
4773
4777
|
});
|
|
4774
4778
|
|
|
4779
|
+
var DEFAULT_MAX_PREVIEW_PIXELS = 4e6;
|
|
4780
|
+
|
|
4781
|
+
function getRasterGrid(raster) {
|
|
4782
|
+
return raster && (raster.grid || raster);
|
|
4783
|
+
}
|
|
4784
|
+
|
|
4785
|
+
function getRasterView(raster) {
|
|
4786
|
+
return raster && (raster.view || raster);
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4789
|
+
function getRasterPreview(raster) {
|
|
4790
|
+
var view = getRasterView(raster);
|
|
4791
|
+
return view && (view.preview || raster.preview);
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
function getRasterBBox(raster) {
|
|
4795
|
+
var grid = getRasterGrid(raster);
|
|
4796
|
+
return grid && grid.bbox || raster && raster.bbox || null;
|
|
4797
|
+
}
|
|
4798
|
+
|
|
4799
|
+
function getRasterTransform(raster) {
|
|
4800
|
+
var grid = getRasterGrid(raster);
|
|
4801
|
+
return grid && grid.transform || raster && raster.transform || null;
|
|
4802
|
+
}
|
|
4803
|
+
|
|
4804
|
+
function getRasterWidth(raster) {
|
|
4805
|
+
var grid = getRasterGrid(raster);
|
|
4806
|
+
return grid && grid.width || 0;
|
|
4807
|
+
}
|
|
4808
|
+
|
|
4809
|
+
function getRasterHeight(raster) {
|
|
4810
|
+
var grid = getRasterGrid(raster);
|
|
4811
|
+
return grid && grid.height || 0;
|
|
4812
|
+
}
|
|
4813
|
+
|
|
4814
|
+
function getRasterBandCount(raster) {
|
|
4815
|
+
var grid = getRasterGrid(raster);
|
|
4816
|
+
return grid && grid.bands || 0;
|
|
4817
|
+
}
|
|
4818
|
+
|
|
4819
|
+
function getRasterPixelType(raster) {
|
|
4820
|
+
var grid = getRasterGrid(raster);
|
|
4821
|
+
return grid && grid.pixelType || null;
|
|
4822
|
+
}
|
|
4823
|
+
|
|
4824
|
+
function copyRasterData(raster) {
|
|
4825
|
+
var copy = utils.extend({}, raster);
|
|
4826
|
+
if (raster.grid) {
|
|
4827
|
+
copy.grid = copyRasterGrid(raster.grid);
|
|
4828
|
+
}
|
|
4829
|
+
if (raster.view) {
|
|
4830
|
+
copy.view = copyRasterView(raster.view);
|
|
4831
|
+
}
|
|
4832
|
+
if (raster.derivation) {
|
|
4833
|
+
copy.derivation = utils.extend({}, raster.derivation);
|
|
4834
|
+
if (raster.derivation.bands) copy.derivation.bands = copyObjectOrArray(raster.derivation.bands);
|
|
4835
|
+
}
|
|
4836
|
+
if (raster.source) copy.source = utils.extend({}, raster.source);
|
|
4837
|
+
|
|
4838
|
+
// Back-compat for the first raster model.
|
|
4839
|
+
if (raster.pixels) copy.pixels = copyTypedArray(raster.pixels);
|
|
4840
|
+
if (raster.preview) copy.preview = copyRasterPreview(raster.preview);
|
|
4841
|
+
if (raster.bbox) copy.bbox = raster.bbox.concat();
|
|
4842
|
+
if (raster.transform) copy.transform = copyObjectOrArray(raster.transform);
|
|
4843
|
+
return copy;
|
|
4844
|
+
}
|
|
4845
|
+
|
|
4846
|
+
function copyRasterGrid(grid) {
|
|
4847
|
+
var copy = utils.extend({}, grid);
|
|
4848
|
+
if (grid.samples) copy.samples = copyTypedArray(grid.samples);
|
|
4849
|
+
if (grid.sampleBands) copy.sampleBands = grid.sampleBands.concat();
|
|
4850
|
+
if (grid.bbox) copy.bbox = grid.bbox.concat();
|
|
4851
|
+
if (grid.transform) copy.transform = copyObjectOrArray(grid.transform);
|
|
4852
|
+
return copy;
|
|
4853
|
+
}
|
|
4854
|
+
|
|
4855
|
+
function copyRasterView(view) {
|
|
4856
|
+
var copy = utils.extend({}, view);
|
|
4857
|
+
if (view.recipe) copy.recipe = copyObjectOrArray(view.recipe);
|
|
4858
|
+
if (view.preview) copy.preview = copyRasterPreview(view.preview);
|
|
4859
|
+
if (view.scalingStats) copy.scalingStats = copyObjectOrArray(view.scalingStats);
|
|
4860
|
+
return copy;
|
|
4861
|
+
}
|
|
4862
|
+
|
|
4863
|
+
function copyRasterPreview(preview) {
|
|
4864
|
+
var copy = utils.extend({}, preview);
|
|
4865
|
+
delete copy.canvas;
|
|
4866
|
+
if (preview.pixels) copy.pixels = copyTypedArray(preview.pixels);
|
|
4867
|
+
return copy;
|
|
4868
|
+
}
|
|
4869
|
+
|
|
4870
|
+
function copyTypedArray(arr) {
|
|
4871
|
+
if (Array.isArray(arr)) return arr.map(copyTypedArray);
|
|
4872
|
+
return arr && arr.slice ? arr.slice() : arr;
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4875
|
+
function createRasterPreview(raster, opts) {
|
|
4876
|
+
opts = opts || {};
|
|
4877
|
+
var grid = getRasterGrid(raster);
|
|
4878
|
+
var recipe = getRasterViewRecipe(grid, raster.view && raster.view.recipe, opts);
|
|
4879
|
+
var stats = getRasterViewScalingStats(raster, recipe);
|
|
4880
|
+
var maxPixels = opts.maxPixels || opts.raster_max_pixels || opts.rasterMaxPixels || DEFAULT_MAX_PREVIEW_PIXELS;
|
|
4881
|
+
var scale = Math.min(1, Math.sqrt(maxPixels / (grid.width * grid.height)));
|
|
4882
|
+
var width = Math.max(1, Math.round(grid.width * scale));
|
|
4883
|
+
var height = Math.max(1, Math.round(grid.height * scale));
|
|
4884
|
+
return renderRasterPreview(grid, recipe, width, height, stats);
|
|
4885
|
+
}
|
|
4886
|
+
|
|
4887
|
+
function getRasterViewRecipe(grid, recipeArg, opts) {
|
|
4888
|
+
var recipe = Object.assign({}, recipeArg || {});
|
|
4889
|
+
var scaling = opts && opts.scaling || recipe.scaling || getDefaultRasterScaling(grid);
|
|
4890
|
+
var scaleRange = opts && (opts.scale_range || opts.scaleRange) || recipe.scaleRange;
|
|
4891
|
+
var percentileRange = opts && (opts.percentile_range || opts.percentileRange) || recipe.percentileRange;
|
|
4892
|
+
if (scaling != 'none' && scaling != 'minmax' && scaling != 'percentile') {
|
|
4893
|
+
stop$1('Unsupported raster scaling method:', scaling);
|
|
4894
|
+
}
|
|
4895
|
+
return Object.assign(recipe, {
|
|
4896
|
+
type: recipe.type || (grid.bands >= 3 ? 'rgb' : 'gray'),
|
|
4897
|
+
bands: recipe.bands || grid.sampleBands || null,
|
|
4898
|
+
scaling: scaling,
|
|
4899
|
+
scaleRange: parseRangeOption(scaleRange, [0, 100], 'scale-range'),
|
|
4900
|
+
percentileRange: parseRangeOption(percentileRange, [2, 98], 'percentile-range')
|
|
4901
|
+
});
|
|
4902
|
+
}
|
|
4903
|
+
|
|
4904
|
+
function renderRasterPreview(grid, recipe, width, height, statsArg) {
|
|
4905
|
+
recipe = getRasterViewRecipe(grid, recipe);
|
|
4906
|
+
if (useFastRawEightBitRendering(grid, recipe)) {
|
|
4907
|
+
return renderRawEightBitPreview(grid, width, height, null);
|
|
4908
|
+
}
|
|
4909
|
+
return renderRasterGridPreview(grid, recipe, width, height, statsArg || getRasterScalingStats(grid, recipe), null);
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
function renderRasterViewportPreview(grid, recipe, bbox, width, height, statsArg) {
|
|
4913
|
+
recipe = getRasterViewRecipe(grid, recipe);
|
|
4914
|
+
if (!intersectBboxes(grid.bbox, bbox)) return null;
|
|
4915
|
+
if (useFastRawEightBitRendering(grid, recipe)) {
|
|
4916
|
+
return Object.assign(renderRawEightBitPreview(grid, width, height, bbox), {
|
|
4917
|
+
bbox: bbox.concat()
|
|
4918
|
+
});
|
|
4919
|
+
}
|
|
4920
|
+
return Object.assign(renderRasterGridPreview(grid, recipe, width, height, statsArg || getRasterScalingStats(grid, recipe), bbox), {
|
|
4921
|
+
bbox: bbox.concat()
|
|
4922
|
+
});
|
|
4923
|
+
}
|
|
4924
|
+
|
|
4925
|
+
function getRasterScalingStats(grid, recipe) {
|
|
4926
|
+
recipe = getRasterViewRecipe(grid, recipe);
|
|
4927
|
+
return getScalingStats(grid.samples, grid.bands, grid.nodata, recipe);
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4930
|
+
function getRasterViewScalingStats(raster, recipeArg) {
|
|
4931
|
+
var grid = getRasterGrid(raster);
|
|
4932
|
+
var view = getRasterView(raster);
|
|
4933
|
+
var recipe = getRasterViewRecipe(grid, recipeArg || view && view.recipe);
|
|
4934
|
+
var key, cached, stats;
|
|
4935
|
+
if (recipe.scaling == 'none') return null;
|
|
4936
|
+
key = getRasterScalingStatsKey(grid, recipe);
|
|
4937
|
+
cached = view && view.scalingStats;
|
|
4938
|
+
if (cached && cached.key == key) return cached.stats;
|
|
4939
|
+
stats = getRasterScalingStats(grid, recipe);
|
|
4940
|
+
if (view) {
|
|
4941
|
+
view.scalingStats = {
|
|
4942
|
+
key: key,
|
|
4943
|
+
stats: stats
|
|
4944
|
+
};
|
|
4945
|
+
}
|
|
4946
|
+
return stats;
|
|
4947
|
+
}
|
|
4948
|
+
|
|
4949
|
+
function renderRasterGridPreview(grid, recipe, width, height, statsArg, sourceBbox) {
|
|
4950
|
+
var samples = grid.samples;
|
|
4951
|
+
var bands = grid.bands;
|
|
4952
|
+
var noData = grid.nodata;
|
|
4953
|
+
var pixels = new Uint8ClampedArray(width * height * 4);
|
|
4954
|
+
var stats = statsArg || getScalingStats(samples, bands, noData, recipe);
|
|
4955
|
+
var sourceRange = recipe.scaling == 'none' ? getPixelTypeRange(grid.pixelType) : null;
|
|
4956
|
+
var displayRange = getDisplayRange(recipe.scaleRange);
|
|
4957
|
+
var src, dest, val, isNoData, j;
|
|
4958
|
+
for (var y = 0; y < height; y++) {
|
|
4959
|
+
for (var x = 0; x < width; x++) {
|
|
4960
|
+
src = getPreviewSourceOffset(grid, sourceBbox, x, y, width, height, bands);
|
|
4961
|
+
dest = (y * width + x) * 4;
|
|
4962
|
+
isNoData = noData !== null && noData !== undefined && allSamplesAreNoData(samples, src, bands, noData);
|
|
4963
|
+
if (bands == 1) {
|
|
4964
|
+
val = scaleSample(samples[src], stats && stats[0], sourceRange, displayRange);
|
|
4965
|
+
pixels[dest] = val;
|
|
4966
|
+
pixels[dest + 1] = val;
|
|
4967
|
+
pixels[dest + 2] = val;
|
|
4968
|
+
pixels[dest + 3] = isNoData ? 0 : 255;
|
|
4969
|
+
} else {
|
|
4970
|
+
for (j = 0; j < 3; j++) {
|
|
4971
|
+
pixels[dest + j] = scaleSample(samples[src + j], stats && stats[j], sourceRange, displayRange);
|
|
4972
|
+
}
|
|
4973
|
+
pixels[dest + 3] = isNoData ? 0 : bands >= 4 ? scaleSample(samples[src + 3], stats && stats[3], sourceRange, [0, 255]) : 255;
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
}
|
|
4977
|
+
return {
|
|
4978
|
+
width: width,
|
|
4979
|
+
height: height,
|
|
4980
|
+
bands: 4,
|
|
4981
|
+
pixelType: 'uint8',
|
|
4982
|
+
colorModel: 'rgba',
|
|
4983
|
+
pixels: pixels
|
|
4984
|
+
};
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
function renderRawEightBitPreview(grid, width, height, sourceBbox) {
|
|
4988
|
+
var samples = grid.samples;
|
|
4989
|
+
var bands = grid.bands;
|
|
4990
|
+
var pixels = new Uint8ClampedArray(width * height * 4);
|
|
4991
|
+
var src, dest, val;
|
|
4992
|
+
for (var y = 0; y < height; y++) {
|
|
4993
|
+
for (var x = 0; x < width; x++) {
|
|
4994
|
+
src = getPreviewSourceOffset(grid, sourceBbox, x, y, width, height, bands);
|
|
4995
|
+
dest = (y * width + x) * 4;
|
|
4996
|
+
if (bands == 1) {
|
|
4997
|
+
val = samples[src];
|
|
4998
|
+
pixels[dest] = val;
|
|
4999
|
+
pixels[dest + 1] = val;
|
|
5000
|
+
pixels[dest + 2] = val;
|
|
5001
|
+
pixels[dest + 3] = 255;
|
|
5002
|
+
} else {
|
|
5003
|
+
pixels[dest] = samples[src];
|
|
5004
|
+
pixels[dest + 1] = samples[src + 1];
|
|
5005
|
+
pixels[dest + 2] = samples[src + 2];
|
|
5006
|
+
pixels[dest + 3] = bands >= 4 ? samples[src + 3] : 255;
|
|
5007
|
+
}
|
|
5008
|
+
}
|
|
5009
|
+
}
|
|
5010
|
+
return {
|
|
5011
|
+
width: width,
|
|
5012
|
+
height: height,
|
|
5013
|
+
bands: 4,
|
|
5014
|
+
pixelType: 'uint8',
|
|
5015
|
+
colorModel: 'rgba',
|
|
5016
|
+
pixels: pixels
|
|
5017
|
+
};
|
|
5018
|
+
}
|
|
5019
|
+
|
|
5020
|
+
function getPreviewSourceOffset(grid, sourceBbox, x, y, width, height, bands) {
|
|
5021
|
+
var sx, sy, mapX, mapY, rb;
|
|
5022
|
+
if (!sourceBbox) {
|
|
5023
|
+
sy = Math.min(grid.height - 1, Math.floor((y + 0.5) * grid.height / height));
|
|
5024
|
+
sx = Math.min(grid.width - 1, Math.floor((x + 0.5) * grid.width / width));
|
|
5025
|
+
} else {
|
|
5026
|
+
rb = grid.bbox;
|
|
5027
|
+
mapX = sourceBbox[0] + (x + 0.5) / width * (sourceBbox[2] - sourceBbox[0]);
|
|
5028
|
+
mapY = sourceBbox[3] - (y + 0.5) / height * (sourceBbox[3] - sourceBbox[1]);
|
|
5029
|
+
sx = Math.max(0, Math.min(grid.width - 1, Math.floor((mapX - rb[0]) / (rb[2] - rb[0]) * grid.width)));
|
|
5030
|
+
sy = Math.max(0, Math.min(grid.height - 1, Math.floor((rb[3] - mapY) / (rb[3] - rb[1]) * grid.height)));
|
|
5031
|
+
}
|
|
5032
|
+
return (sy * grid.width + sx) * bands;
|
|
5033
|
+
}
|
|
5034
|
+
|
|
5035
|
+
function clipRasterToBBox(lyr, bbox, opts) {
|
|
5036
|
+
var raster = lyr.raster;
|
|
5037
|
+
var grid = getRasterGrid(raster);
|
|
5038
|
+
var clipBbox = intersectBboxes(grid.bbox, bbox);
|
|
5039
|
+
if (!clipBbox) {
|
|
5040
|
+
warn('Raster clipping rectangle does not intersect the raster layer');
|
|
5041
|
+
return false;
|
|
5042
|
+
}
|
|
5043
|
+
var crop = getRasterCrop(grid, clipBbox);
|
|
5044
|
+
if (crop.width === 0 || crop.height === 0) {
|
|
5045
|
+
warn('Raster clipping rectangle does not intersect the raster layer');
|
|
5046
|
+
return false;
|
|
5047
|
+
}
|
|
5048
|
+
noteLayerWillChange(lyr, {operation: 'clipRasterToBBox', unit: 'raster'});
|
|
5049
|
+
raster.grid = cropRasterGrid(grid, crop, clipBbox);
|
|
5050
|
+
raster.view = raster.view || {};
|
|
5051
|
+
raster.view.preview = createRasterPreview(raster, opts || {});
|
|
5052
|
+
clearLegacyRasterFields(raster);
|
|
5053
|
+
markLayerChanged(lyr, {operation: 'clipRasterToBBox', unit: 'raster'});
|
|
5054
|
+
return true;
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5057
|
+
function intersectBboxes(a, b) {
|
|
5058
|
+
var bbox = [
|
|
5059
|
+
Math.max(a[0], b[0]),
|
|
5060
|
+
Math.max(a[1], b[1]),
|
|
5061
|
+
Math.min(a[2], b[2]),
|
|
5062
|
+
Math.min(a[3], b[3])
|
|
5063
|
+
];
|
|
5064
|
+
return bbox[2] <= bbox[0] || bbox[3] <= bbox[1] ? null : bbox;
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
function getRasterCrop(grid, bbox) {
|
|
5068
|
+
var rb = grid.bbox;
|
|
5069
|
+
var x0 = Math.max(0, Math.floor((bbox[0] - rb[0]) / (rb[2] - rb[0]) * grid.width));
|
|
5070
|
+
var x1 = Math.min(grid.width, Math.ceil((bbox[2] - rb[0]) / (rb[2] - rb[0]) * grid.width));
|
|
5071
|
+
var y0 = Math.max(0, Math.floor((rb[3] - bbox[3]) / (rb[3] - rb[1]) * grid.height));
|
|
5072
|
+
var y1 = Math.min(grid.height, Math.ceil((rb[3] - bbox[1]) / (rb[3] - rb[1]) * grid.height));
|
|
5073
|
+
return {
|
|
5074
|
+
x: x0,
|
|
5075
|
+
y: y0,
|
|
5076
|
+
width: Math.max(0, x1 - x0),
|
|
5077
|
+
height: Math.max(0, y1 - y0)
|
|
5078
|
+
};
|
|
5079
|
+
}
|
|
5080
|
+
|
|
5081
|
+
function cropRasterGrid(grid, crop, bbox) {
|
|
5082
|
+
var samples = new grid.samples.constructor(crop.width * crop.height * grid.bands);
|
|
5083
|
+
var rowCount = crop.width * grid.bands;
|
|
5084
|
+
var src, dest;
|
|
5085
|
+
for (var y = 0; y < crop.height; y++) {
|
|
5086
|
+
src = ((crop.y + y) * grid.width + crop.x) * grid.bands;
|
|
5087
|
+
dest = y * rowCount;
|
|
5088
|
+
samples.set(grid.samples.subarray(src, src + rowCount), dest);
|
|
5089
|
+
}
|
|
5090
|
+
return Object.assign({}, grid, {
|
|
5091
|
+
width: crop.width,
|
|
5092
|
+
height: crop.height,
|
|
5093
|
+
samples: samples,
|
|
5094
|
+
bbox: bbox,
|
|
5095
|
+
transform: updateTransformForBBox(grid.transform, bbox, crop.width, crop.height)
|
|
5096
|
+
});
|
|
5097
|
+
}
|
|
5098
|
+
|
|
5099
|
+
function getRasterLayerBounds(lyr) {
|
|
5100
|
+
var bbox = lyr.raster && getRasterBBox(lyr.raster);
|
|
5101
|
+
return bbox && bbox.length == 4 ? new Bounds(bbox) : null;
|
|
5102
|
+
}
|
|
5103
|
+
|
|
5104
|
+
function requireRasterLayer(lyr) {
|
|
5105
|
+
if (!lyr || !lyr.raster_type || !lyr.raster) {
|
|
5106
|
+
stop$1('Expected a raster layer');
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
|
|
5110
|
+
function clearLegacyRasterFields(raster) {
|
|
5111
|
+
delete raster.width;
|
|
5112
|
+
delete raster.height;
|
|
5113
|
+
delete raster.bands;
|
|
5114
|
+
delete raster.pixelType;
|
|
5115
|
+
delete raster.nodata;
|
|
5116
|
+
delete raster.bbox;
|
|
5117
|
+
delete raster.transform;
|
|
5118
|
+
delete raster.colorModel;
|
|
5119
|
+
delete raster.preview;
|
|
5120
|
+
delete raster.pixels;
|
|
5121
|
+
}
|
|
5122
|
+
|
|
5123
|
+
function updateTransformForBBox(transform, bbox, width, height) {
|
|
5124
|
+
if (!transform) return null;
|
|
5125
|
+
return [
|
|
5126
|
+
(bbox[2] - bbox[0]) / width,
|
|
5127
|
+
0,
|
|
5128
|
+
bbox[0],
|
|
5129
|
+
0,
|
|
5130
|
+
-(bbox[3] - bbox[1]) / height,
|
|
5131
|
+
bbox[3]
|
|
5132
|
+
];
|
|
5133
|
+
}
|
|
5134
|
+
|
|
5135
|
+
function getBandStats(data, bands, noData) {
|
|
5136
|
+
var stats = [];
|
|
5137
|
+
for (var band = 0; band < bands; band++) {
|
|
5138
|
+
stats[band] = getSingleBandStats(data, bands, band, noData);
|
|
5139
|
+
}
|
|
5140
|
+
return stats;
|
|
5141
|
+
}
|
|
5142
|
+
|
|
5143
|
+
function getSingleBandStats(data, bands, band, noData) {
|
|
5144
|
+
var min = Infinity;
|
|
5145
|
+
var max = -Infinity;
|
|
5146
|
+
var val;
|
|
5147
|
+
for (var i = band; i < data.length; i += bands) {
|
|
5148
|
+
val = data[i];
|
|
5149
|
+
if (!isValidBandValue(val, noData)) continue;
|
|
5150
|
+
if (val < min) min = val;
|
|
5151
|
+
if (val > max) max = val;
|
|
5152
|
+
}
|
|
5153
|
+
return min < Infinity && max > min ? {min: min, max: max} : {min: 0, max: 255};
|
|
5154
|
+
}
|
|
5155
|
+
|
|
5156
|
+
function getSharedBandStats(data, bands, noData) {
|
|
5157
|
+
var stats = getBandStats(data, bands, noData);
|
|
5158
|
+
var min = Math.min(stats[0].min, stats[1].min, stats[2].min);
|
|
5159
|
+
var max = Math.max(stats[0].max, stats[1].max, stats[2].max);
|
|
5160
|
+
var shared = max > min ? {min: min, max: max} : {min: 0, max: 255};
|
|
5161
|
+
stats[0] = stats[1] = stats[2] = shared;
|
|
5162
|
+
return stats;
|
|
5163
|
+
}
|
|
5164
|
+
|
|
5165
|
+
function getScalingStats(data, bands, noData, recipe) {
|
|
5166
|
+
var shared = recipe.type == 'rgb' && bands >= 3;
|
|
5167
|
+
if (recipe.scaling == 'minmax') {
|
|
5168
|
+
return shared ? getSharedBandStats(data, bands, noData) : getBandStats(data, bands, noData);
|
|
5169
|
+
}
|
|
5170
|
+
if (recipe.scaling == 'percentile') {
|
|
5171
|
+
return shared ? getSharedPercentileStats(data, bands, noData, recipe.percentileRange) :
|
|
5172
|
+
getBandPercentileStats(data, bands, noData, recipe.percentileRange);
|
|
5173
|
+
}
|
|
5174
|
+
return null;
|
|
5175
|
+
}
|
|
5176
|
+
|
|
5177
|
+
function scaleSample(val, stats, sourceRange, displayRange) {
|
|
5178
|
+
var range = stats || sourceRange || {min: 0, max: 255};
|
|
5179
|
+
var pct = range.max > range.min ? (val - range.min) / (range.max - range.min) : 0;
|
|
5180
|
+
var scaled = displayRange[0] + pct * (displayRange[1] - displayRange[0]);
|
|
5181
|
+
return Math.max(0, Math.min(255, Math.round(scaled)));
|
|
5182
|
+
}
|
|
5183
|
+
|
|
5184
|
+
function getDefaultRasterScaling(grid, recipe) {
|
|
5185
|
+
return isEightBitPixelType(grid.pixelType) ? 'none' : 'percentile';
|
|
5186
|
+
}
|
|
5187
|
+
|
|
5188
|
+
function parseRangeOption(val, def, name) {
|
|
5189
|
+
var range;
|
|
5190
|
+
if (val == null || val === '') return def;
|
|
5191
|
+
range = Array.isArray(val) ? val : String(val).split(',');
|
|
5192
|
+
if (range.length != 2) {
|
|
5193
|
+
stop$1('Expected ' + name + '= to contain two comma-separated numbers');
|
|
5194
|
+
}
|
|
5195
|
+
range = range.map(Number);
|
|
5196
|
+
if (!isFinite(range[0]) || !isFinite(range[1]) || range[0] < 0 || range[1] > 100 || range[1] < range[0]) {
|
|
5197
|
+
stop$1('Expected ' + name + '= values between 0 and 100');
|
|
5198
|
+
}
|
|
5199
|
+
return range;
|
|
5200
|
+
}
|
|
5201
|
+
|
|
5202
|
+
function getDisplayRange(scaleRange) {
|
|
5203
|
+
return [
|
|
5204
|
+
scaleRange[0] / 100 * 255,
|
|
5205
|
+
scaleRange[1] / 100 * 255
|
|
5206
|
+
];
|
|
5207
|
+
}
|
|
5208
|
+
|
|
5209
|
+
function getPixelTypeRange(pixelType) {
|
|
5210
|
+
switch (pixelType) {
|
|
5211
|
+
case 'uint8': return {min: 0, max: 255};
|
|
5212
|
+
case 'uint16': return {min: 0, max: 65535};
|
|
5213
|
+
case 'uint32': return {min: 0, max: 4294967295};
|
|
5214
|
+
case 'int8': return {min: -128, max: 127};
|
|
5215
|
+
case 'int16': return {min: -32768, max: 32767};
|
|
5216
|
+
case 'int32': return {min: -2147483648, max: 2147483647};
|
|
5217
|
+
}
|
|
5218
|
+
return null;
|
|
5219
|
+
}
|
|
5220
|
+
|
|
5221
|
+
function isEightBitPixelType(pixelType) {
|
|
5222
|
+
return pixelType == 'uint8' || pixelType == 'int8';
|
|
5223
|
+
}
|
|
5224
|
+
|
|
5225
|
+
function useFastRawEightBitRendering(grid, recipe) {
|
|
5226
|
+
return grid.pixelType == 'uint8' &&
|
|
5227
|
+
recipe.scaling == 'none' &&
|
|
5228
|
+
recipe.scaleRange[0] === 0 &&
|
|
5229
|
+
recipe.scaleRange[1] === 100 &&
|
|
5230
|
+
(recipe.type == 'gray' && grid.bands == 1 || recipe.type == 'rgb' && grid.bands >= 3) &&
|
|
5231
|
+
(grid.nodata === null || grid.nodata === undefined);
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
function getRasterScalingStatsKey(grid, recipe) {
|
|
5235
|
+
return [
|
|
5236
|
+
grid.width,
|
|
5237
|
+
grid.height,
|
|
5238
|
+
grid.bands,
|
|
5239
|
+
grid.pixelType,
|
|
5240
|
+
grid.samples && grid.samples.length,
|
|
5241
|
+
grid.nodata,
|
|
5242
|
+
recipe.type,
|
|
5243
|
+
recipe.scaling,
|
|
5244
|
+
recipe.scaleRange && recipe.scaleRange.join(','),
|
|
5245
|
+
recipe.percentileRange && recipe.percentileRange.join(',')
|
|
5246
|
+
].join('|');
|
|
5247
|
+
}
|
|
5248
|
+
|
|
5249
|
+
function getBandPercentileStats(data, bands, noData, range) {
|
|
5250
|
+
var stats = [];
|
|
5251
|
+
for (var band = 0; band < bands; band++) {
|
|
5252
|
+
stats[band] = getPercentileStats(data, bands, [band], noData, range);
|
|
5253
|
+
}
|
|
5254
|
+
return stats;
|
|
5255
|
+
}
|
|
5256
|
+
|
|
5257
|
+
function getSharedPercentileStats(data, bands, noData, range) {
|
|
5258
|
+
var stats = getBandPercentileStats(data, bands, noData, range);
|
|
5259
|
+
var shared = getPercentileStats(data, bands, [0, 1, 2], noData, range);
|
|
5260
|
+
stats[0] = stats[1] = stats[2] = shared;
|
|
5261
|
+
return stats;
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5264
|
+
function getPercentileStats(data, bands, bandIds, noData, range) {
|
|
5265
|
+
var integerRange = getSmallIntegerRange(data);
|
|
5266
|
+
return integerRange ?
|
|
5267
|
+
getHistogramPercentileStats(data, bands, bandIds, noData, range, integerRange) :
|
|
5268
|
+
getApproxHistogramPercentileStats(data, bands, bandIds, noData, range);
|
|
5269
|
+
}
|
|
5270
|
+
|
|
5271
|
+
function getSmallIntegerRange(data) {
|
|
5272
|
+
if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) return {min: 0, max: 255};
|
|
5273
|
+
if (data instanceof Int8Array) return {min: -128, max: 127};
|
|
5274
|
+
if (data instanceof Uint16Array) return {min: 0, max: 65535};
|
|
5275
|
+
if (data instanceof Int16Array) return {min: -32768, max: 32767};
|
|
5276
|
+
return null;
|
|
5277
|
+
}
|
|
5278
|
+
|
|
5279
|
+
function getHistogramPercentileStats(data, bands, bandIds, noData, range, integerRange) {
|
|
5280
|
+
var counts = new Uint32Array(integerRange.max - integerRange.min + 1);
|
|
5281
|
+
var count = 0, val;
|
|
5282
|
+
forEachBandValue(data, bands, bandIds, noData, function(v) {
|
|
5283
|
+
val = v - integerRange.min;
|
|
5284
|
+
counts[val]++;
|
|
5285
|
+
count++;
|
|
5286
|
+
});
|
|
5287
|
+
return count > 0 ? {
|
|
5288
|
+
min: getHistogramPercentileValue(counts, integerRange.min, count, range[0]),
|
|
5289
|
+
max: getHistogramPercentileValue(counts, integerRange.min, count, range[1])
|
|
5290
|
+
} : {min: 0, max: 255};
|
|
5291
|
+
}
|
|
5292
|
+
|
|
5293
|
+
function getApproxHistogramPercentileStats(data, bands, bandIds, noData, range) {
|
|
5294
|
+
var bounds = getBandValueBounds(data, bands, bandIds, noData);
|
|
5295
|
+
var binCount = 65536;
|
|
5296
|
+
var counts, count, scale, maxBin;
|
|
5297
|
+
if (!bounds || bounds.max <= bounds.min) {
|
|
5298
|
+
return bounds || {min: 0, max: 255};
|
|
5299
|
+
}
|
|
5300
|
+
counts = new Uint32Array(binCount);
|
|
5301
|
+
count = 0;
|
|
5302
|
+
scale = (binCount - 1) / (bounds.max - bounds.min);
|
|
5303
|
+
maxBin = binCount - 1;
|
|
5304
|
+
forEachBandValue(data, bands, bandIds, noData, function(val) {
|
|
5305
|
+
counts[Math.max(0, Math.min(maxBin, Math.floor((val - bounds.min) * scale)))]++;
|
|
5306
|
+
count++;
|
|
5307
|
+
});
|
|
5308
|
+
return count > 0 ? {
|
|
5309
|
+
min: getApproxHistogramPercentileValue(counts, bounds, count, range[0]),
|
|
5310
|
+
max: getApproxHistogramPercentileValue(counts, bounds, count, range[1])
|
|
5311
|
+
} : {min: 0, max: 255};
|
|
5312
|
+
}
|
|
5313
|
+
|
|
5314
|
+
function getBandValueBounds(data, bands, bandIds, noData) {
|
|
5315
|
+
var min = Infinity;
|
|
5316
|
+
var max = -Infinity;
|
|
5317
|
+
forEachBandValue(data, bands, bandIds, noData, function(val) {
|
|
5318
|
+
if (val < min) min = val;
|
|
5319
|
+
if (val > max) max = val;
|
|
5320
|
+
});
|
|
5321
|
+
return min < Infinity ? {min: min, max: max} : null;
|
|
5322
|
+
}
|
|
5323
|
+
|
|
5324
|
+
function getHistogramPercentileValue(counts, offset, count, pct) {
|
|
5325
|
+
var target = getPercentileRank(count, pct);
|
|
5326
|
+
var sum = 0;
|
|
5327
|
+
for (var i = 0; i < counts.length; i++) {
|
|
5328
|
+
sum += counts[i];
|
|
5329
|
+
if (sum > target) return i + offset;
|
|
5330
|
+
}
|
|
5331
|
+
return counts.length - 1 + offset;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
function getApproxHistogramPercentileValue(counts, bounds, count, pct) {
|
|
5335
|
+
var bin = getHistogramPercentileValue(counts, 0, count, pct);
|
|
5336
|
+
return bounds.min + bin / (counts.length - 1) * (bounds.max - bounds.min);
|
|
5337
|
+
}
|
|
5338
|
+
|
|
5339
|
+
function forEachBandValue(data, bands, bandIds, noData, cb) {
|
|
5340
|
+
var val;
|
|
5341
|
+
for (var i = 0; i < data.length; i += bands) {
|
|
5342
|
+
for (var j = 0; j < bandIds.length; j++) {
|
|
5343
|
+
val = data[i + bandIds[j]];
|
|
5344
|
+
if (!isValidBandValue(val, noData)) continue;
|
|
5345
|
+
cb(val);
|
|
5346
|
+
}
|
|
5347
|
+
}
|
|
5348
|
+
}
|
|
5349
|
+
|
|
5350
|
+
function isValidBandValue(val, noData) {
|
|
5351
|
+
return isFinite(val) && (noData === null || noData === undefined || val != noData);
|
|
5352
|
+
}
|
|
5353
|
+
|
|
5354
|
+
function getPercentileRank(count, pct) {
|
|
5355
|
+
return Math.max(0, Math.min(count - 1, Math.floor((count - 1) * pct / 100)));
|
|
5356
|
+
}
|
|
5357
|
+
|
|
5358
|
+
function allSamplesAreNoData(data, offset, bands, noData) {
|
|
5359
|
+
var n = Math.min(bands, 3);
|
|
5360
|
+
for (var i = 0; i < n; i++) {
|
|
5361
|
+
if (data[offset + i] != noData) return false;
|
|
5362
|
+
}
|
|
5363
|
+
return true;
|
|
5364
|
+
}
|
|
5365
|
+
|
|
5366
|
+
function copyObjectOrArray(obj) {
|
|
5367
|
+
return obj && obj.concat ? obj.concat() : utils.extend({}, obj);
|
|
5368
|
+
}
|
|
5369
|
+
|
|
5370
|
+
var RasterUtils = /*#__PURE__*/Object.freeze({
|
|
5371
|
+
__proto__: null,
|
|
5372
|
+
clipRasterToBBox: clipRasterToBBox,
|
|
5373
|
+
copyRasterData: copyRasterData,
|
|
5374
|
+
copyRasterGrid: copyRasterGrid,
|
|
5375
|
+
copyRasterPreview: copyRasterPreview,
|
|
5376
|
+
copyRasterView: copyRasterView,
|
|
5377
|
+
copyTypedArray: copyTypedArray,
|
|
5378
|
+
createRasterPreview: createRasterPreview,
|
|
5379
|
+
cropRasterGrid: cropRasterGrid,
|
|
5380
|
+
getRasterBBox: getRasterBBox,
|
|
5381
|
+
getRasterBandCount: getRasterBandCount,
|
|
5382
|
+
getRasterCrop: getRasterCrop,
|
|
5383
|
+
getRasterGrid: getRasterGrid,
|
|
5384
|
+
getRasterHeight: getRasterHeight,
|
|
5385
|
+
getRasterLayerBounds: getRasterLayerBounds,
|
|
5386
|
+
getRasterPixelType: getRasterPixelType,
|
|
5387
|
+
getRasterPreview: getRasterPreview,
|
|
5388
|
+
getRasterScalingStats: getRasterScalingStats,
|
|
5389
|
+
getRasterScalingStatsKey: getRasterScalingStatsKey,
|
|
5390
|
+
getRasterTransform: getRasterTransform,
|
|
5391
|
+
getRasterView: getRasterView,
|
|
5392
|
+
getRasterViewRecipe: getRasterViewRecipe,
|
|
5393
|
+
getRasterViewScalingStats: getRasterViewScalingStats,
|
|
5394
|
+
getRasterWidth: getRasterWidth,
|
|
5395
|
+
intersectBboxes: intersectBboxes,
|
|
5396
|
+
renderRasterPreview: renderRasterPreview,
|
|
5397
|
+
renderRasterViewportPreview: renderRasterViewportPreview,
|
|
5398
|
+
requireRasterLayer: requireRasterLayer
|
|
5399
|
+
});
|
|
5400
|
+
|
|
4775
5401
|
// Insert a column of values into a (new or existing) data field
|
|
4776
5402
|
function insertFieldValues(lyr, fieldName, values) {
|
|
4777
5403
|
var size = getFeatureCount(lyr) || values.length,
|
|
@@ -4864,7 +5490,9 @@
|
|
|
4864
5490
|
|
|
4865
5491
|
function getFeatureCount(lyr) {
|
|
4866
5492
|
var count = 0;
|
|
4867
|
-
if (lyr
|
|
5493
|
+
if (layerHasRaster(lyr)) {
|
|
5494
|
+
count = 1;
|
|
5495
|
+
} else if (lyr.data) {
|
|
4868
5496
|
count = lyr.data.size();
|
|
4869
5497
|
} else if (lyr.shapes) {
|
|
4870
5498
|
count = lyr.shapes.length;
|
|
@@ -5052,6 +5680,7 @@
|
|
|
5052
5680
|
if (lyr.shapes) {
|
|
5053
5681
|
copy.shapes = cloneShapes(lyr.shapes);
|
|
5054
5682
|
}
|
|
5683
|
+
if (lyr.raster) copy.raster = copyRasterData(lyr.raster);
|
|
5055
5684
|
return copy;
|
|
5056
5685
|
}
|
|
5057
5686
|
|
|
@@ -5087,10 +5716,13 @@
|
|
|
5087
5716
|
bounds = getPointBounds$1(lyr.shapes);
|
|
5088
5717
|
} else if (lyr.geometry_type == 'polygon' || lyr.geometry_type == 'polyline') {
|
|
5089
5718
|
bounds = getPathBounds(lyr.shapes, arcs);
|
|
5719
|
+
} else if (layerHasRaster(lyr)) {
|
|
5720
|
+
bounds = getRasterLayerBounds(lyr);
|
|
5090
5721
|
} else ;
|
|
5091
5722
|
return bounds;
|
|
5092
5723
|
}
|
|
5093
5724
|
|
|
5725
|
+
|
|
5094
5726
|
function isolateLayer(layer, dataset) {
|
|
5095
5727
|
return utils.defaults({
|
|
5096
5728
|
layers: dataset.layers.filter(function(lyr) {return lyr == layer;})
|
|
@@ -5129,6 +5761,7 @@
|
|
|
5129
5761
|
layerHasNonNullShapes: layerHasNonNullShapes,
|
|
5130
5762
|
layerHasPaths: layerHasPaths,
|
|
5131
5763
|
layerHasPoints: layerHasPoints,
|
|
5764
|
+
layerHasRaster: layerHasRaster,
|
|
5132
5765
|
layerIsEmpty: layerIsEmpty,
|
|
5133
5766
|
layerIsGeometric: layerIsGeometric,
|
|
5134
5767
|
layerIsRectangle: layerIsRectangle,
|
|
@@ -8260,6 +8893,12 @@
|
|
|
8260
8893
|
});
|
|
8261
8894
|
}
|
|
8262
8895
|
|
|
8896
|
+
function datasetHasRaster(dataset) {
|
|
8897
|
+
return utils.some(dataset.layers, function(lyr) {
|
|
8898
|
+
return layerHasRaster(lyr);
|
|
8899
|
+
});
|
|
8900
|
+
}
|
|
8901
|
+
|
|
8263
8902
|
function datasetHasPaths(dataset) {
|
|
8264
8903
|
return utils.some(dataset.layers, function(lyr) {
|
|
8265
8904
|
return layerHasPaths(lyr);
|
|
@@ -8377,6 +9016,7 @@
|
|
|
8377
9016
|
copyDatasetInfo: copyDatasetInfo,
|
|
8378
9017
|
datasetHasGeometry: datasetHasGeometry,
|
|
8379
9018
|
datasetHasPaths: datasetHasPaths,
|
|
9019
|
+
datasetHasRaster: datasetHasRaster,
|
|
8380
9020
|
datasetIsEmpty: datasetIsEmpty,
|
|
8381
9021
|
getDatasetBounds: getDatasetBounds,
|
|
8382
9022
|
mergeDatasetInfo: mergeDatasetInfo,
|
|
@@ -8489,8 +9129,14 @@
|
|
|
8489
9129
|
function guessInputFileType(file) {
|
|
8490
9130
|
var ext = getFileExtension(file || '').toLowerCase(),
|
|
8491
9131
|
type = null;
|
|
8492
|
-
if (ext == 'dbf' || ext == 'shp' || ext == 'kml' || ext == 'svg' || ext == 'fgb' || ext == 'gpkg') {
|
|
9132
|
+
if (ext == 'dbf' || ext == 'shp' || ext == 'kml' || ext == 'svg' || ext == 'fgb' || ext == 'gpkg' || ext == 'png') {
|
|
8493
9133
|
type = ext;
|
|
9134
|
+
} else if (ext == 'jpg' || ext == 'jpeg') {
|
|
9135
|
+
type = 'jpeg';
|
|
9136
|
+
} else if (ext == 'tif' || ext == 'tiff') {
|
|
9137
|
+
type = 'geotiff';
|
|
9138
|
+
} else if (isWorldFileExtension(ext)) {
|
|
9139
|
+
type = 'world';
|
|
8494
9140
|
} else if (ext == 'parquet' || ext == 'geoparquet') {
|
|
8495
9141
|
type = 'parquet';
|
|
8496
9142
|
} else if (isAuxiliaryInputFileType(ext)) {
|
|
@@ -8507,7 +9153,15 @@
|
|
|
8507
9153
|
|
|
8508
9154
|
// File types that can be imported but are not convertible to datasets
|
|
8509
9155
|
function isAuxiliaryInputFileType(type) {
|
|
8510
|
-
return type == 'prj' || type == 'shx' || type == 'cpg';
|
|
9156
|
+
return type == 'prj' || type == 'shx' || type == 'cpg' || type == 'world';
|
|
9157
|
+
}
|
|
9158
|
+
|
|
9159
|
+
function isRasterImageInputType(type) {
|
|
9160
|
+
return type == 'png' || type == 'jpeg';
|
|
9161
|
+
}
|
|
9162
|
+
|
|
9163
|
+
function isWorldFileExtension(ext) {
|
|
9164
|
+
return /^(tfw|pgw|pngw|jgw|jpw|jpgw|jpegw|wld)$/i.test(ext || '');
|
|
8511
9165
|
}
|
|
8512
9166
|
|
|
8513
9167
|
function guessInputContentType(content) {
|
|
@@ -8634,7 +9288,9 @@
|
|
|
8634
9288
|
function isSupportedBinaryInputType(path) {
|
|
8635
9289
|
var ext = getFileExtension(path).toLowerCase();
|
|
8636
9290
|
return ext == 'shp' || ext == 'shx' || ext == 'dbf' ||
|
|
8637
|
-
ext == 'fgb' || ext == 'gpkg' || ext == 'parquet' || ext == 'geoparquet' ||
|
|
9291
|
+
ext == 'fgb' || ext == 'gpkg' || ext == 'parquet' || ext == 'geoparquet' ||
|
|
9292
|
+
ext == 'tif' || ext == 'tiff' || ext == 'png' || ext == 'jpg' || ext == 'jpeg' ||
|
|
9293
|
+
ext == PACKAGE_EXT; // GUI also supports zip files
|
|
8638
9294
|
}
|
|
8639
9295
|
|
|
8640
9296
|
function isImportableAsBinary(path) {
|
|
@@ -8663,7 +9319,9 @@
|
|
|
8663
9319
|
isKmzFile: isKmzFile,
|
|
8664
9320
|
isPackageFile: isPackageFile,
|
|
8665
9321
|
isPotentialCommandFile: isPotentialCommandFile,
|
|
9322
|
+
isRasterImageInputType: isRasterImageInputType,
|
|
8666
9323
|
isSupportedBinaryInputType: isSupportedBinaryInputType,
|
|
9324
|
+
isWorldFileExtension: isWorldFileExtension,
|
|
8667
9325
|
isZipFile: isZipFile,
|
|
8668
9326
|
looksLikeContentFile: looksLikeContentFile,
|
|
8669
9327
|
looksLikeImportableFile: looksLikeImportableFile,
|
|
@@ -17490,7 +18148,7 @@
|
|
|
17490
18148
|
// higher-level mapshaper-svg.mjs (which would otherwise form a cycle).
|
|
17491
18149
|
|
|
17492
18150
|
function featureHasSvgSymbol(d) {
|
|
17493
|
-
return !!(d && (d['svg-symbol'] || d.r));
|
|
18151
|
+
return !!(d && (d['svg-symbol'] || d.r || d.icon || d['icon-size']));
|
|
17494
18152
|
}
|
|
17495
18153
|
|
|
17496
18154
|
function featureHasLabel(d) {
|
|
@@ -17763,6 +18421,9 @@
|
|
|
17763
18421
|
'font-style': null,
|
|
17764
18422
|
'font-stretch': null,
|
|
17765
18423
|
'font-weight': null,
|
|
18424
|
+
icon: null,
|
|
18425
|
+
'icon-color': 'color',
|
|
18426
|
+
'icon-size': 'number',
|
|
17766
18427
|
'label-text': null, // leaving this null
|
|
17767
18428
|
'letter-spacing': 'measure',
|
|
17768
18429
|
'line-height': 'measure',
|
|
@@ -18110,12 +18771,44 @@
|
|
|
18110
18771
|
if (d['svg-symbol']) {
|
|
18111
18772
|
return renderComplexSymbol(d['svg-symbol']);
|
|
18112
18773
|
}
|
|
18774
|
+
if (featureHasIcon(d)) {
|
|
18775
|
+
return renderIcon(d);
|
|
18776
|
+
}
|
|
18113
18777
|
if (d.r > 0) {
|
|
18114
18778
|
return circle(d);
|
|
18115
18779
|
}
|
|
18116
18780
|
return empty();
|
|
18117
18781
|
}
|
|
18118
18782
|
|
|
18783
|
+
function featureHasIcon(d) {
|
|
18784
|
+
return !!(d && (d.icon || d['icon-size'] || (d['icon-color'] && d.r > 0)));
|
|
18785
|
+
}
|
|
18786
|
+
|
|
18787
|
+
function renderIcon(d) {
|
|
18788
|
+
var type = d.icon || 'circle';
|
|
18789
|
+
var r = getIconRadius(d);
|
|
18790
|
+
if (r > 0 === false) return empty();
|
|
18791
|
+
if (type == 'circle') return circle(getIconStyleData(d, r));
|
|
18792
|
+
if (type == 'square') return square(getIconStyleData(d, r), 0, 0);
|
|
18793
|
+
if (type == 'ring') return ring(getIconStyleData(d, r), 0, 0);
|
|
18794
|
+
if (type == 'star') return star(getIconStyleData(d, r));
|
|
18795
|
+
message('Unknown icon type: ' + type);
|
|
18796
|
+
return empty();
|
|
18797
|
+
}
|
|
18798
|
+
|
|
18799
|
+
function getIconRadius(d) {
|
|
18800
|
+
if (d['icon-size'] > 0) return d['icon-size'] / 2;
|
|
18801
|
+
if (d.r > 0) return d.r;
|
|
18802
|
+
return 5;
|
|
18803
|
+
}
|
|
18804
|
+
|
|
18805
|
+
function getIconStyleData(d, r) {
|
|
18806
|
+
var o = utils.extend({}, d);
|
|
18807
|
+
o.r = r;
|
|
18808
|
+
o.fill = d['icon-color'] || d.fill || 'black';
|
|
18809
|
+
return o;
|
|
18810
|
+
}
|
|
18811
|
+
|
|
18119
18812
|
function renderComplexSymbol(sym, x, y) {
|
|
18120
18813
|
if (utils.isString(sym)) {
|
|
18121
18814
|
sym = JSON.parse(sym);
|
|
@@ -18190,10 +18883,44 @@
|
|
|
18190
18883
|
height: r * 2
|
|
18191
18884
|
}
|
|
18192
18885
|
};
|
|
18193
|
-
applyStyleAttributes(o, 'point', d);
|
|
18886
|
+
applyStyleAttributes(o, 'point', d, nonCirclePointFilter);
|
|
18887
|
+
return o;
|
|
18888
|
+
}
|
|
18889
|
+
|
|
18890
|
+
function ring(d, x, y) {
|
|
18891
|
+
var o = circle(d, x, y);
|
|
18892
|
+
o.properties.fill = 'none';
|
|
18893
|
+
o.properties.stroke = d.fill;
|
|
18894
|
+
if (!o.properties['stroke-width']) {
|
|
18895
|
+
o.properties['stroke-width'] = 1;
|
|
18896
|
+
}
|
|
18897
|
+
return o;
|
|
18898
|
+
}
|
|
18899
|
+
|
|
18900
|
+
function star(d) {
|
|
18901
|
+
var coords = getStarCoords$1(d.r);
|
|
18902
|
+
var o = importPolygon([coords]);
|
|
18903
|
+
applyStyleAttributes(o, 'point', d, nonCirclePointFilter);
|
|
18194
18904
|
return o;
|
|
18195
18905
|
}
|
|
18196
18906
|
|
|
18907
|
+
function nonCirclePointFilter(k) {
|
|
18908
|
+
return k != 'r';
|
|
18909
|
+
}
|
|
18910
|
+
|
|
18911
|
+
function getStarCoords$1(r) {
|
|
18912
|
+
var coords = [];
|
|
18913
|
+
var innerR = r * 0.42;
|
|
18914
|
+
var angle, len;
|
|
18915
|
+
for (var i=0; i<10; i++) {
|
|
18916
|
+
len = i % 2 === 0 ? r : innerR;
|
|
18917
|
+
angle = -Math.PI / 2 + i * Math.PI / 5;
|
|
18918
|
+
coords.push([roundToTenths(Math.cos(angle) * len), roundToTenths(Math.sin(angle) * len)]);
|
|
18919
|
+
}
|
|
18920
|
+
coords.push(coords[0].concat());
|
|
18921
|
+
return coords;
|
|
18922
|
+
}
|
|
18923
|
+
|
|
18197
18924
|
function line(d, x, y) {
|
|
18198
18925
|
var coords, o;
|
|
18199
18926
|
coords = [[x, y], [x + (d.dx || 0), y + (d.dy || 0)]];
|
|
@@ -18899,7 +19626,7 @@
|
|
|
18899
19626
|
|
|
18900
19627
|
// just a dot, no label or icon
|
|
18901
19628
|
function isSimpleCircle(rec) {
|
|
18902
|
-
return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text']);
|
|
19629
|
+
return rec && (rec.r > 0 && !rec['svg-symbol'] && !rec['label-text'] && !rec.icon && !rec['icon-size'] && !rec['icon-color']);
|
|
18903
19630
|
}
|
|
18904
19631
|
|
|
18905
19632
|
function importMultiPoint(coords, rec) {
|
|
@@ -18927,6 +19654,8 @@
|
|
|
18927
19654
|
importPolygon: importPolygon
|
|
18928
19655
|
});
|
|
18929
19656
|
|
|
19657
|
+
var ILLUSTRATOR_PATH_VERTEX_LIMIT = 32000;
|
|
19658
|
+
|
|
18930
19659
|
//
|
|
18931
19660
|
function exportSVG(dataset, opts) {
|
|
18932
19661
|
var namespace = 'xmlns="http://www.w3.org/2000/svg"';
|
|
@@ -18970,6 +19699,8 @@
|
|
|
18970
19699
|
var obj;
|
|
18971
19700
|
if (layerHasFurniture(lyr)) {
|
|
18972
19701
|
obj = exportFurnitureLayerForSVG(lyr, frame, opts);
|
|
19702
|
+
} else if (layerHasRaster(lyr)) {
|
|
19703
|
+
obj = exportRasterLayerForSVG(lyr, frame, opts);
|
|
18973
19704
|
} else {
|
|
18974
19705
|
obj = exportLayerForSVG(lyr, dataset, opts);
|
|
18975
19706
|
}
|
|
@@ -19086,11 +19817,147 @@ ${svg}
|
|
|
19086
19817
|
return layerObj;
|
|
19087
19818
|
}
|
|
19088
19819
|
|
|
19820
|
+
function exportRasterLayerForSVG(lyr, frame, opts) {
|
|
19821
|
+
var raster = lyr.raster;
|
|
19822
|
+
var clipped = clipRasterPreviewToFrame(raster, frame);
|
|
19823
|
+
var bbox = transformRasterBboxForSVG(clipped.bbox, frame);
|
|
19824
|
+
var href;
|
|
19825
|
+
var layerObj = getEmptyLayerForSVG(lyr, opts);
|
|
19826
|
+
if (!clipped.preview.width || !clipped.preview.height) {
|
|
19827
|
+
layerObj.children = [];
|
|
19828
|
+
return layerObj;
|
|
19829
|
+
}
|
|
19830
|
+
href = encodeRasterPreview(clipped.preview, opts);
|
|
19831
|
+
layerObj.children = [{
|
|
19832
|
+
tag: 'image',
|
|
19833
|
+
properties: {
|
|
19834
|
+
x: bbox[0],
|
|
19835
|
+
y: bbox[1],
|
|
19836
|
+
width: bbox[2] - bbox[0],
|
|
19837
|
+
height: bbox[3] - bbox[1],
|
|
19838
|
+
href: href,
|
|
19839
|
+
preserveAspectRatio: 'none'
|
|
19840
|
+
}
|
|
19841
|
+
}];
|
|
19842
|
+
return layerObj;
|
|
19843
|
+
}
|
|
19844
|
+
|
|
19845
|
+
function clipRasterPreviewToFrame(raster, frame) {
|
|
19846
|
+
var rasterBbox = getRasterBBox(raster);
|
|
19847
|
+
var preview = getRasterPreview(raster);
|
|
19848
|
+
var rasterBounds = new Bounds(rasterBbox);
|
|
19849
|
+
var clipBounds = new Bounds(frame.bbox);
|
|
19850
|
+
var bbox = intersectBboxes(rasterBounds.toArray(), clipBounds.toArray()) || [0, 0, 0, 0];
|
|
19851
|
+
var crop = getRasterPreviewCrop(rasterBbox, preview, bbox);
|
|
19852
|
+
return {
|
|
19853
|
+
bbox: bbox,
|
|
19854
|
+
preview: cropRasterPreview(preview, crop)
|
|
19855
|
+
};
|
|
19856
|
+
}
|
|
19857
|
+
|
|
19858
|
+
function getRasterPreviewCrop(rasterBbox, preview, bbox) {
|
|
19859
|
+
var rb = rasterBbox;
|
|
19860
|
+
var p = preview;
|
|
19861
|
+
var x0 = Math.max(0, Math.floor((bbox[0] - rb[0]) / (rb[2] - rb[0]) * p.width));
|
|
19862
|
+
var x1 = Math.min(p.width, Math.ceil((bbox[2] - rb[0]) / (rb[2] - rb[0]) * p.width));
|
|
19863
|
+
var y0 = Math.max(0, Math.floor((rb[3] - bbox[3]) / (rb[3] - rb[1]) * p.height));
|
|
19864
|
+
var y1 = Math.min(p.height, Math.ceil((rb[3] - bbox[1]) / (rb[3] - rb[1]) * p.height));
|
|
19865
|
+
return {
|
|
19866
|
+
x: x0,
|
|
19867
|
+
y: y0,
|
|
19868
|
+
width: Math.max(0, x1 - x0),
|
|
19869
|
+
height: Math.max(0, y1 - y0)
|
|
19870
|
+
};
|
|
19871
|
+
}
|
|
19872
|
+
|
|
19873
|
+
function cropRasterPreview(preview, crop) {
|
|
19874
|
+
if (crop.x === 0 && crop.y === 0 && crop.width == preview.width && crop.height == preview.height) {
|
|
19875
|
+
return preview;
|
|
19876
|
+
}
|
|
19877
|
+
var pixels = new Uint8ClampedArray(crop.width * crop.height * 4);
|
|
19878
|
+
var src, dest, rowBytes = crop.width * 4;
|
|
19879
|
+
for (var y = 0; y < crop.height; y++) {
|
|
19880
|
+
src = ((crop.y + y) * preview.width + crop.x) * 4;
|
|
19881
|
+
dest = y * rowBytes;
|
|
19882
|
+
pixels.set(preview.pixels.subarray(src, src + rowBytes), dest);
|
|
19883
|
+
}
|
|
19884
|
+
return Object.assign({}, preview, {
|
|
19885
|
+
width: crop.width,
|
|
19886
|
+
height: crop.height,
|
|
19887
|
+
pixels: pixels
|
|
19888
|
+
});
|
|
19889
|
+
}
|
|
19890
|
+
|
|
19891
|
+
function transformRasterBboxForSVG(bbox, frame) {
|
|
19892
|
+
var srcBounds = new Bounds(frame.bbox);
|
|
19893
|
+
var destBounds = frame.bbox2 ? new Bounds(frame.bbox2) : new Bounds(0, 0, frame.width, frame.height);
|
|
19894
|
+
srcBounds.fillOut(destBounds.width() / destBounds.height());
|
|
19895
|
+
var fwd = srcBounds.getTransform(destBounds, frame.invert_y);
|
|
19896
|
+
var p1 = fwd.transform(bbox[0], bbox[3]);
|
|
19897
|
+
var p2 = fwd.transform(bbox[2], bbox[1]);
|
|
19898
|
+
return [p1[0], p1[1], p2[0], p2[1]];
|
|
19899
|
+
}
|
|
19900
|
+
|
|
19901
|
+
function encodeRasterPreview(preview, opts) {
|
|
19902
|
+
var format = getSvgRasterFormat(preview, opts);
|
|
19903
|
+
var data = format == 'png' ? encodePng(preview) : encodeJpeg(preview, opts);
|
|
19904
|
+
return 'data:image/' + format + ';base64,' + data;
|
|
19905
|
+
}
|
|
19906
|
+
|
|
19907
|
+
function getSvgRasterFormat(preview, opts) {
|
|
19908
|
+
var fmt = opts.svg_raster_format || opts.raster_format || null;
|
|
19909
|
+
if (fmt) return fmt == 'jpg' ? 'jpeg' : fmt;
|
|
19910
|
+
return previewHasTransparency(preview) ? 'png' : 'jpeg';
|
|
19911
|
+
}
|
|
19912
|
+
|
|
19913
|
+
function previewHasTransparency(preview) {
|
|
19914
|
+
var pixels = preview.pixels;
|
|
19915
|
+
for (var i = 3; i < pixels.length; i += 4) {
|
|
19916
|
+
if (pixels[i] < 255) return true;
|
|
19917
|
+
}
|
|
19918
|
+
return false;
|
|
19919
|
+
}
|
|
19920
|
+
|
|
19921
|
+
function encodeJpeg(preview, opts) {
|
|
19922
|
+
if (runningInBrowser() && typeof document != 'undefined') {
|
|
19923
|
+
return encodeWithCanvas(preview, 'image/jpeg', opts.svg_raster_quality || 0.85);
|
|
19924
|
+
}
|
|
19925
|
+
var jpeg = require$1('jpeg-js');
|
|
19926
|
+
var quality = Math.round((opts.svg_raster_quality || 0.85) * 100);
|
|
19927
|
+
return Buffer.from(jpeg.encode({
|
|
19928
|
+
data: Buffer.from(preview.pixels),
|
|
19929
|
+
width: preview.width,
|
|
19930
|
+
height: preview.height
|
|
19931
|
+
}, quality).data).toString('base64');
|
|
19932
|
+
}
|
|
19933
|
+
|
|
19934
|
+
function encodePng(preview) {
|
|
19935
|
+
if (runningInBrowser() && typeof document != 'undefined') {
|
|
19936
|
+
return encodeWithCanvas(preview, 'image/png');
|
|
19937
|
+
}
|
|
19938
|
+
var PNG = require$1('pngjs').PNG;
|
|
19939
|
+
var png = new PNG({width: preview.width, height: preview.height});
|
|
19940
|
+
png.data = Buffer.from(preview.pixels);
|
|
19941
|
+
return Buffer.from(PNG.sync.write(png)).toString('base64');
|
|
19942
|
+
}
|
|
19943
|
+
|
|
19944
|
+
function encodeWithCanvas(preview, type, quality) {
|
|
19945
|
+
var canvas = document.createElement('canvas');
|
|
19946
|
+
var ctx = canvas.getContext('2d');
|
|
19947
|
+
var dataUrl;
|
|
19948
|
+
canvas.width = preview.width;
|
|
19949
|
+
canvas.height = preview.height;
|
|
19950
|
+
ctx.putImageData(new ImageData(preview.pixels, preview.width, preview.height), 0, 0);
|
|
19951
|
+
dataUrl = canvas.toDataURL(type, quality);
|
|
19952
|
+
return dataUrl.split(',')[1];
|
|
19953
|
+
}
|
|
19954
|
+
|
|
19089
19955
|
function exportSymbolsForSVG(lyr, dataset, opts) {
|
|
19090
19956
|
// TODO: convert geojson features one at a time
|
|
19091
19957
|
var d = utils.defaults({layers: [lyr]}, dataset);
|
|
19092
19958
|
var geojson = exportDatasetAsGeoJSON(d, opts);
|
|
19093
19959
|
var features = geojson.features || geojson.geometries || (geojson.type ? [geojson] : []);
|
|
19960
|
+
warnIfIllustratorPathLimitExceeded(lyr, features);
|
|
19094
19961
|
var children = importGeoJSONFeatures(features, opts);
|
|
19095
19962
|
// Drop empty placeholder <g/> elements (features whose geometry was null in the
|
|
19096
19963
|
// source data, collapsed during simplification, or otherwise produced no
|
|
@@ -19109,6 +19976,53 @@ ${svg}
|
|
|
19109
19976
|
return children;
|
|
19110
19977
|
}
|
|
19111
19978
|
|
|
19979
|
+
function warnIfIllustratorPathLimitExceeded(lyr, features) {
|
|
19980
|
+
var count = 0;
|
|
19981
|
+
var max = 0;
|
|
19982
|
+
if (lyr.geometry_type != 'polygon' && lyr.geometry_type != 'polyline') return;
|
|
19983
|
+
features.forEach(function(feature) {
|
|
19984
|
+
var geom = feature.geometry || feature;
|
|
19985
|
+
var n = countSvgPathVertices(geom);
|
|
19986
|
+
if (n > ILLUSTRATOR_PATH_VERTEX_LIMIT) {
|
|
19987
|
+
count++;
|
|
19988
|
+
max = Math.max(max, n);
|
|
19989
|
+
}
|
|
19990
|
+
});
|
|
19991
|
+
if (count > 0) {
|
|
19992
|
+
warn(utils.format(
|
|
19993
|
+
'%,d SVG path%s in layer "%s" contain%s more than %,d vertices; Adobe Illustrator may not import %s. The largest path has %,d vertices.',
|
|
19994
|
+
count,
|
|
19995
|
+
utils.pluralSuffix(count),
|
|
19996
|
+
lyr.name || '[unnamed]',
|
|
19997
|
+
count == 1 ? 's' : '',
|
|
19998
|
+
ILLUSTRATOR_PATH_VERTEX_LIMIT,
|
|
19999
|
+
count == 1 ? 'it' : 'them',
|
|
20000
|
+
max
|
|
20001
|
+
));
|
|
20002
|
+
}
|
|
20003
|
+
}
|
|
20004
|
+
|
|
20005
|
+
function countSvgPathVertices(geom) {
|
|
20006
|
+
var coords = geom && geom.coordinates;
|
|
20007
|
+
if (!coords) return 0;
|
|
20008
|
+
if (geom.type == 'LineString') return coords.length;
|
|
20009
|
+
if (geom.type == 'MultiLineString' || geom.type == 'Polygon') {
|
|
20010
|
+
return sumPathLengths(coords);
|
|
20011
|
+
}
|
|
20012
|
+
if (geom.type == 'MultiPolygon') {
|
|
20013
|
+
return coords.reduce(function(sum, polygon) {
|
|
20014
|
+
return sum + sumPathLengths(polygon);
|
|
20015
|
+
}, 0);
|
|
20016
|
+
}
|
|
20017
|
+
return 0;
|
|
20018
|
+
}
|
|
20019
|
+
|
|
20020
|
+
function sumPathLengths(paths) {
|
|
20021
|
+
return paths.reduce(function(sum, path) {
|
|
20022
|
+
return sum + path.length;
|
|
20023
|
+
}, 0);
|
|
20024
|
+
}
|
|
20025
|
+
|
|
19112
20026
|
function isEmptyPlaceholder(o) {
|
|
19113
20027
|
return o.tag == 'g' && (!o.children || o.children.length === 0);
|
|
19114
20028
|
}
|
|
@@ -19206,7 +20120,7 @@ ${svg}
|
|
|
19206
20120
|
// TODO: set fill="none" in SVG symbols, not on the container
|
|
19207
20121
|
// (setting fill=none on the container overrides the default black fill
|
|
19208
20122
|
// on paths, which may alter the appearance of SVG icons loaded from external URLs).
|
|
19209
|
-
if (lyr.geometry_type == 'polyline' ||
|
|
20123
|
+
if (lyr.geometry_type == 'polyline' || layerHasSvgSymbolField(lyr)) {
|
|
19210
20124
|
layerObj.properties.fill = 'none';
|
|
19211
20125
|
}
|
|
19212
20126
|
|
|
@@ -19229,6 +20143,15 @@ ${svg}
|
|
|
19229
20143
|
}
|
|
19230
20144
|
|
|
19231
20145
|
function layerHasSvgSymbols(lyr) {
|
|
20146
|
+
return lyr.geometry_type == 'point' && lyr.data && (
|
|
20147
|
+
lyr.data.fieldExists('svg-symbol') ||
|
|
20148
|
+
lyr.data.fieldExists('icon') ||
|
|
20149
|
+
lyr.data.fieldExists('icon-size') ||
|
|
20150
|
+
(lyr.data.fieldExists('icon-color') && lyr.data.fieldExists('r'))
|
|
20151
|
+
);
|
|
20152
|
+
}
|
|
20153
|
+
|
|
20154
|
+
function layerHasSvgSymbolField(lyr) {
|
|
19232
20155
|
return lyr.geometry_type == 'point' && lyr.data && lyr.data.fieldExists('svg-symbol');
|
|
19233
20156
|
}
|
|
19234
20157
|
|
|
@@ -19245,6 +20168,7 @@ ${svg}
|
|
|
19245
20168
|
exportDataAttributesForSVG: exportDataAttributesForSVG,
|
|
19246
20169
|
exportFurnitureLayerForSVG: exportFurnitureLayerForSVG,
|
|
19247
20170
|
exportLayerForSVG: exportLayerForSVG,
|
|
20171
|
+
exportRasterLayerForSVG: exportRasterLayerForSVG,
|
|
19248
20172
|
exportSVG: exportSVG,
|
|
19249
20173
|
featureHasLabel: featureHasLabel,
|
|
19250
20174
|
featureHasSvgSymbol: featureHasSvgSymbol,
|
|
@@ -22481,6 +23405,8 @@ ${svg}
|
|
|
22481
23405
|
name: lyr.name || null,
|
|
22482
23406
|
geometry_type: lyr.geometry_type || null,
|
|
22483
23407
|
shapes: lyr.shapes || null,
|
|
23408
|
+
raster_type: lyr.raster_type || null,
|
|
23409
|
+
raster: lyr.raster ? exportRasterData(lyr.raster) : null,
|
|
22484
23410
|
data: data,
|
|
22485
23411
|
menu_order: lyr.menu_order || null,
|
|
22486
23412
|
pinned: lyr.pinned || opts.show_all || false,
|
|
@@ -22488,6 +23414,37 @@ ${svg}
|
|
|
22488
23414
|
};
|
|
22489
23415
|
}
|
|
22490
23416
|
|
|
23417
|
+
function exportRasterData(raster) {
|
|
23418
|
+
var copy = Object.assign({}, raster);
|
|
23419
|
+
if (raster.grid) {
|
|
23420
|
+
copy.grid = Object.assign({}, raster.grid);
|
|
23421
|
+
if (raster.grid.samples) {
|
|
23422
|
+
copy.grid.samples = typedArrayToBuffer(raster.grid.samples);
|
|
23423
|
+
}
|
|
23424
|
+
}
|
|
23425
|
+
if (raster.view) {
|
|
23426
|
+
copy.view = Object.assign({}, raster.view);
|
|
23427
|
+
if (raster.view.preview) {
|
|
23428
|
+
copy.view.preview = Object.assign({}, raster.view.preview);
|
|
23429
|
+
delete copy.view.preview.canvas;
|
|
23430
|
+
if (raster.view.preview.pixels) {
|
|
23431
|
+
copy.view.preview.pixels = typedArrayToBuffer(raster.view.preview.pixels);
|
|
23432
|
+
}
|
|
23433
|
+
}
|
|
23434
|
+
}
|
|
23435
|
+
if (raster.preview) {
|
|
23436
|
+
copy.preview = Object.assign({}, raster.preview);
|
|
23437
|
+
delete copy.preview.canvas;
|
|
23438
|
+
if (raster.preview.pixels) {
|
|
23439
|
+
copy.preview.pixels = typedArrayToBuffer(raster.preview.pixels);
|
|
23440
|
+
}
|
|
23441
|
+
}
|
|
23442
|
+
if (raster.pixels) {
|
|
23443
|
+
copy.pixels = typedArrayToBuffer(raster.pixels);
|
|
23444
|
+
}
|
|
23445
|
+
return copy;
|
|
23446
|
+
}
|
|
23447
|
+
|
|
22491
23448
|
function exportInfo(info) {
|
|
22492
23449
|
info = Object.assign({}, info);
|
|
22493
23450
|
if (info.crs && !info.crs_string && !info.wkt1) {
|
|
@@ -26128,7 +27085,7 @@ ${svg}
|
|
|
26128
27085
|
|
|
26129
27086
|
var writerPromise = null;
|
|
26130
27087
|
var zstdPromise = null;
|
|
26131
|
-
var dynamicImportModule$
|
|
27088
|
+
var dynamicImportModule$2 = Function('id', 'return import(id)');
|
|
26132
27089
|
|
|
26133
27090
|
async function exportGeoParquet(dataset, opts, filenameOverride) {
|
|
26134
27091
|
var writer = await loadGeoParquetWriter();
|
|
@@ -26343,7 +27300,7 @@ ${svg}
|
|
|
26343
27300
|
return mod;
|
|
26344
27301
|
}
|
|
26345
27302
|
if (!writerPromise) {
|
|
26346
|
-
writerPromise = dynamicImportModule$
|
|
27303
|
+
writerPromise = dynamicImportModule$2('hyparquet-writer');
|
|
26347
27304
|
}
|
|
26348
27305
|
var nodeMod = await writerPromise;
|
|
26349
27306
|
return nodeMod.default && !nodeMod.parquetWriteBuffer ? nodeMod.default : nodeMod;
|
|
@@ -26412,7 +27369,7 @@ ${svg}
|
|
|
26412
27369
|
mod = require$1('@bokuweb/zstd-wasm');
|
|
26413
27370
|
} else {
|
|
26414
27371
|
if (!zstdPromise) {
|
|
26415
|
-
zstdPromise = dynamicImportModule$
|
|
27372
|
+
zstdPromise = dynamicImportModule$2('@bokuweb/zstd-wasm');
|
|
26416
27373
|
}
|
|
26417
27374
|
mod = await zstdPromise;
|
|
26418
27375
|
}
|
|
@@ -26535,6 +27492,7 @@ ${svg}
|
|
|
26535
27492
|
async function exportDatasets(datasets, opts) {
|
|
26536
27493
|
var format = getOutputFormat(datasets[0], opts);
|
|
26537
27494
|
var files;
|
|
27495
|
+
validateRasterExportFormat(datasets, format);
|
|
26538
27496
|
if (format != 'geoparquet' && (opts.compression || opts.level !== undefined)) {
|
|
26539
27497
|
error('The compression= and level= options only apply to GeoParquet output');
|
|
26540
27498
|
}
|
|
@@ -26604,6 +27562,18 @@ ${svg}
|
|
|
26604
27562
|
return files;
|
|
26605
27563
|
}
|
|
26606
27564
|
|
|
27565
|
+
function validateRasterExportFormat(datasets, format) {
|
|
27566
|
+
if (!datasetsHaveRasterLayers(datasets)) return;
|
|
27567
|
+
if (format == 'svg' || format == PACKAGE_EXT) return;
|
|
27568
|
+
stop$1('Raster layers can only be exported as SVG or ' + PACKAGE_EXT + ' files');
|
|
27569
|
+
}
|
|
27570
|
+
|
|
27571
|
+
function datasetsHaveRasterLayers(datasets) {
|
|
27572
|
+
return datasets.some(function(dataset) {
|
|
27573
|
+
return dataset.layers && dataset.layers.some(layerHasRaster);
|
|
27574
|
+
});
|
|
27575
|
+
}
|
|
27576
|
+
|
|
26607
27577
|
// Return an array of objects with 'filename' and 'content' members.
|
|
26608
27578
|
//
|
|
26609
27579
|
function exportFileContent(dataset, opts) {
|
|
@@ -26616,6 +27586,7 @@ ${svg}
|
|
|
26616
27586
|
} else if (!exporter) {
|
|
26617
27587
|
error('Unknown output format:', outFmt);
|
|
26618
27588
|
}
|
|
27589
|
+
validateRasterExportFormat([dataset], outFmt);
|
|
26619
27590
|
|
|
26620
27591
|
// shallow-copy dataset and layers, so layers can be renamed for export
|
|
26621
27592
|
dataset = utils.defaults({
|
|
@@ -26691,7 +27662,11 @@ ${svg}
|
|
|
26691
27662
|
// Throw errors for various error conditions
|
|
26692
27663
|
function validateLayerData(layers) {
|
|
26693
27664
|
layers.forEach(function(lyr) {
|
|
26694
|
-
if (
|
|
27665
|
+
if (layerHasRaster(lyr)) {
|
|
27666
|
+
if (!getRasterBBox(lyr.raster) || !getRasterPreview(lyr.raster) && !(getRasterGrid(lyr.raster) && getRasterGrid(lyr.raster).samples)) {
|
|
27667
|
+
error('A raster layer is missing preview data or bounds');
|
|
27668
|
+
}
|
|
27669
|
+
} else if (!lyr.geometry_type) {
|
|
26695
27670
|
// allowing data-only layers
|
|
26696
27671
|
if (lyr.shapes && utils.some(lyr.shapes, function(o) {
|
|
26697
27672
|
return !!o;
|
|
@@ -28250,7 +29225,7 @@ ${svg}
|
|
|
28250
29225
|
|
|
28251
29226
|
};
|
|
28252
29227
|
|
|
28253
|
-
this.
|
|
29228
|
+
this.getHelpLines = function(cmdName) {
|
|
28254
29229
|
var helpCommands, singleCommand, lines;
|
|
28255
29230
|
if (cmdName) {
|
|
28256
29231
|
singleCommand = findCommandDefn(cmdName, getCommands());
|
|
@@ -28262,113 +29237,115 @@ ${svg}
|
|
|
28262
29237
|
helpCommands = getCommands().filter(function(cmd) {return cmd.name && cmd.describe || cmd.title;});
|
|
28263
29238
|
lines = getMultiCommandLines(helpCommands);
|
|
28264
29239
|
}
|
|
29240
|
+
return lines;
|
|
29241
|
+
};
|
|
28265
29242
|
|
|
28266
|
-
|
|
28267
|
-
|
|
28268
|
-
|
|
28269
|
-
var colWidth = calcColWidth(lines);
|
|
28270
|
-
var gutter = ' ';
|
|
28271
|
-
var indent = runningInBrowser() ? '' : ' ';
|
|
28272
|
-
var helpStr = lines.map(function(line) {
|
|
28273
|
-
if (Array.isArray(line)) {
|
|
28274
|
-
line = indent + utils.rpad(line[0], colWidth, ' ') + gutter + line[1];
|
|
28275
|
-
}
|
|
28276
|
-
return line;
|
|
28277
|
-
}).join('\n');
|
|
28278
|
-
return helpStr;
|
|
28279
|
-
}
|
|
28280
|
-
|
|
28281
|
-
function getSingleCommandLines(cmd) {
|
|
28282
|
-
var lines = [];
|
|
28283
|
-
var options = [];
|
|
28284
|
-
cmd.options.forEach(function(opt) {
|
|
28285
|
-
options = options.concat(getOptionLines(opt));
|
|
28286
|
-
});
|
|
29243
|
+
this.getHelpMessage = function(cmdName) {
|
|
29244
|
+
return formatLines(this.getHelpLines(cmdName));
|
|
29245
|
+
};
|
|
28287
29246
|
|
|
28288
|
-
|
|
28289
|
-
|
|
28290
|
-
|
|
28291
|
-
|
|
29247
|
+
function formatLines(lines) {
|
|
29248
|
+
var colWidth = calcColWidth(lines);
|
|
29249
|
+
var gutter = ' ';
|
|
29250
|
+
var indent = runningInBrowser() ? '' : ' ';
|
|
29251
|
+
var helpStr = lines.map(function(line) {
|
|
29252
|
+
if (Array.isArray(line)) {
|
|
29253
|
+
line = indent + utils.rpad(line[0], colWidth, ' ') + gutter + line[1];
|
|
28292
29254
|
}
|
|
29255
|
+
return line;
|
|
29256
|
+
}).join('\n');
|
|
29257
|
+
return helpStr;
|
|
29258
|
+
}
|
|
28293
29259
|
|
|
28294
|
-
|
|
28295
|
-
|
|
28296
|
-
|
|
28297
|
-
|
|
28298
|
-
|
|
28299
|
-
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
|
|
28303
|
-
|
|
28304
|
-
|
|
29260
|
+
function getSingleCommandLines(cmd) {
|
|
29261
|
+
var lines = [];
|
|
29262
|
+
var options = [];
|
|
29263
|
+
cmd.options.forEach(function(opt) {
|
|
29264
|
+
options = options.concat(getOptionLines(opt));
|
|
29265
|
+
});
|
|
29266
|
+
|
|
29267
|
+
lines.push('COMMAND', getCommandLine(cmd));
|
|
29268
|
+
if (options.length > 0) {
|
|
29269
|
+
lines.push('', 'OPTIONS');
|
|
29270
|
+
lines = lines.concat(options);
|
|
28305
29271
|
}
|
|
28306
29272
|
|
|
28307
|
-
|
|
28308
|
-
|
|
28309
|
-
|
|
28310
|
-
|
|
28311
|
-
|
|
28312
|
-
|
|
28313
|
-
|
|
28314
|
-
|
|
28315
|
-
|
|
28316
|
-
lines.push([label, description]);
|
|
28317
|
-
} else {
|
|
28318
|
-
label = opt.name;
|
|
28319
|
-
if (opt.alias) label += ', ' + opt.alias;
|
|
28320
|
-
if (opt.type != 'flag' && !opt.assign_to) label += '=';
|
|
28321
|
-
lines.push([label, description]);
|
|
28322
|
-
}
|
|
28323
|
-
return lines;
|
|
29273
|
+
// examples
|
|
29274
|
+
if (cmd.examples) {
|
|
29275
|
+
lines.push('', 'EXAMPLE' + (cmd.examples.length > 1 ? 'S' : ''));
|
|
29276
|
+
cmd.examples.forEach(function(ex, i) {
|
|
29277
|
+
if (i > 0) lines.push('');
|
|
29278
|
+
ex.split('\n').forEach(function(line, i) {
|
|
29279
|
+
lines.push(' ' + line);
|
|
29280
|
+
});
|
|
29281
|
+
});
|
|
28324
29282
|
}
|
|
29283
|
+
return lines;
|
|
29284
|
+
}
|
|
28325
29285
|
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
|
|
29286
|
+
function getOptionLines(opt, cmd) {
|
|
29287
|
+
var lines = [];
|
|
29288
|
+
var description = opt.describe;
|
|
29289
|
+
var label;
|
|
29290
|
+
if (!description) ; else if (opt.label) {
|
|
29291
|
+
lines.push([opt.label, description]);
|
|
29292
|
+
} else if (opt.DEFAULT) {
|
|
29293
|
+
label = opt.name + '=';
|
|
29294
|
+
lines.push(['<' + opt.name + '>', 'shortcut for ' + label]);
|
|
29295
|
+
lines.push([label, description]);
|
|
29296
|
+
} else {
|
|
29297
|
+
label = opt.name;
|
|
29298
|
+
if (opt.alias) label += ', ' + opt.alias;
|
|
29299
|
+
if (opt.type != 'flag' && !opt.assign_to) label += '=';
|
|
29300
|
+
lines.push([label, description]);
|
|
28330
29301
|
}
|
|
29302
|
+
return lines;
|
|
29303
|
+
}
|
|
28331
29304
|
|
|
28332
|
-
|
|
28333
|
-
|
|
28334
|
-
|
|
28335
|
-
|
|
29305
|
+
function getCommandLine(cmd) {
|
|
29306
|
+
var name = cmd.name ? "-" + cmd.name : '';
|
|
29307
|
+
if (cmd.alias) name += ', -' + cmd.alias;
|
|
29308
|
+
return [name, cmd.describe || '(undocumented command)'];
|
|
29309
|
+
}
|
|
28336
29310
|
|
|
28337
|
-
|
|
28338
|
-
|
|
28339
|
-
|
|
28340
|
-
|
|
28341
|
-
} else {
|
|
28342
|
-
lines.push(getCommandLine(cmd));
|
|
28343
|
-
}
|
|
28344
|
-
});
|
|
29311
|
+
function getMultiCommandLines(commands) {
|
|
29312
|
+
var lines = [];
|
|
29313
|
+
// usage
|
|
29314
|
+
if (_usage) lines.push(_usage);
|
|
28345
29315
|
|
|
28346
|
-
|
|
28347
|
-
|
|
28348
|
-
|
|
28349
|
-
|
|
28350
|
-
|
|
28351
|
-
|
|
29316
|
+
// list of commands
|
|
29317
|
+
commands.forEach(function(cmd) {
|
|
29318
|
+
if (cmd.title) {
|
|
29319
|
+
lines.push('', cmd.title);
|
|
29320
|
+
} else {
|
|
29321
|
+
lines.push(getCommandLine(cmd));
|
|
28352
29322
|
}
|
|
29323
|
+
});
|
|
28353
29324
|
|
|
28354
|
-
|
|
28355
|
-
|
|
28356
|
-
|
|
28357
|
-
|
|
28358
|
-
|
|
29325
|
+
// examples
|
|
29326
|
+
if (_examples.length > 0) {
|
|
29327
|
+
lines.push('', 'Examples');
|
|
29328
|
+
_examples.forEach(function(str) {
|
|
29329
|
+
lines.push('', str);
|
|
29330
|
+
});
|
|
28359
29331
|
}
|
|
28360
29332
|
|
|
28361
|
-
|
|
28362
|
-
|
|
28363
|
-
|
|
28364
|
-
lines.forEach(function(line) {
|
|
28365
|
-
if (Array.isArray(line)) {
|
|
28366
|
-
w = Math.max(w, line[0].length);
|
|
28367
|
-
}
|
|
28368
|
-
});
|
|
28369
|
-
return w;
|
|
29333
|
+
// note
|
|
29334
|
+
if (_note) {
|
|
29335
|
+
lines.push('', _note);
|
|
28370
29336
|
}
|
|
28371
|
-
|
|
29337
|
+
return lines;
|
|
29338
|
+
}
|
|
29339
|
+
|
|
29340
|
+
function calcColWidth(lines) {
|
|
29341
|
+
var w = 0;
|
|
29342
|
+
lines.forEach(function(line) {
|
|
29343
|
+
if (Array.isArray(line)) {
|
|
29344
|
+
w = Math.max(w, line[0].length);
|
|
29345
|
+
}
|
|
29346
|
+
});
|
|
29347
|
+
return w;
|
|
29348
|
+
}
|
|
28372
29349
|
|
|
28373
29350
|
function getCommands() {
|
|
28374
29351
|
return _commands.map(function(cmd) {
|
|
@@ -28978,6 +29955,18 @@ ${svg}
|
|
|
28978
29955
|
type: 'strings',
|
|
28979
29956
|
describe: '[GPKG] comma-sep. list of layers to import'
|
|
28980
29957
|
})
|
|
29958
|
+
.option('scaling', {
|
|
29959
|
+
describe: '[raster] raster display scaling method: none,minmax,percentile'
|
|
29960
|
+
})
|
|
29961
|
+
.option('scale-range', {
|
|
29962
|
+
describe: '[raster] display intensity range in percent, e.g. 0,100'
|
|
29963
|
+
})
|
|
29964
|
+
.option('percentile-range', {
|
|
29965
|
+
describe: '[raster] input percentile range for percentile scaling, e.g. 2,98'
|
|
29966
|
+
})
|
|
29967
|
+
.option('rendition', {
|
|
29968
|
+
describe: '[GeoTIFF] import a GeoTIFF rendition: full,overview-1,etc.'
|
|
29969
|
+
})
|
|
28981
29970
|
.option('geometry-type', {
|
|
28982
29971
|
// undocumented; GeoJSON import rejects all but one kind of geometry
|
|
28983
29972
|
// describe: '[GeoJSON] Import one kind of geometry (point|polygon|polyline)'
|
|
@@ -30488,6 +31477,15 @@ ${svg}
|
|
|
30488
31477
|
.option('r', {
|
|
30489
31478
|
describe: 'symbol radius (set this to export points as circles)',
|
|
30490
31479
|
})
|
|
31480
|
+
.option('icon', {
|
|
31481
|
+
describe: 'point icon shape; one of: circle, square, ring, star'
|
|
31482
|
+
})
|
|
31483
|
+
.option('icon-size', {
|
|
31484
|
+
describe: 'point icon size in pixels'
|
|
31485
|
+
})
|
|
31486
|
+
.option('icon-color', {
|
|
31487
|
+
describe: 'point icon color (defaults to fill color, then black)'
|
|
31488
|
+
})
|
|
30491
31489
|
.option('label-text', {
|
|
30492
31490
|
describe: 'label text (set this to export points as labels)'
|
|
30493
31491
|
})
|
|
@@ -34307,7 +35305,7 @@ ${svg}
|
|
|
34307
35305
|
|
|
34308
35306
|
var hyparquetPromise = null;
|
|
34309
35307
|
var compressorsPromise = null;
|
|
34310
|
-
var dynamicImportModule = Function('id', 'return import(id)');
|
|
35308
|
+
var dynamicImportModule$1 = Function('id', 'return import(id)');
|
|
34311
35309
|
var mproj = null;
|
|
34312
35310
|
|
|
34313
35311
|
async function importGeoParquet(input, optsArg) {
|
|
@@ -34354,7 +35352,7 @@ ${svg}
|
|
|
34354
35352
|
return mod;
|
|
34355
35353
|
}
|
|
34356
35354
|
if (!hyparquetPromise) {
|
|
34357
|
-
hyparquetPromise = dynamicImportModule('hyparquet');
|
|
35355
|
+
hyparquetPromise = dynamicImportModule$1('hyparquet');
|
|
34358
35356
|
}
|
|
34359
35357
|
var nodeMod = await hyparquetPromise;
|
|
34360
35358
|
return nodeMod.default && !nodeMod.parquetReadObjects ? nodeMod.default : nodeMod;
|
|
@@ -34365,7 +35363,7 @@ ${svg}
|
|
|
34365
35363
|
return getHyparquetCompressors(require$1('hyparquet-compressors'));
|
|
34366
35364
|
}
|
|
34367
35365
|
if (!compressorsPromise) {
|
|
34368
|
-
compressorsPromise = dynamicImportModule('hyparquet-compressors');
|
|
35366
|
+
compressorsPromise = dynamicImportModule$1('hyparquet-compressors');
|
|
34369
35367
|
}
|
|
34370
35368
|
return getHyparquetCompressors(await compressorsPromise);
|
|
34371
35369
|
}
|
|
@@ -34694,6 +35692,555 @@ ${svg}
|
|
|
34694
35692
|
};
|
|
34695
35693
|
}
|
|
34696
35694
|
|
|
35695
|
+
var geotiffPromise = null;
|
|
35696
|
+
var dynamicImportModule = Function('id', 'return import(id)');
|
|
35697
|
+
var DEFAULT_MAX_IMPORT_PIXELS = 16e6;
|
|
35698
|
+
|
|
35699
|
+
async function importGeoTIFF(input, optsArg) {
|
|
35700
|
+
var opts = optsArg || {};
|
|
35701
|
+
var geotiff = await loadGeoTIFFLib();
|
|
35702
|
+
var source = getGeoTIFFSource(input);
|
|
35703
|
+
var tiff = await openGeoTIFF(source, geotiff);
|
|
35704
|
+
var sourceImage = await tiff.getImage();
|
|
35705
|
+
var importImage = await selectGeoTIFFImportImage(tiff, sourceImage, opts);
|
|
35706
|
+
var imported = await importGeoTIFFImage(importImage, input, opts, sourceImage);
|
|
35707
|
+
var dataset = {
|
|
35708
|
+
info: {
|
|
35709
|
+
raster_sources: [imported.source]
|
|
35710
|
+
},
|
|
35711
|
+
layers: [{
|
|
35712
|
+
name: input && input.filename ? getFileBase(input.filename) : null,
|
|
35713
|
+
raster_type: 'grid',
|
|
35714
|
+
raster: imported.raster
|
|
35715
|
+
}]
|
|
35716
|
+
};
|
|
35717
|
+
await importGeoTIFFCrs(dataset, sourceImage);
|
|
35718
|
+
return dataset;
|
|
35719
|
+
}
|
|
35720
|
+
|
|
35721
|
+
async function loadGeoTIFFLib() {
|
|
35722
|
+
var mod;
|
|
35723
|
+
if (runningInBrowser()) {
|
|
35724
|
+
mod = require$1('geotiff');
|
|
35725
|
+
if (!mod || !mod.fromArrayBuffer) {
|
|
35726
|
+
stop$1('GeoTIFF library is not loaded');
|
|
35727
|
+
}
|
|
35728
|
+
return mod;
|
|
35729
|
+
}
|
|
35730
|
+
if (!geotiffPromise) {
|
|
35731
|
+
geotiffPromise = dynamicImportModule('geotiff');
|
|
35732
|
+
}
|
|
35733
|
+
mod = await geotiffPromise;
|
|
35734
|
+
return mod.default && !mod.fromArrayBuffer ? mod.default : mod;
|
|
35735
|
+
}
|
|
35736
|
+
|
|
35737
|
+
async function openGeoTIFF(source, geotiff) {
|
|
35738
|
+
if (!source) {
|
|
35739
|
+
stop$1('Missing GeoTIFF source data');
|
|
35740
|
+
}
|
|
35741
|
+
return geotiff.fromArrayBuffer(source);
|
|
35742
|
+
}
|
|
35743
|
+
|
|
35744
|
+
function getGeoTIFFSource(input) {
|
|
35745
|
+
var content = input && input.content;
|
|
35746
|
+
if (!content) return null;
|
|
35747
|
+
if (content instanceof ArrayBuffer) return content;
|
|
35748
|
+
return content.buffer.slice(content.byteOffset || 0, (content.byteOffset || 0) + content.byteLength);
|
|
35749
|
+
}
|
|
35750
|
+
|
|
35751
|
+
async function importGeoTIFFImage(importImage, input, opts, sourceImage) {
|
|
35752
|
+
var image = importImage.image;
|
|
35753
|
+
var width = importImage.width;
|
|
35754
|
+
var height = importImage.height;
|
|
35755
|
+
var samplesPerPixel = image.getSamplesPerPixel();
|
|
35756
|
+
var samples = getDisplaySamples(samplesPerPixel);
|
|
35757
|
+
var imageBbox = getImageBoundingBox(sourceImage);
|
|
35758
|
+
repairDeferredOffsetArrays(image);
|
|
35759
|
+
var data = await readGeoTIFFSamples(image, samples, width, height);
|
|
35760
|
+
var noData = getNoDataValue(image);
|
|
35761
|
+
var sourceId = getSourceId(input);
|
|
35762
|
+
var raster = {
|
|
35763
|
+
sourceId: sourceId,
|
|
35764
|
+
grid: {
|
|
35765
|
+
width: width,
|
|
35766
|
+
height: height,
|
|
35767
|
+
bands: samples.length,
|
|
35768
|
+
pixelType: getPixelType(image),
|
|
35769
|
+
samples: data,
|
|
35770
|
+
sampleBands: samples,
|
|
35771
|
+
nodata: noData,
|
|
35772
|
+
bbox: imageBbox,
|
|
35773
|
+
transform: getImageTransformForSize(sourceImage, width, height, imageBbox)
|
|
35774
|
+
},
|
|
35775
|
+
derivation: {
|
|
35776
|
+
type: samples.length >= 3 ? 'rgb' : 'gray',
|
|
35777
|
+
sourceId: sourceId,
|
|
35778
|
+
bands: samples
|
|
35779
|
+
},
|
|
35780
|
+
view: {
|
|
35781
|
+
recipe: {
|
|
35782
|
+
type: samples.length >= 3 ? 'rgb' : 'gray',
|
|
35783
|
+
bands: samples
|
|
35784
|
+
}
|
|
35785
|
+
}
|
|
35786
|
+
};
|
|
35787
|
+
raster.view.recipe = getRasterViewRecipe(raster.grid, raster.view.recipe, opts);
|
|
35788
|
+
raster.view.preview = createRasterPreview(raster, opts);
|
|
35789
|
+
return {
|
|
35790
|
+
raster: raster,
|
|
35791
|
+
source: getSourceInfo$1(input, sourceId, sourceImage)
|
|
35792
|
+
};
|
|
35793
|
+
}
|
|
35794
|
+
|
|
35795
|
+
async function selectGeoTIFFImportImage(tiff, sourceImage, opts) {
|
|
35796
|
+
var maxPixels = getMaxImportPixels(opts);
|
|
35797
|
+
var renditions = await getGeoTIFFRenditions(tiff, sourceImage);
|
|
35798
|
+
var source = renditions[0];
|
|
35799
|
+
var best = getRequestedRendition(renditions, opts.rendition);
|
|
35800
|
+
var bestPixels;
|
|
35801
|
+
if (!best) {
|
|
35802
|
+
best = source;
|
|
35803
|
+
bestPixels = best.width * best.height;
|
|
35804
|
+
if (bestPixels > maxPixels) {
|
|
35805
|
+
best = getAutomaticRendition(renditions, maxPixels);
|
|
35806
|
+
bestPixels = best.width * best.height;
|
|
35807
|
+
if (bestPixels > maxPixels) {
|
|
35808
|
+
best = getResizedImportImage(best, maxPixels);
|
|
35809
|
+
}
|
|
35810
|
+
}
|
|
35811
|
+
}
|
|
35812
|
+
if (renditions.length > 1 && (runningInBrowser() || opts.rendition)) {
|
|
35813
|
+
message(getRenditionsMessage(renditions, best));
|
|
35814
|
+
}
|
|
35815
|
+
if (best.slug != 'full' || best.width != source.width || best.height != source.height) {
|
|
35816
|
+
warnOnce(getImportRenditionMessage(best, source));
|
|
35817
|
+
}
|
|
35818
|
+
return best;
|
|
35819
|
+
}
|
|
35820
|
+
|
|
35821
|
+
async function getGeoTIFFRenditions(tiff, sourceImage) {
|
|
35822
|
+
var imageCount = await tiff.getImageCount();
|
|
35823
|
+
var renditions = [getRenditionInfo(sourceImage, 0)];
|
|
35824
|
+
var image;
|
|
35825
|
+
for (var i = 1; i < imageCount; i++) {
|
|
35826
|
+
image = await tiff.getImage(i);
|
|
35827
|
+
renditions.push(getRenditionInfo(image, i));
|
|
35828
|
+
}
|
|
35829
|
+
return renditions;
|
|
35830
|
+
}
|
|
35831
|
+
|
|
35832
|
+
function getRenditionInfo(image, index) {
|
|
35833
|
+
return {
|
|
35834
|
+
image: image,
|
|
35835
|
+
index: index,
|
|
35836
|
+
slug: index === 0 ? 'full' : 'overview-' + index,
|
|
35837
|
+
width: image.getWidth(),
|
|
35838
|
+
height: image.getHeight()
|
|
35839
|
+
};
|
|
35840
|
+
}
|
|
35841
|
+
|
|
35842
|
+
function getRequestedRendition(renditions, slug) {
|
|
35843
|
+
var match;
|
|
35844
|
+
if (!slug) return null;
|
|
35845
|
+
slug = String(slug);
|
|
35846
|
+
match = renditions.find(function(rendition) {
|
|
35847
|
+
return rendition.slug == slug || rendition.width + 'x' + rendition.height == slug;
|
|
35848
|
+
});
|
|
35849
|
+
if (!match) {
|
|
35850
|
+
stop$1('Unknown GeoTIFF rendition:', slug + '.', 'Use one of:', renditions.map(function(rendition) {
|
|
35851
|
+
return rendition.slug;
|
|
35852
|
+
}).join(','));
|
|
35853
|
+
}
|
|
35854
|
+
return match;
|
|
35855
|
+
}
|
|
35856
|
+
|
|
35857
|
+
function getAutomaticRendition(renditions, maxPixels) {
|
|
35858
|
+
var best = renditions[0];
|
|
35859
|
+
var bestPixels = best.width * best.height;
|
|
35860
|
+
var rendition, pixels;
|
|
35861
|
+
for (var i = 1; i < renditions.length; i++) {
|
|
35862
|
+
rendition = renditions[i];
|
|
35863
|
+
pixels = rendition.width * rendition.height;
|
|
35864
|
+
if (pixels <= maxPixels && (bestPixels > maxPixels || pixels > bestPixels)) {
|
|
35865
|
+
best = rendition;
|
|
35866
|
+
bestPixels = pixels;
|
|
35867
|
+
} else if (bestPixels > maxPixels && pixels < bestPixels) {
|
|
35868
|
+
best = rendition;
|
|
35869
|
+
bestPixels = pixels;
|
|
35870
|
+
}
|
|
35871
|
+
}
|
|
35872
|
+
return best;
|
|
35873
|
+
}
|
|
35874
|
+
|
|
35875
|
+
function getRenditionsMessage(renditions, selected) {
|
|
35876
|
+
var lines = ['GeoTIFF renditions:'];
|
|
35877
|
+
renditions.forEach(function(rendition) {
|
|
35878
|
+
lines.push(' ' + rendition.slug + ': ' + rendition.width + 'x' + rendition.height +
|
|
35879
|
+
(rendition.slug == selected.slug ? ' [selected]' : ''));
|
|
35880
|
+
});
|
|
35881
|
+
lines.push('Use import option rendition=<slug> to select a different rendition.');
|
|
35882
|
+
return lines.join('\n');
|
|
35883
|
+
}
|
|
35884
|
+
|
|
35885
|
+
function getImportRenditionMessage(importImage, source) {
|
|
35886
|
+
if (importImage.resampled) {
|
|
35887
|
+
return 'Using resampled GeoTIFF ' + (importImage.sourceSlug == 'full' ? 'full-resolution image' : 'rendition ' + importImage.sourceSlug) +
|
|
35888
|
+
' for import: ' + importImage.width + 'x' + importImage.height +
|
|
35889
|
+
' (source: ' + source.width + 'x' + source.height + ').';
|
|
35890
|
+
}
|
|
35891
|
+
return 'Using reduced-resolution GeoTIFF rendition for import: ' + importImage.slug + ' ' +
|
|
35892
|
+
importImage.width + 'x' + importImage.height + ' (source: ' + source.width + 'x' + source.height + ').';
|
|
35893
|
+
}
|
|
35894
|
+
|
|
35895
|
+
function getResizedImportImage(importImage, maxPixels) {
|
|
35896
|
+
var scale = Math.min(1, Math.sqrt(maxPixels / (importImage.width * importImage.height)));
|
|
35897
|
+
return Object.assign({}, importImage, {
|
|
35898
|
+
sourceSlug: importImage.slug,
|
|
35899
|
+
slug: importImage.slug + '-resampled',
|
|
35900
|
+
resampled: true,
|
|
35901
|
+
width: Math.max(1, Math.round(importImage.width * scale)),
|
|
35902
|
+
height: Math.max(1, Math.round(importImage.height * scale))
|
|
35903
|
+
});
|
|
35904
|
+
}
|
|
35905
|
+
|
|
35906
|
+
function getMaxImportPixels(opts) {
|
|
35907
|
+
return opts.maxPixels || opts.raster_max_pixels || opts.rasterMaxPixels ||
|
|
35908
|
+
DEFAULT_MAX_IMPORT_PIXELS;
|
|
35909
|
+
}
|
|
35910
|
+
|
|
35911
|
+
async function readGeoTIFFSamples(image, samples, width, height) {
|
|
35912
|
+
var opts = {
|
|
35913
|
+
interleave: true,
|
|
35914
|
+
width: width,
|
|
35915
|
+
height: height
|
|
35916
|
+
};
|
|
35917
|
+
if (useRGBRead(image, samples)) {
|
|
35918
|
+
return image.readRGB(opts);
|
|
35919
|
+
}
|
|
35920
|
+
opts.samples = samples;
|
|
35921
|
+
return image.readRasters(opts);
|
|
35922
|
+
}
|
|
35923
|
+
|
|
35924
|
+
function useRGBRead(image, samples) {
|
|
35925
|
+
return samples.length == 3 && getPhotometricInterpretation(image) == 6 && image.readRGB;
|
|
35926
|
+
}
|
|
35927
|
+
|
|
35928
|
+
function getDisplaySamples(samplesPerPixel) {
|
|
35929
|
+
if (samplesPerPixel >= 4) return [0, 1, 2, 3];
|
|
35930
|
+
if (samplesPerPixel >= 3) return [0, 1, 2];
|
|
35931
|
+
return [0];
|
|
35932
|
+
}
|
|
35933
|
+
|
|
35934
|
+
function getNoDataValue(image) {
|
|
35935
|
+
var val = image.getGDALNoData && image.getGDALNoData();
|
|
35936
|
+
return val == null || val === '' ? null : +val;
|
|
35937
|
+
}
|
|
35938
|
+
|
|
35939
|
+
function getPixelType(image) {
|
|
35940
|
+
var fmt = image.getSampleFormat && image.getSampleFormat();
|
|
35941
|
+
var bits = image.getBitsPerSample && image.getBitsPerSample();
|
|
35942
|
+
if (Array.isArray(fmt)) fmt = fmt[0];
|
|
35943
|
+
if (Array.isArray(bits)) bits = bits[0];
|
|
35944
|
+
var type = fmt == 3 ? 'float' : fmt == 2 ? 'int' : 'uint';
|
|
35945
|
+
return bits ? type + bits : type;
|
|
35946
|
+
}
|
|
35947
|
+
|
|
35948
|
+
function getImageBoundingBox(image) {
|
|
35949
|
+
try {
|
|
35950
|
+
return image.getBoundingBox().map(Number);
|
|
35951
|
+
} catch(e) {
|
|
35952
|
+
stop$1('GeoTIFF is missing georeferencing metadata');
|
|
35953
|
+
}
|
|
35954
|
+
}
|
|
35955
|
+
|
|
35956
|
+
function getImageTransformForSize(image, width, height, bbox) {
|
|
35957
|
+
var sourceBbox = bbox || getImageBoundingBox(image);
|
|
35958
|
+
return [
|
|
35959
|
+
(sourceBbox[2] - sourceBbox[0]) / width,
|
|
35960
|
+
0,
|
|
35961
|
+
sourceBbox[0],
|
|
35962
|
+
0,
|
|
35963
|
+
(sourceBbox[1] - sourceBbox[3]) / height,
|
|
35964
|
+
sourceBbox[3]
|
|
35965
|
+
];
|
|
35966
|
+
}
|
|
35967
|
+
|
|
35968
|
+
function getImageTransform(image) {
|
|
35969
|
+
var origin = image.getOrigin && image.getOrigin();
|
|
35970
|
+
var resolution = image.getResolution && image.getResolution();
|
|
35971
|
+
if (!origin || !resolution) return null;
|
|
35972
|
+
return [resolution[0], 0, origin[0], 0, resolution[1], origin[1]];
|
|
35973
|
+
}
|
|
35974
|
+
|
|
35975
|
+
function getPhotometricInterpretation(image) {
|
|
35976
|
+
var fileDirectory = image && image.fileDirectory;
|
|
35977
|
+
return fileDirectory && fileDirectory.actualizedFields && fileDirectory.actualizedFields.get(262);
|
|
35978
|
+
}
|
|
35979
|
+
|
|
35980
|
+
function repairDeferredOffsetArrays(image) {
|
|
35981
|
+
var fileDirectory = image && image.fileDirectory;
|
|
35982
|
+
var arrays = fileDirectory && fileDirectory.deferredArrays;
|
|
35983
|
+
if (!arrays || !fileDirectory.actualizedFields) return;
|
|
35984
|
+
// Work around geotiff.js decoding big-endian deferred offset/count arrays as little-endian.
|
|
35985
|
+
[273, 279, 324, 325].forEach(function(tag) {
|
|
35986
|
+
var deferred = arrays.get(tag);
|
|
35987
|
+
var values;
|
|
35988
|
+
if (!deferred || deferred.littleEndian) return;
|
|
35989
|
+
values = decodeDeferredIntegerArray(deferred);
|
|
35990
|
+
if (!values) return;
|
|
35991
|
+
fileDirectory.actualizedFields.set(tag, values);
|
|
35992
|
+
arrays.delete(tag);
|
|
35993
|
+
});
|
|
35994
|
+
}
|
|
35995
|
+
|
|
35996
|
+
function decodeDeferredIntegerArray(deferred) {
|
|
35997
|
+
var source = deferred.source && deferred.source.arrayBuffer;
|
|
35998
|
+
var offset = deferred.arrayOffset;
|
|
35999
|
+
var length = deferred.length;
|
|
36000
|
+
var itemSize = deferred.itemSize;
|
|
36001
|
+
var view, values;
|
|
36002
|
+
if (!source || !length || !itemSize) return null;
|
|
36003
|
+
view = new DataView(source, offset, length * itemSize);
|
|
36004
|
+
if (itemSize == 2) {
|
|
36005
|
+
values = new Uint16Array(length);
|
|
36006
|
+
for (var i = 0; i < length; i++) values[i] = view.getUint16(i * itemSize, false);
|
|
36007
|
+
return values;
|
|
36008
|
+
}
|
|
36009
|
+
if (itemSize == 4) {
|
|
36010
|
+
values = new Uint32Array(length);
|
|
36011
|
+
for (var j = 0; j < length; j++) values[j] = view.getUint32(j * itemSize, false);
|
|
36012
|
+
return values;
|
|
36013
|
+
}
|
|
36014
|
+
if (itemSize == 8 && typeof view.getBigUint64 == 'function') {
|
|
36015
|
+
values = [];
|
|
36016
|
+
for (var k = 0; k < length; k++) values[k] = Number(view.getBigUint64(k * itemSize, false));
|
|
36017
|
+
return values;
|
|
36018
|
+
}
|
|
36019
|
+
return null;
|
|
36020
|
+
}
|
|
36021
|
+
|
|
36022
|
+
function getSourceId(input) {
|
|
36023
|
+
return input && input.filename ? getFileBase(input.filename) : 'geotiff-source';
|
|
36024
|
+
}
|
|
36025
|
+
|
|
36026
|
+
function getSourceInfo$1(input, sourceId, image) {
|
|
36027
|
+
var content = input && input.content;
|
|
36028
|
+
return {
|
|
36029
|
+
id: sourceId,
|
|
36030
|
+
filename: input && input.filename || null,
|
|
36031
|
+
byteLength: content && content.byteLength || null,
|
|
36032
|
+
storage: runningInBrowser() ? 'indexeddb-pending' : 'path',
|
|
36033
|
+
width: image.getWidth(),
|
|
36034
|
+
height: image.getHeight(),
|
|
36035
|
+
bands: image.getSamplesPerPixel(),
|
|
36036
|
+
pixelType: getPixelType(image),
|
|
36037
|
+
bbox: getImageBoundingBox(image),
|
|
36038
|
+
transform: getImageTransform(image)
|
|
36039
|
+
};
|
|
36040
|
+
}
|
|
36041
|
+
|
|
36042
|
+
async function importGeoTIFFCrs(dataset, image) {
|
|
36043
|
+
var crsString = getGeoTIFFCrsString(image);
|
|
36044
|
+
if (!crsString) {
|
|
36045
|
+
warnOnce('Unable to import CRS from GeoTIFF metadata');
|
|
36046
|
+
return;
|
|
36047
|
+
}
|
|
36048
|
+
await initProjLibrary({crs: crsString});
|
|
36049
|
+
try {
|
|
36050
|
+
setDatasetCrsInfo(dataset, getCrsInfo(crsString));
|
|
36051
|
+
} catch(e) {
|
|
36052
|
+
dataset.info = Object.assign(dataset.info || {}, {crs_string: crsString});
|
|
36053
|
+
}
|
|
36054
|
+
}
|
|
36055
|
+
|
|
36056
|
+
function getGeoTIFFCrsString(image) {
|
|
36057
|
+
var keys = image.getGeoKeys && image.getGeoKeys() || {};
|
|
36058
|
+
var code = keys.ProjectedCSTypeGeoKey || keys.GeographicTypeGeoKey;
|
|
36059
|
+
return code ? 'EPSG:' + code : null;
|
|
36060
|
+
}
|
|
36061
|
+
|
|
36062
|
+
async function importImageRaster(input, optsArg) {
|
|
36063
|
+
var opts = optsArg || {};
|
|
36064
|
+
var imageType = input.png ? 'png' : input.jpeg ? 'jpeg' : null;
|
|
36065
|
+
var imageInput = input[imageType];
|
|
36066
|
+
var decoded = await decodeImage(imageInput, imageType);
|
|
36067
|
+
var world = parseWorldFile(input.world && input.world.content);
|
|
36068
|
+
var sourceId = getFileBase(imageInput.filename || imageType);
|
|
36069
|
+
var transform, bbox, raster, dataset;
|
|
36070
|
+
if (!world) {
|
|
36071
|
+
stop$1('Image raster import requires a world file');
|
|
36072
|
+
}
|
|
36073
|
+
transform = getWorldTransform(world);
|
|
36074
|
+
bbox = getWorldFileBBox(transform, decoded.width, decoded.height);
|
|
36075
|
+
raster = {
|
|
36076
|
+
sourceId: sourceId,
|
|
36077
|
+
grid: {
|
|
36078
|
+
width: decoded.width,
|
|
36079
|
+
height: decoded.height,
|
|
36080
|
+
bands: decoded.bands,
|
|
36081
|
+
pixelType: 'uint8',
|
|
36082
|
+
samples: decoded.samples,
|
|
36083
|
+
sampleBands: decoded.sampleBands,
|
|
36084
|
+
nodata: null,
|
|
36085
|
+
bbox: bbox,
|
|
36086
|
+
transform: transform
|
|
36087
|
+
},
|
|
36088
|
+
derivation: {
|
|
36089
|
+
type: decoded.bands >= 3 ? 'rgb' : 'gray',
|
|
36090
|
+
sourceId: sourceId,
|
|
36091
|
+
bands: decoded.sampleBands
|
|
36092
|
+
},
|
|
36093
|
+
view: {
|
|
36094
|
+
recipe: {
|
|
36095
|
+
type: decoded.bands >= 3 ? 'rgb' : 'gray',
|
|
36096
|
+
bands: decoded.sampleBands
|
|
36097
|
+
}
|
|
36098
|
+
}
|
|
36099
|
+
};
|
|
36100
|
+
raster.view.recipe = getRasterViewRecipe(raster.grid, raster.view.recipe, opts);
|
|
36101
|
+
raster.view.preview = createRasterPreview(raster, opts);
|
|
36102
|
+
dataset = {
|
|
36103
|
+
info: {
|
|
36104
|
+
raster_sources: [getSourceInfo(imageInput, sourceId, imageType, input)]
|
|
36105
|
+
},
|
|
36106
|
+
layers: [{
|
|
36107
|
+
name: imageInput.filename ? getFileBase(imageInput.filename) : null,
|
|
36108
|
+
raster_type: 'grid',
|
|
36109
|
+
raster: raster
|
|
36110
|
+
}]
|
|
36111
|
+
};
|
|
36112
|
+
importImageCrs(dataset, input.prj);
|
|
36113
|
+
return dataset;
|
|
36114
|
+
}
|
|
36115
|
+
|
|
36116
|
+
async function decodeImage(input, imageType) {
|
|
36117
|
+
if (runningInBrowser()) {
|
|
36118
|
+
return decodeImageInBrowser(input.content, imageType);
|
|
36119
|
+
}
|
|
36120
|
+
return imageType == 'png' ? decodePng(input.content) : decodeJpeg(input.content);
|
|
36121
|
+
}
|
|
36122
|
+
|
|
36123
|
+
function decodePng(content) {
|
|
36124
|
+
var png = require$1('pngjs').PNG.sync.read(Buffer.from(content));
|
|
36125
|
+
return rgbaToImageData(png.data, png.width, png.height, true);
|
|
36126
|
+
}
|
|
36127
|
+
|
|
36128
|
+
function decodeJpeg(content) {
|
|
36129
|
+
var jpeg = require$1('jpeg-js');
|
|
36130
|
+
var image = jpeg.decode(Buffer.from(content), {useTArray: true});
|
|
36131
|
+
return rgbaToImageData(image.data, image.width, image.height, false);
|
|
36132
|
+
}
|
|
36133
|
+
|
|
36134
|
+
async function decodeImageInBrowser(content, imageType) {
|
|
36135
|
+
var blob = new Blob([content], {type: imageType == 'png' ? 'image/png' : 'image/jpeg'});
|
|
36136
|
+
var bitmap = await createImageBitmap(blob);
|
|
36137
|
+
var canvas = document.createElement('canvas');
|
|
36138
|
+
var ctx, data;
|
|
36139
|
+
canvas.width = bitmap.width;
|
|
36140
|
+
canvas.height = bitmap.height;
|
|
36141
|
+
ctx = canvas.getContext('2d');
|
|
36142
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
36143
|
+
data = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
|
|
36144
|
+
if (bitmap.close) bitmap.close();
|
|
36145
|
+
return rgbaToImageData(data, canvas.width, canvas.height, imageType == 'png');
|
|
36146
|
+
}
|
|
36147
|
+
|
|
36148
|
+
function rgbaToImageData(rgba, width, height, keepAlpha) {
|
|
36149
|
+
var bands = keepAlpha ? 4 : 3;
|
|
36150
|
+
var samples = new Uint8Array(width * height * bands);
|
|
36151
|
+
var src, dest;
|
|
36152
|
+
for (var i = 0, n = width * height; i < n; i++) {
|
|
36153
|
+
src = i * 4;
|
|
36154
|
+
dest = i * bands;
|
|
36155
|
+
samples[dest] = rgba[src];
|
|
36156
|
+
samples[dest + 1] = rgba[src + 1];
|
|
36157
|
+
samples[dest + 2] = rgba[src + 2];
|
|
36158
|
+
if (keepAlpha) samples[dest + 3] = rgba[src + 3];
|
|
36159
|
+
}
|
|
36160
|
+
return {
|
|
36161
|
+
width: width,
|
|
36162
|
+
height: height,
|
|
36163
|
+
bands: bands,
|
|
36164
|
+
samples: samples,
|
|
36165
|
+
sampleBands: bands == 4 ? [0, 1, 2, 3] : [0, 1, 2]
|
|
36166
|
+
};
|
|
36167
|
+
}
|
|
36168
|
+
|
|
36169
|
+
function parseWorldFile(content) {
|
|
36170
|
+
if (!content) return null;
|
|
36171
|
+
var vals = String(content).trim().split(/\s+/).map(Number);
|
|
36172
|
+
if (vals.length < 6 || vals.some(function(val) { return !isFinite(val); })) {
|
|
36173
|
+
stop$1('Invalid world file');
|
|
36174
|
+
}
|
|
36175
|
+
return vals.slice(0, 6);
|
|
36176
|
+
}
|
|
36177
|
+
|
|
36178
|
+
function getWorldTransform(world) {
|
|
36179
|
+
var a = world[0], d = world[1], b = world[2], e = world[3],
|
|
36180
|
+
c = world[4], f = world[5];
|
|
36181
|
+
return [
|
|
36182
|
+
a,
|
|
36183
|
+
b,
|
|
36184
|
+
c - a / 2 - b / 2,
|
|
36185
|
+
d,
|
|
36186
|
+
e,
|
|
36187
|
+
f - d / 2 - e / 2
|
|
36188
|
+
];
|
|
36189
|
+
}
|
|
36190
|
+
|
|
36191
|
+
function getWorldFileBBox(transform, width, height) {
|
|
36192
|
+
var corners = [
|
|
36193
|
+
transformPoint(transform, 0, 0),
|
|
36194
|
+
transformPoint(transform, width, 0),
|
|
36195
|
+
transformPoint(transform, width, height),
|
|
36196
|
+
transformPoint(transform, 0, height)
|
|
36197
|
+
];
|
|
36198
|
+
var xs = corners.map(function(p) { return p[0]; });
|
|
36199
|
+
var ys = corners.map(function(p) { return p[1]; });
|
|
36200
|
+
return [
|
|
36201
|
+
Math.min.apply(null, xs),
|
|
36202
|
+
Math.min.apply(null, ys),
|
|
36203
|
+
Math.max.apply(null, xs),
|
|
36204
|
+
Math.max.apply(null, ys)
|
|
36205
|
+
];
|
|
36206
|
+
}
|
|
36207
|
+
|
|
36208
|
+
function transformPoint(t, col, row) {
|
|
36209
|
+
return [
|
|
36210
|
+
t[0] * col + t[1] * row + t[2],
|
|
36211
|
+
t[3] * col + t[4] * row + t[5]
|
|
36212
|
+
];
|
|
36213
|
+
}
|
|
36214
|
+
|
|
36215
|
+
function importImageCrs(dataset, prj) {
|
|
36216
|
+
var wkt = prj && prj.content;
|
|
36217
|
+
if (!wkt) {
|
|
36218
|
+
warn('Image raster is missing a .prj file; CRS is unknown');
|
|
36219
|
+
return;
|
|
36220
|
+
}
|
|
36221
|
+
try {
|
|
36222
|
+
setDatasetCrsInfo(dataset, {
|
|
36223
|
+
wkt1: wkt,
|
|
36224
|
+
crs: parsePrj(wkt)
|
|
36225
|
+
});
|
|
36226
|
+
} catch(e) {
|
|
36227
|
+
dataset.info.wkt1 = wkt;
|
|
36228
|
+
}
|
|
36229
|
+
}
|
|
36230
|
+
|
|
36231
|
+
function getSourceInfo(input, sourceId, imageType, group) {
|
|
36232
|
+
var content = input && input.content;
|
|
36233
|
+
return {
|
|
36234
|
+
id: sourceId,
|
|
36235
|
+
type: imageType,
|
|
36236
|
+
filename: input && input.filename || null,
|
|
36237
|
+
byteLength: content && content.byteLength || null,
|
|
36238
|
+
storage: runningInBrowser() ? 'indexeddb-pending' : 'path',
|
|
36239
|
+
worldFile: group.world && group.world.filename || null,
|
|
36240
|
+
prjFile: group.prj && group.prj.filename || null
|
|
36241
|
+
};
|
|
36242
|
+
}
|
|
36243
|
+
|
|
34697
36244
|
var INHERITED_STYLE_KEYS = [
|
|
34698
36245
|
'fill', 'fill-opacity',
|
|
34699
36246
|
'stroke', 'stroke-width', 'stroke-opacity', 'stroke-dasharray',
|
|
@@ -35647,6 +37194,10 @@ ${svg}
|
|
|
35647
37194
|
stop$1("GeoPackage import requires async import path");
|
|
35648
37195
|
} else if (obj.parquet) {
|
|
35649
37196
|
stop$1("GeoParquet import requires async import path");
|
|
37197
|
+
} else if (obj.geotiff) {
|
|
37198
|
+
stop$1("GeoTIFF import requires async import path");
|
|
37199
|
+
} else if (obj.png || obj.jpeg) {
|
|
37200
|
+
stop$1("Image raster import requires async import path");
|
|
35650
37201
|
}
|
|
35651
37202
|
|
|
35652
37203
|
return finalizeImportedDataset(dataset, dataFmt, data, opts);
|
|
@@ -35667,6 +37218,14 @@ ${svg}
|
|
|
35667
37218
|
dataFmt = 'geoparquet';
|
|
35668
37219
|
data = obj.parquet;
|
|
35669
37220
|
dataset = await importGeoParquet(data, opts);
|
|
37221
|
+
} else if (obj.geotiff) {
|
|
37222
|
+
dataFmt = 'geotiff';
|
|
37223
|
+
data = obj.geotiff;
|
|
37224
|
+
dataset = await importGeoTIFF(data, opts);
|
|
37225
|
+
} else if (obj.png || obj.jpeg) {
|
|
37226
|
+
dataFmt = obj.png ? 'png' : 'jpeg';
|
|
37227
|
+
data = obj[dataFmt];
|
|
37228
|
+
dataset = await importImageRaster(obj, opts);
|
|
35670
37229
|
} else {
|
|
35671
37230
|
return importContent(obj, opts);
|
|
35672
37231
|
}
|
|
@@ -35868,11 +37427,63 @@ ${svg}
|
|
|
35868
37427
|
if (data) {
|
|
35869
37428
|
data = importTable(data);
|
|
35870
37429
|
}
|
|
37430
|
+
if (lyr.raster) {
|
|
37431
|
+
lyr.raster = importRasterData(lyr.raster);
|
|
37432
|
+
}
|
|
35871
37433
|
return Object.assign(lyr, {
|
|
35872
37434
|
data: lyr.data ? new DataTable(data) : null
|
|
35873
37435
|
});
|
|
35874
37436
|
}
|
|
35875
37437
|
|
|
37438
|
+
function importRasterData(raster) {
|
|
37439
|
+
var copy = Object.assign({}, raster);
|
|
37440
|
+
if (raster.grid) {
|
|
37441
|
+
copy.grid = Object.assign({}, raster.grid);
|
|
37442
|
+
if (raster.grid.samples) {
|
|
37443
|
+
copy.grid.samples = restoreRasterSamples(raster.grid.samples, raster.grid.pixelType);
|
|
37444
|
+
}
|
|
37445
|
+
}
|
|
37446
|
+
if (raster.view) {
|
|
37447
|
+
copy.view = Object.assign({}, raster.view);
|
|
37448
|
+
if (raster.view.preview) {
|
|
37449
|
+
copy.view.preview = Object.assign({}, raster.view.preview);
|
|
37450
|
+
if (raster.view.preview.pixels) {
|
|
37451
|
+
copy.view.preview.pixels = new Uint8ClampedArray(BinArray.copyToArrayBuffer(raster.view.preview.pixels));
|
|
37452
|
+
}
|
|
37453
|
+
}
|
|
37454
|
+
}
|
|
37455
|
+
if (raster.preview) {
|
|
37456
|
+
copy.preview = Object.assign({}, raster.preview);
|
|
37457
|
+
if (raster.preview.pixels) {
|
|
37458
|
+
copy.preview.pixels = new Uint8ClampedArray(BinArray.copyToArrayBuffer(raster.preview.pixels));
|
|
37459
|
+
}
|
|
37460
|
+
}
|
|
37461
|
+
if (raster.pixels) {
|
|
37462
|
+
copy.pixels = new Uint8ClampedArray(BinArray.copyToArrayBuffer(raster.pixels));
|
|
37463
|
+
}
|
|
37464
|
+
return copy;
|
|
37465
|
+
}
|
|
37466
|
+
|
|
37467
|
+
function restoreRasterSamples(buf, pixelType) {
|
|
37468
|
+
var arrbuf = BinArray.copyToArrayBuffer(buf);
|
|
37469
|
+
var Ctor = getRasterSampleArrayConstructor(pixelType);
|
|
37470
|
+
return new Ctor(arrbuf);
|
|
37471
|
+
}
|
|
37472
|
+
|
|
37473
|
+
function getRasterSampleArrayConstructor(pixelType) {
|
|
37474
|
+
switch (pixelType) {
|
|
37475
|
+
case 'uint8': return Uint8Array;
|
|
37476
|
+
case 'int8': return Int8Array;
|
|
37477
|
+
case 'uint16': return Uint16Array;
|
|
37478
|
+
case 'int16': return Int16Array;
|
|
37479
|
+
case 'uint32': return Uint32Array;
|
|
37480
|
+
case 'int32': return Int32Array;
|
|
37481
|
+
case 'float32': return Float32Array;
|
|
37482
|
+
case 'float64': return Float64Array;
|
|
37483
|
+
}
|
|
37484
|
+
return Uint8Array;
|
|
37485
|
+
}
|
|
37486
|
+
|
|
35876
37487
|
var Unpack = /*#__PURE__*/Object.freeze({
|
|
35877
37488
|
__proto__: null,
|
|
35878
37489
|
restoreSessionData: restoreSessionData,
|
|
@@ -36004,11 +37615,18 @@ ${svg}
|
|
|
36004
37615
|
function expandKmzFile(file, cache) {
|
|
36005
37616
|
var files = expandZipFile(file, cache);
|
|
36006
37617
|
var name = replaceFileExtension(parseLocalPath(file).filename, 'kml');
|
|
36007
|
-
|
|
36008
|
-
|
|
37618
|
+
files = files.map(function(file) {
|
|
37619
|
+
if (file == 'doc.kml') {
|
|
37620
|
+
return name;
|
|
37621
|
+
}
|
|
37622
|
+
return file;
|
|
37623
|
+
});
|
|
37624
|
+
if ('doc.kml' in cache) {
|
|
36009
37625
|
cache[name] = cache['doc.kml'];
|
|
36010
37626
|
}
|
|
36011
|
-
return files
|
|
37627
|
+
return files.filter(function(file) {
|
|
37628
|
+
return guessInputFileType(file) == 'kml';
|
|
37629
|
+
});
|
|
36012
37630
|
}
|
|
36013
37631
|
|
|
36014
37632
|
function expandZipFile(file, cache) {
|
|
@@ -36100,6 +37718,8 @@ ${svg}
|
|
|
36100
37718
|
content = null; // for g.c.
|
|
36101
37719
|
if (fileType == 'shp' || fileType == 'dbf') {
|
|
36102
37720
|
readShapefileAuxFiles(path, input, cache);
|
|
37721
|
+
} else if (isRasterImageInputType(fileType)) {
|
|
37722
|
+
readRasterImageAuxFiles(path, input, cache);
|
|
36103
37723
|
}
|
|
36104
37724
|
if (fileType == 'shp' && !input.dbf) {
|
|
36105
37725
|
message(utils.format("[%s] .dbf file is missing - shapes imported without attribute data.", path));
|
|
@@ -36154,11 +37774,13 @@ ${svg}
|
|
|
36154
37774
|
content = null;
|
|
36155
37775
|
if (fileType == 'shp' || fileType == 'dbf') {
|
|
36156
37776
|
readShapefileAuxFiles(path, input, cache);
|
|
37777
|
+
} else if (isRasterImageInputType(fileType)) {
|
|
37778
|
+
readRasterImageAuxFiles(path, input, cache);
|
|
36157
37779
|
}
|
|
36158
37780
|
if (fileType == 'shp' && !input.dbf) {
|
|
36159
37781
|
message(utils.format("[%s] .dbf file is missing - shapes imported without attribute data.", path));
|
|
36160
37782
|
}
|
|
36161
|
-
return fileType == 'gpkg' || fileType == 'fgb' || fileType == 'parquet' ? importContentAsync(input, opts) : importContent(input, opts);
|
|
37783
|
+
return fileType == 'gpkg' || fileType == 'fgb' || fileType == 'parquet' || fileType == 'geotiff' || isRasterImageInputType(fileType) ? importContentAsync(input, opts) : importContent(input, opts);
|
|
36162
37784
|
}
|
|
36163
37785
|
|
|
36164
37786
|
// Import multiple files to a single dataset
|
|
@@ -36192,6 +37814,7 @@ ${svg}
|
|
|
36192
37814
|
async function importFilesTogetherAsync(files, opts) {
|
|
36193
37815
|
var unbuiltTopology = false;
|
|
36194
37816
|
var datasets = [];
|
|
37817
|
+
files = removeRasterImageSidecars(files);
|
|
36195
37818
|
for (var fname of files) {
|
|
36196
37819
|
// import without topology or snapping
|
|
36197
37820
|
var importOpts = utils.defaults({no_topology: true, snap: false, snap_interval: null, files: [fname]}, opts);
|
|
@@ -36300,6 +37923,60 @@ ${svg}
|
|
|
36300
37923
|
}
|
|
36301
37924
|
}
|
|
36302
37925
|
|
|
37926
|
+
function readRasterImageAuxFiles(path, obj, cache) {
|
|
37927
|
+
var prjPath = replaceFileExtension(path, 'prj');
|
|
37928
|
+
var worldPath = findWorldFile(path, cache);
|
|
37929
|
+
if (cli.isFile(prjPath, cache)) {
|
|
37930
|
+
obj.prj = {filename: prjPath, content: cli.readFile(prjPath, 'utf-8', cache)};
|
|
37931
|
+
}
|
|
37932
|
+
if (worldPath) {
|
|
37933
|
+
obj.world = {filename: worldPath, content: cli.readFile(worldPath, 'utf-8', cache)};
|
|
37934
|
+
}
|
|
37935
|
+
}
|
|
37936
|
+
|
|
37937
|
+
function findWorldFile(path, cache) {
|
|
37938
|
+
var candidates = getWorldFileCandidates(path);
|
|
37939
|
+
for (var i = 0; i < candidates.length; i++) {
|
|
37940
|
+
if (cli.isFile(candidates[i], cache)) return candidates[i];
|
|
37941
|
+
}
|
|
37942
|
+
return null;
|
|
37943
|
+
}
|
|
37944
|
+
|
|
37945
|
+
function getWorldFileCandidates(path) {
|
|
37946
|
+
var ext = getFileExtension(path).toLowerCase();
|
|
37947
|
+
var candidates = [replaceFileExtension(path, 'wld'), replaceFileExtension(path, 'tfw')];
|
|
37948
|
+
if (ext == 'png') {
|
|
37949
|
+
candidates.unshift(replaceFileExtension(path, 'pgw'), replaceFileExtension(path, 'pngw'));
|
|
37950
|
+
} else if (ext == 'jpg' || ext == 'jpeg') {
|
|
37951
|
+
candidates.unshift(
|
|
37952
|
+
replaceFileExtension(path, 'jgw'),
|
|
37953
|
+
replaceFileExtension(path, 'jpw'),
|
|
37954
|
+
replaceFileExtension(path, 'jpgw'),
|
|
37955
|
+
replaceFileExtension(path, 'jpegw')
|
|
37956
|
+
);
|
|
37957
|
+
}
|
|
37958
|
+
return utils.uniq(candidates);
|
|
37959
|
+
}
|
|
37960
|
+
|
|
37961
|
+
function removeRasterImageSidecars(files) {
|
|
37962
|
+
var imageBases = {};
|
|
37963
|
+
files.forEach(function(file) {
|
|
37964
|
+
var type = guessInputFileType(file);
|
|
37965
|
+
if (isRasterImageInputType(type)) {
|
|
37966
|
+
imageBases[getFileBase(file).toLowerCase()] = true;
|
|
37967
|
+
}
|
|
37968
|
+
});
|
|
37969
|
+
return files.filter(function(file) {
|
|
37970
|
+
var ext = getFileExtension(file).toLowerCase();
|
|
37971
|
+
var type = guessInputFileType(file);
|
|
37972
|
+
var base = getFileBase(file).toLowerCase();
|
|
37973
|
+
if ((type == 'prj' || isWorldFileExtension(ext)) && imageBases[base]) {
|
|
37974
|
+
return false;
|
|
37975
|
+
}
|
|
37976
|
+
return true;
|
|
37977
|
+
});
|
|
37978
|
+
}
|
|
37979
|
+
|
|
36303
37980
|
var FileImport = /*#__PURE__*/Object.freeze({
|
|
36304
37981
|
__proto__: null,
|
|
36305
37982
|
importFile: importFile,
|
|
@@ -43124,6 +44801,10 @@ ${svg}
|
|
|
43124
44801
|
var lyr2 = outputLayers[i];
|
|
43125
44802
|
lyr.shapes = lyr2.shapes;
|
|
43126
44803
|
lyr.data = lyr2.data;
|
|
44804
|
+
if (lyr2.raster) {
|
|
44805
|
+
lyr.raster = lyr2.raster;
|
|
44806
|
+
lyr.raster_type = lyr2.raster_type;
|
|
44807
|
+
}
|
|
43127
44808
|
});
|
|
43128
44809
|
dissolveArcs(dataset);
|
|
43129
44810
|
}
|
|
@@ -43134,8 +44815,15 @@ ${svg}
|
|
|
43134
44815
|
profileStart('clipLayers');
|
|
43135
44816
|
opts = opts || {no_cleanup: true}; // TODO: update testing functions
|
|
43136
44817
|
var usingPathClip = utils.some(targetLayers, layerHasPaths);
|
|
44818
|
+
var usingRasterClip = utils.some(targetLayers, layerHasRaster);
|
|
43137
44819
|
var mergedDataset, clipLyr, nodes, result;
|
|
43138
|
-
var clipDataset
|
|
44820
|
+
var clipDataset;
|
|
44821
|
+
if (usingRasterClip) {
|
|
44822
|
+
result = clipRasterLayers(targetLayers, clipSrc, targetDataset, type, opts);
|
|
44823
|
+
profileEnd('clipLayers');
|
|
44824
|
+
return result;
|
|
44825
|
+
}
|
|
44826
|
+
clipDataset = normalizeOverlaySource(clipSrc, targetDataset, opts);
|
|
43139
44827
|
if (!opts.no_warn) {
|
|
43140
44828
|
warnIfBoundsDontOverlap(targetLayers, targetDataset, clipDataset, type);
|
|
43141
44829
|
}
|
|
@@ -43169,6 +44857,30 @@ ${svg}
|
|
|
43169
44857
|
return result;
|
|
43170
44858
|
}
|
|
43171
44859
|
|
|
44860
|
+
function clipRasterLayers(targetLayers, clipSrc, targetDataset, type, opts) {
|
|
44861
|
+
var clipDataset, clipBounds, bbox;
|
|
44862
|
+
if (type != 'clip') {
|
|
44863
|
+
stop$1('Raster layers only support clipping');
|
|
44864
|
+
}
|
|
44865
|
+
if (utils.some(targetLayers, function(lyr) {return !layerHasRaster(lyr);})) {
|
|
44866
|
+
stop$1('Raster clipping cannot be mixed with vector target layers');
|
|
44867
|
+
}
|
|
44868
|
+
if (opts.bbox2) {
|
|
44869
|
+
bbox = opts.bbox2;
|
|
44870
|
+
} else {
|
|
44871
|
+
clipDataset = normalizeOverlaySource(clipSrc, targetDataset, opts);
|
|
44872
|
+
clipBounds = getLayerBounds(clipDataset.layers[0], clipDataset.arcs);
|
|
44873
|
+
if (!clipBounds || !clipBounds.hasBounds()) {
|
|
44874
|
+
stop$1('Missing raster clipping bounds');
|
|
44875
|
+
}
|
|
44876
|
+
bbox = clipBounds.toArray();
|
|
44877
|
+
}
|
|
44878
|
+
return targetLayers.map(function(lyr) {
|
|
44879
|
+
clipRasterToBBox(lyr, bbox, opts);
|
|
44880
|
+
return lyr;
|
|
44881
|
+
});
|
|
44882
|
+
}
|
|
44883
|
+
|
|
43172
44884
|
function clipLayersByBBox(layers, dataset, opts) {
|
|
43173
44885
|
var bbox = opts.bbox2;
|
|
43174
44886
|
var clipLyr = divideDatasetByBBox(dataset, bbox);
|
|
@@ -44055,7 +45767,14 @@ ${svg}
|
|
|
44055
45767
|
}]
|
|
44056
45768
|
};
|
|
44057
45769
|
}
|
|
44058
|
-
|
|
45770
|
+
if (runningInBrowser()) {
|
|
45771
|
+
message({
|
|
45772
|
+
type: 'mapshaper-console-info',
|
|
45773
|
+
layers: arr
|
|
45774
|
+
});
|
|
45775
|
+
} else {
|
|
45776
|
+
message(formatInfo(arr));
|
|
45777
|
+
}
|
|
44059
45778
|
};
|
|
44060
45779
|
|
|
44061
45780
|
cmd.printInfo = cmd.info; // old name
|
|
@@ -44069,6 +45788,16 @@ ${svg}
|
|
|
44069
45788
|
null_shape_count: 0,
|
|
44070
45789
|
null_data_count: lyr.data ? countNullRecords(lyr.data.getRecords()) : n
|
|
44071
45790
|
};
|
|
45791
|
+
if (layerHasRaster(lyr)) {
|
|
45792
|
+
o.geometry_type = null;
|
|
45793
|
+
o.raster_type = lyr.raster_type;
|
|
45794
|
+
o.raster_width = getRasterWidth(lyr.raster);
|
|
45795
|
+
o.raster_height = getRasterHeight(lyr.raster);
|
|
45796
|
+
o.raster_bands = getRasterBandCount(lyr.raster);
|
|
45797
|
+
o.raster_pixel_type = getRasterPixelType(lyr.raster);
|
|
45798
|
+
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
45799
|
+
o.proj4 = getProjInfo(dataset);
|
|
45800
|
+
}
|
|
44072
45801
|
if (lyr.shapes && lyr.shapes.length > 0) {
|
|
44073
45802
|
o.null_shape_count = countNullShapes(lyr.shapes);
|
|
44074
45803
|
o.bbox = getLayerBounds(lyr, dataset.arcs).toArray();
|
|
@@ -44098,7 +45827,7 @@ ${svg}
|
|
|
44098
45827
|
var str = '';
|
|
44099
45828
|
arr.forEach(function(info, i) {
|
|
44100
45829
|
var title = 'Layer: ' + (info.layer_name || '[unnamed layer]');
|
|
44101
|
-
var tableStr = formatAttributeTableInfo(info.attribute_data);
|
|
45830
|
+
var tableStr = info.raster_type ? '' : formatAttributeTableInfo(info.attribute_data);
|
|
44102
45831
|
var tableWidth = measureLongestLine(tableStr);
|
|
44103
45832
|
var ruleLen = Math.min(Math.max(title.length, tableWidth), MAX_RULE_LEN);
|
|
44104
45833
|
str += '\n';
|
|
@@ -44113,12 +45842,17 @@ ${svg}
|
|
|
44113
45842
|
|
|
44114
45843
|
function formatLayerInfo(data) {
|
|
44115
45844
|
var str = '';
|
|
44116
|
-
str += "Type: " + (data.geometry_type || "tabular data") + "\n";
|
|
44117
|
-
|
|
45845
|
+
str += "Type: " + (data.raster_type ? "raster data" : data.geometry_type || "tabular data") + "\n";
|
|
45846
|
+
if (data.raster_type) {
|
|
45847
|
+
str += utils.format("Size: %,d x %,d x %,d\n", data.raster_width, data.raster_height, data.raster_bands);
|
|
45848
|
+
str += "Data: " + (data.raster_pixel_type || 'unknown') + "\n";
|
|
45849
|
+
} else {
|
|
45850
|
+
str += utils.format("Records: %,d\n",data.feature_count);
|
|
45851
|
+
}
|
|
44118
45852
|
if (data.null_shape_count > 0) {
|
|
44119
45853
|
str += utils.format("Nulls: %'d", data.null_shape_count) + "\n";
|
|
44120
45854
|
}
|
|
44121
|
-
if (data.geometry_type && data.feature_count > data.null_shape_count) {
|
|
45855
|
+
if (data.raster_type || data.geometry_type && data.feature_count > data.null_shape_count) {
|
|
44122
45856
|
str += "Bounds: " + data.bbox.join(',') + "\n";
|
|
44123
45857
|
str += "CRS: " + data.proj4 + "\n";
|
|
44124
45858
|
}
|
|
@@ -49377,8 +51111,15 @@ ${svg}
|
|
|
49377
51111
|
}
|
|
49378
51112
|
|
|
49379
51113
|
cmd.printHelp = function(opts) {
|
|
49380
|
-
var
|
|
49381
|
-
|
|
51114
|
+
var parser = getOptionParser();
|
|
51115
|
+
if (runningInBrowser()) {
|
|
51116
|
+
message({
|
|
51117
|
+
type: 'mapshaper-console-help',
|
|
51118
|
+
lines: parser.getHelpLines(opts.command)
|
|
51119
|
+
});
|
|
51120
|
+
} else {
|
|
51121
|
+
print(parser.getHelpMessage(opts.command));
|
|
51122
|
+
}
|
|
49382
51123
|
};
|
|
49383
51124
|
|
|
49384
51125
|
function stopJob(job) {
|
|
@@ -55528,7 +57269,7 @@ ${svg}
|
|
|
55528
57269
|
});
|
|
55529
57270
|
}
|
|
55530
57271
|
|
|
55531
|
-
var version = "0.7.
|
|
57272
|
+
var version = "0.7.14";
|
|
55532
57273
|
|
|
55533
57274
|
// Parse command line args into commands and run them
|
|
55534
57275
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|
|
@@ -56429,6 +58170,8 @@ ${svg}
|
|
|
56429
58170
|
detail: copyDetail(detail),
|
|
56430
58171
|
name: layer.name,
|
|
56431
58172
|
geometry_type: layer.geometry_type,
|
|
58173
|
+
raster_type: layer.raster_type || null,
|
|
58174
|
+
raster: layer.raster ? copyRasterData(layer.raster) : null,
|
|
56432
58175
|
shapes: layer.shapes ? cloneShapes(layer.shapes) : null,
|
|
56433
58176
|
data: layer.data || null
|
|
56434
58177
|
});
|
|
@@ -56722,6 +58465,8 @@ ${svg}
|
|
|
56722
58465
|
revision: getUndoRevision(unit.target),
|
|
56723
58466
|
name: unit.target.name,
|
|
56724
58467
|
geometry_type: unit.target.geometry_type,
|
|
58468
|
+
raster_type: unit.target.raster_type || null,
|
|
58469
|
+
raster: unit.target.raster ? copyRasterData(unit.target.raster) : null,
|
|
56725
58470
|
shapes: unit.target.shapes ? cloneShapes(unit.target.shapes) : null,
|
|
56726
58471
|
data: unit.target.data || null
|
|
56727
58472
|
});
|
|
@@ -56848,6 +58593,8 @@ ${svg}
|
|
|
56848
58593
|
function restoreLayer(unit) {
|
|
56849
58594
|
unit.target.name = unit.name;
|
|
56850
58595
|
unit.target.geometry_type = unit.geometry_type;
|
|
58596
|
+
unit.target.raster_type = unit.raster_type || null;
|
|
58597
|
+
unit.target.raster = unit.raster ? copyRasterData(unit.raster) : null;
|
|
56851
58598
|
unit.target.shapes = unit.shapes ? cloneShapes(unit.shapes) : null;
|
|
56852
58599
|
unit.target.data = unit.data;
|
|
56853
58600
|
}
|
|
@@ -57051,6 +58798,7 @@ ${svg}
|
|
|
57051
58798
|
Lines,
|
|
57052
58799
|
Logging,
|
|
57053
58800
|
Profile,
|
|
58801
|
+
RasterUtils,
|
|
57054
58802
|
Merging,
|
|
57055
58803
|
MosaicIndex$1,
|
|
57056
58804
|
OptionParsingUtils,
|