var olcs_unused_var; /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./src/olcs/AbstractSynchronizer.js": /*!******************************************!*\ !*** ./src/olcs/AbstractSynchronizer.js ***! \******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Group.js */ "ol/layer/Group.js"); /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /** * @module olcs.AbstractSynchronizer */ class AbstractSynchronizer { /** * @param {!ol.Map} map * @param {!Cesium.Scene} scene * @template T * @abstract * @api */ constructor(map, scene) { /** * @type {!ol.Map} * @protected */ this.map = map; /** * @type {ol.View} * @protected */ this.view = map.getView(); /** * @type {!Cesium.Scene} * @protected */ this.scene = scene; /** * @type {ol.Collection.} * @protected */ this.olLayers = map.getLayerGroup().getLayers(); /** * @type {ol.layer.Group} */ this.mapLayerGroup = map.getLayerGroup(); /** * Map of OpenLayers layer ids (from getUid) to the Cesium ImageryLayers. * Null value means, that we are unable to create equivalent layers. * @type {Object.>} * @protected */ this.layerMap = {}; /** * Map of listen keys for OpenLayers layer layers ids (from getUid). * @type {!Object.>} * @protected */ this.olLayerListenKeys = {}; /** * Map of listen keys for OpenLayers layer groups ids (from getUid). * @type {!Object.>} * @private */ this.olGroupListenKeys_ = {}; } /** * Destroy all and perform complete synchronization of the layers. * @api */ synchronize() { this.destroyAll(); this.addLayers_(this.mapLayerGroup); } /** * Order counterparts using the same algorithm as the Openlayers renderer: * z-index then original sequence order. * @protected */ orderLayers() { // Ordering logics is handled in subclasses. } /** * Add a layer hierarchy. * @param {ol.layer.Base} root * @private */ addLayers_(root) { /** @type {Array} */ const fifo = [{ layer: root, parents: [] }]; while (fifo.length > 0) { const olLayerWithParents = fifo.splice(0, 1)[0]; const olLayer = olLayerWithParents.layer; const olLayerId = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(olLayer).toString(); this.olLayerListenKeys[olLayerId] = []; console.assert(!this.layerMap[olLayerId]); let cesiumObjects = null; if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default())) { this.listenForGroupChanges_(olLayer); if (olLayer !== this.mapLayerGroup) { cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents); } if (!cesiumObjects) { olLayer.getLayers().forEach((l) => { if (l) { const newOlLayerWithParents = { layer: l, parents: olLayer === this.mapLayerGroup ? [] : [olLayerWithParents.layer].concat(olLayerWithParents.parents) }; fifo.push(newOlLayerWithParents); } }); } } else { cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents); if (!cesiumObjects) { // keep an eye on the layers that once failed to be added (might work when the layer is updated) // for example when a source is set after the layer is added to the map const layerId = olLayerId; const layerWithParents = olLayerWithParents; const onLayerChange = (e) => { const cesiumObjs = this.createSingleLayerCounterparts(layerWithParents); if (cesiumObjs) { // unsubscribe event listener layerWithParents.layer.un('change', onLayerChange); this.addCesiumObjects_(cesiumObjs, layerId, layerWithParents.layer); this.orderLayers(); } }; this.olLayerListenKeys[olLayerId].push((0,_util_js__WEBPACK_IMPORTED_MODULE_2__.olcsListen)(layerWithParents.layer, 'change', onLayerChange)); } } // add Cesium layers if (cesiumObjects) { this.addCesiumObjects_(cesiumObjects, olLayerId, olLayer); } } this.orderLayers(); } /** * Add Cesium objects. * @param {Array.} cesiumObjects * @param {string} layerId * @param {ol.layer.Base} layer * @private */ addCesiumObjects_(cesiumObjects, layerId, layer) { this.layerMap[layerId] = cesiumObjects; this.olLayerListenKeys[layerId].push((0,_util_js__WEBPACK_IMPORTED_MODULE_2__.olcsListen)(layer, 'change:zIndex', () => this.orderLayers())); cesiumObjects.forEach((cesiumObject) => { this.addCesiumObject(cesiumObject); }); } /** * Remove and destroy a single layer. * @param {ol.layer.Layer} layer * @return {boolean} counterpart destroyed * @private */ removeAndDestroySingleLayer_(layer) { const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(layer).toString(); const counterparts = this.layerMap[uid]; if (!!counterparts) { counterparts.forEach((counterpart) => { this.removeSingleCesiumObject(counterpart, false); this.destroyCesiumObject(counterpart); }); this.olLayerListenKeys[uid].forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey); delete this.olLayerListenKeys[uid]; } delete this.layerMap[uid]; return !!counterparts; } /** * Unlisten a single layer group. * @param {ol.layer.Group} group * @private */ unlistenSingleGroup_(group) { if (group === this.mapLayerGroup) { return; } const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(group).toString(); const keys = this.olGroupListenKeys_[uid]; keys.forEach((key) => { (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(key); }); delete this.olGroupListenKeys_[uid]; delete this.layerMap[uid]; } /** * Remove layer hierarchy. * @param {ol.layer.Base} root * @private */ removeLayer_(root) { if (!!root) { const fifo = [root]; while (fifo.length > 0) { const olLayer = fifo.splice(0, 1)[0]; const done = this.removeAndDestroySingleLayer_(olLayer); if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default())) { this.unlistenSingleGroup_(olLayer); if (!done) { // No counterpart for the group itself so removing // each of the child layers. olLayer.getLayers().forEach((l) => { fifo.push(l); }); } } } } } /** * Register listeners for single layer group change. * @param {ol.layer.Group} group * @private */ listenForGroupChanges_(group) { const uuid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(group).toString(); console.assert(this.olGroupListenKeys_[uuid] === undefined); const listenKeyArray = []; this.olGroupListenKeys_[uuid] = listenKeyArray; // only the keys that need to be relistened when collection changes let contentKeys = []; const listenAddRemove = (function() { const collection = group.getLayers(); if (collection) { contentKeys = [ collection.on('add', (event) => { this.addLayers_(event.element); }), collection.on('remove', (event) => { this.removeLayer_(event.element); }) ]; listenKeyArray.push(...contentKeys); } }).bind(this); listenAddRemove(); listenKeyArray.push(group.on('change:layers', (e) => { contentKeys.forEach((el) => { const i = listenKeyArray.indexOf(el); if (i >= 0) { listenKeyArray.splice(i, 1); } (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(el); }); listenAddRemove(); })); } /** * Destroys all the created Cesium objects. * @protected */ destroyAll() { this.removeAllCesiumObjects(true); // destroy let objKey; for (objKey in this.olGroupListenKeys_) { const keys = this.olGroupListenKeys_[objKey]; keys.forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey); } for (objKey in this.olLayerListenKeys) { this.olLayerListenKeys[objKey].forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey); } this.olGroupListenKeys_ = {}; this.olLayerListenKeys = {}; this.layerMap = {}; } /** * Adds a single Cesium object to the collection. * @param {!T} object * @abstract * @protected */ addCesiumObject(object) {} /** * @param {!T} object * @abstract * @protected */ destroyCesiumObject(object) {} /** * Remove single Cesium object from the collection. * @param {!T} object * @param {boolean} destroy * @abstract * @protected */ removeSingleCesiumObject(object, destroy) {} /** * Remove all Cesium objects from the collection. * @param {boolean} destroy * @abstract * @protected */ removeAllCesiumObjects(destroy) {} /** * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents * @return {?Array.} * @abstract * @protected */ createSingleLayerCounterparts(olLayerWithParents) {} } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AbstractSynchronizer); /***/ }), /***/ "./src/olcs/AutoRenderLoop.js": /*!************************************!*\ !*** ./src/olcs/AutoRenderLoop.js ***! \************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /** * @module olcs.AutoRenderLoop */ class AutoRenderLoop { /** * @constructor * @param {olcs.OLCesium} ol3d */ constructor(ol3d) { this.ol3d = ol3d; this.scene_ = ol3d.getCesiumScene(); this.canvas_ = this.scene_.canvas; this._boundNotifyRepaintRequired = this.notifyRepaintRequired.bind(this); this.repaintEventNames_ = [ 'mousemove', 'mousedown', 'mouseup', 'touchstart', 'touchend', 'touchmove', 'pointerdown', 'pointerup', 'pointermove', 'wheel' ]; this.enable(); } /** * Enable. */ enable() { this.scene_.requestRenderMode = true; this.scene_.maximumRenderTimeChange = 1000; for (const repaintKey of this.repaintEventNames_) { this.canvas_.addEventListener(repaintKey, this._boundNotifyRepaintRequired, false); } window.addEventListener('resize', this._boundNotifyRepaintRequired, false); // Listen for changes on the layer group this.ol3d.getOlMap().getLayerGroup().on('change', this._boundNotifyRepaintRequired); } /** * Disable. */ disable() { for (const repaintKey of this.repaintEventNames_) { this.canvas_.removeEventListener(repaintKey, this._boundNotifyRepaintRequired, false); } window.removeEventListener('resize', this._boundNotifyRepaintRequired, false); this.ol3d.getOlMap().getLayerGroup().un('change', this._boundNotifyRepaintRequired); this.scene_.requestRenderMode = false; } /** * Restart render loop. * Force a restart of the render loop. * @api */ restartRenderLoop() { this.notifyRepaintRequired(); } notifyRepaintRequired() { this.scene_.requestRender(); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AutoRenderLoop); /***/ }), /***/ "./src/olcs/Camera.js": /*!****************************!*\ !*** ./src/olcs/Camera.js ***! \****************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math.js */ "./src/olcs/math.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js"); /** * @module olcs.Camera */ class Camera { /** * This object takes care of additional 3d-specific properties of the view and * ensures proper synchronization with the underlying raw Cesium.Camera object. * @param {!Cesium.Scene} scene * @param {!ol.Map} map * @api */ constructor(scene, map) { /** * @type {!Cesium.Scene} * @private */ this.scene_ = scene; /** * @type {!Cesium.Camera} * @private */ this.cam_ = scene.camera; /** * @type {!ol.Map} * @private */ this.map_ = map; /** * @type {?ol.View} * @private */ this.view_ = null; /** * @type {?ol.EventsKey} * @private */ this.viewListenKey_ = null; /** * @type {!ol.TransformFunction} * @private */ this.toLonLat_ = Camera.identityProjection; /** * @type {!ol.TransformFunction} * @private */ this.fromLonLat_ = Camera.identityProjection; /** * 0 -- topdown, PI/2 -- the horizon * @type {number} * @private */ this.tilt_ = 0; /** * @type {number} * @private */ this.distance_ = 0; /** * @type {?Cesium.Matrix4} * @private */ this.lastCameraViewMatrix_ = null; /** * This is used to discard change events on view caused by updateView method. * @type {boolean} * @private */ this.viewUpdateInProgress_ = false; this.map_.on('change:view', (e) => { this.setView_(this.map_.getView()); }); this.setView_(this.map_.getView()); } /** * @param {Array.} input Input coordinate array. * @param {Array.=} opt_output Output array of coordinate values. * @param {number=} opt_dimension Dimension. * @return {Array.} Input coordinate array (same array as input). */ static identityProjection(input, opt_output, opt_dimension) { const dim = opt_dimension || input.length; if (opt_output) { for (let i = 0; i < dim; ++i) { opt_output[i] = input[i]; } } return input; } /** * @param {?ol.View} view New view to use. * @private */ setView_(view) { if (this.view_) { (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(this.viewListenKey_); this.viewListenKey_ = null; } this.view_ = view; if (view) { const toLonLat = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_2__.getTransform)(view.getProjection(), 'EPSG:4326'); const fromLonLat = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_2__.getTransform)('EPSG:4326', view.getProjection()); console.assert(toLonLat && fromLonLat); this.toLonLat_ = toLonLat; this.fromLonLat_ = fromLonLat; this.viewListenKey_ = view.on('propertychange', e => this.handleViewEvent_(e)); this.readFromView(); } else { this.toLonLat_ = Camera.identityProjection; this.fromLonLat_ = Camera.identityProjection; } } /** * @param {?} e * @private */ handleViewEvent_(e) { if (!this.viewUpdateInProgress_) { this.readFromView(); } } /** * @param {number} heading In radians. * @api */ setHeading(heading) { if (!this.view_) { return; } this.view_.setRotation(heading); } /** * @return {number|undefined} Heading in radians. * @api */ getHeading() { if (!this.view_) { return undefined; } const rotation = this.view_.getRotation(); return rotation || 0; } /** * @param {number} tilt In radians. * @api */ setTilt(tilt) { this.tilt_ = tilt; this.updateCamera_(); } /** * @return {number} Tilt in radians. * @api */ getTilt() { return this.tilt_; } /** * @param {number} distance In meters. * @api */ setDistance(distance) { this.distance_ = distance; this.updateCamera_(); this.updateView(); } /** * @return {number} Distance in meters. * @api */ getDistance() { return this.distance_; } /** * Shortcut for ol.View.setCenter(). * @param {!ol.Coordinate} center Same projection as the ol.View. * @api */ setCenter(center) { if (!this.view_) { return; } this.view_.setCenter(center); } /** * Shortcut for ol.View.getCenter(). * @return {ol.Coordinate|undefined} Same projection as the ol.View. * @api */ getCenter() { if (!this.view_) { return undefined; } return this.view_.getCenter(); } /** * Sets the position of the camera. * @param {!ol.Coordinate} position Same projection as the ol.View. * @api */ setPosition(position) { if (!this.toLonLat_) { return; } const ll = this.toLonLat_(position); console.assert(ll); const carto = new Cesium.Cartographic( (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[0]), (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1]), this.getAltitude()); this.cam_.setView({ destination: Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto) }); this.updateView(); } /** * Calculates position under the camera. * @return {!ol.Coordinate|undefined} Same projection as the ol.View. * @api */ getPosition() { if (!this.fromLonLat_) { return undefined; } const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.cam_.position); const pos = this.fromLonLat_([ (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(carto.longitude), (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(carto.latitude) ]); console.assert(pos); return pos; } /** * @param {number} altitude In meters. * @api */ setAltitude(altitude) { const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic( this.cam_.position); carto.height = altitude; this.cam_.position = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); this.updateView(); } /** * @return {number} Altitude in meters. * @api */ getAltitude() { const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic( this.cam_.position); return carto.height; } /** * Updates the state of the underlying Cesium.Camera * according to the current values of the properties. * @private */ updateCamera_() { if (!this.view_ || !this.toLonLat_) { return; } const center = this.view_.getCenter(); if (!center) { return; } const ll = this.toLonLat_(center); console.assert(ll); const carto = new Cesium.Cartographic((0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[0]), (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1])); if (this.scene_.globe) { const height = this.scene_.globe.getHeight(carto); carto.height = height || 0; } const destination = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); /** @type {Cesium.optionsOrientation} */ const orientation = { pitch: this.tilt_ - Cesium.Math.PI_OVER_TWO, heading: -this.view_.getRotation(), roll: undefined }; this.cam_.setView({ destination, orientation }); this.cam_.moveBackward(this.distance_); this.checkCameraChange(true); } /** * Calculates the values of the properties from the current ol.View state. * @api */ readFromView() { if (!this.view_ || !this.toLonLat_) { return; } const center = this.view_.getCenter(); if (center === undefined || center === null) { return; } const ll = this.toLonLat_(center); console.assert(ll); const resolution = this.view_.getResolution(); this.distance_ = this.calcDistanceForResolution( resolution || 0, (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1])); this.updateCamera_(); } /** * Calculates the values of the properties from the current Cesium.Camera state. * Modifies the center, resolution and rotation properties of the view. * @api */ updateView() { if (!this.view_ || !this.fromLonLat_) { return; } this.viewUpdateInProgress_ = true; // target & distance const ellipsoid = Cesium.Ellipsoid.WGS84; const scene = this.scene_; const target = _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].pickCenterPoint(scene); let bestTarget = target; if (!bestTarget) { //TODO: how to handle this properly ? const globe = scene.globe; const carto = this.cam_.positionCartographic.clone(); const height = globe.getHeight(carto); carto.height = height || 0; bestTarget = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); } this.distance_ = Cesium.Cartesian3.distance(bestTarget, this.cam_.position); const bestTargetCartographic = ellipsoid.cartesianToCartographic(bestTarget); this.view_.setCenter(this.fromLonLat_([ (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(bestTargetCartographic.longitude), (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(bestTargetCartographic.latitude)])); // resolution this.view_.setResolution( this.calcResolutionForDistance(this.distance_, bestTargetCartographic ? bestTargetCartographic.latitude : 0)); /* * Since we are positioning the target, the values of heading and tilt * need to be calculated _at the target_. */ if (target) { const pos = this.cam_.position; // normal to the ellipsoid at the target const targetNormal = new Cesium.Cartesian3(); ellipsoid.geocentricSurfaceNormal(target, targetNormal); // vector from the target to the camera const targetToCamera = new Cesium.Cartesian3(); Cesium.Cartesian3.subtract(pos, target, targetToCamera); Cesium.Cartesian3.normalize(targetToCamera, targetToCamera); // HEADING const up = this.cam_.up; const right = this.cam_.right; const normal = new Cesium.Cartesian3(-target.y, target.x, 0); // what is it? const heading = Cesium.Cartesian3.angleBetween(right, normal); const cross = Cesium.Cartesian3.cross(target, up, new Cesium.Cartesian3()); const orientation = cross.z; this.view_.setRotation((orientation < 0 ? heading : -heading)); // TILT const tiltAngle = Math.acos( Cesium.Cartesian3.dot(targetNormal, targetToCamera)); this.tilt_ = isNaN(tiltAngle) ? 0 : tiltAngle; } else { // fallback when there is no target this.view_.setRotation(this.cam_.heading); this.tilt_ = -this.cam_.pitch + Math.PI / 2; } this.viewUpdateInProgress_ = false; } /** * Check if the underlying camera state has changed and ensure synchronization. * @param {boolean=} opt_dontSync Do not synchronize the view. */ checkCameraChange(opt_dontSync) { const old = this.lastCameraViewMatrix_; const current = this.cam_.viewMatrix; if (!old || !Cesium.Matrix4.equalsEpsilon(old, current, 1e-5)) { this.lastCameraViewMatrix_ = current.clone(); if (opt_dontSync !== true) { this.updateView(); } } } /** * calculate the distance between camera and centerpoint based on the resolution and latitude value * @param {number} resolution Number of map units per pixel. * @param {number} latitude Latitude in radians. * @return {number} The calculated distance. * @api */ calcDistanceForResolution(resolution, latitude) { return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.calcDistanceForResolution)(resolution, latitude, this.scene_, this.view_.getProjection()); } /** * calculate the resolution based on a distance(camera to position) and latitude value * @param {number} distance * @param {number} latitude * @return {number} The calculated resolution. * @api */ calcResolutionForDistance(distance, latitude) { return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.calcResolutionForDistance)(distance, latitude, this.scene_, this.view_.getProjection()); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Camera); /***/ }), /***/ "./src/olcs/FeatureConverter.js": /*!**************************************!*\ !*** ./src/olcs/FeatureConverter.js ***! \**************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/geom/Geometry.js */ "ol/geom/Geometry.js"); /* harmony import */ var ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/style/Icon.js */ "ol/style/Icon.js"); /* harmony import */ var ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source/Vector.js */ "ol/source/Vector.js"); /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/source/Cluster.js */ "ol/source/Cluster.js"); /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/geom/Polygon.js */ "ol/geom/Polygon.js"); /* harmony import */ var ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var ol_extent_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/extent.js */ "ol/extent"); /* harmony import */ var ol_extent_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_extent_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/geom/SimpleGeometry.js */ "ol/geom/SimpleGeometry.js"); /* harmony import */ var ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js"); /* harmony import */ var _core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./core/VectorLayerCounterpart.js */ "./src/olcs/core/VectorLayerCounterpart.js"); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /** * @module olcs.FeatureConverter */ /** * @typedef {Object} ModelStyle * @property {Cesium.Matrix4} [debugModelMatrix] * @property {Cesium.ModelFromGltfOptions} cesiumOptions */ class FeatureConverter { /** * Concrete base class for converting from OpenLayers3 vectors to Cesium * primitives. * Extending this class is possible provided that the extending class and * the library are compiled together by the closure compiler. * @param {!Cesium.Scene} scene Cesium scene. * @constructor * @api */ constructor(scene) { /** * @protected */ this.scene = scene; /** * Bind once to have a unique function for using as a listener * @type {function(ol.source.Vector.Event)} * @private */ this.boundOnRemoveOrClearFeatureListener_ = this.onRemoveOrClearFeature_.bind(this); /** * @type {Cesium.Cartesian3} * @private */ this.defaultBillboardEyeOffset_ = new Cesium.Cartesian3(0, 0, 10); } /** * @param {ol.source.Vector.Event} evt * @private */ onRemoveOrClearFeature_(evt) { const source = evt.target; console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default())); const cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers']; if (cancellers) { const feature = evt.feature; if (feature) { // remove const id = (0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature); const canceller = cancellers[id]; if (canceller) { canceller(); delete cancellers[id]; } } else { // clear for (const key in cancellers) { if (cancellers.hasOwnProperty(key)) { cancellers[key](); } } _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'] = {}; } } } /** * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!Cesium.Primitive|Cesium.Label|Cesium.Billboard} primitive * @protected */ setReferenceForPicking(layer, feature, primitive) { primitive.olLayer = layer; primitive.olFeature = feature; } /** * Basics primitive creation using a color attribute. * Note that Cesium has 'interior' and outline geometries. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!ol.geom.Geometry} olGeometry OpenLayers geometry. * @param {!Cesium.Geometry} geometry * @param {!Cesium.Color} color * @param {number=} opt_lineWidth * @return {Cesium.Primitive} * @protected */ createColoredPrimitive(layer, feature, olGeometry, geometry, color, opt_lineWidth) { const createInstance = function(geometry, color) { const instance = new Cesium.GeometryInstance({ // always update Cesium externs before adding a property geometry }); if (color && !(color instanceof Cesium.ImageMaterialProperty)) { instance.attributes = { color: Cesium.ColorGeometryInstanceAttribute.fromColor(color) }; } return instance; }; const options = { // always update Cesium externs before adding a property flat: true, // work with all geometries renderState: { depthTest: { enabled: true } } }; if (opt_lineWidth !== undefined) { if (!options.renderState) { options.renderState = {}; } options.renderState.lineWidth = opt_lineWidth; } const instances = createInstance(geometry, color); const heightReference = this.getHeightReference(layer, feature, olGeometry); let primitive; if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) { const ctor = instances.geometry.constructor; if (ctor && !ctor['createShadowVolume']) { return null; } primitive = new Cesium.GroundPrimitive({ geometryInstances: instances }); } else { primitive = new Cesium.Primitive({ geometryInstances: instances }); } if (color instanceof Cesium.ImageMaterialProperty) { const dataUri = color.image.getValue().toDataURL(); primitive.appearance = new Cesium.MaterialAppearance({ flat: true, renderState: { depthTest: { enabled: true } }, material: new Cesium.Material({ fabric: { type: 'Image', uniforms: { image: dataUri } } }) }); } else { primitive.appearance = new Cesium.PerInstanceColorAppearance(options); } this.setReferenceForPicking(layer, feature, primitive); return primitive; } /** * Return the fill or stroke color from a plain ol style. * @param {!ol.style.Style|ol.style.Text} style * @param {boolean} outline * @return {!Cesium.Color} * @protected */ extractColorFromOlStyle(style, outline) { const fillColor = style.getFill() ? style.getFill().getColor() : null; const strokeColor = style.getStroke() ? style.getStroke().getColor() : null; let olColor = 'black'; if (strokeColor && outline) { olColor = strokeColor; } else if (fillColor) { olColor = fillColor; } return _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].convertColorToCesium(olColor); } /** * Return the width of stroke from a plain ol style. * @param {!ol.style.Style|ol.style.Text} style * @return {number} * @protected */ extractLineWidthFromOlStyle(style) { // Handling of line width WebGL limitations is handled by Cesium. const width = style.getStroke() ? style.getStroke().getWidth() : undefined; return width !== undefined ? width : 1; } /** * Create a primitive collection out of two Cesium geometries. * Only the OpenLayers style colors will be used. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!ol.geom.Geometry} olGeometry OpenLayers geometry. * @param {!Cesium.Geometry} fillGeometry * @param {!Cesium.Geometry} outlineGeometry * @param {!ol.style.Style} olStyle * @return {!Cesium.PrimitiveCollection} * @protected */ wrapFillAndOutlineGeometries(layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle) { const fillColor = this.extractColorFromOlStyle(olStyle, false); const outlineColor = this.extractColorFromOlStyle(olStyle, true); const primitives = new Cesium.PrimitiveCollection(); if (olStyle.getFill()) { const p1 = this.createColoredPrimitive(layer, feature, olGeometry, fillGeometry, fillColor); console.assert(!!p1); primitives.add(p1); } if (olStyle.getStroke() && outlineGeometry) { const width = this.extractLineWidthFromOlStyle(olStyle); const p2 = this.createColoredPrimitive(layer, feature, olGeometry, outlineGeometry, outlineColor, width); if (p2) { // Some outline geometries are not supported by Cesium in clamp to ground // mode. These primitives are skipped. primitives.add(p2); } } return primitives; } // Geometry converters /** * Create a Cesium primitive if style has a text component. * Eventually return a PrimitiveCollection including current primitive. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Geometry} geometry * @param {!ol.style.Style} style * @param {!Cesium.Primitive} primitive current primitive * @return {!Cesium.PrimitiveCollection} * @protected */ addTextStyle(layer, feature, geometry, style, primitive) { let primitives; if (!(primitive instanceof Cesium.PrimitiveCollection)) { primitives = new Cesium.PrimitiveCollection(); primitives.add(primitive); } else { primitives = primitive; } if (!style.getText()) { return primitives; } const text = /** @type {!ol.style.Text} */ (style.getText()); const label = this.olGeometry4326TextPartToCesium(layer, feature, geometry, text); if (label) { primitives.add(label); } return primitives; } /** * Add a billboard to a Cesium.BillboardCollection. * Overriding this wrapper allows manipulating the billboard options. * @param {!Cesium.BillboardCollection} billboards * @param {!Cesium.optionsBillboardCollectionAdd} bbOptions * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!ol.geom.Geometry} geometry * @param {!ol.style.Style} style * @return {!Cesium.Billboard} newly created billboard * @api */ csAddBillboard(billboards, bbOptions, layer, feature, geometry, style) { if (!bbOptions.eyeOffset) { bbOptions.eyeOffset = this.defaultBillboardEyeOffset_; } const bb = billboards.add(bbOptions); this.setReferenceForPicking(layer, feature, bb); return bb; } /** * Convert an OpenLayers circle geometry to Cesium. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Circle} olGeometry OpenLayers circle geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} olStyle * @return {!Cesium.PrimitiveCollection} primitives * @api */ olCircleGeometryToCesium(layer, feature, olGeometry, projection, olStyle) { olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection); console.assert(olGeometry.getType() == 'Circle'); // ol.Coordinate let center = olGeometry.getCenter(); const height = center.length == 3 ? center[2] : 0.0; let point = center.slice(); point[0] += olGeometry.getRadius(); // Cesium center = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(center); point = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(point); // Accurate computation of straight distance const radius = Cesium.Cartesian3.distance(center, point); const fillGeometry = new Cesium.CircleGeometry({ // always update Cesium externs before adding a property center, radius, height }); let outlinePrimitive, outlineGeometry; if (this.getHeightReference(layer, feature, olGeometry) === Cesium.HeightReference.CLAMP_TO_GROUND) { const width = this.extractLineWidthFromOlStyle(olStyle); if (width) { const circlePolygon = (0,ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__.circular)(olGeometry.getCenter(), radius); const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(circlePolygon.getLinearRing(0).getCoordinates()); if (!(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) { const color = this.extractColorFromOlStyle(olStyle, true); outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions); } else { outlinePrimitive = new Cesium.GroundPolylinePrimitive({ geometryInstances: new Cesium.GeometryInstance({ geometry: new Cesium.GroundPolylineGeometry({positions, width}), }), appearance: new Cesium.PolylineMaterialAppearance({ material: this.olStyleToCesium(feature, olStyle, true), }), classificationType: Cesium.ClassificationType.TERRAIN, }); outlinePrimitive.readyPromise.then(() => { this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive); }); } } } else { outlineGeometry = new Cesium.CircleOutlineGeometry({ // always update Cesium externs before adding a property center, radius, extrudedHeight: height, height }); } const primitives = this.wrapFillAndOutlineGeometries( layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle); if (outlinePrimitive) { primitives.add(outlinePrimitive); } return this.addTextStyle(layer, feature, olGeometry, olStyle, primitives); } /** * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!number} width The width of the line. * @param {!Cesium.Color} color The color of the line. * @param {!Array|Array>} positions The vertices of the line(s). * @return {!Cesium.GroundPrimitive} primitive */ createStackedGroundCorridors(layer, feature, width, color, positions) { // Convert positions to an Array if it isn't if (!Array.isArray(positions[0])) { positions = [positions]; } width = Math.max(3, width); // A <3px width is too small for ground primitives const geometryInstances = []; let previousDistance = 0; // A stack of ground lines with increasing width (in meters) are created. // Only one of these lines is displayed at any time giving a feeling of continuity. // The values for the distance and width factor are more or less arbitrary. // Applications can override this logics by subclassing the FeatureConverter class. for (const distance of [1000, 4000, 16000, 64000, 254000, 1000000, 10000000]) { width *= 2.14; const geometryOptions = { // always update Cesium externs before adding a property width, vertexFormat: Cesium.VertexFormat.POSITION_ONLY }; for (const linePositions of positions) { geometryOptions.positions = linePositions; geometryInstances.push(new Cesium.GeometryInstance({ geometry: new Cesium.CorridorGeometry(geometryOptions), attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(color), distanceDisplayCondition: new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(previousDistance, distance - 1) } })); } previousDistance = distance; } return new Cesium.GroundPrimitive({ // always update Cesium externs before adding a property geometryInstances }); } /** * Convert an OpenLayers line string geometry to Cesium. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.LineString} olGeometry OpenLayers line string geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} olStyle * @return {!Cesium.PrimitiveCollection} primitives * @api */ olLineStringGeometryToCesium(layer, feature, olGeometry, projection, olStyle) { olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection); console.assert(olGeometry.getType() == 'LineString'); const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(olGeometry.getCoordinates()); const width = this.extractLineWidthFromOlStyle(olStyle); let outlinePrimitive; const heightReference = this.getHeightReference(layer, feature, olGeometry); if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND && !(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) { const color = this.extractColorFromOlStyle(olStyle, true); outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions); } else { const appearance = new Cesium.PolylineMaterialAppearance({ // always update Cesium externs before adding a property material: this.olStyleToCesium(feature, olStyle, true) }); const geometryOptions = { // always update Cesium externs before adding a property positions, width, }; const primitiveOptions = { // always update Cesium externs before adding a property appearance }; if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) { const geometry = new Cesium.GroundPolylineGeometry(geometryOptions); primitiveOptions.geometryInstances = new Cesium.GeometryInstance({ geometry }), outlinePrimitive = new Cesium.GroundPolylinePrimitive(primitiveOptions); outlinePrimitive.readyPromise.then(() => { this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive); }); } else { geometryOptions.vertexFormat = appearance.vertexFormat; const geometry = new Cesium.PolylineGeometry(geometryOptions); primitiveOptions.geometryInstances = new Cesium.GeometryInstance({ geometry }), outlinePrimitive = new Cesium.Primitive(primitiveOptions); } } this.setReferenceForPicking(layer, feature, outlinePrimitive); return this.addTextStyle(layer, feature, olGeometry, olStyle, outlinePrimitive); } /** * Convert an OpenLayers polygon geometry to Cesium. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Polygon} olGeometry OpenLayers polygon geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} olStyle * @return {!Cesium.PrimitiveCollection} primitives * @api */ olPolygonGeometryToCesium(layer, feature, olGeometry, projection, olStyle) { olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection); console.assert(olGeometry.getType() == 'Polygon'); const heightReference = this.getHeightReference(layer, feature, olGeometry); let fillGeometry, outlineGeometry, outlinePrimitive; if ((olGeometry.getCoordinates()[0].length == 5) && (feature.getGeometry().get('olcs.polygon_kind') === 'rectangle')) { // Create a rectangle according to the longitude and latitude curves const coordinates = olGeometry.getCoordinates()[0]; // Extract the West, South, East, North coordinates const extent = (0,ol_extent_js__WEBPACK_IMPORTED_MODULE_5__.boundingExtent)(coordinates); const rectangle = Cesium.Rectangle.fromDegrees(extent[0], extent[1], extent[2], extent[3]); // Extract the average height of the vertices let maxHeight = 0.0; if (coordinates[0].length == 3) { for (let c = 0; c < coordinates.length; c++) { maxHeight = Math.max(maxHeight, coordinates[c][2]); } } // Render the cartographic rectangle fillGeometry = new Cesium.RectangleGeometry({ ellipsoid: Cesium.Ellipsoid.WGS84, rectangle, height: maxHeight }); outlineGeometry = new Cesium.RectangleOutlineGeometry({ ellipsoid: Cesium.Ellipsoid.WGS84, rectangle, height: maxHeight }); } else { const rings = olGeometry.getLinearRings(); // always update Cesium externs before adding a property const hierarchy = {}; const polygonHierarchy = hierarchy; console.assert(rings.length > 0); for (let i = 0; i < rings.length; ++i) { const olPos = rings[i].getCoordinates(); const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(olPos); console.assert(positions && positions.length > 0); if (i == 0) { hierarchy.positions = positions; } else { if (!hierarchy.holes) { hierarchy.holes = []; } hierarchy.holes.push({ positions }); } } fillGeometry = new Cesium.PolygonGeometry({ // always update Cesium externs before adding a property polygonHierarchy, perPositionHeight: true }); // Since Cesium doesn't yet support Polygon outlines on terrain yet (coming soon...?) // we don't create an outline geometry if clamped, but instead do the polyline method // for each ring. Most of this code should be removeable when Cesium adds // support for Polygon outlines on terrain. if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) { const width = this.extractLineWidthFromOlStyle(olStyle); if (width > 0) { const positions = [hierarchy.positions]; if (hierarchy.holes) { for (let i = 0; i < hierarchy.holes.length; ++i) { positions.push(hierarchy.holes[i].positions); } } if (!(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) { const color = this.extractColorFromOlStyle(olStyle, true); outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions); } else { const appearance = new Cesium.PolylineMaterialAppearance({ // always update Cesium externs before adding a property material: this.olStyleToCesium(feature, olStyle, true) }); const geometryInstances = []; for (const linePositions of positions) { const polylineGeometry = new Cesium.GroundPolylineGeometry({positions: linePositions, width}); geometryInstances.push(new Cesium.GeometryInstance({ geometry: polylineGeometry })); } const primitiveOptions = { // always update Cesium externs before adding a property appearance, geometryInstances }; outlinePrimitive = new Cesium.GroundPolylinePrimitive(primitiveOptions); outlinePrimitive.readyPromise.then(() => { this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive); }); } } } else { // Actually do the normal polygon thing. This should end the removable // section of code described above. outlineGeometry = new Cesium.PolygonOutlineGeometry({ // always update Cesium externs before adding a property polygonHierarchy: hierarchy, perPositionHeight: true }); } } const primitives = this.wrapFillAndOutlineGeometries( layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle); if (outlinePrimitive) { primitives.add(outlinePrimitive); } return this.addTextStyle(layer, feature, olGeometry, olStyle, primitives); } /** * @param {ol.layer.Vector|ol.layer.Image} layer * @param {ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Geometry} geometry * @return {!Cesium.HeightReference} * @api */ getHeightReference(layer, feature, geometry) { // Read from the geometry let altitudeMode = geometry.get('altitudeMode'); // Or from the feature if (altitudeMode === undefined) { altitudeMode = feature.get('altitudeMode'); } // Or from the layer if (altitudeMode === undefined) { altitudeMode = layer.get('altitudeMode'); } let heightReference = Cesium.HeightReference.NONE; if (altitudeMode === 'clampToGround') { heightReference = Cesium.HeightReference.CLAMP_TO_GROUND; } else if (altitudeMode === 'relativeToGround') { heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND; } return heightReference; } /** * Convert a point geometry to a Cesium BillboardCollection. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Point} olGeometry OpenLayers point geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} style * @param {!ol.style.Image} imageStyle * @param {!Cesium.BillboardCollection} billboards * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when the new billboard is added. * @api */ createBillboardFromImage( layer, feature, olGeometry, projection, style, imageStyle, billboards, opt_newBillboardCallback ) { if (imageStyle instanceof (ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default())) { // make sure the image is scheduled for load imageStyle.load(); } const image = imageStyle.getImage(1); // get normal density const isImageLoaded = function(image) { return image.src != '' && image.naturalHeight != 0 && image.naturalWidth != 0 && image.complete; }; const reallyCreateBillboard = (function() { if (!image) { return; } if (!(image instanceof HTMLCanvasElement || image instanceof Image || image instanceof HTMLImageElement)) { return; } const center = olGeometry.getCoordinates(); const position = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(center); let color; const opacity = imageStyle.getOpacity(); if (opacity !== undefined) { color = new Cesium.Color(1.0, 1.0, 1.0, opacity); } const scale = imageStyle.getScale(); const heightReference = this.getHeightReference(layer, feature, olGeometry); const bbOptions = /** @type {Cesium.optionsBillboardCollectionAdd} */ ({ // always update Cesium externs before adding a property image, color, scale, heightReference, position }); // merge in cesium options from openlayers feature Object.assign(bbOptions, feature.get('cesiumOptions')); if (imageStyle instanceof (ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default())) { const anchor = imageStyle.getAnchor(); if (anchor) { bbOptions.pixelOffset = new Cesium.Cartesian2((image.width / 2 - anchor[0]) * scale, (image.height / 2 - anchor[1]) * scale); } } const bb = this.csAddBillboard(billboards, bbOptions, layer, feature, olGeometry, style); if (opt_newBillboardCallback) { opt_newBillboardCallback(bb); } }).bind(this); if (image instanceof Image && !isImageLoaded(image)) { // Cesium requires the image to be loaded let cancelled = false; const source = layer.getSource(); const canceller = function() { cancelled = true; }; source.on(['removefeature', 'clear'], this.boundOnRemoveOrClearFeatureListener_); let cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers']; if (!cancellers) { cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'] = {}; } const fuid = (0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature); if (cancellers[fuid]) { // When the feature change quickly, a canceller may still be present so // we cancel it here to prevent creation of a billboard. cancellers[fuid](); } cancellers[fuid] = canceller; const listener = function() { image.removeEventListener('load', listener); if (!billboards.isDestroyed() && !cancelled) { // Create billboard if the feature is still displayed on the map. reallyCreateBillboard(); } }; image.addEventListener('load', listener); } else { reallyCreateBillboard(); } } /** * Convert a point geometry to a Cesium BillboardCollection. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Point} olGeometry OpenLayers point geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} style * @param {!Cesium.BillboardCollection} billboards * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when * the new billboard is added. * @return {Cesium.Primitive} primitives * @api */ olPointGeometryToCesium( layer, feature, olGeometry, projection, style, billboards, opt_newBillboardCallback ) { console.assert(olGeometry.getType() == 'Point'); olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection); let modelPrimitive = null; const imageStyle = style.getImage(); if (imageStyle) { const olcsModelFunction = /** @type {function():olcsx.ModelStyle} */ (olGeometry.get('olcs_model') || feature.get('olcs_model')); if (olcsModelFunction) { const olcsModel = olcsModelFunction(); const options = /** @type {Cesium.ModelFromGltfOptions} */ (Object.assign({}, {scene: this.scene}, olcsModel.cesiumOptions)); const model = Cesium.Model.fromGltf(options); modelPrimitive = new Cesium.PrimitiveCollection(); modelPrimitive.add(model); if (olcsModel.debugModelMatrix) { modelPrimitive.add(new Cesium.DebugModelMatrixPrimitive({ modelMatrix: olcsModel.debugModelMatrix })); } } else { this.createBillboardFromImage(layer, feature, olGeometry, projection, style, imageStyle, billboards, opt_newBillboardCallback); } } if (style.getText()) { return this.addTextStyle(layer, feature, olGeometry, style, modelPrimitive || new Cesium.Primitive()); } else { return modelPrimitive; } } /** * Convert an OpenLayers multi-something geometry to Cesium. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Geometry} geometry OpenLayers geometry. * @param {!ol.ProjectionLike} projection * @param {!ol.style.Style} olStyle * @param {!Cesium.BillboardCollection} billboards * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when * the new billboard is added. * @return {Cesium.Primitive} primitives * @api */ olMultiGeometryToCesium( layer, feature, geometry, projection, olStyle, billboards, opt_newBillboardCallback ) { // Do not reproject to 4326 now because it will be done later. // FIXME: would be better to combine all child geometries in one primitive // instead we create n primitives for simplicity. const accumulate = function(geometries, functor) { const primitives = new Cesium.PrimitiveCollection(); geometries.forEach((geometry) => { primitives.add(functor(layer, feature, geometry, projection, olStyle)); }); return primitives; }; let subgeos; switch (geometry.getType()) { case 'MultiPoint': geometry = /** @type {!ol.geom.MultiPoint} */ (geometry); subgeos = geometry.getPoints(); if (olStyle.getText()) { const primitives = new Cesium.PrimitiveCollection(); subgeos.forEach((geometry) => { console.assert(geometry); const result = this.olPointGeometryToCesium(layer, feature, geometry, projection, olStyle, billboards, opt_newBillboardCallback); if (result) { primitives.add(result); } }); return primitives; } else { subgeos.forEach((geometry) => { console.assert(geometry); this.olPointGeometryToCesium(layer, feature, geometry, projection, olStyle, billboards, opt_newBillboardCallback); }); return null; } case 'MultiLineString': geometry = /** @type {!ol.geom.MultiLineString} */ (geometry); subgeos = geometry.getLineStrings(); return accumulate(subgeos, this.olLineStringGeometryToCesium.bind(this)); case 'MultiPolygon': geometry = /** @type {!ol.geom.MultiPolygon} */ (geometry); subgeos = geometry.getPolygons(); return accumulate(subgeos, this.olPolygonGeometryToCesium.bind(this)); default: console.assert(false, `Unhandled multi geometry type${geometry.getType()}`); } } /** * Convert an OpenLayers text style to Cesium. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature.. * @param {!ol.geom.Geometry} geometry * @param {!ol.style.Text} style * @return {Cesium.LabelCollection} Cesium primitive * @api */ olGeometry4326TextPartToCesium(layer, feature, geometry, style) { const text = style.getText(); if (!text) { return null; } const labels = new Cesium.LabelCollection({scene: this.scene}); // TODO: export and use the text draw position from OpenLayers . // See src/ol/render/vector.js const extentCenter = (0,ol_extent_js__WEBPACK_IMPORTED_MODULE_5__.getCenter)(geometry.getExtent()); if (geometry instanceof (ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6___default())) { const first = geometry.getFirstCoordinate(); extentCenter[2] = first.length == 3 ? first[2] : 0.0; } const options = /** @type {Cesium.optionsLabelCollection} */ ({}); options.position = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(extentCenter); options.text = text; options.heightReference = this.getHeightReference(layer, feature, geometry); const offsetX = style.getOffsetX(); const offsetY = style.getOffsetY(); if (offsetX != 0 && offsetY != 0) { const offset = new Cesium.Cartesian2(offsetX, offsetY); options.pixelOffset = offset; } options.font = style.getFont() || '10px sans-serif'; // OpenLayers default let labelStyle = undefined; if (style.getFill()) { options.fillColor = this.extractColorFromOlStyle(style, false); labelStyle = Cesium.LabelStyle.FILL; } if (style.getStroke()) { options.outlineWidth = this.extractLineWidthFromOlStyle(style); options.outlineColor = this.extractColorFromOlStyle(style, true); labelStyle = Cesium.LabelStyle.OUTLINE; } if (style.getFill() && style.getStroke()) { labelStyle = Cesium.LabelStyle.FILL_AND_OUTLINE; } options.style = labelStyle; let horizontalOrigin; switch (style.getTextAlign()) { case 'left': horizontalOrigin = Cesium.HorizontalOrigin.LEFT; break; case 'right': horizontalOrigin = Cesium.HorizontalOrigin.RIGHT; break; case 'center': default: horizontalOrigin = Cesium.HorizontalOrigin.CENTER; } options.horizontalOrigin = horizontalOrigin; if (style.getTextBaseline()) { let verticalOrigin; switch (style.getTextBaseline()) { case 'top': verticalOrigin = Cesium.VerticalOrigin.TOP; break; case 'middle': verticalOrigin = Cesium.VerticalOrigin.CENTER; break; case 'bottom': verticalOrigin = Cesium.VerticalOrigin.BOTTOM; break; case 'alphabetic': verticalOrigin = Cesium.VerticalOrigin.TOP; break; case 'hanging': verticalOrigin = Cesium.VerticalOrigin.BOTTOM; break; default: console.assert(false, `unhandled baseline ${style.getTextBaseline()}`); } options.verticalOrigin = verticalOrigin; } const l = labels.add(options); this.setReferenceForPicking(layer, feature, l); return labels; } /** * Convert an OpenLayers style to a Cesium Material. * @param {ol.Feature} feature OpenLayers feature.. * @param {!ol.style.Style} style * @param {boolean} outline * @return {Cesium.Material} * @api */ olStyleToCesium(feature, style, outline) { const fill = style.getFill(); const stroke = style.getStroke(); if ((outline && !stroke) || (!outline && !fill)) { return null; // FIXME use a default style? Developer error? } let color = outline ? stroke.getColor() : fill.getColor(); color = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].convertColorToCesium(color); if (outline && stroke.getLineDash()) { return Cesium.Material.fromType('Stripe', { // always update Cesium externs before adding a property horizontal: false, repeat: 500, // TODO how to calculate this? evenColor: color, oddColor: new Cesium.Color(0, 0, 0, 0) // transparent }); } else { return Cesium.Material.fromType('Color', { // always update Cesium externs before adding a property color }); } } /** * Compute OpenLayers plain style. * Evaluates style function, blend arrays, get default style. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature * @param {ol.StyleFunction|undefined} fallbackStyleFunction * @param {number} resolution * @return {Array.} null if no style is available * @api */ computePlainStyle(layer, feature, fallbackStyleFunction, resolution) { /** * @type {ol.FeatureStyleFunction|undefined} */ const featureStyleFunction = feature.getStyleFunction(); /** * @type {ol.style.Style|Array.} */ let style = null; if (featureStyleFunction) { style = featureStyleFunction(feature, resolution); } if (!style && fallbackStyleFunction) { style = fallbackStyleFunction(feature, resolution); } if (!style) { // The feature must not be displayed return null; } // FIXME combine materials as in cesium-materials-pack? // then this function must return a custom material // More simply, could blend the colors like described in // http://en.wikipedia.org/wiki/Alpha_compositing return Array.isArray(style) ? style : [style]; } /** * @protected * @param {!ol.Feature} feature * @param {!ol.style.Style} style * @param {!ol.geom.Geometry=} opt_geom Geometry to be converted. * @return {ol.geom.Geometry|undefined} */ getGeometryFromFeature(feature, style, opt_geom) { if (opt_geom) { return opt_geom; } const geom3d = /** @type {!ol.geom.Geometry} */(feature.get('olcs.3d_geometry')); if (geom3d && geom3d instanceof (ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default())) { return geom3d; } if (style) { const geomFuncRes = style.getGeometryFunction()(feature); if (geomFuncRes instanceof (ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default())) { return geomFuncRes; } } return feature.getGeometry(); } /** * Convert one OpenLayers feature up to a collection of Cesium primitives. * @param {ol.layer.Vector|ol.layer.Image} layer * @param {!ol.Feature} feature OpenLayers feature. * @param {!ol.style.Style} style * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context * @param {!ol.geom.Geometry=} opt_geom Geometry to be converted. * @return {Cesium.Primitive} primitives * @api */ olFeatureToCesium(layer, feature, style, context, opt_geom) { let geom = this.getGeometryFromFeature(feature, style, opt_geom); if (!geom) { // OpenLayers features may not have a geometry // See http://geojson.org/geojson-spec.html#feature-objects return null; } const proj = context.projection; const newBillboardAddedCallback = function(bb) { const featureBb = context.featureToCesiumMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)]; if (featureBb instanceof Array) { featureBb.push(bb); } else { context.featureToCesiumMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)] = [bb]; } }; switch (geom.getType()) { case 'GeometryCollection': const primitives = new Cesium.PrimitiveCollection(); const collection = /** @type {!ol.geom.GeometryCollection} */ (geom); // TODO: use getGeometriesArray() instead collection.getGeometries().forEach((geom) => { if (geom) { const prims = this.olFeatureToCesium(layer, feature, style, context, geom); if (prims) { primitives.add(prims); } } }); return primitives; case 'Point': geom = /** @type {!ol.geom.Point} */ (geom); const bbs = context.billboards; const result = this.olPointGeometryToCesium(layer, feature, geom, proj, style, bbs, newBillboardAddedCallback); if (!result) { // no wrapping primitive return null; } else { return result; } case 'Circle': geom = /** @type {!ol.geom.Circle} */ (geom); return this.olCircleGeometryToCesium(layer, feature, geom, proj, style); case 'LineString': geom = /** @type {!ol.geom.LineString} */ (geom); return this.olLineStringGeometryToCesium(layer, feature, geom, proj, style); case 'Polygon': geom = /** @type {!ol.geom.Polygon} */ (geom); return this.olPolygonGeometryToCesium(layer, feature, geom, proj, style); case 'MultiPoint': case 'MultiLineString': case 'MultiPolygon': const result2 = this.olMultiGeometryToCesium(layer, feature, geom, proj, style, context.billboards, newBillboardAddedCallback); if (!result2) { // no wrapping primitive return null; } else { return result2; } case 'LinearRing': throw new Error('LinearRing should only be part of polygon.'); default: throw new Error(`Ol geom type not handled : ${geom.getType()}`); } } /** * Convert an OpenLayers vector layer to Cesium primitive collection. * For each feature, the associated primitive will be stored in * `featurePrimitiveMap`. * @param {!(ol.layer.Vector|ol.layer.Image)} olLayer * @param {!ol.View} olView * @param {!Object.} featurePrimitiveMap * @return {!olcs.core.VectorLayerCounterpart} * @api */ olVectorLayerToCesium(olLayer, olView, featurePrimitiveMap) { const proj = olView.getProjection(); const resolution = olView.getResolution(); if (resolution === undefined || !proj) { console.assert(false, 'View not ready'); // an assertion is not enough for closure to assume resolution and proj // are defined throw new Error('View not ready'); } let source = olLayer.getSource(); if (source instanceof (ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3___default())) { source = source.getSource(); } console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default())); const features = source.getFeatures(); const counterpart = new _core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_8__["default"](proj, this.scene); const context = counterpart.context; for (let i = 0; i < features.length; ++i) { const feature = features[i]; if (!feature) { continue; } /** * @type {ol.StyleFunction|undefined} */ const layerStyle = olLayer.getStyleFunction(); const styles = this.computePlainStyle(olLayer, feature, layerStyle, resolution); if (!styles || !styles.length) { // only 'render' features with a style continue; } /** * @type {Cesium.Primitive|null} */ let primitives = null; for (let i = 0; i < styles.length; i++) { const prims = this.olFeatureToCesium(olLayer, feature, styles[i], context); if (prims) { if (!primitives) { primitives = prims; } else if (prims) { let i = 0, prim; while ((prim = prims.get(i))) { primitives.add(prim); i++; } } } } if (!primitives) { continue; } featurePrimitiveMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)] = primitives; counterpart.getRootPrimitive().add(primitives); } return counterpart; } /** * Convert an OpenLayers feature to Cesium primitive collection. * @param {!(ol.layer.Vector|ol.layer.Image)} layer * @param {!ol.View} view * @param {!ol.Feature} feature * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context * @return {Cesium.Primitive} * @api */ convert(layer, view, feature, context) { const proj = view.getProjection(); const resolution = view.getResolution(); if (resolution == undefined || !proj) { return null; } /** * @type {ol.StyleFunction|undefined} */ const layerStyle = layer.getStyleFunction(); const styles = this.computePlainStyle(layer, feature, layerStyle, resolution); if (!styles || !styles.length) { // only 'render' features with a style return null; } context.projection = proj; /** * @type {Cesium.Primitive|null} */ let primitives = null; for (let i = 0; i < styles.length; i++) { const prims = this.olFeatureToCesium(layer, feature, styles[i], context); if (!primitives) { primitives = prims; } else if (prims) { let i = 0, prim; while ((prim = prims.get(i))) { primitives.add(prim); i++; } } } return primitives; } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FeatureConverter); /***/ }), /***/ "./src/olcs/MVTImageryProvider.js": /*!****************************************!*\ !*** ./src/olcs/MVTImageryProvider.js ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ MVTImageryProvider) /* harmony export */ }); /* harmony import */ var ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/format/MVT.js */ "ol/format/MVT.js"); /* harmony import */ var ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/style/Style.js */ "ol/style/Style.js"); /* harmony import */ var ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/style/Stroke.js */ "ol/style/Stroke.js"); /* harmony import */ var ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var ol_render_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/render.js */ "ol/render.js"); /* harmony import */ var ol_render_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_render_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var ol_util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/util.js */ "ol/util.js"); /* harmony import */ var ol_util_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_util_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/structs/LRUCache.js */ "ol/structs/LRUCache.js"); /* harmony import */ var ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ol/tilegrid.js */ "ol/tilegrid.js"); /* harmony import */ var ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ol/tileurlfunction.js */ "ol/tileurlfunction.js"); /* harmony import */ var ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__); const format = new (ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0___default())(); const styles = [new (ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1___default())({ stroke: new (ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2___default())({ color: 'blue', width: 2 }) })]; class MVTImageryProvider { constructor(options) { this.urls = options.urls; this.ready = true; this.readyPromise = Promise.resolve(true); this.tileWidth = 256; this.tileHeight = 256; this.maximumLevel = options.maximumLevel || 20; this.minimumLevel = options.minimumLevel || 0; this.tilingScheme = new Cesium.WebMercatorTilingScheme; this.rectangle = options.rectangle || this.tilingScheme.rectangle; this.errorEvent = new Cesium.Event(); this.credit = options.credit; this.hasAlphaChannel = true; this.styleFunction_ = options.styleFunction || (() => styles); this.projection_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_4__.get)('EPSG:3857'); this.emptyCanvas_ = document.createElement('canvas'); this.emptyCanvas_.width = 1; this.emptyCanvas_.height = 1; this.tileRectangle_ = new Cesium.Rectangle(); const cacheSize = options.cacheSize !== undefined ? options.cacheSize : 50; this.tileCache = new (ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default())(cacheSize); this.featureCache = options.featureCache || new (ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default())(cacheSize); // to avoid too frequent cache grooming we allow x2 capacity const tileGrid = (0,ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__.getForProjection)(this.projection_); this.tileFunction_ = (0,ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__.createFromTemplates)(this.urls, tileGrid); } getTileCredits() { return []; } pickFeatures() { } getTileFeatures(z, x, y) { const cacheKey = this.getCacheKey_(z, x, y); let promise; if (this.featureCache.containsKey(cacheKey)) { promise = this.featureCache.get(cacheKey); } if (!promise) { const url = this.getUrl_(z, x, y); promise = fetch(url) .then(r => (r.ok ? r : Promise.reject(r))) .then(r => r.arrayBuffer()) .then(buffer => this.readFeaturesFromBuffer(buffer)); this.featureCache.set(cacheKey, promise); if (this.featureCache.getCount() > 2 * this.featureCache.highWaterMark) { while (this.featureCache.canExpireCache()) { this.featureCache.pop(); } } } return promise; } readFeaturesFromBuffer(buffer) { let options; if (ol_util_js__WEBPACK_IMPORTED_MODULE_5__.VERSION <= '6.4.4') { // See https://github.com/openlayers/openlayers/pull/11540 options = { extent: [0, 0, 4096, 4096], dataProjection: format.dataProjection, featureProjection: format.dataProjection }; } const features = format.readFeatures(buffer, options); const scaleFactor = this.tileWidth / 4096; features.forEach((f) => { const flatCoordinates = f.getFlatCoordinates(); let flip = false; for (let i = 0; i < flatCoordinates.length; ++i) { flatCoordinates[i] *= scaleFactor; if (flip) { // FIXME: why do we need this now? flatCoordinates[i] = this.tileWidth - flatCoordinates[i]; } if (ol_util_js__WEBPACK_IMPORTED_MODULE_5__.VERSION <= '6.4.4') { flip = !flip; } } }); return features; } getUrl_(z, x, y) { const url = this.tileFunction_([z, x, y]); return url; } getCacheKey_(z, x, y) { return `${z}_${x}_${y}`; } requestImage(x, y, z, request) { if (z < this.minimumLevel) { return this.emptyCanvas_; } try { const cacheKey = this.getCacheKey_(z, x, y); let promise; if (this.tileCache.containsKey(cacheKey)) { promise = this.tileCache.get(cacheKey); } if (!promise) { promise = this.getTileFeatures(z, x, y) .then((features) => { // FIXME: here we suppose the 2D projection is in meters this.tilingScheme.tileXYToNativeRectangle(x, y, z, this.tileRectangle_); const resolution = (this.tileRectangle_.east - this.tileRectangle_.west) / this.tileWidth; return this.rasterizeFeatures(features, this.styleFunction_, resolution); }); this.tileCache.set(cacheKey, promise); if (this.tileCache.getCount() > 2 * this.tileCache.highWaterMark) { while (this.tileCache.canExpireCache()) { this.tileCache.pop(); } } } return promise; } catch (e) { console.trace(e); this.raiseEvent('could not render pbf to tile', e); } } rasterizeFeatures(features, styleFunction, resolution) { const canvas = document.createElement('canvas'); const vectorContext = (0,ol_render_js__WEBPACK_IMPORTED_MODULE_3__.toContext)(canvas.getContext('2d'), {size: [this.tileWidth, this.tileHeight]}); features.forEach((f) => { const styles = styleFunction(f, resolution); if (styles) { styles.forEach((style) => { vectorContext.setStyle(style); vectorContext.drawGeometry(f); }); } }); return canvas; } } /***/ }), /***/ "./src/olcs/OLCesium.js": /*!******************************!*\ !*** ./src/olcs/OLCesium.js ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/geom/Point.js */ "ol/geom/Point.js"); /* harmony import */ var ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js"); /* harmony import */ var _AutoRenderLoop_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AutoRenderLoop.js */ "./src/olcs/AutoRenderLoop.js"); /* harmony import */ var _Camera_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Camera.js */ "./src/olcs/Camera.js"); /* harmony import */ var _RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./RasterSynchronizer.js */ "./src/olcs/RasterSynchronizer.js"); /* harmony import */ var _VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./VectorSynchronizer.js */ "./src/olcs/VectorSynchronizer.js"); /* harmony import */ var _OverlaySynchronizer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./OverlaySynchronizer.js */ "./src/olcs/OverlaySynchronizer.js"); /** * @module olcs.OLCesium */ /** * @typedef {Object} OLCesiumOptions * @property {import('ol/Map.js').default} map The OpenLayers map we want to show on a Cesium scene. * @property {Cesium.Viewer} [viewer] Cesium viewer. * @property {function(!import('ol/Map.js').default, !Cesium.Scene, !Cesium.DataSourceCollection): Array} * [createSynchronizers] Callback function which will be called by the {@link olcs.OLCesium} * constructor to create custom synchronizers. Receives an `ol.Map` and a `Cesium.Scene` as arguments, * and needs to return an array of {@link import('olcs/AbstractSynchronizer.js').default}. * @property {function(): Cesium.JulianDate} [time] Control the current time used by Cesium. * @property {boolean} [stopOpenLayersEventsPropagation] Prevent propagation of mouse/touch events to * OpenLayers when Cesium is active. */ class OLCesium { /** * @param {!OLCesiumOptions} options Options. * @constructor * @api */ constructor(options) { /** * @type {olcs.AutoRenderLoop} * @private */ this.autoRenderLoop_ = null; /** * @type {!ol.Map} * @private */ this.map_ = options.map; /** * @type {!function(): Cesium.JulianDate} * @private */ this.time_ = options.time || function() { return Cesium.JulianDate.now(); }; /** * No change of the view projection. * @private */ this.to4326Transform_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_1__.getTransform)(this.map_.getView().getProjection(), 'EPSG:4326'); /** * @type {number} * @private */ this.resolutionScale_ = 1.0; /** * @type {number} * @private */ this.canvasClientWidth_ = 0.0; /** * @type {number} * @private */ this.canvasClientHeight_ = 0.0; /** * @type {boolean} * @private */ this.resolutionScaleChanged_ = true; // force resize const fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;'; /** * @type {!Element} * @private */ this.container_ = document.createElement('DIV'); const containerAttribute = document.createAttribute('style'); containerAttribute.value = `${fillArea}visibility:hidden;`; this.container_.setAttributeNode(containerAttribute); //火星科技添加 let viewer = options.viewer viewer.container.appendChild(this.container_); // /** // * Whether the Cesium container is placed over the ol map. // * a target => side by side mode // * no target => over map mode // * @type {boolean} // * @private // */ // this.isOverMap_ = false; // if (this.isOverMap_ && options.stopOpenLayersEventsPropagation) { // const overlayEvents = ['click', 'dblclick', 'mousedown', 'touchstart', 'MSPointerDown', 'pointerdown', 'mousewheel', 'wheel']; // for (let i = 0, ii = overlayEvents.length; i < ii; ++i) { // this.container_.addEventListener(overlayEvents[i], evt => evt.stopPropagation()); // } // } // /** // * @type {!HTMLCanvasElement} // * @private // */ // this.canvas_ = /** @type {!HTMLCanvasElement} */ (document.createElement('CANVAS')); // const canvasAttribute = document.createAttribute('style'); // canvasAttribute.value = fillArea; // this.canvas_.setAttributeNode(canvasAttribute); // if (olcsUtil.supportsImageRenderingPixelated()) { // // non standard CSS4 // this.canvas_.style['imageRendering'] = olcsUtil.imageRenderingValue(); // } // this.canvas_.oncontextmenu = function() { return false; }; // this.canvas_.onselectstart = function() { return false; }; // this.container_.appendChild(this.canvas_); /** * @type {boolean} * @private */ this.enabled_ = false; /** * @type {!Array.} * @private */ this.pausedInteractions_ = []; /** * @type {?ol.layer.Group} * @private */ this.hiddenRootGroup_ = null; // const sceneOptions = options.sceneOptions !== undefined ? options.sceneOptions : // /** @type {Cesium.SceneOptions} */ ({}); // sceneOptions.canvas = this.canvas_; // sceneOptions.scene3DOnly = true; /** * @type {!Cesium.Scene} * @private */ this.scene_ = viewer.scene; // const sscc = this.scene_.screenSpaceCameraController; // sscc.tiltEventTypes.push({ // 'eventType': Cesium.CameraEventType.LEFT_DRAG, // 'modifier': Cesium.KeyboardEventModifier.SHIFT // }); // sscc.tiltEventTypes.push({ // 'eventType': Cesium.CameraEventType.LEFT_DRAG, // 'modifier': Cesium.KeyboardEventModifier.ALT // }); // sscc.enableLook = false; // this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z; /** * @type {!olcs.Camera} * @private */ this.camera_ = new _Camera_js__WEBPACK_IMPORTED_MODULE_5__["default"](this.scene_, this.map_); /** * @type {!Cesium.Globe} * @private */ this.globe_ = viewer.scene.globe; // this.globe_.baseColor = Cesium.Color.WHITE; // this.scene_.globe = this.globe_; // this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere(); // The first layer of Cesium is special; using a 1x1 transparent image to workaround it. // See https://github.com/AnalyticalGraphicsInc/cesium/issues/1323 for details. // const firstImageryProvider = new Cesium.SingleTileImageryProvider({ // url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=', // rectangle: Cesium.Rectangle.fromDegrees(0, 0, 1, 1) // the Rectangle dimensions are arbitrary // }); // this.globe_.imageryLayers.addImageryProvider(firstImageryProvider, 0); this.dataSourceCollection_ = viewer.dataSources this.dataSourceDisplay_ = viewer.dataSourceDisplay const synchronizers = options.createSynchronizers ? options.createSynchronizers(this.map_, this.scene_, this.dataSourceCollection_) : [ new _RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_6__["default"](this.map_, this.scene_), new _VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__["default"](this.map_, this.scene_), new _OverlaySynchronizer_js__WEBPACK_IMPORTED_MODULE_8__["default"](this.map_, this.scene_) ]; // Assures correct canvas size after initialisation // this.handleResize_(); for (let i = synchronizers.length - 1; i >= 0; --i) { synchronizers[i].synchronize(); } // /** // * Time of the last rendered frame, as returned by `performance.now()`. // * @type {number} // * @private // */ // this.lastFrameTime_ = 0; // /** // * The identifier returned by `requestAnimationFrame`. // * @type {number|undefined} // * @private // */ // this.renderId_ = undefined; // /** // * Target frame rate for the render loop. // * @type {number} // * @private // */ // this.targetFrameRate_ = Number.POSITIVE_INFINITY; // /** // * If the Cesium render loop is being blocked. // * @type {boolean} // * @private // */ // this.blockCesiumRendering_ = false; // /** // * If the warmup routine is active. // * @type {boolean} // * @private // */ // this.warmingUp_ = false; /** * @type {ol.Feature} * @private */ this.trackedFeature_ = null; /** * @type {Cesium.Entity} * @private */ this.trackedEntity_ = null; // /** // * @type {Cesium.EntityView} // * @private // */ // this.entityView_ = null; // /** // * @type {boolean} // * @private // */ // this.needTrackedEntityUpdate_ = false; // /** // * @type {!Cesium.BoundingSphere} // */ // this.boundingSphereScratch_ = new Cesium.BoundingSphere(); // const eventHelper = new Cesium.EventHelper(); // eventHelper.add(this.scene_.postRender, OLCesium.prototype.updateTrackedEntity_, this); // Cesium has a mechanism to prevent the camera to go under the terrain. // Unfortunately, it is only active when all the terrain has been loaded, which: // - does not prevent the camera to sink under terrain anymore; // - introduce a jumping effect once all terrain has been loaded and the position of the camera is finally fixed. // The property below enables a workaround found in the Camptocamp Cesium fork. // See also https://github.com/AnalyticalGraphicsInc/cesium/issues/5999. // Cesium.Camera.enableSuspendTerrainAdjustment = false; viewer.scene.postUpdate.addEventListener(this.onAnimationFrame_, this); } // /** // * Render the Cesium scene. // * @private // */ // render_() { // // // if a call to `requestAnimationFrame` is pending, cancel it // // if (this.renderId_ !== undefined) { // // cancelAnimationFrame(this.renderId_); // // this.renderId_ = undefined; // // } // // // only render if Cesium is enabled/warming and rendering hasn't been blocked // // if ((this.enabled_ || this.warmingUp_) && !this.blockCesiumRendering_) { // // this.renderId_ = requestAnimationFrame(this.onAnimationFrame_.bind(this)); // // } // } /** * Callback for `requestAnimationFrame`. * @param {number} frameTime The frame time, from `performance.now()`. * @private */ onAnimationFrame_(frameTime) { // this.renderId_ = undefined; // // check if a frame was rendered within the target frame rate // const interval = 1000.0 / this.targetFrameRate_; // const delta = frameTime - this.lastFrameTime_; // if (delta < interval) { // // too soon, don't render yet // this.render_(); // return; // } // time to render a frame, save the time // this.lastFrameTime_ = frameTime; // const julianDate = this.time_(); // this.scene_.initializeFrame(); // this.handleResize_(); // this.dataSourceDisplay_.update(julianDate); // // Update tracked entity // if (this.entityView_) { // const trackedEntity = this.trackedEntity_; // const trackedState = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_); // if (trackedState === Cesium.BoundingSphereState.DONE) { // this.boundingSphereScratch_.radius = 1; // a radius of 1 is enough for tracking points // this.entityView_.update(julianDate, this.boundingSphereScratch_); // } // } // this.scene_.render(julianDate); this.camera_.checkCameraChange(); // request the next render call after this one completes to ensure the browser doesn't get backed up // this.render_(); } /** * @private */ // updateTrackedEntity_() { // if (!this.needTrackedEntityUpdate_) { // return; // } // const trackedEntity = this.trackedEntity_; // const scene = this.scene_; // const state = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_); // if (state === Cesium.BoundingSphereState.PENDING) { // return; // } // scene.screenSpaceCameraController.enableTilt = false; // const bs = state !== Cesium.BoundingSphereState.FAILED ? this.boundingSphereScratch_ : undefined; // if (bs) { // bs.radius = 1; // } // this.entityView_ = new Cesium.EntityView(trackedEntity, scene, scene.mapProjection.ellipsoid); // this.entityView_.update(this.time_(), bs); // this.needTrackedEntityUpdate_ = false; // } // /** // * @private // */ // handleResize_() { // let width = this.canvas_.clientWidth; // let height = this.canvas_.clientHeight; // if (width === 0 | height === 0) { // // The canvas DOM element is not ready yet. // return; // } // if (width === this.canvasClientWidth_ && // height === this.canvasClientHeight_ && // !this.resolutionScaleChanged_) { // return; // } // let resolutionScale = this.resolutionScale_; // if (!olcsUtil.supportsImageRenderingPixelated()) { // resolutionScale *= window.devicePixelRatio || 1.0; // } // this.resolutionScaleChanged_ = false; // this.canvasClientWidth_ = width; // this.canvasClientHeight_ = height; // width *= resolutionScale; // height *= resolutionScale; // this.canvas_.width = width; // this.canvas_.height = height; // // this.scene_.camera.frustum.aspectRatio = width / height; // } /** * @return {!olcs.Camera} * @api */ getCamera() { return this.camera_; } /** * @return {!ol.Map} * @api */ getOlMap() { return this.map_; } /** * @return {!ol.View} * @api */ getOlView() { const view = this.map_.getView(); console.assert(view); return view; } /** * @return {!Cesium.Scene} * @api */ getCesiumScene() { return this.scene_; } /** * @return {!Cesium.DataSourceCollection} * @api */ getDataSources() { return this.dataSourceCollection_; } /** * @return {!Cesium.DataSourceDisplay} * @api */ getDataSourceDisplay() { return this.dataSourceDisplay_; } /** * @return {boolean} * @api */ getEnabled() { return this.enabled_; } /** * Enables/disables the Cesium. * This modifies the visibility style of the container element. * @param {boolean} enable * @api */ setEnabled(enable) { if (this.enabled_ === enable) { return; } this.enabled_ = enable; // some Cesium operations are operating with canvas.clientWidth, // so we can't remove it from DOM or even make display:none; // this.container_.style.visibility = this.enabled_ ? 'visible' : 'hidden'; // let interactions; if (this.enabled_) { // this.throwOnUnitializedMap_(); // if (this.isOverMap_) { // interactions = this.map_.getInteractions(); // interactions.forEach((el, i, arr) => { // this.pausedInteractions_.push(el); // }); // interactions.clear(); // this.map_.addInteraction = interaction => this.pausedInteractions_.push(interaction); // this.map_.removeInteraction = interaction => // this.pausedInteractions_ = this.pausedInteractions_.filter(i => i !== interaction); // const rootGroup = this.map_.getLayerGroup(); // if (rootGroup.getVisible()) { // this.hiddenRootGroup_ = rootGroup; // this.hiddenRootGroup_.setVisible(false); // } // this.map_.getOverlayContainer().classList.add('olcs-hideoverlay'); // } this.camera_.readFromView(); // this.render_(); } else { // if (this.isOverMap_) { // interactions = this.map_.getInteractions(); // this.pausedInteractions_.forEach((interaction) => { // interactions.push(interaction); // }); // this.pausedInteractions_.length = 0; // this.map_.addInteraction = interaction => this.map_.getInteractions().push(interaction); // this.map_.removeInteraction = interaction => this.map_.getInteractions().remove(interaction); // this.map_.getOverlayContainer().classList.remove('olcs-hideoverlay'); // if (this.hiddenRootGroup_) { // this.hiddenRootGroup_.setVisible(true); // this.hiddenRootGroup_ = null; // } // } this.camera_.updateView(); } } /** * Preload Cesium so that it is ready when transitioning from 2D to 3D. * @param {number} height Target height of the camera * @param {number} timeout Milliseconds after which the warming will stop * @api */ warmUp(height, timeout) { if (this.enabled_) { // already enabled return; } this.throwOnUnitializedMap_(); this.camera_.readFromView(); const ellipsoid = this.globe_.ellipsoid; const csCamera = this.scene_.camera; const position = ellipsoid.cartesianToCartographic(csCamera.position); if (position.height < height) { position.height = height; csCamera.position = ellipsoid.cartographicToCartesian(position); } // this.warmingUp_ = true; // // this.render_(); // setTimeout(() => { // this.warmingUp_ = false; // }, timeout); } // /** // * Block Cesium rendering to save resources. // * @param {boolean} block True to block. // * @api // */ // setBlockCesiumRendering(block) { // if (this.blockCesiumRendering_ !== block) { // this.blockCesiumRendering_ = block; // // reset the render loop // this.render_(); // } // } /** * Render the globe only when necessary in order to save resources. * Experimental. * @api */ enableAutoRenderLoop() { if (!this.autoRenderLoop_) { this.autoRenderLoop_ = new _AutoRenderLoop_js__WEBPACK_IMPORTED_MODULE_4__["default"](this); } } /** * Get the autorender loop. * @return {?olcs.AutoRenderLoop} * @api */ getAutoRenderLoop() { return this.autoRenderLoop_; } /** * The 3D Cesium globe is rendered in a canvas with two different dimensions: * clientWidth and clientHeight which are the dimension on the screen and * width and height which are the dimensions of the drawing buffer. * * By using a resolution scale lower than 1.0, it is possible to render the * globe in a buffer smaller than the canvas client dimensions and improve * performance, at the cost of quality. * * Pixel ratio should also be taken into account; by default, a device with * pixel ratio of 2.0 will have a buffer surface 4 times bigger than the client * surface. * * @param {number} value * @this {olcs.OLCesium} * @api */ setResolutionScale(value) { value = Math.max(0, value); if (value !== this.resolutionScale_) { this.resolutionScale_ = Math.max(0, value); this.resolutionScaleChanged_ = true; if (this.autoRenderLoop_) { this.autoRenderLoop_.restartRenderLoop(); } } } // /** // * Set the target frame rate for the renderer. Set to `Number.POSITIVE_INFINITY` // * to render as quickly as possible. // * @param {number} value The frame rate, in frames per second. // * @api // */ // setTargetFrameRate(value) { // if (this.targetFrameRate_ !== value) { // this.targetFrameRate_ = value; // // reset the render loop // this.render_(); // } // } /** * Check if OpenLayers map is not properly initialized. * @private */ throwOnUnitializedMap_() { const map = this.map_; const view = map.getView(); const center = view.getCenter(); if (!view.isDef() || isNaN(center[0]) || isNaN(center[1])) { throw new Error(`The OpenLayers map is not properly initialized: ${center} / ${view.getResolution()}`); } } /** * @type {ol.Feature} */ get trackedFeature() { return this.trackedFeature_; } /** * @param {ol.Feature} feature */ set trackedFeature(feature) { if (this.trackedFeature_ !== feature) { const scene = this.scene_; //Stop tracking if (!feature || !feature.getGeometry()) { // this.needTrackedEntityUpdate_ = false; scene.screenSpaceCameraController.enableTilt = true; if (this.trackedEntity_) { this.dataSourceDisplay_.defaultDataSource.entities.remove(this.trackedEntity_); } this.trackedEntity_ = null; this.trackedFeature_ = null; this.entityView_ = null; scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY); return; } this.trackedFeature_ = feature; //We can't start tracking immediately, so we set a flag and start tracking //when the bounding sphere is ready (most likely next frame). // this.needTrackedEntityUpdate_ = true; const to4326Transform = this.to4326Transform_; const toCesiumPosition = function() { const geometry = feature.getGeometry(); console.assert(geometry instanceof (ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0___default())); const coo = geometry.getCoordinates(); const coo4326 = to4326Transform(coo, undefined, coo.length); return _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].ol4326CoordinateToCesiumCartesian(coo4326); }; // Create an invisible point entity for tracking. // It is independant from the primitive/geometry created by the vector synchronizer. const options = { 'position': new Cesium.CallbackProperty((time, result) => toCesiumPosition(), false), 'point': { 'pixelSize': 1, 'color': Cesium.Color.TRANSPARENT } }; this.trackedEntity_ = this.dataSourceDisplay_.defaultDataSource.entities.add(options); } } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OLCesium); /***/ }), /***/ "./src/olcs/OverlaySynchronizer.js": /*!*****************************************!*\ !*** ./src/olcs/OverlaySynchronizer.js ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _SynchronizedOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SynchronizedOverlay.js */ "./src/olcs/SynchronizedOverlay.js"); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /** * @module olcs.OverlaySynchronizer */ class OverlaySynchronizer { /** * @param {!ol.Map} map * @param {!Cesium.Scene} scene * @constructor * @template T * @api */ constructor(map, scene) { /** * @type {!ol.Map} * @protected */ this.map = map; /** * @type {ol.Collection.} * @private */ this.overlays_ = this.map.getOverlays(); /** * @type {!Cesium.Scene} * @protected */ this.scene = scene; /** * @private * @type {!Element} */ this.overlayContainerStopEvent_ = document.createElement('DIV'); this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent'; const overlayEvents = ['click', 'dblclick', 'mousedown', 'touchstart', 'MSPointerDown', 'pointerdown', 'mousewheel', 'wheel']; overlayEvents.forEach((event) => { this.overlayContainerStopEvent_.addEventListener(event, evt => evt.stopPropagation()); }); this.scene.canvas.parentElement.appendChild(this.overlayContainerStopEvent_); /** * @private * @type {!Element} */ this.overlayContainer_ = document.createElement('DIV'); this.overlayContainer_.className = 'ol-overlaycontainer'; this.scene.canvas.parentElement.appendChild(this.overlayContainer_); /** * @type {!Object} * @private */ this.overlayMap_ = {}; } /** * Get the element that serves as a container for overlays that don't allow * event propagation. Elements added to this container won't let mousedown and * touchstart events through to the map, so clicks and gestures on an overlay * don't trigger any {@link ol.MapBrowserEvent}. * @return {!Element} The map's overlay container that stops events. */ getOverlayContainerStopEvent() { return this.overlayContainerStopEvent_; } /** * Get the element that serves as a container for overlays. * @return {!Element} The map's overlay container. */ getOverlayContainer() { return this.overlayContainer_; } /** * Destroy all and perform complete synchronization of the overlays. * @api */ synchronize() { this.destroyAll(); this.addOverlays(); this.overlays_.on('add', this.addOverlayFromEvent_.bind(this)); this.overlays_.on('remove', this.removeOverlayFromEvent_.bind(this)); } /** * @param {ol.Collection.Event} event * @private */ addOverlayFromEvent_(event) { const overlay = /** @type {ol.Overlay} */ (event.element); this.addOverlay(overlay); } /** * @api */ addOverlays() { this.overlays_.forEach((overlay) => { this.addOverlay(overlay); }); } /** * @param {ol.Overlay} overlay * @api */ addOverlay(overlay) { if (!overlay) { return; } const cesiumOverlay = new _SynchronizedOverlay_js__WEBPACK_IMPORTED_MODULE_0__["default"]({ scene: this.scene, synchronizer: this, parent: overlay }); const overlayId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(overlay).toString(); this.overlayMap_[overlayId] = cesiumOverlay; } /** * @param {ol.Collection.Event} event * @private */ removeOverlayFromEvent_(event) { const removedOverlay = /** @type {ol.Overlay} */ (event.element); this.removeOverlay(removedOverlay); } /** * Removes an overlay from the scene * @param {ol.Overlay} overlay * @api */ removeOverlay(overlay) { const overlayId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(overlay).toString(); const csOverlay = this.overlayMap_[overlayId]; if (csOverlay) { csOverlay.destroy(); delete this.overlayMap_[overlayId]; } } /** * Destroys all the created Cesium objects. * @protected */ destroyAll() { Object.keys(this.overlayMap_).forEach((key) => { const overlay = this.overlayMap_[key]; overlay.destroy(); delete this.overlayMap_[key]; }); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OverlaySynchronizer); /***/ }), /***/ "./src/olcs/RasterSynchronizer.js": /*!****************************************!*\ !*** ./src/olcs/RasterSynchronizer.js ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/layer/Group.js */ "ol/layer/Group.js"); /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /* harmony import */ var _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js"); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js"); /** * @module olcs.RasterSynchronizer */ class RasterSynchronizer extends _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__["default"] { /** * This object takes care of one-directional synchronization of * Openlayers raster layers to the given Cesium globe. * @param {!ol.Map} map * @param {!Cesium.Scene} scene * @constructor * @extends {olcsAbstractSynchronizer.} * @api */ constructor(map, scene) { super(map, scene); /** * @type {!Cesium.ImageryLayerCollection} * @private */ this.cesiumLayers_ = scene.imageryLayers; /** * @type {!Cesium.ImageryLayerCollection} * @private */ this.ourLayers_ = new Cesium.ImageryLayerCollection(); } /** * @inheritDoc */ addCesiumObject(object) { this.cesiumLayers_.add(object); this.ourLayers_.add(object); } /** * @inheritDoc */ destroyCesiumObject(object) { object.destroy(); } /** * @inheritDoc */ removeSingleCesiumObject(object, destroy) { this.cesiumLayers_.remove(object, destroy); this.ourLayers_.remove(object, false); } /** * @inheritDoc */ removeAllCesiumObjects(destroy) { for (let i = 0; i < this.ourLayers_.length; ++i) { this.cesiumLayers_.remove(this.ourLayers_.get(i), destroy); } this.ourLayers_.removeAll(false); } /** * Creates an array of Cesium.ImageryLayer. * May be overriden by child classes to implement custom behavior. * The default implementation handles tiled imageries in EPSG:4326 or * EPSG:3859. * @param {!ol.layer.Base} olLayer * @param {!ol.proj.Projection} viewProj Projection of the view. * @return {?Array.} array or null if not possible * (or supported) * @protected */ convertLayerToCesiumImageries(olLayer, viewProj) { const result = _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].tileLayerToImageryLayer(this.map, olLayer, viewProj); return result ? [result] : null; } /** * @inheritDoc */ createSingleLayerCounterparts(olLayerWithParents) { const olLayer = olLayerWithParents.layer; const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer).toString(); const viewProj = this.view.getProjection(); console.assert(viewProj); const cesiumObjects = this.convertLayerToCesiumImageries(olLayer, viewProj); if (cesiumObjects) { const listenKeyArray = []; [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => { listenKeyArray.push(olLayerItem.on(['change:opacity', 'change:visible'], () => { // the compiler does not seem to be able to infer this console.assert(cesiumObjects); for (let i = 0; i < cesiumObjects.length; ++i) { _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]); } })); }); if (olLayer.getStyleFunction) { let previousStyleFunction = olLayer.getStyleFunction(); // there is no convenient way to detect a style function change in OL listenKeyArray.push(olLayer.on('change', () => { const currentStyleFunction = olLayer.getStyleFunction(); if (previousStyleFunction === currentStyleFunction) { return; } previousStyleFunction = currentStyleFunction; for (let i = 0; i < cesiumObjects.length; ++i) { const csObj = cesiumObjects[i]; // clear cache and set new style if (csObj._imageryCache && csObj.imageryProvider.cache_) { csObj._imageryCache = {}; csObj.imageryProvider.cache_ = {}; csObj.imageryProvider.styleFunction_ = currentStyleFunction; } } this.scene.requestRender(); })); } for (let i = 0; i < cesiumObjects.length; ++i) { _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]); } // there is no way to modify Cesium layer extent, // we have to recreate when OpenLayers layer extent changes: listenKeyArray.push(olLayer.on('change:extent', (e) => { for (let i = 0; i < cesiumObjects.length; ++i) { this.cesiumLayers_.remove(cesiumObjects[i], true); // destroy this.ourLayers_.remove(cesiumObjects[i], false); } delete this.layerMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer)]; // invalidate the map entry this.synchronize(); })); listenKeyArray.push(olLayer.on('change', (e) => { // when the source changes, re-add the layer to force update for (let i = 0; i < cesiumObjects.length; ++i) { const position = this.cesiumLayers_.indexOf(cesiumObjects[i]); if (position >= 0) { this.cesiumLayers_.remove(cesiumObjects[i], false); this.cesiumLayers_.add(cesiumObjects[i], position); } } })); this.olLayerListenKeys[uid].push(...listenKeyArray); } return Array.isArray(cesiumObjects) ? cesiumObjects : null; } /** * Order counterparts using the same algorithm as the Openlayers renderer: * z-index then original sequence order. * @override * @protected */ orderLayers() { const layers = []; const zIndices = {}; const queue = [this.mapLayerGroup]; while (queue.length > 0) { const olLayer = queue.splice(0, 1)[0]; layers.push(olLayer); zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer)] = olLayer.getZIndex() || 0; if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0___default())) { const sublayers = olLayer.getLayers(); if (sublayers) { // Prepend queue with sublayers in order queue.unshift(...sublayers.getArray()); } } } (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.stableSort)(layers, (layer1, layer2) => zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(layer1)] - zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(layer2)] ); layers.forEach((olLayer) => { const olLayerId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer).toString(); const cesiumObjects = this.layerMap[olLayerId]; if (cesiumObjects) { cesiumObjects.forEach((cesiumObject) => { this.raiseToTop(cesiumObject); }); } }); } /** * @param {Cesium.ImageryLayer} counterpart */ raiseToTop(counterpart) { this.cesiumLayers_.raiseToTop(counterpart); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RasterSynchronizer); /***/ }), /***/ "./src/olcs/SynchronizedOverlay.js": /*!*****************************************!*\ !*** ./src/olcs/SynchronizedOverlay.js ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Overlay.js */ "ol/Overlay.js"); /* harmony import */ var ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__); /** * @module olcs.SynchronizedOverlay */ /** * Options for SynchronizedOverlay * @typedef {Object} SynchronizedOverlayOptions * @property {!Cesium.Scene} scene * @property {olOverlay} parent * @property {!import('olsc/OverlaySynchronizer.js').default} synchronizer */ class SynchronizedOverlay extends (ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0___default()) { /** * @param {olcsx.SynchronizedOverlayOptions} options SynchronizedOverlay Options. * @api */ constructor(options) { const parent = options.parent; super(parent.getOptions()); /** * @private * @type {?Function} */ this.scenePostRenderListenerRemover_ = null; /** * @private * @type {!Cesium.Scene} */ this.scene_ = options.scene; /** * @private * @type {!olcs.OverlaySynchronizer} */ this.synchronizer_ = options.synchronizer; /** * @private * @type {!ol.Overlay} */ this.parent_ = parent; /** * @private * @type {ol.Coordinate|undefined} */ this.positionWGS84_ = undefined; /** * @private * @type {MutationObserver} */ this.observer_ = new MutationObserver(this.handleElementChanged.bind(this)); /** * @private * @type {Array.} */ this.attributeObserver_ = []; /** * @private * @type {Array} */ this.listenerKeys_ = []; // synchronize our Overlay with the parent Overlay const setPropertyFromEvent = event => this.setPropertyFromEvent_(event); this.listenerKeys_.push(this.parent_.on('change:position', setPropertyFromEvent)); this.listenerKeys_.push(this.parent_.on('change:element', setPropertyFromEvent)); this.listenerKeys_.push(this.parent_.on('change:offset', setPropertyFromEvent)); this.listenerKeys_.push(this.parent_.on('change:position', setPropertyFromEvent)); this.listenerKeys_.push(this.parent_.on('change:positioning', setPropertyFromEvent)); this.setProperties(this.parent_.getProperties()); this.handleMapChanged(); this.handleElementChanged(); } /** * @param {Node} target * @private */ observeTarget_(target) { if (!this.observer_) { // not ready, skip the event (this occurs on construction) return; } this.observer_.disconnect(); this.observer_.observe(target, { attributes: false, childList: true, characterData: true, subtree: true }); this.attributeObserver_.forEach((observer) => { observer.disconnect(); }); this.attributeObserver_.length = 0; for (let i = 0; i < target.childNodes.length; i++) { const node = target.childNodes[i]; if (node.nodeType === 1) { const observer = new MutationObserver(this.handleElementChanged.bind(this)); observer.observe(node, { attributes: true, subtree: true }); this.attributeObserver_.push(observer); } } } /** * * @param {ol.Object.Event} event * @private */ setPropertyFromEvent_(event) { if (event.target && event.key) { this.set(event.key, event.target.get(event.key)); } } /** * Get the scene associated with this overlay. * @see ol.Overlay.prototype.getMap * @return {!Cesium.Scene} The scene that the overlay is part of. * @api */ getScene() { return this.scene_; } /** * @override */ handleMapChanged() { if (this.scenePostRenderListenerRemover_) { this.scenePostRenderListenerRemover_(); (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.removeNode)(this.element); } this.scenePostRenderListenerRemover_ = null; const scene = this.getScene(); if (scene) { this.scenePostRenderListenerRemover_ = scene.postRender.addEventListener(this.updatePixelPosition.bind(this)); this.updatePixelPosition(); const container = this.stopEvent ? this.synchronizer_.getOverlayContainerStopEvent() : this.synchronizer_.getOverlayContainer(); if (this.insertFirst) { container.insertBefore(this.element, container.childNodes[0] || null); } else { container.appendChild(this.element); } } } /** * @override */ handlePositionChanged() { // transform position to WGS84 const position = this.getPosition(); if (position) { const sourceProjection = this.parent_.getMap().getView().getProjection(); this.positionWGS84_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_1__.transform)(position, sourceProjection, 'EPSG:4326'); } else { this.positionWGS84_ = undefined; } this.updatePixelPosition(); } /** * @override */ handleElementChanged() { function cloneNode(node, parent) { const clone = node.cloneNode(); if (node.nodeName === 'CANVAS') { const ctx = clone.getContext('2d'); ctx.drawImage(node, 0, 0); } if (parent) { parent.appendChild(clone); } if (node.nodeType != Node.TEXT_NODE) { clone.addEventListener('click', (event) => { node.dispatchEvent(new MouseEvent('click', event)); event.stopPropagation(); }); } const nodes = node.childNodes; for (let i = 0; i < nodes.length; i++) { if (!nodes[i]) { continue; } cloneNode(nodes[i], clone); } return clone; } (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.removeChildren)(this.element); const element = this.getElement(); if (element) { if (element.parentNode && element.parentNode.childNodes) { for (const node of element.parentNode.childNodes) { const clonedNode = cloneNode(node, null); this.element.appendChild(clonedNode); } } } if (element.parentNode) { // set new Observer this.observeTarget_(element.parentNode); } } /** * @override */ updatePixelPosition() { const position = this.positionWGS84_; if (!this.scene_ || !position) { this.setVisible(false); return; } let height = 0; if (position.length === 2) { const globeHeight = this.scene_.globe.getHeight(Cesium.Cartographic.fromDegrees(position[0], position[1])); if (globeHeight && this.scene_.globe.tilesLoaded) { position[2] = globeHeight; } if (globeHeight) { height = globeHeight; } } else { height = position[2]; } const cartesian = Cesium.Cartesian3.fromDegrees(position[0], position[1], height); const camera = this.scene_.camera; const ellipsoidBoundingSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(), 6356752); const occluder = new Cesium.Occluder(ellipsoidBoundingSphere, camera.position); // check if overlay position is behind the horizon if (!occluder.isPointVisible(cartesian)) { this.setVisible(false); return; } const cullingVolume = camera.frustum.computeCullingVolume(camera.position, camera.direction, camera.up); // check if overlay position is visible from the camera if (cullingVolume.computeVisibility(new Cesium.BoundingSphere(cartesian)) !== 1) { this.setVisible(false); return; } this.setVisible(true); const pixelCartesian = this.scene_.cartesianToCanvasCoordinates(cartesian); const pixel = [pixelCartesian.x, pixelCartesian.y]; const mapSize = [this.scene_.canvas.width, this.scene_.canvas.height]; this.updateRenderedPosition(pixel, mapSize); } /** * Destroys the overlay, removing all its listeners and elements * @api */ destroy() { if (this.scenePostRenderListenerRemover_) { this.scenePostRenderListenerRemover_(); } if (this.observer_) { this.observer_.disconnect(); } (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__.unByKey)(this.listenerKeys_); this.listenerKeys_.splice(0); if (this.element.removeNode) { this.element.removeNode(true); } else { this.element.remove(); } this.element = null; } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SynchronizedOverlay); /***/ }), /***/ "./src/olcs/VectorSynchronizer.js": /*!****************************************!*\ !*** ./src/olcs/VectorSynchronizer.js ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/source/Vector.js */ "ol/source/Vector.js"); /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Layer.js */ "ol/layer/Layer.js"); /* harmony import */ var ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source/Cluster.js */ "ol/source/Cluster.js"); /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/layer/Image.js */ "ol/layer/Image.js"); /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /* harmony import */ var ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/layer/Vector.js */ "ol/layer/Vector.js"); /* harmony import */ var ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/layer/VectorTile.js */ "ol/layer/VectorTile.js"); /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js"); /* harmony import */ var _FeatureConverter_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FeatureConverter.js */ "./src/olcs/FeatureConverter.js"); /** * @module olcs.VectorSynchronizer */ class VectorSynchronizer extends _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__["default"] { /** * Unidirectionally synchronize OpenLayers vector layers to Cesium. * @param {!ol.Map} map * @param {!Cesium.Scene} scene * @param {olcs.FeatureConverter=} opt_converter * @extends {olcs.AbstractSynchronizer.} * @api */ constructor(map, scene, opt_converter) { super(map, scene); /** * @protected */ this.converter = opt_converter || new _FeatureConverter_js__WEBPACK_IMPORTED_MODULE_8__["default"](scene); /** * @private */ this.csAllPrimitives_ = new Cesium.PrimitiveCollection(); scene.primitives.add(this.csAllPrimitives_); this.csAllPrimitives_.destroyPrimitives = false; } /** * @inheritDoc */ addCesiumObject(counterpart) { console.assert(counterpart); counterpart.getRootPrimitive()['counterpart'] = counterpart; this.csAllPrimitives_.add(counterpart.getRootPrimitive()); } /** * @inheritDoc */ destroyCesiumObject(object) { object.getRootPrimitive().destroy(); } /** * @inheritDoc */ removeSingleCesiumObject(object, destroy) { object.destroy(); this.csAllPrimitives_.destroyPrimitives = destroy; this.csAllPrimitives_.remove(object.getRootPrimitive()); this.csAllPrimitives_.destroyPrimitives = false; } /** * @inheritDoc */ removeAllCesiumObjects(destroy) { this.csAllPrimitives_.destroyPrimitives = destroy; if (destroy) { for (let i = 0; i < this.csAllPrimitives_.length; ++i) { this.csAllPrimitives_.get(i)['counterpart'].destroy(); } } this.csAllPrimitives_.removeAll(); this.csAllPrimitives_.destroyPrimitives = false; } /** * Synchronizes the layer visibility properties * to the given Cesium Primitive. * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents * @param {!Cesium.Primitive} csPrimitive */ updateLayerVisibility(olLayerWithParents, csPrimitive) { let visible = true; [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayer) => { const layerVisible = olLayer.getVisible(); if (layerVisible !== undefined) { visible &= layerVisible; } else { visible = false; } }); csPrimitive.show = visible; } /** * @inheritDoc */ createSingleLayerCounterparts(olLayerWithParents) { const olLayer = olLayerWithParents.layer; if (!(olLayer instanceof (ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default())) || olLayer instanceof (ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6___default())) { return null; } console.assert(olLayer instanceof (ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1___default())); let source = olLayer.getSource(); if (source instanceof (ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2___default())) { source = source.getSource(); } if (!source) { return null; } console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0___default())); console.assert(this.view); const view = this.view; const featurePrimitiveMap = {}; const counterpart = this.converter.olVectorLayerToCesium(olLayer, view, featurePrimitiveMap); const csPrimitives = counterpart.getRootPrimitive(); const olListenKeys = counterpart.olListenKeys; [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => { olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(olLayerItem, 'change:visible', () => { this.updateLayerVisibility(olLayerWithParents, csPrimitives); })); }); this.updateLayerVisibility(olLayerWithParents, csPrimitives); const onAddFeature = (function(feature) { console.assert( (olLayer instanceof (ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default())) || (olLayer instanceof (ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3___default())) ); const context = counterpart.context; const prim = this.converter.convert(olLayer, view, feature, context); if (prim) { featurePrimitiveMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_4__.getUid)(feature)] = prim; csPrimitives.add(prim); } }).bind(this); const onRemoveFeature = (function(feature) { const id = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__.getUid)(feature); const context = counterpart.context; const bbs = context.featureToCesiumMap[id]; if (bbs) { delete context.featureToCesiumMap[id]; bbs.forEach((bb) => { if (bb instanceof Cesium.Billboard) { context.billboards.remove(bb); } }); } const csPrimitive = featurePrimitiveMap[id]; delete featurePrimitiveMap[id]; if (csPrimitive) { csPrimitives.remove(csPrimitive); } }).bind(this); olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'addfeature', (e) => { console.assert(e.feature); onAddFeature(e.feature); }, this)); olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'removefeature', (e) => { console.assert(e.feature); onRemoveFeature(e.feature); }, this)); olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'changefeature', (e) => { const feature = e.feature; console.assert(feature); onRemoveFeature(feature); onAddFeature(feature); }, this)); return counterpart ? [counterpart] : null; } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VectorSynchronizer); /***/ }), /***/ "./src/olcs/contrib/LazyLoader.js": /*!****************************************!*\ !*** ./src/olcs/contrib/LazyLoader.js ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ LazyLoader) /* harmony export */ }); /** * @module olcs.contrib.LazyLoader */ class LazyLoader { /** * @param {string} url * @api */ constructor(url) { /** * @type {Promise} * @protected */ this.promise; /** * @private * @type {string} */ this.url_ = url; } /** * @return {Promise} * @api */ load() { if (!this.promise) { // not yet loading this.promise = new Promise((resolve, reject) => { const script = document.createElement('script'); script.onload = () => resolve(); script.onerror = () => reject(); document.head.appendChild(script); script.src = this.url_; }); } return this.promise; } } /***/ }), /***/ "./src/olcs/contrib/Manager.js": /*!*************************************!*\ !*** ./src/olcs/contrib/Manager.js ***! \*************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../contrib/LazyLoader.js */ "./src/olcs/contrib/LazyLoader.js"); /* harmony import */ var _OLCesium_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../OLCesium.js */ "./src/olcs/OLCesium.js"); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../core.js */ "./src/olcs/core.js"); /* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math.js */ "./src/olcs/math.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_4__); /** * @module olcs.contrib.Manager */ /** * @typedef {Object} ManagerOptions * @property {import('ol/Map.js').default} map * @property {import('ol/extent.js').Extent} [cameraExtentInRadians] * @property {string} [cesiumIonDefaultAccessToken] */ const Manager = class extends (ol_Observable_js__WEBPACK_IMPORTED_MODULE_4___default()) { /** * @param {string} cesiumUrl * @param {olcsx.contrib.ManagerOptions} options * @api */ constructor(cesiumUrl, {map, cameraExtentInRadians, cesiumIonDefaultAccessToken} = {}) { super(); /** * @type {string} * @private */ this.cesiumUrl_ = cesiumUrl; /** * @type {ol.Map} * @protected */ this.map = map; /** * @type {ol.Extent} * @protected */ this.cameraExtentInRadians = cameraExtentInRadians || null; /** * @private * @type {Cesium.BoundingSphere} */ this.boundingSphere_; /** * @type {boolean} * @private */ this.blockLimiter_ = false; /** * @type {Promise.} * @private */ this.promise_; /** * @type {string} * @private */ this.cesiumIonDefaultAccessToken_ = cesiumIonDefaultAccessToken; /** * @type {olcs.OLCesium} * @protected */ this.ol3d; /** * @const {number} Tilt angle in radians * @private */ this.cesiumInitialTilt_ = (0,_math_js__WEBPACK_IMPORTED_MODULE_3__.toRadians)(50); /** * @protected * @type {number} */ this.fogDensity = 0.0001; /** * @protected * @type {number} */ this.fogSSEFactor = 25; /** * Limit the minimum distance to the terrain to 2m. * @protected * @type {number} */ this.minimumZoomDistance = 2; /** * Limit the maximum distance to the earth to 10'000km. * @protected * @type {number} */ this.maximumZoomDistance = 10000000; // when closer to 3000m, restrict the available positions harder /** * @protected * @param {number} height */ this.limitCameraToBoundingSphereRatio = height => (height > 3000 ? 9 : 3); } /** * @return {Promise.} */ load() { if (!this.promise_) { const cesiumLazyLoader = new _contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_0__["default"](this.cesiumUrl_); this.promise_ = cesiumLazyLoader.load().then(() => this.onCesiumLoaded()); } return this.promise_; } /** * @protected * @return {olcs.OLCesium} */ onCesiumLoaded() { if (this.cameraExtentInRadians) { const rect = new Cesium.Rectangle(...this.cameraExtentInRadians); // Set the fly home rectangle Cesium.Camera.DEFAULT_VIEW_RECTANGLE = rect; this.boundingSphere_ = Cesium.BoundingSphere.fromRectangle3D(rect, Cesium.Ellipsoid.WGS84, 300); // lux mean height is 300m } if (this.cesiumIonDefaultAccessToken_) { Cesium.Ion.defaultAccessToken = this.cesiumIonDefaultAccessToken_; } this.ol3d = this.instantiateOLCesium(); const scene = this.ol3d.getCesiumScene(); this.configureForUsability(scene); this.configureForPerformance(scene); this.dispatchEvent('load'); return this.ol3d; } /** * Application code should override this method. * @return {olcs.OLCesium} */ instantiateOLCesium() { console.assert(this.map); const ol3d = new _OLCesium_js__WEBPACK_IMPORTED_MODULE_1__["default"]({map: this.map}); const scene = ol3d.getCesiumScene(); const terrainProvider = Cesium.createWorldTerrain(); scene.terrainProvider = terrainProvider; return ol3d; } /** * @param {!Cesium.Scene} scene The scene, passed as parameter for convenience. * @protected */ configureForPerformance(scene) { const fog = scene.fog; fog.enabled = true; fog.density = this.fogDensity; fog.screenSpaceErrorFactor = this.fogSSEFactor; } /** * @param {!Cesium.Scene} scene The scene, passed as parameter for convenience. * @protected */ configureForUsability(scene) { const sscController = scene.screenSpaceCameraController; sscController.minimumZoomDistance = this.minimumZoomDistance; sscController.maximumZoomDistance = this.maximumZoomDistance; // Do not see through the terrain. Seeing through the terrain does not make // sense anyway, except for debugging scene.globe.depthTestAgainstTerrain = true; // Use white instead of the black default colour for the globe when tiles are missing scene.globe.baseColor = Cesium.Color.WHITE; scene.backgroundColor = Cesium.Color.WHITE; if (this.boundingSphere_) { scene.postRender.addEventListener(this.limitCameraToBoundingSphere.bind(this), scene); } // Stop rendering Cesium when there is nothing to do. This drastically reduces CPU/GPU consumption. this.ol3d.enableAutoRenderLoop(); } /** * Constrain the camera so that it stays close to the bounding sphere of the map extent. * Near the ground the allowed distance is shorter. * @protected */ limitCameraToBoundingSphere() { if (this.boundingSphere_ && !this.blockLimiter_) { const scene = this.ol3d.getCesiumScene(); const camera = scene.camera; const position = camera.position; const carto = Cesium.Cartographic.fromCartesian(position); const ratio = this.limitCameraToBoundingSphereRatio(carto.height); if (Cesium.Cartesian3.distance(this.boundingSphere_.center, position) > this.boundingSphere_.radius * ratio) { const currentlyFlying = camera.flying; if (currentlyFlying === true) { // There is a flying property and its value is true return; } else { this.blockLimiter_ = true; const unblockLimiter = () => this.blockLimiter_ = false; camera.flyToBoundingSphere(this.boundingSphere_, { complete: unblockLimiter, cancel: unblockLimiter }); } } } } /** * Enable or disable ol3d with a default animation. * @export * @return {Promise} */ toggle3d() { return this.load().then((/** @const {!olcs.OLCesium} */ ol3d) => { const is3DCurrentlyEnabled = ol3d.getEnabled(); const scene = ol3d.getCesiumScene(); if (is3DCurrentlyEnabled) { // Disable 3D console.assert(this.map); return _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].resetToNorthZenith(this.map, scene).then(() => { ol3d.setEnabled(false); this.dispatchEvent('toggle'); }); } else { // Enable 3D ol3d.setEnabled(true); this.dispatchEvent('toggle'); return _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].rotateAroundBottomCenter(scene, this.cesiumInitialTilt_); } }); } /** * Enable ol3d with a view built from parameters. * * @export * @param {number} lon * @param {number} lat * @param {number} elevation * @param {number} headingDeg Heading value in degrees. * @param {number} pitchDeg Pitch value in degrees. * @returns {Promise} */ set3dWithView(lon, lat, elevation, headingDeg, pitchDeg) { return this.load().then((/** @const {!olcs.OLCesium} */ ol3d) => { const is3DCurrentlyEnabled = ol3d.getEnabled(); const scene = ol3d.getCesiumScene(); const camera = scene.camera; const destination = Cesium.Cartesian3.fromDegrees(lon, lat, elevation); const heading = Cesium.Math.toRadians(headingDeg); const pitch = Cesium.Math.toRadians(pitchDeg); const roll = 0; const orientation = {heading, pitch, roll}; if (!is3DCurrentlyEnabled) { ol3d.setEnabled(true); this.dispatchEvent('toggle'); } camera.setView({ destination, orientation }); }); } /** * @export * @return {boolean} */ is3dEnabled() { return !!this.ol3d && this.ol3d.getEnabled(); } /** * @return {number} */ getHeading() { return this.map ? this.map.getView().getRotation() || 0 : 0; } /** * @return {number|undefined} */ getTiltOnGlobe() { const scene = this.ol3d.getCesiumScene(); const tiltOnGlobe = _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].computeSignedTiltAngleOnGlobe(scene); return -tiltOnGlobe; } /** * @param {number} angle */ setHeading(angle) { const scene = this.ol3d.getCesiumScene(); const bottom = _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].pickBottomPoint(scene); if (bottom) { _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].setHeadingUsingBottomCenter(scene, angle, bottom); } } /** * @export * @return {olcs.OLCesium} */ getOl3d() { return this.ol3d; } /** * @export * @return {!ol.View} */ getOlView() { const view = this.map.getView(); console.assert(view); return view; } /** * @export * @return {Cesium.Matrix4} */ getCesiumViewMatrix() { return this.ol3d.getCesiumScene().camera.viewMatrix; } /** * @export * @return {!Cesium.Scene} */ getCesiumScene() { return this.ol3d.getCesiumScene(); } /** * @export * @param {!Cesium.Rectangle} rectangle * @param {number=} offset in meters * @return {Promise} */ flyToRectangle(rectangle, offset = 0) { const camera = this.getCesiumScene().camera; const destination = camera.getRectangleCameraCoordinates(rectangle); const mag = Cesium.Cartesian3.magnitude(destination) + offset; Cesium.Cartesian3.normalize(destination, destination); Cesium.Cartesian3.multiplyByScalar(destination, mag, destination); return new Promise((resolve, reject) => { if (!this.cameraExtentInRadians) { reject(); return; } camera.flyTo({ destination, complete: () => resolve(), cancel: () => reject(), endTransform: Cesium.Matrix4.IDENTITY }); }); } /** * @protected * @return {Cesium.Rectangle|undefined} */ getCameraExtentRectangle() { if (this.cameraExtentInRadians) { return new Cesium.Rectangle(...this.cameraExtentInRadians); } } }; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Manager); /***/ }), /***/ "./src/olcs/core.js": /*!**************************!*\ !*** ./src/olcs/core.js ***! \**************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "attributionsFunctionToCredits": () => (/* binding */ attributionsFunctionToCredits), /* harmony export */ "calcDistanceForResolution": () => (/* binding */ calcDistanceForResolution), /* harmony export */ "calcResolutionForDistance": () => (/* binding */ calcResolutionForDistance), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_easing_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/easing.js */ "ol/easing.js"); /* harmony import */ var ol_easing_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_easing_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Tile.js */ "ol/layer/Tile.js"); /* harmony import */ var ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/layer/Image.js */ "ol/layer/Image.js"); /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/source/ImageStatic.js */ "ol/source/ImageStatic.js"); /* harmony import */ var ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4__); /* harmony import */ var ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/source/ImageWMS.js */ "ol/source/ImageWMS.js"); /* harmony import */ var ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/source/TileImage.js */ "ol/source/TileImage.js"); /* harmony import */ var ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6__); /* harmony import */ var ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ol/source/TileWMS.js */ "ol/source/TileWMS.js"); /* harmony import */ var ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7__); /* harmony import */ var ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ol/source/VectorTile.js */ "ol/source/VectorTile.js"); /* harmony import */ var ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8__); /* harmony import */ var ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ol/source/Image.js */ "ol/source/Image.js"); /* harmony import */ var ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__); /* harmony import */ var _core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./core/OLImageryProvider.js */ "./src/olcs/core/OLImageryProvider.js"); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js"); /* harmony import */ var _MVTImageryProvider_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./MVTImageryProvider.js */ "./src/olcs/MVTImageryProvider.js"); /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ol/layer/VectorTile.js */ "ol/layer/VectorTile.js"); /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13__); /* harmony import */ var ol_extent__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ol/extent */ "ol/extent"); /* harmony import */ var ol_extent__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(ol_extent__WEBPACK_IMPORTED_MODULE_14__); /** * @module olcs.core */ const exports = {}; /** * @typedef {Object} CesiumUrlDefinition * @property {string} url * @property {string} subdomains */ /** * Options for rotate around axis core function. * @typedef {Object} RotateAroundAxisOption * @property {number} [duration] * @property {function(number): number} [easing] * @property {function(): void} [callback] */ /** * @typedef {Object} LayerWithParents * @property {import('ol/layer/Base.js').default} layer * @property {Array} parents */ /** * Compute the pixel width and height of a point in meters using the * camera frustum. * @param {!Cesium.Scene} scene * @param {!Cesium.Cartesian3} target * @return {!Cesium.Cartesian2} the pixel size * @api */ exports.computePixelSizeAtCoordinate = function(scene, target) { const camera = scene.camera; const canvas = scene.canvas; const frustum = camera.frustum; const distance = Cesium.Cartesian3.magnitude(Cesium.Cartesian3.subtract( camera.position, target, new Cesium.Cartesian3())); return frustum.getPixelDimensions(canvas.clientWidth, canvas.clientHeight, distance, scene.pixelRatio, new Cesium.Cartesian2()); }; /** * Compute bounding box around a target point. * @param {!Cesium.Scene} scene * @param {!Cesium.Cartesian3} target * @param {number} amount Half the side of the box, in pixels. * @return {Array} bottom left and top right * coordinates of the box */ exports.computeBoundingBoxAtTarget = function(scene, target, amount) { const pixelSize = exports.computePixelSizeAtCoordinate(scene, target); const transform = Cesium.Transforms.eastNorthUpToFixedFrame(target); const bottomLeft = Cesium.Matrix4.multiplyByPoint( transform, new Cesium.Cartesian3(-pixelSize.x * amount, -pixelSize.y * amount, 0), new Cesium.Cartesian3()); const topRight = Cesium.Matrix4.multiplyByPoint( transform, new Cesium.Cartesian3(pixelSize.x * amount, pixelSize.y * amount, 0), new Cesium.Cartesian3()); return Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray( [bottomLeft, topRight]); }; /** * * @param {!ol.geom.Geometry} geometry * @param {number} height * @api */ exports.applyHeightOffsetToGeometry = function(geometry, height) { geometry.applyTransform((input, output, stride) => { console.assert(input === output); if (stride !== undefined && stride >= 3) { for (let i = 0; i < output.length; i += stride) { output[i + 2] = output[i + 2] + height; } } return output; }); }; /** * @param {ol.Coordinate} coordinates * @param {number=} rotation * @param {!Cesium.Cartesian3=} translation * @param {!Cesium.Cartesian3=} scale * @return {!Cesium.Matrix4} * @api */ exports.createMatrixAtCoordinates = function(coordinates, rotation = 0, translation = Cesium.Cartesian3.ZERO, scale = new Cesium.Cartesian3(1, 1, 1)) { const position = exports.ol4326CoordinateToCesiumCartesian(coordinates); const rawMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position); const quaternion = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, -rotation); const rotationMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(translation, quaternion, scale); return Cesium.Matrix4.multiply(rawMatrix, rotationMatrix, new Cesium.Matrix4()); }; /** * @param {!Cesium.Camera} camera * @param {number} angle * @param {!Cesium.Cartesian3} axis * @param {!Cesium.Matrix4} transform * @param {RotateAroundAxisOption=} opt_options * @api */ exports.rotateAroundAxis = function(camera, angle, axis, transform, opt_options) { const clamp = Cesium.Math.clamp; const defaultValue = Cesium.defaultValue; const options = opt_options || {}; const duration = defaultValue(options.duration, 500); // ms const easing = defaultValue(options.easing, ol_easing_js__WEBPACK_IMPORTED_MODULE_0__.linear); const callback = options.callback; let lastProgress = 0; const oldTransform = new Cesium.Matrix4(); const start = Date.now(); const step = function() { const timestamp = Date.now(); const timeDifference = timestamp - start; const progress = easing(clamp(timeDifference / duration, 0, 1)); console.assert(progress >= lastProgress); camera.transform.clone(oldTransform); const stepAngle = (progress - lastProgress) * angle; lastProgress = progress; camera.lookAtTransform(transform); camera.rotate(axis, stepAngle); camera.lookAtTransform(oldTransform); if (progress < 1) { window.requestAnimationFrame(step); } else { if (callback) { callback(); } } }; window.requestAnimationFrame(step); }; /** * @param {!Cesium.Scene} scene * @param {number} heading * @param {!Cesium.Cartesian3} bottomCenter * @param {RotateAroundAxisOption=} opt_options * @api */ exports.setHeadingUsingBottomCenter = function(scene, heading, bottomCenter, opt_options) { const camera = scene.camera; // Compute the camera position to zenith quaternion const angleToZenith = exports.computeAngleToZenith(scene, bottomCenter); const axis = camera.right; const quaternion = Cesium.Quaternion.fromAxisAngle(axis, angleToZenith); const rotation = Cesium.Matrix3.fromQuaternion(quaternion); // Get the zenith point from the rotation of the position vector const vector = new Cesium.Cartesian3(); Cesium.Cartesian3.subtract(camera.position, bottomCenter, vector); const zenith = new Cesium.Cartesian3(); Cesium.Matrix3.multiplyByVector(rotation, vector, zenith); Cesium.Cartesian3.add(zenith, bottomCenter, zenith); // Actually rotate around the zenith normal const transform = Cesium.Matrix4.fromTranslation(zenith); const rotateAroundAxis = exports.rotateAroundAxis; rotateAroundAxis(camera, heading, zenith, transform, opt_options); }; /** * Get the 3D position of the given pixel of the canvas. * @param {!Cesium.Scene} scene * @param {!Cesium.Cartesian2} pixel * @return {!Cesium.Cartesian3|undefined} * @api */ exports.pickOnTerrainOrEllipsoid = function(scene, pixel) { const ray = scene.camera.getPickRay(pixel); const target = scene.globe.pick(ray, scene); return target || scene.camera.pickEllipsoid(pixel); }; /** * Get the 3D position of the point at the bottom-center of the screen. * @param {!Cesium.Scene} scene * @return {!Cesium.Cartesian3|undefined} * @api */ exports.pickBottomPoint = function(scene) { const canvas = scene.canvas; const bottom = new Cesium.Cartesian2( canvas.clientWidth / 2, canvas.clientHeight); return exports.pickOnTerrainOrEllipsoid(scene, bottom); }; /** * Get the 3D position of the point at the center of the screen. * @param {!Cesium.Scene} scene * @return {!Cesium.Cartesian3|undefined} * @api */ exports.pickCenterPoint = function(scene) { const canvas = scene.canvas; const center = new Cesium.Cartesian2( canvas.clientWidth / 2, canvas.clientHeight / 2); return exports.pickOnTerrainOrEllipsoid(scene, center); }; /** * Compute the signed tilt angle on globe, between the opposite of the * camera direction and the target normal. Return undefined if there is no * intersection of the camera direction with the globe. * @param {!Cesium.Scene} scene * @return {number|undefined} * @api */ exports.computeSignedTiltAngleOnGlobe = function(scene) { const camera = scene.camera; const ray = new Cesium.Ray(camera.position, camera.direction); let target = scene.globe.pick(ray, scene); if (!target) { // no tiles in the area were loaded? const ellipsoid = Cesium.Ellipsoid.WGS84; const obj = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid); if (obj) { target = Cesium.Ray.getPoint(ray, obj.start); } } if (!target) { return undefined; } const normal = new Cesium.Cartesian3(); Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(target, normal); const angleBetween = exports.signedAngleBetween; const angle = angleBetween(camera.direction, normal, camera.right) - Math.PI; return Cesium.Math.convertLongitudeRange(angle); }; /** * Compute the ray from the camera to the bottom-center of the screen. * @param {!Cesium.Scene} scene * @return {!Cesium.Ray} */ exports.bottomFovRay = function(scene) { const camera = scene.camera; const fovy2 = camera.frustum.fovy / 2; const direction = camera.direction; const rotation = Cesium.Quaternion.fromAxisAngle(camera.right, fovy2); const matrix = Cesium.Matrix3.fromQuaternion(rotation); const vector = new Cesium.Cartesian3(); Cesium.Matrix3.multiplyByVector(matrix, direction, vector); return new Cesium.Ray(camera.position, vector); }; /** * Compute the angle between two Cartesian3. * @param {!Cesium.Cartesian3} first * @param {!Cesium.Cartesian3} second * @param {!Cesium.Cartesian3} normal Normal to test orientation against. * @return {number} */ exports.signedAngleBetween = function(first, second, normal) { // We are using the dot for the angle. // Then the cross and the dot for the sign. const a = new Cesium.Cartesian3(); const b = new Cesium.Cartesian3(); const c = new Cesium.Cartesian3(); Cesium.Cartesian3.normalize(first, a); Cesium.Cartesian3.normalize(second, b); Cesium.Cartesian3.cross(a, b, c); const cosine = Cesium.Cartesian3.dot(a, b); const sine = Cesium.Cartesian3.magnitude(c); // Sign of the vector product and the orientation normal const sign = Cesium.Cartesian3.dot(normal, c); const angle = Math.atan2(sine, cosine); return sign >= 0 ? angle : -angle; }; /** * Compute the rotation angle around a given point, needed to reach the * zenith position. * At a zenith position, the camera direction is going througth the earth * center and the frustrum bottom ray is going through the chosen pivot * point. * The bottom-center of the screen is a good candidate for the pivot point. * @param {!Cesium.Scene} scene * @param {!Cesium.Cartesian3} pivot Point around which the camera rotates. * @return {number} * @api */ exports.computeAngleToZenith = function(scene, pivot) { // This angle is the sum of the angles 'fy' and 'a', which are defined // using the pivot point and its surface normal. // Zenith | camera // \ | / // \fy| / // \ |a/ // \|/pivot const camera = scene.camera; const fy = camera.frustum.fovy / 2; const ray = exports.bottomFovRay(scene); const direction = Cesium.Cartesian3.clone(ray.direction); Cesium.Cartesian3.negate(direction, direction); const normal = new Cesium.Cartesian3(); Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(pivot, normal); const left = new Cesium.Cartesian3(); Cesium.Cartesian3.negate(camera.right, left); const a = exports.signedAngleBetween(normal, direction, left); return a + fy; }; /** * Convert an OpenLayers extent to a Cesium rectangle. * @param {ol.Extent} extent Extent. * @param {ol.ProjectionLike} projection Extent projection. * @return {Cesium.Rectangle} The corresponding Cesium rectangle. * @api */ exports.extentToRectangle = function(extent, projection) { if (extent && projection) { const ext = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.transformExtent)(extent, projection, 'EPSG:4326'); return Cesium.Rectangle.fromDegrees(ext[0], ext[1], ext[2], ext[3]); } else { return null; } }; /** * @param {!ol.Map} olMap * @param {!ol.source.Source} source * @param {!ol.View} viewProj * @param {!ol.layer.Base} olLayer * @return {!Cesium.ImageryProvider} */ exports.sourceToImageryProvider = function(olMap, source, viewProj, olLayer) { const skip = source.get('olcs_skip'); if (skip) { return null; } let provider = null; // Convert ImageWMS to TileWMS if (source instanceof (ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5___default()) && source.getUrl() && source.getImageLoadFunction() === ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__.defaultImageLoadFunction) { const sourceProps = { 'olcs.proxy': source.get('olcs.proxy'), 'olcs.extent': source.get('olcs.extent'), 'olcs.projection': source.get('olcs.projection'), 'olcs.imagesource': source }; source = new (ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7___default())({ url: source.getUrl(), attributions: source.getAttributions(), projection: source.getProjection(), params: source.getParams() }); source.setProperties(sourceProps); } if (source instanceof (ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6___default())) { let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source); if (!projection) { // if not explicit, assume the same projection as view projection = viewProj; } if (exports.isCesiumProjection(projection)) { provider = new _core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_10__["default"](olMap, source, viewProj); } // Projection not supported by Cesium else { return null; } } else if (source instanceof (ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4___default())) { let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source); if (!projection) { projection = viewProj; } if (exports.isCesiumProjection(projection)) { provider = new Cesium.SingleTileImageryProvider({ url: source.getUrl(), rectangle: new Cesium.Rectangle.fromDegrees( source.getImageExtent()[0], source.getImageExtent()[1], source.getImageExtent()[2], source.getImageExtent()[3] ) }); } // Projection not supported by Cesium else { return null; } } else if (source instanceof (ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8___default())) { let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source); if (!projection) { projection = viewProj; } if (skip === false) { // MVT is experimental, it should be whitelisted to be synchronized const fromCode = projection.getCode().split(':')[1]; const urls = source.urls.map(u => u.replace(fromCode, '3857')); const extent = olLayer.getExtent(); const rectangle = exports.extentToRectangle(extent, projection); const minimumLevel = source.get('olcs_minimumLevel'); const attributionsFunction = source.getAttributions(); const styleFunction = olLayer.getStyleFunction(); let credit; if (extent && attributionsFunction) { const center = (0,ol_extent__WEBPACK_IMPORTED_MODULE_14__.getCenter)(extent); credit = attributionsFunctionToCredits(attributionsFunction, 0, center, extent)[0]; } provider = new _MVTImageryProvider_js__WEBPACK_IMPORTED_MODULE_12__["default"]({ credit, rectangle, minimumLevel, styleFunction, urls }); return provider; } return null; // FIXME: it is disabled by default right now } else { // sources other than TileImage|ImageStatic are currently not supported return null; } return provider; }; /** * Creates Cesium.ImageryLayer best corresponding to the given ol.layer.Layer. * Only supports raster layers and static images * @param {!ol.Map} olMap * @param {!ol.layer.Base} olLayer * @param {!ol.proj.Projection} viewProj Projection of the view. * @return {?Cesium.ImageryLayer} null if not possible (or supported) * @api */ exports.tileLayerToImageryLayer = function(olMap, olLayer, viewProj) { if (!(olLayer instanceof (ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1___default())) && !(olLayer instanceof (ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2___default())) && !(olLayer instanceof (ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13___default()))) { return null; } const source = olLayer.getSource(); if (!source) { return null; } let provider = source.get('olcs_provider'); if (!provider) { provider = this.sourceToImageryProvider(olMap, source, viewProj, olLayer); } if (!provider) { return null; } const layerOptions = {}; const forcedExtent = /** @type {ol.Extent} */ (olLayer.get('olcs.extent')); const ext = forcedExtent || olLayer.getExtent(); if (ext) { layerOptions.rectangle = exports.extentToRectangle(ext, viewProj); } const cesiumLayer = new Cesium.ImageryLayer(provider, layerOptions); return cesiumLayer; }; /** * Synchronizes the layer rendering properties (opacity, visible) * to the given Cesium ImageryLayer. * @param {olcsx.LayerWithParents} olLayerWithParents * @param {!Cesium.ImageryLayer} csLayer * @api */ exports.updateCesiumLayerProperties = function(olLayerWithParents, csLayer) { let opacity = 1; let visible = true; [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayer) => { const layerOpacity = olLayer.getOpacity(); if (layerOpacity !== undefined) { opacity *= layerOpacity; } const layerVisible = olLayer.getVisible(); if (layerVisible !== undefined) { visible &= layerVisible; } }); csLayer.alpha = opacity; csLayer.show = visible; }; /** * Convert a 2D or 3D OpenLayers coordinate to Cesium. * @param {ol.Coordinate} coordinate Ol3 coordinate. * @return {!Cesium.Cartesian3} Cesium cartesian coordinate * @api */ exports.ol4326CoordinateToCesiumCartesian = function(coordinate) { const coo = coordinate; return coo.length > 2 ? Cesium.Cartesian3.fromDegrees(coo[0], coo[1], coo[2]) : Cesium.Cartesian3.fromDegrees(coo[0], coo[1]); }; /** * Convert an array of 2D or 3D OpenLayers coordinates to Cesium. * @param {Array.} coordinates Ol3 coordinates. * @return {!Array.} Cesium cartesian coordinates * @api */ exports.ol4326CoordinateArrayToCsCartesians = function(coordinates) { console.assert(coordinates !== null); const toCartesian = exports.ol4326CoordinateToCesiumCartesian; const cartesians = []; for (let i = 0; i < coordinates.length; ++i) { cartesians.push(toCartesian(coordinates[i])); } return cartesians; }; /** * Reproject an OpenLayers geometry to EPSG:4326 if needed. * The geometry will be cloned only when original projection is not EPSG:4326 * and the properties will be shallow copied. * @param {!T} geometry * @param {!ol.ProjectionLike} projection * @return {!T} * @template T * @api */ exports.olGeometryCloneTo4326 = function(geometry, projection) { console.assert(projection); const proj4326 = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:4326'); const proj = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)(projection); if (proj !== proj4326) { const properties = geometry.getProperties(); geometry = geometry.clone(); geometry.transform(proj, proj4326); geometry.setProperties(properties); } return geometry; }; /** * Convert an OpenLayers color to Cesium. * @param {ol.Color|CanvasGradient|CanvasPattern|string} olColor * @return {!Cesium.Color} * @api */ exports.convertColorToCesium = function(olColor) { olColor = olColor || 'black'; if (Array.isArray(olColor)) { return new Cesium.Color( Cesium.Color.byteToFloat(olColor[0]), Cesium.Color.byteToFloat(olColor[1]), Cesium.Color.byteToFloat(olColor[2]), olColor[3] ); } else if (typeof olColor == 'string') { return Cesium.Color.fromCssColorString(olColor); } else if (olColor instanceof CanvasPattern || olColor instanceof CanvasGradient) { // Render the CanvasPattern/CanvasGradient into a canvas that will be sent to Cesium as material const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = canvas.height = 256; ctx.fillStyle = olColor; ctx.fillRect(0, 0, canvas.width, canvas.height); return new Cesium.ImageMaterialProperty({ image: canvas }); } console.assert(false, 'impossible'); }; /** * Convert an OpenLayers url to Cesium. * @param {string} url * @return {!CesiumUrlDefinition} * @api */ exports.convertUrlToCesium = function(url) { let subdomains = ''; const re = /\{(\d|[a-z])-(\d|[a-z])\}/; const match = re.exec(url); if (match) { url = url.replace(re, '{s}'); const startCharCode = match[1].charCodeAt(0); const stopCharCode = match[2].charCodeAt(0); let charCode; for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) { subdomains += String.fromCharCode(charCode); } } return { url, subdomains }; }; /** * Animate the return to a top-down view from the zenith. * The camera is rotated to orient to the North. * @param {!ol.Map} map * @param {!Cesium.Scene} scene * @return {Promise} * @api */ exports.resetToNorthZenith = function(map, scene) { return new Promise((resolve, reject) => { const camera = scene.camera; const pivot = exports.pickBottomPoint(scene); if (!pivot) { reject('Could not get bottom pivot'); return; } const currentHeading = map.getView().getRotation(); if (currentHeading === undefined) { reject('The view is not initialized'); return; } const angle = exports.computeAngleToZenith(scene, pivot); // Point to North exports.setHeadingUsingBottomCenter(scene, currentHeading, pivot); // Go to zenith const transform = Cesium.Matrix4.fromTranslation(pivot); const axis = camera.right; const options = { callback: () => { const view = map.getView(); exports.normalizeView(view); resolve(); } }; exports.rotateAroundAxis(camera, -angle, axis, transform, options); }); }; /** * @param {!Cesium.Scene} scene * @param {number} angle in radian * @return {Promise} * @api */ exports.rotateAroundBottomCenter = function(scene, angle) { return new Promise((resolve, reject) => { const camera = scene.camera; const pivot = exports.pickBottomPoint(scene); if (!pivot) { reject('could not get bottom pivot'); return; } const options = {callback: resolve}; const transform = Cesium.Matrix4.fromTranslation(pivot); const axis = camera.right; const rotateAroundAxis = exports.rotateAroundAxis; rotateAroundAxis(camera, -angle, axis, transform, options); }); }; /** * Set the OpenLayers view to a specific rotation and * the nearest resolution. * @param {ol.View} view * @param {number=} angle * @api */ exports.normalizeView = function(view, angle = 0) { const resolution = view.getResolution(); view.setRotation(angle); if (view.constrainResolution) { view.setResolution(view.constrainResolution(resolution)); } else { view.setResolution(view.getConstrainedResolution(resolution)); } }; /** * Check if the given projection is managed by Cesium (WGS84 or Mercator Spheric) * * @param {ol.proj.Projection} projection Projection to check. * @returns {boolean} Whether it's managed by Cesium. */ exports.isCesiumProjection = function(projection) { const is3857 = projection === (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:3857'); const is4326 = projection === (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:4326'); return is3857 || is4326; }; function attributionsFunctionToCredits(attributionsFunction, zoom, center, extent) { const frameState = { viewState: {zoom, center}, extent, }; if (!attributionsFunction) { return []; } let attributions = attributionsFunction(frameState); if (!Array.isArray(attributions)) { attributions = [attributions]; } return attributions.map(html => new Cesium.Credit(html, true)); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (exports); /** * calculate the distance between camera and centerpoint based on the resolution and latitude value * @param {number} resolution Number of map units per pixel. * @param {number} latitude Latitude in radians. * @param {import('cesium').Scene} scene. * @param {import('ol/proj/Projection').default} projection View projection. * @return {number} The calculated distance. * @api */ function calcDistanceForResolution(resolution, latitude, scene, projection) { const canvas = scene.canvas; const camera = scene.camera; const fovy = camera.frustum.fovy; // vertical field of view console.assert(!isNaN(fovy)); const metersPerUnit = projection.getMetersPerUnit(); // number of "map units" visible in 2D (vertically) const visibleMapUnits = resolution * canvas.clientHeight; // The metersPerUnit does not take latitude into account, but it should // be lower with increasing latitude -- we have to compensate. // In 3D it is not possible to maintain the resolution at more than one point, // so it only makes sense to use the latitude of the "target" point. const relativeCircumference = Math.cos(Math.abs(latitude)); // how many meters should be visible in 3D const visibleMeters = visibleMapUnits * metersPerUnit * relativeCircumference; // distance required to view the calculated length in meters // // fovy/2 // |\ // x | \ // |--\ // visibleMeters/2 const requiredDistance = (visibleMeters / 2) / Math.tan(fovy / 2); // NOTE: This calculation is not absolutely precise, because metersPerUnit // is a great simplification. It does not take ellipsoid/terrain into account. return requiredDistance; } /** * calculate the resolution based on a distance(camera to position) and latitude value * @param {number} distance * @param {number} latitude * @param {import('cesium').Scene} scene. * @param {import('ol/proj/Projection').default} projection View projection. * @return {number} The calculated resolution. * @api */ function calcResolutionForDistance(distance, latitude, scene, projection) { // See the reverse calculation (calcDistanceForResolution) for details const canvas = scene.canvas; const camera = scene.camera; const fovy = camera.frustum.fovy; // vertical field of view console.assert(!isNaN(fovy)); const metersPerUnit = projection.getMetersPerUnit(); const visibleMeters = 2 * distance * Math.tan(fovy / 2); const relativeCircumference = Math.cos(Math.abs(latitude)); const visibleMapUnits = visibleMeters / metersPerUnit / relativeCircumference; const resolution = visibleMapUnits / canvas.clientHeight; return resolution; } /***/ }), /***/ "./src/olcs/core/OLImageryProvider.js": /*!********************************************!*\ !*** ./src/olcs/core/OLImageryProvider.js ***! \********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js"); /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util.js */ "./src/olcs/util.js"); /* harmony import */ var ol_source_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source.js */ "ol/source.js"); /* harmony import */ var ol_source_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../core.js */ "./src/olcs/core.js"); /** * @module olcs.core.OLImageryProvider */ const olUseNewCoordinates = (function() { const tileSource = new ol_source_js__WEBPACK_IMPORTED_MODULE_2__.Tile({ projection: 'EPSG:3857', wrapX: true }); const tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]); return tileCoord && tileCoord[1] === 33 && tileCoord[2] === 22; // See b/test/spec/ol/source/tile.test.js // of e9a30c5cb7e3721d9370025fbe5472c322847b35 in OpenLayers repository })(); class OLImageryProvider /* should not extend Cesium.ImageryProvider */ { /** * Special class derived from Cesium.ImageryProvider * that is connected to the given ol.source.TileImage. * @param {!ol.Map} olMap * @param {!ol.source.TileImage} source * @param {ol.proj.Projection=} opt_fallbackProj Projection to assume if the * projection of the source is not defined. * @constructor * @extends {Cesium.ImageryProvider} */ constructor(olMap, source, opt_fallbackProj) { // Do not extend or call super constructor from // Cesium.ImageryProvider since this particular function is a // 'non instanciable interface' which throws on instanciation. /** * @type {!ol.source.TileImage} * @private */ this.source_ = source; /** * @type {?ol.proj.Projection} * @private */ this.projection_ = null; /** * @type {?ol.proj.Projection} * @private */ this.fallbackProj_ = opt_fallbackProj || null; /** * @type {boolean} * @private */ this.ready_ = false; /** * @type {?Cesium.TilingScheme} * @private */ this.tilingScheme_ = null; /** * @type {?Cesium.Rectangle} * @private */ this.rectangle_ = null; /** * @type {!ol.Map} * @private */ this.map_ = olMap; /** * @type {boolean} * @private */ this.shouldRequestNextLevel = false; const proxy = this.source_.get('olcs.proxy'); if (proxy) { if (typeof proxy === 'function') { this.proxy_ = { 'getURL': proxy }; } else if (typeof proxy === 'string') { this.proxy_ = new Cesium.DefaultProxy(proxy); } } this.errorEvent_ = new Cesium.Event(); this.emptyCanvas_ = document.createElement('canvas'); this.emptyCanvas_.width = 1; this.emptyCanvas_.height = 1; this.source_.on('change', (e) => { this.handleSourceChanged_(); }); this.handleSourceChanged_(); } /** * Checks if the underlying source is ready and cached required data. * @private */ handleSourceChanged_(frameState) { if (!this.ready_ && this.source_.getState() == 'ready') { this.projection_ = _util_js__WEBPACK_IMPORTED_MODULE_1__["default"].getSourceProjection(this.source_) || this.fallbackProj_; const options = {numberOfLevelZeroTilesX: 1, numberOfLevelZeroTilesY: 1}; if (this.source_.tileGrid !== null) { // Get the number of tiles at level 0 if it is defined this.source_.tileGrid.forEachTileCoord(this.projection_.getExtent(), 0, ([zoom, xIndex, yIndex]) => { options.numberOfLevelZeroTilesX = xIndex + 1; options.numberOfLevelZeroTilesY = yIndex + 1; }); } if (this.projection_ == (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_0__.get)('EPSG:4326')) { // Cesium zoom level 0 is OpenLayers zoom level 1 for layer in EPSG:4326 with a single tile on level 0 this.shouldRequestNextLevel = options.numberOfLevelZeroTilesX === 1 && options.numberOfLevelZeroTilesY === 1; this.tilingScheme_ = new Cesium.GeographicTilingScheme(options); } else if (this.projection_ == (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_0__.get)('EPSG:3857')) { this.shouldRequestNextLevel = false; this.tilingScheme_ = new Cesium.WebMercatorTilingScheme(options); } else { return; } this.rectangle_ = this.tilingScheme_.rectangle; this.ready_ = true; } } /** * Generates the proper attributions for a given position and zoom * level. * @export * @override */ getTileCredits(x, y, level) { const attributionsFunction = this.source_.getAttributions(); if (!attributionsFunction) { return []; } const extent = this.map_.getView().calculateExtent(this.map_.getSize()); const center = this.map_.getView().getCenter(); const zoom = this.shouldRequestNextLevel ? level + 1 : level; return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.attributionsFunctionToCredits)(attributionsFunction, zoom, center, extent); } /** * @export * @override */ requestImage(x, y, level) { const tileUrlFunction = this.source_.getTileUrlFunction(); if (tileUrlFunction && this.projection_) { const z_ = this.shouldRequestNextLevel ? level + 1 : level; let y_ = y; if (!olUseNewCoordinates) { // OpenLayers version 3 to 5 tile coordinates increase from bottom to top y_ = -y - 1; } let url = tileUrlFunction.call(this.source_, [z_, x, y_], 1, this.projection_); if (this.proxy_) { url = this.proxy_.getURL(url); } return url ? Cesium.ImageryProvider.loadImage(this, url) : this.emptyCanvas_; } else { // return empty canvas to stop Cesium from retrying later return this.emptyCanvas_; } } } // definitions of getters that are required to be present // in the Cesium.ImageryProvider instance: Object.defineProperties(OLImageryProvider.prototype, { 'ready': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() {return this.ready_;} }, 'rectangle': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() {return this.rectangle_;} }, 'tileWidth': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() { const tg = this.source_.getTileGrid(); return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[0] : tg.getTileSize(0)) : 256; } }, 'tileHeight': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() { const tg = this.source_.getTileGrid(); return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[1] : tg.getTileSize(0)) : 256; } }, 'maximumLevel': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() { const tg = this.source_.getTileGrid(); return tg ? tg.getMaxZoom() : 18; } }, 'minimumLevel': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() { // WARNING: Do not use the minimum level (at least until the extent is // properly set). Cesium assumes the minimumLevel to contain only // a few tiles and tries to load them all at once -- this can // freeze and/or crash the browser ! return 0; //var tg = this.source_.getTileGrid(); //return tg ? tg.getMinZoom() : 0; } }, 'tilingScheme': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() {return this.tilingScheme_;} }, 'tileDiscardPolicy': { 'get': function() {return undefined;} }, 'errorEvent': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() {return this.errorEvent_;} }, 'proxy': { 'get': /** @this {olcs.core.OLImageryProvider} */ function() {return this.proxy_;} }, 'hasAlphaChannel': { 'get': function() {return true;} }, 'pickFeatures': { 'get': function() {return undefined;} } }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OLImageryProvider); /***/ }), /***/ "./src/olcs/core/VectorLayerCounterpart.js": /*!*************************************************!*\ !*** ./src/olcs/core/VectorLayerCounterpart.js ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js"); /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__); /** * @module olcs.core.VectorLayerCounterpart */ /** * Context for feature conversion. * @typedef {Object} OlFeatureToCesiumContext * @property {!(import('ol/Projection.js').default|string)} projection * @property {!Cesium.PrimitiveCollection} primitives * @property {Object>} featureToCesiumMap * @property {!Cesium.BillboardCollection} billboards */ class VectorLayerCounterpart { /** * Result of the conversion of an OpenLayers layer to Cesium. * @param {!(ol.proj.Projection|string)} layerProjection * @param {!Cesium.Scene} scene */ constructor(layerProjection, scene) { const billboards = new Cesium.BillboardCollection({scene}); const primitives = new Cesium.PrimitiveCollection(); /** * @type {!Array.} */ this.olListenKeys = []; this.rootCollection_ = new Cesium.PrimitiveCollection(); /** * @type {!OlFeatureToCesiumContext} */ this.context = { projection: layerProjection, billboards, featureToCesiumMap: {}, primitives }; this.rootCollection_.add(billboards); this.rootCollection_.add(primitives); } /** * Unlisten. */ destroy() { this.olListenKeys.forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey); this.olListenKeys.length = 0; } /** * @return {!Cesium.Primitive} */ getRootPrimitive() { return this.rootCollection_; } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VectorLayerCounterpart); /***/ }), /***/ "./src/olcs/math.js": /*!**************************!*\ !*** ./src/olcs/math.js ***! \**************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "toDegrees": () => (/* binding */ toDegrees), /* harmony export */ "toRadians": () => (/* binding */ toRadians) /* harmony export */ }); /** * Converts radians to to degrees. * * @param {number} angleInRadians Angle in radians. * @return {number} Angle in degrees. */ function toDegrees(angleInRadians) { return angleInRadians * 180 / Math.PI; } /** * Converts degrees to radians. * * @param {number} angleInDegrees Angle in degrees. * @return {number} Angle in radians. */ function toRadians(angleInDegrees) { return angleInDegrees * Math.PI / 180; } /***/ }), /***/ "./src/olcs/util.js": /*!**************************!*\ !*** ./src/olcs/util.js ***! \**************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ "getUid": () => (/* binding */ getUid), /* harmony export */ "isGroundPolylinePrimitiveSupported": () => (/* binding */ isGroundPolylinePrimitiveSupported), /* harmony export */ "olcsListen": () => (/* binding */ olcsListen), /* harmony export */ "removeChildren": () => (/* binding */ removeChildren), /* harmony export */ "removeNode": () => (/* binding */ removeNode), /* harmony export */ "stableSort": () => (/* binding */ stableSort) /* harmony export */ }); /** * @module olcs.util */ const exports = {}; /** * Cast to object. * @param {Object} param * @return {Object} */ exports.obj = function(param) { return param; }; /** * @type {boolean|undefined} * @private */ exports.supportsImageRenderingPixelatedResult_ = undefined; /** * @type {string|undefined} * @private */ exports.imageRenderingValueResult_ = undefined; /** * @return {boolean} */ exports.supportsImageRenderingPixelated = function() { if (exports.supportsImageRenderingPixelatedResult_ === undefined) { const canvas = document.createElement('canvas'); canvas.setAttribute('style', 'image-rendering: -moz-crisp-edges; image-rendering: pixelated;'); // canvas.style.imageRendering will be undefined, null or an // empty string on unsupported browsers. const tmp = canvas.style['imageRendering']; // non standard exports.supportsImageRenderingPixelatedResult_ = !!tmp; if (exports.supportsImageRenderingPixelatedResult_) { exports.imageRenderingValueResult_ = tmp; } } return exports.supportsImageRenderingPixelatedResult_; }; /** * @return {string} */ exports.imageRenderingValue = function() { exports.supportsImageRenderingPixelated(); return exports.imageRenderingValueResult_ || ''; }; /** * Return the projection of the source that Cesium should use. * * @param {ol.source.Source} source Source. * @returns {ol.proj.Projection} The projection of the source. */ exports.getSourceProjection = function(source) { return /** @type {ol.proj.Projection} */ (source.get('olcs.projection')) || source.getProjection(); }; /** * @param {ol.Observable} observable * @param {string} type * @param {Function} listener * @return {!ol.events.EventsKey} */ function olcsListen(observable, type, listener) { // See https://github.com/openlayers/openlayers/pull/8481 // ol.events.listen is internal so we use `on` instead. // And since `on` as a convoluted API (can return an EventsKey or an array of them) // we use a cast here. return /** @type {!ol.events.EventsKey} */ (observable.on(type, listener)); } /** * Counter for getUid. * @type {number} */ let uidCounter_ = 0; /** * Gets a unique ID for an object. This mutates the object so that further calls * with the same object as a parameter returns the same value. Unique IDs are generated * as a strictly increasing sequence. Adapted from goog.getUid. * * @param {Object} obj The object to get the unique ID for. * @return {number} The unique ID for the object. */ function getUid(obj) { return obj.olcs_uid || (obj.olcs_uid = ++uidCounter_); } /** * Sort the passed array such that the relative order of equal elements is preverved. * See https://en.wikipedia.org/wiki/Sorting_algorithm#Stability for details. * @param {Array<*>} arr The array to sort (modifies original). * @param {!function(*, *): number} compareFnc Comparison function. */ function stableSort(arr, compareFnc) { const length = arr.length; const tmp = Array(arr.length); for (let i = 0; i < length; i++) { tmp[i] = {index: i, value: arr[i]}; } tmp.sort((a, b) => compareFnc(a.value, b.value) || a.index - b.index); for (let i = 0; i < arr.length; i++) { arr[i] = tmp[i].value; } } /** * @param {Node} node The node to remove. * @returns {Node} The node that was removed or null. */ function removeNode(node) { return node && node.parentNode ? node.parentNode.removeChild(node) : null; } /** * @param {Node} node The node to remove the children from. */ function removeChildren(node) { while (node.lastChild) { node.removeChild(node.lastChild); } } /** * @param {Cesium.Scene} scene The scene. */ function isGroundPolylinePrimitiveSupported(scene) { const obj = Cesium.GroundPolylinePrimitive; return obj && obj.isSupported(scene); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (exports); /***/ }), /***/ "ol/Observable.js": /*!********************************!*\ !*** external "ol.Observable" ***! \********************************/ /***/ ((module) => { module.exports = ol.Observable; /***/ }), /***/ "ol/Overlay.js": /*!*****************************!*\ !*** external "ol.Overlay" ***! \*****************************/ /***/ ((module) => { module.exports = ol.Overlay; /***/ }), /***/ "ol/easing.js": /*!****************************!*\ !*** external "ol.easing" ***! \****************************/ /***/ ((module) => { module.exports = ol.easing; /***/ }), /***/ "ol/extent": /*!****************************!*\ !*** external "ol.extent" ***! \****************************/ /***/ ((module) => { module.exports = ol.extent; /***/ }), /***/ "ol/format/MVT.js": /*!********************************!*\ !*** external "ol.format.MVT" ***! \********************************/ /***/ ((module) => { module.exports = ol.format.MVT; /***/ }), /***/ "ol/geom/Geometry.js": /*!***********************************!*\ !*** external "ol.geom.Geometry" ***! \***********************************/ /***/ ((module) => { module.exports = ol.geom.Geometry; /***/ }), /***/ "ol/geom/Point.js": /*!********************************!*\ !*** external "ol.geom.Point" ***! \********************************/ /***/ ((module) => { module.exports = ol.geom.Point; /***/ }), /***/ "ol/geom/Polygon.js": /*!**********************************!*\ !*** external "ol.geom.Polygon" ***! \**********************************/ /***/ ((module) => { module.exports = ol.geom.Polygon; /***/ }), /***/ "ol/geom/SimpleGeometry.js": /*!*****************************************!*\ !*** external "ol.geom.SimpleGeometry" ***! \*****************************************/ /***/ ((module) => { module.exports = ol.geom.SimpleGeometry; /***/ }), /***/ "ol/layer/Group.js": /*!*********************************!*\ !*** external "ol.layer.Group" ***! \*********************************/ /***/ ((module) => { module.exports = ol.layer.Group; /***/ }), /***/ "ol/layer/Image.js": /*!*********************************!*\ !*** external "ol.layer.Image" ***! \*********************************/ /***/ ((module) => { module.exports = ol.layer.Image; /***/ }), /***/ "ol/layer/Layer.js": /*!*********************************!*\ !*** external "ol.layer.Layer" ***! \*********************************/ /***/ ((module) => { module.exports = ol.layer.Layer; /***/ }), /***/ "ol/layer/Tile.js": /*!********************************!*\ !*** external "ol.layer.Tile" ***! \********************************/ /***/ ((module) => { module.exports = ol.layer.Tile; /***/ }), /***/ "ol/layer/Vector.js": /*!**********************************!*\ !*** external "ol.layer.Vector" ***! \**********************************/ /***/ ((module) => { module.exports = ol.layer.Vector; /***/ }), /***/ "ol/layer/VectorTile.js": /*!**************************************!*\ !*** external "ol.layer.VectorTile" ***! \**************************************/ /***/ ((module) => { module.exports = ol.layer.VectorTile; /***/ }), /***/ "ol/proj.js": /*!**************************!*\ !*** external "ol.proj" ***! \**************************/ /***/ ((module) => { module.exports = ol.proj; /***/ }), /***/ "ol/render.js": /*!****************************!*\ !*** external "ol.render" ***! \****************************/ /***/ ((module) => { module.exports = ol.render; /***/ }), /***/ "ol/source.js": /*!****************************!*\ !*** external "ol.source" ***! \****************************/ /***/ ((module) => { module.exports = ol.source; /***/ }), /***/ "ol/source/Cluster.js": /*!************************************!*\ !*** external "ol.source.Cluster" ***! \************************************/ /***/ ((module) => { module.exports = ol.source.Cluster; /***/ }), /***/ "ol/source/Image.js": /*!**********************************!*\ !*** external "ol.source.Image" ***! \**********************************/ /***/ ((module) => { module.exports = ol.source.Image; /***/ }), /***/ "ol/source/ImageStatic.js": /*!****************************************!*\ !*** external "ol.source.ImageStatic" ***! \****************************************/ /***/ ((module) => { module.exports = ol.source.ImageStatic; /***/ }), /***/ "ol/source/ImageWMS.js": /*!*************************************!*\ !*** external "ol.source.ImageWMS" ***! \*************************************/ /***/ ((module) => { module.exports = ol.source.ImageWMS; /***/ }), /***/ "ol/source/TileImage.js": /*!**************************************!*\ !*** external "ol.source.TileImage" ***! \**************************************/ /***/ ((module) => { module.exports = ol.source.TileImage; /***/ }), /***/ "ol/source/TileWMS.js": /*!************************************!*\ !*** external "ol.source.TileWMS" ***! \************************************/ /***/ ((module) => { module.exports = ol.source.TileWMS; /***/ }), /***/ "ol/source/Vector.js": /*!***********************************!*\ !*** external "ol.source.Vector" ***! \***********************************/ /***/ ((module) => { module.exports = ol.source.Vector; /***/ }), /***/ "ol/source/VectorTile.js": /*!***************************************!*\ !*** external "ol.source.VectorTile" ***! \***************************************/ /***/ ((module) => { module.exports = ol.source.VectorTile; /***/ }), /***/ "ol/structs/LRUCache.js": /*!**************************************!*\ !*** external "ol.structs.LRUCache" ***! \**************************************/ /***/ ((module) => { module.exports = ol.structs.LRUCache; /***/ }), /***/ "ol/style/Icon.js": /*!********************************!*\ !*** external "ol.style.Icon" ***! \********************************/ /***/ ((module) => { module.exports = ol.style.Icon; /***/ }), /***/ "ol/style/Stroke.js": /*!**********************************!*\ !*** external "ol.style.Stroke" ***! \**********************************/ /***/ ((module) => { module.exports = ol.style.Stroke; /***/ }), /***/ "ol/style/Style.js": /*!*********************************!*\ !*** external "ol.style.Style" ***! \*********************************/ /***/ ((module) => { module.exports = ol.style.Style; /***/ }), /***/ "ol/tilegrid.js": /*!******************************!*\ !*** external "ol.tilegrid" ***! \******************************/ /***/ ((module) => { module.exports = ol.tilegrid; /***/ }), /***/ "ol/tileurlfunction.js": /*!*************************************!*\ !*** external "ol.tileurlfunction" ***! \*************************************/ /***/ ((module) => { module.exports = ol.tileurlfunction; /***/ }), /***/ "ol/util.js": /*!**************************!*\ !*** external "ol.util" ***! \**************************/ /***/ ((module) => { module.exports = ol.util; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { /*!******************************!*\ !*** ./src/index.library.js ***! \******************************/ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./olcs/OLCesium.js */ "./src/olcs/OLCesium.js"); /* harmony import */ var _olcs_AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./olcs/AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js"); /* harmony import */ var _olcs_RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./olcs/RasterSynchronizer.js */ "./src/olcs/RasterSynchronizer.js"); /* harmony import */ var _olcs_VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./olcs/VectorSynchronizer.js */ "./src/olcs/VectorSynchronizer.js"); /* harmony import */ var _olcs_core_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./olcs/core.js */ "./src/olcs/core.js"); /* harmony import */ var _olcs_core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./olcs/core/OLImageryProvider.js */ "./src/olcs/core/OLImageryProvider.js"); /* harmony import */ var _olcs_core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./olcs/core/VectorLayerCounterpart.js */ "./src/olcs/core/VectorLayerCounterpart.js"); /* harmony import */ var _olcs_contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./olcs/contrib/LazyLoader.js */ "./src/olcs/contrib/LazyLoader.js"); /* harmony import */ var _olcs_contrib_Manager_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./olcs/contrib/Manager.js */ "./src/olcs/contrib/Manager.js"); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__["default"]); // Using var for phantomJS // eslint-disable-next-line no-var var olcs = window['olcs'] = {}; olcs.OLCesium = _olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__["default"]; olcs.AbstractSynchronizer = _olcs_AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_1__["default"]; olcs.RasterSynchronizer = _olcs_RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__["default"]; olcs.VectorSynchronizer = _olcs_VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_3__["default"]; olcs.core = _olcs_core_js__WEBPACK_IMPORTED_MODULE_4__["default"]; olcs.core.OLImageryProvider = _olcs_core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_5__["default"]; olcs.core.VectorLayerCounterpart = _olcs_core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_6__["default"]; olcs.contrib = {}; olcs.contrib.LazyLoader = _olcs_contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_7__["default"]; olcs.contrib.Manager = _olcs_contrib_Manager_js__WEBPACK_IMPORTED_MODULE_8__["default"]; })(); olcs_unused_var = __webpack_exports__; /******/ })() ; //# sourceMappingURL=olcesium-debug.js.map