qwc2
Version:
QGIS Web Client
947 lines (932 loc) • 65.4 kB
JavaScript
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
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 _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
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) { _defineProperty(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 _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* Copyright 2024 Sourcepole AG
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import Instance from '@giro3d/giro3d/core/Instance.js';
import Coordinates, { crsIsGeographic } from '@giro3d/giro3d/core/geographic/Coordinates';
import Ellipsoid from '@giro3d/giro3d/core/geographic/Ellipsoid';
import Extent from '@giro3d/giro3d/core/geographic/Extent.js';
import CoordinateSystem from '@giro3d/giro3d/core/geographic/coordinate-system/CoordinateSystem';
import ElevationLayer from '@giro3d/giro3d/core/layer/ElevationLayer.js';
import DrapedFeatureCollection from '@giro3d/giro3d/entities/DrapedFeatureCollection';
import Map from '@giro3d/giro3d/entities/Map.js';
import Tiles3D from "@giro3d/giro3d/entities/Tiles3D.js";
import Inspector from "@giro3d/giro3d/gui/Inspector.js";
import GeoTIFFSource from "@giro3d/giro3d/sources/GeoTIFFSource.js";
import axios from 'axios';
import { fromUrl } from "geotiff";
import isEmpty from 'lodash.isempty';
import PropTypes from 'prop-types';
import { Vector2, CubeTextureLoader, Group, Raycaster, Mesh, Box3, Vector3, Matrix4 } from 'three';
import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader';
import { v4 as uuidv4 } from 'uuid';
import { LayerRole } from '../../actions/layers';
import { setCurrentTask } from '../../actions/task';
import ConfigUtils from '../../utils/ConfigUtils';
import CoordinatesUtils from '../../utils/CoordinatesUtils';
import LayerUtils from '../../utils/LayerUtils';
import MiscUtils from '../../utils/MiscUtils';
import { registerPermalinkDataStoreHook, unregisterPermalinkDataStoreHook, UrlParams } from '../../utils/PermaLinkUtils';
import ServiceLayerUtils from '../../utils/ServiceLayerUtils';
import ThemeUtils from '../../utils/ThemeUtils';
import { MapContainerPortalContext } from '../PluginsContainer';
import EditDataset3D from './EditDataset3D';
import MapControls3D from './MapControls3D';
import View3DSwitcher from './View3DSwitcher';
import LayerRegistry from './layers/index';
import { importGltf, updateObjectLabel } from './utils/MiscUtils3D';
import Tiles3DStyle from './utils/Tiles3DStyle';
import './style/Map3D.css';
// Ensures unUnload is called *after* all other children have unmounted
var UnloadWrapper = /*#__PURE__*/function (_React$Component) {
function UnloadWrapper() {
var _this;
_classCallCheck(this, UnloadWrapper);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _callSuper(this, UnloadWrapper, [].concat(args));
_defineProperty(_this, "onUnload", function (el) {
if (!el) {
_this.props.onUnload(_this.props.sceneId);
}
});
return _this;
}
_inherits(UnloadWrapper, _React$Component);
return _createClass(UnloadWrapper, [{
key: "render",
value: function render() {
return /*#__PURE__*/React.createElement("div", null, this.props.children, /*#__PURE__*/React.createElement("span", {
ref: this.onUnload
}));
}
}]);
}(React.Component);
_defineProperty(UnloadWrapper, "propTypes", {
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
onUnload: PropTypes.func,
sceneId: PropTypes.string
});
var Map3D = /*#__PURE__*/function (_React$Component2) {
function Map3D(props) {
var _this2;
_classCallCheck(this, Map3D);
_this2 = _callSuper(this, Map3D, [props]);
_defineProperty(_this2, "state", {
sceneContext: _objectSpread(_objectSpread({}, Map3D.defaultSceneState), {}, {
addLayer: function addLayer(layer) {},
getLayer: function getLayer(layerId) {},
removeLayer: function removeLayer(layerId) {},
updateColorLayer: function updateColorLayer(layerId, options, path) {},
setBaseLayer: function setBaseLayer(layer, visibility) {},
add3dTiles: function add3dTiles(url, options) {},
addSceneObject: function addSceneObject(objectId, object) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var showEditTool = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
},
getSceneObject: function getSceneObject(objectId) {},
removeSceneObject: function removeSceneObject(objectId) {},
updateSceneObject: function updateSceneObject(objectId, options) {},
zoomToObject: function zoomToObject(objectId) {},
getMap: function getMap() {},
setViewToExtent: function setViewToExtent(bounds, angle) {},
getTerrainHeightFromDTM: function getTerrainHeightFromDTM(scenePos) {},
getTerrainHeightFromMap: function getTerrainHeightFromMap(scenePos) {},
getSceneIntersection: function getSceneIntersection(x, y, objects) {},
getSetting: function getSetting(key) {},
setSetting: function setSetting(key, value) {}
}),
sceneId: null
});
_defineProperty(_this2, "applyBaseLayer", function () {
var _baseLayer$name;
var baseLayer = _this2.state.sceneContext.baseLayers.find(function (e) {
return e.visibility === true;
});
_this2.removeLayer("__baselayer");
UrlParams.updateParams({
bl3d: (_baseLayer$name = baseLayer === null || baseLayer === void 0 ? void 0 : baseLayer.name) !== null && _baseLayer$name !== void 0 ? _baseLayer$name : ''
});
if (!baseLayer) {
return;
}
var layerCreator = LayerRegistry[baseLayer.type];
if (layerCreator !== null && layerCreator !== void 0 && layerCreator.create3d) {
var layer3d = layerCreator.create3d(baseLayer, _this2.state.sceneContext.mapCrs);
_this2.addLayer("__baselayer", layer3d);
_this2.map.insertLayerAfter(layer3d, null);
}
});
_defineProperty(_this2, "setBaseLayer", function (layer, visibility) {
var _this2$state$sceneCon;
var currentBaseLayer = ((_this2$state$sceneCon = _this2.state.sceneContext.baseLayers.find(function (l) {
return l.visibility === true;
})) === null || _this2$state$sceneCon === void 0 ? void 0 : _this2$state$sceneCon.name) || "";
if (visibility && (layer === null || layer === void 0 ? void 0 : layer.name) === currentBaseLayer) {
// Nothing changed
return;
}
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
baseLayers: state.sceneContext.baseLayers.map(function (entry) {
return _objectSpread(_objectSpread({}, entry), {}, {
visibility: entry.name === layer.name ? visibility : false
});
})
})
};
});
});
_defineProperty(_this2, "collectColorLayers", function (prevColorLayers, prevLayers) {
var prevLayerMap = prevLayers.reduce(function (res, layer) {
return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, layer.id, layer));
}, {});
return _this2.props.layers.reduce(function (colorLayers, layer) {
var _prevOptions$visibili, _prevOptions$opacity, _prevOptions$extrusio, _prevOptions$fields;
if (layer.role !== LayerRole.THEME && layer.role !== LayerRole.USERLAYER) {
return colorLayers;
}
var prevOptions = prevColorLayers[layer.id];
if (prevOptions && layer === prevLayerMap[layer.id]) {
colorLayers[layer.id] = prevOptions;
return colorLayers;
}
var layerCreator = LayerRegistry[layer.type];
if (!layerCreator || !layerCreator.create3d) {
return colorLayers;
}
var _preserveSublayerOptions = function preserveSublayerOptions(entry, prevEntry) {
var _entry$sublayers, _entry$sublayers$map;
return (_entry$sublayers = entry.sublayers) === null || _entry$sublayers === void 0 || (_entry$sublayers$map = _entry$sublayers.map) === null || _entry$sublayers$map === void 0 ? void 0 : _entry$sublayers$map.call(_entry$sublayers, function (child) {
var _prevEntry$sublayers, _prevEntry$sublayers$;
var prevChild = prevEntry === null || prevEntry === void 0 || (_prevEntry$sublayers = prevEntry.sublayers) === null || _prevEntry$sublayers === void 0 || (_prevEntry$sublayers$ = _prevEntry$sublayers.find) === null || _prevEntry$sublayers$ === void 0 ? void 0 : _prevEntry$sublayers$.call(_prevEntry$sublayers, function (x) {
return x.name === child.name;
});
if ((prevChild === null || prevChild === void 0 ? void 0 : prevChild.name) === child.name) {
return _objectSpread(_objectSpread({}, child), {}, {
visibility: prevChild.visibility,
opacity: prevChild.opacity,
sublayers: _preserveSublayerOptions(child, prevChild)
});
} else {
return child;
}
});
};
colorLayers[layer.id] = _objectSpread(_objectSpread({}, layer), {}, {
visibility: (_prevOptions$visibili = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.visibility) !== null && _prevOptions$visibili !== void 0 ? _prevOptions$visibili : false,
opacity: (_prevOptions$opacity = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity) !== null && _prevOptions$opacity !== void 0 ? _prevOptions$opacity : 255,
extrusionHeight: (_prevOptions$extrusio = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== null && _prevOptions$extrusio !== void 0 ? _prevOptions$extrusio : layerCreator.createFeatureSource ? 0 : undefined,
fields: (_prevOptions$fields = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.fields) !== null && _prevOptions$fields !== void 0 ? _prevOptions$fields : undefined,
sublayers: _preserveSublayerOptions(layer, prevOptions)
});
Object.assign(colorLayers[layer.id], LayerUtils.buildWMSLayerParams(colorLayers[layer.id]));
if (colorLayers[layer.id].fields === undefined && layerCreator.getFields) {
layerCreator.getFields(layer).then(function (fields) {
_this2.updateColorLayer(layer.id, {
fields: fields
});
});
}
return colorLayers;
}, {});
});
_defineProperty(_this2, "applyColorLayerUpdates", function (colorLayers, prevColorLayers) {
// Add-update new layers
var layerBelow = _this2.getLayer("__baselayer");
Object.entries(colorLayers).reverse().forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
layerId = _ref2[0],
options = _ref2[1];
var prevOptions = prevColorLayers[layerId];
if (options === prevOptions) {
return;
}
var layerCreator = LayerRegistry[options.type];
var mapLayer = _this2.getLayer(layerId);
if (mapLayer) {
layerCreator.update3d(mapLayer.source, options, prevOptions, _this2.state.sceneContext.mapCrs);
} else {
mapLayer = layerCreator.create3d(options, _this2.state.sceneContext.mapCrs);
_this2.addLayer(layerId, mapLayer);
}
_this2.map.insertLayerAfter(mapLayer, layerBelow);
mapLayer.visible = options.visibility;
mapLayer.opacity = options.opacity / 255;
layerBelow = mapLayer;
if (options.extrusionHeight !== undefined && options.extrusionHeight !== 0) {
_this2.createUpdateExtrudedLayer(layerCreator, mapLayer, options, options.features !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.features));
} else if ((prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== undefined && (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== 0) {
_this2.removeExtrudedLayer(options.id);
}
});
// Remove old layers
Object.entries(prevColorLayers).forEach(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
layerId = _ref4[0],
options = _ref4[1];
if (!(layerId in colorLayers)) {
if (options.extrusionHeight !== undefined && options.extrusionHeight !== 0) {
_this2.removeExtrudedLayer(options.id);
}
_this2.removeLayer(layerId);
}
});
_this2.instance.notifyChange(_this2.map);
});
_defineProperty(_this2, "createUpdateExtrudedLayer", function (layerCreator, mapLayer, options) {
var _options$features, _options$features$red;
var forceCreate = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var objId = options.id + ":extruded";
var makeColor = function makeColor(c) {
if (Array.isArray(c)) {
return c[0] << 16 | c[1] << 8 | c[2];
} else if (typeof c === "string") {
return parseInt(c.replace("#", ""), 16);
} else {
return c;
}
};
var obj = _this2.objectMap[objId];
if (!obj || forceCreate) {
var _options$color;
if (obj) {
_this2.instance.remove(obj);
}
var layercolor = makeColor((_options$color = options.color) !== null && _options$color !== void 0 ? _options$color : "#FF0000");
obj = new DrapedFeatureCollection({
source: layerCreator.createFeatureSource(mapLayer, options, _this2.state.sceneContext.mapCrs),
drapingMode: 'per-feature',
extrusionOffset: function extrusionOffset(feature) {
if (typeof obj.userData.extrusionHeight === "string") {
return parseFloat(feature.getProperties()[obj.userData.extrusionHeight]) || 0;
} else {
return obj.userData.extrusionHeight;
}
},
style: function style(feature) {
var _obj$userData$feature, _obj$userData$feature2;
return (_obj$userData$feature = (_obj$userData$feature2 = obj.userData.featureStyles) === null || _obj$userData$feature2 === void 0 ? void 0 : _obj$userData$feature2[feature.getId()]) !== null && _obj$userData$feature !== void 0 ? _obj$userData$feature : {
fill: {
color: layercolor,
shading: true
}
};
}
});
obj.castShadow = true;
obj.receiveShadow = true;
_this2.instance.add(obj).then(function () {
obj.attach(_this2.map);
});
_this2.objectMap[objId] = obj;
}
obj.userData.extrusionHeight = options.extrusionHeight;
obj.userData.featureStyles = (_options$features = options.features) === null || _options$features === void 0 || (_options$features$red = _options$features.reduce) === null || _options$features$red === void 0 ? void 0 : _options$features$red.call(_options$features, function (res, feature) {
return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, feature.id, {
fill: {
color: makeColor(feature.styleOptions.fillColor),
shading: true
}
}));
}, {});
obj.opacity = mapLayer.opacity;
obj.visible = mapLayer.visible;
if (obj.visible) {
obj.updateStyles();
}
});
_defineProperty(_this2, "removeExtrudedLayer", function (layerId) {
var objId = layerId + ":extruded";
if (_this2.objectMap[objId]) {
_this2.instance.remove(_this2.objectMap[objId]);
delete _this2.objectMap[objId];
}
_this2.instance.notifyChange();
});
_defineProperty(_this2, "applySceneObjectUpdates", function (sceneObjects, prevSceneObjects) {
Object.entries(sceneObjects).forEach(function (_ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
objectId = _ref6[0],
options = _ref6[1];
var prevOptions = prevSceneObjects === null || prevSceneObjects === void 0 ? void 0 : prevSceneObjects[objectId];
var object = _this2.objectMap[objectId];
if (options.opacity !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity) || options.visibility !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.visibility)) {
object.visible = options.visibility && options.opacity > 0;
if (object.opacity !== undefined) {
object.opacity = options.opacity / 255;
} else {
object.traverse(function (child) {
if (child instanceof Mesh) {
child.material.transparent = options.opacity < 255;
child.material.opacity = options.opacity / 255;
child.material.needsUpdate = true;
}
});
}
_this2.instance.notifyChange(object);
}
if (options.style !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.style)) {
_this2.loadTilesetStyle(objectId, options);
}
if (options.tilesetStyle !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.tilesetStyle)) {
object.tiles.group.children.forEach(function (group) {
Tiles3DStyle.applyTileStyle(group, options, _this2.state.sceneContext);
});
_this2.instance.notifyChange(object);
}
});
});
_defineProperty(_this2, "addLayer", function (layerId, layer) {
layer.userData.layerId = layerId;
_this2.map.addLayer(layer);
});
_defineProperty(_this2, "getLayer", function (layerId) {
var _this2$map$getLayers$;
return (_this2$map$getLayers$ = _this2.map.getLayers(function (l) {
return l.userData.layerId === layerId;
})[0]) !== null && _this2$map$getLayers$ !== void 0 ? _this2$map$getLayers$ : null;
});
_defineProperty(_this2, "removeLayer", function (layerId) {
_this2.map.getLayers(function (l) {
return l.userData.layerId === layerId;
}).forEach(function (layer) {
_this2.map.removeLayer(layer, {
dispose: true
});
});
});
_defineProperty(_this2, "updateColorLayer", function (layerId, options) {
var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
_this2.setState(function (state) {
var entry = _objectSpread({}, state.sceneContext.colorLayers[layerId]);
var subentry = entry;
path.forEach(function (idx) {
subentry.sublayers = _toConsumableArray(subentry.sublayers);
subentry.sublayers[idx] = _objectSpread({}, subentry.sublayers[idx]);
subentry = subentry.sublayers[idx];
});
Object.assign(subentry, options);
Object.assign(entry, LayerUtils.buildWMSLayerParams(entry));
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
colorLayers: _objectSpread(_objectSpread({}, state.sceneContext.colorLayers), {}, _defineProperty({}, layerId, entry))
})
};
});
});
_defineProperty(_this2, "add3dTiles", function (url, name) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var showEditTool = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
var matrix = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
var label = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
var tiles = new Tiles3D({
url: MiscUtils.resolveAssetsPath(url)
});
// Recenter tile group
tiles.tiles.addEventListener('load-tile-set', function (_ref7) {
var tileSet = _ref7.tileSet;
if (tileSet.root.parent === null) {
var bbox = new Box3();
tiles.tiles.getBoundingBox(bbox);
var center = bbox.getCenter(new Vector3());
tiles.tiles.group.position.sub(center);
if (matrix) {
tiles.tiles.group.parent.applyMatrix4(matrix);
} else {
tiles.tiles.group.parent.position.copy(center);
}
tiles.tiles.group.parent.updateMatrixWorld(true);
if (label) {
tiles.tiles.group.parent.userData.label = label;
updateObjectLabel(tiles.tiles.group.parent, _this2.state.sceneContext);
}
}
_this2.instance.notifyChange(tiles);
if (showEditTool) {
_this2.props.setCurrentTask("EditDataset3D", null, null, {
objectId: name
});
}
});
tiles.tiles.addEventListener('needs-update', function () {
_this2.instance.notifyChange(tiles);
});
// Apply style when loading tile
tiles.tiles.addEventListener('load-model', function (_ref8) {
var scene = _ref8.scene;
scene.userData.tilesetName = name;
scene.userData.featureIdAttr = "id";
Tiles3DStyle.applyTileStyle(scene, _this2.state.sceneContext.sceneObjects[name], _this2.state.sceneContext);
_this2.instance.notifyChange(tiles);
});
// Show/hide labels when tile visibility changes
tiles.tiles.addEventListener('tile-visibility-change', function (_ref9) {
var _scene$userData$tileL, _scene$userData;
var scene = _ref9.scene,
visible = _ref9.visible;
Object.values((_scene$userData$tileL = scene === null || scene === void 0 || (_scene$userData = scene.userData) === null || _scene$userData === void 0 ? void 0 : _scene$userData.tileLabels) !== null && _scene$userData$tileL !== void 0 ? _scene$userData$tileL : {}).forEach(function (l) {
l.labelObject.visible = visible;
l.labelObject.element.style.display = visible ? 'initial' : 'none';
});
});
tiles.castShadow = true;
tiles.receiveShadow = true;
tiles.userData.layertree = true;
_this2.instance.add(tiles);
_this2.objectMap[name] = tiles;
_this2.setState(function (state) {
var objectState = _objectSpread({
imported: true,
visibility: true,
opacity: 255,
layertree: true,
title: name
}, options);
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
sceneObjects: _objectSpread(_objectSpread({}, state.sceneContext.sceneObjects), {}, _defineProperty({}, name, objectState))
})
};
});
});
_defineProperty(_this2, "addSceneObject", function (objectId, object) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var showEditTool = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
_this2.sceneObjectGroup.add(object);
_this2.objectMap[objectId] = object;
_this2.instance.notifyChange(object);
_this2.setState(function (state) {
var objectState = _objectSpread({
visibility: true,
opacity: 255,
layertree: false
}, options);
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
sceneObjects: _objectSpread(_objectSpread({}, state.sceneContext.sceneObjects), {}, _defineProperty({}, objectId, objectState))
})
};
});
if (showEditTool) {
_this2.props.setCurrentTask("EditDataset3D", null, null, {
objectId: objectId
});
}
});
_defineProperty(_this2, "getSceneObject", function (objectId) {
return _this2.objectMap[objectId];
});
_defineProperty(_this2, "removeSceneObject", function (objectId) {
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
var object = _this2.objectMap[objectId];
if (!object) {
return;
}
// Ensure labels are removed
object.traverse(function (c) {
if (c.isCSS2DObject) {
c.element.parentNode.removeChild(c.element);
}
});
if (object.tiles) {
_this2.instance.remove(object);
} else {
_this2.sceneObjectGroup.remove(object);
}
delete _this2.objectMap[objectId];
_this2.instance.notifyChange();
_this2.setState(function (state) {
var newSceneObjects = _objectSpread({}, state.sceneContext.sceneObjects);
delete newSceneObjects[objectId];
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
sceneObjects: newSceneObjects
})
};
}, callback);
});
_defineProperty(_this2, "updateSceneObject", function (objectId, options) {
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
sceneObjects: _objectSpread(_objectSpread({}, state.sceneContext.sceneObjects), {}, _defineProperty({}, objectId, _objectSpread(_objectSpread({}, state.sceneContext.sceneObjects[objectId]), options)))
})
};
});
});
_defineProperty(_this2, "zoomToObject", function (objectId) {
var margin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 20;
var obj = _this2.state.sceneContext.getSceneObject(objectId);
var bbox = new Box3();
if (obj !== null && obj !== void 0 && obj.tiles) {
obj.tiles.getBoundingBox(bbox);
} else {
bbox.setFromObject(obj);
}
if (!bbox.isEmpty()) {
var bounds = [bbox.min.x - margin, bbox.min.y - margin, bbox.max.x + margin, bbox.max.y + margin];
_this2.state.sceneContext.setViewToExtent(bounds, 0);
}
});
_defineProperty(_this2, "getMap", function () {
return _this2.map;
});
_defineProperty(_this2, "setupContainer", function (el) {
if (el) {
_this2.container = el;
el.resizeObserver = new ResizeObserver(function (entries) {
var rect = entries[0].contentRect;
_this2.state.sceneContext.scene.view.dispatchEvent({
type: 'view-resized',
width: rect.width,
height: rect.height
});
});
el.resizeObserver.observe(el);
_this2.setupInstance();
}
});
_defineProperty(_this2, "setupInstance", function () {
var _this2$props$theme$ma, _this2$props$theme$ma2, _this2$props$theme$ma3, _this2$props$theme$ma4, _this2$props$theme$ma5, _this2$props$theme$ma8, _this2$props$theme$ma9, _this2$props$theme$ma10;
if (_this2.instance) {
_this2.disposeInstance();
}
if (!_this2.props.theme) {
return;
}
var projection = _this2.props.theme.mapCrs;
var crs = CoordinateSystem.fromSrid(projection);
// Setup instance
_this2.instance = new Instance({
target: _this2.container,
crs: crs,
renderer: {
clearColor: 0x000000,
preserveDrawingBuffer: true
}
});
_this2.sceneObjectGroup = new Group();
_this2.sceneObjectGroup.name = "sceneObjects";
_this2.instance.add(_this2.sceneObjectGroup);
// Setup map
var initialBbox = (_this2$props$theme$ma = (_this2$props$theme$ma2 = _this2.props.theme.map3d) === null || _this2$props$theme$ma2 === void 0 ? void 0 : _this2$props$theme$ma2.extent) !== null && _this2$props$theme$ma !== void 0 ? _this2$props$theme$ma : _this2.props.theme.initialBbox;
var bounds = CoordinatesUtils.reprojectBbox(initialBbox.bounds, initialBbox.crs, projection);
var extent = new Extent(crs, bounds[0], bounds[2], bounds[1], bounds[3]);
_this2.map = new Map({
extent: extent,
backgroundColor: "white"
});
_this2.instance.add(_this2.map);
// Setup camera
var center = extent.center();
if (crsIsGeographic(center.crs)) {
var position = Ellipsoid.WGS84.toCartesian(center.latitude, center.longitude, center.altitude);
_this2.instance.view.camera.position.set(position.x, position.y, 0.5 * (extent.east - extent.west));
} else {
_this2.instance.view.camera.position.set(center.x, center.y, 0.5 * (extent.east - extent.west));
}
// Skybox
var cubeTextureLoader = new CubeTextureLoader();
cubeTextureLoader.setPath(ConfigUtils.getAssetsPath() + "/3d/skybox/");
var cubeTexture = cubeTextureLoader.load(["px.jpg", "nx.jpg", "py.jpg", "ny.jpg", "pz.jpg", "nz.jpg"]);
_this2.instance.scene.background = cubeTexture;
// Setup elevation
var demUrl = MiscUtils.resolveAssetsPath((_this2$props$theme$ma3 = (_this2$props$theme$ma4 = _this2.props.theme.map3d) === null || _this2$props$theme$ma4 === void 0 || (_this2$props$theme$ma4 = _this2$props$theme$ma4.dtm) === null || _this2$props$theme$ma4 === void 0 ? void 0 : _this2$props$theme$ma4.url) !== null && _this2$props$theme$ma3 !== void 0 ? _this2$props$theme$ma3 : "");
var demCrs = CoordinateSystem.fromSrid(((_this2$props$theme$ma5 = _this2.props.theme.map3d) === null || _this2$props$theme$ma5 === void 0 || (_this2$props$theme$ma5 = _this2$props$theme$ma5.dtm) === null || _this2$props$theme$ma5 === void 0 ? void 0 : _this2$props$theme$ma5.crs) || "EPSG:3857");
if (demUrl) {
var _this2$props$theme$ma6, _this2$props$theme$ma7;
var demSource = new GeoTIFFSource({
url: demUrl,
crs: demCrs
});
var demMin = (_this2$props$theme$ma6 = _this2.props.theme.map3d.dtm.min) !== null && _this2$props$theme$ma6 !== void 0 ? _this2$props$theme$ma6 : undefined;
var demMax = (_this2$props$theme$ma7 = _this2.props.theme.map3d.dtm.max) !== null && _this2$props$theme$ma7 !== void 0 ? _this2$props$theme$ma7 : undefined;
var elevationLayer = new ElevationLayer({
name: 'dem',
extent: extent,
source: demSource,
minmax: demMin !== undefined && demMax !== undefined ? {
demMin: demMin,
demMax: demMax
} : undefined
});
_this2.addLayer("__dtm", elevationLayer);
}
// Collect baselayers
var externalLayers = {};
var baseLayers = ThemeUtils.createThemeBackgroundLayers(((_this2$props$theme$ma8 = _this2.props.theme.map3d) === null || _this2$props$theme$ma8 === void 0 ? void 0 : _this2$props$theme$ma8.basemaps) || [], _this2.props.themes, null, externalLayers);
for (var _i = 0, _Object$keys = Object.keys(externalLayers); _i < _Object$keys.length; _i++) {
var key = _Object$keys[_i];
var idx = key.indexOf(":");
var service = key.slice(0, idx);
var serviceUrl = key.slice(idx + 1);
ServiceLayerUtils.findLayers(service, serviceUrl, externalLayers[key], projection, function (id, layer) {
// Don't expose sublayers
if (layer) {
layer.sublayers = null;
}
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
baseLayers: LayerUtils.replacePlaceholderLayer(state.sceneContext.baseLayers, id, layer)
})
};
});
});
}
// Collect color layers
var colorLayers = _this2.collectColorLayers([], []);
var sceneObjects = {};
_this2.objectMap = {};
// Add 3d tiles
(((_this2$props$theme$ma9 = _this2.props.theme.map3d) === null || _this2$props$theme$ma9 === void 0 ? void 0 : _this2$props$theme$ma9.tiles3d) || []).forEach(function (entry) {
var _entry$visibility, _entry$title;
var tiles = new Tiles3D({
url: MiscUtils.resolveAssetsPath(entry.url),
errorTarget: 32
});
tiles.tiles.addEventListener('load-tile-set', function () {
_this2.instance.notifyChange(tiles);
});
tiles.tiles.addEventListener('needs-update', function () {
_this2.instance.notifyChange(tiles);
});
// Apply style when loading tile
tiles.tiles.addEventListener('load-model', function (_ref10) {
var _entry$idAttr;
var scene = _ref10.scene;
scene.userData.tilesetName = entry.name;
scene.userData.featureIdAttr = (_entry$idAttr = entry.idAttr) !== null && _entry$idAttr !== void 0 ? _entry$idAttr : "id";
Tiles3DStyle.applyTileStyle(scene, _this2.state.sceneContext.sceneObjects[entry.name], _this2.state.sceneContext);
_this2.instance.notifyChange(tiles);
});
// Show/hide labels when tile visibility changes
tiles.tiles.addEventListener('tile-visibility-change', function (_ref11) {
var _scene$userData$tileL2, _scene$userData2;
var scene = _ref11.scene,
visible = _ref11.visible;
Object.values((_scene$userData$tileL2 = scene === null || scene === void 0 || (_scene$userData2 = scene.userData) === null || _scene$userData2 === void 0 ? void 0 : _scene$userData2.tileLabels) !== null && _scene$userData$tileL2 !== void 0 ? _scene$userData$tileL2 : {}).forEach(function (label) {
label.labelObject.visible = visible;
label.labelObject.element.style.display = visible ? 'initial' : 'none';
});
});
tiles.castShadow = true;
tiles.receiveShadow = true;
tiles.userData.layertree = true;
_this2.instance.add(tiles);
_this2.objectMap[entry.name] = tiles;
sceneObjects[entry.name] = {
visibility: (_entry$visibility = entry.visibility) !== null && _entry$visibility !== void 0 ? _entry$visibility : true,
opacity: 255,
layertree: true,
title: (_entry$title = entry.title) !== null && _entry$title !== void 0 ? _entry$title : entry.name,
baseColor: entry.baseColor,
styles: entry.styles,
style: entry.style || Object.keys(entry.styles || {})[0] || null,
tilesetStyle: null,
idAttr: entry.idAttr,
colorAttr: entry.colorAttr,
alphaAttr: entry.alphaAttr,
labelAttr: entry.labelAttr
};
});
// Add other objects
(((_this2$props$theme$ma10 = _this2.props.theme.map3d) === null || _this2$props$theme$ma10 === void 0 ? void 0 : _this2$props$theme$ma10.objects3d) || []).forEach(function (entry) {
var _entry$title2, _entry$visibility2;
importGltf(MiscUtils.resolveAssetsPath(entry.url), (_entry$title2 = entry.title) !== null && _entry$title2 !== void 0 ? _entry$title2 : entry.name, _this2.state.sceneContext, {
visibility: (_entry$visibility2 = entry.visibility) !== null && _entry$visibility2 !== void 0 ? _entry$visibility2 : true
});
});
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
scene: _this2.instance,
map: _this2.map,
mapCrs: projection,
dtmUrl: demUrl,
dtmCrs: demCrs,
baseLayers: baseLayers,
colorLayers: colorLayers,
sceneObjects: sceneObjects
}),
sceneId: uuidv4()
};
});
// Inspector
if (["1", "true"].includes((UrlParams.getParam("inspector") || "").toLowerCase())) {
var inspectorContainer = document.createElement("div");
inspectorContainer.className = 'map3d-inspector';
_this2.container.appendChild(inspectorContainer);
_this2.inspector = new Inspector(inspectorContainer, _this2.instance);
}
_this2.instance.addEventListener('update-start', _this2.instanceOnUpdateStart);
_this2.instance.addEventListener('update-end', _this2.instanceOnUpdateEnd);
_this2.instance.addEventListener('before-entity-update', _this2.instanceOnBeforeEntityUpdate);
_this2.instance.addEventListener('after-entity-update', _this2.instanceOnAfterEntityUpdate);
});
_defineProperty(_this2, "instanceOnUpdateStart", function () {
var camera = _this2.instance.view.camera;
var quality = _this2.state.sceneContext.settings.sceneQuality;
var isFirstPerson = _this2.state.sceneContext.scene.view.controls.isFirstPerson;
var maxDistance = isFirstPerson ? 200 + 20 * quality : 500 + quality * quality;
// Hide scene objects according to scene quality
Object.entries(_this2.state.sceneContext.sceneObjects).forEach(function (_ref12) {
var _ref13 = _slicedToArray(_ref12, 2),
objId = _ref13[0],
options = _ref13[1];
var object = _this2.objectMap[objId];
if (options.layertree && object.isObject3D && object.visible) {
object.children.forEach(function (child) {
if (child.geometry) {
if (!child.geometry.boundingBox) {
child.geometry.computeBoundingBox();
}
var localCenter = child.geometry.boundingBox.getCenter(new Vector3());
var worldCenter = localCenter.applyMatrix4(child.matrixWorld);
var distance = camera.position.distanceTo(worldCenter);
child.userData.__wasVisible = child.visible;
if (distance > maxDistance) {
child.visible = false;
}
}
});
}
});
});
_defineProperty(_this2, "instanceOnUpdateEnd", function () {
Object.entries(_this2.state.sceneContext.sceneObjects).forEach(function (_ref14) {
var _ref15 = _slicedToArray(_ref14, 2),
objId = _ref15[0],
options = _ref15[1];
var object = _this2.objectMap[objId];
if (options.layertree && object.isObject3D) {
object.children.forEach(function (child) {
child.visible = child.userData.__wasVisible;
delete child.userData.__wasVisible;
});
}
});
});
_defineProperty(_this2, "instanceOnBeforeEntityUpdate", function (_ref16) {
var entity = _ref16.entity;
if (entity !== _this2.map) {
_this2.instance.view.camera.userData.__previousFar = _this2.instance.view.camera.far;
var quality = _this2.state.sceneContext.settings.sceneQuality;
var isFirstPerson = _this2.state.sceneContext.scene.view.controls.isFirstPerson;
_this2.instance.view.camera.far = isFirstPerson ? 200 + 20 * quality : 500 + quality * quality;
_this2.instance.view.camera.updateProjectionMatrix();
}
});
_defineProperty(_this2, "instanceOnAfterEntityUpdate", function (_ref17) {
var entity = _ref17.entity;
if (entity !== _this2.map) {
_this2.instance.view.camera.far = _this2.instance.view.camera.userData.__previousFar;
delete _this2.instance.view.camera.userData.__previousFar;
_this2.instance.view.camera.updateProjectionMatrix();
}
});
_defineProperty(_this2, "loadTilesetStyle", function (objectId, options) {
var _options$styles;
var url = (_options$styles = options.styles) === null || _options$styles === void 0 ? void 0 : _options$styles[options.style];
if (_this2.tilesetStyles[url]) {
_this2.updateSceneObject(objectId, {
tilesetStyle: _this2.tilesetStyles[url]
});
} else if (url) {
var fullUrl = MiscUtils.resolveAssetsPath(url);
axios.get(fullUrl).then(function (response) {
_this2.tilesetStyles[url] = response.data;
_this2.updateSceneObject(objectId, {
tilesetStyle: _this2.tilesetStyles[url]
});
})["catch"](function () {
_this2.tilesetStyles[url] = {};
_this2.updateSceneObject(objectId, {
tilesetStyle: _this2.tilesetStyles[url]
});
});
} else {
_this2.tilesetStyles[url] = null;
_this2.updateSceneObject(objectId, {
tilesetStyle: _this2.tilesetStyles[url]
});
}
});
_defineProperty(_this2, "disposeInstance", function () {
_this2.instance.removeEventListener('update-start', _this2.instanceOnUpdateStart);
_this2.instance.removeEventListener('update-end', _this2.instanceOnUpdateEnd);
_this2.instance.removeEventListener('before-entity-update', _this2.instanceOnBeforeEntityUpdate);
_this2.instance.removeEventListener('after-entity-update', _this2.instanceOnAfterEntityUpdate);
if (_this2.inspector) {
_this2.inspector.detach();
}
_this2.map.dispose({
disposeLayers: true
});
Object.values(_this2.objectMap).forEach(function (object) {
_this2.instance.remove(object);
});
_this2.instance.dispose();
_this2.inspector = null;
_this2.map = null;
_this2.objectMap = {};
_this2.sceneObjectGroup = null;
_this2.instance = null;
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), Map3D.defaultSceneState)
};
});
_this2.props.setCurrentTask(null);
});
_defineProperty(_this2, "onUnload", function (key) {
// Ensure scene has not already been disposed
if (_this2.state.sceneId === key) {
_this2.disposeInstance();
}
});
_defineProperty(_this2, "setupControls", function (instance) {
_this2.setState(function (state) {
return {
sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
setViewToExtent: instance === null || instance === void 0 ? void 0 : instance.setViewToExtent,
restoreView: instance === null || instance === void 0 ? void 0 : instance.restoreView
})
};
}, _this2.props.onMapInitialized);
});
_defineProperty(_this2, "getTerrainHeightFromDTM", function (scenePos) {
var returnArray = true;
if (!Array.isArray(scenePos[0])) {
returnArray = false;
scenePos = [scenePos];
}
var dtmPos = scenePos.map(function (p) {
return CoordinatesUtils.reproject(p, _this2.state.sceneContext.mapCrs, _this2.state.sceneContext.dtmCrs.name);
});
var dtmExt = [Infinity, Infinity, -Infinity, -Infinity];
dtmPos.forEach(function (p) {
dtmExt[0] = Math.min(dtmExt[0], p[0]);
dtmExt[1] = Math.min(dtmExt[1], p[1]);
dtmExt[2] = Math.max(dtmExt[2], p[0]);
dtmExt[3] = Math.max(dtmExt[3], p[1]);
});
return new Promise(function (resolve) {
if (!_this2.state.sceneContext.dtmUrl) {
resolve(returnArray ? scenePos.map(function (x) {
return 0;
}) : 0);
return;
}
fromUrl(_this2.state.sceneContext.dtmUrl).then(function (tiff) {
tiff.getImage().then(function (image) {
var _image$fileDirectory = image.fileDirectory,
ModelTiepoint = _image$fileDirectory.ModelTiepoint,
ModelPixelScale = _image$fileDirectory.ModelPixelScale;
// Extract scale and tiepoint values
var _ref18 = [ModelPixelScale[0], ModelPixelScale[1]],
scaleX = _ref18[0],
scaleY = _ref18[1];
var _ref19 = [ModelTiepoint[3], ModelTiepoint[4]],
tiepointX = _ref19[0],
tiepointY = _ref19[1]; // Tiepoint world coordinates
// Calculate pixel indices (rounded to nearest integers)
var minPixelX = Math.round((dtmExt[0] - tiepointX) / scaleX);
var minPixelY = Math.round((tiepointY - dtmExt[3]) / scaleY); // Inverted Y-axis in image