kepler.gl
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
923 lines (899 loc) • 130 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getNumRasterTilesBeingLoaded = exports["default"] = exports.LOAD_ELEVATION_AFTER_ZOOM = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _core = require("@deck.gl/core");
var _geoLayers = require("@deck.gl/geo-layers");
var _pmtiles = require("@loaders.gl/pmtiles");
var _memoize = _interopRequireDefault(require("lodash/memoize"));
var _layers = require("@deck.gl/layers");
var _constants = require("@kepler.gl/constants");
var _deckglLayers = require("@kepler.gl/deckgl-layers");
var _commonUtils = require("@kepler.gl/common-utils");
var _utils = require("@kepler.gl/utils");
var _config = require("./config");
var _gpuUtils = require("./gpu-utils");
var _image = require("./image");
var _rasterTileIcon = _interopRequireDefault(require("./raster-tile-icon"));
var _rasterTileUtils = require("./raster-tile-utils");
var _baseLayer = _interopRequireDefault(require("../base-layer"));
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _superPropGet(t, e, r, o) { var p = (0, _get2["default"])((0, _getPrototypeOf2["default"])(1 & o ? t.prototype : t), e, r); return 2 & o ? function (t) { return p.apply(r, t); } : p; } // SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project
// Adjust tileSize to devicePixelRatio, but not higher than 2 to reduce requests to server
var devicePixelRatio = Math.min(2, typeof window !== 'undefined' && window.devicePixelRatio || 1);
// Global counter that represents the number of tiles currently being loaded across all the raster tile layers
var tilesBeingLoaded = 0;
// This is a temp solution to track loading
var getNumRasterTilesBeingLoaded = exports.getNumRasterTilesBeingLoaded = function getNumRasterTilesBeingLoaded() {
return tilesBeingLoaded;
};
var LOAD_ELEVATION_AFTER_ZOOM = exports.LOAD_ELEVATION_AFTER_ZOOM = 8.9;
var getShouldLoadTerrain = function getShouldLoadTerrain(stac, mapState, visConfig) {
var _stac$rasterTileServe, _stac$rasterServerSup;
return Boolean(
// we need a raster tile server for elevations even when we user PMTiles
((_stac$rasterTileServe = stac.rasterTileServerUrls) === null || _stac$rasterTileServe === void 0 ? void 0 : _stac$rasterTileServe.length) > 0 &&
// check the switch from the layer configurator
visConfig.enableTerrain && (
// disabled in Top view by default
mapState.dragRotate || visConfig.enableTerrainTopView) && ((_stac$rasterServerSup = stac.rasterServerSupportsElevation) !== null && _stac$rasterServerSup !== void 0 ? _stac$rasterServerSup : (0, _utils.getApplicationConfig)().rasterServerSupportsElevation));
};
var RasterTileLayer = exports["default"] = /*#__PURE__*/function (_KeplerLayer) {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function RasterTileLayer(props) {
var _this;
(0, _classCallCheck2["default"])(this, RasterTileLayer);
_this = _callSuper(this, RasterTileLayer, [props]);
/** Min bands image data value, based on the current viewport */
(0, _defineProperty2["default"])(_this, "minViewportPixelValue", Infinity);
/** Max bands image data value, based on the current viewport */
(0, _defineProperty2["default"])(_this, "maxViewportPixelValue", -Infinity);
/** Memoized method that calculates data source params */
/** Callback to trigger a map redraw (stored from layerCallbacks) */
(0, _defineProperty2["default"])(_this, "onRedrawNeeded", void 0);
/** Track the last rendered preset to detect changes */
(0, _defineProperty2["default"])(_this, "_lastRenderedPreset", void 0);
/** Timeout ID for deferred redraws */
(0, _defineProperty2["default"])(_this, "_redrawTimeout", void 0);
(0, _defineProperty2["default"])(_this, "getDataSourceParams", void 0);
_this.registerVisConfig(_config.rasterVisConfigs);
// No two STAC ids may be the same within a single collection, though it's conceivably possible
// across multiple STAC collections there could be an id collision. Note: STAC Collection
// objects don't have a `collection` key; STAC Item objects have a `collection` key (which
// matches the collection's `id`).
var resolver = function resolver(stac, preset, presetOptions) {
var _presetOptions$single, _presetOptions$single2;
return "".concat(stac.id, "-").concat(stac.collection, "-").concat(preset, "-").concat((_presetOptions$single = presetOptions.singleBand) === null || _presetOptions$single === void 0 ? void 0 : _presetOptions$single.assetId, "-").concat((_presetOptions$single2 = presetOptions.singleBand) === null || _presetOptions$single2 === void 0 ? void 0 : _presetOptions$single2.bandIndex);
};
_this.getDataSourceParams = (0, _memoize["default"])(function (stac, preset, presetOptions) {
return (0, _rasterTileUtils.getDataSourceParams)(stac, preset, presetOptions);
}, resolver);
_this.meta = {
zRange: null
};
return _this;
}
(0, _inherits2["default"])(RasterTileLayer, _KeplerLayer);
return (0, _createClass2["default"])(RasterTileLayer, [{
key: "type",
get: function get() {
return _constants.LAYER_TYPES.rasterTile;
}
}, {
key: "name",
get: function get() {
return 'Raster Tile';
}
}, {
key: "layerIcon",
get: function get() {
return _rasterTileIcon["default"];
}
}, {
key: "supportedDatasetTypes",
get: function get() {
return [_constants.DatasetType.RASTER_TILE];
}
}, {
key: "visualChannels",
get: function get() {
var categoricalColorLegends = this.config.visConfig.colorRange.colorLegends;
if (categoricalColorLegends) {
return {
color: _superPropGet(RasterTileLayer, "visualChannels", this, 1).color
};
} else {
return {};
}
}
}, {
key: "requireData",
get: function get() {
return true;
}
}, {
key: "getDefaultLayerConfig",
value: function getDefaultLayerConfig(props) {
return _objectSpread(_objectSpread({}, _superPropGet(RasterTileLayer, "getDefaultLayerConfig", this, 3)([props])), {}, {
colorField: {
analyzerType: '',
name: 'Category',
format: '',
type: 'string',
fieldIdx: -1,
valueAccessor: function valueAccessor() {
return '';
},
displayName: 'Category'
}
});
}
}, {
key: "getHoverData",
value: function getHoverData() {
return null;
}
// We can render without columns, so we redefine this method
}, {
key: "shouldRenderLayer",
value: function shouldRenderLayer() {
return Boolean(this.type && this.config.isVisible);
}
}, {
key: "formatLayerData",
value: function formatLayerData(datasets, oldLayerData) {
var _dataset$metadata;
var dataId = this.config.dataId;
if (!(0, _commonUtils.notNullorUndefined)(dataId)) {
return {};
}
var dataset = datasets[dataId];
// call updateData to updateLayerMeta
var dataUpdateTriggers = this.getDataUpdateTriggers(dataset);
var triggerChanged = this.getChangedTriggers(dataUpdateTriggers);
if (triggerChanged && triggerChanged.getMeta) {
this.updateLayerMeta(dataset);
}
var tileSource = null;
if (((_dataset$metadata = dataset.metadata) === null || _dataset$metadata === void 0 ? void 0 : _dataset$metadata.pmtilesType) === _constants.PMTilesType.RASTER) {
var metadataUrl = dataset.metadata.metadataUrl;
// use the old tile source if it exists and matches the new metadataUrl
var _ref = oldLayerData || {},
oldDataset = _ref.dataset,
oldTileSource = _ref.tileSource;
if (oldDataset === dataset && (oldTileSource === null || oldTileSource === void 0 ? void 0 : oldTileSource.data) === metadataUrl) {
tileSource = oldLayerData.tileSource;
} else {
tileSource = metadataUrl ? _pmtiles.PMTilesSource.createDataSource(metadataUrl, {}) : null;
}
}
return {
dataset: dataset,
tileSource: tileSource
};
}
}, {
key: "updateLayerMeta",
value: function updateLayerMeta(dataset) {
if (dataset.type !== _constants.DatasetType.RASTER_TILE) {
return;
}
var stac = dataset.metadata;
if (stac.pmtilesType === _constants.PMTilesType.RASTER) {
return this.updateMeta({
bounds: stac.bounds
});
}
var bounds = (0, _rasterTileUtils.getSTACBounds)(stac);
if (bounds) {
// If a STAC Item (i.e. stac.type === 'Feature'), then set map bounds.
// But we don't want to set bounds for Landsat or Sentinel because it would zoom out to zoom
// 0, and we don't have low-zoom tiles.
if (stac.type === 'Feature') {
this.updateMeta({
bounds: bounds
});
}
}
}
/**
* Run when adding a new dataset
*/
}, {
key: "setInitialLayerConfig",
value: function setInitialLayerConfig(dataset) {
var stac = dataset === null || dataset === void 0 ? void 0 : dataset.metadata;
if (!stac) {
return this;
}
if (stac.pmtilesType === _constants.PMTilesType.RASTER) {
return this;
}
// When a STAC Collection is added, useStacSearching should be true to prevent a black screen
this.updateLayerVisConfig({
useSTACSearching: stac.type === 'Collection'
});
// Set singleBandName if there is only one band
var availableBands = (0, _rasterTileUtils.getEOBands)(stac) || [];
if ((availableBands === null || availableBands === void 0 ? void 0 : availableBands.length) === 1) {
this.updateLayerVisConfig({
singleBandName: availableBands[0].name
});
}
// Change the preset if the default one is not allowed
var availablePresets = (0, _rasterTileUtils.filterAvailablePresets)(stac, _config.PRESET_OPTIONS);
if (availablePresets !== null && availablePresets !== void 0 && availablePresets.length && !(availablePresets !== null && availablePresets !== void 0 && availablePresets.includes(this.visConfigSettings.preset.defaultValue))) {
this.updateLayerVisConfig({
preset: availablePresets[0]
});
}
// Apply improved image processing props only for non single band modes
var preset = this.config.visConfig.preset;
var colorDefaults = _config.DATA_SOURCE_COLOR_DEFAULTS[stac.id];
if (colorDefaults && preset !== 'singleBand') {
this.updateLayerVisConfig(colorDefaults);
}
/*
LandSat specifies temporal bounds but the valid data is after end date
const updatedDates = timeRangeToStacTemporalInterval(
stac as StacTypes.STACCollection,
this.config.visConfig.startDate,
this.config.visConfig.endDate
);
this.updateLayerVisConfig(updatedDates);
*/
return this;
}
/**
* Update zRange of viewport. This is necessary so that tiles in extruded mode are shown properly
* at high elevations: https://github.com/foursquare/studio-monorepo/pull/1892/files
* Derived from https://github.com/visgl/deck.gl/blob/8d824a4b836fee3bfebe6fc962e0f03d8c1dbd0d/modules/geo-layers/src/terrain-layer/terrain-layer.js#L173-L196
*
* @param tiles Array of tiles in current viewport
*/
}, {
key: "onViewportLoad",
value: function onViewportLoad(tiles) {
this.updateMinMaxPixelValue(tiles);
var newZRange = (0, _rasterTileUtils.computeZRange)(tiles);
if (!newZRange) {
return;
}
var zRange = this.meta.zRange;
if (!zRange || newZRange[0] < zRange[0] || newZRange[1] > zRange[1]) {
this.meta.zRange = newZRange;
}
}
/**
* Update viewport-related minPxelValue and maxPixelValue
* @param tiles - deck.gl tiles
*/
}, {
key: "updateMinMaxPixelValue",
value: function updateMinMaxPixelValue(tiles) {
var _getMinMaxFromTile2DH = (0, _rasterTileUtils.getMinMaxFromTile2DHeaders)(tiles),
_getMinMaxFromTile2DH2 = (0, _slicedToArray2["default"])(_getMinMaxFromTile2DH, 2),
min = _getMinMaxFromTile2DH2[0],
max = _getMinMaxFromTile2DH2[1];
this.minViewportPixelValue = min;
this.maxViewportPixelValue = max;
}
/**
* Calculate min and max values of input raster band image properties
* and update `minBandsValue` and `maxBandsValue`
* @param images - raster band image properties
* @return [min, max] pixel values for the tile
*/
}, {
key: "getMinMaxPixelValues",
value: function getMinMaxPixelValues(images) {
var minPixelValue = Infinity;
var maxPixelValue = -Infinity;
if (images) {
var _iterator = _createForOfIteratorHelper(images),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var image = _step.value;
var _getImageMinMax = (0, _rasterTileUtils.getImageMinMax)(image.data),
_getImageMinMax2 = (0, _slicedToArray2["default"])(_getImageMinMax, 2),
min = _getImageMinMax2[0],
max = _getImageMinMax2[1];
if (typeof min === 'number') {
minPixelValue = Math.min(min, minPixelValue);
}
if (typeof max === 'number') {
maxPixelValue = Math.max(max, maxPixelValue);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
return [minPixelValue, maxPixelValue];
}
// generate a deck layer
}, {
key: "renderLayer",
value: function renderLayer(opts) {
var _this$config$visConfi,
_this2 = this,
_data$dataset;
var data = opts.data,
layerCallbacks = opts.layerCallbacks;
// Store callback to trigger map redraw when sublayers need async re-render
this.onRedrawNeeded = layerCallbacks === null || layerCallbacks === void 0 ? void 0 : layerCallbacks.onRedrawNeeded;
// Detect preset changes and schedule a deferred redraw so that
// deck.gl re-renders sublayers after the new pipeline compiles
var currentPreset = (_this$config$visConfi = this.config.visConfig) === null || _this$config$visConfi === void 0 ? void 0 : _this$config$visConfi.preset;
if (this._lastRenderedPreset !== undefined && this._lastRenderedPreset !== currentPreset) {
if (this._redrawTimeout) clearTimeout(this._redrawTimeout);
this._redrawTimeout = setTimeout(function () {
var _this2$onRedrawNeeded;
_this2._redrawTimeout = undefined;
(_this2$onRedrawNeeded = _this2.onRedrawNeeded) === null || _this2$onRedrawNeeded === void 0 || _this2$onRedrawNeeded.call(_this2);
}, 100);
}
this._lastRenderedPreset = currentPreset;
if ((data === null || data === void 0 || (_data$dataset = data.dataset) === null || _data$dataset === void 0 || (_data$dataset = _data$dataset.metadata) === null || _data$dataset === void 0 ? void 0 : _data$dataset.pmtilesType) === _constants.PMTilesType.RASTER) {
return this.renderPMTilesLayer(opts);
}
return this.renderStacLayer(opts);
}
}, {
key: "renderStacLayer",
value: function renderStacLayer(opts) {
var _data$dataset2,
_this3 = this;
var data = opts.data,
mapState = opts.mapState,
experimentalContext = opts.experimentalContext,
layerCallbacks = opts.layerCallbacks;
var stac = data === null || data === void 0 || (_data$dataset2 = data.dataset) === null || _data$dataset2 === void 0 ? void 0 : _data$dataset2.metadata;
// If a tabular dataset is loaded, and then the layer type is switched from Point to Raster Tile
// layer, this `stac` object will exist but will not be raster metadata
if (!stac || !stac.stac_version) {
return [];
}
var visConfig = this.config.visConfig;
var _this$getDefaultDeckL = this.getDefaultDeckLayerProps(opts),
id = _this$getDefaultDeckL.id,
opacity = _this$getDefaultDeckL.opacity,
visible = _this$getDefaultDeckL.visible;
var hasShadowEffect = experimentalContext === null || experimentalContext === void 0 ? void 0 : experimentalContext.hasShadowEffect;
var preset = visConfig.preset,
colormapId = visConfig.colormapId,
linearRescaling = visConfig.linearRescaling,
linearRescalingFactor = visConfig.linearRescalingFactor,
nonLinearRescaling = visConfig.nonLinearRescaling,
gammaContrastFactor = visConfig.gammaContrastFactor,
sigmoidalContrastFactor = visConfig.sigmoidalContrastFactor,
sigmoidalBiasFactor = visConfig.sigmoidalBiasFactor,
saturationValue = visConfig.saturationValue,
filterEnabled = visConfig.filterEnabled,
filterRange = visConfig.filterRange,
useSTACSearching = visConfig.useSTACSearching,
stacSearchProvider = visConfig.stacSearchProvider,
startDate = visConfig.startDate,
endDate = visConfig.endDate,
_stacQuery = visConfig._stacQuery,
singleBandName = visConfig.singleBandName,
categoricalColorMap = visConfig.colorRange.colorMap,
dynamicColor = visConfig.dynamicColor;
var shouldLoadTerrain = getShouldLoadTerrain(stac, mapState, visConfig);
if (new Date(endDate) < new Date(startDate)) {
return [];
}
var bandCombination = _config.PRESET_OPTIONS[preset].bandCombination;
var singleBand = (0, _rasterTileUtils.getSingleBandPresetOptions)(stac, singleBandName);
var dataSourceParams = this.getDataSourceParams(stac, preset, {
singleBand: singleBand
});
if (!dataSourceParams) {
return [];
}
var minZoom = dataSourceParams.minZoom,
maxZoom = dataSourceParams.maxZoom,
globalBounds = dataSourceParams.globalBounds,
loadAssetIds = dataSourceParams.loadAssetIds,
loadBandIndexes = dataSourceParams.loadBandIndexes,
renderBandIndexes = dataSourceParams.renderBandIndexes,
dataType = dataSourceParams.dataType,
dsMinPixelValue = dataSourceParams.minPixelValue,
dsMaxPixelValue = dataSourceParams.maxPixelValue,
minCategoricalBandValue = dataSourceParams.minCategoricalBandValue,
maxCategoricalBandValue = dataSourceParams.maxCategoricalBandValue;
var minPixelValue = !dynamicColor && Number.isFinite(dsMinPixelValue) ? dsMinPixelValue : this.minViewportPixelValue;
var maxPixelValue = !dynamicColor && Number.isFinite(dsMaxPixelValue) ? dsMaxPixelValue : this.maxViewportPixelValue;
var getTileDataCustomProps = {
stac: stac,
loadAssetIds: loadAssetIds,
loadBandIndexes: loadBandIndexes,
colormapId: colormapId,
shouldLoadTerrain: shouldLoadTerrain,
globalBounds: globalBounds,
useSTACSearching: useSTACSearching,
stacSearchProvider: stacSearchProvider,
startDate: startDate,
endDate: endDate,
_stacQuery: _stacQuery,
categoricalColorMap: categoricalColorMap,
minCategoricalBandValue: minCategoricalBandValue,
maxCategoricalBandValue: maxCategoricalBandValue
};
var tileLayer = new _geoLayers.TileLayer(_objectSpread(_objectSpread({
id: id,
minZoom: minZoom,
maxZoom: maxZoom,
tileSize: 512 / devicePixelRatio,
getTileData: function getTileData(args) {
return _this3.getTileData(_objectSpread(_objectSpread({}, args), getTileDataCustomProps));
},
onViewportLoad: this.onViewportLoad.bind(this),
// @ts-expect-error - TS doesn't know we'll pass appropriate props here
renderSubLayers: renderSubLayersStac,
maxRequests: (0, _rasterTileUtils.getMaxRequests)(stac.rasterTileServerUrls || []),
// Passing visible on to TileLayer is necessary for split view to work
visible: visible,
updateTriggers: {
getTileData: [shouldLoadTerrain,
// Colormap has changed
colormapId].concat((0, _toConsumableArray2["default"])(loadAssetIds), (0, _toConsumableArray2["default"])(loadBandIndexes), [useSTACSearching, stacSearchProvider, startDate, endDate, _stacQuery, categoricalColorMap, minCategoricalBandValue, maxCategoricalBandValue])
}
}, shouldLoadTerrain ? {
zRange: this.meta.zRange || null,
refinementStrategy: 'no-overlap'
} : {}), {}, {
renderBandIndexes: renderBandIndexes,
opacity: opacity,
linearRescaling: linearRescaling,
linearRescalingFactor: linearRescalingFactor,
nonLinearRescaling: nonLinearRescaling,
minPixelValue: minPixelValue,
maxPixelValue: maxPixelValue,
gammaContrastFactor: gammaContrastFactor,
sigmoidalContrastFactor: sigmoidalContrastFactor,
sigmoidalBiasFactor: sigmoidalBiasFactor,
saturationValue: saturationValue,
bandCombination: bandCombination,
filterEnabled: filterEnabled,
filterRange: filterRange,
dataType: dataType,
minCategoricalBandValue: minCategoricalBandValue,
maxCategoricalBandValue: maxCategoricalBandValue,
hasCategoricalColorMap: Boolean(categoricalColorMap),
hasShadowEffect: hasShadowEffect,
onRedrawNeeded: layerCallbacks === null || layerCallbacks === void 0 ? void 0 : layerCallbacks.onRedrawNeeded
}));
return [tileLayer];
}
}, {
key: "renderPMTilesLayer",
value: function renderPMTilesLayer(opts) {
var _data$dataset3,
_this4 = this;
var _this$getDefaultDeckL2 = this.getDefaultDeckLayerProps(opts),
id = _this$getDefaultDeckL2.id,
opacity = _this$getDefaultDeckL2.opacity,
visible = _this$getDefaultDeckL2.visible;
var data = opts.data,
mapState = opts.mapState,
layerCallbacks = opts.layerCallbacks;
var metadata = data === null || data === void 0 || (_data$dataset3 = data.dataset) === null || _data$dataset3 === void 0 ? void 0 : _data$dataset3.metadata;
var visConfig = this.config.visConfig;
var tileSource = data.tileSource;
var showTileBorders = false;
var minZoom = metadata.minZoom || 0;
var maxZoom = metadata.maxZoom || 30;
var shouldLoadTerrain = getShouldLoadTerrain(metadata, mapState, visConfig);
return [new _geoLayers.TileLayer(_objectSpread(_objectSpread({
id: id,
getTileData: function getTileData(args) {
return _this4.getTileDataPMTiles(_objectSpread(_objectSpread({}, args), {}, {
shouldLoadTerrain: shouldLoadTerrain,
metadata: metadata
}), tileSource);
},
// Assume the pmtiles file support HTTP/2, so we aren't limited by the browser to a certain number per domain.
maxRequests: 20,
pickable: true,
autoHighlight: showTileBorders,
onViewportLoad: this.onViewportLoad.bind(this),
minZoom: minZoom,
maxZoom: maxZoom,
tileSize: 512 / devicePixelRatio,
zoomOffset: devicePixelRatio === 1 ? -1 : 0,
// @ts-expect-error - TS doesn't know we'll pass appropriate props here
renderSubLayers: renderSubLayersPMTiles,
tileSource: tileSource,
showTileBorders: showTileBorders,
visible: visible,
opacity: opacity,
updateTriggers: {
getTileData: [shouldLoadTerrain]
}
}, shouldLoadTerrain ? {
zRange: this.meta.zRange || null,
refinementStrategy: 'no-overlap'
} : {}), {}, {
onRedrawNeeded: layerCallbacks === null || layerCallbacks === void 0 ? void 0 : layerCallbacks.onRedrawNeeded
}))];
}
}, {
key: "getTileData",
value: function () {
var _getTileData = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(props) {
var shouldLoadTerrain, globalBounds, _props$bbox, west, south, east, north, zoom, assetRequests, terrain, _yield$Promise$all, _yield$Promise$all2, images, _terrain, _this$getMinMaxPixelV, _this$getMinMaxPixelV2, min, max;
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
shouldLoadTerrain = props.shouldLoadTerrain, globalBounds = props.globalBounds, _props$bbox = props.bbox, west = _props$bbox.west, south = _props$bbox.south, east = _props$bbox.east, north = _props$bbox.north, zoom = props.index.z;
if (!(globalBounds && !(0, _rasterTileUtils.bboxIntersects)(globalBounds, [west, south, east, north]))) {
_context.next = 3;
break;
}
return _context.abrupt("return", null);
case 3:
_context.next = 5;
return (0, _image.getSTACImageRequests)(props);
case 5:
assetRequests = _context.sent;
if (assetRequests) {
_context.next = 14;
break;
}
_context.t0 = shouldLoadTerrain && LOAD_ELEVATION_AFTER_ZOOM < zoom;
if (!_context.t0) {
_context.next = 12;
break;
}
_context.next = 11;
return (0, _image.loadTerrain)({
boundsForGeometry: [west, north, east, south],
index: props.index,
signal: props.signal,
rasterTileServerUrls: props.stac.rasterTileServerUrls || [],
rasterServerMaxRetries: props.stac.rasterServerMaxRetries,
rasterServerRetryDelay: props.stac.rasterServerRetryDelay,
rasterServerServerErrorsToRetry: props.stac.rasterServerServerErrorsToRetry,
rasterServerMaxPerServerRequests: props.stac.rasterServerMaxPerServerRequests
});
case 11:
_context.t0 = _context.sent;
case 12:
terrain = _context.t0;
return _context.abrupt("return", _objectSpread({
images: null
}, terrain ? {
terrain: terrain
} : {}));
case 14:
tilesBeingLoaded++;
// Wrap loading images into a try/catch because tiles that are only briefly in view will be
// aborted. The `AbortController.abort()` creates a DOMException error.
// Note that since loading is async, try/catch will only work when awaited inside the try block
_context.prev = 15;
_context.next = 18;
return Promise.all([(0, _image.loadImages)(assetRequests, props.colormapId, {
colorMap: props.categoricalColorMap,
minValue: props.minCategoricalBandValue,
maxValue: props.maxCategoricalBandValue
}), shouldLoadTerrain && LOAD_ELEVATION_AFTER_ZOOM < zoom ? (0, _image.loadTerrain)({
boundsForGeometry: [west, north, east, south],
index: props.index,
signal: props.signal,
rasterTileServerUrls: props.stac.rasterTileServerUrls || [],
rasterServerMaxRetries: props.stac.rasterServerMaxRetries,
rasterServerRetryDelay: props.stac.rasterServerRetryDelay,
rasterServerServerErrorsToRetry: props.stac.rasterServerServerErrorsToRetry,
rasterServerMaxPerServerRequests: props.stac.rasterServerMaxPerServerRequests
}) : null]);
case 18:
_yield$Promise$all = _context.sent;
_yield$Promise$all2 = (0, _slicedToArray2["default"])(_yield$Promise$all, 2);
images = _yield$Promise$all2[0];
_terrain = _yield$Promise$all2[1];
_this$getMinMaxPixelV = this.getMinMaxPixelValues(images.imageBands), _this$getMinMaxPixelV2 = (0, _slicedToArray2["default"])(_this$getMinMaxPixelV, 2), min = _this$getMinMaxPixelV2[0], max = _this$getMinMaxPixelV2[1];
tilesBeingLoaded--;
// Add terrain data only if we requested it above
return _context.abrupt("return", _objectSpread(_objectSpread({
images: images
}, _terrain ? {
terrain: _terrain
} : {}), {}, {
minPixelValue: min,
maxPixelValue: max
}));
case 27:
_context.prev = 27;
_context.t1 = _context["catch"](15);
tilesBeingLoaded--;
if (!(_context.t1.name === 'AbortError')) {
_context.next = 32;
break;
}
return _context.abrupt("return", null);
case 32:
throw _context.t1;
case 33:
case "end":
return _context.stop();
}
}, _callee, this, [[15, 27]]);
}));
function getTileData(_x) {
return _getTileData.apply(this, arguments);
}
return getTileData;
}()
}, {
key: "getTileDataPMTiles",
value: function () {
var _getTileDataPMTiles = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(props, tileSource) {
var shouldLoadTerrain, globalBounds, _props$bbox2, west, south, east, north, zoom, metadata, _yield$Promise$all3, _yield$Promise$all4, image, terrain, minPixelValue, maxPixelValue, _this$getMinMaxPixelV3, _this$getMinMaxPixelV4, min, max;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
shouldLoadTerrain = props.shouldLoadTerrain, globalBounds = props.globalBounds, _props$bbox2 = props.bbox, west = _props$bbox2.west, south = _props$bbox2.south, east = _props$bbox2.east, north = _props$bbox2.north, zoom = props.index.z, metadata = props.metadata;
if (!(globalBounds && !(0, _rasterTileUtils.bboxIntersects)(globalBounds, [west, south, east, north]))) {
_context2.next = 3;
break;
}
return _context2.abrupt("return", null);
case 3:
tilesBeingLoaded++;
_context2.prev = 4;
_context2.next = 7;
return Promise.all([tileSource.getTileData(props)]);
case 7:
_yield$Promise$all3 = _context2.sent;
_yield$Promise$all4 = (0, _slicedToArray2["default"])(_yield$Promise$all3, 1);
image = _yield$Promise$all4[0];
if (!(image && shouldLoadTerrain && LOAD_ELEVATION_AFTER_ZOOM < zoom)) {
_context2.next = 16;
break;
}
_context2.next = 13;
return (0, _image.loadTerrain)({
boundsForGeometry: [west, north, east, south],
index: props.index,
signal: props.signal,
rasterTileServerUrls: metadata.rasterTileServerUrls,
rasterServerMaxRetries: metadata.rasterServerMaxRetries,
rasterServerRetryDelay: metadata.rasterServerRetryDelay,
rasterServerServerErrorsToRetry: metadata.rasterServerServerErrorsToRetry,
rasterServerMaxPerServerRequests: metadata.rasterServerMaxPerServerRequests
});
case 13:
_context2.t0 = _context2.sent;
_context2.next = 17;
break;
case 16:
_context2.t0 = null;
case 17:
terrain = _context2.t0;
minPixelValue = null;
maxPixelValue = null;
if (image) {
_this$getMinMaxPixelV3 = this.getMinMaxPixelValues([{
data: image
}]), _this$getMinMaxPixelV4 = (0, _slicedToArray2["default"])(_this$getMinMaxPixelV3, 2), min = _this$getMinMaxPixelV4[0], max = _this$getMinMaxPixelV4[1];
minPixelValue = min;
maxPixelValue = max;
}
tilesBeingLoaded--;
// Add terrain data only if we requested it above
return _context2.abrupt("return", _objectSpread({
image: image,
minPixelValue: minPixelValue,
maxPixelValue: maxPixelValue
}, terrain ? {
terrain: terrain
} : {}));
case 25:
_context2.prev = 25;
_context2.t1 = _context2["catch"](4);
tilesBeingLoaded--;
if (!(_context2.t1.name === 'AbortError')) {
_context2.next = 30;
break;
}
return _context2.abrupt("return", null);
case 30:
throw _context2.t1;
case 31:
case "end":
return _context2.stop();
}
}, _callee2, this, [[4, 25]]);
}));
function getTileDataPMTiles(_x2, _x3) {
return _getTileDataPMTiles.apply(this, arguments);
}
return getTileDataPMTiles;
}()
}], [{
key: "findDefaultLayerProps",
value: function findDefaultLayerProps(dataset) {
if (dataset.type !== _constants.DatasetType.RASTER_TILE) {
return {
props: []
};
}
var newLayerProp = {
dataId: dataset.id,
label: dataset.label,
isVisible: true
};
return {
props: [newLayerProp]
};
}
}]);
}(_baseLayer["default"]);
function renderSubLayersStac(props) {
var tile = props.tile,
data = props.data,
globalMinPixelValue = props.minPixelValue,
globalMaxPixelValue = props.maxPixelValue;
var bbox = tile.bbox;
var west = bbox.west,
south = bbox.south,
east = bbox.east,
north = bbox.north;
if (!data) {
return [];
}
var images = data.images,
terrain = data.terrain,
tileMinPixelValue = data.minPixelValue,
tileMaxPixelValue = data.maxPixelValue;
if (!images || Array.isArray(images) && images.length === 0) {
return [];
}
var minPixelValue = Number.isFinite(globalMinPixelValue) ? globalMinPixelValue : tileMinPixelValue;
var maxPixelValue = Number.isFinite(globalMaxPixelValue) ? globalMaxPixelValue : tileMaxPixelValue;
if (typeof minPixelValue !== 'number' || typeof maxPixelValue !== 'number') {
return [];
}
var _getModules = (0, _gpuUtils.getModules)({
images: images,
props: _objectSpread(_objectSpread({}, props), {}, {
minPixelValue: minPixelValue,
maxPixelValue: maxPixelValue
})
}),
modules = _getModules.modules,
moduleProps = _getModules.moduleProps;
var idSuffix = props.hasShadowEffect ? 'shadow' : '';
return terrain ? new _deckglLayers.RasterMeshLayer(props, {
id: "raster-3d-layer-".concat(props.id, "-").concat(idSuffix),
// Dummy data
data: [1],
mesh: terrain,
images: images,
modules: modules,
moduleProps: moduleProps,
getPolygonOffset: null,
coordinateSystem: _core.COORDINATE_SYSTEM.LNGLAT,
// Color to use if surfaceImage is unavailable
getColor: [255, 255, 255]
// material: false
}) : new _deckglLayers.RasterLayer(props, {
id: "raster-2d-layer-".concat(props.id, "-").concat(idSuffix),
images: images,
modules: modules,
moduleProps: moduleProps,
bounds: [west, south, east, north],
_imageCoordinateSystem: _core.COORDINATE_SYSTEM.CARTESIAN
});
}
function renderSubLayersPMTiles(props) {
var _props$data;
var tileSource = props.tileSource,
showTileBorders = props.showTileBorders,
minZoom = props.minZoom,
maxZoom = props.maxZoom,
_props$tile = props.tile,
zoom = _props$tile.index.z,
_props$tile$bbox = _props$tile.bbox,
west = _props$tile$bbox.west,
south = _props$tile$bbox.south,
east = _props$tile$bbox.east,
north = _props$tile$bbox.north;
var layers = [];
if ((_props$data = props.data) !== null && _props$data !== void 0 && _props$data.image) {
switch (tileSource.mimeType) {
case 'image/png':
case 'image/jpeg':
case 'image/webp':
case 'image/avif':
layers.push(getRasterLayerPMTiles(props));
break;
default:
break;
}
}
// Debug tile borders
var borderColor = zoom <= minZoom || zoom >= maxZoom ? [255, 0, 0, 255] : [0, 0, 255, 255];
if (showTileBorders) {
layers.push(new _layers.PathLayer({
id: "".concat(props.id, "-border"),
data: [[[west, north], [west, south], [east, south], [east, north], [west, north]]],
getPath: function getPath(d) {
return d;
},
getColor: borderColor,
widthMinPixels: 4
}));
}
return layers;
}
function getRasterLayerPMTiles(props) {
var tile = props.tile,
data = props.data;
var bbox = tile.bbox;
var west = bbox.west,
south = bbox.south,
east = bbox.east,
north = bbox.north;
if (!(data !== null && data !== void 0 && data.image)) {
return [];
}
var images = {
imageRgba: {
data: data.image
}
};
var terrain = data.terrain;
var _getModules2 = (0, _gpuUtils.getModules)({
images: images
}),
modules = _getModules2.modules,
moduleProps = _getModules2.moduleProps;
return terrain ? new _deckglLayers.RasterMeshLayer(props, {
id: "raster-3d-layer-".concat(props.id),
// Dummy data
data: [1],
mesh: terrain,
images: images,
modules: modules,
moduleProps: moduleProps,
getPolygonOffset: null,
coordinateSystem: _core.COORDINATE_SYSTEM.LNGLAT,
// Color to use if surfaceImage is unavailable
getColor: [255, 255, 255]
// material: false
}) : new _deckglLayers.RasterLayer(props, {
id: "raster-2d-layer-".concat(props.id),
data: null,
images: images,
modules: modules,
moduleProps: moduleProps,
bounds: [west, south, east, north],
_imageCoordinateSystem: _core.COORDINATE_SYSTEM.CARTESIAN
});
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY29yZSIsInJlcXVpcmUiLCJfZ2VvTGF5ZXJzIiwiX3BtdGlsZXMiLCJfbWVtb2l6ZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJfbGF5ZXJzIiwiX2NvbnN0YW50cyIsIl9kZWNrZ2xMYXllcnMiLCJfY29tbW9uVXRpbHMiLCJfdXRpbHMiLCJfY29uZmlnIiwiX2dwdVV0aWxzIiwiX2ltYWdlIiwiX3Jhc3RlclRpbGVJY29uIiwiX3Jhc3RlclRpbGVVdGlscyIsIl9iYXNlTGF5ZXIiLCJfY3JlYXRlRm9yT2ZJdGVyYXRvckhlbHBlciIsInIiLCJlIiwidCIsIlN5bWJvbCIsIml0ZXJhdG9yIiwiQXJyYXkiLCJpc0FycmF5IiwiX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5IiwibGVuZ3RoIiwiX24iLCJGIiwicyIsIm4iLCJkb25lIiwidmFsdWUiLCJmIiwiVHlwZUVycm9yIiwibyIsImEiLCJ1IiwiY2FsbCIsIm5leHQiLCJfYXJyYXlMaWtlVG9BcnJheSIsInRvU3RyaW5nIiwic2xpY2UiLCJjb25zdHJ1Y3RvciIsIm5hbWUiLCJmcm9tIiwidGVzdCIsIm93bktleXMiLCJPYmplY3QiLCJrZXlzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiZmlsdGVyIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVmaW5lUHJvcGVydHkiLCJfY2FsbFN1cGVyIiwiX2dldFByb3RvdHlwZU9mMiIsIl9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuMiIsIl9pc05hdGl2ZVJlZmxlY3RDb25zdHJ1Y3QiLCJSZWZsZWN0IiwiY29uc3RydWN0IiwiQm9vbGVhbiIsInByb3RvdHlwZSIsInZhbHVlT2YiLCJfc3VwZXJQcm9wR2V0IiwicCIsIl9nZXQyIiwiZGV2aWNlUGl4ZWxSYXRpbyIsIk1hdGgiLCJtaW4iLCJ3aW5kb3ciLCJ0aWxlc0JlaW5nTG9hZGVkIiwiZ2V0TnVtUmFzdGVyVGlsZXNCZWluZ0xvYWRlZCIsImV4cG9ydHMiLCJMT0FEX0VMRVZBVElPTl9BRlRFUl9aT09NIiwiZ2V0U2hvdWxkTG9hZFRlcnJhaW4iLCJzdGFjIiwibWFwU3RhdGUiLCJ2aXNDb25maWciLCJfc3RhYyRyYXN0ZXJUaWxlU2VydmUiLCJfc3RhYyRyYXN0ZXJTZXJ2ZXJTdXAiLCJyYXN0ZXJUaWxlU2VydmVyVXJscyIsImVuYWJsZVRlcnJhaW4iLCJkcmFnUm90YXRlIiwiZW5hYmxlVGVycmFpblRvcFZpZXciLCJyYXN0ZXJTZXJ2ZXJTdXBwb3J0c0VsZXZhdGlvbiIsImdldEFwcGxpY2F0aW9uQ29uZmlnIiwiUmFzdGVyVGlsZUxheWVyIiwiX0tlcGxlckxheWVyIiwicHJvcHMiLCJfdGhpcyIsIl9jbGFzc0NhbGxDaGVjazIiLCJJbmZpbml0eSIsInJlZ2lzdGVyVmlzQ29uZmlnIiwicmFzdGVyVmlzQ29uZmlncyIsInJlc29sdmVyIiwicHJlc2V0IiwicHJlc2V0T3B0aW9ucyIsIl9wcmVzZXRPcHRpb25zJHNpbmdsZSIsIl9wcmVzZXRPcHRpb25zJHNpbmdsZTIiLCJjb25jYXQiLCJpZCIsImNvbGxlY3Rpb24iLCJzaW5nbGVCYW5kIiwiYXNzZXRJZCIsImJhbmRJbmRleCIsImdldERhdGFTb3VyY2VQYXJhbXMiLCJtZW1vaXplIiwibWV0YSIsInpSYW5nZSIsIl9pbmhlcml0czIiLCJfY3JlYXRlQ2xhc3MyIiwia2V5IiwiZ2V0IiwiTEFZRVJfVFlQRVMiLCJyYXN0ZXJUaWxlIiwiUmFzdGVySWNvbiIsIkRhdGFzZXRUeXBlIiwiUkFTVEVSX1RJTEUiLCJjYXRlZ29yaWNhbENvbG9yTGVnZW5kcyIsImNvbmZpZyIsImNvbG9yUmFuZ2UiLCJjb2xvckxlZ2VuZHMiLCJjb2xvciIsImdldERlZmF1bHRMYXllckNvbmZpZyIsImNvbG9yRmllbGQiLCJhbmFseXplclR5cGUiLCJmb3JtYXQiLCJ0eXBlIiwiZmllbGRJZHgiLCJ2YWx1ZUFjY2Vzc29yIiwiZGlzcGxheU5hbWUiLCJnZXRIb3ZlckRhdGEiLCJzaG91bGRSZW5kZXJMYXllciIsImlzVmlzaWJsZSIsImZvcm1hdExheWVyRGF0YSIsImRhdGFzZXRzIiwib2xkTGF5ZXJEYXRhIiwiX2RhdGFzZXQkbWV0YWRhdGEiLCJkYXRhSWQiLCJub3ROdWxsb3JVbmRlZmluZWQiLCJkYXRhc2V0IiwiZGF0YVVwZGF0ZVRyaWdnZXJzIiwiZ2V0RGF0YVVwZGF0ZVRyaWdnZXJzIiwidHJpZ2dlckNoYW5nZWQiLCJnZXRDaGFuZ2VkVHJpZ2dlcnMiLCJnZXRNZXRhIiwidXBkYXRlTGF5ZXJNZXRhIiwidGlsZVNvdXJjZSIsIm1ldGFkYXRhIiwicG10aWxlc1R5cGUiLCJQTVRpbGVzVHlwZSIsIlJBU1RFUiIsIm1ldGFkYXRhVXJsIiwiX3JlZiIsIm9sZERhdGFzZXQiLCJvbGRUaWxlU291cmNlIiwiZGF0YSIsIlBNVGlsZXNTb3VyY2UiLCJjcmVhdGVEYXRhU291cmNlIiwidXBkYXRlTWV0YSIsImJvdW5kcyIsImdldFNUQUNCb3VuZHMiLCJzZXRJbml0aWFsTGF5ZXJDb25maWciLCJ1cGRhdGVMYXllclZpc0NvbmZpZyIsInVzZVNUQUNTZWFyY2hpbmciLCJhdmFpbGFibGVCYW5kcyIsImdldEVPQmFuZHMiLCJzaW5nbGVCYW5kTmFtZSIsImF2YWlsYWJsZVByZXNldHMiLCJmaWx0ZXJBdmFpbGFibGVQcmVzZXRzIiwiUFJFU0VUX09QVElPTlMiLCJpbmNsdWRlcyIsInZpc0NvbmZpZ1NldHRpbmdzIiwiZGVmYXVsdFZhbHVlIiwiY29sb3JEZWZhdWx0cyIsIkRBVEFfU09VUkNFX0NPTE9SX0RFRkFVTFRTIiwib25WaWV3cG9ydExvYWQiLCJ0aWxlcyIsInVwZGF0ZU1pbk1heFBpeGVsVmFsdWUiLCJuZXdaUmFuZ2UiLCJjb21wdXRlWlJhbmdlIiwiX2dldE1pbk1heEZyb21UaWxlMkRIIiwiZ2V0TWluTWF4RnJvbVRpbGUyREhlYWRlcnMiLCJfZ2V0TWluTWF4RnJvbVRpbGUyREgyIiwiX3NsaWNlZFRvQXJyYXkyIiwibWF4IiwibWluVmlld3BvcnRQaXhlbFZhbHVlIiwibWF4Vmlld3BvcnRQaXhlbFZhbHVlIiwiZ2V0TWluTWF4UGl4ZWxWYWx1ZXMiLCJpbWFnZXMiLCJtaW5QaXhlbFZhbHVlIiwibWF4UGl4ZWxWYWx1ZSIsIl9pdGVyYXRvciIsIl9zdGVwIiwiaW1hZ2UiLCJfZ2V0SW1hZ2VNaW5NYXgiLCJnZXRJbWFnZU1pbk1heCIsIl9nZXRJbWFnZU1pbk1heDIiLCJlcnIiLCJyZW5kZXJMYXllciIsIm9wdHMiLCJfdGhpcyRjb25maWckdmlzQ29uZmkiLCJfdGhpczIiLCJfZGF0YSRkYXRhc2V0IiwibGF5ZXJDYWxsYmFja3MiLCJvblJlZHJhd05lZWRlZCIsImN1cnJlbnRQcmVzZXQiLCJfbGFzdFJlbmRlcmVkUHJlc2V0IiwidW5kZWZpbmVkIiwiX3JlZHJhd1RpbWVvdXQiLCJjbGVhclRpbWVvdXQiLCJzZXRUaW1lb3V0IiwiX3RoaXMyJG9uUmVkcmF3TmVlZGVkIiwicmVuZGVyUE1UaWxlc0xheWVyIiwicmVuZGVyU3RhY0xheWVyIiwiX2RhdGEkZGF0YXNldDIiLCJfdGhpczMiLCJleHBlcmltZW50YWxDb250ZXh0Iiwic3RhY192ZXJzaW9uIiwiX3RoaXMkZ2V0RGVmYXVsdERlY2tMIiwiZ2V0RGVmYXVsdERlY2tMYXllclByb3BzIiwib3BhY2l0eSIsInZpc2libGUiLCJoYXNTaGFkb3dFZmZlY3QiLCJjb2xvcm1hcElkIiwibGluZWFyUmVzY2FsaW5nIiwibGluZWFyUmVzY2FsaW5nRmFjdG9yIiwibm9uTGluZWFyUmVzY2FsaW5nIiwiZ2FtbWFDb250cmFzdEZhY3RvciIsInNpZ21vaWRhbENvbnRyYXN0RmFjdG9yIiwic2lnbW9pZGFsQmlhc0ZhY3RvciIsInNhdHVyYXRpb25WYWx1ZSIsImZpbHRlckVuYWJsZWQiLCJmaWx0ZXJSYW5nZSIsInN0YWNTZWFyY2hQcm92aWRlciIsInN0YXJ0RGF0ZSIsImVuZERhdGUiLCJfc3RhY1F1ZXJ5IiwiY2F0ZWdvcmljYWxDb2xvck1hcCIsImNvbG9yTWFwIiwiZHluYW1pY0NvbG9yIiwic2hvdWxkTG9hZFRlcnJhaW4iLCJEYXRlIiwiYmFuZENvbWJpbmF0aW9uIiwiZ2V0U2luZ2xlQmFuZFByZXNldE9wdGlvbnMiLCJkYXRhU291cmNlUGFyYW1zIiwibWluWm9vbSIsIm1heFpvb20iLCJnbG9iYWxCb3VuZHMiLCJsb2FkQXNzZXRJZHMiLCJsb2FkQmFuZEluZGV4ZXMiLCJyZW5kZXJCYW5kSW5kZXhlcyIsImRhdGFUeXBlIiwiZHNNaW5QaXhlbFZhbHVlIiwiZHNNYXhQaXhlbFZhbHVlIiwibWluQ2F0ZWdvcmljYWxCYW5kVmFsdWUiLCJtYXhDYXRlZ29yaWNhbEJhbmRWYWx1ZSIsIk51bWJlciIsImlzRmluaXRlIiwiZ2V0VGlsZURhdGFDdXN0b21Qcm9wcyIsInRpbGVMYXllciIsIlRpbGVMYXllciIsInRpbGVTaXplIiwiZ2V0VGlsZURhdGEiLCJhcmdzIiwiYmluZCIsInJlbmRlclN1YkxheWVycyIsInJlbmRlclN1YkxheWVyc1N0YWMiLCJtYXhSZXF1ZXN0cyIsImdldE1heFJlcXVlc3RzIiwidXBkYXRlVHJpZ2dlcnMiLCJfdG9Db25zdW1hYmxlQXJyYXkyIiwicmVmaW5lbWVudFN0cmF0ZWd5IiwiaGFzQ2F0ZWdvcmljYWxDb2xvck1hcCIsIl9kYXRhJGRhdGFzZXQzIiwiX3RoaXM0IiwiX3RoaXMkZ2V0RGVmYXVsdERlY2tMMiIsInNob3dUaWxlQm9yZGVycyIsImdldFRpbGVEYXRhUE1UaWxlcyIsInBpY2thYmxlIiwiYXV0b0hpZ2hsaWdodCIsInpvb21PZmZzZXQiLCJyZW5kZXJTdWJMYXllcnNQTVRpbGVzIiwiX2dldFRpbGVEYXRhIiwiX2FzeW5jVG9HZW5lcmF0b3IyIiwiX3JlZ2VuZXJhdG9yIiwibWFyayIsIl9jYWxsZWUiLCJfcHJvcHMkYmJveCIsIndlc3QiLCJzb3V0aCIsImVhc3QiLCJub3J0aCIsInpvb20iLCJhc3NldFJlcXVlc3RzIiwidGVycmFpbiIsIl95aWVsZCRQcm9taXNlJGFsbCIsIl95aWVsZCRQcm9taXNlJGFsbDIiLCJfdGVycmFpbiIsIl90aGlzJGdldE1pbk1heFBpeGVsViIsIl90aGlzJGdldE1pbk1heFBpeGVsVjIiLCJ3cmFwIiwiX2NhbGxlZSQiLCJfY29udGV4dCIsInByZXYiLCJiYm94IiwiaW5kZXgiLCJ6IiwiYmJveEludGVyc2VjdHMiLCJhYnJ1cHQiLCJnZXRTVEFDSW1hZ2VSZXF1ZXN0cyIsInNlbnQiLCJ0MCIsImxvYWRUZXJyYWluIiwiYm91bmRzRm9yR2VvbWV0cnkiLCJzaWduYWwiLCJyYXN0ZXJTZXJ2ZXJNYXhSZXRyaWVzIiwicmFzdGVyU2VydmVyUmV0cnlEZWxheSIsInJhc3RlclNlcnZlclNlcnZlckVycm9yc1RvUmV0cnkiLCJyYXN0ZXJTZXJ2ZXJNYXhQZXJTZXJ2ZXJSZXF1ZXN0cyIsIlByb21pc2UiLCJhbGwiLCJsb2FkSW1hZ2VzIiwibWluVmFsdWUiLCJtYXhWYWx1ZSIsImltYWdlQmFuZHMiLCJ0MSIsInN0b3AiLCJfeCIsIl9nZXRUaWxlRGF0YVBNVGlsZXMiLCJfY2FsbGVlMiIsIl9wcm9wcyRiYm94MiIsIl95aWVsZCRQcm9taXNlJGFsbDMiLCJfeWllbGQkUHJvbWlzZSRhbGw0IiwiX3RoaXMkZ2V0TWluTWF4UGl4ZWxWMyIsIl90aGlzJGdldE1pbk1heFBpeGVsVjQiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJfeDIiLCJfeDMiLCJmaW5kRGVmYXVsdExheWVyUHJvcHMiLCJuZXdMYXllclByb3AiLCJsYWJlbCIsIktlcGxlckxheWVyIiwidGlsZSIsImdsb2JhbE1pblBpeGVsVmFsdWUiLCJnbG9iYWxNYXhQaXhlbFZhbHVlIiwidGlsZU1pblBpeGVsVmFsdWUiLCJ0aWxlTWF4UGl4ZWxWYWx1ZSIsIl9nZXRNb2R1bGVzIiwiZ2V0TW9kdWxlcyIsIm1vZHVsZXMiLCJtb2R1bGVQcm9wcyIsImlkU3VmZml4IiwiUmFzdGVyTWVzaExheWVyIiwibWVzaCIsImdldFBvbHlnb25PZmZzZXQiLCJjb29yZGluYXRlU3lzdGVtIiwiQ09PUkRJTkFURV9TWVNURU0iLCJMTkdMQVQiLCJnZXRDb2xvciIsIlJhc3RlckxheWVyIiwiX2ltYWdlQ29vcmRpbmF0ZVN5c3RlbSIsIkNBUlRFU0lBTiIsIl9wcm9wcyRkYXRhIiwiX3Byb3BzJHRpbGUiLCJfcHJvcHMkdGlsZSRiYm94IiwibGF5ZXJzIiwibWltZVR5cGUiLCJnZXRSYXN0ZXJMYXllclBNVGlsZXMiLCJib3JkZXJDb2xvciIsIlBhdGhMYXllciIsImdldFBhdGgiLCJkIiwid2lkdGhNaW5QaXhlbHMiLCJpbWFnZVJnYmEiLCJfZ2V0TW9kdWxlczIiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvcmFzdGVyLXRpbGUvcmFzdGVyLXRpbGUtbGF5ZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVFxuLy8gQ29weXJpZ2h0IGNvbnRyaWJ1dG9ycyB0byB0aGUga2VwbGVyLmdsIHByb2plY3RcblxuaW1wb3J0IHtDT09SRElOQVRFX1NZU1RFTSwgTGF5ZXIgYXMgRGVja0xheWVyfSBmcm9tICdAZGVja