@deck.gl/geo-layers
Version:
deck.gl layers supporting geospatial use cases and GIS formats
431 lines (358 loc) • 16.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.normalizeLongitudes = normalizeLongitudes;
exports.scalePolygon = scalePolygon;
exports.default = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
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 _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _h3Js = require("h3-js");
var _core = require("@math.gl/core");
var _core2 = require("@deck.gl/core");
var _layers = require("@deck.gl/layers");
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; }
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; }
var UPDATE_THRESHOLD_KM = 10;
function normalizeLongitudes(vertices, refLng) {
refLng = refLng === undefined ? vertices[0][0] : refLng;
var _iterator = _createForOfIteratorHelper(vertices),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var pt = _step.value;
var deltaLng = pt[0] - refLng;
if (deltaLng > 180) {
pt[0] -= 360;
} else if (deltaLng < -180) {
pt[0] += 360;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
function scalePolygon(hexId, vertices, factor) {
var _h3ToGeo = (0, _h3Js.h3ToGeo)(hexId),
_h3ToGeo2 = (0, _slicedToArray2.default)(_h3ToGeo, 2),
lat = _h3ToGeo2[0],
lng = _h3ToGeo2[1];
var actualCount = vertices.length;
normalizeLongitudes(vertices, lng);
var vertexCount = vertices[0] === vertices[actualCount - 1] ? actualCount - 1 : actualCount;
for (var i = 0; i < vertexCount; i++) {
vertices[i][0] = (0, _core.lerp)(lng, vertices[i][0], factor);
vertices[i][1] = (0, _core.lerp)(lat, vertices[i][1], factor);
}
}
function getHexagonCentroid(getHexagon, object, objectInfo) {
var hexagonId = getHexagon(object, objectInfo);
var _h3ToGeo3 = (0, _h3Js.h3ToGeo)(hexagonId),
_h3ToGeo4 = (0, _slicedToArray2.default)(_h3ToGeo3, 2),
lat = _h3ToGeo4[0],
lng = _h3ToGeo4[1];
return [lng, lat];
}
function h3ToPolygon(hexId) {
var coverage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
var flatten = arguments.length > 2 ? arguments[2] : undefined;
var vertices = (0, _h3Js.h3ToGeoBoundary)(hexId, true);
if (coverage !== 1) {
scalePolygon(hexId, vertices, coverage);
} else {
normalizeLongitudes(vertices);
}
if (flatten) {
var positions = new Float64Array(vertices.length * 2);
var i = 0;
var _iterator2 = _createForOfIteratorHelper(vertices),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var pt = _step2.value;
positions[i++] = pt[0];
positions[i++] = pt[1];
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
return positions;
}
return vertices;
}
function mergeTriggers(getHexagon, coverage) {
var trigger;
if (getHexagon === undefined || getHexagon === null) {
trigger = coverage;
} else if ((0, _typeof2.default)(getHexagon) === 'object') {
trigger = _objectSpread(_objectSpread({}, getHexagon), {}, {
coverage: coverage
});
} else {
trigger = {
getHexagon: getHexagon,
coverage: coverage
};
}
return trigger;
}
var defaultProps = _objectSpread(_objectSpread({}, _layers.PolygonLayer.defaultProps), {}, {
highPrecision: 'auto',
coverage: {
type: 'number',
min: 0,
max: 1,
value: 1
},
centerHexagon: null,
getHexagon: {
type: 'accessor',
value: function value(x) {
return x.hexagon;
}
},
extruded: true
});
delete defaultProps.getLineDashArray;
var H3HexagonLayer = function (_CompositeLayer) {
(0, _inherits2.default)(H3HexagonLayer, _CompositeLayer);
var _super = _createSuper(H3HexagonLayer);
function H3HexagonLayer() {
(0, _classCallCheck2.default)(this, H3HexagonLayer);
return _super.apply(this, arguments);
}
(0, _createClass2.default)(H3HexagonLayer, [{
key: "shouldUpdateState",
value: function shouldUpdateState(_ref) {
var changeFlags = _ref.changeFlags;
return this._shouldUseHighPrecision() ? changeFlags.propsOrDataChanged : changeFlags.somethingChanged;
}
}, {
key: "updateState",
value: function updateState(_ref2) {
var props = _ref2.props,
oldProps = _ref2.oldProps,
changeFlags = _ref2.changeFlags;
if (props.highPrecision !== true && (changeFlags.dataChanged || changeFlags.updateTriggers && changeFlags.updateTriggers.getHexagon)) {
var dataProps = this._calculateH3DataProps(props);
this.setState(dataProps);
}
this._updateVertices(this.context.viewport);
}
}, {
key: "_calculateH3DataProps",
value: function _calculateH3DataProps(props) {
var resolution = -1;
var hasPentagon = false;
var hasMultipleRes = false;
var _createIterable = (0, _core2.createIterable)(props.data),
iterable = _createIterable.iterable,
objectInfo = _createIterable.objectInfo;
var _iterator3 = _createForOfIteratorHelper(iterable),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var object = _step3.value;
objectInfo.index++;
var hexId = props.getHexagon(object, objectInfo);
var hexResolution = (0, _h3Js.h3GetResolution)(hexId);
if (resolution < 0) {
resolution = hexResolution;
if (!props.highPrecision) break;
} else if (resolution !== hexResolution) {
hasMultipleRes = true;
break;
}
if ((0, _h3Js.h3IsPentagon)(hexId)) {
hasPentagon = true;
break;
}
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
return {
resolution: resolution,
edgeLengthKM: resolution >= 0 ? (0, _h3Js.edgeLength)(resolution, _h3Js.UNITS.km) : 0,
hasMultipleRes: hasMultipleRes,
hasPentagon: hasPentagon
};
}
}, {
key: "_shouldUseHighPrecision",
value: function _shouldUseHighPrecision() {
if (this.props.highPrecision === 'auto') {
var _this$state = this.state,
resolution = _this$state.resolution,
hasPentagon = _this$state.hasPentagon,
hasMultipleRes = _this$state.hasMultipleRes;
var viewport = this.context.viewport;
return viewport.resolution || hasMultipleRes || hasPentagon || resolution >= 0 && resolution <= 5;
}
return this.props.highPrecision;
}
}, {
key: "_updateVertices",
value: function _updateVertices(viewport) {
if (this._shouldUseHighPrecision()) {
return;
}
var _this$state2 = this.state,
resolution = _this$state2.resolution,
edgeLengthKM = _this$state2.edgeLengthKM,
centerHex = _this$state2.centerHex;
if (resolution < 0) {
return;
}
var hex = this.props.centerHexagon || (0, _h3Js.geoToH3)(viewport.latitude, viewport.longitude, resolution);
if (centerHex === hex) {
return;
}
if (centerHex) {
var distance = (0, _h3Js.h3Distance)(centerHex, hex);
if (distance >= 0 && distance * edgeLengthKM < UPDATE_THRESHOLD_KM) {
return;
}
}
var unitsPerMeter = viewport.distanceScales.unitsPerMeter;
var vertices = h3ToPolygon(hex);
var _h3ToGeo5 = (0, _h3Js.h3ToGeo)(hex),
_h3ToGeo6 = (0, _slicedToArray2.default)(_h3ToGeo5, 2),
centerLat = _h3ToGeo6[0],
centerLng = _h3ToGeo6[1];
var _viewport$projectFlat = viewport.projectFlat([centerLng, centerLat]),
_viewport$projectFlat2 = (0, _slicedToArray2.default)(_viewport$projectFlat, 2),
centerX = _viewport$projectFlat2[0],
centerY = _viewport$projectFlat2[1];
vertices = vertices.map(function (p) {
var worldPosition = viewport.projectFlat(p);
return [(worldPosition[0] - centerX) / unitsPerMeter[0], (worldPosition[1] - centerY) / unitsPerMeter[1]];
});
this.setState({
centerHex: hex,
vertices: vertices
});
}
}, {
key: "renderLayers",
value: function renderLayers() {
return this._shouldUseHighPrecision() ? this._renderPolygonLayer() : this._renderColumnLayer();
}
}, {
key: "_getForwardProps",
value: function _getForwardProps() {
var _this$props = this.props,
elevationScale = _this$props.elevationScale,
material = _this$props.material,
coverage = _this$props.coverage,
extruded = _this$props.extruded,
wireframe = _this$props.wireframe,
stroked = _this$props.stroked,
filled = _this$props.filled,
lineWidthUnits = _this$props.lineWidthUnits,
lineWidthScale = _this$props.lineWidthScale,
lineWidthMinPixels = _this$props.lineWidthMinPixels,
lineWidthMaxPixels = _this$props.lineWidthMaxPixels,
getFillColor = _this$props.getFillColor,
getElevation = _this$props.getElevation,
getLineColor = _this$props.getLineColor,
getLineWidth = _this$props.getLineWidth,
transitions = _this$props.transitions,
updateTriggers = _this$props.updateTriggers;
return {
elevationScale: elevationScale,
extruded: extruded,
coverage: coverage,
wireframe: wireframe,
stroked: stroked,
filled: filled,
lineWidthUnits: lineWidthUnits,
lineWidthScale: lineWidthScale,
lineWidthMinPixels: lineWidthMinPixels,
lineWidthMaxPixels: lineWidthMaxPixels,
material: material,
getElevation: getElevation,
getFillColor: getFillColor,
getLineColor: getLineColor,
getLineWidth: getLineWidth,
transitions: transitions,
updateTriggers: {
getFillColor: updateTriggers.getFillColor,
getElevation: updateTriggers.getElevation,
getLineColor: updateTriggers.getLineColor,
getLineWidth: updateTriggers.getLineWidth
}
};
}
}, {
key: "_renderPolygonLayer",
value: function _renderPolygonLayer() {
var _this$props2 = this.props,
data = _this$props2.data,
getHexagon = _this$props2.getHexagon,
updateTriggers = _this$props2.updateTriggers,
coverage = _this$props2.coverage;
var SubLayerClass = this.getSubLayerClass('hexagon-cell-hifi', _layers.PolygonLayer);
var forwardProps = this._getForwardProps();
forwardProps.updateTriggers.getPolygon = mergeTriggers(updateTriggers.getHexagon, coverage);
return new SubLayerClass(forwardProps, this.getSubLayerProps({
id: 'hexagon-cell-hifi',
updateTriggers: forwardProps.updateTriggers
}), {
data: data,
_normalize: false,
_windingOrder: 'CCW',
positionFormat: 'XY',
getPolygon: function getPolygon(object, objectInfo) {
var hexagonId = getHexagon(object, objectInfo);
return h3ToPolygon(hexagonId, coverage, true);
}
});
}
}, {
key: "_renderColumnLayer",
value: function _renderColumnLayer() {
var _this$props3 = this.props,
data = _this$props3.data,
getHexagon = _this$props3.getHexagon,
updateTriggers = _this$props3.updateTriggers;
var SubLayerClass = this.getSubLayerClass('hexagon-cell', _layers.ColumnLayer);
var forwardProps = this._getForwardProps();
forwardProps.updateTriggers.getPosition = updateTriggers.getHexagon;
return new SubLayerClass(forwardProps, this.getSubLayerProps({
id: 'hexagon-cell',
flatShading: true,
updateTriggers: forwardProps.updateTriggers
}), {
data: data,
diskResolution: 6,
radius: 1,
vertices: this.state.vertices,
getPosition: getHexagonCentroid.bind(null, getHexagon)
});
}
}]);
return H3HexagonLayer;
}(_core2.CompositeLayer);
exports.default = H3HexagonLayer;
H3HexagonLayer.defaultProps = defaultProps;
H3HexagonLayer.layerName = 'H3HexagonLayer';
//# sourceMappingURL=h3-hexagon-layer.js.map