UNPKG

olcs

Version:

OpenLayers Cesium integration and plugin library

236 lines 17.2 kB
import Observable from 'ol/Observable.js'; import OLCesium from '../OLCesium.js'; import { computeSignedTiltAngleOnGlobe, limitCameraToBoundingSphere, pickBottomPoint, resetToNorthZenith, rotateAroundBottomCenter, setHeadingUsingBottomCenter, } from '../core'; import { toRadians } from '../math.js'; import olcsContribLazyLoader from './LazyLoader.js'; /** * @typedef {Object} ManagerOptions * @property {import('ol/Map.js').default} map * @property {import('ol/extent.js').Extent} [cameraExtentInRadians] * @property {string} [cesiumIonDefaultAccessToken] */ export default class Manager extends Observable { cesiumUrl_; boundingSphere_; promise_; cesiumIonDefaultAccessToken_; map; cameraExtentInRadians; ol3d; cesiumInitialTilt_ = toRadians(50); fogDensity = 0.0001; fogSSEFactor = 25; minimumZoomDistance = 2; /** * Limit the maximum distance to the earth to 10'000km. */ maximumZoomDistance = 10000000; // when closer to 3000m, restrict the available positions harder limitCameraToBoundingSphereRatio = (height) => height > 3000 ? 9 : 3; /** * @param {string} cesiumUrl * @param {olcsx.contrib.ManagerOptions} options * @api */ constructor(cesiumUrl, { map, cameraExtentInRadians, cesiumIonDefaultAccessToken, }) { super(); this.cesiumUrl_ = cesiumUrl; console.assert(!!map); this.map = map; this.cameraExtentInRadians = cameraExtentInRadians || null; this.cesiumIonDefaultAccessToken_ = cesiumIonDefaultAccessToken; } /** * Lazy load Cesium. */ load() { if (!this.promise_) { const cesiumLazyLoader = new olcsContribLazyLoader(this.cesiumUrl_); this.promise_ = cesiumLazyLoader.load().then(() => this.onCesiumLoaded()); } return this.promise_; } /** * Hook called when Cesium has been lazy loaded. */ onCesiumLoaded() { if (this.cameraExtentInRadians) { const rect = new Cesium.Rectangle(...this.cameraExtentInRadians); // Set the fly home rectangle Cesium.Camera.DEFAULT_VIEW_RECTANGLE = rect; this.boundingSphere_ = Cesium.BoundingSphere.fromRectangle3D(rect, Cesium.Ellipsoid.WGS84, 300); // lux mean height is 300m } if (this.cesiumIonDefaultAccessToken_) { Cesium.Ion.defaultAccessToken = this.cesiumIonDefaultAccessToken_; } this.ol3d = this.instantiateOLCesium(); const scene = this.ol3d.getCesiumScene(); this.configureForUsability(scene); this.configureForPerformance(scene); this.dispatchEvent('load'); return this.ol3d; } /** * Application code should override this method. */ instantiateOLCesium() { const ol3d = new OLCesium({ map: this.map }); const scene = ol3d.getCesiumScene(); Cesium.createWorldTerrainAsync().then((tp) => (scene.terrainProvider = tp)); return ol3d; } /** * Override with custom performance optimization logics, if needed. * @param scene */ configureForPerformance(scene) { const fog = scene.fog; fog.enabled = true; fog.density = this.fogDensity; fog.screenSpaceErrorFactor = this.fogSSEFactor; } /** * Override with custom usabliity logics, id needed. * @param scene */ configureForUsability(scene) { const sscController = scene.screenSpaceCameraController; sscController.minimumZoomDistance = this.minimumZoomDistance; sscController.maximumZoomDistance = this.maximumZoomDistance; // Do not see through the terrain. Seeing through the terrain does not make // sense anyway, except for debugging scene.globe.depthTestAgainstTerrain = true; // Use white instead of the black default colour for the globe when tiles are missing scene.globe.baseColor = Cesium.Color.WHITE; scene.backgroundColor = Cesium.Color.WHITE; if (this.boundingSphere_) { scene.postRender.addEventListener(this.limitCameraToBoundingSphere.bind(this)); } // Stop rendering Cesium when there is nothing to do. This drastically reduces CPU/GPU consumption. this.ol3d.enableAutoRenderLoop(); } /** * Constrain the camera so that it stays close to the bounding sphere of the map extent. * Near the ground the allowed distance is shorter. */ limitCameraToBoundingSphere() { const scene = this.ol3d.getCesiumScene(); limitCameraToBoundingSphere(scene.camera, this.boundingSphere_, this.limitCameraToBoundingSphereRatio); } /** * Enable or disable ol3d with a default animation. */ toggle3d() { return this.load().then((/** @const {!olcs.OLCesium} */ ol3d) => { const is3DCurrentlyEnabled = ol3d.getEnabled(); const scene = ol3d.getCesiumScene(); if (is3DCurrentlyEnabled) { // Disable 3D console.assert(!!this.map); return resetToNorthZenith(this.map, scene).then(() => { ol3d.setEnabled(false); this.dispatchEvent('toggle'); }); } // Enable 3D ol3d.setEnabled(true); this.dispatchEvent('toggle'); return rotateAroundBottomCenter(scene, this.cesiumInitialTilt_); }); } /** * Enable ol3d with a view built from parameters. * @param lon * @param lat * @param elevation * @param headingDeg * @param pitchDeg */ set3dWithView(lon, lat, elevation, headingDeg, pitchDeg) { return this.load().then((ol3d) => { const is3DCurrentlyEnabled = ol3d.getEnabled(); const scene = ol3d.getCesiumScene(); const camera = scene.camera; const destination = Cesium.Cartesian3.fromDegrees(lon, lat, elevation); const heading = Cesium.Math.toRadians(headingDeg); const pitch = Cesium.Math.toRadians(pitchDeg); const roll = 0; const orientation = { heading, pitch, roll }; if (!is3DCurrentlyEnabled) { ol3d.setEnabled(true); this.dispatchEvent('toggle'); } camera.setView({ destination, orientation, }); }); } /** * Whether OL-Cesium has been loaded and 3D mode is enabled. */ is3dEnabled() { return !!this.ol3d && this.ol3d.getEnabled(); } /** * @return {number} */ getHeading() { return this.map ? this.map.getView().getRotation() || 0 : 0; } /** * @return {number|undefined} */ getTiltOnGlobe() { const scene = this.ol3d.getCesiumScene(); const tiltOnGlobe = computeSignedTiltAngleOnGlobe(scene); return -tiltOnGlobe; } /** * Set heading. * This assumes ol3d has been loaded. * @param angle */ setHeading(angle) { const scene = this.ol3d.getCesiumScene(); const bottom = pickBottomPoint(scene); if (bottom) { setHeadingUsingBottomCenter(scene, angle, bottom); } } getOl3d() { return this.ol3d; } getCesiumViewMatrix() { return this.ol3d.getCesiumScene().camera.viewMatrix; } getCesiumScene() { return this.ol3d.getCesiumScene(); } /** * Fly to some rectangle. * This assumes ol3d has been loaded. * @param rectangle * @param offset */ flyToRectangle(rectangle, offset = 0) { const camera = this.getCesiumScene().camera; const destination = camera.getRectangleCameraCoordinates(rectangle); const mag = Cesium.Cartesian3.magnitude(destination) + offset; Cesium.Cartesian3.normalize(destination, destination); Cesium.Cartesian3.multiplyByScalar(destination, mag, destination); return new Promise((resolve, reject) => { if (!this.cameraExtentInRadians) { reject(); return; } camera.flyTo({ destination, complete: () => resolve(), cancel: () => reject(), endTransform: Cesium.Matrix4.IDENTITY, }); }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWFuYWdlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9vbGNzL2NvbnRyaWIvTWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLFVBQVUsTUFBTSxrQkFBa0IsQ0FBQztBQUUxQyxPQUFPLFFBQVEsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0QyxPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLDJCQUEyQixFQUMzQixlQUFlLEVBQ2Ysa0JBQWtCLEVBQ2xCLHdCQUF3QixFQUN4QiwyQkFBMkIsR0FDNUIsTUFBTSxTQUFTLENBQUM7QUFDakIsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLFlBQVksQ0FBQztBQUNyQyxPQUFPLHFCQUFxQixNQUFNLGlCQUFpQixDQUFDO0FBRXBEOzs7OztHQUtHO0FBRUgsTUFBTSxDQUFDLE9BQU8sT0FBTyxPQUFRLFNBQVEsVUFBVTtJQUNyQyxVQUFVLENBQVM7SUFDbkIsZUFBZSxDQUFpQjtJQUNoQyxRQUFRLENBQW9CO0lBQzVCLDRCQUE0QixDQUFTO0lBQ25DLEdBQUcsQ0FBUTtJQUNYLHFCQUFxQixDQUFTO0lBQzlCLElBQUksQ0FBVztJQUNqQixrQkFBa0IsR0FBRyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFFakMsVUFBVSxHQUFHLE1BQU0sQ0FBQztJQUVwQixZQUFZLEdBQUcsRUFBRSxDQUFDO0lBRWxCLG1CQUFtQixHQUFHLENBQUMsQ0FBQztJQUVsQzs7T0FFRztJQUNPLG1CQUFtQixHQUFXLFFBQVEsQ0FBQztJQUVqRCxnRUFBZ0U7SUFDdEQsZ0NBQWdDLEdBQUcsQ0FBQyxNQUFjLEVBQUUsRUFBRSxDQUM5RCxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV4Qjs7OztPQUlHO0lBQ0gsWUFDRSxTQUFpQixFQUNqQixFQUNFLEdBQUcsRUFDSCxxQkFBcUIsRUFDckIsMkJBQTJCLEdBSzVCO1FB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