@deck.gl/geo-layers
Version:
deck.gl layers supporting geospatial use cases and GIS formats
522 lines (428 loc) • 19.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _core = require("@deck.gl/core");
var _core2 = require("@math.gl/core");
var _mvt = require("@loaders.gl/mvt");
var _gis = require("@loaders.gl/gis");
var _extensions = require("@deck.gl/extensions");
var _tileLayer = _interopRequireDefault(require("../tile-layer/tile-layer"));
var _utils = require("../tile-layer/utils");
var _coordinateTransform = require("./coordinate-transform");
var _findIndexBinary = _interopRequireDefault(require("./find-index-binary"));
var _layers = require("@deck.gl/layers");
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, 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 normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var WORLD_SIZE = 512;
var defaultProps = _objectSpread(_objectSpread({}, _layers.GeoJsonLayer.defaultProps), {}, {
uniqueIdProperty: {
type: 'string',
value: ''
},
highlightedFeatureId: null,
loaders: [_mvt.MVTWorkerLoader],
binary: true
});
var MVTLayer = function (_TileLayer) {
(0, _inherits2.default)(MVTLayer, _TileLayer);
var _super = _createSuper(MVTLayer);
function MVTLayer() {
(0, _classCallCheck2.default)(this, MVTLayer);
return _super.apply(this, arguments);
}
(0, _createClass2.default)(MVTLayer, [{
key: "initializeState",
value: function initializeState() {
(0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "initializeState", this).call(this);
var binary = this.context.viewport.resolution !== undefined ? false : this.props.binary;
this.setState({
binary: binary,
data: null,
tileJSON: null
});
}
}, {
key: "isLoaded",
get: function get() {
return this.state.data && this.state.tileset && (0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "isLoaded", this);
}
}, {
key: "updateState",
value: function updateState(_ref) {
var props = _ref.props,
oldProps = _ref.oldProps,
context = _ref.context,
changeFlags = _ref.changeFlags;
if (changeFlags.dataChanged) {
this._updateTileData();
}
if (this.state.data) {
(0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "updateState", this).call(this, {
props: props,
oldProps: oldProps,
context: context,
changeFlags: changeFlags
});
this._setWGS84PropertyForTiles();
}
var highlightColor = props.highlightColor;
if (highlightColor !== oldProps.highlightColor && Array.isArray(highlightColor)) {
this.setState({
highlightColor: highlightColor
});
}
}
}, {
key: "_updateTileData",
value: function () {
var _updateTileData2 = (0, _asyncToGenerator2.default)(_regenerator.default.mark(function _callee() {
var data, tileJSON, _this$props, onDataLoad, fetch;
return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
data = this.props.data;
tileJSON = null;
if (!(typeof data === 'string' && !(0, _utils.isURLTemplate)(data))) {
_context.next = 18;
break;
}
_this$props = this.props, onDataLoad = _this$props.onDataLoad, fetch = _this$props.fetch;
this.setState({
data: null,
tileJSON: null
});
_context.prev = 5;
_context.next = 8;
return fetch(data, {
propName: 'data',
layer: this,
loaders: []
});
case 8:
tileJSON = _context.sent;
_context.next = 15;
break;
case 11:
_context.prev = 11;
_context.t0 = _context["catch"](5);
this.raiseError(_context.t0, 'loading TileJSON');
data = null;
case 15:
if (onDataLoad) {
onDataLoad(tileJSON);
}
_context.next = 19;
break;
case 18:
if (data.tilejson) {
tileJSON = data;
}
case 19:
if (tileJSON) {
data = tileJSON.tiles;
}
this.setState({
data: data,
tileJSON: tileJSON
});
case 21:
case "end":
return _context.stop();
}
}
}, _callee, this, [[5, 11]]);
}));
function _updateTileData() {
return _updateTileData2.apply(this, arguments);
}
return _updateTileData;
}()
}, {
key: "_getTilesetOptions",
value: function _getTilesetOptions(props) {
var opts = (0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "_getTilesetOptions", this).call(this, props);
var tileJSON = this.state.tileJSON;
if (tileJSON) {
if (Number.isFinite(tileJSON.minzoom) && tileJSON.minzoom > props.minZoom) {
opts.minZoom = tileJSON.minzoom;
}
if (Number.isFinite(tileJSON.maxzoom) && (!Number.isFinite(props.maxZoom) || tileJSON.maxzoom < props.maxZoom)) {
opts.maxZoom = tileJSON.maxzoom;
}
}
return opts;
}
}, {
key: "renderLayers",
value: function renderLayers() {
if (!this.state.data) return null;
return (0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "renderLayers", this).call(this);
}
}, {
key: "getTileData",
value: function getTileData(tile) {
var _loadOptions;
var url = (0, _utils.getURLFromTemplate)(this.state.data, tile);
if (!url) {
return Promise.reject('Invalid URL');
}
var loadOptions = this.getLoadOptions();
var binary = this.state.binary;
var fetch = this.props.fetch;
var signal = tile.signal,
x = tile.x,
y = tile.y,
z = tile.z;
loadOptions = _objectSpread(_objectSpread({}, loadOptions), {}, {
mimeType: 'application/x-protobuf',
mvt: _objectSpread(_objectSpread({}, (_loadOptions = loadOptions) === null || _loadOptions === void 0 ? void 0 : _loadOptions.mvt), {}, {
coordinates: this.context.viewport.resolution ? 'wgs84' : 'local',
tileIndex: {
x: x,
y: y,
z: z
}
}),
gis: binary ? {
format: 'binary'
} : {}
});
return fetch(url, {
propName: 'data',
layer: this,
loadOptions: loadOptions,
signal: signal
});
}
}, {
key: "renderSubLayers",
value: function renderSubLayers(props) {
var tile = props.tile;
var worldScale = Math.pow(2, tile.z);
var xScale = WORLD_SIZE / worldScale;
var yScale = -xScale;
var xOffset = WORLD_SIZE * tile.x / worldScale;
var yOffset = WORLD_SIZE * (1 - tile.y / worldScale);
var modelMatrix = new _core2.Matrix4().scale([xScale, yScale, 1]);
props.autoHighlight = false;
if (!this.context.viewport.resolution) {
props.modelMatrix = modelMatrix;
props.coordinateOrigin = [xOffset, yOffset, 0];
props.coordinateSystem = _core.COORDINATE_SYSTEM.CARTESIAN;
props.extensions = [].concat((0, _toConsumableArray2.default)(props.extensions || []), [new _extensions.ClipExtension()]);
}
var subLayers = (0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "renderSubLayers", this).call(this, props);
if (this.state.binary && !(subLayers instanceof _layers.GeoJsonLayer)) {
_core.log.warn('renderSubLayers() must return GeoJsonLayer when using binary:true')();
}
return subLayers;
}
}, {
key: "_updateAutoHighlight",
value: function _updateAutoHighlight(info) {
var uniqueIdProperty = this.props.uniqueIdProperty;
var _this$state = this.state,
hoveredFeatureId = _this$state.hoveredFeatureId,
hoveredFeatureLayerName = _this$state.hoveredFeatureLayerName;
var hoveredFeature = info.object;
var newHoveredFeatureId;
var newHoveredFeatureLayerName;
if (hoveredFeature) {
newHoveredFeatureId = getFeatureUniqueId(hoveredFeature, uniqueIdProperty);
newHoveredFeatureLayerName = getFeatureLayerName(hoveredFeature);
}
var highlightColor = this.props.highlightColor;
if (typeof highlightColor === 'function') {
highlightColor = highlightColor(info);
}
if (hoveredFeatureId !== newHoveredFeatureId || hoveredFeatureLayerName !== newHoveredFeatureLayerName) {
this.setState({
highlightColor: highlightColor,
hoveredFeatureId: newHoveredFeatureId,
hoveredFeatureLayerName: newHoveredFeatureLayerName
});
}
}
}, {
key: "getPickingInfo",
value: function getPickingInfo(params) {
var info = (0, _get2.default)((0, _getPrototypeOf2.default)(MVTLayer.prototype), "getPickingInfo", this).call(this, params);
var isWGS84 = this.context.viewport.resolution;
if (this.state.binary && info.index !== -1) {
var data = params.sourceLayer.props.data;
info.object = (0, _gis.binaryToGeojson)(data, {
globalFeatureId: info.index
});
}
if (info.object && !isWGS84) {
info.object = transformTileCoordsToWGS84(info.object, info.tile.bbox, this.context.viewport);
}
return info;
}
}, {
key: "getSubLayerPropsByTile",
value: function getSubLayerPropsByTile(tile) {
return {
highlightedObjectIndex: this.getHighlightedObjectIndex(tile),
highlightColor: this.state.highlightColor
};
}
}, {
key: "getHighlightedObjectIndex",
value: function getHighlightedObjectIndex(tile) {
var _this$state2 = this.state,
hoveredFeatureId = _this$state2.hoveredFeatureId,
hoveredFeatureLayerName = _this$state2.hoveredFeatureLayerName,
binary = _this$state2.binary;
var _this$props2 = this.props,
uniqueIdProperty = _this$props2.uniqueIdProperty,
highlightedFeatureId = _this$props2.highlightedFeatureId;
var data = tile.content;
var isHighlighted = isFeatureIdDefined(highlightedFeatureId);
var isFeatureIdPresent = isFeatureIdDefined(hoveredFeatureId) || isHighlighted;
if (!isFeatureIdPresent) {
return -1;
}
var featureIdToHighlight = isHighlighted ? highlightedFeatureId : hoveredFeatureId;
if (Array.isArray(data)) {
return data.findIndex(function (feature) {
var isMatchingId = getFeatureUniqueId(feature, uniqueIdProperty) === featureIdToHighlight;
var isMatchingLayer = isHighlighted || getFeatureLayerName(feature) === hoveredFeatureLayerName;
return isMatchingId && isMatchingLayer;
});
} else if (data && binary) {
return (0, _findIndexBinary.default)(data, uniqueIdProperty, featureIdToHighlight, isHighlighted ? '' : hoveredFeatureLayerName);
}
return -1;
}
}, {
key: "_pickObjects",
value: function _pickObjects(maxObjects) {
var _this$context = this.context,
deck = _this$context.deck,
viewport = _this$context.viewport;
var width = viewport.width;
var height = viewport.height;
var x = viewport.x;
var y = viewport.y;
var layerIds = [this.id];
return deck.pickObjects({
x: x,
y: y,
width: width,
height: height,
layerIds: layerIds,
maxObjects: maxObjects
});
}
}, {
key: "getRenderedFeatures",
value: function getRenderedFeatures() {
var maxFeatures = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
var features = this._pickObjects(maxFeatures);
var featureCache = new Set();
var renderedFeatures = [];
var _iterator = _createForOfIteratorHelper(features),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var f = _step.value;
var featureId = getFeatureUniqueId(f.object, this.props.uniqueIdProperty);
if (featureId === undefined) {
renderedFeatures.push(f.object);
} else if (!featureCache.has(featureId)) {
featureCache.add(featureId);
renderedFeatures.push(f.object);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return renderedFeatures;
}
}, {
key: "_setWGS84PropertyForTiles",
value: function _setWGS84PropertyForTiles() {
var _this = this;
var propName = 'dataInWGS84';
var tileset = this.state.tileset;
tileset.selectedTiles.forEach(function (tile) {
if (!tile.hasOwnProperty(propName)) {
Object.defineProperty(tile, propName, {
get: function get() {
if (!tile.content) {
return null;
}
if (_this.state.binary && Array.isArray(tile.content) && !tile.content.length) {
return [];
}
if (tile._contentWGS84 === undefined) {
var content = _this.state.binary ? (0, _gis.binaryToGeojson)(tile.content) : tile.content;
tile._contentWGS84 = content.map(function (feature) {
return transformTileCoordsToWGS84(feature, tile.bbox, _this.context.viewport);
});
}
return tile._contentWGS84;
}
});
}
});
}
}]);
return MVTLayer;
}(_tileLayer.default);
exports.default = MVTLayer;
function getFeatureUniqueId(feature, uniqueIdProperty) {
if (uniqueIdProperty) {
return feature.properties[uniqueIdProperty];
}
if ('id' in feature) {
return feature.id;
}
return undefined;
}
function getFeatureLayerName(feature) {
var _feature$properties;
return ((_feature$properties = feature.properties) === null || _feature$properties === void 0 ? void 0 : _feature$properties.layerName) || null;
}
function isFeatureIdDefined(value) {
return value !== undefined && value !== null && value !== '';
}
function transformTileCoordsToWGS84(object, bbox, viewport) {
var feature = _objectSpread(_objectSpread({}, object), {}, {
geometry: {
type: object.geometry.type
}
});
Object.defineProperty(feature.geometry, 'coordinates', {
get: function get() {
var wgs84Geom = (0, _coordinateTransform.transform)(object.geometry, bbox, viewport);
return wgs84Geom.coordinates;
}
});
return feature;
}
MVTLayer.layerName = 'MVTLayer';
MVTLayer.defaultProps = defaultProps;
//# sourceMappingURL=mvt-layer.js.map