UNPKG

qwc2

Version:
947 lines (932 loc) 65.4 kB
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