cesium
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
191 lines (164 loc) • 6.99 kB
JavaScript
import Cartesian3 from '../Core/Cartesian3.js';
import Cartographic from '../Core/Cartographic.js';
import Check from '../Core/Check.js';
import defined from '../Core/defined.js';
import destroyObject from '../Core/destroyObject.js';
import Event from '../Core/Event.js';
import Iso8601 from '../Core/Iso8601.js';
import CesiumMath from '../Core/Math.js';
import HeightReference from '../Scene/HeightReference.js';
import SceneMode from '../Scene/SceneMode.js';
import Property from './Property.js';
var scratchPosition = new Cartesian3();
var scratchCarto = new Cartographic();
/**
* @private
*/
function TerrainOffsetProperty(scene, positionProperty, heightReferenceProperty, extrudedHeightReferenceProperty) {
//>>includeStart('debug', pragmas.debug);
Check.defined('scene', scene);
Check.defined('positionProperty', positionProperty);
//>>includeEnd('debug');
this._scene = scene;
this._heightReference = heightReferenceProperty;
this._extrudedHeightReference = extrudedHeightReferenceProperty;
this._positionProperty = positionProperty;
this._position = new Cartesian3();
this._cartographicPosition = new Cartographic();
this._normal = new Cartesian3();
this._definitionChanged = new Event();
this._terrainHeight = 0;
this._removeCallbackFunc = undefined;
this._removeEventListener = undefined;
this._removeModeListener = undefined;
var that = this;
if (defined(scene.globe)) {
this._removeEventListener = scene.terrainProviderChanged.addEventListener(function() {
that._updateClamping();
});
this._removeModeListener = scene.morphComplete.addEventListener(function() {
that._updateClamping();
});
}
if (positionProperty.isConstant) {
var position = positionProperty.getValue(Iso8601.MINIMUM_VALUE, scratchPosition);
if (!defined(position) || Cartesian3.equals(position, Cartesian3.ZERO) || !defined(scene.globe)) {
return;
}
this._position = Cartesian3.clone(position, this._position);
this._updateClamping();
this._normal = scene.globe.ellipsoid.geodeticSurfaceNormal(position, this._normal);
}
}
Object.defineProperties(TerrainOffsetProperty.prototype, {
/**
* Gets a value indicating if this property is constant.
* @memberof TerrainOffsetProperty.prototype
*
* @type {Boolean}
* @readonly
*/
isConstant : {
get : function() {
return false;
}
},
/**
* Gets the event that is raised whenever the definition of this property changes.
* @memberof TerrainOffsetProperty.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged : {
get : function() {
return this._definitionChanged;
}
}
});
/**
* @private
*/
TerrainOffsetProperty.prototype._updateClamping = function() {
if (defined(this._removeCallbackFunc)) {
this._removeCallbackFunc();
}
var scene = this._scene;
var globe = scene.globe;
var position = this._position;
if (!defined(globe) || Cartesian3.equals(position, Cartesian3.ZERO)) {
this._terrainHeight = 0;
return;
}
var ellipsoid = globe.ellipsoid;
var surface = globe._surface;
var that = this;
var cartographicPosition = ellipsoid.cartesianToCartographic(position, this._cartographicPosition);
var height = globe.getHeight(cartographicPosition);
if (defined(height)) {
this._terrainHeight = height;
} else {
this._terrainHeight = 0;
}
function updateFunction(clampedPosition) {
if (scene.mode === SceneMode.SCENE3D) {
var carto = ellipsoid.cartesianToCartographic(clampedPosition, scratchCarto);
that._terrainHeight = carto.height;
} else {
that._terrainHeight = clampedPosition.x;
}
that.definitionChanged.raiseEvent();
}
this._removeCallbackFunc = surface.updateHeight(cartographicPosition, updateFunction);
};
/**
* Gets the height relative to the terrain based on the positions.
*
* @returns {Cartesian3} The offset
*/
TerrainOffsetProperty.prototype.getValue = function(time, result) {
var heightReference = Property.getValueOrDefault(this._heightReference, time, HeightReference.NONE);
var extrudedHeightReference = Property.getValueOrDefault(this._extrudedHeightReference, time, HeightReference.NONE);
if (heightReference === HeightReference.NONE && extrudedHeightReference !== HeightReference.RELATIVE_TO_GROUND) {
this._position = Cartesian3.clone(Cartesian3.ZERO, this._position);
return Cartesian3.clone(Cartesian3.ZERO, result);
}
if (this._positionProperty.isConstant) {
return Cartesian3.multiplyByScalar(this._normal, this._terrainHeight, result);
}
var scene = this._scene;
var position = this._positionProperty.getValue(time, scratchPosition);
if (!defined(position) || Cartesian3.equals(position, Cartesian3.ZERO) || !defined(scene.globe)) {
return Cartesian3.clone(Cartesian3.ZERO, result);
}
if (Cartesian3.equalsEpsilon(this._position, position, CesiumMath.EPSILON10)) {
return Cartesian3.multiplyByScalar(this._normal, this._terrainHeight, result);
}
this._position = Cartesian3.clone(position, this._position);
this._updateClamping();
var normal = scene.globe.ellipsoid.geodeticSurfaceNormal(position, this._normal);
return Cartesian3.multiplyByScalar(normal, this._terrainHeight, result);
};
TerrainOffsetProperty.prototype.isDestroyed = function() {
return false;
};
TerrainOffsetProperty.prototype.destroy = function() {
if (defined(this._removeEventListener)) {
this._removeEventListener();
}
if (defined(this._removeModeListener)) {
this._removeModeListener();
}
if (defined(this._removeCallbackFunc)) {
this._removeCallbackFunc();
}
return destroyObject(this);
};
/**
* A function which creates one or more providers.
* @callback TerrainOffsetProperty~PositionFunction
* @param {JulianDate} time The clock time at which to retrieve the position
* @param {Cartesian3} result The result position
* @returns {Cartesian3} The position at which to do the terrain height check
*/
export default TerrainOffsetProperty;