UNPKG

olcs

Version:

OpenLayers Cesium integration and plugin library

346 lines 24.5 kB
import { unByKey as olObservableUnByKey } from 'ol/Observable.js'; import { toRadians, toDegrees } from './math.js'; import { getTransform } from 'ol/proj.js'; import { pickCenterPoint, calcDistanceForResolution, calcResolutionForDistance } from './core.js'; /** * @param input Input coordinate array. * @param opt_output Output array of coordinate values. * @param opt_dimension Dimension. * @return Input coordinate array (same array as input). */ export function identityProjection(input, opt_output, opt_dimension) { const dim = opt_dimension || input.length; if (opt_output) { for (let i = 0; i < dim; ++i) { opt_output[i] = input[i]; } } return input; } export default class Camera { scene_; cam_; map_; view_; viewListenKey_ = null; toLonLat_ = identityProjection; fromLonLat_ = identityProjection; /** * 0 -- topdown, PI/2 -- the horizon */ tilt_ = 0; distance_ = 0; lastCameraViewMatrix_ = null; /** * This is used to discard change events on view caused by updateView method. */ viewUpdateInProgress_ = false; /** * This object takes care of additional 3d-specific properties of the view and * ensures proper synchronization with the underlying raw Cesium.Camera object. */ constructor(scene, map) { this.scene_ = scene; this.cam_ = scene.camera; this.map_ = map; this.map_.on('change:view', (e) => { this.setView_(this.map_.getView()); }); this.setView_(this.map_.getView()); } destroy() { olObservableUnByKey(this.viewListenKey_); this.viewListenKey_ = null; } /** * @param {?ol.View} view New view to use. */ setView_(view) { olObservableUnByKey(this.viewListenKey_); this.viewListenKey_ = null; this.view_ = view; if (view) { const toLonLat = getTransform(view.getProjection(), 'EPSG:4326'); const fromLonLat = getTransform('EPSG:4326', view.getProjection()); console.assert(!!(toLonLat && fromLonLat)); this.toLonLat_ = toLonLat; this.fromLonLat_ = fromLonLat; this.viewListenKey_ = view.on('propertychange', e => this.handleViewChangedEvent_()); this.readFromView(); } else { this.toLonLat_ = identityProjection; this.fromLonLat_ = identityProjection; } } handleViewChangedEvent_() { if (!this.viewUpdateInProgress_) { this.readFromView(); } } /** * @deprecated * @param heading In radians. */ setHeading(heading) { if (!this.view_) { return; } this.view_.setRotation(heading); } /** * @deprecated * @return Heading in radians. */ getHeading() { if (!this.view_) { return undefined; } const rotation = this.view_.getRotation(); return rotation || 0; } /** * @param tilt In radians. */ setTilt(tilt) { this.tilt_ = tilt; this.updateCamera_(); } /** * @return Tilt in radians. */ getTilt() { return this.tilt_; } /** * @param distance In meters. */ setDistance(distance) { this.distance_ = distance; this.updateCamera_(); this.updateView(); } /** * @return Distance in meters. */ getDistance() { return this.distance_; } /** * @deprecated * Shortcut for ol.View.setCenter(). * @param center Same projection as the ol.View. */ setCenter(center) { if (!this.view_) { return; } this.view_.setCenter(center); } /** * @deprecated * Shortcut for ol.View.getCenter(). * @return {ol.Coordinate|undefined} Same projection as the ol.View. * @api */ getCenter() { if (!this.view_) { return undefined; } return this.view_.getCenter(); } /** * Sets the position of the camera. * @param position Same projection as the ol.View. */ setPosition(position) { if (!this.toLonLat_) { return; } const ll = this.toLonLat_(position); console.assert(!!ll); const carto = new Cesium.Cartographic(toRadians(ll[0]), toRadians(ll[1]), this.getAltitude()); this.cam_.setView({ destination: Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto) }); this.updateView(); } /** * Calculates position under the camera. * @return Coordinates in same projection as the ol.View. * @api */ getPosition() { if (!this.fromLonLat_) { return undefined; } const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.cam_.position); const pos = this.fromLonLat_([ toDegrees(carto.longitude), toDegrees(carto.latitude) ]); console.assert(!!pos); return pos; } /** * @param altitude In meters. */ setAltitude(altitude) { const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.cam_.position); carto.height = altitude; this.cam_.position = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); this.updateView(); } /** * @return Altitude in meters. */ getAltitude() { const carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.cam_.position); return carto.height; } /** * Updates the state of the underlying Cesium.Camera * according to the current values of the properties. */ updateCamera_() { if (!this.view_ || !this.toLonLat_) { return; } const center = this.view_.getCenter(); if (!center) { return; } const ll = this.toLonLat_(center); console.assert(!!ll); const carto = new Cesium.Cartographic(toRadians(ll[0]), toRadians(ll[1])); if (this.scene_.globe) { const height = this.scene_.globe.getHeight(carto); carto.height = height || 0; } const destination = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); const orientation = { pitch: this.tilt_ - Cesium.Math.PI_OVER_TWO, heading: -this.view_.getRotation(), roll: undefined }; this.cam_.setView({ destination, orientation }); this.cam_.moveBackward(this.distance_); this.checkCameraChange(true); } /** * Calculates the values of the properties from the current ol.View state. */ readFromView() { if (!this.view_ || !this.toLonLat_) { return; } const center = this.view_.getCenter(); if (center === undefined || center === null) { return; } const ll = this.toLonLat_(center); console.assert(!!ll); const resolution = this.view_.getResolution(); this.distance_ = this.calcDistanceForResolution(resolution || 0, toRadians(ll[1])); this.updateCamera_(); } /** * Calculates the values of the properties from the current Cesium.Camera state. * Modifies the center, resolution and rotation properties of the view. */ updateView() { if (!this.view_ || !this.fromLonLat_) { return; } this.viewUpdateInProgress_ = true; // target & distance const ellipsoid = Cesium.Ellipsoid.WGS84; const scene = this.scene_; const target = pickCenterPoint(scene); let bestTarget = target; if (!bestTarget) { //TODO: how to handle this properly ? const globe = scene.globe; const carto = this.cam_.positionCartographic.clone(); const height = globe.getHeight(carto); carto.height = height || 0; bestTarget = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); } this.distance_ = Cesium.Cartesian3.distance(bestTarget, this.cam_.position); const bestTargetCartographic = ellipsoid.cartesianToCartographic(bestTarget); this.view_.setCenter(this.fromLonLat_([ toDegrees(bestTargetCartographic.longitude), toDegrees(bestTargetCartographic.latitude) ])); // resolution this.view_.setResolution(this.calcResolutionForDistance(this.distance_, bestTargetCartographic ? bestTargetCartographic.latitude : 0)); /* * Since we are positioning the target, the values of heading and tilt * need to be calculated _at the target_. */ if (target) { const pos = this.cam_.position; // normal to the ellipsoid at the target const targetNormal = new Cesium.Cartesian3(); ellipsoid.geocentricSurfaceNormal(target, targetNormal); // vector from the target to the camera const targetToCamera = new Cesium.Cartesian3(); Cesium.Cartesian3.subtract(pos, target, targetToCamera); Cesium.Cartesian3.normalize(targetToCamera, targetToCamera); // HEADING const up = this.cam_.up; const right = this.cam_.right; const normal = new Cesium.Cartesian3(-target.y, target.x, 0); // what is it? const heading = Cesium.Cartesian3.angleBetween(right, normal); const cross = Cesium.Cartesian3.cross(target, up, new Cesium.Cartesian3()); const orientation = cross.z; this.view_.setRotation((orientation < 0 ? heading : -heading)); // TILT const tiltAngle = Math.acos(Cesium.Cartesian3.dot(targetNormal, targetToCamera)); this.tilt_ = isNaN(tiltAngle) ? 0 : tiltAngle; } else { // fallback when there is no target this.view_.setRotation(this.cam_.heading); this.tilt_ = -this.cam_.pitch + Math.PI / 2; } // delay resetting the guard flag to account for asynchronous event generation in ol maps setTimeout(() => this.viewUpdateInProgress_ = false, 1000); } /** * Check if the underlying camera state has changed and ensure synchronization. * @param opt_dontSync Do not synchronize the view. */ checkCameraChange(opt_dontSync) { const old = this.lastCameraViewMatrix_; const current = this.cam_.viewMatrix; if (!old || !Cesium.Matrix4.equalsEpsilon(old, current, 1e-7)) { this.lastCameraViewMatrix_ = current.clone(); if (opt_dontSync !== true) { this.updateView(); } } } /** * calculate the distance between camera and centerpoint based on the resolution and latitude value * @param resolution Number of map units per pixel. * @param latitude Latitude in radians. * @return The calculated distance. */ calcDistanceForResolution(resolution, latitude) { return calcDistanceForResolution(resolution, latitude, this.scene_, this.view_.getProjection()); } /** * calculate the resolution based on a distance(camera to position) and latitude value * @param distance * @param latitude * @return} The calculated resolution. */ calcResolutionForDistance(distance, latitude) { return calcResolutionForDistance(distance, latitude, this.scene_, this.view_.getProjection()); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FtZXJhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL29sY3MvQ2FtZXJhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxPQUFPLElBQUksbUJBQW1CLEVBQUMsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRSxPQUFPLEVBQUMsU0FBUyxFQUFFLFNBQVMsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUMvQyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ3hDLE9BQU8sRUFBQyxlQUFlLEVBQUUseUJBQXlCLEVBQUUseUJBQXlCLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFLaEc7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsS0FBZSxFQUFFLFVBQXFCLEVBQUUsYUFBc0I7SUFDL0YsTUFBTSxHQUFHLEdBQUcsYUFBYSxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDMUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNmLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUM3QixVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNCLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDO0FBRUQsTUFBTSxDQUFDLE9BQU8sT0FBTyxNQUFNO0lBQ2pCLE1BQU0sQ0FBUTtJQUNkLElBQUksQ0FBZTtJQUNuQixJQUFJLENBQU07SUFDVixLQUFLLENBQU87SUFFWixjQUFjLEdBQWMsSUFBSSxDQUFDO0lBRWpDLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQztJQUMvQixXQUFXLEdBQUcsa0JBQWtCLENBQUM7SUFFekM7O09BRUc7SUFDSyxLQUFLLEdBQVcsQ0FBQyxDQUFDO0lBQ2xCLFNBQVMsR0FBRyxDQUFDLENBQUM7SUFDZCxxQkFBcUIs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