园林绿化
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6567 lines
208 KiB

  1. var olcs_unused_var;
  2. /******/ (() => { // webpackBootstrap
  3. /******/ "use strict";
  4. /******/ var __webpack_modules__ = ({
  5. /***/ "./src/olcs/AbstractSynchronizer.js":
  6. /*!******************************************!*\
  7. !*** ./src/olcs/AbstractSynchronizer.js ***!
  8. \******************************************/
  9. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  10. __webpack_require__.r(__webpack_exports__);
  11. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  12. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  13. /* harmony export */ });
  14. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js");
  15. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__);
  16. /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Group.js */ "ol/layer/Group.js");
  17. /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1__);
  18. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  19. /**
  20. * @module olcs.AbstractSynchronizer
  21. */
  22. class AbstractSynchronizer {
  23. /**
  24. * @param {!ol.Map} map
  25. * @param {!Cesium.Scene} scene
  26. * @template T
  27. * @abstract
  28. * @api
  29. */
  30. constructor(map, scene) {
  31. /**
  32. * @type {!ol.Map}
  33. * @protected
  34. */
  35. this.map = map;
  36. /**
  37. * @type {ol.View}
  38. * @protected
  39. */
  40. this.view = map.getView();
  41. /**
  42. * @type {!Cesium.Scene}
  43. * @protected
  44. */
  45. this.scene = scene;
  46. /**
  47. * @type {ol.Collection.<ol.layer.Base>}
  48. * @protected
  49. */
  50. this.olLayers = map.getLayerGroup().getLayers();
  51. /**
  52. * @type {ol.layer.Group}
  53. */
  54. this.mapLayerGroup = map.getLayerGroup();
  55. /**
  56. * Map of OpenLayers layer ids (from getUid) to the Cesium ImageryLayers.
  57. * Null value means, that we are unable to create equivalent layers.
  58. * @type {Object.<string, ?Array.<T>>}
  59. * @protected
  60. */
  61. this.layerMap = {};
  62. /**
  63. * Map of listen keys for OpenLayers layer layers ids (from getUid).
  64. * @type {!Object.<string, Array<ol.EventsKey>>}
  65. * @protected
  66. */
  67. this.olLayerListenKeys = {};
  68. /**
  69. * Map of listen keys for OpenLayers layer groups ids (from getUid).
  70. * @type {!Object.<string, !Array.<ol.EventsKey>>}
  71. * @private
  72. */
  73. this.olGroupListenKeys_ = {};
  74. }
  75. /**
  76. * Destroy all and perform complete synchronization of the layers.
  77. * @api
  78. */
  79. synchronize() {
  80. this.destroyAll();
  81. this.addLayers_(this.mapLayerGroup);
  82. }
  83. /**
  84. * Order counterparts using the same algorithm as the Openlayers renderer:
  85. * z-index then original sequence order.
  86. * @protected
  87. */
  88. orderLayers() {
  89. // Ordering logics is handled in subclasses.
  90. }
  91. /**
  92. * Add a layer hierarchy.
  93. * @param {ol.layer.Base} root
  94. * @private
  95. */
  96. addLayers_(root) {
  97. /** @type {Array<import('olsc/core.js').LayerWithParents>} */
  98. const fifo = [{
  99. layer: root,
  100. parents: []
  101. }];
  102. while (fifo.length > 0) {
  103. const olLayerWithParents = fifo.splice(0, 1)[0];
  104. const olLayer = olLayerWithParents.layer;
  105. const olLayerId = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(olLayer).toString();
  106. this.olLayerListenKeys[olLayerId] = [];
  107. console.assert(!this.layerMap[olLayerId]);
  108. let cesiumObjects = null;
  109. if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default())) {
  110. this.listenForGroupChanges_(olLayer);
  111. if (olLayer !== this.mapLayerGroup) {
  112. cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents);
  113. }
  114. if (!cesiumObjects) {
  115. olLayer.getLayers().forEach((l) => {
  116. if (l) {
  117. const newOlLayerWithParents = {
  118. layer: l,
  119. parents: olLayer === this.mapLayerGroup ?
  120. [] :
  121. [olLayerWithParents.layer].concat(olLayerWithParents.parents)
  122. };
  123. fifo.push(newOlLayerWithParents);
  124. }
  125. });
  126. }
  127. } else {
  128. cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents);
  129. if (!cesiumObjects) {
  130. // keep an eye on the layers that once failed to be added (might work when the layer is updated)
  131. // for example when a source is set after the layer is added to the map
  132. const layerId = olLayerId;
  133. const layerWithParents = olLayerWithParents;
  134. const onLayerChange = (e) => {
  135. const cesiumObjs = this.createSingleLayerCounterparts(layerWithParents);
  136. if (cesiumObjs) {
  137. // unsubscribe event listener
  138. layerWithParents.layer.un('change', onLayerChange);
  139. this.addCesiumObjects_(cesiumObjs, layerId, layerWithParents.layer);
  140. this.orderLayers();
  141. }
  142. };
  143. this.olLayerListenKeys[olLayerId].push((0,_util_js__WEBPACK_IMPORTED_MODULE_2__.olcsListen)(layerWithParents.layer, 'change', onLayerChange));
  144. }
  145. }
  146. // add Cesium layers
  147. if (cesiumObjects) {
  148. this.addCesiumObjects_(cesiumObjects, olLayerId, olLayer);
  149. }
  150. }
  151. this.orderLayers();
  152. }
  153. /**
  154. * Add Cesium objects.
  155. * @param {Array.<T>} cesiumObjects
  156. * @param {string} layerId
  157. * @param {ol.layer.Base} layer
  158. * @private
  159. */
  160. addCesiumObjects_(cesiumObjects, layerId, layer) {
  161. this.layerMap[layerId] = cesiumObjects;
  162. this.olLayerListenKeys[layerId].push((0,_util_js__WEBPACK_IMPORTED_MODULE_2__.olcsListen)(layer, 'change:zIndex', () => this.orderLayers()));
  163. cesiumObjects.forEach((cesiumObject) => {
  164. this.addCesiumObject(cesiumObject);
  165. });
  166. }
  167. /**
  168. * Remove and destroy a single layer.
  169. * @param {ol.layer.Layer} layer
  170. * @return {boolean} counterpart destroyed
  171. * @private
  172. */
  173. removeAndDestroySingleLayer_(layer) {
  174. const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(layer).toString();
  175. const counterparts = this.layerMap[uid];
  176. if (!!counterparts) {
  177. counterparts.forEach((counterpart) => {
  178. this.removeSingleCesiumObject(counterpart, false);
  179. this.destroyCesiumObject(counterpart);
  180. });
  181. this.olLayerListenKeys[uid].forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey);
  182. delete this.olLayerListenKeys[uid];
  183. }
  184. delete this.layerMap[uid];
  185. return !!counterparts;
  186. }
  187. /**
  188. * Unlisten a single layer group.
  189. * @param {ol.layer.Group} group
  190. * @private
  191. */
  192. unlistenSingleGroup_(group) {
  193. if (group === this.mapLayerGroup) {
  194. return;
  195. }
  196. const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(group).toString();
  197. const keys = this.olGroupListenKeys_[uid];
  198. keys.forEach((key) => {
  199. (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(key);
  200. });
  201. delete this.olGroupListenKeys_[uid];
  202. delete this.layerMap[uid];
  203. }
  204. /**
  205. * Remove layer hierarchy.
  206. * @param {ol.layer.Base} root
  207. * @private
  208. */
  209. removeLayer_(root) {
  210. if (!!root) {
  211. const fifo = [root];
  212. while (fifo.length > 0) {
  213. const olLayer = fifo.splice(0, 1)[0];
  214. const done = this.removeAndDestroySingleLayer_(olLayer);
  215. if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_1___default())) {
  216. this.unlistenSingleGroup_(olLayer);
  217. if (!done) {
  218. // No counterpart for the group itself so removing
  219. // each of the child layers.
  220. olLayer.getLayers().forEach((l) => {
  221. fifo.push(l);
  222. });
  223. }
  224. }
  225. }
  226. }
  227. }
  228. /**
  229. * Register listeners for single layer group change.
  230. * @param {ol.layer.Group} group
  231. * @private
  232. */
  233. listenForGroupChanges_(group) {
  234. const uuid = (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.getUid)(group).toString();
  235. console.assert(this.olGroupListenKeys_[uuid] === undefined);
  236. const listenKeyArray = [];
  237. this.olGroupListenKeys_[uuid] = listenKeyArray;
  238. // only the keys that need to be relistened when collection changes
  239. let contentKeys = [];
  240. const listenAddRemove = (function() {
  241. const collection = group.getLayers();
  242. if (collection) {
  243. contentKeys = [
  244. collection.on('add', (event) => {
  245. this.addLayers_(event.element);
  246. }),
  247. collection.on('remove', (event) => {
  248. this.removeLayer_(event.element);
  249. })
  250. ];
  251. listenKeyArray.push(...contentKeys);
  252. }
  253. }).bind(this);
  254. listenAddRemove();
  255. listenKeyArray.push(group.on('change:layers', (e) => {
  256. contentKeys.forEach((el) => {
  257. const i = listenKeyArray.indexOf(el);
  258. if (i >= 0) {
  259. listenKeyArray.splice(i, 1);
  260. }
  261. (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(el);
  262. });
  263. listenAddRemove();
  264. }));
  265. }
  266. /**
  267. * Destroys all the created Cesium objects.
  268. * @protected
  269. */
  270. destroyAll() {
  271. this.removeAllCesiumObjects(true); // destroy
  272. let objKey;
  273. for (objKey in this.olGroupListenKeys_) {
  274. const keys = this.olGroupListenKeys_[objKey];
  275. keys.forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey);
  276. }
  277. for (objKey in this.olLayerListenKeys) {
  278. this.olLayerListenKeys[objKey].forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey);
  279. }
  280. this.olGroupListenKeys_ = {};
  281. this.olLayerListenKeys = {};
  282. this.layerMap = {};
  283. }
  284. /**
  285. * Adds a single Cesium object to the collection.
  286. * @param {!T} object
  287. * @abstract
  288. * @protected
  289. */
  290. addCesiumObject(object) {}
  291. /**
  292. * @param {!T} object
  293. * @abstract
  294. * @protected
  295. */
  296. destroyCesiumObject(object) {}
  297. /**
  298. * Remove single Cesium object from the collection.
  299. * @param {!T} object
  300. * @param {boolean} destroy
  301. * @abstract
  302. * @protected
  303. */
  304. removeSingleCesiumObject(object, destroy) {}
  305. /**
  306. * Remove all Cesium objects from the collection.
  307. * @param {boolean} destroy
  308. * @abstract
  309. * @protected
  310. */
  311. removeAllCesiumObjects(destroy) {}
  312. /**
  313. * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents
  314. * @return {?Array.<T>}
  315. * @abstract
  316. * @protected
  317. */
  318. createSingleLayerCounterparts(olLayerWithParents) {}
  319. }
  320. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AbstractSynchronizer);
  321. /***/ }),
  322. /***/ "./src/olcs/AutoRenderLoop.js":
  323. /*!************************************!*\
  324. !*** ./src/olcs/AutoRenderLoop.js ***!
  325. \************************************/
  326. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  327. __webpack_require__.r(__webpack_exports__);
  328. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  329. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  330. /* harmony export */ });
  331. /**
  332. * @module olcs.AutoRenderLoop
  333. */
  334. class AutoRenderLoop {
  335. /**
  336. * @constructor
  337. * @param {olcs.OLCesium} ol3d
  338. */
  339. constructor(ol3d) {
  340. this.ol3d = ol3d;
  341. this.scene_ = ol3d.getCesiumScene();
  342. this.canvas_ = this.scene_.canvas;
  343. this._boundNotifyRepaintRequired = this.notifyRepaintRequired.bind(this);
  344. this.repaintEventNames_ = [
  345. 'mousemove', 'mousedown', 'mouseup',
  346. 'touchstart', 'touchend', 'touchmove',
  347. 'pointerdown', 'pointerup', 'pointermove',
  348. 'wheel'
  349. ];
  350. this.enable();
  351. }
  352. /**
  353. * Enable.
  354. */
  355. enable() {
  356. this.scene_.requestRenderMode = true;
  357. this.scene_.maximumRenderTimeChange = 1000;
  358. for (const repaintKey of this.repaintEventNames_) {
  359. this.canvas_.addEventListener(repaintKey, this._boundNotifyRepaintRequired, false);
  360. }
  361. window.addEventListener('resize', this._boundNotifyRepaintRequired, false);
  362. // Listen for changes on the layer group
  363. this.ol3d.getOlMap().getLayerGroup().on('change', this._boundNotifyRepaintRequired);
  364. }
  365. /**
  366. * Disable.
  367. */
  368. disable() {
  369. for (const repaintKey of this.repaintEventNames_) {
  370. this.canvas_.removeEventListener(repaintKey, this._boundNotifyRepaintRequired, false);
  371. }
  372. window.removeEventListener('resize', this._boundNotifyRepaintRequired, false);
  373. this.ol3d.getOlMap().getLayerGroup().un('change', this._boundNotifyRepaintRequired);
  374. this.scene_.requestRenderMode = false;
  375. }
  376. /**
  377. * Restart render loop.
  378. * Force a restart of the render loop.
  379. * @api
  380. */
  381. restartRenderLoop() {
  382. this.notifyRepaintRequired();
  383. }
  384. notifyRepaintRequired() {
  385. this.scene_.requestRender();
  386. }
  387. }
  388. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (AutoRenderLoop);
  389. /***/ }),
  390. /***/ "./src/olcs/Camera.js":
  391. /*!****************************!*\
  392. !*** ./src/olcs/Camera.js ***!
  393. \****************************/
  394. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  395. __webpack_require__.r(__webpack_exports__);
  396. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  397. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  398. /* harmony export */ });
  399. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js");
  400. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__);
  401. /* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./math.js */ "./src/olcs/math.js");
  402. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  403. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_2__);
  404. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js");
  405. /**
  406. * @module olcs.Camera
  407. */
  408. class Camera {
  409. /**
  410. * This object takes care of additional 3d-specific properties of the view and
  411. * ensures proper synchronization with the underlying raw Cesium.Camera object.
  412. * @param {!Cesium.Scene} scene
  413. * @param {!ol.Map} map
  414. * @api
  415. */
  416. constructor(scene, map) {
  417. /**
  418. * @type {!Cesium.Scene}
  419. * @private
  420. */
  421. this.scene_ = scene;
  422. /**
  423. * @type {!Cesium.Camera}
  424. * @private
  425. */
  426. this.cam_ = scene.camera;
  427. /**
  428. * @type {!ol.Map}
  429. * @private
  430. */
  431. this.map_ = map;
  432. /**
  433. * @type {?ol.View}
  434. * @private
  435. */
  436. this.view_ = null;
  437. /**
  438. * @type {?ol.EventsKey}
  439. * @private
  440. */
  441. this.viewListenKey_ = null;
  442. /**
  443. * @type {!ol.TransformFunction}
  444. * @private
  445. */
  446. this.toLonLat_ = Camera.identityProjection;
  447. /**
  448. * @type {!ol.TransformFunction}
  449. * @private
  450. */
  451. this.fromLonLat_ = Camera.identityProjection;
  452. /**
  453. * 0 -- topdown, PI/2 -- the horizon
  454. * @type {number}
  455. * @private
  456. */
  457. this.tilt_ = 0;
  458. /**
  459. * @type {number}
  460. * @private
  461. */
  462. this.distance_ = 0;
  463. /**
  464. * @type {?Cesium.Matrix4}
  465. * @private
  466. */
  467. this.lastCameraViewMatrix_ = null;
  468. /**
  469. * This is used to discard change events on view caused by updateView method.
  470. * @type {boolean}
  471. * @private
  472. */
  473. this.viewUpdateInProgress_ = false;
  474. this.map_.on('change:view', (e) => {
  475. this.setView_(this.map_.getView());
  476. });
  477. this.setView_(this.map_.getView());
  478. }
  479. /**
  480. * @param {Array.<number>} input Input coordinate array.
  481. * @param {Array.<number>=} opt_output Output array of coordinate values.
  482. * @param {number=} opt_dimension Dimension.
  483. * @return {Array.<number>} Input coordinate array (same array as input).
  484. */
  485. static identityProjection(input, opt_output, opt_dimension) {
  486. const dim = opt_dimension || input.length;
  487. if (opt_output) {
  488. for (let i = 0; i < dim; ++i) {
  489. opt_output[i] = input[i];
  490. }
  491. }
  492. return input;
  493. }
  494. /**
  495. * @param {?ol.View} view New view to use.
  496. * @private
  497. */
  498. setView_(view) {
  499. if (this.view_) {
  500. (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey)(this.viewListenKey_);
  501. this.viewListenKey_ = null;
  502. }
  503. this.view_ = view;
  504. if (view) {
  505. const toLonLat = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_2__.getTransform)(view.getProjection(), 'EPSG:4326');
  506. const fromLonLat = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_2__.getTransform)('EPSG:4326', view.getProjection());
  507. console.assert(toLonLat && fromLonLat);
  508. this.toLonLat_ = toLonLat;
  509. this.fromLonLat_ = fromLonLat;
  510. this.viewListenKey_ = view.on('propertychange', e => this.handleViewEvent_(e));
  511. this.readFromView();
  512. } else {
  513. this.toLonLat_ = Camera.identityProjection;
  514. this.fromLonLat_ = Camera.identityProjection;
  515. }
  516. }
  517. /**
  518. * @param {?} e
  519. * @private
  520. */
  521. handleViewEvent_(e) {
  522. if (!this.viewUpdateInProgress_) {
  523. this.readFromView();
  524. }
  525. }
  526. /**
  527. * @param {number} heading In radians.
  528. * @api
  529. */
  530. setHeading(heading) {
  531. if (!this.view_) {
  532. return;
  533. }
  534. this.view_.setRotation(heading);
  535. }
  536. /**
  537. * @return {number|undefined} Heading in radians.
  538. * @api
  539. */
  540. getHeading() {
  541. if (!this.view_) {
  542. return undefined;
  543. }
  544. const rotation = this.view_.getRotation();
  545. return rotation || 0;
  546. }
  547. /**
  548. * @param {number} tilt In radians.
  549. * @api
  550. */
  551. setTilt(tilt) {
  552. this.tilt_ = tilt;
  553. this.updateCamera_();
  554. }
  555. /**
  556. * @return {number} Tilt in radians.
  557. * @api
  558. */
  559. getTilt() {
  560. return this.tilt_;
  561. }
  562. /**
  563. * @param {number} distance In meters.
  564. * @api
  565. */
  566. setDistance(distance) {
  567. this.distance_ = distance;
  568. this.updateCamera_();
  569. this.updateView();
  570. }
  571. /**
  572. * @return {number} Distance in meters.
  573. * @api
  574. */
  575. getDistance() {
  576. return this.distance_;
  577. }
  578. /**
  579. * Shortcut for ol.View.setCenter().
  580. * @param {!ol.Coordinate} center Same projection as the ol.View.
  581. * @api
  582. */
  583. setCenter(center) {
  584. if (!this.view_) {
  585. return;
  586. }
  587. this.view_.setCenter(center);
  588. }
  589. /**
  590. * Shortcut for ol.View.getCenter().
  591. * @return {ol.Coordinate|undefined} Same projection as the ol.View.
  592. * @api
  593. */
  594. getCenter() {
  595. if (!this.view_) {
  596. return undefined;
  597. }
  598. return this.view_.getCenter();
  599. }
  600. /**
  601. * Sets the position of the camera.
  602. * @param {!ol.Coordinate} position Same projection as the ol.View.
  603. * @api
  604. */
  605. setPosition(position) {
  606. if (!this.toLonLat_) {
  607. return;
  608. }
  609. const ll = this.toLonLat_(position);
  610. console.assert(ll);
  611. const carto = new Cesium.Cartographic(
  612. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[0]),
  613. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1]),
  614. this.getAltitude());
  615. this.cam_.setView({
  616. destination: Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto)
  617. });
  618. this.updateView();
  619. }
  620. /**
  621. * Calculates position under the camera.
  622. * @return {!ol.Coordinate|undefined} Same projection as the ol.View.
  623. * @api
  624. */
  625. getPosition() {
  626. if (!this.fromLonLat_) {
  627. return undefined;
  628. }
  629. const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.cam_.position);
  630. const pos = this.fromLonLat_([
  631. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(carto.longitude),
  632. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(carto.latitude)
  633. ]);
  634. console.assert(pos);
  635. return pos;
  636. }
  637. /**
  638. * @param {number} altitude In meters.
  639. * @api
  640. */
  641. setAltitude(altitude) {
  642. const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(
  643. this.cam_.position);
  644. carto.height = altitude;
  645. this.cam_.position = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto);
  646. this.updateView();
  647. }
  648. /**
  649. * @return {number} Altitude in meters.
  650. * @api
  651. */
  652. getAltitude() {
  653. const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(
  654. this.cam_.position);
  655. return carto.height;
  656. }
  657. /**
  658. * Updates the state of the underlying Cesium.Camera
  659. * according to the current values of the properties.
  660. * @private
  661. */
  662. updateCamera_() {
  663. if (!this.view_ || !this.toLonLat_) {
  664. return;
  665. }
  666. const center = this.view_.getCenter();
  667. if (!center) {
  668. return;
  669. }
  670. const ll = this.toLonLat_(center);
  671. console.assert(ll);
  672. const carto = new Cesium.Cartographic((0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[0]),
  673. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1]));
  674. if (this.scene_.globe) {
  675. const height = this.scene_.globe.getHeight(carto);
  676. carto.height = height || 0;
  677. }
  678. const destination = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto);
  679. /** @type {Cesium.optionsOrientation} */
  680. const orientation = {
  681. pitch: this.tilt_ - Cesium.Math.PI_OVER_TWO,
  682. heading: -this.view_.getRotation(),
  683. roll: undefined
  684. };
  685. this.cam_.setView({
  686. destination,
  687. orientation
  688. });
  689. this.cam_.moveBackward(this.distance_);
  690. this.checkCameraChange(true);
  691. }
  692. /**
  693. * Calculates the values of the properties from the current ol.View state.
  694. * @api
  695. */
  696. readFromView() {
  697. if (!this.view_ || !this.toLonLat_) {
  698. return;
  699. }
  700. const center = this.view_.getCenter();
  701. if (center === undefined || center === null) {
  702. return;
  703. }
  704. const ll = this.toLonLat_(center);
  705. console.assert(ll);
  706. const resolution = this.view_.getResolution();
  707. this.distance_ = this.calcDistanceForResolution(
  708. resolution || 0, (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toRadians)(ll[1]));
  709. this.updateCamera_();
  710. }
  711. /**
  712. * Calculates the values of the properties from the current Cesium.Camera state.
  713. * Modifies the center, resolution and rotation properties of the view.
  714. * @api
  715. */
  716. updateView() {
  717. if (!this.view_ || !this.fromLonLat_) {
  718. return;
  719. }
  720. this.viewUpdateInProgress_ = true;
  721. // target & distance
  722. const ellipsoid = Cesium.Ellipsoid.WGS84;
  723. const scene = this.scene_;
  724. const target = _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].pickCenterPoint(scene);
  725. let bestTarget = target;
  726. if (!bestTarget) {
  727. //TODO: how to handle this properly ?
  728. const globe = scene.globe;
  729. const carto = this.cam_.positionCartographic.clone();
  730. const height = globe.getHeight(carto);
  731. carto.height = height || 0;
  732. bestTarget = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto);
  733. }
  734. this.distance_ = Cesium.Cartesian3.distance(bestTarget, this.cam_.position);
  735. const bestTargetCartographic = ellipsoid.cartesianToCartographic(bestTarget);
  736. this.view_.setCenter(this.fromLonLat_([
  737. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(bestTargetCartographic.longitude),
  738. (0,_math_js__WEBPACK_IMPORTED_MODULE_1__.toDegrees)(bestTargetCartographic.latitude)]));
  739. // resolution
  740. this.view_.setResolution(
  741. this.calcResolutionForDistance(this.distance_,
  742. bestTargetCartographic ? bestTargetCartographic.latitude : 0));
  743. /*
  744. * Since we are positioning the target, the values of heading and tilt
  745. * need to be calculated _at the target_.
  746. */
  747. if (target) {
  748. const pos = this.cam_.position;
  749. // normal to the ellipsoid at the target
  750. const targetNormal = new Cesium.Cartesian3();
  751. ellipsoid.geocentricSurfaceNormal(target, targetNormal);
  752. // vector from the target to the camera
  753. const targetToCamera = new Cesium.Cartesian3();
  754. Cesium.Cartesian3.subtract(pos, target, targetToCamera);
  755. Cesium.Cartesian3.normalize(targetToCamera, targetToCamera);
  756. // HEADING
  757. const up = this.cam_.up;
  758. const right = this.cam_.right;
  759. const normal = new Cesium.Cartesian3(-target.y, target.x, 0); // what is it?
  760. const heading = Cesium.Cartesian3.angleBetween(right, normal);
  761. const cross = Cesium.Cartesian3.cross(target, up, new Cesium.Cartesian3());
  762. const orientation = cross.z;
  763. this.view_.setRotation((orientation < 0 ? heading : -heading));
  764. // TILT
  765. const tiltAngle = Math.acos(
  766. Cesium.Cartesian3.dot(targetNormal, targetToCamera));
  767. this.tilt_ = isNaN(tiltAngle) ? 0 : tiltAngle;
  768. } else {
  769. // fallback when there is no target
  770. this.view_.setRotation(this.cam_.heading);
  771. this.tilt_ = -this.cam_.pitch + Math.PI / 2;
  772. }
  773. this.viewUpdateInProgress_ = false;
  774. }
  775. /**
  776. * Check if the underlying camera state has changed and ensure synchronization.
  777. * @param {boolean=} opt_dontSync Do not synchronize the view.
  778. */
  779. checkCameraChange(opt_dontSync) {
  780. const old = this.lastCameraViewMatrix_;
  781. const current = this.cam_.viewMatrix;
  782. if (!old || !Cesium.Matrix4.equalsEpsilon(old, current, 1e-5)) {
  783. this.lastCameraViewMatrix_ = current.clone();
  784. if (opt_dontSync !== true) {
  785. this.updateView();
  786. }
  787. }
  788. }
  789. /**
  790. * calculate the distance between camera and centerpoint based on the resolution and latitude value
  791. * @param {number} resolution Number of map units per pixel.
  792. * @param {number} latitude Latitude in radians.
  793. * @return {number} The calculated distance.
  794. * @api
  795. */
  796. calcDistanceForResolution(resolution, latitude) {
  797. return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.calcDistanceForResolution)(resolution, latitude, this.scene_, this.view_.getProjection());
  798. }
  799. /**
  800. * calculate the resolution based on a distance(camera to position) and latitude value
  801. * @param {number} distance
  802. * @param {number} latitude
  803. * @return {number} The calculated resolution.
  804. * @api
  805. */
  806. calcResolutionForDistance(distance, latitude) {
  807. return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.calcResolutionForDistance)(distance, latitude, this.scene_, this.view_.getProjection());
  808. }
  809. }
  810. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Camera);
  811. /***/ }),
  812. /***/ "./src/olcs/FeatureConverter.js":
  813. /*!**************************************!*\
  814. !*** ./src/olcs/FeatureConverter.js ***!
  815. \**************************************/
  816. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  817. __webpack_require__.r(__webpack_exports__);
  818. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  819. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  820. /* harmony export */ });
  821. /* harmony import */ var ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/geom/Geometry.js */ "ol/geom/Geometry.js");
  822. /* harmony import */ var ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0__);
  823. /* harmony import */ var ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/style/Icon.js */ "ol/style/Icon.js");
  824. /* harmony import */ var ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1__);
  825. /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source/Vector.js */ "ol/source/Vector.js");
  826. /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2__);
  827. /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/source/Cluster.js */ "ol/source/Cluster.js");
  828. /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3__);
  829. /* harmony import */ var ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/geom/Polygon.js */ "ol/geom/Polygon.js");
  830. /* harmony import */ var ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__);
  831. /* harmony import */ var ol_extent_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/extent.js */ "ol/extent");
  832. /* harmony import */ var ol_extent_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_extent_js__WEBPACK_IMPORTED_MODULE_5__);
  833. /* harmony import */ var ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/geom/SimpleGeometry.js */ "ol/geom/SimpleGeometry.js");
  834. /* harmony import */ var ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6__);
  835. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js");
  836. /* harmony import */ var _core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./core/VectorLayerCounterpart.js */ "./src/olcs/core/VectorLayerCounterpart.js");
  837. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  838. /**
  839. * @module olcs.FeatureConverter
  840. */
  841. /**
  842. * @typedef {Object} ModelStyle
  843. * @property {Cesium.Matrix4} [debugModelMatrix]
  844. * @property {Cesium.ModelFromGltfOptions} cesiumOptions
  845. */
  846. class FeatureConverter {
  847. /**
  848. * Concrete base class for converting from OpenLayers3 vectors to Cesium
  849. * primitives.
  850. * Extending this class is possible provided that the extending class and
  851. * the library are compiled together by the closure compiler.
  852. * @param {!Cesium.Scene} scene Cesium scene.
  853. * @constructor
  854. * @api
  855. */
  856. constructor(scene) {
  857. /**
  858. * @protected
  859. */
  860. this.scene = scene;
  861. /**
  862. * Bind once to have a unique function for using as a listener
  863. * @type {function(ol.source.Vector.Event)}
  864. * @private
  865. */
  866. this.boundOnRemoveOrClearFeatureListener_ = this.onRemoveOrClearFeature_.bind(this);
  867. /**
  868. * @type {Cesium.Cartesian3}
  869. * @private
  870. */
  871. this.defaultBillboardEyeOffset_ = new Cesium.Cartesian3(0, 0, 10);
  872. }
  873. /**
  874. * @param {ol.source.Vector.Event} evt
  875. * @private
  876. */
  877. onRemoveOrClearFeature_(evt) {
  878. const source = evt.target;
  879. console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default()));
  880. const cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'];
  881. if (cancellers) {
  882. const feature = evt.feature;
  883. if (feature) {
  884. // remove
  885. const id = (0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature);
  886. const canceller = cancellers[id];
  887. if (canceller) {
  888. canceller();
  889. delete cancellers[id];
  890. }
  891. } else {
  892. // clear
  893. for (const key in cancellers) {
  894. if (cancellers.hasOwnProperty(key)) {
  895. cancellers[key]();
  896. }
  897. }
  898. _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'] = {};
  899. }
  900. }
  901. }
  902. /**
  903. * @param {ol.layer.Vector|ol.layer.Image} layer
  904. * @param {!ol.Feature} feature OpenLayers feature.
  905. * @param {!Cesium.Primitive|Cesium.Label|Cesium.Billboard} primitive
  906. * @protected
  907. */
  908. setReferenceForPicking(layer, feature, primitive) {
  909. primitive.olLayer = layer;
  910. primitive.olFeature = feature;
  911. }
  912. /**
  913. * Basics primitive creation using a color attribute.
  914. * Note that Cesium has 'interior' and outline geometries.
  915. * @param {ol.layer.Vector|ol.layer.Image} layer
  916. * @param {!ol.Feature} feature OpenLayers feature.
  917. * @param {!ol.geom.Geometry} olGeometry OpenLayers geometry.
  918. * @param {!Cesium.Geometry} geometry
  919. * @param {!Cesium.Color} color
  920. * @param {number=} opt_lineWidth
  921. * @return {Cesium.Primitive}
  922. * @protected
  923. */
  924. createColoredPrimitive(layer, feature, olGeometry, geometry, color, opt_lineWidth) {
  925. const createInstance = function(geometry, color) {
  926. const instance = new Cesium.GeometryInstance({
  927. // always update Cesium externs before adding a property
  928. geometry
  929. });
  930. if (color && !(color instanceof Cesium.ImageMaterialProperty)) {
  931. instance.attributes = {
  932. color: Cesium.ColorGeometryInstanceAttribute.fromColor(color)
  933. };
  934. }
  935. return instance;
  936. };
  937. const options = {
  938. // always update Cesium externs before adding a property
  939. flat: true, // work with all geometries
  940. renderState: {
  941. depthTest: {
  942. enabled: true
  943. }
  944. }
  945. };
  946. if (opt_lineWidth !== undefined) {
  947. if (!options.renderState) {
  948. options.renderState = {};
  949. }
  950. options.renderState.lineWidth = opt_lineWidth;
  951. }
  952. const instances = createInstance(geometry, color);
  953. const heightReference = this.getHeightReference(layer, feature, olGeometry);
  954. let primitive;
  955. if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) {
  956. const ctor = instances.geometry.constructor;
  957. if (ctor && !ctor['createShadowVolume']) {
  958. return null;
  959. }
  960. primitive = new Cesium.GroundPrimitive({
  961. geometryInstances: instances
  962. });
  963. } else {
  964. primitive = new Cesium.Primitive({
  965. geometryInstances: instances
  966. });
  967. }
  968. if (color instanceof Cesium.ImageMaterialProperty) {
  969. const dataUri = color.image.getValue().toDataURL();
  970. primitive.appearance = new Cesium.MaterialAppearance({
  971. flat: true,
  972. renderState: {
  973. depthTest: {
  974. enabled: true
  975. }
  976. },
  977. material: new Cesium.Material({
  978. fabric: {
  979. type: 'Image',
  980. uniforms: {
  981. image: dataUri
  982. }
  983. }
  984. })
  985. });
  986. } else {
  987. primitive.appearance = new Cesium.PerInstanceColorAppearance(options);
  988. }
  989. this.setReferenceForPicking(layer, feature, primitive);
  990. return primitive;
  991. }
  992. /**
  993. * Return the fill or stroke color from a plain ol style.
  994. * @param {!ol.style.Style|ol.style.Text} style
  995. * @param {boolean} outline
  996. * @return {!Cesium.Color}
  997. * @protected
  998. */
  999. extractColorFromOlStyle(style, outline) {
  1000. const fillColor = style.getFill() ? style.getFill().getColor() : null;
  1001. const strokeColor = style.getStroke() ? style.getStroke().getColor() : null;
  1002. let olColor = 'black';
  1003. if (strokeColor && outline) {
  1004. olColor = strokeColor;
  1005. } else if (fillColor) {
  1006. olColor = fillColor;
  1007. }
  1008. return _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].convertColorToCesium(olColor);
  1009. }
  1010. /**
  1011. * Return the width of stroke from a plain ol style.
  1012. * @param {!ol.style.Style|ol.style.Text} style
  1013. * @return {number}
  1014. * @protected
  1015. */
  1016. extractLineWidthFromOlStyle(style) {
  1017. // Handling of line width WebGL limitations is handled by Cesium.
  1018. const width = style.getStroke() ? style.getStroke().getWidth() : undefined;
  1019. return width !== undefined ? width : 1;
  1020. }
  1021. /**
  1022. * Create a primitive collection out of two Cesium geometries.
  1023. * Only the OpenLayers style colors will be used.
  1024. * @param {ol.layer.Vector|ol.layer.Image} layer
  1025. * @param {!ol.Feature} feature OpenLayers feature.
  1026. * @param {!ol.geom.Geometry} olGeometry OpenLayers geometry.
  1027. * @param {!Cesium.Geometry} fillGeometry
  1028. * @param {!Cesium.Geometry} outlineGeometry
  1029. * @param {!ol.style.Style} olStyle
  1030. * @return {!Cesium.PrimitiveCollection}
  1031. * @protected
  1032. */
  1033. wrapFillAndOutlineGeometries(layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle) {
  1034. const fillColor = this.extractColorFromOlStyle(olStyle, false);
  1035. const outlineColor = this.extractColorFromOlStyle(olStyle, true);
  1036. const primitives = new Cesium.PrimitiveCollection();
  1037. if (olStyle.getFill()) {
  1038. const p1 = this.createColoredPrimitive(layer, feature, olGeometry,
  1039. fillGeometry, fillColor);
  1040. console.assert(!!p1);
  1041. primitives.add(p1);
  1042. }
  1043. if (olStyle.getStroke() && outlineGeometry) {
  1044. const width = this.extractLineWidthFromOlStyle(olStyle);
  1045. const p2 = this.createColoredPrimitive(layer, feature, olGeometry,
  1046. outlineGeometry, outlineColor, width);
  1047. if (p2) {
  1048. // Some outline geometries are not supported by Cesium in clamp to ground
  1049. // mode. These primitives are skipped.
  1050. primitives.add(p2);
  1051. }
  1052. }
  1053. return primitives;
  1054. }
  1055. // Geometry converters
  1056. /**
  1057. * Create a Cesium primitive if style has a text component.
  1058. * Eventually return a PrimitiveCollection including current primitive.
  1059. * @param {ol.layer.Vector|ol.layer.Image} layer
  1060. * @param {!ol.Feature} feature OpenLayers feature..
  1061. * @param {!ol.geom.Geometry} geometry
  1062. * @param {!ol.style.Style} style
  1063. * @param {!Cesium.Primitive} primitive current primitive
  1064. * @return {!Cesium.PrimitiveCollection}
  1065. * @protected
  1066. */
  1067. addTextStyle(layer, feature, geometry, style, primitive) {
  1068. let primitives;
  1069. if (!(primitive instanceof Cesium.PrimitiveCollection)) {
  1070. primitives = new Cesium.PrimitiveCollection();
  1071. primitives.add(primitive);
  1072. } else {
  1073. primitives = primitive;
  1074. }
  1075. if (!style.getText()) {
  1076. return primitives;
  1077. }
  1078. const text = /** @type {!ol.style.Text} */ (style.getText());
  1079. const label = this.olGeometry4326TextPartToCesium(layer, feature, geometry,
  1080. text);
  1081. if (label) {
  1082. primitives.add(label);
  1083. }
  1084. return primitives;
  1085. }
  1086. /**
  1087. * Add a billboard to a Cesium.BillboardCollection.
  1088. * Overriding this wrapper allows manipulating the billboard options.
  1089. * @param {!Cesium.BillboardCollection} billboards
  1090. * @param {!Cesium.optionsBillboardCollectionAdd} bbOptions
  1091. * @param {ol.layer.Vector|ol.layer.Image} layer
  1092. * @param {!ol.Feature} feature OpenLayers feature.
  1093. * @param {!ol.geom.Geometry} geometry
  1094. * @param {!ol.style.Style} style
  1095. * @return {!Cesium.Billboard} newly created billboard
  1096. * @api
  1097. */
  1098. csAddBillboard(billboards, bbOptions, layer, feature, geometry, style) {
  1099. if (!bbOptions.eyeOffset) {
  1100. bbOptions.eyeOffset = this.defaultBillboardEyeOffset_;
  1101. }
  1102. const bb = billboards.add(bbOptions);
  1103. this.setReferenceForPicking(layer, feature, bb);
  1104. return bb;
  1105. }
  1106. /**
  1107. * Convert an OpenLayers circle geometry to Cesium.
  1108. * @param {ol.layer.Vector|ol.layer.Image} layer
  1109. * @param {!ol.Feature} feature OpenLayers feature..
  1110. * @param {!ol.geom.Circle} olGeometry OpenLayers circle geometry.
  1111. * @param {!ol.ProjectionLike} projection
  1112. * @param {!ol.style.Style} olStyle
  1113. * @return {!Cesium.PrimitiveCollection} primitives
  1114. * @api
  1115. */
  1116. olCircleGeometryToCesium(layer, feature, olGeometry, projection, olStyle) {
  1117. olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection);
  1118. console.assert(olGeometry.getType() == 'Circle');
  1119. // ol.Coordinate
  1120. let center = olGeometry.getCenter();
  1121. const height = center.length == 3 ? center[2] : 0.0;
  1122. let point = center.slice();
  1123. point[0] += olGeometry.getRadius();
  1124. // Cesium
  1125. center = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(center);
  1126. point = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(point);
  1127. // Accurate computation of straight distance
  1128. const radius = Cesium.Cartesian3.distance(center, point);
  1129. const fillGeometry = new Cesium.CircleGeometry({
  1130. // always update Cesium externs before adding a property
  1131. center,
  1132. radius,
  1133. height
  1134. });
  1135. let outlinePrimitive, outlineGeometry;
  1136. if (this.getHeightReference(layer, feature, olGeometry) === Cesium.HeightReference.CLAMP_TO_GROUND) {
  1137. const width = this.extractLineWidthFromOlStyle(olStyle);
  1138. if (width) {
  1139. const circlePolygon = (0,ol_geom_Polygon_js__WEBPACK_IMPORTED_MODULE_4__.circular)(olGeometry.getCenter(), radius);
  1140. const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(circlePolygon.getLinearRing(0).getCoordinates());
  1141. if (!(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) {
  1142. const color = this.extractColorFromOlStyle(olStyle, true);
  1143. outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions);
  1144. } else {
  1145. outlinePrimitive = new Cesium.GroundPolylinePrimitive({
  1146. geometryInstances: new Cesium.GeometryInstance({
  1147. geometry: new Cesium.GroundPolylineGeometry({positions, width}),
  1148. }),
  1149. appearance: new Cesium.PolylineMaterialAppearance({
  1150. material: this.olStyleToCesium(feature, olStyle, true),
  1151. }),
  1152. classificationType: Cesium.ClassificationType.TERRAIN,
  1153. });
  1154. outlinePrimitive.readyPromise.then(() => {
  1155. this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive);
  1156. });
  1157. }
  1158. }
  1159. } else {
  1160. outlineGeometry = new Cesium.CircleOutlineGeometry({
  1161. // always update Cesium externs before adding a property
  1162. center,
  1163. radius,
  1164. extrudedHeight: height,
  1165. height
  1166. });
  1167. }
  1168. const primitives = this.wrapFillAndOutlineGeometries(
  1169. layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle);
  1170. if (outlinePrimitive) {
  1171. primitives.add(outlinePrimitive);
  1172. }
  1173. return this.addTextStyle(layer, feature, olGeometry, olStyle, primitives);
  1174. }
  1175. /**
  1176. * @param {ol.layer.Vector|ol.layer.Image} layer
  1177. * @param {!ol.Feature} feature OpenLayers feature..
  1178. * @param {!number} width The width of the line.
  1179. * @param {!Cesium.Color} color The color of the line.
  1180. * @param {!Array<Cesium.Cartesian3>|Array<Array<Cesium.Cartesian3>>} positions The vertices of the line(s).
  1181. * @return {!Cesium.GroundPrimitive} primitive
  1182. */
  1183. createStackedGroundCorridors(layer, feature, width, color, positions) {
  1184. // Convert positions to an Array if it isn't
  1185. if (!Array.isArray(positions[0])) {
  1186. positions = [positions];
  1187. }
  1188. width = Math.max(3, width); // A <3px width is too small for ground primitives
  1189. const geometryInstances = [];
  1190. let previousDistance = 0;
  1191. // A stack of ground lines with increasing width (in meters) are created.
  1192. // Only one of these lines is displayed at any time giving a feeling of continuity.
  1193. // The values for the distance and width factor are more or less arbitrary.
  1194. // Applications can override this logics by subclassing the FeatureConverter class.
  1195. for (const distance of [1000, 4000, 16000, 64000, 254000, 1000000, 10000000]) {
  1196. width *= 2.14;
  1197. const geometryOptions = {
  1198. // always update Cesium externs before adding a property
  1199. width,
  1200. vertexFormat: Cesium.VertexFormat.POSITION_ONLY
  1201. };
  1202. for (const linePositions of positions) {
  1203. geometryOptions.positions = linePositions;
  1204. geometryInstances.push(new Cesium.GeometryInstance({
  1205. geometry: new Cesium.CorridorGeometry(geometryOptions),
  1206. attributes: {
  1207. color: Cesium.ColorGeometryInstanceAttribute.fromColor(color),
  1208. distanceDisplayCondition: new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(previousDistance, distance - 1)
  1209. }
  1210. }));
  1211. }
  1212. previousDistance = distance;
  1213. }
  1214. return new Cesium.GroundPrimitive({
  1215. // always update Cesium externs before adding a property
  1216. geometryInstances
  1217. });
  1218. }
  1219. /**
  1220. * Convert an OpenLayers line string geometry to Cesium.
  1221. * @param {ol.layer.Vector|ol.layer.Image} layer
  1222. * @param {!ol.Feature} feature OpenLayers feature..
  1223. * @param {!ol.geom.LineString} olGeometry OpenLayers line string geometry.
  1224. * @param {!ol.ProjectionLike} projection
  1225. * @param {!ol.style.Style} olStyle
  1226. * @return {!Cesium.PrimitiveCollection} primitives
  1227. * @api
  1228. */
  1229. olLineStringGeometryToCesium(layer, feature, olGeometry, projection, olStyle) {
  1230. olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection);
  1231. console.assert(olGeometry.getType() == 'LineString');
  1232. const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(olGeometry.getCoordinates());
  1233. const width = this.extractLineWidthFromOlStyle(olStyle);
  1234. let outlinePrimitive;
  1235. const heightReference = this.getHeightReference(layer, feature, olGeometry);
  1236. if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND && !(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) {
  1237. const color = this.extractColorFromOlStyle(olStyle, true);
  1238. outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions);
  1239. } else {
  1240. const appearance = new Cesium.PolylineMaterialAppearance({
  1241. // always update Cesium externs before adding a property
  1242. material: this.olStyleToCesium(feature, olStyle, true)
  1243. });
  1244. const geometryOptions = {
  1245. // always update Cesium externs before adding a property
  1246. positions,
  1247. width,
  1248. };
  1249. const primitiveOptions = {
  1250. // always update Cesium externs before adding a property
  1251. appearance
  1252. };
  1253. if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) {
  1254. const geometry = new Cesium.GroundPolylineGeometry(geometryOptions);
  1255. primitiveOptions.geometryInstances = new Cesium.GeometryInstance({
  1256. geometry
  1257. }),
  1258. outlinePrimitive = new Cesium.GroundPolylinePrimitive(primitiveOptions);
  1259. outlinePrimitive.readyPromise.then(() => {
  1260. this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive);
  1261. });
  1262. } else {
  1263. geometryOptions.vertexFormat = appearance.vertexFormat;
  1264. const geometry = new Cesium.PolylineGeometry(geometryOptions);
  1265. primitiveOptions.geometryInstances = new Cesium.GeometryInstance({
  1266. geometry
  1267. }),
  1268. outlinePrimitive = new Cesium.Primitive(primitiveOptions);
  1269. }
  1270. }
  1271. this.setReferenceForPicking(layer, feature, outlinePrimitive);
  1272. return this.addTextStyle(layer, feature, olGeometry, olStyle, outlinePrimitive);
  1273. }
  1274. /**
  1275. * Convert an OpenLayers polygon geometry to Cesium.
  1276. * @param {ol.layer.Vector|ol.layer.Image} layer
  1277. * @param {!ol.Feature} feature OpenLayers feature..
  1278. * @param {!ol.geom.Polygon} olGeometry OpenLayers polygon geometry.
  1279. * @param {!ol.ProjectionLike} projection
  1280. * @param {!ol.style.Style} olStyle
  1281. * @return {!Cesium.PrimitiveCollection} primitives
  1282. * @api
  1283. */
  1284. olPolygonGeometryToCesium(layer, feature, olGeometry, projection, olStyle) {
  1285. olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection);
  1286. console.assert(olGeometry.getType() == 'Polygon');
  1287. const heightReference = this.getHeightReference(layer, feature, olGeometry);
  1288. let fillGeometry, outlineGeometry, outlinePrimitive;
  1289. if ((olGeometry.getCoordinates()[0].length == 5) &&
  1290. (feature.getGeometry().get('olcs.polygon_kind') === 'rectangle')) {
  1291. // Create a rectangle according to the longitude and latitude curves
  1292. const coordinates = olGeometry.getCoordinates()[0];
  1293. // Extract the West, South, East, North coordinates
  1294. const extent = (0,ol_extent_js__WEBPACK_IMPORTED_MODULE_5__.boundingExtent)(coordinates);
  1295. const rectangle = Cesium.Rectangle.fromDegrees(extent[0], extent[1],
  1296. extent[2], extent[3]);
  1297. // Extract the average height of the vertices
  1298. let maxHeight = 0.0;
  1299. if (coordinates[0].length == 3) {
  1300. for (let c = 0; c < coordinates.length; c++) {
  1301. maxHeight = Math.max(maxHeight, coordinates[c][2]);
  1302. }
  1303. }
  1304. // Render the cartographic rectangle
  1305. fillGeometry = new Cesium.RectangleGeometry({
  1306. ellipsoid: Cesium.Ellipsoid.WGS84,
  1307. rectangle,
  1308. height: maxHeight
  1309. });
  1310. outlineGeometry = new Cesium.RectangleOutlineGeometry({
  1311. ellipsoid: Cesium.Ellipsoid.WGS84,
  1312. rectangle,
  1313. height: maxHeight
  1314. });
  1315. } else {
  1316. const rings = olGeometry.getLinearRings();
  1317. // always update Cesium externs before adding a property
  1318. const hierarchy = {};
  1319. const polygonHierarchy = hierarchy;
  1320. console.assert(rings.length > 0);
  1321. for (let i = 0; i < rings.length; ++i) {
  1322. const olPos = rings[i].getCoordinates();
  1323. const positions = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateArrayToCsCartesians(olPos);
  1324. console.assert(positions && positions.length > 0);
  1325. if (i == 0) {
  1326. hierarchy.positions = positions;
  1327. } else {
  1328. if (!hierarchy.holes) {
  1329. hierarchy.holes = [];
  1330. }
  1331. hierarchy.holes.push({
  1332. positions
  1333. });
  1334. }
  1335. }
  1336. fillGeometry = new Cesium.PolygonGeometry({
  1337. // always update Cesium externs before adding a property
  1338. polygonHierarchy,
  1339. perPositionHeight: true
  1340. });
  1341. // Since Cesium doesn't yet support Polygon outlines on terrain yet (coming soon...?)
  1342. // we don't create an outline geometry if clamped, but instead do the polyline method
  1343. // for each ring. Most of this code should be removeable when Cesium adds
  1344. // support for Polygon outlines on terrain.
  1345. if (heightReference === Cesium.HeightReference.CLAMP_TO_GROUND) {
  1346. const width = this.extractLineWidthFromOlStyle(olStyle);
  1347. if (width > 0) {
  1348. const positions = [hierarchy.positions];
  1349. if (hierarchy.holes) {
  1350. for (let i = 0; i < hierarchy.holes.length; ++i) {
  1351. positions.push(hierarchy.holes[i].positions);
  1352. }
  1353. }
  1354. if (!(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.isGroundPolylinePrimitiveSupported)(this.scene)) {
  1355. const color = this.extractColorFromOlStyle(olStyle, true);
  1356. outlinePrimitive = this.createStackedGroundCorridors(layer, feature, width, color, positions);
  1357. } else {
  1358. const appearance = new Cesium.PolylineMaterialAppearance({
  1359. // always update Cesium externs before adding a property
  1360. material: this.olStyleToCesium(feature, olStyle, true)
  1361. });
  1362. const geometryInstances = [];
  1363. for (const linePositions of positions) {
  1364. const polylineGeometry = new Cesium.GroundPolylineGeometry({positions: linePositions, width});
  1365. geometryInstances.push(new Cesium.GeometryInstance({
  1366. geometry: polylineGeometry
  1367. }));
  1368. }
  1369. const primitiveOptions = {
  1370. // always update Cesium externs before adding a property
  1371. appearance,
  1372. geometryInstances
  1373. };
  1374. outlinePrimitive = new Cesium.GroundPolylinePrimitive(primitiveOptions);
  1375. outlinePrimitive.readyPromise.then(() => {
  1376. this.setReferenceForPicking(layer, feature, outlinePrimitive._primitive);
  1377. });
  1378. }
  1379. }
  1380. } else {
  1381. // Actually do the normal polygon thing. This should end the removable
  1382. // section of code described above.
  1383. outlineGeometry = new Cesium.PolygonOutlineGeometry({
  1384. // always update Cesium externs before adding a property
  1385. polygonHierarchy: hierarchy,
  1386. perPositionHeight: true
  1387. });
  1388. }
  1389. }
  1390. const primitives = this.wrapFillAndOutlineGeometries(
  1391. layer, feature, olGeometry, fillGeometry, outlineGeometry, olStyle);
  1392. if (outlinePrimitive) {
  1393. primitives.add(outlinePrimitive);
  1394. }
  1395. return this.addTextStyle(layer, feature, olGeometry, olStyle, primitives);
  1396. }
  1397. /**
  1398. * @param {ol.layer.Vector|ol.layer.Image} layer
  1399. * @param {ol.Feature} feature OpenLayers feature..
  1400. * @param {!ol.geom.Geometry} geometry
  1401. * @return {!Cesium.HeightReference}
  1402. * @api
  1403. */
  1404. getHeightReference(layer, feature, geometry) {
  1405. // Read from the geometry
  1406. let altitudeMode = geometry.get('altitudeMode');
  1407. // Or from the feature
  1408. if (altitudeMode === undefined) {
  1409. altitudeMode = feature.get('altitudeMode');
  1410. }
  1411. // Or from the layer
  1412. if (altitudeMode === undefined) {
  1413. altitudeMode = layer.get('altitudeMode');
  1414. }
  1415. let heightReference = Cesium.HeightReference.NONE;
  1416. if (altitudeMode === 'clampToGround') {
  1417. heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
  1418. } else if (altitudeMode === 'relativeToGround') {
  1419. heightReference = Cesium.HeightReference.RELATIVE_TO_GROUND;
  1420. }
  1421. return heightReference;
  1422. }
  1423. /**
  1424. * Convert a point geometry to a Cesium BillboardCollection.
  1425. * @param {ol.layer.Vector|ol.layer.Image} layer
  1426. * @param {!ol.Feature} feature OpenLayers feature..
  1427. * @param {!ol.geom.Point} olGeometry OpenLayers point geometry.
  1428. * @param {!ol.ProjectionLike} projection
  1429. * @param {!ol.style.Style} style
  1430. * @param {!ol.style.Image} imageStyle
  1431. * @param {!Cesium.BillboardCollection} billboards
  1432. * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when the new billboard is added.
  1433. * @api
  1434. */
  1435. createBillboardFromImage(
  1436. layer,
  1437. feature,
  1438. olGeometry,
  1439. projection,
  1440. style,
  1441. imageStyle,
  1442. billboards,
  1443. opt_newBillboardCallback
  1444. ) {
  1445. if (imageStyle instanceof (ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default())) {
  1446. // make sure the image is scheduled for load
  1447. imageStyle.load();
  1448. }
  1449. const image = imageStyle.getImage(1); // get normal density
  1450. const isImageLoaded = function(image) {
  1451. return image.src != '' &&
  1452. image.naturalHeight != 0 &&
  1453. image.naturalWidth != 0 &&
  1454. image.complete;
  1455. };
  1456. const reallyCreateBillboard = (function() {
  1457. if (!image) {
  1458. return;
  1459. }
  1460. if (!(image instanceof HTMLCanvasElement ||
  1461. image instanceof Image ||
  1462. image instanceof HTMLImageElement)) {
  1463. return;
  1464. }
  1465. const center = olGeometry.getCoordinates();
  1466. const position = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(center);
  1467. let color;
  1468. const opacity = imageStyle.getOpacity();
  1469. if (opacity !== undefined) {
  1470. color = new Cesium.Color(1.0, 1.0, 1.0, opacity);
  1471. }
  1472. const scale = imageStyle.getScale();
  1473. const heightReference = this.getHeightReference(layer, feature, olGeometry);
  1474. const bbOptions = /** @type {Cesium.optionsBillboardCollectionAdd} */ ({
  1475. // always update Cesium externs before adding a property
  1476. image,
  1477. color,
  1478. scale,
  1479. heightReference,
  1480. position
  1481. });
  1482. // merge in cesium options from openlayers feature
  1483. Object.assign(bbOptions, feature.get('cesiumOptions'));
  1484. if (imageStyle instanceof (ol_style_Icon_js__WEBPACK_IMPORTED_MODULE_1___default())) {
  1485. const anchor = imageStyle.getAnchor();
  1486. if (anchor) {
  1487. bbOptions.pixelOffset = new Cesium.Cartesian2((image.width / 2 - anchor[0]) * scale, (image.height / 2 - anchor[1]) * scale);
  1488. }
  1489. }
  1490. const bb = this.csAddBillboard(billboards, bbOptions, layer, feature, olGeometry, style);
  1491. if (opt_newBillboardCallback) {
  1492. opt_newBillboardCallback(bb);
  1493. }
  1494. }).bind(this);
  1495. if (image instanceof Image && !isImageLoaded(image)) {
  1496. // Cesium requires the image to be loaded
  1497. let cancelled = false;
  1498. const source = layer.getSource();
  1499. const canceller = function() {
  1500. cancelled = true;
  1501. };
  1502. source.on(['removefeature', 'clear'],
  1503. this.boundOnRemoveOrClearFeatureListener_);
  1504. let cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'];
  1505. if (!cancellers) {
  1506. cancellers = _util_js__WEBPACK_IMPORTED_MODULE_9__["default"].obj(source)['olcs_cancellers'] = {};
  1507. }
  1508. const fuid = (0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature);
  1509. if (cancellers[fuid]) {
  1510. // When the feature change quickly, a canceller may still be present so
  1511. // we cancel it here to prevent creation of a billboard.
  1512. cancellers[fuid]();
  1513. }
  1514. cancellers[fuid] = canceller;
  1515. const listener = function() {
  1516. image.removeEventListener('load', listener);
  1517. if (!billboards.isDestroyed() && !cancelled) {
  1518. // Create billboard if the feature is still displayed on the map.
  1519. reallyCreateBillboard();
  1520. }
  1521. };
  1522. image.addEventListener('load', listener);
  1523. } else {
  1524. reallyCreateBillboard();
  1525. }
  1526. }
  1527. /**
  1528. * Convert a point geometry to a Cesium BillboardCollection.
  1529. * @param {ol.layer.Vector|ol.layer.Image} layer
  1530. * @param {!ol.Feature} feature OpenLayers feature..
  1531. * @param {!ol.geom.Point} olGeometry OpenLayers point geometry.
  1532. * @param {!ol.ProjectionLike} projection
  1533. * @param {!ol.style.Style} style
  1534. * @param {!Cesium.BillboardCollection} billboards
  1535. * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when
  1536. * the new billboard is added.
  1537. * @return {Cesium.Primitive} primitives
  1538. * @api
  1539. */
  1540. olPointGeometryToCesium(
  1541. layer,
  1542. feature,
  1543. olGeometry,
  1544. projection,
  1545. style,
  1546. billboards,
  1547. opt_newBillboardCallback
  1548. ) {
  1549. console.assert(olGeometry.getType() == 'Point');
  1550. olGeometry = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].olGeometryCloneTo4326(olGeometry, projection);
  1551. let modelPrimitive = null;
  1552. const imageStyle = style.getImage();
  1553. if (imageStyle) {
  1554. const olcsModelFunction = /** @type {function():olcsx.ModelStyle} */ (olGeometry.get('olcs_model') || feature.get('olcs_model'));
  1555. if (olcsModelFunction) {
  1556. const olcsModel = olcsModelFunction();
  1557. const options = /** @type {Cesium.ModelFromGltfOptions} */ (Object.assign({}, {scene: this.scene}, olcsModel.cesiumOptions));
  1558. const model = Cesium.Model.fromGltf(options);
  1559. modelPrimitive = new Cesium.PrimitiveCollection();
  1560. modelPrimitive.add(model);
  1561. if (olcsModel.debugModelMatrix) {
  1562. modelPrimitive.add(new Cesium.DebugModelMatrixPrimitive({
  1563. modelMatrix: olcsModel.debugModelMatrix
  1564. }));
  1565. }
  1566. } else {
  1567. this.createBillboardFromImage(layer, feature, olGeometry, projection, style, imageStyle, billboards, opt_newBillboardCallback);
  1568. }
  1569. }
  1570. if (style.getText()) {
  1571. return this.addTextStyle(layer, feature, olGeometry, style, modelPrimitive || new Cesium.Primitive());
  1572. } else {
  1573. return modelPrimitive;
  1574. }
  1575. }
  1576. /**
  1577. * Convert an OpenLayers multi-something geometry to Cesium.
  1578. * @param {ol.layer.Vector|ol.layer.Image} layer
  1579. * @param {!ol.Feature} feature OpenLayers feature..
  1580. * @param {!ol.geom.Geometry} geometry OpenLayers geometry.
  1581. * @param {!ol.ProjectionLike} projection
  1582. * @param {!ol.style.Style} olStyle
  1583. * @param {!Cesium.BillboardCollection} billboards
  1584. * @param {function(!Cesium.Billboard)=} opt_newBillboardCallback Called when
  1585. * the new billboard is added.
  1586. * @return {Cesium.Primitive} primitives
  1587. * @api
  1588. */
  1589. olMultiGeometryToCesium(
  1590. layer,
  1591. feature,
  1592. geometry,
  1593. projection,
  1594. olStyle,
  1595. billboards,
  1596. opt_newBillboardCallback
  1597. ) {
  1598. // Do not reproject to 4326 now because it will be done later.
  1599. // FIXME: would be better to combine all child geometries in one primitive
  1600. // instead we create n primitives for simplicity.
  1601. const accumulate = function(geometries, functor) {
  1602. const primitives = new Cesium.PrimitiveCollection();
  1603. geometries.forEach((geometry) => {
  1604. primitives.add(functor(layer, feature, geometry, projection, olStyle));
  1605. });
  1606. return primitives;
  1607. };
  1608. let subgeos;
  1609. switch (geometry.getType()) {
  1610. case 'MultiPoint':
  1611. geometry = /** @type {!ol.geom.MultiPoint} */ (geometry);
  1612. subgeos = geometry.getPoints();
  1613. if (olStyle.getText()) {
  1614. const primitives = new Cesium.PrimitiveCollection();
  1615. subgeos.forEach((geometry) => {
  1616. console.assert(geometry);
  1617. const result = this.olPointGeometryToCesium(layer, feature, geometry,
  1618. projection, olStyle, billboards, opt_newBillboardCallback);
  1619. if (result) {
  1620. primitives.add(result);
  1621. }
  1622. });
  1623. return primitives;
  1624. } else {
  1625. subgeos.forEach((geometry) => {
  1626. console.assert(geometry);
  1627. this.olPointGeometryToCesium(layer, feature, geometry, projection,
  1628. olStyle, billboards, opt_newBillboardCallback);
  1629. });
  1630. return null;
  1631. }
  1632. case 'MultiLineString':
  1633. geometry = /** @type {!ol.geom.MultiLineString} */ (geometry);
  1634. subgeos = geometry.getLineStrings();
  1635. return accumulate(subgeos, this.olLineStringGeometryToCesium.bind(this));
  1636. case 'MultiPolygon':
  1637. geometry = /** @type {!ol.geom.MultiPolygon} */ (geometry);
  1638. subgeos = geometry.getPolygons();
  1639. return accumulate(subgeos, this.olPolygonGeometryToCesium.bind(this));
  1640. default:
  1641. console.assert(false, `Unhandled multi geometry type${geometry.getType()}`);
  1642. }
  1643. }
  1644. /**
  1645. * Convert an OpenLayers text style to Cesium.
  1646. * @param {ol.layer.Vector|ol.layer.Image} layer
  1647. * @param {!ol.Feature} feature OpenLayers feature..
  1648. * @param {!ol.geom.Geometry} geometry
  1649. * @param {!ol.style.Text} style
  1650. * @return {Cesium.LabelCollection} Cesium primitive
  1651. * @api
  1652. */
  1653. olGeometry4326TextPartToCesium(layer, feature, geometry, style) {
  1654. const text = style.getText();
  1655. if (!text) {
  1656. return null;
  1657. }
  1658. const labels = new Cesium.LabelCollection({scene: this.scene});
  1659. // TODO: export and use the text draw position from OpenLayers .
  1660. // See src/ol/render/vector.js
  1661. const extentCenter = (0,ol_extent_js__WEBPACK_IMPORTED_MODULE_5__.getCenter)(geometry.getExtent());
  1662. if (geometry instanceof (ol_geom_SimpleGeometry_js__WEBPACK_IMPORTED_MODULE_6___default())) {
  1663. const first = geometry.getFirstCoordinate();
  1664. extentCenter[2] = first.length == 3 ? first[2] : 0.0;
  1665. }
  1666. const options = /** @type {Cesium.optionsLabelCollection} */ ({});
  1667. options.position = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].ol4326CoordinateToCesiumCartesian(extentCenter);
  1668. options.text = text;
  1669. options.heightReference = this.getHeightReference(layer, feature, geometry);
  1670. const offsetX = style.getOffsetX();
  1671. const offsetY = style.getOffsetY();
  1672. if (offsetX != 0 && offsetY != 0) {
  1673. const offset = new Cesium.Cartesian2(offsetX, offsetY);
  1674. options.pixelOffset = offset;
  1675. }
  1676. options.font = style.getFont() || '10px sans-serif'; // OpenLayers default
  1677. let labelStyle = undefined;
  1678. if (style.getFill()) {
  1679. options.fillColor = this.extractColorFromOlStyle(style, false);
  1680. labelStyle = Cesium.LabelStyle.FILL;
  1681. }
  1682. if (style.getStroke()) {
  1683. options.outlineWidth = this.extractLineWidthFromOlStyle(style);
  1684. options.outlineColor = this.extractColorFromOlStyle(style, true);
  1685. labelStyle = Cesium.LabelStyle.OUTLINE;
  1686. }
  1687. if (style.getFill() && style.getStroke()) {
  1688. labelStyle = Cesium.LabelStyle.FILL_AND_OUTLINE;
  1689. }
  1690. options.style = labelStyle;
  1691. let horizontalOrigin;
  1692. switch (style.getTextAlign()) {
  1693. case 'left':
  1694. horizontalOrigin = Cesium.HorizontalOrigin.LEFT;
  1695. break;
  1696. case 'right':
  1697. horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;
  1698. break;
  1699. case 'center':
  1700. default:
  1701. horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
  1702. }
  1703. options.horizontalOrigin = horizontalOrigin;
  1704. if (style.getTextBaseline()) {
  1705. let verticalOrigin;
  1706. switch (style.getTextBaseline()) {
  1707. case 'top':
  1708. verticalOrigin = Cesium.VerticalOrigin.TOP;
  1709. break;
  1710. case 'middle':
  1711. verticalOrigin = Cesium.VerticalOrigin.CENTER;
  1712. break;
  1713. case 'bottom':
  1714. verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
  1715. break;
  1716. case 'alphabetic':
  1717. verticalOrigin = Cesium.VerticalOrigin.TOP;
  1718. break;
  1719. case 'hanging':
  1720. verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
  1721. break;
  1722. default:
  1723. console.assert(false, `unhandled baseline ${style.getTextBaseline()}`);
  1724. }
  1725. options.verticalOrigin = verticalOrigin;
  1726. }
  1727. const l = labels.add(options);
  1728. this.setReferenceForPicking(layer, feature, l);
  1729. return labels;
  1730. }
  1731. /**
  1732. * Convert an OpenLayers style to a Cesium Material.
  1733. * @param {ol.Feature} feature OpenLayers feature..
  1734. * @param {!ol.style.Style} style
  1735. * @param {boolean} outline
  1736. * @return {Cesium.Material}
  1737. * @api
  1738. */
  1739. olStyleToCesium(feature, style, outline) {
  1740. const fill = style.getFill();
  1741. const stroke = style.getStroke();
  1742. if ((outline && !stroke) || (!outline && !fill)) {
  1743. return null; // FIXME use a default style? Developer error?
  1744. }
  1745. let color = outline ? stroke.getColor() : fill.getColor();
  1746. color = _core_js__WEBPACK_IMPORTED_MODULE_7__["default"].convertColorToCesium(color);
  1747. if (outline && stroke.getLineDash()) {
  1748. return Cesium.Material.fromType('Stripe', {
  1749. // always update Cesium externs before adding a property
  1750. horizontal: false,
  1751. repeat: 500, // TODO how to calculate this?
  1752. evenColor: color,
  1753. oddColor: new Cesium.Color(0, 0, 0, 0) // transparent
  1754. });
  1755. } else {
  1756. return Cesium.Material.fromType('Color', {
  1757. // always update Cesium externs before adding a property
  1758. color
  1759. });
  1760. }
  1761. }
  1762. /**
  1763. * Compute OpenLayers plain style.
  1764. * Evaluates style function, blend arrays, get default style.
  1765. * @param {ol.layer.Vector|ol.layer.Image} layer
  1766. * @param {!ol.Feature} feature
  1767. * @param {ol.StyleFunction|undefined} fallbackStyleFunction
  1768. * @param {number} resolution
  1769. * @return {Array.<!ol.style.Style>} null if no style is available
  1770. * @api
  1771. */
  1772. computePlainStyle(layer, feature, fallbackStyleFunction, resolution) {
  1773. /**
  1774. * @type {ol.FeatureStyleFunction|undefined}
  1775. */
  1776. const featureStyleFunction = feature.getStyleFunction();
  1777. /**
  1778. * @type {ol.style.Style|Array.<ol.style.Style>}
  1779. */
  1780. let style = null;
  1781. if (featureStyleFunction) {
  1782. style = featureStyleFunction(feature, resolution);
  1783. }
  1784. if (!style && fallbackStyleFunction) {
  1785. style = fallbackStyleFunction(feature, resolution);
  1786. }
  1787. if (!style) {
  1788. // The feature must not be displayed
  1789. return null;
  1790. }
  1791. // FIXME combine materials as in cesium-materials-pack?
  1792. // then this function must return a custom material
  1793. // More simply, could blend the colors like described in
  1794. // http://en.wikipedia.org/wiki/Alpha_compositing
  1795. return Array.isArray(style) ? style : [style];
  1796. }
  1797. /**
  1798. * @protected
  1799. * @param {!ol.Feature} feature
  1800. * @param {!ol.style.Style} style
  1801. * @param {!ol.geom.Geometry=} opt_geom Geometry to be converted.
  1802. * @return {ol.geom.Geometry|undefined}
  1803. */
  1804. getGeometryFromFeature(feature, style, opt_geom) {
  1805. if (opt_geom) {
  1806. return opt_geom;
  1807. }
  1808. const geom3d = /** @type {!ol.geom.Geometry} */(feature.get('olcs.3d_geometry'));
  1809. if (geom3d && geom3d instanceof (ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default())) {
  1810. return geom3d;
  1811. }
  1812. if (style) {
  1813. const geomFuncRes = style.getGeometryFunction()(feature);
  1814. if (geomFuncRes instanceof (ol_geom_Geometry_js__WEBPACK_IMPORTED_MODULE_0___default())) {
  1815. return geomFuncRes;
  1816. }
  1817. }
  1818. return feature.getGeometry();
  1819. }
  1820. /**
  1821. * Convert one OpenLayers feature up to a collection of Cesium primitives.
  1822. * @param {ol.layer.Vector|ol.layer.Image} layer
  1823. * @param {!ol.Feature} feature OpenLayers feature.
  1824. * @param {!ol.style.Style} style
  1825. * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context
  1826. * @param {!ol.geom.Geometry=} opt_geom Geometry to be converted.
  1827. * @return {Cesium.Primitive} primitives
  1828. * @api
  1829. */
  1830. olFeatureToCesium(layer, feature, style, context, opt_geom) {
  1831. let geom = this.getGeometryFromFeature(feature, style, opt_geom);
  1832. if (!geom) {
  1833. // OpenLayers features may not have a geometry
  1834. // See http://geojson.org/geojson-spec.html#feature-objects
  1835. return null;
  1836. }
  1837. const proj = context.projection;
  1838. const newBillboardAddedCallback = function(bb) {
  1839. const featureBb = context.featureToCesiumMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)];
  1840. if (featureBb instanceof Array) {
  1841. featureBb.push(bb);
  1842. }
  1843. else {
  1844. context.featureToCesiumMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)] = [bb];
  1845. }
  1846. };
  1847. switch (geom.getType()) {
  1848. case 'GeometryCollection':
  1849. const primitives = new Cesium.PrimitiveCollection();
  1850. const collection = /** @type {!ol.geom.GeometryCollection} */ (geom);
  1851. // TODO: use getGeometriesArray() instead
  1852. collection.getGeometries().forEach((geom) => {
  1853. if (geom) {
  1854. const prims = this.olFeatureToCesium(layer, feature, style, context,
  1855. geom);
  1856. if (prims) {
  1857. primitives.add(prims);
  1858. }
  1859. }
  1860. });
  1861. return primitives;
  1862. case 'Point':
  1863. geom = /** @type {!ol.geom.Point} */ (geom);
  1864. const bbs = context.billboards;
  1865. const result = this.olPointGeometryToCesium(layer, feature, geom, proj,
  1866. style, bbs, newBillboardAddedCallback);
  1867. if (!result) {
  1868. // no wrapping primitive
  1869. return null;
  1870. } else {
  1871. return result;
  1872. }
  1873. case 'Circle':
  1874. geom = /** @type {!ol.geom.Circle} */ (geom);
  1875. return this.olCircleGeometryToCesium(layer, feature, geom, proj,
  1876. style);
  1877. case 'LineString':
  1878. geom = /** @type {!ol.geom.LineString} */ (geom);
  1879. return this.olLineStringGeometryToCesium(layer, feature, geom, proj,
  1880. style);
  1881. case 'Polygon':
  1882. geom = /** @type {!ol.geom.Polygon} */ (geom);
  1883. return this.olPolygonGeometryToCesium(layer, feature, geom, proj,
  1884. style);
  1885. case 'MultiPoint':
  1886. case 'MultiLineString':
  1887. case 'MultiPolygon':
  1888. const result2 = this.olMultiGeometryToCesium(layer, feature, geom, proj,
  1889. style, context.billboards, newBillboardAddedCallback);
  1890. if (!result2) {
  1891. // no wrapping primitive
  1892. return null;
  1893. } else {
  1894. return result2;
  1895. }
  1896. case 'LinearRing':
  1897. throw new Error('LinearRing should only be part of polygon.');
  1898. default:
  1899. throw new Error(`Ol geom type not handled : ${geom.getType()}`);
  1900. }
  1901. }
  1902. /**
  1903. * Convert an OpenLayers vector layer to Cesium primitive collection.
  1904. * For each feature, the associated primitive will be stored in
  1905. * `featurePrimitiveMap`.
  1906. * @param {!(ol.layer.Vector|ol.layer.Image)} olLayer
  1907. * @param {!ol.View} olView
  1908. * @param {!Object.<number, !Cesium.Primitive>} featurePrimitiveMap
  1909. * @return {!olcs.core.VectorLayerCounterpart}
  1910. * @api
  1911. */
  1912. olVectorLayerToCesium(olLayer, olView, featurePrimitiveMap) {
  1913. const proj = olView.getProjection();
  1914. const resolution = olView.getResolution();
  1915. if (resolution === undefined || !proj) {
  1916. console.assert(false, 'View not ready');
  1917. // an assertion is not enough for closure to assume resolution and proj
  1918. // are defined
  1919. throw new Error('View not ready');
  1920. }
  1921. let source = olLayer.getSource();
  1922. if (source instanceof (ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_3___default())) {
  1923. source = source.getSource();
  1924. }
  1925. console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_2___default()));
  1926. const features = source.getFeatures();
  1927. const counterpart = new _core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_8__["default"](proj, this.scene);
  1928. const context = counterpart.context;
  1929. for (let i = 0; i < features.length; ++i) {
  1930. const feature = features[i];
  1931. if (!feature) {
  1932. continue;
  1933. }
  1934. /**
  1935. * @type {ol.StyleFunction|undefined}
  1936. */
  1937. const layerStyle = olLayer.getStyleFunction();
  1938. const styles = this.computePlainStyle(olLayer, feature, layerStyle,
  1939. resolution);
  1940. if (!styles || !styles.length) {
  1941. // only 'render' features with a style
  1942. continue;
  1943. }
  1944. /**
  1945. * @type {Cesium.Primitive|null}
  1946. */
  1947. let primitives = null;
  1948. for (let i = 0; i < styles.length; i++) {
  1949. const prims = this.olFeatureToCesium(olLayer, feature, styles[i], context);
  1950. if (prims) {
  1951. if (!primitives) {
  1952. primitives = prims;
  1953. } else if (prims) {
  1954. let i = 0, prim;
  1955. while ((prim = prims.get(i))) {
  1956. primitives.add(prim);
  1957. i++;
  1958. }
  1959. }
  1960. }
  1961. }
  1962. if (!primitives) {
  1963. continue;
  1964. }
  1965. featurePrimitiveMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_9__.getUid)(feature)] = primitives;
  1966. counterpart.getRootPrimitive().add(primitives);
  1967. }
  1968. return counterpart;
  1969. }
  1970. /**
  1971. * Convert an OpenLayers feature to Cesium primitive collection.
  1972. * @param {!(ol.layer.Vector|ol.layer.Image)} layer
  1973. * @param {!ol.View} view
  1974. * @param {!ol.Feature} feature
  1975. * @param {!import('olcs/core/VectorLayerConterpart.js').OlFeatureToCesiumContext} context
  1976. * @return {Cesium.Primitive}
  1977. * @api
  1978. */
  1979. convert(layer, view, feature, context) {
  1980. const proj = view.getProjection();
  1981. const resolution = view.getResolution();
  1982. if (resolution == undefined || !proj) {
  1983. return null;
  1984. }
  1985. /**
  1986. * @type {ol.StyleFunction|undefined}
  1987. */
  1988. const layerStyle = layer.getStyleFunction();
  1989. const styles = this.computePlainStyle(layer, feature, layerStyle, resolution);
  1990. if (!styles || !styles.length) {
  1991. // only 'render' features with a style
  1992. return null;
  1993. }
  1994. context.projection = proj;
  1995. /**
  1996. * @type {Cesium.Primitive|null}
  1997. */
  1998. let primitives = null;
  1999. for (let i = 0; i < styles.length; i++) {
  2000. const prims = this.olFeatureToCesium(layer, feature, styles[i], context);
  2001. if (!primitives) {
  2002. primitives = prims;
  2003. } else if (prims) {
  2004. let i = 0, prim;
  2005. while ((prim = prims.get(i))) {
  2006. primitives.add(prim);
  2007. i++;
  2008. }
  2009. }
  2010. }
  2011. return primitives;
  2012. }
  2013. }
  2014. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (FeatureConverter);
  2015. /***/ }),
  2016. /***/ "./src/olcs/MVTImageryProvider.js":
  2017. /*!****************************************!*\
  2018. !*** ./src/olcs/MVTImageryProvider.js ***!
  2019. \****************************************/
  2020. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  2021. __webpack_require__.r(__webpack_exports__);
  2022. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  2023. /* harmony export */ "default": () => (/* binding */ MVTImageryProvider)
  2024. /* harmony export */ });
  2025. /* harmony import */ var ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/format/MVT.js */ "ol/format/MVT.js");
  2026. /* harmony import */ var ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0__);
  2027. /* harmony import */ var ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/style/Style.js */ "ol/style/Style.js");
  2028. /* harmony import */ var ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1__);
  2029. /* harmony import */ var ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/style/Stroke.js */ "ol/style/Stroke.js");
  2030. /* harmony import */ var ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2__);
  2031. /* harmony import */ var ol_render_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/render.js */ "ol/render.js");
  2032. /* harmony import */ var ol_render_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_render_js__WEBPACK_IMPORTED_MODULE_3__);
  2033. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  2034. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_4__);
  2035. /* harmony import */ var ol_util_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/util.js */ "ol/util.js");
  2036. /* harmony import */ var ol_util_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_util_js__WEBPACK_IMPORTED_MODULE_5__);
  2037. /* harmony import */ var ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/structs/LRUCache.js */ "ol/structs/LRUCache.js");
  2038. /* harmony import */ var ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6__);
  2039. /* harmony import */ var ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ol/tilegrid.js */ "ol/tilegrid.js");
  2040. /* harmony import */ var ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__);
  2041. /* harmony import */ var ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ol/tileurlfunction.js */ "ol/tileurlfunction.js");
  2042. /* harmony import */ var ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__);
  2043. const format = new (ol_format_MVT_js__WEBPACK_IMPORTED_MODULE_0___default())();
  2044. const styles = [new (ol_style_Style_js__WEBPACK_IMPORTED_MODULE_1___default())({
  2045. stroke: new (ol_style_Stroke_js__WEBPACK_IMPORTED_MODULE_2___default())({
  2046. color: 'blue',
  2047. width: 2
  2048. })
  2049. })];
  2050. class MVTImageryProvider {
  2051. constructor(options) {
  2052. this.urls = options.urls;
  2053. this.ready = true;
  2054. this.readyPromise = Promise.resolve(true);
  2055. this.tileWidth = 256;
  2056. this.tileHeight = 256;
  2057. this.maximumLevel = options.maximumLevel || 20;
  2058. this.minimumLevel = options.minimumLevel || 0;
  2059. this.tilingScheme = new Cesium.WebMercatorTilingScheme;
  2060. this.rectangle = options.rectangle || this.tilingScheme.rectangle;
  2061. this.errorEvent = new Cesium.Event();
  2062. this.credit = options.credit;
  2063. this.hasAlphaChannel = true;
  2064. this.styleFunction_ = options.styleFunction || (() => styles);
  2065. this.projection_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_4__.get)('EPSG:3857');
  2066. this.emptyCanvas_ = document.createElement('canvas');
  2067. this.emptyCanvas_.width = 1;
  2068. this.emptyCanvas_.height = 1;
  2069. this.tileRectangle_ = new Cesium.Rectangle();
  2070. const cacheSize = options.cacheSize !== undefined ? options.cacheSize : 50;
  2071. this.tileCache = new (ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default())(cacheSize);
  2072. this.featureCache = options.featureCache || new (ol_structs_LRUCache_js__WEBPACK_IMPORTED_MODULE_6___default())(cacheSize);
  2073. // to avoid too frequent cache grooming we allow x2 capacity
  2074. const tileGrid = (0,ol_tilegrid_js__WEBPACK_IMPORTED_MODULE_7__.getForProjection)(this.projection_);
  2075. this.tileFunction_ = (0,ol_tileurlfunction_js__WEBPACK_IMPORTED_MODULE_8__.createFromTemplates)(this.urls, tileGrid);
  2076. }
  2077. getTileCredits() {
  2078. return [];
  2079. }
  2080. pickFeatures() {
  2081. }
  2082. getTileFeatures(z, x, y) {
  2083. const cacheKey = this.getCacheKey_(z, x, y);
  2084. let promise;
  2085. if (this.featureCache.containsKey(cacheKey)) {
  2086. promise = this.featureCache.get(cacheKey);
  2087. }
  2088. if (!promise) {
  2089. const url = this.getUrl_(z, x, y);
  2090. promise = fetch(url)
  2091. .then(r => (r.ok ? r : Promise.reject(r)))
  2092. .then(r => r.arrayBuffer())
  2093. .then(buffer => this.readFeaturesFromBuffer(buffer));
  2094. this.featureCache.set(cacheKey, promise);
  2095. if (this.featureCache.getCount() > 2 * this.featureCache.highWaterMark) {
  2096. while (this.featureCache.canExpireCache()) {
  2097. this.featureCache.pop();
  2098. }
  2099. }
  2100. }
  2101. return promise;
  2102. }
  2103. readFeaturesFromBuffer(buffer) {
  2104. let options;
  2105. if (ol_util_js__WEBPACK_IMPORTED_MODULE_5__.VERSION <= '6.4.4') {
  2106. // See https://github.com/openlayers/openlayers/pull/11540
  2107. options = {
  2108. extent: [0, 0, 4096, 4096],
  2109. dataProjection: format.dataProjection,
  2110. featureProjection: format.dataProjection
  2111. };
  2112. }
  2113. const features = format.readFeatures(buffer, options);
  2114. const scaleFactor = this.tileWidth / 4096;
  2115. features.forEach((f) => {
  2116. const flatCoordinates = f.getFlatCoordinates();
  2117. let flip = false;
  2118. for (let i = 0; i < flatCoordinates.length; ++i) {
  2119. flatCoordinates[i] *= scaleFactor;
  2120. if (flip) {
  2121. // FIXME: why do we need this now?
  2122. flatCoordinates[i] = this.tileWidth - flatCoordinates[i];
  2123. }
  2124. if (ol_util_js__WEBPACK_IMPORTED_MODULE_5__.VERSION <= '6.4.4') {
  2125. flip = !flip;
  2126. }
  2127. }
  2128. });
  2129. return features;
  2130. }
  2131. getUrl_(z, x, y) {
  2132. const url = this.tileFunction_([z, x, y]);
  2133. return url;
  2134. }
  2135. getCacheKey_(z, x, y) {
  2136. return `${z}_${x}_${y}`;
  2137. }
  2138. requestImage(x, y, z, request) {
  2139. if (z < this.minimumLevel) {
  2140. return this.emptyCanvas_;
  2141. }
  2142. try {
  2143. const cacheKey = this.getCacheKey_(z, x, y);
  2144. let promise;
  2145. if (this.tileCache.containsKey(cacheKey)) {
  2146. promise = this.tileCache.get(cacheKey);
  2147. }
  2148. if (!promise) {
  2149. promise = this.getTileFeatures(z, x, y)
  2150. .then((features) => {
  2151. // FIXME: here we suppose the 2D projection is in meters
  2152. this.tilingScheme.tileXYToNativeRectangle(x, y, z, this.tileRectangle_);
  2153. const resolution = (this.tileRectangle_.east - this.tileRectangle_.west) / this.tileWidth;
  2154. return this.rasterizeFeatures(features, this.styleFunction_, resolution);
  2155. });
  2156. this.tileCache.set(cacheKey, promise);
  2157. if (this.tileCache.getCount() > 2 * this.tileCache.highWaterMark) {
  2158. while (this.tileCache.canExpireCache()) {
  2159. this.tileCache.pop();
  2160. }
  2161. }
  2162. }
  2163. return promise;
  2164. } catch (e) {
  2165. console.trace(e);
  2166. this.raiseEvent('could not render pbf to tile', e);
  2167. }
  2168. }
  2169. rasterizeFeatures(features, styleFunction, resolution) {
  2170. const canvas = document.createElement('canvas');
  2171. const vectorContext = (0,ol_render_js__WEBPACK_IMPORTED_MODULE_3__.toContext)(canvas.getContext('2d'), {size: [this.tileWidth, this.tileHeight]});
  2172. features.forEach((f) => {
  2173. const styles = styleFunction(f, resolution);
  2174. if (styles) {
  2175. styles.forEach((style) => {
  2176. vectorContext.setStyle(style);
  2177. vectorContext.drawGeometry(f);
  2178. });
  2179. }
  2180. });
  2181. return canvas;
  2182. }
  2183. }
  2184. /***/ }),
  2185. /***/ "./src/olcs/OLCesium.js":
  2186. /*!******************************!*\
  2187. !*** ./src/olcs/OLCesium.js ***!
  2188. \******************************/
  2189. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  2190. __webpack_require__.r(__webpack_exports__);
  2191. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  2192. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  2193. /* harmony export */ });
  2194. /* harmony import */ var ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/geom/Point.js */ "ol/geom/Point.js");
  2195. /* harmony import */ var ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0__);
  2196. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  2197. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_1__);
  2198. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  2199. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js");
  2200. /* harmony import */ var _AutoRenderLoop_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./AutoRenderLoop.js */ "./src/olcs/AutoRenderLoop.js");
  2201. /* harmony import */ var _Camera_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Camera.js */ "./src/olcs/Camera.js");
  2202. /* harmony import */ var _RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./RasterSynchronizer.js */ "./src/olcs/RasterSynchronizer.js");
  2203. /* harmony import */ var _VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./VectorSynchronizer.js */ "./src/olcs/VectorSynchronizer.js");
  2204. /* harmony import */ var _OverlaySynchronizer_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./OverlaySynchronizer.js */ "./src/olcs/OverlaySynchronizer.js");
  2205. /**
  2206. * @module olcs.OLCesium
  2207. */
  2208. /**
  2209. * @typedef {Object} OLCesiumOptions
  2210. * @property {import('ol/Map.js').default} map The OpenLayers map we want to show on a Cesium scene.
  2211. * @property {Cesium.Viewer} [viewer] Cesium viewer.
  2212. * @property {function(!import('ol/Map.js').default, !Cesium.Scene, !Cesium.DataSourceCollection): Array<import('olcs/AbstractSynchronizer.js').default>}
  2213. * [createSynchronizers] Callback function which will be called by the {@link olcs.OLCesium}
  2214. * constructor to create custom synchronizers. Receives an `ol.Map` and a `Cesium.Scene` as arguments,
  2215. * and needs to return an array of {@link import('olcs/AbstractSynchronizer.js').default}.
  2216. * @property {function(): Cesium.JulianDate} [time] Control the current time used by Cesium.
  2217. * @property {boolean} [stopOpenLayersEventsPropagation] Prevent propagation of mouse/touch events to
  2218. * OpenLayers when Cesium is active.
  2219. */
  2220. class OLCesium {
  2221. /**
  2222. * @param {!OLCesiumOptions} options Options.
  2223. * @constructor
  2224. * @api
  2225. */
  2226. constructor(options) {
  2227. /**
  2228. * @type {olcs.AutoRenderLoop}
  2229. * @private
  2230. */
  2231. this.autoRenderLoop_ = null;
  2232. /**
  2233. * @type {!ol.Map}
  2234. * @private
  2235. */
  2236. this.map_ = options.map;
  2237. /**
  2238. * @type {!function(): Cesium.JulianDate}
  2239. * @private
  2240. */
  2241. this.time_ = options.time || function() {
  2242. return Cesium.JulianDate.now();
  2243. };
  2244. /**
  2245. * No change of the view projection.
  2246. * @private
  2247. */
  2248. this.to4326Transform_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_1__.getTransform)(this.map_.getView().getProjection(), 'EPSG:4326');
  2249. /**
  2250. * @type {number}
  2251. * @private
  2252. */
  2253. this.resolutionScale_ = 1.0;
  2254. /**
  2255. * @type {number}
  2256. * @private
  2257. */
  2258. this.canvasClientWidth_ = 0.0;
  2259. /**
  2260. * @type {number}
  2261. * @private
  2262. */
  2263. this.canvasClientHeight_ = 0.0;
  2264. /**
  2265. * @type {boolean}
  2266. * @private
  2267. */
  2268. this.resolutionScaleChanged_ = true; // force resize
  2269. const fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;';
  2270. /**
  2271. * @type {!Element}
  2272. * @private
  2273. */
  2274. this.container_ = document.createElement('DIV');
  2275. const containerAttribute = document.createAttribute('style');
  2276. containerAttribute.value = `${fillArea}visibility:hidden;`;
  2277. this.container_.setAttributeNode(containerAttribute);
  2278. //火星科技添加
  2279. let viewer = options.viewer
  2280. viewer.container.appendChild(this.container_);
  2281. // /**
  2282. // * Whether the Cesium container is placed over the ol map.
  2283. // * a target => side by side mode
  2284. // * no target => over map mode
  2285. // * @type {boolean}
  2286. // * @private
  2287. // */
  2288. // this.isOverMap_ = false;
  2289. // if (this.isOverMap_ && options.stopOpenLayersEventsPropagation) {
  2290. // const overlayEvents = ['click', 'dblclick', 'mousedown', 'touchstart', 'MSPointerDown', 'pointerdown', 'mousewheel', 'wheel'];
  2291. // for (let i = 0, ii = overlayEvents.length; i < ii; ++i) {
  2292. // this.container_.addEventListener(overlayEvents[i], evt => evt.stopPropagation());
  2293. // }
  2294. // }
  2295. // /**
  2296. // * @type {!HTMLCanvasElement}
  2297. // * @private
  2298. // */
  2299. // this.canvas_ = /** @type {!HTMLCanvasElement} */ (document.createElement('CANVAS'));
  2300. // const canvasAttribute = document.createAttribute('style');
  2301. // canvasAttribute.value = fillArea;
  2302. // this.canvas_.setAttributeNode(canvasAttribute);
  2303. // if (olcsUtil.supportsImageRenderingPixelated()) {
  2304. // // non standard CSS4
  2305. // this.canvas_.style['imageRendering'] = olcsUtil.imageRenderingValue();
  2306. // }
  2307. // this.canvas_.oncontextmenu = function() { return false; };
  2308. // this.canvas_.onselectstart = function() { return false; };
  2309. // this.container_.appendChild(this.canvas_);
  2310. /**
  2311. * @type {boolean}
  2312. * @private
  2313. */
  2314. this.enabled_ = false;
  2315. /**
  2316. * @type {!Array.<ol.interaction.Interaction>}
  2317. * @private
  2318. */
  2319. this.pausedInteractions_ = [];
  2320. /**
  2321. * @type {?ol.layer.Group}
  2322. * @private
  2323. */
  2324. this.hiddenRootGroup_ = null;
  2325. // const sceneOptions = options.sceneOptions !== undefined ? options.sceneOptions :
  2326. // /** @type {Cesium.SceneOptions} */ ({});
  2327. // sceneOptions.canvas = this.canvas_;
  2328. // sceneOptions.scene3DOnly = true;
  2329. /**
  2330. * @type {!Cesium.Scene}
  2331. * @private
  2332. */
  2333. this.scene_ = viewer.scene;
  2334. // const sscc = this.scene_.screenSpaceCameraController;
  2335. // sscc.tiltEventTypes.push({
  2336. // 'eventType': Cesium.CameraEventType.LEFT_DRAG,
  2337. // 'modifier': Cesium.KeyboardEventModifier.SHIFT
  2338. // });
  2339. // sscc.tiltEventTypes.push({
  2340. // 'eventType': Cesium.CameraEventType.LEFT_DRAG,
  2341. // 'modifier': Cesium.KeyboardEventModifier.ALT
  2342. // });
  2343. // sscc.enableLook = false;
  2344. // this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
  2345. /**
  2346. * @type {!olcs.Camera}
  2347. * @private
  2348. */
  2349. this.camera_ = new _Camera_js__WEBPACK_IMPORTED_MODULE_5__["default"](this.scene_, this.map_);
  2350. /**
  2351. * @type {!Cesium.Globe}
  2352. * @private
  2353. */
  2354. this.globe_ = viewer.scene.globe;
  2355. // this.globe_.baseColor = Cesium.Color.WHITE;
  2356. // this.scene_.globe = this.globe_;
  2357. // this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere();
  2358. // The first layer of Cesium is special; using a 1x1 transparent image to workaround it.
  2359. // See https://github.com/AnalyticalGraphicsInc/cesium/issues/1323 for details.
  2360. // const firstImageryProvider = new Cesium.SingleTileImageryProvider({
  2361. // url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=',
  2362. // rectangle: Cesium.Rectangle.fromDegrees(0, 0, 1, 1) // the Rectangle dimensions are arbitrary
  2363. // });
  2364. // this.globe_.imageryLayers.addImageryProvider(firstImageryProvider, 0);
  2365. this.dataSourceCollection_ = viewer.dataSources
  2366. this.dataSourceDisplay_ = viewer.dataSourceDisplay
  2367. const synchronizers = options.createSynchronizers ?
  2368. options.createSynchronizers(this.map_, this.scene_, this.dataSourceCollection_) : [
  2369. new _RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_6__["default"](this.map_, this.scene_),
  2370. new _VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__["default"](this.map_, this.scene_),
  2371. new _OverlaySynchronizer_js__WEBPACK_IMPORTED_MODULE_8__["default"](this.map_, this.scene_)
  2372. ];
  2373. // Assures correct canvas size after initialisation
  2374. // this.handleResize_();
  2375. for (let i = synchronizers.length - 1; i >= 0; --i) {
  2376. synchronizers[i].synchronize();
  2377. }
  2378. // /**
  2379. // * Time of the last rendered frame, as returned by `performance.now()`.
  2380. // * @type {number}
  2381. // * @private
  2382. // */
  2383. // this.lastFrameTime_ = 0;
  2384. // /**
  2385. // * The identifier returned by `requestAnimationFrame`.
  2386. // * @type {number|undefined}
  2387. // * @private
  2388. // */
  2389. // this.renderId_ = undefined;
  2390. // /**
  2391. // * Target frame rate for the render loop.
  2392. // * @type {number}
  2393. // * @private
  2394. // */
  2395. // this.targetFrameRate_ = Number.POSITIVE_INFINITY;
  2396. // /**
  2397. // * If the Cesium render loop is being blocked.
  2398. // * @type {boolean}
  2399. // * @private
  2400. // */
  2401. // this.blockCesiumRendering_ = false;
  2402. // /**
  2403. // * If the warmup routine is active.
  2404. // * @type {boolean}
  2405. // * @private
  2406. // */
  2407. // this.warmingUp_ = false;
  2408. /**
  2409. * @type {ol.Feature}
  2410. * @private
  2411. */
  2412. this.trackedFeature_ = null;
  2413. /**
  2414. * @type {Cesium.Entity}
  2415. * @private
  2416. */
  2417. this.trackedEntity_ = null;
  2418. // /**
  2419. // * @type {Cesium.EntityView}
  2420. // * @private
  2421. // */
  2422. // this.entityView_ = null;
  2423. // /**
  2424. // * @type {boolean}
  2425. // * @private
  2426. // */
  2427. // this.needTrackedEntityUpdate_ = false;
  2428. // /**
  2429. // * @type {!Cesium.BoundingSphere}
  2430. // */
  2431. // this.boundingSphereScratch_ = new Cesium.BoundingSphere();
  2432. // const eventHelper = new Cesium.EventHelper();
  2433. // eventHelper.add(this.scene_.postRender, OLCesium.prototype.updateTrackedEntity_, this);
  2434. // Cesium has a mechanism to prevent the camera to go under the terrain.
  2435. // Unfortunately, it is only active when all the terrain has been loaded, which:
  2436. // - does not prevent the camera to sink under terrain anymore;
  2437. // - introduce a jumping effect once all terrain has been loaded and the position of the camera is finally fixed.
  2438. // The property below enables a workaround found in the Camptocamp Cesium fork.
  2439. // See also https://github.com/AnalyticalGraphicsInc/cesium/issues/5999.
  2440. // Cesium.Camera.enableSuspendTerrainAdjustment = false;
  2441. viewer.scene.postUpdate.addEventListener(this.onAnimationFrame_, this);
  2442. }
  2443. // /**
  2444. // * Render the Cesium scene.
  2445. // * @private
  2446. // */
  2447. // render_() {
  2448. // // // if a call to `requestAnimationFrame` is pending, cancel it
  2449. // // if (this.renderId_ !== undefined) {
  2450. // // cancelAnimationFrame(this.renderId_);
  2451. // // this.renderId_ = undefined;
  2452. // // }
  2453. // // // only render if Cesium is enabled/warming and rendering hasn't been blocked
  2454. // // if ((this.enabled_ || this.warmingUp_) && !this.blockCesiumRendering_) {
  2455. // // this.renderId_ = requestAnimationFrame(this.onAnimationFrame_.bind(this));
  2456. // // }
  2457. // }
  2458. /**
  2459. * Callback for `requestAnimationFrame`.
  2460. * @param {number} frameTime The frame time, from `performance.now()`.
  2461. * @private
  2462. */
  2463. onAnimationFrame_(frameTime) {
  2464. // this.renderId_ = undefined;
  2465. // // check if a frame was rendered within the target frame rate
  2466. // const interval = 1000.0 / this.targetFrameRate_;
  2467. // const delta = frameTime - this.lastFrameTime_;
  2468. // if (delta < interval) {
  2469. // // too soon, don't render yet
  2470. // this.render_();
  2471. // return;
  2472. // }
  2473. // time to render a frame, save the time
  2474. // this.lastFrameTime_ = frameTime;
  2475. // const julianDate = this.time_();
  2476. // this.scene_.initializeFrame();
  2477. // this.handleResize_();
  2478. // this.dataSourceDisplay_.update(julianDate);
  2479. // // Update tracked entity
  2480. // if (this.entityView_) {
  2481. // const trackedEntity = this.trackedEntity_;
  2482. // const trackedState = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_);
  2483. // if (trackedState === Cesium.BoundingSphereState.DONE) {
  2484. // this.boundingSphereScratch_.radius = 1; // a radius of 1 is enough for tracking points
  2485. // this.entityView_.update(julianDate, this.boundingSphereScratch_);
  2486. // }
  2487. // }
  2488. // this.scene_.render(julianDate);
  2489. this.camera_.checkCameraChange();
  2490. // request the next render call after this one completes to ensure the browser doesn't get backed up
  2491. // this.render_();
  2492. }
  2493. /**
  2494. * @private
  2495. */
  2496. // updateTrackedEntity_() {
  2497. // if (!this.needTrackedEntityUpdate_) {
  2498. // return;
  2499. // }
  2500. // const trackedEntity = this.trackedEntity_;
  2501. // const scene = this.scene_;
  2502. // const state = this.dataSourceDisplay_.getBoundingSphere(trackedEntity, false, this.boundingSphereScratch_);
  2503. // if (state === Cesium.BoundingSphereState.PENDING) {
  2504. // return;
  2505. // }
  2506. // scene.screenSpaceCameraController.enableTilt = false;
  2507. // const bs = state !== Cesium.BoundingSphereState.FAILED ? this.boundingSphereScratch_ : undefined;
  2508. // if (bs) {
  2509. // bs.radius = 1;
  2510. // }
  2511. // this.entityView_ = new Cesium.EntityView(trackedEntity, scene, scene.mapProjection.ellipsoid);
  2512. // this.entityView_.update(this.time_(), bs);
  2513. // this.needTrackedEntityUpdate_ = false;
  2514. // }
  2515. // /**
  2516. // * @private
  2517. // */
  2518. // handleResize_() {
  2519. // let width = this.canvas_.clientWidth;
  2520. // let height = this.canvas_.clientHeight;
  2521. // if (width === 0 | height === 0) {
  2522. // // The canvas DOM element is not ready yet.
  2523. // return;
  2524. // }
  2525. // if (width === this.canvasClientWidth_ &&
  2526. // height === this.canvasClientHeight_ &&
  2527. // !this.resolutionScaleChanged_) {
  2528. // return;
  2529. // }
  2530. // let resolutionScale = this.resolutionScale_;
  2531. // if (!olcsUtil.supportsImageRenderingPixelated()) {
  2532. // resolutionScale *= window.devicePixelRatio || 1.0;
  2533. // }
  2534. // this.resolutionScaleChanged_ = false;
  2535. // this.canvasClientWidth_ = width;
  2536. // this.canvasClientHeight_ = height;
  2537. // width *= resolutionScale;
  2538. // height *= resolutionScale;
  2539. // this.canvas_.width = width;
  2540. // this.canvas_.height = height;
  2541. // // this.scene_.camera.frustum.aspectRatio = width / height;
  2542. // }
  2543. /**
  2544. * @return {!olcs.Camera}
  2545. * @api
  2546. */
  2547. getCamera() {
  2548. return this.camera_;
  2549. }
  2550. /**
  2551. * @return {!ol.Map}
  2552. * @api
  2553. */
  2554. getOlMap() {
  2555. return this.map_;
  2556. }
  2557. /**
  2558. * @return {!ol.View}
  2559. * @api
  2560. */
  2561. getOlView() {
  2562. const view = this.map_.getView();
  2563. console.assert(view);
  2564. return view;
  2565. }
  2566. /**
  2567. * @return {!Cesium.Scene}
  2568. * @api
  2569. */
  2570. getCesiumScene() {
  2571. return this.scene_;
  2572. }
  2573. /**
  2574. * @return {!Cesium.DataSourceCollection}
  2575. * @api
  2576. */
  2577. getDataSources() {
  2578. return this.dataSourceCollection_;
  2579. }
  2580. /**
  2581. * @return {!Cesium.DataSourceDisplay}
  2582. * @api
  2583. */
  2584. getDataSourceDisplay() {
  2585. return this.dataSourceDisplay_;
  2586. }
  2587. /**
  2588. * @return {boolean}
  2589. * @api
  2590. */
  2591. getEnabled() {
  2592. return this.enabled_;
  2593. }
  2594. /**
  2595. * Enables/disables the Cesium.
  2596. * This modifies the visibility style of the container element.
  2597. * @param {boolean} enable
  2598. * @api
  2599. */
  2600. setEnabled(enable) {
  2601. if (this.enabled_ === enable) {
  2602. return;
  2603. }
  2604. this.enabled_ = enable;
  2605. // some Cesium operations are operating with canvas.clientWidth,
  2606. // so we can't remove it from DOM or even make display:none;
  2607. // this.container_.style.visibility = this.enabled_ ? 'visible' : 'hidden';
  2608. // let interactions;
  2609. if (this.enabled_) {
  2610. // this.throwOnUnitializedMap_();
  2611. // if (this.isOverMap_) {
  2612. // interactions = this.map_.getInteractions();
  2613. // interactions.forEach((el, i, arr) => {
  2614. // this.pausedInteractions_.push(el);
  2615. // });
  2616. // interactions.clear();
  2617. // this.map_.addInteraction = interaction => this.pausedInteractions_.push(interaction);
  2618. // this.map_.removeInteraction = interaction =>
  2619. // this.pausedInteractions_ = this.pausedInteractions_.filter(i => i !== interaction);
  2620. // const rootGroup = this.map_.getLayerGroup();
  2621. // if (rootGroup.getVisible()) {
  2622. // this.hiddenRootGroup_ = rootGroup;
  2623. // this.hiddenRootGroup_.setVisible(false);
  2624. // }
  2625. // this.map_.getOverlayContainer().classList.add('olcs-hideoverlay');
  2626. // }
  2627. this.camera_.readFromView();
  2628. // this.render_();
  2629. } else {
  2630. // if (this.isOverMap_) {
  2631. // interactions = this.map_.getInteractions();
  2632. // this.pausedInteractions_.forEach((interaction) => {
  2633. // interactions.push(interaction);
  2634. // });
  2635. // this.pausedInteractions_.length = 0;
  2636. // this.map_.addInteraction = interaction => this.map_.getInteractions().push(interaction);
  2637. // this.map_.removeInteraction = interaction => this.map_.getInteractions().remove(interaction);
  2638. // this.map_.getOverlayContainer().classList.remove('olcs-hideoverlay');
  2639. // if (this.hiddenRootGroup_) {
  2640. // this.hiddenRootGroup_.setVisible(true);
  2641. // this.hiddenRootGroup_ = null;
  2642. // }
  2643. // }
  2644. this.camera_.updateView();
  2645. }
  2646. }
  2647. /**
  2648. * Preload Cesium so that it is ready when transitioning from 2D to 3D.
  2649. * @param {number} height Target height of the camera
  2650. * @param {number} timeout Milliseconds after which the warming will stop
  2651. * @api
  2652. */
  2653. warmUp(height, timeout) {
  2654. if (this.enabled_) {
  2655. // already enabled
  2656. return;
  2657. }
  2658. this.throwOnUnitializedMap_();
  2659. this.camera_.readFromView();
  2660. const ellipsoid = this.globe_.ellipsoid;
  2661. const csCamera = this.scene_.camera;
  2662. const position = ellipsoid.cartesianToCartographic(csCamera.position);
  2663. if (position.height < height) {
  2664. position.height = height;
  2665. csCamera.position = ellipsoid.cartographicToCartesian(position);
  2666. }
  2667. // this.warmingUp_ = true;
  2668. // // this.render_();
  2669. // setTimeout(() => {
  2670. // this.warmingUp_ = false;
  2671. // }, timeout);
  2672. }
  2673. // /**
  2674. // * Block Cesium rendering to save resources.
  2675. // * @param {boolean} block True to block.
  2676. // * @api
  2677. // */
  2678. // setBlockCesiumRendering(block) {
  2679. // if (this.blockCesiumRendering_ !== block) {
  2680. // this.blockCesiumRendering_ = block;
  2681. // // reset the render loop
  2682. // this.render_();
  2683. // }
  2684. // }
  2685. /**
  2686. * Render the globe only when necessary in order to save resources.
  2687. * Experimental.
  2688. * @api
  2689. */
  2690. enableAutoRenderLoop() {
  2691. if (!this.autoRenderLoop_) {
  2692. this.autoRenderLoop_ = new _AutoRenderLoop_js__WEBPACK_IMPORTED_MODULE_4__["default"](this);
  2693. }
  2694. }
  2695. /**
  2696. * Get the autorender loop.
  2697. * @return {?olcs.AutoRenderLoop}
  2698. * @api
  2699. */
  2700. getAutoRenderLoop() {
  2701. return this.autoRenderLoop_;
  2702. }
  2703. /**
  2704. * The 3D Cesium globe is rendered in a canvas with two different dimensions:
  2705. * clientWidth and clientHeight which are the dimension on the screen and
  2706. * width and height which are the dimensions of the drawing buffer.
  2707. *
  2708. * By using a resolution scale lower than 1.0, it is possible to render the
  2709. * globe in a buffer smaller than the canvas client dimensions and improve
  2710. * performance, at the cost of quality.
  2711. *
  2712. * Pixel ratio should also be taken into account; by default, a device with
  2713. * pixel ratio of 2.0 will have a buffer surface 4 times bigger than the client
  2714. * surface.
  2715. *
  2716. * @param {number} value
  2717. * @this {olcs.OLCesium}
  2718. * @api
  2719. */
  2720. setResolutionScale(value) {
  2721. value = Math.max(0, value);
  2722. if (value !== this.resolutionScale_) {
  2723. this.resolutionScale_ = Math.max(0, value);
  2724. this.resolutionScaleChanged_ = true;
  2725. if (this.autoRenderLoop_) {
  2726. this.autoRenderLoop_.restartRenderLoop();
  2727. }
  2728. }
  2729. }
  2730. // /**
  2731. // * Set the target frame rate for the renderer. Set to `Number.POSITIVE_INFINITY`
  2732. // * to render as quickly as possible.
  2733. // * @param {number} value The frame rate, in frames per second.
  2734. // * @api
  2735. // */
  2736. // setTargetFrameRate(value) {
  2737. // if (this.targetFrameRate_ !== value) {
  2738. // this.targetFrameRate_ = value;
  2739. // // reset the render loop
  2740. // this.render_();
  2741. // }
  2742. // }
  2743. /**
  2744. * Check if OpenLayers map is not properly initialized.
  2745. * @private
  2746. */
  2747. throwOnUnitializedMap_() {
  2748. const map = this.map_;
  2749. const view = map.getView();
  2750. const center = view.getCenter();
  2751. if (!view.isDef() || isNaN(center[0]) || isNaN(center[1])) {
  2752. throw new Error(`The OpenLayers map is not properly initialized: ${center} / ${view.getResolution()}`);
  2753. }
  2754. }
  2755. /**
  2756. * @type {ol.Feature}
  2757. */
  2758. get trackedFeature() {
  2759. return this.trackedFeature_;
  2760. }
  2761. /**
  2762. * @param {ol.Feature} feature
  2763. */
  2764. set trackedFeature(feature) {
  2765. if (this.trackedFeature_ !== feature) {
  2766. const scene = this.scene_;
  2767. //Stop tracking
  2768. if (!feature || !feature.getGeometry()) {
  2769. // this.needTrackedEntityUpdate_ = false;
  2770. scene.screenSpaceCameraController.enableTilt = true;
  2771. if (this.trackedEntity_) {
  2772. this.dataSourceDisplay_.defaultDataSource.entities.remove(this.trackedEntity_);
  2773. }
  2774. this.trackedEntity_ = null;
  2775. this.trackedFeature_ = null;
  2776. this.entityView_ = null;
  2777. scene.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
  2778. return;
  2779. }
  2780. this.trackedFeature_ = feature;
  2781. //We can't start tracking immediately, so we set a flag and start tracking
  2782. //when the bounding sphere is ready (most likely next frame).
  2783. // this.needTrackedEntityUpdate_ = true;
  2784. const to4326Transform = this.to4326Transform_;
  2785. const toCesiumPosition = function() {
  2786. const geometry = feature.getGeometry();
  2787. console.assert(geometry instanceof (ol_geom_Point_js__WEBPACK_IMPORTED_MODULE_0___default()));
  2788. const coo = geometry.getCoordinates();
  2789. const coo4326 = to4326Transform(coo, undefined, coo.length);
  2790. return _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].ol4326CoordinateToCesiumCartesian(coo4326);
  2791. };
  2792. // Create an invisible point entity for tracking.
  2793. // It is independant from the primitive/geometry created by the vector synchronizer.
  2794. const options = {
  2795. 'position': new Cesium.CallbackProperty((time, result) => toCesiumPosition(), false),
  2796. 'point': {
  2797. 'pixelSize': 1,
  2798. 'color': Cesium.Color.TRANSPARENT
  2799. }
  2800. };
  2801. this.trackedEntity_ = this.dataSourceDisplay_.defaultDataSource.entities.add(options);
  2802. }
  2803. }
  2804. }
  2805. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OLCesium);
  2806. /***/ }),
  2807. /***/ "./src/olcs/OverlaySynchronizer.js":
  2808. /*!*****************************************!*\
  2809. !*** ./src/olcs/OverlaySynchronizer.js ***!
  2810. \*****************************************/
  2811. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  2812. __webpack_require__.r(__webpack_exports__);
  2813. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  2814. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  2815. /* harmony export */ });
  2816. /* harmony import */ var _SynchronizedOverlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SynchronizedOverlay.js */ "./src/olcs/SynchronizedOverlay.js");
  2817. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  2818. /**
  2819. * @module olcs.OverlaySynchronizer
  2820. */
  2821. class OverlaySynchronizer {
  2822. /**
  2823. * @param {!ol.Map} map
  2824. * @param {!Cesium.Scene} scene
  2825. * @constructor
  2826. * @template T
  2827. * @api
  2828. */
  2829. constructor(map, scene) {
  2830. /**
  2831. * @type {!ol.Map}
  2832. * @protected
  2833. */
  2834. this.map = map;
  2835. /**
  2836. * @type {ol.Collection.<ol.Overlay>}
  2837. * @private
  2838. */
  2839. this.overlays_ = this.map.getOverlays();
  2840. /**
  2841. * @type {!Cesium.Scene}
  2842. * @protected
  2843. */
  2844. this.scene = scene;
  2845. /**
  2846. * @private
  2847. * @type {!Element}
  2848. */
  2849. this.overlayContainerStopEvent_ = document.createElement('DIV');
  2850. this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent';
  2851. const overlayEvents = ['click', 'dblclick', 'mousedown', 'touchstart', 'MSPointerDown', 'pointerdown', 'mousewheel', 'wheel'];
  2852. overlayEvents.forEach((event) => {
  2853. this.overlayContainerStopEvent_.addEventListener(event, evt => evt.stopPropagation());
  2854. });
  2855. this.scene.canvas.parentElement.appendChild(this.overlayContainerStopEvent_);
  2856. /**
  2857. * @private
  2858. * @type {!Element}
  2859. */
  2860. this.overlayContainer_ = document.createElement('DIV');
  2861. this.overlayContainer_.className = 'ol-overlaycontainer';
  2862. this.scene.canvas.parentElement.appendChild(this.overlayContainer_);
  2863. /**
  2864. * @type {!Object<?,olcs.SynchronizedOverlay>}
  2865. * @private
  2866. */
  2867. this.overlayMap_ = {};
  2868. }
  2869. /**
  2870. * Get the element that serves as a container for overlays that don't allow
  2871. * event propagation. Elements added to this container won't let mousedown and
  2872. * touchstart events through to the map, so clicks and gestures on an overlay
  2873. * don't trigger any {@link ol.MapBrowserEvent}.
  2874. * @return {!Element} The map's overlay container that stops events.
  2875. */
  2876. getOverlayContainerStopEvent() {
  2877. return this.overlayContainerStopEvent_;
  2878. }
  2879. /**
  2880. * Get the element that serves as a container for overlays.
  2881. * @return {!Element} The map's overlay container.
  2882. */
  2883. getOverlayContainer() {
  2884. return this.overlayContainer_;
  2885. }
  2886. /**
  2887. * Destroy all and perform complete synchronization of the overlays.
  2888. * @api
  2889. */
  2890. synchronize() {
  2891. this.destroyAll();
  2892. this.addOverlays();
  2893. this.overlays_.on('add', this.addOverlayFromEvent_.bind(this));
  2894. this.overlays_.on('remove', this.removeOverlayFromEvent_.bind(this));
  2895. }
  2896. /**
  2897. * @param {ol.Collection.Event} event
  2898. * @private
  2899. */
  2900. addOverlayFromEvent_(event) {
  2901. const overlay = /** @type {ol.Overlay} */ (event.element);
  2902. this.addOverlay(overlay);
  2903. }
  2904. /**
  2905. * @api
  2906. */
  2907. addOverlays() {
  2908. this.overlays_.forEach((overlay) => { this.addOverlay(overlay); });
  2909. }
  2910. /**
  2911. * @param {ol.Overlay} overlay
  2912. * @api
  2913. */
  2914. addOverlay(overlay) {
  2915. if (!overlay) {
  2916. return;
  2917. }
  2918. const cesiumOverlay = new _SynchronizedOverlay_js__WEBPACK_IMPORTED_MODULE_0__["default"]({
  2919. scene: this.scene,
  2920. synchronizer: this,
  2921. parent: overlay
  2922. });
  2923. const overlayId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(overlay).toString();
  2924. this.overlayMap_[overlayId] = cesiumOverlay;
  2925. }
  2926. /**
  2927. * @param {ol.Collection.Event} event
  2928. * @private
  2929. */
  2930. removeOverlayFromEvent_(event) {
  2931. const removedOverlay = /** @type {ol.Overlay} */ (event.element);
  2932. this.removeOverlay(removedOverlay);
  2933. }
  2934. /**
  2935. * Removes an overlay from the scene
  2936. * @param {ol.Overlay} overlay
  2937. * @api
  2938. */
  2939. removeOverlay(overlay) {
  2940. const overlayId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(overlay).toString();
  2941. const csOverlay = this.overlayMap_[overlayId];
  2942. if (csOverlay) {
  2943. csOverlay.destroy();
  2944. delete this.overlayMap_[overlayId];
  2945. }
  2946. }
  2947. /**
  2948. * Destroys all the created Cesium objects.
  2949. * @protected
  2950. */
  2951. destroyAll() {
  2952. Object.keys(this.overlayMap_).forEach((key) => {
  2953. const overlay = this.overlayMap_[key];
  2954. overlay.destroy();
  2955. delete this.overlayMap_[key];
  2956. });
  2957. }
  2958. }
  2959. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OverlaySynchronizer);
  2960. /***/ }),
  2961. /***/ "./src/olcs/RasterSynchronizer.js":
  2962. /*!****************************************!*\
  2963. !*** ./src/olcs/RasterSynchronizer.js ***!
  2964. \****************************************/
  2965. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  2966. __webpack_require__.r(__webpack_exports__);
  2967. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  2968. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  2969. /* harmony export */ });
  2970. /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/layer/Group.js */ "ol/layer/Group.js");
  2971. /* harmony import */ var ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0__);
  2972. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  2973. /* harmony import */ var _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js");
  2974. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./core.js */ "./src/olcs/core.js");
  2975. /**
  2976. * @module olcs.RasterSynchronizer
  2977. */
  2978. class RasterSynchronizer extends _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__["default"] {
  2979. /**
  2980. * This object takes care of one-directional synchronization of
  2981. * Openlayers raster layers to the given Cesium globe.
  2982. * @param {!ol.Map} map
  2983. * @param {!Cesium.Scene} scene
  2984. * @constructor
  2985. * @extends {olcsAbstractSynchronizer.<Cesium.ImageryLayer>}
  2986. * @api
  2987. */
  2988. constructor(map, scene) {
  2989. super(map, scene);
  2990. /**
  2991. * @type {!Cesium.ImageryLayerCollection}
  2992. * @private
  2993. */
  2994. this.cesiumLayers_ = scene.imageryLayers;
  2995. /**
  2996. * @type {!Cesium.ImageryLayerCollection}
  2997. * @private
  2998. */
  2999. this.ourLayers_ = new Cesium.ImageryLayerCollection();
  3000. }
  3001. /**
  3002. * @inheritDoc
  3003. */
  3004. addCesiumObject(object) {
  3005. this.cesiumLayers_.add(object);
  3006. this.ourLayers_.add(object);
  3007. }
  3008. /**
  3009. * @inheritDoc
  3010. */
  3011. destroyCesiumObject(object) {
  3012. object.destroy();
  3013. }
  3014. /**
  3015. * @inheritDoc
  3016. */
  3017. removeSingleCesiumObject(object, destroy) {
  3018. this.cesiumLayers_.remove(object, destroy);
  3019. this.ourLayers_.remove(object, false);
  3020. }
  3021. /**
  3022. * @inheritDoc
  3023. */
  3024. removeAllCesiumObjects(destroy) {
  3025. for (let i = 0; i < this.ourLayers_.length; ++i) {
  3026. this.cesiumLayers_.remove(this.ourLayers_.get(i), destroy);
  3027. }
  3028. this.ourLayers_.removeAll(false);
  3029. }
  3030. /**
  3031. * Creates an array of Cesium.ImageryLayer.
  3032. * May be overriden by child classes to implement custom behavior.
  3033. * The default implementation handles tiled imageries in EPSG:4326 or
  3034. * EPSG:3859.
  3035. * @param {!ol.layer.Base} olLayer
  3036. * @param {!ol.proj.Projection} viewProj Projection of the view.
  3037. * @return {?Array.<!Cesium.ImageryLayer>} array or null if not possible
  3038. * (or supported)
  3039. * @protected
  3040. */
  3041. convertLayerToCesiumImageries(olLayer, viewProj) {
  3042. const result = _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].tileLayerToImageryLayer(this.map, olLayer, viewProj);
  3043. return result ? [result] : null;
  3044. }
  3045. /**
  3046. * @inheritDoc
  3047. */
  3048. createSingleLayerCounterparts(olLayerWithParents) {
  3049. const olLayer = olLayerWithParents.layer;
  3050. const uid = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer).toString();
  3051. const viewProj = this.view.getProjection();
  3052. console.assert(viewProj);
  3053. const cesiumObjects = this.convertLayerToCesiumImageries(olLayer, viewProj);
  3054. if (cesiumObjects) {
  3055. const listenKeyArray = [];
  3056. [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => {
  3057. listenKeyArray.push(olLayerItem.on(['change:opacity', 'change:visible'], () => {
  3058. // the compiler does not seem to be able to infer this
  3059. console.assert(cesiumObjects);
  3060. for (let i = 0; i < cesiumObjects.length; ++i) {
  3061. _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
  3062. }
  3063. }));
  3064. });
  3065. if (olLayer.getStyleFunction) {
  3066. let previousStyleFunction = olLayer.getStyleFunction();
  3067. // there is no convenient way to detect a style function change in OL
  3068. listenKeyArray.push(olLayer.on('change', () => {
  3069. const currentStyleFunction = olLayer.getStyleFunction();
  3070. if (previousStyleFunction === currentStyleFunction) {
  3071. return;
  3072. }
  3073. previousStyleFunction = currentStyleFunction;
  3074. for (let i = 0; i < cesiumObjects.length; ++i) {
  3075. const csObj = cesiumObjects[i];
  3076. // clear cache and set new style
  3077. if (csObj._imageryCache && csObj.imageryProvider.cache_) {
  3078. csObj._imageryCache = {};
  3079. csObj.imageryProvider.cache_ = {};
  3080. csObj.imageryProvider.styleFunction_ = currentStyleFunction;
  3081. }
  3082. }
  3083. this.scene.requestRender();
  3084. }));
  3085. }
  3086. for (let i = 0; i < cesiumObjects.length; ++i) {
  3087. _core_js__WEBPACK_IMPORTED_MODULE_3__["default"].updateCesiumLayerProperties(olLayerWithParents, cesiumObjects[i]);
  3088. }
  3089. // there is no way to modify Cesium layer extent,
  3090. // we have to recreate when OpenLayers layer extent changes:
  3091. listenKeyArray.push(olLayer.on('change:extent', (e) => {
  3092. for (let i = 0; i < cesiumObjects.length; ++i) {
  3093. this.cesiumLayers_.remove(cesiumObjects[i], true); // destroy
  3094. this.ourLayers_.remove(cesiumObjects[i], false);
  3095. }
  3096. delete this.layerMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer)]; // invalidate the map entry
  3097. this.synchronize();
  3098. }));
  3099. listenKeyArray.push(olLayer.on('change', (e) => {
  3100. // when the source changes, re-add the layer to force update
  3101. for (let i = 0; i < cesiumObjects.length; ++i) {
  3102. const position = this.cesiumLayers_.indexOf(cesiumObjects[i]);
  3103. if (position >= 0) {
  3104. this.cesiumLayers_.remove(cesiumObjects[i], false);
  3105. this.cesiumLayers_.add(cesiumObjects[i], position);
  3106. }
  3107. }
  3108. }));
  3109. this.olLayerListenKeys[uid].push(...listenKeyArray);
  3110. }
  3111. return Array.isArray(cesiumObjects) ? cesiumObjects : null;
  3112. }
  3113. /**
  3114. * Order counterparts using the same algorithm as the Openlayers renderer:
  3115. * z-index then original sequence order.
  3116. * @override
  3117. * @protected
  3118. */
  3119. orderLayers() {
  3120. const layers = [];
  3121. const zIndices = {};
  3122. const queue = [this.mapLayerGroup];
  3123. while (queue.length > 0) {
  3124. const olLayer = queue.splice(0, 1)[0];
  3125. layers.push(olLayer);
  3126. zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer)] = olLayer.getZIndex() || 0;
  3127. if (olLayer instanceof (ol_layer_Group_js__WEBPACK_IMPORTED_MODULE_0___default())) {
  3128. const sublayers = olLayer.getLayers();
  3129. if (sublayers) {
  3130. // Prepend queue with sublayers in order
  3131. queue.unshift(...sublayers.getArray());
  3132. }
  3133. }
  3134. }
  3135. (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.stableSort)(layers, (layer1, layer2) =>
  3136. zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(layer1)] - zIndices[(0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(layer2)]
  3137. );
  3138. layers.forEach((olLayer) => {
  3139. const olLayerId = (0,_util_js__WEBPACK_IMPORTED_MODULE_1__.getUid)(olLayer).toString();
  3140. const cesiumObjects = this.layerMap[olLayerId];
  3141. if (cesiumObjects) {
  3142. cesiumObjects.forEach((cesiumObject) => { this.raiseToTop(cesiumObject); });
  3143. }
  3144. });
  3145. }
  3146. /**
  3147. * @param {Cesium.ImageryLayer} counterpart
  3148. */
  3149. raiseToTop(counterpart) {
  3150. this.cesiumLayers_.raiseToTop(counterpart);
  3151. }
  3152. }
  3153. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RasterSynchronizer);
  3154. /***/ }),
  3155. /***/ "./src/olcs/SynchronizedOverlay.js":
  3156. /*!*****************************************!*\
  3157. !*** ./src/olcs/SynchronizedOverlay.js ***!
  3158. \*****************************************/
  3159. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  3160. __webpack_require__.r(__webpack_exports__);
  3161. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  3162. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  3163. /* harmony export */ });
  3164. /* harmony import */ var ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Overlay.js */ "ol/Overlay.js");
  3165. /* harmony import */ var ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0__);
  3166. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  3167. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_1__);
  3168. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  3169. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js");
  3170. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__);
  3171. /**
  3172. * @module olcs.SynchronizedOverlay
  3173. */
  3174. /**
  3175. * Options for SynchronizedOverlay
  3176. * @typedef {Object} SynchronizedOverlayOptions
  3177. * @property {!Cesium.Scene} scene
  3178. * @property {olOverlay} parent
  3179. * @property {!import('olsc/OverlaySynchronizer.js').default} synchronizer
  3180. */
  3181. class SynchronizedOverlay extends (ol_Overlay_js__WEBPACK_IMPORTED_MODULE_0___default()) {
  3182. /**
  3183. * @param {olcsx.SynchronizedOverlayOptions} options SynchronizedOverlay Options.
  3184. * @api
  3185. */
  3186. constructor(options) {
  3187. const parent = options.parent;
  3188. super(parent.getOptions());
  3189. /**
  3190. * @private
  3191. * @type {?Function}
  3192. */
  3193. this.scenePostRenderListenerRemover_ = null;
  3194. /**
  3195. * @private
  3196. * @type {!Cesium.Scene}
  3197. */
  3198. this.scene_ = options.scene;
  3199. /**
  3200. * @private
  3201. * @type {!olcs.OverlaySynchronizer}
  3202. */
  3203. this.synchronizer_ = options.synchronizer;
  3204. /**
  3205. * @private
  3206. * @type {!ol.Overlay}
  3207. */
  3208. this.parent_ = parent;
  3209. /**
  3210. * @private
  3211. * @type {ol.Coordinate|undefined}
  3212. */
  3213. this.positionWGS84_ = undefined;
  3214. /**
  3215. * @private
  3216. * @type {MutationObserver}
  3217. */
  3218. this.observer_ = new MutationObserver(this.handleElementChanged.bind(this));
  3219. /**
  3220. * @private
  3221. * @type {Array.<MutationObserver>}
  3222. */
  3223. this.attributeObserver_ = [];
  3224. /**
  3225. * @private
  3226. * @type {Array<ol.EventsKey>}
  3227. */
  3228. this.listenerKeys_ = [];
  3229. // synchronize our Overlay with the parent Overlay
  3230. const setPropertyFromEvent = event => this.setPropertyFromEvent_(event);
  3231. this.listenerKeys_.push(this.parent_.on('change:position', setPropertyFromEvent));
  3232. this.listenerKeys_.push(this.parent_.on('change:element', setPropertyFromEvent));
  3233. this.listenerKeys_.push(this.parent_.on('change:offset', setPropertyFromEvent));
  3234. this.listenerKeys_.push(this.parent_.on('change:position', setPropertyFromEvent));
  3235. this.listenerKeys_.push(this.parent_.on('change:positioning', setPropertyFromEvent));
  3236. this.setProperties(this.parent_.getProperties());
  3237. this.handleMapChanged();
  3238. this.handleElementChanged();
  3239. }
  3240. /**
  3241. * @param {Node} target
  3242. * @private
  3243. */
  3244. observeTarget_(target) {
  3245. if (!this.observer_) {
  3246. // not ready, skip the event (this occurs on construction)
  3247. return;
  3248. }
  3249. this.observer_.disconnect();
  3250. this.observer_.observe(target, {
  3251. attributes: false,
  3252. childList: true,
  3253. characterData: true,
  3254. subtree: true
  3255. });
  3256. this.attributeObserver_.forEach((observer) => {
  3257. observer.disconnect();
  3258. });
  3259. this.attributeObserver_.length = 0;
  3260. for (let i = 0; i < target.childNodes.length; i++) {
  3261. const node = target.childNodes[i];
  3262. if (node.nodeType === 1) {
  3263. const observer = new MutationObserver(this.handleElementChanged.bind(this));
  3264. observer.observe(node, {
  3265. attributes: true,
  3266. subtree: true
  3267. });
  3268. this.attributeObserver_.push(observer);
  3269. }
  3270. }
  3271. }
  3272. /**
  3273. *
  3274. * @param {ol.Object.Event} event
  3275. * @private
  3276. */
  3277. setPropertyFromEvent_(event) {
  3278. if (event.target && event.key) {
  3279. this.set(event.key, event.target.get(event.key));
  3280. }
  3281. }
  3282. /**
  3283. * Get the scene associated with this overlay.
  3284. * @see ol.Overlay.prototype.getMap
  3285. * @return {!Cesium.Scene} The scene that the overlay is part of.
  3286. * @api
  3287. */
  3288. getScene() {
  3289. return this.scene_;
  3290. }
  3291. /**
  3292. * @override
  3293. */
  3294. handleMapChanged() {
  3295. if (this.scenePostRenderListenerRemover_) {
  3296. this.scenePostRenderListenerRemover_();
  3297. (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.removeNode)(this.element);
  3298. }
  3299. this.scenePostRenderListenerRemover_ = null;
  3300. const scene = this.getScene();
  3301. if (scene) {
  3302. this.scenePostRenderListenerRemover_ = scene.postRender.addEventListener(this.updatePixelPosition.bind(this));
  3303. this.updatePixelPosition();
  3304. const container = this.stopEvent ?
  3305. this.synchronizer_.getOverlayContainerStopEvent() : this.synchronizer_.getOverlayContainer();
  3306. if (this.insertFirst) {
  3307. container.insertBefore(this.element, container.childNodes[0] || null);
  3308. } else {
  3309. container.appendChild(this.element);
  3310. }
  3311. }
  3312. }
  3313. /**
  3314. * @override
  3315. */
  3316. handlePositionChanged() {
  3317. // transform position to WGS84
  3318. const position = this.getPosition();
  3319. if (position) {
  3320. const sourceProjection = this.parent_.getMap().getView().getProjection();
  3321. this.positionWGS84_ = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_1__.transform)(position, sourceProjection, 'EPSG:4326');
  3322. } else {
  3323. this.positionWGS84_ = undefined;
  3324. }
  3325. this.updatePixelPosition();
  3326. }
  3327. /**
  3328. * @override
  3329. */
  3330. handleElementChanged() {
  3331. function cloneNode(node, parent) {
  3332. const clone = node.cloneNode();
  3333. if (node.nodeName === 'CANVAS') {
  3334. const ctx = clone.getContext('2d');
  3335. ctx.drawImage(node, 0, 0);
  3336. }
  3337. if (parent) {
  3338. parent.appendChild(clone);
  3339. }
  3340. if (node.nodeType != Node.TEXT_NODE) {
  3341. clone.addEventListener('click', (event) => {
  3342. node.dispatchEvent(new MouseEvent('click', event));
  3343. event.stopPropagation();
  3344. });
  3345. }
  3346. const nodes = node.childNodes;
  3347. for (let i = 0; i < nodes.length; i++) {
  3348. if (!nodes[i]) {
  3349. continue;
  3350. }
  3351. cloneNode(nodes[i], clone);
  3352. }
  3353. return clone;
  3354. }
  3355. (0,_util_js__WEBPACK_IMPORTED_MODULE_2__.removeChildren)(this.element);
  3356. const element = this.getElement();
  3357. if (element) {
  3358. if (element.parentNode && element.parentNode.childNodes) {
  3359. for (const node of element.parentNode.childNodes) {
  3360. const clonedNode = cloneNode(node, null);
  3361. this.element.appendChild(clonedNode);
  3362. }
  3363. }
  3364. }
  3365. if (element.parentNode) {
  3366. // set new Observer
  3367. this.observeTarget_(element.parentNode);
  3368. }
  3369. }
  3370. /**
  3371. * @override
  3372. */
  3373. updatePixelPosition() {
  3374. const position = this.positionWGS84_;
  3375. if (!this.scene_ || !position) {
  3376. this.setVisible(false);
  3377. return;
  3378. }
  3379. let height = 0;
  3380. if (position.length === 2) {
  3381. const globeHeight = this.scene_.globe.getHeight(Cesium.Cartographic.fromDegrees(position[0], position[1]));
  3382. if (globeHeight && this.scene_.globe.tilesLoaded) {
  3383. position[2] = globeHeight;
  3384. }
  3385. if (globeHeight) {
  3386. height = globeHeight;
  3387. }
  3388. } else {
  3389. height = position[2];
  3390. }
  3391. const cartesian = Cesium.Cartesian3.fromDegrees(position[0], position[1], height);
  3392. const camera = this.scene_.camera;
  3393. const ellipsoidBoundingSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(), 6356752);
  3394. const occluder = new Cesium.Occluder(ellipsoidBoundingSphere, camera.position);
  3395. // check if overlay position is behind the horizon
  3396. if (!occluder.isPointVisible(cartesian)) {
  3397. this.setVisible(false);
  3398. return;
  3399. }
  3400. const cullingVolume = camera.frustum.computeCullingVolume(camera.position, camera.direction, camera.up);
  3401. // check if overlay position is visible from the camera
  3402. if (cullingVolume.computeVisibility(new Cesium.BoundingSphere(cartesian)) !== 1) {
  3403. this.setVisible(false);
  3404. return;
  3405. }
  3406. this.setVisible(true);
  3407. const pixelCartesian = this.scene_.cartesianToCanvasCoordinates(cartesian);
  3408. const pixel = [pixelCartesian.x, pixelCartesian.y];
  3409. const mapSize = [this.scene_.canvas.width, this.scene_.canvas.height];
  3410. this.updateRenderedPosition(pixel, mapSize);
  3411. }
  3412. /**
  3413. * Destroys the overlay, removing all its listeners and elements
  3414. * @api
  3415. */
  3416. destroy() {
  3417. if (this.scenePostRenderListenerRemover_) {
  3418. this.scenePostRenderListenerRemover_();
  3419. }
  3420. if (this.observer_) {
  3421. this.observer_.disconnect();
  3422. }
  3423. (0,ol_Observable_js__WEBPACK_IMPORTED_MODULE_3__.unByKey)(this.listenerKeys_);
  3424. this.listenerKeys_.splice(0);
  3425. if (this.element.removeNode) {
  3426. this.element.removeNode(true);
  3427. } else {
  3428. this.element.remove();
  3429. }
  3430. this.element = null;
  3431. }
  3432. }
  3433. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SynchronizedOverlay);
  3434. /***/ }),
  3435. /***/ "./src/olcs/VectorSynchronizer.js":
  3436. /*!****************************************!*\
  3437. !*** ./src/olcs/VectorSynchronizer.js ***!
  3438. \****************************************/
  3439. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  3440. __webpack_require__.r(__webpack_exports__);
  3441. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  3442. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  3443. /* harmony export */ });
  3444. /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/source/Vector.js */ "ol/source/Vector.js");
  3445. /* harmony import */ var ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0__);
  3446. /* harmony import */ var ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Layer.js */ "ol/layer/Layer.js");
  3447. /* harmony import */ var ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1__);
  3448. /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source/Cluster.js */ "ol/source/Cluster.js");
  3449. /* harmony import */ var ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2__);
  3450. /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/layer/Image.js */ "ol/layer/Image.js");
  3451. /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3__);
  3452. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  3453. /* harmony import */ var ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/layer/Vector.js */ "ol/layer/Vector.js");
  3454. /* harmony import */ var ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5__);
  3455. /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/layer/VectorTile.js */ "ol/layer/VectorTile.js");
  3456. /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6__);
  3457. /* harmony import */ var _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js");
  3458. /* harmony import */ var _FeatureConverter_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./FeatureConverter.js */ "./src/olcs/FeatureConverter.js");
  3459. /**
  3460. * @module olcs.VectorSynchronizer
  3461. */
  3462. class VectorSynchronizer extends _AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_7__["default"] {
  3463. /**
  3464. * Unidirectionally synchronize OpenLayers vector layers to Cesium.
  3465. * @param {!ol.Map} map
  3466. * @param {!Cesium.Scene} scene
  3467. * @param {olcs.FeatureConverter=} opt_converter
  3468. * @extends {olcs.AbstractSynchronizer.<olcs.core.VectorLayerCounterpart>}
  3469. * @api
  3470. */
  3471. constructor(map, scene, opt_converter) {
  3472. super(map, scene);
  3473. /**
  3474. * @protected
  3475. */
  3476. this.converter = opt_converter || new _FeatureConverter_js__WEBPACK_IMPORTED_MODULE_8__["default"](scene);
  3477. /**
  3478. * @private
  3479. */
  3480. this.csAllPrimitives_ = new Cesium.PrimitiveCollection();
  3481. scene.primitives.add(this.csAllPrimitives_);
  3482. this.csAllPrimitives_.destroyPrimitives = false;
  3483. }
  3484. /**
  3485. * @inheritDoc
  3486. */
  3487. addCesiumObject(counterpart) {
  3488. console.assert(counterpart);
  3489. counterpart.getRootPrimitive()['counterpart'] = counterpart;
  3490. this.csAllPrimitives_.add(counterpart.getRootPrimitive());
  3491. }
  3492. /**
  3493. * @inheritDoc
  3494. */
  3495. destroyCesiumObject(object) {
  3496. object.getRootPrimitive().destroy();
  3497. }
  3498. /**
  3499. * @inheritDoc
  3500. */
  3501. removeSingleCesiumObject(object, destroy) {
  3502. object.destroy();
  3503. this.csAllPrimitives_.destroyPrimitives = destroy;
  3504. this.csAllPrimitives_.remove(object.getRootPrimitive());
  3505. this.csAllPrimitives_.destroyPrimitives = false;
  3506. }
  3507. /**
  3508. * @inheritDoc
  3509. */
  3510. removeAllCesiumObjects(destroy) {
  3511. this.csAllPrimitives_.destroyPrimitives = destroy;
  3512. if (destroy) {
  3513. for (let i = 0; i < this.csAllPrimitives_.length; ++i) {
  3514. this.csAllPrimitives_.get(i)['counterpart'].destroy();
  3515. }
  3516. }
  3517. this.csAllPrimitives_.removeAll();
  3518. this.csAllPrimitives_.destroyPrimitives = false;
  3519. }
  3520. /**
  3521. * Synchronizes the layer visibility properties
  3522. * to the given Cesium Primitive.
  3523. * @param {import('olsc/core.js').LayerWithParents} olLayerWithParents
  3524. * @param {!Cesium.Primitive} csPrimitive
  3525. */
  3526. updateLayerVisibility(olLayerWithParents, csPrimitive) {
  3527. let visible = true;
  3528. [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayer) => {
  3529. const layerVisible = olLayer.getVisible();
  3530. if (layerVisible !== undefined) {
  3531. visible &= layerVisible;
  3532. } else {
  3533. visible = false;
  3534. }
  3535. });
  3536. csPrimitive.show = visible;
  3537. }
  3538. /**
  3539. * @inheritDoc
  3540. */
  3541. createSingleLayerCounterparts(olLayerWithParents) {
  3542. const olLayer = olLayerWithParents.layer;
  3543. if (!(olLayer instanceof (ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default())) || olLayer instanceof (ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_6___default())) {
  3544. return null;
  3545. }
  3546. console.assert(olLayer instanceof (ol_layer_Layer_js__WEBPACK_IMPORTED_MODULE_1___default()));
  3547. let source = olLayer.getSource();
  3548. if (source instanceof (ol_source_Cluster_js__WEBPACK_IMPORTED_MODULE_2___default())) {
  3549. source = source.getSource();
  3550. }
  3551. if (!source) {
  3552. return null;
  3553. }
  3554. console.assert(source instanceof (ol_source_Vector_js__WEBPACK_IMPORTED_MODULE_0___default()));
  3555. console.assert(this.view);
  3556. const view = this.view;
  3557. const featurePrimitiveMap = {};
  3558. const counterpart = this.converter.olVectorLayerToCesium(olLayer, view,
  3559. featurePrimitiveMap);
  3560. const csPrimitives = counterpart.getRootPrimitive();
  3561. const olListenKeys = counterpart.olListenKeys;
  3562. [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayerItem) => {
  3563. olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(olLayerItem, 'change:visible', () => {
  3564. this.updateLayerVisibility(olLayerWithParents, csPrimitives);
  3565. }));
  3566. });
  3567. this.updateLayerVisibility(olLayerWithParents, csPrimitives);
  3568. const onAddFeature = (function(feature) {
  3569. console.assert(
  3570. (olLayer instanceof (ol_layer_Vector_js__WEBPACK_IMPORTED_MODULE_5___default())) ||
  3571. (olLayer instanceof (ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_3___default()))
  3572. );
  3573. const context = counterpart.context;
  3574. const prim = this.converter.convert(olLayer, view, feature, context);
  3575. if (prim) {
  3576. featurePrimitiveMap[(0,_util_js__WEBPACK_IMPORTED_MODULE_4__.getUid)(feature)] = prim;
  3577. csPrimitives.add(prim);
  3578. }
  3579. }).bind(this);
  3580. const onRemoveFeature = (function(feature) {
  3581. const id = (0,_util_js__WEBPACK_IMPORTED_MODULE_4__.getUid)(feature);
  3582. const context = counterpart.context;
  3583. const bbs = context.featureToCesiumMap[id];
  3584. if (bbs) {
  3585. delete context.featureToCesiumMap[id];
  3586. bbs.forEach((bb) => {
  3587. if (bb instanceof Cesium.Billboard) {
  3588. context.billboards.remove(bb);
  3589. }
  3590. });
  3591. }
  3592. const csPrimitive = featurePrimitiveMap[id];
  3593. delete featurePrimitiveMap[id];
  3594. if (csPrimitive) {
  3595. csPrimitives.remove(csPrimitive);
  3596. }
  3597. }).bind(this);
  3598. olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'addfeature', (e) => {
  3599. console.assert(e.feature);
  3600. onAddFeature(e.feature);
  3601. }, this));
  3602. olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'removefeature', (e) => {
  3603. console.assert(e.feature);
  3604. onRemoveFeature(e.feature);
  3605. }, this));
  3606. olListenKeys.push((0,_util_js__WEBPACK_IMPORTED_MODULE_4__.olcsListen)(source, 'changefeature', (e) => {
  3607. const feature = e.feature;
  3608. console.assert(feature);
  3609. onRemoveFeature(feature);
  3610. onAddFeature(feature);
  3611. }, this));
  3612. return counterpart ? [counterpart] : null;
  3613. }
  3614. }
  3615. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VectorSynchronizer);
  3616. /***/ }),
  3617. /***/ "./src/olcs/contrib/LazyLoader.js":
  3618. /*!****************************************!*\
  3619. !*** ./src/olcs/contrib/LazyLoader.js ***!
  3620. \****************************************/
  3621. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  3622. __webpack_require__.r(__webpack_exports__);
  3623. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  3624. /* harmony export */ "default": () => (/* binding */ LazyLoader)
  3625. /* harmony export */ });
  3626. /**
  3627. * @module olcs.contrib.LazyLoader
  3628. */
  3629. class LazyLoader {
  3630. /**
  3631. * @param {string} url
  3632. * @api
  3633. */
  3634. constructor(url) {
  3635. /**
  3636. * @type {Promise<undefined>}
  3637. * @protected
  3638. */
  3639. this.promise;
  3640. /**
  3641. * @private
  3642. * @type {string}
  3643. */
  3644. this.url_ = url;
  3645. }
  3646. /**
  3647. * @return {Promise<undefined>}
  3648. * @api
  3649. */
  3650. load() {
  3651. if (!this.promise) {
  3652. // not yet loading
  3653. this.promise = new Promise((resolve, reject) => {
  3654. const script = document.createElement('script');
  3655. script.onload = () => resolve();
  3656. script.onerror = () => reject();
  3657. document.head.appendChild(script);
  3658. script.src = this.url_;
  3659. });
  3660. }
  3661. return this.promise;
  3662. }
  3663. }
  3664. /***/ }),
  3665. /***/ "./src/olcs/contrib/Manager.js":
  3666. /*!*************************************!*\
  3667. !*** ./src/olcs/contrib/Manager.js ***!
  3668. \*************************************/
  3669. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  3670. __webpack_require__.r(__webpack_exports__);
  3671. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  3672. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  3673. /* harmony export */ });
  3674. /* harmony import */ var _contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../contrib/LazyLoader.js */ "./src/olcs/contrib/LazyLoader.js");
  3675. /* harmony import */ var _OLCesium_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../OLCesium.js */ "./src/olcs/OLCesium.js");
  3676. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../core.js */ "./src/olcs/core.js");
  3677. /* harmony import */ var _math_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../math.js */ "./src/olcs/math.js");
  3678. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js");
  3679. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_4__);
  3680. /**
  3681. * @module olcs.contrib.Manager
  3682. */
  3683. /**
  3684. * @typedef {Object} ManagerOptions
  3685. * @property {import('ol/Map.js').default} map
  3686. * @property {import('ol/extent.js').Extent} [cameraExtentInRadians]
  3687. * @property {string} [cesiumIonDefaultAccessToken]
  3688. */
  3689. const Manager = class extends (ol_Observable_js__WEBPACK_IMPORTED_MODULE_4___default()) {
  3690. /**
  3691. * @param {string} cesiumUrl
  3692. * @param {olcsx.contrib.ManagerOptions} options
  3693. * @api
  3694. */
  3695. constructor(cesiumUrl, {map, cameraExtentInRadians, cesiumIonDefaultAccessToken} = {}) {
  3696. super();
  3697. /**
  3698. * @type {string}
  3699. * @private
  3700. */
  3701. this.cesiumUrl_ = cesiumUrl;
  3702. /**
  3703. * @type {ol.Map}
  3704. * @protected
  3705. */
  3706. this.map = map;
  3707. /**
  3708. * @type {ol.Extent}
  3709. * @protected
  3710. */
  3711. this.cameraExtentInRadians = cameraExtentInRadians || null;
  3712. /**
  3713. * @private
  3714. * @type {Cesium.BoundingSphere}
  3715. */
  3716. this.boundingSphere_;
  3717. /**
  3718. * @type {boolean}
  3719. * @private
  3720. */
  3721. this.blockLimiter_ = false;
  3722. /**
  3723. * @type {Promise.<olcs.OLCesium>}
  3724. * @private
  3725. */
  3726. this.promise_;
  3727. /**
  3728. * @type {string}
  3729. * @private
  3730. */
  3731. this.cesiumIonDefaultAccessToken_ = cesiumIonDefaultAccessToken;
  3732. /**
  3733. * @type {olcs.OLCesium}
  3734. * @protected
  3735. */
  3736. this.ol3d;
  3737. /**
  3738. * @const {number} Tilt angle in radians
  3739. * @private
  3740. */
  3741. this.cesiumInitialTilt_ = (0,_math_js__WEBPACK_IMPORTED_MODULE_3__.toRadians)(50);
  3742. /**
  3743. * @protected
  3744. * @type {number}
  3745. */
  3746. this.fogDensity = 0.0001;
  3747. /**
  3748. * @protected
  3749. * @type {number}
  3750. */
  3751. this.fogSSEFactor = 25;
  3752. /**
  3753. * Limit the minimum distance to the terrain to 2m.
  3754. * @protected
  3755. * @type {number}
  3756. */
  3757. this.minimumZoomDistance = 2;
  3758. /**
  3759. * Limit the maximum distance to the earth to 10'000km.
  3760. * @protected
  3761. * @type {number}
  3762. */
  3763. this.maximumZoomDistance = 10000000;
  3764. // when closer to 3000m, restrict the available positions harder
  3765. /**
  3766. * @protected
  3767. * @param {number} height
  3768. */
  3769. this.limitCameraToBoundingSphereRatio = height => (height > 3000 ? 9 : 3);
  3770. }
  3771. /**
  3772. * @return {Promise.<olcs.OLCesium>}
  3773. */
  3774. load() {
  3775. if (!this.promise_) {
  3776. const cesiumLazyLoader = new _contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_0__["default"](this.cesiumUrl_);
  3777. this.promise_ = cesiumLazyLoader.load().then(() => this.onCesiumLoaded());
  3778. }
  3779. return this.promise_;
  3780. }
  3781. /**
  3782. * @protected
  3783. * @return {olcs.OLCesium}
  3784. */
  3785. onCesiumLoaded() {
  3786. if (this.cameraExtentInRadians) {
  3787. const rect = new Cesium.Rectangle(...this.cameraExtentInRadians);
  3788. // Set the fly home rectangle
  3789. Cesium.Camera.DEFAULT_VIEW_RECTANGLE = rect;
  3790. this.boundingSphere_ = Cesium.BoundingSphere.fromRectangle3D(rect, Cesium.Ellipsoid.WGS84, 300); // lux mean height is 300m
  3791. }
  3792. if (this.cesiumIonDefaultAccessToken_) {
  3793. Cesium.Ion.defaultAccessToken = this.cesiumIonDefaultAccessToken_;
  3794. }
  3795. this.ol3d = this.instantiateOLCesium();
  3796. const scene = this.ol3d.getCesiumScene();
  3797. this.configureForUsability(scene);
  3798. this.configureForPerformance(scene);
  3799. this.dispatchEvent('load');
  3800. return this.ol3d;
  3801. }
  3802. /**
  3803. * Application code should override this method.
  3804. * @return {olcs.OLCesium}
  3805. */
  3806. instantiateOLCesium() {
  3807. console.assert(this.map);
  3808. const ol3d = new _OLCesium_js__WEBPACK_IMPORTED_MODULE_1__["default"]({map: this.map});
  3809. const scene = ol3d.getCesiumScene();
  3810. const terrainProvider = Cesium.createWorldTerrain();
  3811. scene.terrainProvider = terrainProvider;
  3812. return ol3d;
  3813. }
  3814. /**
  3815. * @param {!Cesium.Scene} scene The scene, passed as parameter for convenience.
  3816. * @protected
  3817. */
  3818. configureForPerformance(scene) {
  3819. const fog = scene.fog;
  3820. fog.enabled = true;
  3821. fog.density = this.fogDensity;
  3822. fog.screenSpaceErrorFactor = this.fogSSEFactor;
  3823. }
  3824. /**
  3825. * @param {!Cesium.Scene} scene The scene, passed as parameter for convenience.
  3826. * @protected
  3827. */
  3828. configureForUsability(scene) {
  3829. const sscController = scene.screenSpaceCameraController;
  3830. sscController.minimumZoomDistance = this.minimumZoomDistance;
  3831. sscController.maximumZoomDistance = this.maximumZoomDistance;
  3832. // Do not see through the terrain. Seeing through the terrain does not make
  3833. // sense anyway, except for debugging
  3834. scene.globe.depthTestAgainstTerrain = true;
  3835. // Use white instead of the black default colour for the globe when tiles are missing
  3836. scene.globe.baseColor = Cesium.Color.WHITE;
  3837. scene.backgroundColor = Cesium.Color.WHITE;
  3838. if (this.boundingSphere_) {
  3839. scene.postRender.addEventListener(this.limitCameraToBoundingSphere.bind(this), scene);
  3840. }
  3841. // Stop rendering Cesium when there is nothing to do. This drastically reduces CPU/GPU consumption.
  3842. this.ol3d.enableAutoRenderLoop();
  3843. }
  3844. /**
  3845. * Constrain the camera so that it stays close to the bounding sphere of the map extent.
  3846. * Near the ground the allowed distance is shorter.
  3847. * @protected
  3848. */
  3849. limitCameraToBoundingSphere() {
  3850. if (this.boundingSphere_ && !this.blockLimiter_) {
  3851. const scene = this.ol3d.getCesiumScene();
  3852. const camera = scene.camera;
  3853. const position = camera.position;
  3854. const carto = Cesium.Cartographic.fromCartesian(position);
  3855. const ratio = this.limitCameraToBoundingSphereRatio(carto.height);
  3856. if (Cesium.Cartesian3.distance(this.boundingSphere_.center, position) > this.boundingSphere_.radius * ratio) {
  3857. const currentlyFlying = camera.flying;
  3858. if (currentlyFlying === true) {
  3859. // There is a flying property and its value is true
  3860. return;
  3861. } else {
  3862. this.blockLimiter_ = true;
  3863. const unblockLimiter = () => this.blockLimiter_ = false;
  3864. camera.flyToBoundingSphere(this.boundingSphere_, {
  3865. complete: unblockLimiter,
  3866. cancel: unblockLimiter
  3867. });
  3868. }
  3869. }
  3870. }
  3871. }
  3872. /**
  3873. * Enable or disable ol3d with a default animation.
  3874. * @export
  3875. * @return {Promise<undefined>}
  3876. */
  3877. toggle3d() {
  3878. return this.load().then((/** @const {!olcs.OLCesium} */ ol3d) => {
  3879. const is3DCurrentlyEnabled = ol3d.getEnabled();
  3880. const scene = ol3d.getCesiumScene();
  3881. if (is3DCurrentlyEnabled) {
  3882. // Disable 3D
  3883. console.assert(this.map);
  3884. return _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].resetToNorthZenith(this.map, scene).then(() => {
  3885. ol3d.setEnabled(false);
  3886. this.dispatchEvent('toggle');
  3887. });
  3888. } else {
  3889. // Enable 3D
  3890. ol3d.setEnabled(true);
  3891. this.dispatchEvent('toggle');
  3892. return _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].rotateAroundBottomCenter(scene, this.cesiumInitialTilt_);
  3893. }
  3894. });
  3895. }
  3896. /**
  3897. * Enable ol3d with a view built from parameters.
  3898. *
  3899. * @export
  3900. * @param {number} lon
  3901. * @param {number} lat
  3902. * @param {number} elevation
  3903. * @param {number} headingDeg Heading value in degrees.
  3904. * @param {number} pitchDeg Pitch value in degrees.
  3905. * @returns {Promise<undefined>}
  3906. */
  3907. set3dWithView(lon, lat, elevation, headingDeg, pitchDeg) {
  3908. return this.load().then((/** @const {!olcs.OLCesium} */ ol3d) => {
  3909. const is3DCurrentlyEnabled = ol3d.getEnabled();
  3910. const scene = ol3d.getCesiumScene();
  3911. const camera = scene.camera;
  3912. const destination = Cesium.Cartesian3.fromDegrees(lon, lat, elevation);
  3913. const heading = Cesium.Math.toRadians(headingDeg);
  3914. const pitch = Cesium.Math.toRadians(pitchDeg);
  3915. const roll = 0;
  3916. const orientation = {heading, pitch, roll};
  3917. if (!is3DCurrentlyEnabled) {
  3918. ol3d.setEnabled(true);
  3919. this.dispatchEvent('toggle');
  3920. }
  3921. camera.setView({
  3922. destination,
  3923. orientation
  3924. });
  3925. });
  3926. }
  3927. /**
  3928. * @export
  3929. * @return {boolean}
  3930. */
  3931. is3dEnabled() {
  3932. return !!this.ol3d && this.ol3d.getEnabled();
  3933. }
  3934. /**
  3935. * @return {number}
  3936. */
  3937. getHeading() {
  3938. return this.map ? this.map.getView().getRotation() || 0 : 0;
  3939. }
  3940. /**
  3941. * @return {number|undefined}
  3942. */
  3943. getTiltOnGlobe() {
  3944. const scene = this.ol3d.getCesiumScene();
  3945. const tiltOnGlobe = _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].computeSignedTiltAngleOnGlobe(scene);
  3946. return -tiltOnGlobe;
  3947. }
  3948. /**
  3949. * @param {number} angle
  3950. */
  3951. setHeading(angle) {
  3952. const scene = this.ol3d.getCesiumScene();
  3953. const bottom = _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].pickBottomPoint(scene);
  3954. if (bottom) {
  3955. _core_js__WEBPACK_IMPORTED_MODULE_2__["default"].setHeadingUsingBottomCenter(scene, angle, bottom);
  3956. }
  3957. }
  3958. /**
  3959. * @export
  3960. * @return {olcs.OLCesium}
  3961. */
  3962. getOl3d() {
  3963. return this.ol3d;
  3964. }
  3965. /**
  3966. * @export
  3967. * @return {!ol.View}
  3968. */
  3969. getOlView() {
  3970. const view = this.map.getView();
  3971. console.assert(view);
  3972. return view;
  3973. }
  3974. /**
  3975. * @export
  3976. * @return {Cesium.Matrix4}
  3977. */
  3978. getCesiumViewMatrix() {
  3979. return this.ol3d.getCesiumScene().camera.viewMatrix;
  3980. }
  3981. /**
  3982. * @export
  3983. * @return {!Cesium.Scene}
  3984. */
  3985. getCesiumScene() {
  3986. return this.ol3d.getCesiumScene();
  3987. }
  3988. /**
  3989. * @export
  3990. * @param {!Cesium.Rectangle} rectangle
  3991. * @param {number=} offset in meters
  3992. * @return {Promise<undefined>}
  3993. */
  3994. flyToRectangle(rectangle, offset = 0) {
  3995. const camera = this.getCesiumScene().camera;
  3996. const destination = camera.getRectangleCameraCoordinates(rectangle);
  3997. const mag = Cesium.Cartesian3.magnitude(destination) + offset;
  3998. Cesium.Cartesian3.normalize(destination, destination);
  3999. Cesium.Cartesian3.multiplyByScalar(destination, mag, destination);
  4000. return new Promise((resolve, reject) => {
  4001. if (!this.cameraExtentInRadians) {
  4002. reject();
  4003. return;
  4004. }
  4005. camera.flyTo({
  4006. destination,
  4007. complete: () => resolve(),
  4008. cancel: () => reject(),
  4009. endTransform: Cesium.Matrix4.IDENTITY
  4010. });
  4011. });
  4012. }
  4013. /**
  4014. * @protected
  4015. * @return {Cesium.Rectangle|undefined}
  4016. */
  4017. getCameraExtentRectangle() {
  4018. if (this.cameraExtentInRadians) {
  4019. return new Cesium.Rectangle(...this.cameraExtentInRadians);
  4020. }
  4021. }
  4022. };
  4023. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Manager);
  4024. /***/ }),
  4025. /***/ "./src/olcs/core.js":
  4026. /*!**************************!*\
  4027. !*** ./src/olcs/core.js ***!
  4028. \**************************/
  4029. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  4030. __webpack_require__.r(__webpack_exports__);
  4031. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  4032. /* harmony export */ "attributionsFunctionToCredits": () => (/* binding */ attributionsFunctionToCredits),
  4033. /* harmony export */ "calcDistanceForResolution": () => (/* binding */ calcDistanceForResolution),
  4034. /* harmony export */ "calcResolutionForDistance": () => (/* binding */ calcResolutionForDistance),
  4035. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  4036. /* harmony export */ });
  4037. /* harmony import */ var ol_easing_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/easing.js */ "ol/easing.js");
  4038. /* harmony import */ var ol_easing_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_easing_js__WEBPACK_IMPORTED_MODULE_0__);
  4039. /* harmony import */ var ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ol/layer/Tile.js */ "ol/layer/Tile.js");
  4040. /* harmony import */ var ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1__);
  4041. /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/layer/Image.js */ "ol/layer/Image.js");
  4042. /* harmony import */ var ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2__);
  4043. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  4044. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_3__);
  4045. /* harmony import */ var ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ol/source/ImageStatic.js */ "ol/source/ImageStatic.js");
  4046. /* harmony import */ var ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4__);
  4047. /* harmony import */ var ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ol/source/ImageWMS.js */ "ol/source/ImageWMS.js");
  4048. /* harmony import */ var ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5__);
  4049. /* harmony import */ var ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ol/source/TileImage.js */ "ol/source/TileImage.js");
  4050. /* harmony import */ var ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6__);
  4051. /* harmony import */ var ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ol/source/TileWMS.js */ "ol/source/TileWMS.js");
  4052. /* harmony import */ var ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7__);
  4053. /* harmony import */ var ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ol/source/VectorTile.js */ "ol/source/VectorTile.js");
  4054. /* harmony import */ var ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8__);
  4055. /* harmony import */ var ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ol/source/Image.js */ "ol/source/Image.js");
  4056. /* harmony import */ var ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__);
  4057. /* harmony import */ var _core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./core/OLImageryProvider.js */ "./src/olcs/core/OLImageryProvider.js");
  4058. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./util.js */ "./src/olcs/util.js");
  4059. /* harmony import */ var _MVTImageryProvider_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./MVTImageryProvider.js */ "./src/olcs/MVTImageryProvider.js");
  4060. /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ol/layer/VectorTile.js */ "ol/layer/VectorTile.js");
  4061. /* harmony import */ var ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13__);
  4062. /* harmony import */ var ol_extent__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ol/extent */ "ol/extent");
  4063. /* harmony import */ var ol_extent__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(ol_extent__WEBPACK_IMPORTED_MODULE_14__);
  4064. /**
  4065. * @module olcs.core
  4066. */
  4067. const exports = {};
  4068. /**
  4069. * @typedef {Object} CesiumUrlDefinition
  4070. * @property {string} url
  4071. * @property {string} subdomains
  4072. */
  4073. /**
  4074. * Options for rotate around axis core function.
  4075. * @typedef {Object} RotateAroundAxisOption
  4076. * @property {number} [duration]
  4077. * @property {function(number): number} [easing]
  4078. * @property {function(): void} [callback]
  4079. */
  4080. /**
  4081. * @typedef {Object} LayerWithParents
  4082. * @property {import('ol/layer/Base.js').default} layer
  4083. * @property {Array<import('ol/layer/Group.js').default>} parents
  4084. */
  4085. /**
  4086. * Compute the pixel width and height of a point in meters using the
  4087. * camera frustum.
  4088. * @param {!Cesium.Scene} scene
  4089. * @param {!Cesium.Cartesian3} target
  4090. * @return {!Cesium.Cartesian2} the pixel size
  4091. * @api
  4092. */
  4093. exports.computePixelSizeAtCoordinate = function(scene, target) {
  4094. const camera = scene.camera;
  4095. const canvas = scene.canvas;
  4096. const frustum = camera.frustum;
  4097. const distance = Cesium.Cartesian3.magnitude(Cesium.Cartesian3.subtract(
  4098. camera.position, target, new Cesium.Cartesian3()));
  4099. return frustum.getPixelDimensions(canvas.clientWidth, canvas.clientHeight,
  4100. distance, scene.pixelRatio, new Cesium.Cartesian2());
  4101. };
  4102. /**
  4103. * Compute bounding box around a target point.
  4104. * @param {!Cesium.Scene} scene
  4105. * @param {!Cesium.Cartesian3} target
  4106. * @param {number} amount Half the side of the box, in pixels.
  4107. * @return {Array<Cesium.Cartographic>} bottom left and top right
  4108. * coordinates of the box
  4109. */
  4110. exports.computeBoundingBoxAtTarget = function(scene, target, amount) {
  4111. const pixelSize = exports.computePixelSizeAtCoordinate(scene, target);
  4112. const transform = Cesium.Transforms.eastNorthUpToFixedFrame(target);
  4113. const bottomLeft = Cesium.Matrix4.multiplyByPoint(
  4114. transform,
  4115. new Cesium.Cartesian3(-pixelSize.x * amount, -pixelSize.y * amount, 0),
  4116. new Cesium.Cartesian3());
  4117. const topRight = Cesium.Matrix4.multiplyByPoint(
  4118. transform,
  4119. new Cesium.Cartesian3(pixelSize.x * amount, pixelSize.y * amount, 0),
  4120. new Cesium.Cartesian3());
  4121. return Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray(
  4122. [bottomLeft, topRight]);
  4123. };
  4124. /**
  4125. *
  4126. * @param {!ol.geom.Geometry} geometry
  4127. * @param {number} height
  4128. * @api
  4129. */
  4130. exports.applyHeightOffsetToGeometry = function(geometry, height) {
  4131. geometry.applyTransform((input, output, stride) => {
  4132. console.assert(input === output);
  4133. if (stride !== undefined && stride >= 3) {
  4134. for (let i = 0; i < output.length; i += stride) {
  4135. output[i + 2] = output[i + 2] + height;
  4136. }
  4137. }
  4138. return output;
  4139. });
  4140. };
  4141. /**
  4142. * @param {ol.Coordinate} coordinates
  4143. * @param {number=} rotation
  4144. * @param {!Cesium.Cartesian3=} translation
  4145. * @param {!Cesium.Cartesian3=} scale
  4146. * @return {!Cesium.Matrix4}
  4147. * @api
  4148. */
  4149. exports.createMatrixAtCoordinates = function(coordinates, rotation = 0, translation = Cesium.Cartesian3.ZERO, scale = new Cesium.Cartesian3(1, 1, 1)) {
  4150. const position = exports.ol4326CoordinateToCesiumCartesian(coordinates);
  4151. const rawMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
  4152. const quaternion = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, -rotation);
  4153. const rotationMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(translation, quaternion, scale);
  4154. return Cesium.Matrix4.multiply(rawMatrix, rotationMatrix, new Cesium.Matrix4());
  4155. };
  4156. /**
  4157. * @param {!Cesium.Camera} camera
  4158. * @param {number} angle
  4159. * @param {!Cesium.Cartesian3} axis
  4160. * @param {!Cesium.Matrix4} transform
  4161. * @param {RotateAroundAxisOption=} opt_options
  4162. * @api
  4163. */
  4164. exports.rotateAroundAxis = function(camera, angle, axis, transform,
  4165. opt_options) {
  4166. const clamp = Cesium.Math.clamp;
  4167. const defaultValue = Cesium.defaultValue;
  4168. const options = opt_options || {};
  4169. const duration = defaultValue(options.duration, 500); // ms
  4170. const easing = defaultValue(options.easing, ol_easing_js__WEBPACK_IMPORTED_MODULE_0__.linear);
  4171. const callback = options.callback;
  4172. let lastProgress = 0;
  4173. const oldTransform = new Cesium.Matrix4();
  4174. const start = Date.now();
  4175. const step = function() {
  4176. const timestamp = Date.now();
  4177. const timeDifference = timestamp - start;
  4178. const progress = easing(clamp(timeDifference / duration, 0, 1));
  4179. console.assert(progress >= lastProgress);
  4180. camera.transform.clone(oldTransform);
  4181. const stepAngle = (progress - lastProgress) * angle;
  4182. lastProgress = progress;
  4183. camera.lookAtTransform(transform);
  4184. camera.rotate(axis, stepAngle);
  4185. camera.lookAtTransform(oldTransform);
  4186. if (progress < 1) {
  4187. window.requestAnimationFrame(step);
  4188. } else {
  4189. if (callback) {
  4190. callback();
  4191. }
  4192. }
  4193. };
  4194. window.requestAnimationFrame(step);
  4195. };
  4196. /**
  4197. * @param {!Cesium.Scene} scene
  4198. * @param {number} heading
  4199. * @param {!Cesium.Cartesian3} bottomCenter
  4200. * @param {RotateAroundAxisOption=} opt_options
  4201. * @api
  4202. */
  4203. exports.setHeadingUsingBottomCenter = function(scene, heading,
  4204. bottomCenter, opt_options) {
  4205. const camera = scene.camera;
  4206. // Compute the camera position to zenith quaternion
  4207. const angleToZenith = exports.computeAngleToZenith(scene, bottomCenter);
  4208. const axis = camera.right;
  4209. const quaternion = Cesium.Quaternion.fromAxisAngle(axis, angleToZenith);
  4210. const rotation = Cesium.Matrix3.fromQuaternion(quaternion);
  4211. // Get the zenith point from the rotation of the position vector
  4212. const vector = new Cesium.Cartesian3();
  4213. Cesium.Cartesian3.subtract(camera.position, bottomCenter, vector);
  4214. const zenith = new Cesium.Cartesian3();
  4215. Cesium.Matrix3.multiplyByVector(rotation, vector, zenith);
  4216. Cesium.Cartesian3.add(zenith, bottomCenter, zenith);
  4217. // Actually rotate around the zenith normal
  4218. const transform = Cesium.Matrix4.fromTranslation(zenith);
  4219. const rotateAroundAxis = exports.rotateAroundAxis;
  4220. rotateAroundAxis(camera, heading, zenith, transform, opt_options);
  4221. };
  4222. /**
  4223. * Get the 3D position of the given pixel of the canvas.
  4224. * @param {!Cesium.Scene} scene
  4225. * @param {!Cesium.Cartesian2} pixel
  4226. * @return {!Cesium.Cartesian3|undefined}
  4227. * @api
  4228. */
  4229. exports.pickOnTerrainOrEllipsoid = function(scene, pixel) {
  4230. const ray = scene.camera.getPickRay(pixel);
  4231. const target = scene.globe.pick(ray, scene);
  4232. return target || scene.camera.pickEllipsoid(pixel);
  4233. };
  4234. /**
  4235. * Get the 3D position of the point at the bottom-center of the screen.
  4236. * @param {!Cesium.Scene} scene
  4237. * @return {!Cesium.Cartesian3|undefined}
  4238. * @api
  4239. */
  4240. exports.pickBottomPoint = function(scene) {
  4241. const canvas = scene.canvas;
  4242. const bottom = new Cesium.Cartesian2(
  4243. canvas.clientWidth / 2, canvas.clientHeight);
  4244. return exports.pickOnTerrainOrEllipsoid(scene, bottom);
  4245. };
  4246. /**
  4247. * Get the 3D position of the point at the center of the screen.
  4248. * @param {!Cesium.Scene} scene
  4249. * @return {!Cesium.Cartesian3|undefined}
  4250. * @api
  4251. */
  4252. exports.pickCenterPoint = function(scene) {
  4253. const canvas = scene.canvas;
  4254. const center = new Cesium.Cartesian2(
  4255. canvas.clientWidth / 2,
  4256. canvas.clientHeight / 2);
  4257. return exports.pickOnTerrainOrEllipsoid(scene, center);
  4258. };
  4259. /**
  4260. * Compute the signed tilt angle on globe, between the opposite of the
  4261. * camera direction and the target normal. Return undefined if there is no
  4262. * intersection of the camera direction with the globe.
  4263. * @param {!Cesium.Scene} scene
  4264. * @return {number|undefined}
  4265. * @api
  4266. */
  4267. exports.computeSignedTiltAngleOnGlobe = function(scene) {
  4268. const camera = scene.camera;
  4269. const ray = new Cesium.Ray(camera.position, camera.direction);
  4270. let target = scene.globe.pick(ray, scene);
  4271. if (!target) {
  4272. // no tiles in the area were loaded?
  4273. const ellipsoid = Cesium.Ellipsoid.WGS84;
  4274. const obj = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid);
  4275. if (obj) {
  4276. target = Cesium.Ray.getPoint(ray, obj.start);
  4277. }
  4278. }
  4279. if (!target) {
  4280. return undefined;
  4281. }
  4282. const normal = new Cesium.Cartesian3();
  4283. Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(target, normal);
  4284. const angleBetween = exports.signedAngleBetween;
  4285. const angle = angleBetween(camera.direction, normal, camera.right) - Math.PI;
  4286. return Cesium.Math.convertLongitudeRange(angle);
  4287. };
  4288. /**
  4289. * Compute the ray from the camera to the bottom-center of the screen.
  4290. * @param {!Cesium.Scene} scene
  4291. * @return {!Cesium.Ray}
  4292. */
  4293. exports.bottomFovRay = function(scene) {
  4294. const camera = scene.camera;
  4295. const fovy2 = camera.frustum.fovy / 2;
  4296. const direction = camera.direction;
  4297. const rotation = Cesium.Quaternion.fromAxisAngle(camera.right, fovy2);
  4298. const matrix = Cesium.Matrix3.fromQuaternion(rotation);
  4299. const vector = new Cesium.Cartesian3();
  4300. Cesium.Matrix3.multiplyByVector(matrix, direction, vector);
  4301. return new Cesium.Ray(camera.position, vector);
  4302. };
  4303. /**
  4304. * Compute the angle between two Cartesian3.
  4305. * @param {!Cesium.Cartesian3} first
  4306. * @param {!Cesium.Cartesian3} second
  4307. * @param {!Cesium.Cartesian3} normal Normal to test orientation against.
  4308. * @return {number}
  4309. */
  4310. exports.signedAngleBetween = function(first, second, normal) {
  4311. // We are using the dot for the angle.
  4312. // Then the cross and the dot for the sign.
  4313. const a = new Cesium.Cartesian3();
  4314. const b = new Cesium.Cartesian3();
  4315. const c = new Cesium.Cartesian3();
  4316. Cesium.Cartesian3.normalize(first, a);
  4317. Cesium.Cartesian3.normalize(second, b);
  4318. Cesium.Cartesian3.cross(a, b, c);
  4319. const cosine = Cesium.Cartesian3.dot(a, b);
  4320. const sine = Cesium.Cartesian3.magnitude(c);
  4321. // Sign of the vector product and the orientation normal
  4322. const sign = Cesium.Cartesian3.dot(normal, c);
  4323. const angle = Math.atan2(sine, cosine);
  4324. return sign >= 0 ? angle : -angle;
  4325. };
  4326. /**
  4327. * Compute the rotation angle around a given point, needed to reach the
  4328. * zenith position.
  4329. * At a zenith position, the camera direction is going througth the earth
  4330. * center and the frustrum bottom ray is going through the chosen pivot
  4331. * point.
  4332. * The bottom-center of the screen is a good candidate for the pivot point.
  4333. * @param {!Cesium.Scene} scene
  4334. * @param {!Cesium.Cartesian3} pivot Point around which the camera rotates.
  4335. * @return {number}
  4336. * @api
  4337. */
  4338. exports.computeAngleToZenith = function(scene, pivot) {
  4339. // This angle is the sum of the angles 'fy' and 'a', which are defined
  4340. // using the pivot point and its surface normal.
  4341. // Zenith | camera
  4342. // \ | /
  4343. // \fy| /
  4344. // \ |a/
  4345. // \|/pivot
  4346. const camera = scene.camera;
  4347. const fy = camera.frustum.fovy / 2;
  4348. const ray = exports.bottomFovRay(scene);
  4349. const direction = Cesium.Cartesian3.clone(ray.direction);
  4350. Cesium.Cartesian3.negate(direction, direction);
  4351. const normal = new Cesium.Cartesian3();
  4352. Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(pivot, normal);
  4353. const left = new Cesium.Cartesian3();
  4354. Cesium.Cartesian3.negate(camera.right, left);
  4355. const a = exports.signedAngleBetween(normal, direction, left);
  4356. return a + fy;
  4357. };
  4358. /**
  4359. * Convert an OpenLayers extent to a Cesium rectangle.
  4360. * @param {ol.Extent} extent Extent.
  4361. * @param {ol.ProjectionLike} projection Extent projection.
  4362. * @return {Cesium.Rectangle} The corresponding Cesium rectangle.
  4363. * @api
  4364. */
  4365. exports.extentToRectangle = function(extent, projection) {
  4366. if (extent && projection) {
  4367. const ext = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.transformExtent)(extent, projection, 'EPSG:4326');
  4368. return Cesium.Rectangle.fromDegrees(ext[0], ext[1], ext[2], ext[3]);
  4369. } else {
  4370. return null;
  4371. }
  4372. };
  4373. /**
  4374. * @param {!ol.Map} olMap
  4375. * @param {!ol.source.Source} source
  4376. * @param {!ol.View} viewProj
  4377. * @param {!ol.layer.Base} olLayer
  4378. * @return {!Cesium.ImageryProvider}
  4379. */
  4380. exports.sourceToImageryProvider = function(olMap, source, viewProj, olLayer) {
  4381. const skip = source.get('olcs_skip');
  4382. if (skip) {
  4383. return null;
  4384. }
  4385. let provider = null;
  4386. // Convert ImageWMS to TileWMS
  4387. if (source instanceof (ol_source_ImageWMS_js__WEBPACK_IMPORTED_MODULE_5___default()) && source.getUrl() &&
  4388. source.getImageLoadFunction() === ol_source_Image_js__WEBPACK_IMPORTED_MODULE_9__.defaultImageLoadFunction) {
  4389. const sourceProps = {
  4390. 'olcs.proxy': source.get('olcs.proxy'),
  4391. 'olcs.extent': source.get('olcs.extent'),
  4392. 'olcs.projection': source.get('olcs.projection'),
  4393. 'olcs.imagesource': source
  4394. };
  4395. source = new (ol_source_TileWMS_js__WEBPACK_IMPORTED_MODULE_7___default())({
  4396. url: source.getUrl(),
  4397. attributions: source.getAttributions(),
  4398. projection: source.getProjection(),
  4399. params: source.getParams()
  4400. });
  4401. source.setProperties(sourceProps);
  4402. }
  4403. if (source instanceof (ol_source_TileImage_js__WEBPACK_IMPORTED_MODULE_6___default())) {
  4404. let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source);
  4405. if (!projection) {
  4406. // if not explicit, assume the same projection as view
  4407. projection = viewProj;
  4408. }
  4409. if (exports.isCesiumProjection(projection)) {
  4410. provider = new _core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_10__["default"](olMap, source, viewProj);
  4411. }
  4412. // Projection not supported by Cesium
  4413. else {
  4414. return null;
  4415. }
  4416. } else if (source instanceof (ol_source_ImageStatic_js__WEBPACK_IMPORTED_MODULE_4___default())) {
  4417. let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source);
  4418. if (!projection) {
  4419. projection = viewProj;
  4420. }
  4421. if (exports.isCesiumProjection(projection)) {
  4422. provider = new Cesium.SingleTileImageryProvider({
  4423. url: source.getUrl(),
  4424. rectangle: new Cesium.Rectangle.fromDegrees(
  4425. source.getImageExtent()[0],
  4426. source.getImageExtent()[1],
  4427. source.getImageExtent()[2],
  4428. source.getImageExtent()[3]
  4429. )
  4430. });
  4431. }
  4432. // Projection not supported by Cesium
  4433. else {
  4434. return null;
  4435. }
  4436. } else if (source instanceof (ol_source_VectorTile_js__WEBPACK_IMPORTED_MODULE_8___default())) {
  4437. let projection = _util_js__WEBPACK_IMPORTED_MODULE_11__["default"].getSourceProjection(source);
  4438. if (!projection) {
  4439. projection = viewProj;
  4440. }
  4441. if (skip === false) {
  4442. // MVT is experimental, it should be whitelisted to be synchronized
  4443. const fromCode = projection.getCode().split(':')[1];
  4444. const urls = source.urls.map(u => u.replace(fromCode, '3857'));
  4445. const extent = olLayer.getExtent();
  4446. const rectangle = exports.extentToRectangle(extent, projection);
  4447. const minimumLevel = source.get('olcs_minimumLevel');
  4448. const attributionsFunction = source.getAttributions();
  4449. const styleFunction = olLayer.getStyleFunction();
  4450. let credit;
  4451. if (extent && attributionsFunction) {
  4452. const center = (0,ol_extent__WEBPACK_IMPORTED_MODULE_14__.getCenter)(extent);
  4453. credit = attributionsFunctionToCredits(attributionsFunction, 0, center, extent)[0];
  4454. }
  4455. provider = new _MVTImageryProvider_js__WEBPACK_IMPORTED_MODULE_12__["default"]({
  4456. credit,
  4457. rectangle,
  4458. minimumLevel,
  4459. styleFunction,
  4460. urls
  4461. });
  4462. return provider;
  4463. }
  4464. return null; // FIXME: it is disabled by default right now
  4465. } else {
  4466. // sources other than TileImage|ImageStatic are currently not supported
  4467. return null;
  4468. }
  4469. return provider;
  4470. };
  4471. /**
  4472. * Creates Cesium.ImageryLayer best corresponding to the given ol.layer.Layer.
  4473. * Only supports raster layers and static images
  4474. * @param {!ol.Map} olMap
  4475. * @param {!ol.layer.Base} olLayer
  4476. * @param {!ol.proj.Projection} viewProj Projection of the view.
  4477. * @return {?Cesium.ImageryLayer} null if not possible (or supported)
  4478. * @api
  4479. */
  4480. exports.tileLayerToImageryLayer = function(olMap, olLayer, viewProj) {
  4481. if (!(olLayer instanceof (ol_layer_Tile_js__WEBPACK_IMPORTED_MODULE_1___default())) && !(olLayer instanceof (ol_layer_Image_js__WEBPACK_IMPORTED_MODULE_2___default())) &&
  4482. !(olLayer instanceof (ol_layer_VectorTile_js__WEBPACK_IMPORTED_MODULE_13___default()))) {
  4483. return null;
  4484. }
  4485. const source = olLayer.getSource();
  4486. if (!source) {
  4487. return null;
  4488. }
  4489. let provider = source.get('olcs_provider');
  4490. if (!provider) {
  4491. provider = this.sourceToImageryProvider(olMap, source, viewProj, olLayer);
  4492. }
  4493. if (!provider) {
  4494. return null;
  4495. }
  4496. const layerOptions = {};
  4497. const forcedExtent = /** @type {ol.Extent} */ (olLayer.get('olcs.extent'));
  4498. const ext = forcedExtent || olLayer.getExtent();
  4499. if (ext) {
  4500. layerOptions.rectangle = exports.extentToRectangle(ext, viewProj);
  4501. }
  4502. const cesiumLayer = new Cesium.ImageryLayer(provider, layerOptions);
  4503. return cesiumLayer;
  4504. };
  4505. /**
  4506. * Synchronizes the layer rendering properties (opacity, visible)
  4507. * to the given Cesium ImageryLayer.
  4508. * @param {olcsx.LayerWithParents} olLayerWithParents
  4509. * @param {!Cesium.ImageryLayer} csLayer
  4510. * @api
  4511. */
  4512. exports.updateCesiumLayerProperties = function(olLayerWithParents, csLayer) {
  4513. let opacity = 1;
  4514. let visible = true;
  4515. [olLayerWithParents.layer].concat(olLayerWithParents.parents).forEach((olLayer) => {
  4516. const layerOpacity = olLayer.getOpacity();
  4517. if (layerOpacity !== undefined) {
  4518. opacity *= layerOpacity;
  4519. }
  4520. const layerVisible = olLayer.getVisible();
  4521. if (layerVisible !== undefined) {
  4522. visible &= layerVisible;
  4523. }
  4524. });
  4525. csLayer.alpha = opacity;
  4526. csLayer.show = visible;
  4527. };
  4528. /**
  4529. * Convert a 2D or 3D OpenLayers coordinate to Cesium.
  4530. * @param {ol.Coordinate} coordinate Ol3 coordinate.
  4531. * @return {!Cesium.Cartesian3} Cesium cartesian coordinate
  4532. * @api
  4533. */
  4534. exports.ol4326CoordinateToCesiumCartesian = function(coordinate) {
  4535. const coo = coordinate;
  4536. return coo.length > 2 ?
  4537. Cesium.Cartesian3.fromDegrees(coo[0], coo[1], coo[2]) :
  4538. Cesium.Cartesian3.fromDegrees(coo[0], coo[1]);
  4539. };
  4540. /**
  4541. * Convert an array of 2D or 3D OpenLayers coordinates to Cesium.
  4542. * @param {Array.<!ol.Coordinate>} coordinates Ol3 coordinates.
  4543. * @return {!Array.<Cesium.Cartesian3>} Cesium cartesian coordinates
  4544. * @api
  4545. */
  4546. exports.ol4326CoordinateArrayToCsCartesians = function(coordinates) {
  4547. console.assert(coordinates !== null);
  4548. const toCartesian = exports.ol4326CoordinateToCesiumCartesian;
  4549. const cartesians = [];
  4550. for (let i = 0; i < coordinates.length; ++i) {
  4551. cartesians.push(toCartesian(coordinates[i]));
  4552. }
  4553. return cartesians;
  4554. };
  4555. /**
  4556. * Reproject an OpenLayers geometry to EPSG:4326 if needed.
  4557. * The geometry will be cloned only when original projection is not EPSG:4326
  4558. * and the properties will be shallow copied.
  4559. * @param {!T} geometry
  4560. * @param {!ol.ProjectionLike} projection
  4561. * @return {!T}
  4562. * @template T
  4563. * @api
  4564. */
  4565. exports.olGeometryCloneTo4326 = function(geometry, projection) {
  4566. console.assert(projection);
  4567. const proj4326 = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:4326');
  4568. const proj = (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)(projection);
  4569. if (proj !== proj4326) {
  4570. const properties = geometry.getProperties();
  4571. geometry = geometry.clone();
  4572. geometry.transform(proj, proj4326);
  4573. geometry.setProperties(properties);
  4574. }
  4575. return geometry;
  4576. };
  4577. /**
  4578. * Convert an OpenLayers color to Cesium.
  4579. * @param {ol.Color|CanvasGradient|CanvasPattern|string} olColor
  4580. * @return {!Cesium.Color}
  4581. * @api
  4582. */
  4583. exports.convertColorToCesium = function(olColor) {
  4584. olColor = olColor || 'black';
  4585. if (Array.isArray(olColor)) {
  4586. return new Cesium.Color(
  4587. Cesium.Color.byteToFloat(olColor[0]),
  4588. Cesium.Color.byteToFloat(olColor[1]),
  4589. Cesium.Color.byteToFloat(olColor[2]),
  4590. olColor[3]
  4591. );
  4592. } else if (typeof olColor == 'string') {
  4593. return Cesium.Color.fromCssColorString(olColor);
  4594. } else if (olColor instanceof CanvasPattern || olColor instanceof CanvasGradient) {
  4595. // Render the CanvasPattern/CanvasGradient into a canvas that will be sent to Cesium as material
  4596. const canvas = document.createElement('canvas');
  4597. const ctx = canvas.getContext('2d');
  4598. canvas.width = canvas.height = 256;
  4599. ctx.fillStyle = olColor;
  4600. ctx.fillRect(0, 0, canvas.width, canvas.height);
  4601. return new Cesium.ImageMaterialProperty({
  4602. image: canvas
  4603. });
  4604. }
  4605. console.assert(false, 'impossible');
  4606. };
  4607. /**
  4608. * Convert an OpenLayers url to Cesium.
  4609. * @param {string} url
  4610. * @return {!CesiumUrlDefinition}
  4611. * @api
  4612. */
  4613. exports.convertUrlToCesium = function(url) {
  4614. let subdomains = '';
  4615. const re = /\{(\d|[a-z])-(\d|[a-z])\}/;
  4616. const match = re.exec(url);
  4617. if (match) {
  4618. url = url.replace(re, '{s}');
  4619. const startCharCode = match[1].charCodeAt(0);
  4620. const stopCharCode = match[2].charCodeAt(0);
  4621. let charCode;
  4622. for (charCode = startCharCode; charCode <= stopCharCode; ++charCode) {
  4623. subdomains += String.fromCharCode(charCode);
  4624. }
  4625. }
  4626. return {
  4627. url,
  4628. subdomains
  4629. };
  4630. };
  4631. /**
  4632. * Animate the return to a top-down view from the zenith.
  4633. * The camera is rotated to orient to the North.
  4634. * @param {!ol.Map} map
  4635. * @param {!Cesium.Scene} scene
  4636. * @return {Promise<undefined>}
  4637. * @api
  4638. */
  4639. exports.resetToNorthZenith = function(map, scene) {
  4640. return new Promise((resolve, reject) => {
  4641. const camera = scene.camera;
  4642. const pivot = exports.pickBottomPoint(scene);
  4643. if (!pivot) {
  4644. reject('Could not get bottom pivot');
  4645. return;
  4646. }
  4647. const currentHeading = map.getView().getRotation();
  4648. if (currentHeading === undefined) {
  4649. reject('The view is not initialized');
  4650. return;
  4651. }
  4652. const angle = exports.computeAngleToZenith(scene, pivot);
  4653. // Point to North
  4654. exports.setHeadingUsingBottomCenter(scene, currentHeading, pivot);
  4655. // Go to zenith
  4656. const transform = Cesium.Matrix4.fromTranslation(pivot);
  4657. const axis = camera.right;
  4658. const options = {
  4659. callback: () => {
  4660. const view = map.getView();
  4661. exports.normalizeView(view);
  4662. resolve();
  4663. }
  4664. };
  4665. exports.rotateAroundAxis(camera, -angle, axis, transform, options);
  4666. });
  4667. };
  4668. /**
  4669. * @param {!Cesium.Scene} scene
  4670. * @param {number} angle in radian
  4671. * @return {Promise<undefined>}
  4672. * @api
  4673. */
  4674. exports.rotateAroundBottomCenter = function(scene, angle) {
  4675. return new Promise((resolve, reject) => {
  4676. const camera = scene.camera;
  4677. const pivot = exports.pickBottomPoint(scene);
  4678. if (!pivot) {
  4679. reject('could not get bottom pivot');
  4680. return;
  4681. }
  4682. const options = {callback: resolve};
  4683. const transform = Cesium.Matrix4.fromTranslation(pivot);
  4684. const axis = camera.right;
  4685. const rotateAroundAxis = exports.rotateAroundAxis;
  4686. rotateAroundAxis(camera, -angle, axis, transform, options);
  4687. });
  4688. };
  4689. /**
  4690. * Set the OpenLayers view to a specific rotation and
  4691. * the nearest resolution.
  4692. * @param {ol.View} view
  4693. * @param {number=} angle
  4694. * @api
  4695. */
  4696. exports.normalizeView = function(view, angle = 0) {
  4697. const resolution = view.getResolution();
  4698. view.setRotation(angle);
  4699. if (view.constrainResolution) {
  4700. view.setResolution(view.constrainResolution(resolution));
  4701. } else {
  4702. view.setResolution(view.getConstrainedResolution(resolution));
  4703. }
  4704. };
  4705. /**
  4706. * Check if the given projection is managed by Cesium (WGS84 or Mercator Spheric)
  4707. *
  4708. * @param {ol.proj.Projection} projection Projection to check.
  4709. * @returns {boolean} Whether it's managed by Cesium.
  4710. */
  4711. exports.isCesiumProjection = function(projection) {
  4712. const is3857 = projection === (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:3857');
  4713. const is4326 = projection === (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_3__.get)('EPSG:4326');
  4714. return is3857 || is4326;
  4715. };
  4716. function attributionsFunctionToCredits(attributionsFunction, zoom, center, extent) {
  4717. const frameState = {
  4718. viewState: {zoom, center},
  4719. extent,
  4720. };
  4721. if (!attributionsFunction) {
  4722. return [];
  4723. }
  4724. let attributions = attributionsFunction(frameState);
  4725. if (!Array.isArray(attributions)) {
  4726. attributions = [attributions];
  4727. }
  4728. return attributions.map(html => new Cesium.Credit(html, true));
  4729. }
  4730. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (exports);
  4731. /**
  4732. * calculate the distance between camera and centerpoint based on the resolution and latitude value
  4733. * @param {number} resolution Number of map units per pixel.
  4734. * @param {number} latitude Latitude in radians.
  4735. * @param {import('cesium').Scene} scene.
  4736. * @param {import('ol/proj/Projection').default} projection View projection.
  4737. * @return {number} The calculated distance.
  4738. * @api
  4739. */
  4740. function calcDistanceForResolution(resolution, latitude, scene, projection) {
  4741. const canvas = scene.canvas;
  4742. const camera = scene.camera;
  4743. const fovy = camera.frustum.fovy; // vertical field of view
  4744. console.assert(!isNaN(fovy));
  4745. const metersPerUnit = projection.getMetersPerUnit();
  4746. // number of "map units" visible in 2D (vertically)
  4747. const visibleMapUnits = resolution * canvas.clientHeight;
  4748. // The metersPerUnit does not take latitude into account, but it should
  4749. // be lower with increasing latitude -- we have to compensate.
  4750. // In 3D it is not possible to maintain the resolution at more than one point,
  4751. // so it only makes sense to use the latitude of the "target" point.
  4752. const relativeCircumference = Math.cos(Math.abs(latitude));
  4753. // how many meters should be visible in 3D
  4754. const visibleMeters = visibleMapUnits * metersPerUnit * relativeCircumference;
  4755. // distance required to view the calculated length in meters
  4756. //
  4757. // fovy/2
  4758. // |\
  4759. // x | \
  4760. // |--\
  4761. // visibleMeters/2
  4762. const requiredDistance = (visibleMeters / 2) / Math.tan(fovy / 2);
  4763. // NOTE: This calculation is not absolutely precise, because metersPerUnit
  4764. // is a great simplification. It does not take ellipsoid/terrain into account.
  4765. return requiredDistance;
  4766. }
  4767. /**
  4768. * calculate the resolution based on a distance(camera to position) and latitude value
  4769. * @param {number} distance
  4770. * @param {number} latitude
  4771. * @param {import('cesium').Scene} scene.
  4772. * @param {import('ol/proj/Projection').default} projection View projection.
  4773. * @return {number} The calculated resolution.
  4774. * @api
  4775. */
  4776. function calcResolutionForDistance(distance, latitude, scene, projection) {
  4777. // See the reverse calculation (calcDistanceForResolution) for details
  4778. const canvas = scene.canvas;
  4779. const camera = scene.camera;
  4780. const fovy = camera.frustum.fovy; // vertical field of view
  4781. console.assert(!isNaN(fovy));
  4782. const metersPerUnit = projection.getMetersPerUnit();
  4783. const visibleMeters = 2 * distance * Math.tan(fovy / 2);
  4784. const relativeCircumference = Math.cos(Math.abs(latitude));
  4785. const visibleMapUnits = visibleMeters / metersPerUnit / relativeCircumference;
  4786. const resolution = visibleMapUnits / canvas.clientHeight;
  4787. return resolution;
  4788. }
  4789. /***/ }),
  4790. /***/ "./src/olcs/core/OLImageryProvider.js":
  4791. /*!********************************************!*\
  4792. !*** ./src/olcs/core/OLImageryProvider.js ***!
  4793. \********************************************/
  4794. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  4795. __webpack_require__.r(__webpack_exports__);
  4796. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  4797. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  4798. /* harmony export */ });
  4799. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/proj.js */ "ol/proj.js");
  4800. /* harmony import */ var ol_proj_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_proj_js__WEBPACK_IMPORTED_MODULE_0__);
  4801. /* harmony import */ var _util_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../util.js */ "./src/olcs/util.js");
  4802. /* harmony import */ var ol_source_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ol/source.js */ "ol/source.js");
  4803. /* harmony import */ var ol_source_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(ol_source_js__WEBPACK_IMPORTED_MODULE_2__);
  4804. /* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../core.js */ "./src/olcs/core.js");
  4805. /**
  4806. * @module olcs.core.OLImageryProvider
  4807. */
  4808. const olUseNewCoordinates = (function() {
  4809. const tileSource = new ol_source_js__WEBPACK_IMPORTED_MODULE_2__.Tile({
  4810. projection: 'EPSG:3857',
  4811. wrapX: true
  4812. });
  4813. const tileCoord = tileSource.getTileCoordForTileUrlFunction([6, -31, 22]);
  4814. return tileCoord && tileCoord[1] === 33 && tileCoord[2] === 22;
  4815. // See b/test/spec/ol/source/tile.test.js
  4816. // of e9a30c5cb7e3721d9370025fbe5472c322847b35 in OpenLayers repository
  4817. })();
  4818. class OLImageryProvider /* should not extend Cesium.ImageryProvider */ {
  4819. /**
  4820. * Special class derived from Cesium.ImageryProvider
  4821. * that is connected to the given ol.source.TileImage.
  4822. * @param {!ol.Map} olMap
  4823. * @param {!ol.source.TileImage} source
  4824. * @param {ol.proj.Projection=} opt_fallbackProj Projection to assume if the
  4825. * projection of the source is not defined.
  4826. * @constructor
  4827. * @extends {Cesium.ImageryProvider}
  4828. */
  4829. constructor(olMap, source, opt_fallbackProj) {
  4830. // Do not extend or call super constructor from
  4831. // Cesium.ImageryProvider since this particular function is a
  4832. // 'non instanciable interface' which throws on instanciation.
  4833. /**
  4834. * @type {!ol.source.TileImage}
  4835. * @private
  4836. */
  4837. this.source_ = source;
  4838. /**
  4839. * @type {?ol.proj.Projection}
  4840. * @private
  4841. */
  4842. this.projection_ = null;
  4843. /**
  4844. * @type {?ol.proj.Projection}
  4845. * @private
  4846. */
  4847. this.fallbackProj_ = opt_fallbackProj || null;
  4848. /**
  4849. * @type {boolean}
  4850. * @private
  4851. */
  4852. this.ready_ = false;
  4853. /**
  4854. * @type {?Cesium.TilingScheme}
  4855. * @private
  4856. */
  4857. this.tilingScheme_ = null;
  4858. /**
  4859. * @type {?Cesium.Rectangle}
  4860. * @private
  4861. */
  4862. this.rectangle_ = null;
  4863. /**
  4864. * @type {!ol.Map}
  4865. * @private
  4866. */
  4867. this.map_ = olMap;
  4868. /**
  4869. * @type {boolean}
  4870. * @private
  4871. */
  4872. this.shouldRequestNextLevel = false;
  4873. const proxy = this.source_.get('olcs.proxy');
  4874. if (proxy) {
  4875. if (typeof proxy === 'function') {
  4876. this.proxy_ = {
  4877. 'getURL': proxy
  4878. };
  4879. } else if (typeof proxy === 'string') {
  4880. this.proxy_ = new Cesium.DefaultProxy(proxy);
  4881. }
  4882. }
  4883. this.errorEvent_ = new Cesium.Event();
  4884. this.emptyCanvas_ = document.createElement('canvas');
  4885. this.emptyCanvas_.width = 1;
  4886. this.emptyCanvas_.height = 1;
  4887. this.source_.on('change', (e) => {
  4888. this.handleSourceChanged_();
  4889. });
  4890. this.handleSourceChanged_();
  4891. }
  4892. /**
  4893. * Checks if the underlying source is ready and cached required data.
  4894. * @private
  4895. */
  4896. handleSourceChanged_(frameState) {
  4897. if (!this.ready_ && this.source_.getState() == 'ready') {
  4898. this.projection_ = _util_js__WEBPACK_IMPORTED_MODULE_1__["default"].getSourceProjection(this.source_) || this.fallbackProj_;
  4899. const options = {numberOfLevelZeroTilesX: 1, numberOfLevelZeroTilesY: 1};
  4900. if (this.source_.tileGrid !== null) {
  4901. // Get the number of tiles at level 0 if it is defined
  4902. this.source_.tileGrid.forEachTileCoord(this.projection_.getExtent(), 0, ([zoom, xIndex, yIndex]) => {
  4903. options.numberOfLevelZeroTilesX = xIndex + 1;
  4904. options.numberOfLevelZeroTilesY = yIndex + 1;
  4905. });
  4906. }
  4907. if (this.projection_ == (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_0__.get)('EPSG:4326')) {
  4908. // Cesium zoom level 0 is OpenLayers zoom level 1 for layer in EPSG:4326 with a single tile on level 0
  4909. this.shouldRequestNextLevel = options.numberOfLevelZeroTilesX === 1 && options.numberOfLevelZeroTilesY === 1;
  4910. this.tilingScheme_ = new Cesium.GeographicTilingScheme(options);
  4911. } else if (this.projection_ == (0,ol_proj_js__WEBPACK_IMPORTED_MODULE_0__.get)('EPSG:3857')) {
  4912. this.shouldRequestNextLevel = false;
  4913. this.tilingScheme_ = new Cesium.WebMercatorTilingScheme(options);
  4914. } else {
  4915. return;
  4916. }
  4917. this.rectangle_ = this.tilingScheme_.rectangle;
  4918. this.ready_ = true;
  4919. }
  4920. }
  4921. /**
  4922. * Generates the proper attributions for a given position and zoom
  4923. * level.
  4924. * @export
  4925. * @override
  4926. */
  4927. getTileCredits(x, y, level) {
  4928. const attributionsFunction = this.source_.getAttributions();
  4929. if (!attributionsFunction) {
  4930. return [];
  4931. }
  4932. const extent = this.map_.getView().calculateExtent(this.map_.getSize());
  4933. const center = this.map_.getView().getCenter();
  4934. const zoom = this.shouldRequestNextLevel ? level + 1 : level;
  4935. return (0,_core_js__WEBPACK_IMPORTED_MODULE_3__.attributionsFunctionToCredits)(attributionsFunction, zoom, center, extent);
  4936. }
  4937. /**
  4938. * @export
  4939. * @override
  4940. */
  4941. requestImage(x, y, level) {
  4942. const tileUrlFunction = this.source_.getTileUrlFunction();
  4943. if (tileUrlFunction && this.projection_) {
  4944. const z_ = this.shouldRequestNextLevel ? level + 1 : level;
  4945. let y_ = y;
  4946. if (!olUseNewCoordinates) {
  4947. // OpenLayers version 3 to 5 tile coordinates increase from bottom to top
  4948. y_ = -y - 1;
  4949. }
  4950. let url = tileUrlFunction.call(this.source_, [z_, x, y_], 1, this.projection_);
  4951. if (this.proxy_) {
  4952. url = this.proxy_.getURL(url);
  4953. }
  4954. return url ? Cesium.ImageryProvider.loadImage(this, url) : this.emptyCanvas_;
  4955. } else {
  4956. // return empty canvas to stop Cesium from retrying later
  4957. return this.emptyCanvas_;
  4958. }
  4959. }
  4960. }
  4961. // definitions of getters that are required to be present
  4962. // in the Cesium.ImageryProvider instance:
  4963. Object.defineProperties(OLImageryProvider.prototype, {
  4964. 'ready': {
  4965. 'get': /** @this {olcs.core.OLImageryProvider} */
  4966. function() {return this.ready_;}
  4967. },
  4968. 'rectangle': {
  4969. 'get': /** @this {olcs.core.OLImageryProvider} */
  4970. function() {return this.rectangle_;}
  4971. },
  4972. 'tileWidth': {
  4973. 'get': /** @this {olcs.core.OLImageryProvider} */
  4974. function() {
  4975. const tg = this.source_.getTileGrid();
  4976. return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[0] : tg.getTileSize(0)) : 256;
  4977. }
  4978. },
  4979. 'tileHeight': {
  4980. 'get': /** @this {olcs.core.OLImageryProvider} */
  4981. function() {
  4982. const tg = this.source_.getTileGrid();
  4983. return tg ? (Array.isArray(tg.getTileSize(0)) ? tg.getTileSize(0)[1] : tg.getTileSize(0)) : 256;
  4984. }
  4985. },
  4986. 'maximumLevel': {
  4987. 'get': /** @this {olcs.core.OLImageryProvider} */
  4988. function() {
  4989. const tg = this.source_.getTileGrid();
  4990. return tg ? tg.getMaxZoom() : 18;
  4991. }
  4992. },
  4993. 'minimumLevel': {
  4994. 'get': /** @this {olcs.core.OLImageryProvider} */
  4995. function() {
  4996. // WARNING: Do not use the minimum level (at least until the extent is
  4997. // properly set). Cesium assumes the minimumLevel to contain only
  4998. // a few tiles and tries to load them all at once -- this can
  4999. // freeze and/or crash the browser !
  5000. return 0;
  5001. //var tg = this.source_.getTileGrid();
  5002. //return tg ? tg.getMinZoom() : 0;
  5003. }
  5004. },
  5005. 'tilingScheme': {
  5006. 'get': /** @this {olcs.core.OLImageryProvider} */
  5007. function() {return this.tilingScheme_;}
  5008. },
  5009. 'tileDiscardPolicy': {
  5010. 'get': function() {return undefined;}
  5011. },
  5012. 'errorEvent': {
  5013. 'get': /** @this {olcs.core.OLImageryProvider} */
  5014. function() {return this.errorEvent_;}
  5015. },
  5016. 'proxy': {
  5017. 'get': /** @this {olcs.core.OLImageryProvider} */
  5018. function() {return this.proxy_;}
  5019. },
  5020. 'hasAlphaChannel': {
  5021. 'get': function() {return true;}
  5022. },
  5023. 'pickFeatures': {
  5024. 'get': function() {return undefined;}
  5025. }
  5026. });
  5027. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (OLImageryProvider);
  5028. /***/ }),
  5029. /***/ "./src/olcs/core/VectorLayerCounterpart.js":
  5030. /*!*************************************************!*\
  5031. !*** ./src/olcs/core/VectorLayerCounterpart.js ***!
  5032. \*************************************************/
  5033. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  5034. __webpack_require__.r(__webpack_exports__);
  5035. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  5036. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  5037. /* harmony export */ });
  5038. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ol/Observable.js */ "ol/Observable.js");
  5039. /* harmony import */ var ol_Observable_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__);
  5040. /**
  5041. * @module olcs.core.VectorLayerCounterpart
  5042. */
  5043. /**
  5044. * Context for feature conversion.
  5045. * @typedef {Object} OlFeatureToCesiumContext
  5046. * @property {!(import('ol/Projection.js').default|string)} projection
  5047. * @property {!Cesium.PrimitiveCollection} primitives
  5048. * @property {Object<number, Array<!Cesium.Primitive|!Cesium.Billboard>>} featureToCesiumMap
  5049. * @property {!Cesium.BillboardCollection} billboards
  5050. */
  5051. class VectorLayerCounterpart {
  5052. /**
  5053. * Result of the conversion of an OpenLayers layer to Cesium.
  5054. * @param {!(ol.proj.Projection|string)} layerProjection
  5055. * @param {!Cesium.Scene} scene
  5056. */
  5057. constructor(layerProjection, scene) {
  5058. const billboards = new Cesium.BillboardCollection({scene});
  5059. const primitives = new Cesium.PrimitiveCollection();
  5060. /**
  5061. * @type {!Array.<ol.EventsKey>}
  5062. */
  5063. this.olListenKeys = [];
  5064. this.rootCollection_ = new Cesium.PrimitiveCollection();
  5065. /**
  5066. * @type {!OlFeatureToCesiumContext}
  5067. */
  5068. this.context = {
  5069. projection: layerProjection,
  5070. billboards,
  5071. featureToCesiumMap: {},
  5072. primitives
  5073. };
  5074. this.rootCollection_.add(billboards);
  5075. this.rootCollection_.add(primitives);
  5076. }
  5077. /**
  5078. * Unlisten.
  5079. */
  5080. destroy() {
  5081. this.olListenKeys.forEach(ol_Observable_js__WEBPACK_IMPORTED_MODULE_0__.unByKey);
  5082. this.olListenKeys.length = 0;
  5083. }
  5084. /**
  5085. * @return {!Cesium.Primitive}
  5086. */
  5087. getRootPrimitive() {
  5088. return this.rootCollection_;
  5089. }
  5090. }
  5091. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (VectorLayerCounterpart);
  5092. /***/ }),
  5093. /***/ "./src/olcs/math.js":
  5094. /*!**************************!*\
  5095. !*** ./src/olcs/math.js ***!
  5096. \**************************/
  5097. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  5098. __webpack_require__.r(__webpack_exports__);
  5099. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  5100. /* harmony export */ "toDegrees": () => (/* binding */ toDegrees),
  5101. /* harmony export */ "toRadians": () => (/* binding */ toRadians)
  5102. /* harmony export */ });
  5103. /**
  5104. * Converts radians to to degrees.
  5105. *
  5106. * @param {number} angleInRadians Angle in radians.
  5107. * @return {number} Angle in degrees.
  5108. */
  5109. function toDegrees(angleInRadians) {
  5110. return angleInRadians * 180 / Math.PI;
  5111. }
  5112. /**
  5113. * Converts degrees to radians.
  5114. *
  5115. * @param {number} angleInDegrees Angle in degrees.
  5116. * @return {number} Angle in radians.
  5117. */
  5118. function toRadians(angleInDegrees) {
  5119. return angleInDegrees * Math.PI / 180;
  5120. }
  5121. /***/ }),
  5122. /***/ "./src/olcs/util.js":
  5123. /*!**************************!*\
  5124. !*** ./src/olcs/util.js ***!
  5125. \**************************/
  5126. /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
  5127. __webpack_require__.r(__webpack_exports__);
  5128. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  5129. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
  5130. /* harmony export */ "getUid": () => (/* binding */ getUid),
  5131. /* harmony export */ "isGroundPolylinePrimitiveSupported": () => (/* binding */ isGroundPolylinePrimitiveSupported),
  5132. /* harmony export */ "olcsListen": () => (/* binding */ olcsListen),
  5133. /* harmony export */ "removeChildren": () => (/* binding */ removeChildren),
  5134. /* harmony export */ "removeNode": () => (/* binding */ removeNode),
  5135. /* harmony export */ "stableSort": () => (/* binding */ stableSort)
  5136. /* harmony export */ });
  5137. /**
  5138. * @module olcs.util
  5139. */
  5140. const exports = {};
  5141. /**
  5142. * Cast to object.
  5143. * @param {Object} param
  5144. * @return {Object}
  5145. */
  5146. exports.obj = function(param) {
  5147. return param;
  5148. };
  5149. /**
  5150. * @type {boolean|undefined}
  5151. * @private
  5152. */
  5153. exports.supportsImageRenderingPixelatedResult_ = undefined;
  5154. /**
  5155. * @type {string|undefined}
  5156. * @private
  5157. */
  5158. exports.imageRenderingValueResult_ = undefined;
  5159. /**
  5160. * @return {boolean}
  5161. */
  5162. exports.supportsImageRenderingPixelated = function() {
  5163. if (exports.supportsImageRenderingPixelatedResult_ === undefined) {
  5164. const canvas = document.createElement('canvas');
  5165. canvas.setAttribute('style', 'image-rendering: -moz-crisp-edges; image-rendering: pixelated;');
  5166. // canvas.style.imageRendering will be undefined, null or an
  5167. // empty string on unsupported browsers.
  5168. const tmp = canvas.style['imageRendering']; // non standard
  5169. exports.supportsImageRenderingPixelatedResult_ = !!tmp;
  5170. if (exports.supportsImageRenderingPixelatedResult_) {
  5171. exports.imageRenderingValueResult_ = tmp;
  5172. }
  5173. }
  5174. return exports.supportsImageRenderingPixelatedResult_;
  5175. };
  5176. /**
  5177. * @return {string}
  5178. */
  5179. exports.imageRenderingValue = function() {
  5180. exports.supportsImageRenderingPixelated();
  5181. return exports.imageRenderingValueResult_ || '';
  5182. };
  5183. /**
  5184. * Return the projection of the source that Cesium should use.
  5185. *
  5186. * @param {ol.source.Source} source Source.
  5187. * @returns {ol.proj.Projection} The projection of the source.
  5188. */
  5189. exports.getSourceProjection = function(source) {
  5190. return /** @type {ol.proj.Projection} */ (source.get('olcs.projection'))
  5191. || source.getProjection();
  5192. };
  5193. /**
  5194. * @param {ol.Observable} observable
  5195. * @param {string} type
  5196. * @param {Function} listener
  5197. * @return {!ol.events.EventsKey}
  5198. */
  5199. function olcsListen(observable, type, listener) {
  5200. // See https://github.com/openlayers/openlayers/pull/8481
  5201. // ol.events.listen is internal so we use `on` instead.
  5202. // And since `on` as a convoluted API (can return an EventsKey or an array of them)
  5203. // we use a cast here.
  5204. return /** @type {!ol.events.EventsKey} */ (observable.on(type, listener));
  5205. }
  5206. /**
  5207. * Counter for getUid.
  5208. * @type {number}
  5209. */
  5210. let uidCounter_ = 0;
  5211. /**
  5212. * Gets a unique ID for an object. This mutates the object so that further calls
  5213. * with the same object as a parameter returns the same value. Unique IDs are generated
  5214. * as a strictly increasing sequence. Adapted from goog.getUid.
  5215. *
  5216. * @param {Object} obj The object to get the unique ID for.
  5217. * @return {number} The unique ID for the object.
  5218. */
  5219. function getUid(obj) {
  5220. return obj.olcs_uid || (obj.olcs_uid = ++uidCounter_);
  5221. }
  5222. /**
  5223. * Sort the passed array such that the relative order of equal elements is preverved.
  5224. * See https://en.wikipedia.org/wiki/Sorting_algorithm#Stability for details.
  5225. * @param {Array<*>} arr The array to sort (modifies original).
  5226. * @param {!function(*, *): number} compareFnc Comparison function.
  5227. */
  5228. function stableSort(arr, compareFnc) {
  5229. const length = arr.length;
  5230. const tmp = Array(arr.length);
  5231. for (let i = 0; i < length; i++) {
  5232. tmp[i] = {index: i, value: arr[i]};
  5233. }
  5234. tmp.sort((a, b) => compareFnc(a.value, b.value) || a.index - b.index);
  5235. for (let i = 0; i < arr.length; i++) {
  5236. arr[i] = tmp[i].value;
  5237. }
  5238. }
  5239. /**
  5240. * @param {Node} node The node to remove.
  5241. * @returns {Node} The node that was removed or null.
  5242. */
  5243. function removeNode(node) {
  5244. return node && node.parentNode ? node.parentNode.removeChild(node) : null;
  5245. }
  5246. /**
  5247. * @param {Node} node The node to remove the children from.
  5248. */
  5249. function removeChildren(node) {
  5250. while (node.lastChild) {
  5251. node.removeChild(node.lastChild);
  5252. }
  5253. }
  5254. /**
  5255. * @param {Cesium.Scene} scene The scene.
  5256. */
  5257. function isGroundPolylinePrimitiveSupported(scene) {
  5258. const obj = Cesium.GroundPolylinePrimitive;
  5259. return obj && obj.isSupported(scene);
  5260. }
  5261. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (exports);
  5262. /***/ }),
  5263. /***/ "ol/Observable.js":
  5264. /*!********************************!*\
  5265. !*** external "ol.Observable" ***!
  5266. \********************************/
  5267. /***/ ((module) => {
  5268. module.exports = ol.Observable;
  5269. /***/ }),
  5270. /***/ "ol/Overlay.js":
  5271. /*!*****************************!*\
  5272. !*** external "ol.Overlay" ***!
  5273. \*****************************/
  5274. /***/ ((module) => {
  5275. module.exports = ol.Overlay;
  5276. /***/ }),
  5277. /***/ "ol/easing.js":
  5278. /*!****************************!*\
  5279. !*** external "ol.easing" ***!
  5280. \****************************/
  5281. /***/ ((module) => {
  5282. module.exports = ol.easing;
  5283. /***/ }),
  5284. /***/ "ol/extent":
  5285. /*!****************************!*\
  5286. !*** external "ol.extent" ***!
  5287. \****************************/
  5288. /***/ ((module) => {
  5289. module.exports = ol.extent;
  5290. /***/ }),
  5291. /***/ "ol/format/MVT.js":
  5292. /*!********************************!*\
  5293. !*** external "ol.format.MVT" ***!
  5294. \********************************/
  5295. /***/ ((module) => {
  5296. module.exports = ol.format.MVT;
  5297. /***/ }),
  5298. /***/ "ol/geom/Geometry.js":
  5299. /*!***********************************!*\
  5300. !*** external "ol.geom.Geometry" ***!
  5301. \***********************************/
  5302. /***/ ((module) => {
  5303. module.exports = ol.geom.Geometry;
  5304. /***/ }),
  5305. /***/ "ol/geom/Point.js":
  5306. /*!********************************!*\
  5307. !*** external "ol.geom.Point" ***!
  5308. \********************************/
  5309. /***/ ((module) => {
  5310. module.exports = ol.geom.Point;
  5311. /***/ }),
  5312. /***/ "ol/geom/Polygon.js":
  5313. /*!**********************************!*\
  5314. !*** external "ol.geom.Polygon" ***!
  5315. \**********************************/
  5316. /***/ ((module) => {
  5317. module.exports = ol.geom.Polygon;
  5318. /***/ }),
  5319. /***/ "ol/geom/SimpleGeometry.js":
  5320. /*!*****************************************!*\
  5321. !*** external "ol.geom.SimpleGeometry" ***!
  5322. \*****************************************/
  5323. /***/ ((module) => {
  5324. module.exports = ol.geom.SimpleGeometry;
  5325. /***/ }),
  5326. /***/ "ol/layer/Group.js":
  5327. /*!*********************************!*\
  5328. !*** external "ol.layer.Group" ***!
  5329. \*********************************/
  5330. /***/ ((module) => {
  5331. module.exports = ol.layer.Group;
  5332. /***/ }),
  5333. /***/ "ol/layer/Image.js":
  5334. /*!*********************************!*\
  5335. !*** external "ol.layer.Image" ***!
  5336. \*********************************/
  5337. /***/ ((module) => {
  5338. module.exports = ol.layer.Image;
  5339. /***/ }),
  5340. /***/ "ol/layer/Layer.js":
  5341. /*!*********************************!*\
  5342. !*** external "ol.layer.Layer" ***!
  5343. \*********************************/
  5344. /***/ ((module) => {
  5345. module.exports = ol.layer.Layer;
  5346. /***/ }),
  5347. /***/ "ol/layer/Tile.js":
  5348. /*!********************************!*\
  5349. !*** external "ol.layer.Tile" ***!
  5350. \********************************/
  5351. /***/ ((module) => {
  5352. module.exports = ol.layer.Tile;
  5353. /***/ }),
  5354. /***/ "ol/layer/Vector.js":
  5355. /*!**********************************!*\
  5356. !*** external "ol.layer.Vector" ***!
  5357. \**********************************/
  5358. /***/ ((module) => {
  5359. module.exports = ol.layer.Vector;
  5360. /***/ }),
  5361. /***/ "ol/layer/VectorTile.js":
  5362. /*!**************************************!*\
  5363. !*** external "ol.layer.VectorTile" ***!
  5364. \**************************************/
  5365. /***/ ((module) => {
  5366. module.exports = ol.layer.VectorTile;
  5367. /***/ }),
  5368. /***/ "ol/proj.js":
  5369. /*!**************************!*\
  5370. !*** external "ol.proj" ***!
  5371. \**************************/
  5372. /***/ ((module) => {
  5373. module.exports = ol.proj;
  5374. /***/ }),
  5375. /***/ "ol/render.js":
  5376. /*!****************************!*\
  5377. !*** external "ol.render" ***!
  5378. \****************************/
  5379. /***/ ((module) => {
  5380. module.exports = ol.render;
  5381. /***/ }),
  5382. /***/ "ol/source.js":
  5383. /*!****************************!*\
  5384. !*** external "ol.source" ***!
  5385. \****************************/
  5386. /***/ ((module) => {
  5387. module.exports = ol.source;
  5388. /***/ }),
  5389. /***/ "ol/source/Cluster.js":
  5390. /*!************************************!*\
  5391. !*** external "ol.source.Cluster" ***!
  5392. \************************************/
  5393. /***/ ((module) => {
  5394. module.exports = ol.source.Cluster;
  5395. /***/ }),
  5396. /***/ "ol/source/Image.js":
  5397. /*!**********************************!*\
  5398. !*** external "ol.source.Image" ***!
  5399. \**********************************/
  5400. /***/ ((module) => {
  5401. module.exports = ol.source.Image;
  5402. /***/ }),
  5403. /***/ "ol/source/ImageStatic.js":
  5404. /*!****************************************!*\
  5405. !*** external "ol.source.ImageStatic" ***!
  5406. \****************************************/
  5407. /***/ ((module) => {
  5408. module.exports = ol.source.ImageStatic;
  5409. /***/ }),
  5410. /***/ "ol/source/ImageWMS.js":
  5411. /*!*************************************!*\
  5412. !*** external "ol.source.ImageWMS" ***!
  5413. \*************************************/
  5414. /***/ ((module) => {
  5415. module.exports = ol.source.ImageWMS;
  5416. /***/ }),
  5417. /***/ "ol/source/TileImage.js":
  5418. /*!**************************************!*\
  5419. !*** external "ol.source.TileImage" ***!
  5420. \**************************************/
  5421. /***/ ((module) => {
  5422. module.exports = ol.source.TileImage;
  5423. /***/ }),
  5424. /***/ "ol/source/TileWMS.js":
  5425. /*!************************************!*\
  5426. !*** external "ol.source.TileWMS" ***!
  5427. \************************************/
  5428. /***/ ((module) => {
  5429. module.exports = ol.source.TileWMS;
  5430. /***/ }),
  5431. /***/ "ol/source/Vector.js":
  5432. /*!***********************************!*\
  5433. !*** external "ol.source.Vector" ***!
  5434. \***********************************/
  5435. /***/ ((module) => {
  5436. module.exports = ol.source.Vector;
  5437. /***/ }),
  5438. /***/ "ol/source/VectorTile.js":
  5439. /*!***************************************!*\
  5440. !*** external "ol.source.VectorTile" ***!
  5441. \***************************************/
  5442. /***/ ((module) => {
  5443. module.exports = ol.source.VectorTile;
  5444. /***/ }),
  5445. /***/ "ol/structs/LRUCache.js":
  5446. /*!**************************************!*\
  5447. !*** external "ol.structs.LRUCache" ***!
  5448. \**************************************/
  5449. /***/ ((module) => {
  5450. module.exports = ol.structs.LRUCache;
  5451. /***/ }),
  5452. /***/ "ol/style/Icon.js":
  5453. /*!********************************!*\
  5454. !*** external "ol.style.Icon" ***!
  5455. \********************************/
  5456. /***/ ((module) => {
  5457. module.exports = ol.style.Icon;
  5458. /***/ }),
  5459. /***/ "ol/style/Stroke.js":
  5460. /*!**********************************!*\
  5461. !*** external "ol.style.Stroke" ***!
  5462. \**********************************/
  5463. /***/ ((module) => {
  5464. module.exports = ol.style.Stroke;
  5465. /***/ }),
  5466. /***/ "ol/style/Style.js":
  5467. /*!*********************************!*\
  5468. !*** external "ol.style.Style" ***!
  5469. \*********************************/
  5470. /***/ ((module) => {
  5471. module.exports = ol.style.Style;
  5472. /***/ }),
  5473. /***/ "ol/tilegrid.js":
  5474. /*!******************************!*\
  5475. !*** external "ol.tilegrid" ***!
  5476. \******************************/
  5477. /***/ ((module) => {
  5478. module.exports = ol.tilegrid;
  5479. /***/ }),
  5480. /***/ "ol/tileurlfunction.js":
  5481. /*!*************************************!*\
  5482. !*** external "ol.tileurlfunction" ***!
  5483. \*************************************/
  5484. /***/ ((module) => {
  5485. module.exports = ol.tileurlfunction;
  5486. /***/ }),
  5487. /***/ "ol/util.js":
  5488. /*!**************************!*\
  5489. !*** external "ol.util" ***!
  5490. \**************************/
  5491. /***/ ((module) => {
  5492. module.exports = ol.util;
  5493. /***/ })
  5494. /******/ });
  5495. /************************************************************************/
  5496. /******/ // The module cache
  5497. /******/ var __webpack_module_cache__ = {};
  5498. /******/
  5499. /******/ // The require function
  5500. /******/ function __webpack_require__(moduleId) {
  5501. /******/ // Check if module is in cache
  5502. /******/ var cachedModule = __webpack_module_cache__[moduleId];
  5503. /******/ if (cachedModule !== undefined) {
  5504. /******/ return cachedModule.exports;
  5505. /******/ }
  5506. /******/ // Create a new module (and put it into the cache)
  5507. /******/ var module = __webpack_module_cache__[moduleId] = {
  5508. /******/ // no module.id needed
  5509. /******/ // no module.loaded needed
  5510. /******/ exports: {}
  5511. /******/ };
  5512. /******/
  5513. /******/ // Execute the module function
  5514. /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  5515. /******/
  5516. /******/ // Return the exports of the module
  5517. /******/ return module.exports;
  5518. /******/ }
  5519. /******/
  5520. /************************************************************************/
  5521. /******/ /* webpack/runtime/compat get default export */
  5522. /******/ (() => {
  5523. /******/ // getDefaultExport function for compatibility with non-harmony modules
  5524. /******/ __webpack_require__.n = (module) => {
  5525. /******/ var getter = module && module.__esModule ?
  5526. /******/ () => (module['default']) :
  5527. /******/ () => (module);
  5528. /******/ __webpack_require__.d(getter, { a: getter });
  5529. /******/ return getter;
  5530. /******/ };
  5531. /******/ })();
  5532. /******/
  5533. /******/ /* webpack/runtime/define property getters */
  5534. /******/ (() => {
  5535. /******/ // define getter functions for harmony exports
  5536. /******/ __webpack_require__.d = (exports, definition) => {
  5537. /******/ for(var key in definition) {
  5538. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  5539. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  5540. /******/ }
  5541. /******/ }
  5542. /******/ };
  5543. /******/ })();
  5544. /******/
  5545. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  5546. /******/ (() => {
  5547. /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  5548. /******/ })();
  5549. /******/
  5550. /******/ /* webpack/runtime/make namespace object */
  5551. /******/ (() => {
  5552. /******/ // define __esModule on exports
  5553. /******/ __webpack_require__.r = (exports) => {
  5554. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  5555. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  5556. /******/ }
  5557. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  5558. /******/ };
  5559. /******/ })();
  5560. /******/
  5561. /************************************************************************/
  5562. var __webpack_exports__ = {};
  5563. // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
  5564. (() => {
  5565. /*!******************************!*\
  5566. !*** ./src/index.library.js ***!
  5567. \******************************/
  5568. __webpack_require__.r(__webpack_exports__);
  5569. /* harmony export */ __webpack_require__.d(__webpack_exports__, {
  5570. /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
  5571. /* harmony export */ });
  5572. /* harmony import */ var _olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./olcs/OLCesium.js */ "./src/olcs/OLCesium.js");
  5573. /* harmony import */ var _olcs_AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./olcs/AbstractSynchronizer.js */ "./src/olcs/AbstractSynchronizer.js");
  5574. /* harmony import */ var _olcs_RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./olcs/RasterSynchronizer.js */ "./src/olcs/RasterSynchronizer.js");
  5575. /* harmony import */ var _olcs_VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./olcs/VectorSynchronizer.js */ "./src/olcs/VectorSynchronizer.js");
  5576. /* harmony import */ var _olcs_core_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./olcs/core.js */ "./src/olcs/core.js");
  5577. /* harmony import */ var _olcs_core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./olcs/core/OLImageryProvider.js */ "./src/olcs/core/OLImageryProvider.js");
  5578. /* harmony import */ var _olcs_core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./olcs/core/VectorLayerCounterpart.js */ "./src/olcs/core/VectorLayerCounterpart.js");
  5579. /* harmony import */ var _olcs_contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./olcs/contrib/LazyLoader.js */ "./src/olcs/contrib/LazyLoader.js");
  5580. /* harmony import */ var _olcs_contrib_Manager_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./olcs/contrib/Manager.js */ "./src/olcs/contrib/Manager.js");
  5581. /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__["default"]);
  5582. // Using var for phantomJS
  5583. // eslint-disable-next-line no-var
  5584. var olcs = window['olcs'] = {};
  5585. olcs.OLCesium = _olcs_OLCesium_js__WEBPACK_IMPORTED_MODULE_0__["default"];
  5586. olcs.AbstractSynchronizer = _olcs_AbstractSynchronizer_js__WEBPACK_IMPORTED_MODULE_1__["default"];
  5587. olcs.RasterSynchronizer = _olcs_RasterSynchronizer_js__WEBPACK_IMPORTED_MODULE_2__["default"];
  5588. olcs.VectorSynchronizer = _olcs_VectorSynchronizer_js__WEBPACK_IMPORTED_MODULE_3__["default"];
  5589. olcs.core = _olcs_core_js__WEBPACK_IMPORTED_MODULE_4__["default"];
  5590. olcs.core.OLImageryProvider = _olcs_core_OLImageryProvider_js__WEBPACK_IMPORTED_MODULE_5__["default"];
  5591. olcs.core.VectorLayerCounterpart = _olcs_core_VectorLayerCounterpart_js__WEBPACK_IMPORTED_MODULE_6__["default"];
  5592. olcs.contrib = {};
  5593. olcs.contrib.LazyLoader = _olcs_contrib_LazyLoader_js__WEBPACK_IMPORTED_MODULE_7__["default"];
  5594. olcs.contrib.Manager = _olcs_contrib_Manager_js__WEBPACK_IMPORTED_MODULE_8__["default"];
  5595. })();
  5596. olcs_unused_var = __webpack_exports__;
  5597. /******/ })()
  5598. ;
  5599. //# sourceMappingURL=olcesium-debug.js.map