lg_frontend/static/libs/mars3d/thirdParty/sensorVolumes/cesium-sensor-volumes.js

2988 lines
105 KiB
JavaScript
Raw Permalink Normal View History

/**
* Cesium Sensor Volumes - https://github.com/jlouns/cesium-sensor-volumes
*
* Copyright 2016 Jonathan Lounsbury
* Copyright 2011-2014 Analytical Graphics Inc. and Cesium Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Portions licensed separately.
* See https://github.com/jlouns/cesium-sensor-volumes/blob/master/LICENSE.md for full licensing details.
*
* Derived from Cesium Sensors - https://github.com/AnalyticalGraphicsInc/cesium-sensors
*/
;(function () {
/**
* @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
* Released under MIT license, http://github.com/requirejs/almond/LICENSE
*/
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*global setTimeout: false */
var requirejs, require, define
;(function (undef) {
var main,
req,
makeMap,
handlers,
defined = {},
waiting = {},
config = {},
defining = {},
hasOwn = Object.prototype.hasOwnProperty,
aps = [].slice,
jsSuffixRegExp = /\.js$/
function hasProp(obj, prop) {
return hasOwn.call(obj, prop)
}
/**
* Given a relative module name, like ./something, normalize it to
* a real name that can be mapped to a path.
* @param {String} name the relative name
* @param {String} baseName a real name that the name arg is relative
* to.
* @returns {String} normalized name
*/
function normalize(name, baseName) {
var nameParts,
nameSegment,
mapValue,
foundMap,
lastIndex,
foundI,
foundStarMap,
starI,
i,
j,
part,
normalizedBaseParts,
baseParts = baseName && baseName.split("/"),
map = config.map,
starMap = (map && map["*"]) || {}
//Adjust any relative paths.
if (name) {
name = name.split("/")
lastIndex = name.length - 1
// If wanting node ID compatibility, strip .js from end
// of IDs. Have to do this here, and not in nameToUrl
// because node allows either .js or non .js to map
// to same file.
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, "")
}
// Starts with a '.' so need the baseName
if (name[0].charAt(0) === "." && baseParts) {
//Convert baseName to array, and lop off the last part,
//so that . matches that 'directory' and not name of the baseName's
//module. For instance, baseName of 'one/two/three', maps to
//'one/two/three.js', but we want the directory, 'one/two' for
//this normalization.
normalizedBaseParts = baseParts.slice(0, baseParts.length - 1)
name = normalizedBaseParts.concat(name)
}
//start trimDots
for (i = 0; i < name.length; i++) {
part = name[i]
if (part === ".") {
name.splice(i, 1)
i -= 1
} else if (part === "..") {
// If at the start, or previous value is still ..,
// keep them so that when converted to a path it may
// still work when converted to a path, even though
// as an ID it is less than ideal. In larger point
// releases, may be better to just kick out an error.
if (i === 0 || (i === 1 && name[2] === "..") || name[i - 1] === "..") {
continue
} else if (i > 0) {
name.splice(i - 1, 2)
i -= 2
}
}
}
//end trimDots
name = name.join("/")
}
//Apply map config if available.
if ((baseParts || starMap) && map) {
nameParts = name.split("/")
for (i = nameParts.length; i > 0; i -= 1) {
nameSegment = nameParts.slice(0, i).join("/")
if (baseParts) {
//Find the longest baseName segment match in the config.
//So, do joins on the biggest to smallest lengths of baseParts.
for (j = baseParts.length; j > 0; j -= 1) {
mapValue = map[baseParts.slice(0, j).join("/")]
//baseName segment has config, find if it has one for
//this name.
if (mapValue) {
mapValue = mapValue[nameSegment]
if (mapValue) {
//Match, update name to the new value.
foundMap = mapValue
foundI = i
break
}
}
}
}
if (foundMap) {
break
}
//Check for a star map match, but just hold on to it,
//if there is a shorter segment match later in a matching
//config, then favor over this star map.
if (!foundStarMap && starMap && starMap[nameSegment]) {
foundStarMap = starMap[nameSegment]
starI = i
}
}
if (!foundMap && foundStarMap) {
foundMap = foundStarMap
foundI = starI
}
if (foundMap) {
nameParts.splice(0, foundI, foundMap)
name = nameParts.join("/")
}
}
return name
}
function makeRequire(relName, forceSync) {
return function () {
//A version of a require function that passes a moduleName
//value for items that may need to
//look up paths relative to the moduleName
var args = aps.call(arguments, 0)
//If first arg is not require('string'), and there is only
//one arg, it is the array form without a callback. Insert
//a null so that the following concat is correct.
if (typeof args[0] !== "string" && args.length === 1) {
args.push(null)
}
return req.apply(undef, args.concat([relName, forceSync]))
}
}
function makeNormalize(relName) {
return function (name) {
return normalize(name, relName)
}
}
function makeLoad(depName) {
return function (value) {
defined[depName] = value
}
}
function callDep(name) {
if (hasProp(waiting, name)) {
var args = waiting[name]
delete waiting[name]
defining[name] = true
main.apply(undef, args)
}
if (!hasProp(defined, name) && !hasProp(defining, name)) {
throw new Error("No " + name)
}
return defined[name]
}
//Turns a plugin!resource to [plugin, resource]
//with the plugin being undefined if the name
//did not have a plugin prefix.
function splitPrefix(name) {
var prefix,
index = name ? name.indexOf("!") : -1
if (index > -1) {
prefix = name.substring(0, index)
name = name.substring(index + 1, name.length)
}
return [prefix, name]
}
//Creates a parts array for a relName where first part is plugin ID,
//second part is resource ID. Assumes relName has already been normalized.
function makeRelParts(relName) {
return relName ? splitPrefix(relName) : []
}
/**
* Makes a name map, normalizing the name, and using a plugin
* for normalization if necessary. Grabs a ref to plugin
* too, as an optimization.
*/
makeMap = function (name, relParts) {
var plugin,
parts = splitPrefix(name),
prefix = parts[0],
relResourceName = relParts[1]
name = parts[1]
if (prefix) {
prefix = normalize(prefix, relResourceName)
plugin = callDep(prefix)
}
//Normalize according
if (prefix) {
if (plugin && plugin.normalize) {
name = plugin.normalize(name, makeNormalize(relResourceName))
} else {
name = normalize(name, relResourceName)
}
} else {
name = normalize(name, relResourceName)
parts = splitPrefix(name)
prefix = parts[0]
name = parts[1]
if (prefix) {
plugin = callDep(prefix)
}
}
//Using ridiculous property names for space reasons
return {
f: prefix ? prefix + "!" + name : name, //fullName
n: name,
pr: prefix,
p: plugin
}
}
function makeConfig(name) {
return function () {
return (config && config.config && config.config[name]) || {}
}
}
handlers = {
require: function (name) {
return makeRequire(name)
},
exports: function (name) {
var e = defined[name]
if (typeof e !== "undefined") {
return e
} else {
return (defined[name] = {})
}
},
module: function (name) {
return {
id: name,
uri: "",
exports: defined[name],
config: makeConfig(name)
}
}
}
main = function (name, deps, callback, relName) {
var cjsModule,
depName,
ret,
map,
i,
relParts,
args = [],
callbackType = typeof callback,
usingExports
//Use name if no relName
relName = relName || name
relParts = makeRelParts(relName)
//Call the callback to define the module, if necessary.
if (callbackType === "undefined" || callbackType === "function") {
//Pull out the defined dependencies and pass the ordered
//values to the callback.
//Default to [require, exports, module] if no deps
deps = !deps.length && callback.length ? ["require", "exports", "module"] : deps
for (i = 0; i < deps.length; i += 1) {
map = makeMap(deps[i], relParts)
depName = map.f
//Fast path CommonJS standard dependencies.
if (depName === "require") {
args[i] = handlers.require(name)
} else if (depName === "exports") {
//CommonJS module spec 1.1
args[i] = handlers.exports(name)
usingExports = true
} else if (depName === "module") {
//CommonJS module spec 1.1
cjsModule = args[i] = handlers.module(name)
} else if (hasProp(defined, depName) || hasProp(waiting, depName) || hasProp(defining, depName)) {
args[i] = callDep(depName)
} else if (map.p) {
map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {})
args[i] = defined[depName]
} else {
throw new Error(name + " missing " + depName)
}
}
ret = callback ? callback.apply(defined[name], args) : undefined
if (name) {
//If setting exports via "module" is in play,
//favor that over return value and exports. After that,
//favor a non-undefined return value over exports use.
if (cjsModule && cjsModule.exports !== undef && cjsModule.exports !== defined[name]) {
defined[name] = cjsModule.exports
} else if (ret !== undef || !usingExports) {
//Use the return value from the function.
defined[name] = ret
}
}
} else if (name) {
//May just be an object definition for the module. Only
//worry about defining if have a module name.
defined[name] = callback
}
}
requirejs =
require =
req =
function (deps, callback, relName, forceSync, alt) {
if (typeof deps === "string") {
if (handlers[deps]) {
//callback in this case is really relName
return handlers[deps](callback)
}
//Just return the module wanted. In this scenario, the
//deps arg is the module name, and second arg (if passed)
//is just the relName.
//Normalize module name, if it contains . or ..
return callDep(makeMap(deps, makeRelParts(callback)).f)
} else if (!deps.splice) {
//deps is a config object, not an array.
config = deps
if (config.deps) {
req(config.deps, config.callback)
}
if (!callback) {
return
}
if (callback.splice) {
//callback is an array, which means it is a dependency list.
//Adjust args if there are dependencies
deps = callback
callback = relName
relName = null
} else {
deps = undef
}
}
//Support require(['a'])
callback = callback || function () {}
//If relName is a function, it is an errback handler,
//so remove it.
if (typeof relName === "function") {
relName = forceSync
forceSync = alt
}
//Simulate async callback;
if (forceSync) {
main(undef, deps, callback, relName)
} else {
//Using a non-zero value because of concern for what old browsers
//do, and latest browsers "upgrade" to 4 if lower value is used:
//http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
//If want a value immediately, use require('id') instead -- something
//that works in almond on the global level, but not guaranteed and
//unlikely to work in other AMD implementations.
setTimeout(function () {
main(undef, deps, callback, relName)
}, 4)
}
return req
}
/**
* Just drops the config on the floor, but returns req in case
* the config return value is used.
*/
req.config = function (cfg) {
return req(cfg)
}
/**
* Expose module registry for debugging and tooling
*/
requirejs._defined = defined
define = function (name, deps, callback) {
if (typeof name !== "string") {
throw new Error("See almond README: incorrect module build, no module name")
}
//This module may not have dependencies
if (!deps.splice) {
//deps is not an array, so probably means
//an object literal or factory function for
//the value. Adjust args.
callback = deps
deps = []
}
if (!hasProp(defined, name) && !hasProp(waiting, name)) {
waiting[name] = [name, deps, callback]
}
}
define.amd = {
jQuery: true
}
})()
define("conic/conic-sensor-graphics", [
"require",
"Cesium/Core/defaultValue",
"Cesium/Core/defined",
"Cesium/Core/DeveloperError",
"Cesium/Core/Event",
"Cesium/DataSources/createMaterialPropertyDescriptor",
"Cesium/DataSources/createPropertyDescriptor"
], function (require) {
"use strict"
var defaultValue = require("Cesium/Core/defaultValue")
var defined = require("Cesium/Core/defined")
var defineProperties = Object.defineProperties
var DeveloperError = require("Cesium/Core/DeveloperError")
var Event = require("Cesium/Core/Event")
var createMaterialPropertyDescriptor = require("Cesium/DataSources/createMaterialPropertyDescriptor")
var createPropertyDescriptor = require("Cesium/DataSources/createPropertyDescriptor")
/**
* An optionally time-dynamic cone.
*
* @alias ConicSensorGraphics
* @constructor
*/
var ConicSensorGraphics = function (options) {
this._minimumClockAngle = undefined
this._minimumClockAngleSubscription = undefined
this._maximumClockAngle = undefined
this._maximumClockAngleSubscription = undefined
this._innerHalfAngle = undefined
this._innerHalfAngleSubscription = undefined
this._outerHalfAngle = undefined
this._outerHalfAngleSubscription = undefined
this._lateralSurfaceMaterial = undefined
this._lateralSurfaceMaterialSubscription = undefined
this._intersectionColor = undefined
this._intersectionColorSubscription = undefined
this._intersectionWidth = undefined
this._intersectionWidthSubscription = undefined
this._showIntersection = undefined
this._showIntersectionSubscription = undefined
this._radius = undefined
this._radiusSubscription = undefined
this._show = undefined
this._showSubscription = undefined
this._definitionChanged = new Event()
this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT))
}
defineProperties(ConicSensorGraphics.prototype, {
/**
* Gets the event that is raised whenever a new property is assigned.
* @memberof ConicSensorGraphics.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function () {
return this._definitionChanged
}
},
/**
* Gets or sets the numeric {@link Property} specifying the the cone's minimum clock angle.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
minimumClockAngle: createPropertyDescriptor("minimumClockAngle"),
/**
* Gets or sets the numeric {@link Property} specifying the the cone's maximum clock angle.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
maximumClockAngle: createPropertyDescriptor("maximumClockAngle"),
/**
* Gets or sets the numeric {@link Property} specifying the the cone's inner half-angle.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
innerHalfAngle: createPropertyDescriptor("innerHalfAngle"),
/**
* Gets or sets the numeric {@link Property} specifying the the cone's outer half-angle.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
outerHalfAngle: createPropertyDescriptor("outerHalfAngle"),
/**
* Gets or sets the {@link MaterialProperty} specifying the the cone's appearance.
* @memberof ConicSensorGraphics.prototype
* @type {MaterialProperty}
*/
lateralSurfaceMaterial: createMaterialPropertyDescriptor("lateralSurfaceMaterial"),
/**
* Gets or sets the {@link Color} {@link Property} specifying the color of the line formed by the intersection of the cone and other central bodies.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
intersectionColor: createPropertyDescriptor("intersectionColor"),
/**
* Gets or sets the numeric {@link Property} specifying the width of the line formed by the intersection of the cone and other central bodies.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
intersectionWidth: createPropertyDescriptor("intersectionWidth"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the line formed by the intersection of the cone and other central bodies.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
showIntersection: createPropertyDescriptor("showIntersection"),
/**
* Gets or sets the numeric {@link Property} specifying the radius of the cone's projection.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
radius: createPropertyDescriptor("radius"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the cone.
* @memberof ConicSensorGraphics.prototype
* @type {Property}
*/
show: createPropertyDescriptor("show")
})
/**
* Duplicates a ConicSensorGraphics instance.
*
* @param {ConicSensorGraphics} [result] The object onto which to store the result.
* @returns {ConicSensorGraphics} The modified result parameter or a new instance if one was not provided.
*/
ConicSensorGraphics.prototype.clone = function (result) {
if (!defined(result)) {
result = new ConicSensorGraphics()
}
result.show = this.show
result.innerHalfAngle = this.innerHalfAngle
result.outerHalfAngle = this.outerHalfAngle
result.minimumClockAngle = this.minimumClockAngle
result.maximumClockAngle = this.maximumClockAngle
result.radius = this.radius
result.showIntersection = this.showIntersection
result.intersectionColor = this.intersectionColor
result.intersectionWidth = this.intersectionWidth
result.lateralSurfaceMaterial = this.lateralSurfaceMaterial
return result
}
/**
* Assigns each unassigned property on this object to the value
* of the same property on the provided source object.
*
* @param {ConicSensorGraphics} source The object to be merged into this object.
*/
ConicSensorGraphics.prototype.merge = function (source) {
// >>includeStart('debug', pragmas.debug);
if (!defined(source)) {
throw new DeveloperError("source is required.")
}
// >>includeEnd('debug');
this.show = defaultValue(this.show, source.show)
this.innerHalfAngle = defaultValue(this.innerHalfAngle, source.innerHalfAngle)
this.outerHalfAngle = defaultValue(this.outerHalfAngle, source.outerHalfAngle)
this.minimumClockAngle = defaultValue(this.minimumClockAngle, source.minimumClockAngle)
this.maximumClockAngle = defaultValue(this.maximumClockAngle, source.maximumClockAngle)
this.radius = defaultValue(this.radius, source.radius)
this.showIntersection = defaultValue(this.showIntersection, source.showIntersection)
this.intersectionColor = defaultValue(this.intersectionColor, source.intersectionColor)
this.intersectionWidth = defaultValue(this.intersectionWidth, source.intersectionWidth)
this.lateralSurfaceMaterial = defaultValue(this.lateralSurfaceMaterial, source.lateralSurfaceMaterial)
}
return ConicSensorGraphics
})
define("text", {
load: function (id) {
throw new Error("Dynamic load not allowed: " + id)
}
})
define("text!custom/custom-sensor-volume-fs.glsl", [], function () {
return `#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
uniform bool u_showIntersection;
uniform bool u_showThroughEllipsoid;
uniform float u_sensorRadius;
uniform float u_normalDirection;
in vec3 v_positionWC;
in vec3 v_positionEC;
in vec3 v_normalEC;
vec4 getColor(float sensorRadius, vec3 pointEC)
{
czm_materialInput materialInput;
vec3 pointMC = (czm_inverseModelView * vec4(pointEC, 1.0)).xyz;
materialInput.st = sensor2dTextureCoordinates(sensorRadius, pointMC);
materialInput.str = pointMC / sensorRadius;
vec3 positionToEyeEC = -v_positionEC;
materialInput.positionToEyeEC = positionToEyeEC;
vec3 normalEC = normalize(v_normalEC);
materialInput.normalEC = u_normalDirection * normalEC;
czm_material material = czm_getMaterial(materialInput);
return mix(czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC), vec4(material.diffuse, material.alpha), 0.4);
}
bool isOnBoundary(float value, float epsilon)
{
float width = getIntersectionWidth();
float tolerance = width * epsilon;
#ifdef GL_OES_standard_derivatives
float delta = max(abs(dFdx(value)), abs(dFdy(value)));
float pixels = width * delta;
float temp = abs(value);
return temp < tolerance && temp < pixels || (delta < 10.0 * tolerance && temp - delta < tolerance && temp < pixels);
#else
return abs(value) < tolerance;
#endif
}
vec4 shade(bool isOnBoundary)
{
if (u_showIntersection && isOnBoundary)
{
return getIntersectionColor();
}
return getColor(u_sensorRadius, v_positionEC);
}
float ellipsoidSurfaceFunction( vec3 point)
{
vec3 scaled = czm_ellipsoidInverseRadii * point;
return dot(scaled, scaled) - 1.0;
}
void main()
{
vec3 sensorVertexWC = czm_model[3].xyz;
vec3 sensorVertexEC = czm_modelView[3].xyz;
float ellipsoidValue = ellipsoidSurfaceFunction( v_positionWC);
if (!u_showThroughEllipsoid)
{
if (ellipsoidValue < 0.0)
{
discard;
}
if (inSensorShadow(sensorVertexWC, v_positionWC))
{
discard;
}
}
if (distance(v_positionEC, sensorVertexEC) > u_sensorRadius)
{
discard;
}
bool isOnEllipsoid = isOnBoundary(ellipsoidValue, czm_epsilon3);
out_FragColor = shade(isOnEllipsoid);
}
`
})
define("text!custom/custom-sensor-volume-vs.glsl", [], function () {
return `in vec4 position;
in vec3 normal;
out vec3 v_positionWC;
out vec3 v_positionEC;
out vec3 v_normalEC;
void main()
{
gl_Position = czm_modelViewProjection * position;
v_positionWC = (czm_model * position).xyz;
v_positionEC = (czm_modelView * position).xyz;
v_normalEC = czm_normal * normal;
}
`
})
define("text!sensor-volume.glsl", [], function () {
return `uniform vec4 u_intersectionColor;
uniform float u_intersectionWidth;
bool inSensorShadow(vec3 coneVertexWC, vec3 pointWC)
{
vec3 D = czm_ellipsoidInverseRadii;
vec3 q = D * coneVertexWC;
float qMagnitudeSquared = dot(q, q);
float test = qMagnitudeSquared - 1.0;
vec3 temp = D * pointWC - q;
float d = dot(temp, q);
return (d < -test) && (d / length(temp) < -sqrt(test));
}
vec4 getIntersectionColor()
{
return u_intersectionColor;
}
float getIntersectionWidth()
{
return u_intersectionWidth;
}
vec2 sensor2dTextureCoordinates(float sensorRadius, vec3 pointMC)
{
float t = pointMC.z / sensorRadius;
float s = 1.0 + (atan(pointMC.y, pointMC.x) / czm_twoPi);
s = s - floor(s);
return vec2(s, t);
}
`
})
define("custom/custom-sensor-volume", [
"require",
"Cesium/Core/BoundingSphere",
"Cesium/Core/Cartesian3",
"Cesium/Core/Color",
"Cesium/Core/combine",
"Cesium/Core/ComponentDatatype",
"Cesium/Core/defaultValue",
"Cesium/Core/defined",
"Cesium/Core/destroyObject",
"Cesium/Core/DeveloperError",
"Cesium/Core/Matrix4",
"Cesium/Core/PrimitiveType",
"Cesium/Renderer/Buffer",
"Cesium/Renderer/BufferUsage",
"Cesium/Renderer/DrawCommand",
"Cesium/Renderer/Pass",
"Cesium/Renderer/RenderState",
"Cesium/Renderer/ShaderProgram",
"Cesium/Renderer/ShaderSource",
"Cesium/Renderer/VertexArray",
"Cesium/Scene/BlendingState",
"Cesium/Scene/CullFace",
"Cesium/Scene/Material",
"Cesium/Scene/SceneMode",
"text!./custom-sensor-volume-fs.glsl",
"text!./custom-sensor-volume-vs.glsl",
"text!../sensor-volume.glsl"
], function (require) {
"use strict"
var BoundingSphere = require("Cesium/Core/BoundingSphere")
var Cartesian3 = require("Cesium/Core/Cartesian3")
var Color = require("Cesium/Core/Color")
var combine = require("Cesium/Core/combine")
var ComponentDatatype = require("Cesium/Core/ComponentDatatype")
var defaultValue = require("Cesium/Core/defaultValue")
var defined = require("Cesium/Core/defined")
var defineProperties = Object.defineProperties
var destroyObject = require("Cesium/Core/destroyObject")
var DeveloperError = require("Cesium/Core/DeveloperError")
var Matrix4 = require("Cesium/Core/Matrix4")
var PrimitiveType = require("Cesium/Core/PrimitiveType")
var Buffer = require("Cesium/Renderer/Buffer")
var BufferUsage = require("Cesium/Renderer/BufferUsage")
var DrawCommand = require("Cesium/Renderer/DrawCommand")
var Pass = require("Cesium/Renderer/Pass")
var RenderState = require("Cesium/Renderer/RenderState")
var ShaderProgram = require("Cesium/Renderer/ShaderProgram")
var ShaderSource = require("Cesium/Renderer/ShaderSource")
var VertexArray = require("Cesium/Renderer/VertexArray")
var BlendingState = require("Cesium/Scene/BlendingState")
var CullFace = require("Cesium/Scene/CullFace")
var Material = require("Cesium/Scene/Material")
var SceneMode = require("Cesium/Scene/SceneMode")
var CustomSensorVolumeFS = require("text!./custom-sensor-volume-fs.glsl")
var CustomSensorVolumeVS = require("text!./custom-sensor-volume-vs.glsl")
var SensorVolume = require("text!../sensor-volume.glsl")
var attributeLocations = {
position: 0,
normal: 1
}
var FAR = 5906376272000.0 // distance from the Sun to Pluto in meters.
/**
* DOC_TBA
*
* @alias CustomSensorVolume
* @constructor
*/
var CustomSensorVolume = function (options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT)
this._pickId = undefined
this._pickPrimitive = defaultValue(options._pickPrimitive, this)
this._frontFaceColorCommand = new DrawCommand()
this._backFaceColorCommand = new DrawCommand()
this._pickCommand = new DrawCommand()
this._boundingSphere = new BoundingSphere()
this._boundingSphereWC = new BoundingSphere()
this._frontFaceColorCommand.primitiveType = PrimitiveType.TRIANGLES
this._frontFaceColorCommand.boundingVolume = this._boundingSphereWC
this._frontFaceColorCommand.owner = this
this._backFaceColorCommand.primitiveType = this._frontFaceColorCommand.primitiveType
this._backFaceColorCommand.boundingVolume = this._frontFaceColorCommand.boundingVolume
this._backFaceColorCommand.owner = this
this._pickCommand.primitiveType = this._frontFaceColorCommand.primitiveType
this._pickCommand.boundingVolume = this._frontFaceColorCommand.boundingVolume
this._pickCommand.owner = this
/**
* <code>true</code> if this sensor will be shown; otherwise, <code>false</code>
*
* @type {Boolean}
* @default true
*/
this.show = defaultValue(options.show, true)
/**
* When <code>true</code>, a polyline is shown where the sensor outline intersections the globe.
*
* @type {Boolean}
*
* @default true
*
* @see CustomSensorVolume#intersectionColor
*/
this.showIntersection = defaultValue(options.showIntersection, true)
/**
* <p>
* Determines if a sensor intersecting the ellipsoid is drawn through the ellipsoid and potentially out
* to the other side, or if the part of the sensor intersecting the ellipsoid stops at the ellipsoid.
* </p>
*
* @type {Boolean}
* @default false
*/
this.showThroughEllipsoid = defaultValue(options.showThroughEllipsoid, false)
this._showThroughEllipsoid = this.showThroughEllipsoid
/**
* The 4x4 transformation matrix that transforms this sensor from model to world coordinates. In it's model
* coordinates, the sensor's principal direction is along the positive z-axis. The clock angle, sometimes
* called azimuth, is the angle in the sensor's X-Y plane measured from the positive X-axis toward the positive
* Y-axis. The cone angle, sometimes called elevation, is the angle out of the X-Y plane along the positive Z-axis.
* <br /><br />
* <div align='center'>
* <img src='images/CustomSensorVolume.setModelMatrix.png' /><br />
* Model coordinate system for a custom sensor
* </div>
*
* @type {Matrix4}
* @default {@link Matrix4.IDENTITY}
*
* @example
* // The sensor's vertex is located on the surface at -75.59777 degrees longitude and 40.03883 degrees latitude.
* // The sensor's opens upward, along the surface normal.
* var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);
* sensor.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
*/
this.modelMatrix = Matrix4.clone(defaultValue(options.modelMatrix, Matrix4.IDENTITY))
this._modelMatrix = new Matrix4()
/**
* DOC_TBA
*
* @type {Number}
* @default {@link Number.POSITIVE_INFINITY}
*/
this.radius = defaultValue(options.radius, Number.POSITIVE_INFINITY)
this._directions = undefined
this._directionsDirty = false
this.directions = defined(options.directions) ? options.directions : []
/**
* The surface appearance of the sensor. This can be one of several built-in {@link Material} objects or a custom material, scripted with
* {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}.
* <p>
* The default material is <code>Material.ColorType</code>.
* </p>
*
* @type {Material}
* @default Material.fromType(Material.ColorType)
*
* @see {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Fabric|Fabric}
*
* @example
* // 1. Change the color of the default material to yellow
* sensor.lateralSurfaceMaterial.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);
*
* // 2. Change material to horizontal stripes
* sensor.lateralSurfaceMaterial = Cesium.Material.fromType(Material.StripeType);
*/
this.lateralSurfaceMaterial = defined(options.lateralSurfaceMaterial) ? options.lateralSurfaceMaterial : Material.fromType(Material.ColorType)
this._lateralSurfaceMaterial = undefined
this._translucent = undefined
/**
* The color of the polyline where the sensor outline intersects the globe. The default is {@link Color.WHITE}.
*
* @type {Color}
* @default {@link Color.WHITE}
*
* @see CustomSensorVolume#showIntersection
*/
this.intersectionColor = Color.clone(defaultValue(options.intersectionColor, Color.WHITE))
/**
* The approximate pixel width of the polyline where the sensor outline intersects the globe. The default is 5.0.
*
* @type {Number}
* @default 5.0
*
* @see CustomSensorVolume#showIntersection
*/
this.intersectionWidth = defaultValue(options.intersectionWidth, 5.0)
/**
* User-defined object returned when the sensors is picked.
*
* @type Object
*
* @default undefined
*
* @see Scene#pick
*/
this.id = options.id
this._id = undefined
var that = this
/* eslint-disable camelcase */
this._uniforms = {
u_showThroughEllipsoid: function () {
return that.showThroughEllipsoid
},
u_showIntersection: function () {
return that.showIntersection
},
u_sensorRadius: function () {
return isFinite(that.radius) ? that.radius : FAR
},
u_intersectionColor: function () {
return that.intersectionColor
},
u_intersectionWidth: function () {
return that.intersectionWidth
},
u_normalDirection: function () {
return 1.0
}
}
}
defineProperties(CustomSensorVolume.prototype, {
directions: {
get: function () {
return this._directions
},
set: function (value) {
this._directions = value
this._directionsDirty = true
}
}
})
var n0Scratch = new Cartesian3()
var n1Scratch = new Cartesian3()
var n2Scratch = new Cartesian3()
function computePositions(customSensorVolume) {
var directions = customSensorVolume._directions
var length = directions.length
var positions = new Float32Array(3 * length)
var r = isFinite(customSensorVolume.radius) ? customSensorVolume.radius : FAR
var boundingVolumePositions = [Cartesian3.ZERO]
for (var i = length - 2, j = length - 1, k = 0; k < length; i = j++, j = k++) {
// PERFORMANCE_IDEA: We can avoid redundant operations for adjacent edges.
var n0 = Cartesian3.fromSpherical(directions[i], n0Scratch)
var n1 = Cartesian3.fromSpherical(directions[j], n1Scratch)
var n2 = Cartesian3.fromSpherical(directions[k], n2Scratch)
// Extend position so the volume encompasses the sensor's radius.
var theta = Math.max(Cartesian3.angleBetween(n0, n1), Cartesian3.angleBetween(n1, n2))
var distance = r / Math.cos(theta * 0.5)
var p = Cartesian3.multiplyByScalar(n1, distance, new Cartesian3())
positions[j * 3] = p.x
positions[j * 3 + 1] = p.y
positions[j * 3 + 2] = p.z
boundingVolumePositions.push(p)
}
BoundingSphere.fromPoints(boundingVolumePositions, customSensorVolume._boundingSphere)
return positions
}
var nScratch = new Cartesian3()
function createVertexArray(customSensorVolume, context) {
var positions = computePositions(customSensorVolume)
var length = customSensorVolume._directions.length
var vertices = new Float32Array(2 * 3 * 3 * length)
var k = 0
for (var i = length - 1, j = 0; j < length; i = j++) {
var p0 = new Cartesian3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2])
var p1 = new Cartesian3(positions[j * 3], positions[j * 3 + 1], positions[j * 3 + 2])
var n = Cartesian3.normalize(Cartesian3.cross(p1, p0, nScratch), nScratch) // Per-face normals
vertices[k++] = 0.0 // Sensor vertex
vertices[k++] = 0.0
vertices[k++] = 0.0
vertices[k++] = n.x
vertices[k++] = n.y
vertices[k++] = n.z
vertices[k++] = p1.x
vertices[k++] = p1.y
vertices[k++] = p1.z
vertices[k++] = n.x
vertices[k++] = n.y
vertices[k++] = n.z
vertices[k++] = p0.x
vertices[k++] = p0.y
vertices[k++] = p0.z
vertices[k++] = n.x
vertices[k++] = n.y
vertices[k++] = n.z
}
var vertexBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: new Float32Array(vertices),
usage: BufferUsage.STATIC_DRAW
})
var stride = 2 * 3 * Float32Array.BYTES_PER_ELEMENT
var attributes = [
{
index: attributeLocations.position,
vertexBuffer: vertexBuffer,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype.FLOAT,
offsetInBytes: 0,
strideInBytes: stride
},
{
index: attributeLocations.normal,
vertexBuffer: vertexBuffer,
componentsPerAttribute: 3,
componentDatatype: ComponentDatatype.FLOAT,
offsetInBytes: 3 * Float32Array.BYTES_PER_ELEMENT,
strideInBytes: stride
}
]
return new VertexArray({
context: context,
attributes: attributes
})
}
/**
* Called when {@link Viewer} or {@link CesiumWidget} render the scene to
* get the draw commands needed to render this primitive.
* <p>
* Do not call this function directly. This is documented just to
* list the exceptions that may be propagated when the scene is rendered:
* </p>
*
* @exception {DeveloperError} this.radius must be greater than or equal to zero.
* @exception {DeveloperError} this.lateralSurfaceMaterial must be defined.
*/
CustomSensorVolume.prototype.update = function (frameState) {
if (!this.show || frameState.mode !== SceneMode.SCENE3D) {
return
}
var context = frameState.context
var commandList = frameState.commandList
// >>includeStart('debug', pragmas.debug);
if (this.radius < 0.0) {
throw new DeveloperError("this.radius must be greater than or equal to zero.")
}
if (!defined(this.lateralSurfaceMaterial)) {
throw new DeveloperError("this.lateralSurfaceMaterial must be defined.")
}
// >>includeEnd('debug');
var translucent = this.lateralSurfaceMaterial.isTranslucent()
// Initial render state creation
if (
this._showThroughEllipsoid !== this.showThroughEllipsoid ||
!defined(this._frontFaceColorCommand.renderState) ||
this._translucent !== translucent
) {
this._showThroughEllipsoid = this.showThroughEllipsoid
this._translucent = translucent
var rs
if (translucent) {
rs = RenderState.fromCache({
depthTest: {
// This would be better served by depth testing with a depth buffer that does not
// include the ellipsoid depth - or a g-buffer containing an ellipsoid mask
// so we can selectively depth test.
enabled: !this.showThroughEllipsoid
},
depthMask: false,
blending: BlendingState.ALPHA_BLEND,
cull: {
enabled: true,
face: CullFace.BACK
}
})
this._frontFaceColorCommand.renderState = rs
this._frontFaceColorCommand.pass = Pass.TRANSLUCENT
rs = RenderState.fromCache({
depthTest: {
enabled: !this.showThroughEllipsoid
},
depthMask: false,
blending: BlendingState.ALPHA_BLEND,
cull: {
enabled: true,
face: CullFace.FRONT
}
})
this._backFaceColorCommand.renderState = rs
this._backFaceColorCommand.pass = Pass.TRANSLUCENT
rs = RenderState.fromCache({
depthTest: {
enabled: !this.showThroughEllipsoid
},
depthMask: false,
blending: BlendingState.ALPHA_BLEND
})
this._pickCommand.renderState = rs
} else {
rs = RenderState.fromCache({
depthTest: {
enabled: true
},
depthMask: true
})
this._frontFaceColorCommand.renderState = rs
this._frontFaceColorCommand.pass = Pass.OPAQUE
rs = RenderState.fromCache({
depthTest: {
enabled: true
},
depthMask: true
})
this._pickCommand.renderState = rs
}
}
// Recreate vertex buffer when directions change
var directionsChanged = this._directionsDirty
if (directionsChanged) {
this._directionsDirty = false
this._va = this._va && this._va.destroy()
var directions = this._directions
if (directions && directions.length >= 3) {
this._frontFaceColorCommand.vertexArray = createVertexArray(this, context)
this._backFaceColorCommand.vertexArray = this._frontFaceColorCommand.vertexArray
this._pickCommand.vertexArray = this._frontFaceColorCommand.vertexArray
}
}
if (!defined(this._frontFaceColorCommand.vertexArray)) {
return
}
var pass = frameState.passes
var modelMatrixChanged = !Matrix4.equals(this.modelMatrix, this._modelMatrix)
if (modelMatrixChanged) {
Matrix4.clone(this.modelMatrix, this._modelMatrix)
}
if (directionsChanged || modelMatrixChanged) {
BoundingSphere.transform(this._boundingSphere, this.modelMatrix, this._boundingSphereWC)
}
this._frontFaceColorCommand.modelMatrix = this.modelMatrix
this._backFaceColorCommand.modelMatrix = this._frontFaceColorCommand.modelMatrix
this._pickCommand.modelMatrix = this._frontFaceColorCommand.modelMatrix
var materialChanged = this._lateralSurfaceMaterial !== this.lateralSurfaceMaterial
this._lateralSurfaceMaterial = this.lateralSurfaceMaterial
this._lateralSurfaceMaterial.update(context)
if (pass.render) {
var frontFaceColorCommand = this._frontFaceColorCommand
var backFaceColorCommand = this._backFaceColorCommand
// Recompile shader when material changes
if (materialChanged || !defined(frontFaceColorCommand.shaderProgram)) {
var fsSource = new ShaderSource({
sources: [SensorVolume, this._lateralSurfaceMaterial.shaderSource, CustomSensorVolumeFS]
})
frontFaceColorCommand.shaderProgram = ShaderProgram.replaceCache({
context: context,
shaderProgram: frontFaceColorCommand.shaderProgram,
vertexShaderSource: CustomSensorVolumeVS,
fragmentShaderSource: fsSource,
attributeLocations: attributeLocations
})
frontFaceColorCommand.uniformMap = combine(this._uniforms, this._lateralSurfaceMaterial._uniforms)
backFaceColorCommand.shaderProgram = frontFaceColorCommand.shaderProgram
backFaceColorCommand.uniformMap = combine(this._uniforms, this._lateralSurfaceMaterial._uniforms)
// eslint-disable-next-line camelcase
backFaceColorCommand.uniformMap.u_normalDirection = function () {
return -1.0
}
}
if (translucent) {
commandList.push(this._backFaceColorCommand, this._frontFaceColorCommand)
} else {
commandList.push(this._frontFaceColorCommand)
}
}
if (pass.pick) {
var pickCommand = this._pickCommand
if (!defined(this._pickId) || this._id !== this.id) {
this._id = this.id
this._pickId = this._pickId && this._pickId.destroy()
this._pickId = context.createPickId({
primitive: this._pickPrimitive,
id: this.id
})
}
// Recompile shader when material changes
if (materialChanged || !defined(pickCommand.shaderProgram)) {
var pickFS = new ShaderSource({
sources: [SensorVolume, this._lateralSurfaceMaterial.shaderSource, CustomSensorVolumeFS],
pickColorQualifier: "uniform"
})
pickCommand.shaderProgram = ShaderProgram.replaceCache({
context: context,
shaderProgram: pickCommand.shaderProgram,
vertexShaderSource: CustomSensorVolumeVS,
fragmentShaderSource: pickFS,
attributeLocations: attributeLocations
})
var that = this
var uniforms = {
// eslint-disable-next-line camelcase
czm_pickColor: function () {
return that._pickId.color
}
}
pickCommand.uniformMap = combine(combine(this._uniforms, this._lateralSurfaceMaterial._uniforms), uniforms)
}
pickCommand.pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE
commandList.push(pickCommand)
}
}
/**
* DOC_TBA
*/
CustomSensorVolume.prototype.isDestroyed = function () {
return false
}
/**
* DOC_TBA
*/
CustomSensorVolume.prototype.destroy = function () {
this._frontFaceColorCommand.vertexArray = this._frontFaceColorCommand.vertexArray && this._frontFaceColorCommand.vertexArray.destroy()
this._frontFaceColorCommand.shaderProgram = this._frontFaceColorCommand.shaderProgram && this._frontFaceColorCommand.shaderProgram.destroy()
this._pickCommand.shaderProgram = this._pickCommand.shaderProgram && this._pickCommand.shaderProgram.destroy()
this._pickId = this._pickId && this._pickId.destroy()
return destroyObject(this)
}
return CustomSensorVolume
})
define("util/remove-primitive", ["require", "Cesium/Core/defined"], function (require) {
"use strict"
var defined = require("Cesium/Core/defined")
return function removePrimitive(entity, hash, primitives) {
var data = hash[entity.id]
if (defined(data)) {
var primitive = data.primitive
primitives.remove(primitive)
if (!primitive.isDestroyed()) {
primitive.destroy()
}
delete hash[entity.id]
}
}
})
define("conic/conic-sensor-visualizer", [
"require",
"Cesium/Core/AssociativeArray",
"Cesium/Core/Cartesian3",
"Cesium/Core/Color",
"Cesium/Core/defined",
"Cesium/Core/destroyObject",
"Cesium/Core/DeveloperError",
"Cesium/Core/Math",
"Cesium/Core/Matrix3",
"Cesium/Core/Matrix4",
"Cesium/Core/Quaternion",
"Cesium/Core/Spherical",
"Cesium/DataSources/MaterialProperty",
"Cesium/DataSources/Property",
"../custom/custom-sensor-volume",
"../util/remove-primitive"
], function (require) {
"use strict"
var AssociativeArray = require("Cesium/Core/AssociativeArray")
var Cartesian3 = require("Cesium/Core/Cartesian3")
var Color = require("Cesium/Core/Color")
var defined = require("Cesium/Core/defined")
var destroyObject = require("Cesium/Core/destroyObject")
var DeveloperError = require("Cesium/Core/DeveloperError")
var CesiumMath = require("Cesium/Core/Math")
var Matrix3 = require("Cesium/Core/Matrix3")
var Matrix4 = require("Cesium/Core/Matrix4")
var Quaternion = require("Cesium/Core/Quaternion")
var Spherical = require("Cesium/Core/Spherical")
var MaterialProperty = require("Cesium/DataSources/MaterialProperty")
var Property = require("Cesium/DataSources/Property")
var CustomSensorVolume = require("../custom/custom-sensor-volume")
var removePrimitive = require("../util/remove-primitive")
var defaultIntersectionColor = Color.WHITE
var defaultIntersectionWidth = 1.0
var defaultRadius = Number.POSITIVE_INFINITY
var matrix3Scratch = new Matrix3()
var cachedPosition = new Cartesian3()
var cachedOrientation = new Quaternion()
function assignSpherical(index, array, clock, cone) {
var spherical = array[index]
if (!defined(spherical)) {
spherical = new Spherical()
array[index] = spherical
}
spherical.clock = clock
spherical.cone = cone
spherical.magnitude = 1.0
}
function computeDirections(primitive, minimumClockAngle, maximumClockAngle, innerHalfAngle, outerHalfAngle) {
var directions = primitive.directions
var angle
var i = 0
var angleStep = CesiumMath.toRadians(2.0)
if (minimumClockAngle === 0.0 && maximumClockAngle === CesiumMath.TWO_PI) {
// No clock angle limits, so this is just a circle.
// There might be a hole but we're ignoring it for now.
for (angle = 0.0; angle < CesiumMath.TWO_PI; angle += angleStep) {
assignSpherical(i++, directions, angle, outerHalfAngle)
}
} else {
// There are clock angle limits.
for (angle = minimumClockAngle; angle < maximumClockAngle; angle += angleStep) {
assignSpherical(i++, directions, angle, outerHalfAngle)
}
assignSpherical(i++, directions, maximumClockAngle, outerHalfAngle)
if (innerHalfAngle) {
for (angle = maximumClockAngle; angle > minimumClockAngle; angle -= angleStep) {
assignSpherical(i++, directions, angle, innerHalfAngle)
}
assignSpherical(i++, directions, minimumClockAngle, innerHalfAngle)
} else {
assignSpherical(i++, directions, maximumClockAngle, 0.0)
}
}
directions.length = i
primitive.directions = directions
}
/**
* A {@link Visualizer} which maps {@link Entity#conicSensor} to a {@link ConicSensor}.
* @alias ConicSensorVisualizer
* @constructor
*
* @param {Scene} scene The scene the primitives will be rendered in.
* @param {EntityCollection} entityCollection The entityCollection to visualize.
*/
var ConicSensorVisualizer = function (scene, entityCollection) {
// >>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError("scene is required.")
}
if (!defined(entityCollection)) {
throw new DeveloperError("entityCollection is required.")
}
// >>includeEnd('debug');
entityCollection.collectionChanged.addEventListener(ConicSensorVisualizer.prototype._onCollectionChanged, this)
this._scene = scene
this._primitives = scene.primitives
this._entityCollection = entityCollection
this._hash = {}
this._entitiesToVisualize = new AssociativeArray()
this._onCollectionChanged(entityCollection, entityCollection.values, [], [])
}
/**
* Updates the primitives created by this visualizer to match their
* Entity counterpart at the given time.
*
* @param {JulianDate} time The time to update to.
* @returns {Boolean} This function always returns true.
*/
ConicSensorVisualizer.prototype.update = function (time) {
// >>includeStart('debug', pragmas.debug);
if (!defined(time)) {
throw new DeveloperError("time is required.")
}
// >>includeEnd('debug');
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = 0, len = entities.length; i < len; i++) {
var entity = entities[i]
var conicSensorGraphics = entity._conicSensor
var position
var orientation
var data = hash[entity.id]
var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(conicSensorGraphics._show, time, true)
if (show) {
position = Property.getValueOrUndefined(entity._position, time, cachedPosition)
orientation = Property.getValueOrUndefined(entity._orientation, time, cachedOrientation)
show = defined(position) && defined(orientation)
}
if (!show) {
// don't bother creating or updating anything else
if (defined(data)) {
data.primitive.show = false
}
continue
}
var primitive = defined(data) ? data.primitive : undefined
if (!defined(primitive)) {
primitive = new CustomSensorVolume()
primitive.id = entity
primitives.add(primitive)
data = {
primitive: primitive,
position: undefined,
orientation: undefined,
minimumClockAngle: undefined,
maximumClockAngle: undefined,
innerHalfAngle: undefined,
outerHalfAngle: undefined
}
hash[entity.id] = data
}
if (!Cartesian3.equals(position, data.position) || !Quaternion.equals(orientation, data.orientation)) {
Matrix4.fromRotationTranslation(Matrix3.fromQuaternion(orientation, matrix3Scratch), position, primitive.modelMatrix)
data.position = Cartesian3.clone(position, data.position)
data.orientation = Quaternion.clone(orientation, data.orientation)
}
primitive.show = true
var minimumClockAngle = Property.getValueOrDefault(conicSensorGraphics._minimumClockAngle, time, 0)
var maximumClockAngle = Property.getValueOrDefault(conicSensorGraphics._maximumClockAngle, time, CesiumMath.TWO_PI)
var innerHalfAngle = Property.getValueOrDefault(conicSensorGraphics._innerHalfAngle, time, 0)
var outerHalfAngle = Property.getValueOrDefault(conicSensorGraphics._outerHalfAngle, time, Math.PI)
if (
minimumClockAngle !== data.minimumClockAngle ||
maximumClockAngle !== data.maximumClockAngle ||
innerHalfAngle !== data.innerHalfAngle ||
outerHalfAngle !== data.outerHalfAngle
) {
computeDirections(primitive, minimumClockAngle, maximumClockAngle, innerHalfAngle, outerHalfAngle)
data.innerHalfAngle = innerHalfAngle
data.maximumClockAngle = maximumClockAngle
data.outerHalfAngle = outerHalfAngle
data.minimumClockAngle = minimumClockAngle
}
primitive.radius = Property.getValueOrDefault(conicSensorGraphics._radius, time, defaultRadius)
primitive.lateralSurfaceMaterial = MaterialProperty.getValue(
time,
conicSensorGraphics._lateralSurfaceMaterial,
primitive.lateralSurfaceMaterial
)
primitive.intersectionColor = Property.getValueOrClonedDefault(
conicSensorGraphics._intersectionColor,
time,
defaultIntersectionColor,
primitive.intersectionColor
)
primitive.intersectionWidth = Property.getValueOrDefault(conicSensorGraphics._intersectionWidth, time, defaultIntersectionWidth)
}
return true
}
/**
* Returns true if this object was destroyed; otherwise, false.
*
* @returns {Boolean} True if this object was destroyed; otherwise, false.
*/
ConicSensorVisualizer.prototype.isDestroyed = function () {
return false
}
/**
* Removes and destroys all primitives created by this instance.
*/
ConicSensorVisualizer.prototype.destroy = function () {
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = entities.length - 1; i > -1; i--) {
removePrimitive(entities[i], hash, primitives)
}
return destroyObject(this)
}
/**
* @private
*/
ConicSensorVisualizer.prototype._onCollectionChanged = function (entityCollection, added, removed, changed) {
var i
var entity
var entities = this._entitiesToVisualize
var hash = this._hash
var primitives = this._primitives
for (i = added.length - 1; i > -1; i--) {
entity = added[i]
if (defined(entity._conicSensor) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i]
if (defined(entity._conicSensor) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
} else {
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i]
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
return ConicSensorVisualizer
})
define("custom/custom-pattern-sensor-graphics", [
"require",
"Cesium/Core/defaultValue",
"Cesium/Core/defined",
"Cesium/Core/DeveloperError",
"Cesium/Core/Event",
"Cesium/DataSources/createMaterialPropertyDescriptor",
"Cesium/DataSources/createPropertyDescriptor"
], function (require) {
"use strict"
var defaultValue = require("Cesium/Core/defaultValue")
var defined = require("Cesium/Core/defined")
var defineProperties = Object.defineProperties
var DeveloperError = require("Cesium/Core/DeveloperError")
var Event = require("Cesium/Core/Event")
var createMaterialPropertyDescriptor = require("Cesium/DataSources/createMaterialPropertyDescriptor")
var createPropertyDescriptor = require("Cesium/DataSources/createPropertyDescriptor")
/**
* An optionally time-dynamic custom patterned sensor.
*
* @alias CustomPatternSensorGraphics
* @constructor
*/
var CustomPatternSensorGraphics = function (options) {
this._directions = undefined
this._directionsSubscription = undefined
this._lateralSurfaceMaterial = undefined
this._lateralSurfaceMaterialSubscription = undefined
this._intersectionColor = undefined
this._intersectionColorSubscription = undefined
this._intersectionWidth = undefined
this._intersectionWidthSubscription = undefined
this._showIntersection = undefined
this._showIntersectionSubscription = undefined
this._radius = undefined
this._radiusSubscription = undefined
this._show = undefined
this._showSubscription = undefined
this._definitionChanged = new Event()
this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT))
}
defineProperties(CustomPatternSensorGraphics.prototype, {
/**
* Gets the event that is raised whenever a new property is assigned.
* @memberof CustomPatternSensorGraphics.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function () {
return this._definitionChanged
}
},
/**
* A {@link Property} which returns an array of {@link Spherical} instances representing the sensor's projection.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
directions: createPropertyDescriptor("directions"),
/**
* Gets or sets the {@link MaterialProperty} specifying the the sensor's appearance.
* @memberof CustomPatternSensorGraphics.prototype
* @type {MaterialProperty}
*/
lateralSurfaceMaterial: createMaterialPropertyDescriptor("lateralSurfaceMaterial"),
/**
* Gets or sets the {@link Color} {@link Property} specifying the color of the line formed by the intersection of the sensor and other central bodies.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
intersectionColor: createPropertyDescriptor("intersectionColor"),
/**
* Gets or sets the numeric {@link Property} specifying the width of the line formed by the intersection of the sensor and other central bodies.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
intersectionWidth: createPropertyDescriptor("intersectionWidth"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the line formed by the intersection of the sensor and other central bodies.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
showIntersection: createPropertyDescriptor("showIntersection"),
/**
* Gets or sets the numeric {@link Property} specifying the radius of the sensor's projection.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
radius: createPropertyDescriptor("radius"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the sensor.
* @memberof CustomPatternSensorGraphics.prototype
* @type {Property}
*/
show: createPropertyDescriptor("show")
})
/**
* Duplicates a CustomPatternSensorGraphics instance.
*
* @param {CustomPatternSensorGraphics} [result] The object onto which to store the result.
* @returns {CustomPatternSensorGraphics} The modified result parameter or a new instance if one was not provided.
*/
CustomPatternSensorGraphics.prototype.clone = function (result) {
if (!defined(result)) {
result = new CustomPatternSensorGraphics()
}
result.directions = this.directions
result.radius = this.radius
result.show = this.show
result.showIntersection = this.showIntersection
result.intersectionColor = this.intersectionColor
result.intersectionWidth = this.intersectionWidth
result.lateralSurfaceMaterial = this.lateralSurfaceMaterial
return result
}
/**
* Assigns each unassigned property on this object to the value
* of the same property on the provided source object.
*
* @param {CustomPatternSensorGraphics} source The object to be merged into this object.
*/
CustomPatternSensorGraphics.prototype.merge = function (source) {
// >>includeStart('debug', pragmas.debug);
if (!defined(source)) {
throw new DeveloperError("source is required.")
}
// >>includeEnd('debug');
this.directions = defaultValue(this.directions, source.directions)
this.radius = defaultValue(this.radius, source.radius)
this.show = defaultValue(this.show, source.show)
this.showIntersection = defaultValue(this.showIntersection, source.showIntersection)
this.intersectionColor = defaultValue(this.intersectionColor, source.intersectionColor)
this.intersectionWidth = defaultValue(this.intersectionWidth, source.intersectionWidth)
this.lateralSurfaceMaterial = defaultValue(this.lateralSurfaceMaterial, source.lateralSurfaceMaterial)
}
return CustomPatternSensorGraphics
})
define("custom/custom-pattern-sensor-visualizer", [
"require",
"Cesium/Core/AssociativeArray",
"Cesium/Core/Cartesian3",
"Cesium/Core/Color",
"Cesium/Core/defined",
"Cesium/Core/destroyObject",
"Cesium/Core/DeveloperError",
"Cesium/Core/Matrix3",
"Cesium/Core/Matrix4",
"Cesium/Core/Quaternion",
"Cesium/DataSources/MaterialProperty",
"Cesium/DataSources/Property",
"../custom/custom-sensor-volume",
"../util/remove-primitive"
], function (require) {
"use strict"
var AssociativeArray = require("Cesium/Core/AssociativeArray")
var Cartesian3 = require("Cesium/Core/Cartesian3")
var Color = require("Cesium/Core/Color")
var defined = require("Cesium/Core/defined")
var destroyObject = require("Cesium/Core/destroyObject")
var DeveloperError = require("Cesium/Core/DeveloperError")
var Matrix3 = require("Cesium/Core/Matrix3")
var Matrix4 = require("Cesium/Core/Matrix4")
var Quaternion = require("Cesium/Core/Quaternion")
var MaterialProperty = require("Cesium/DataSources/MaterialProperty")
var Property = require("Cesium/DataSources/Property")
var CustomSensorVolume = require("../custom/custom-sensor-volume")
var removePrimitive = require("../util/remove-primitive")
var defaultIntersectionColor = Color.WHITE
var defaultIntersectionWidth = 1.0
var defaultRadius = Number.POSITIVE_INFINITY
var matrix3Scratch = new Matrix3()
var cachedPosition = new Cartesian3()
var cachedOrientation = new Quaternion()
/**
* A {@link Visualizer} which maps {@link Entity#customPatternSensor} to a {@link CustomPatternSensor}.
* @alias CustomPatternSensorVisualizer
* @constructor
*
* @param {Scene} scene The scene the primitives will be rendered in.
* @param {EntityCollection} entityCollection The entityCollection to visualize.
*/
var CustomPatternSensorVisualizer = function (scene, entityCollection) {
// >>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError("scene is required.")
}
if (!defined(entityCollection)) {
throw new DeveloperError("entityCollection is required.")
}
// >>includeEnd('debug');
entityCollection.collectionChanged.addEventListener(CustomPatternSensorVisualizer.prototype._onCollectionChanged, this)
this._scene = scene
this._primitives = scene.primitives
this._entityCollection = entityCollection
this._hash = {}
this._entitiesToVisualize = new AssociativeArray()
this._onCollectionChanged(entityCollection, entityCollection.values, [], [])
}
/**
* Updates the primitives created by this visualizer to match their
* Entity counterpart at the given time.
*
* @param {JulianDate} time The time to update to.
* @returns {Boolean} This function always returns true.
*/
CustomPatternSensorVisualizer.prototype.update = function (time) {
// >>includeStart('debug', pragmas.debug);
if (!defined(time)) {
throw new DeveloperError("time is required.")
}
// >>includeEnd('debug');
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = 0, len = entities.length; i < len; i++) {
var entity = entities[i]
var customPatternSensorGraphics = entity._customPatternSensor
var position
var orientation
var directions
var data = hash[entity.id]
var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(customPatternSensorGraphics._show, time, true)
if (show) {
position = Property.getValueOrUndefined(entity._position, time, cachedPosition)
orientation = Property.getValueOrUndefined(entity._orientation, time, cachedOrientation)
directions = Property.getValueOrUndefined(customPatternSensorGraphics._directions, time)
show = defined(position) && defined(orientation) && defined(directions)
}
if (!show) {
// don't bother creating or updating anything else
if (defined(data)) {
data.primitive.show = false
}
continue
}
var primitive = defined(data) ? data.primitive : undefined
if (!defined(primitive)) {
primitive = new CustomSensorVolume()
primitive.id = entity
primitives.add(primitive)
data = {
primitive: primitive,
position: undefined,
orientation: undefined
}
hash[entity.id] = data
}
if (!Cartesian3.equals(position, data.position) || !Quaternion.equals(orientation, data.orientation)) {
Matrix4.fromRotationTranslation(Matrix3.fromQuaternion(orientation, matrix3Scratch), position, primitive.modelMatrix)
data.position = Cartesian3.clone(position, data.position)
data.orientation = Quaternion.clone(orientation, data.orientation)
}
primitive.show = true
primitive.directions = directions
primitive.radius = Property.getValueOrDefault(customPatternSensorGraphics._radius, time, defaultRadius)
primitive.lateralSurfaceMaterial = MaterialProperty.getValue(
time,
customPatternSensorGraphics._lateralSurfaceMaterial,
primitive.lateralSurfaceMaterial
)
primitive.intersectionColor = Property.getValueOrClonedDefault(
customPatternSensorGraphics._intersectionColor,
time,
defaultIntersectionColor,
primitive.intersectionColor
)
primitive.intersectionWidth = Property.getValueOrDefault(customPatternSensorGraphics._intersectionWidth, time, defaultIntersectionWidth)
}
return true
}
/**
* Returns true if this object was destroyed; otherwise, false.
*
* @returns {Boolean} True if this object was destroyed; otherwise, false.
*/
CustomPatternSensorVisualizer.prototype.isDestroyed = function () {
return false
}
/**
* Removes and destroys all primitives created by this instance.
*/
CustomPatternSensorVisualizer.prototype.destroy = function () {
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = entities.length - 1; i > -1; i--) {
removePrimitive(entities[i], hash, primitives)
}
return destroyObject(this)
}
/**
* @private
*/
CustomPatternSensorVisualizer.prototype._onCollectionChanged = function (entityCollection, added, removed, changed) {
var i
var entity
var entities = this._entitiesToVisualize
var hash = this._hash
var primitives = this._primitives
for (i = added.length - 1; i > -1; i--) {
entity = added[i]
if (defined(entity._customPatternSensor) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i]
if (defined(entity._customPatternSensor) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
} else {
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i]
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
return CustomPatternSensorVisualizer
})
define("rectangular/rectangular-sensor-graphics", [
"require",
"Cesium/Core/defaultValue",
"Cesium/Core/defined",
"Cesium/Core/DeveloperError",
"Cesium/Core/Event",
"Cesium/DataSources/createPropertyDescriptor"
], function (require) {
"use strict"
var defaultValue = require("Cesium/Core/defaultValue")
var defined = require("Cesium/Core/defined")
var defineProperties = Object.defineProperties
var DeveloperError = require("Cesium/Core/DeveloperError")
var Event = require("Cesium/Core/Event")
var createPropertyDescriptor = require("Cesium/DataSources/createPropertyDescriptor")
/**
* An optionally time-dynamic pyramid.
*
* @alias RectangularSensorGraphics
* @constructor
*/
var RectangularSensorGraphics = function () {
this._xHalfAngle = undefined
this._xHalfAngleSubscription = undefined
this._yHalfAngle = undefined
this._yHalfAngleSubscription = undefined
this._lateralSurfaceMaterial = undefined
this._lateralSurfaceMaterialSubscription = undefined
this._intersectionColor = undefined
this._intersectionColorSubscription = undefined
this._intersectionWidth = undefined
this._intersectionWidthSubscription = undefined
this._showIntersection = undefined
this._showIntersectionSubscription = undefined
this._radius = undefined
this._radiusSubscription = undefined
this._show = undefined
this._showSubscription = undefined
this._definitionChanged = new Event()
}
defineProperties(RectangularSensorGraphics.prototype, {
/**
* Gets the event that is raised whenever a new property is assigned.
* @memberof RectangularSensorGraphics.prototype
*
* @type {Event}
* @readonly
*/
definitionChanged: {
get: function () {
return this._definitionChanged
}
},
/**
* A {@link Property} which returns an array of {@link Spherical} instances representing the pyramid's projection.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
xHalfAngle: createPropertyDescriptor("xHalfAngle"),
/**
* A {@link Property} which returns an array of {@link Spherical} instances representing the pyramid's projection.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
yHalfAngle: createPropertyDescriptor("yHalfAngle"),
/**
* Gets or sets the {@link MaterialProperty} specifying the the pyramid's appearance.
* @memberof RectangularSensorGraphics.prototype
* @type {MaterialProperty}
*/
lateralSurfaceMaterial: createPropertyDescriptor("lateralSurfaceMaterial"),
/**
* Gets or sets the {@link Color} {@link Property} specifying the color of the line formed by the intersection of the pyramid and other central bodies.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
intersectionColor: createPropertyDescriptor("intersectionColor"),
/**
* Gets or sets the numeric {@link Property} specifying the width of the line formed by the intersection of the pyramid and other central bodies.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
intersectionWidth: createPropertyDescriptor("intersectionWidth"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the line formed by the intersection of the pyramid and other central bodies.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
showIntersection: createPropertyDescriptor("showIntersection"),
/**
* Gets or sets the numeric {@link Property} specifying the radius of the pyramid's projection.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
radius: createPropertyDescriptor("radius"),
/**
* Gets or sets the boolean {@link Property} specifying the visibility of the pyramid.
* @memberof RectangularSensorGraphics.prototype
* @type {Property}
*/
show: createPropertyDescriptor("show")
})
/**
* Duplicates a RectangularSensorGraphics instance.
*
* @param {RectangularSensorGraphics} [result] The object onto which to store the result.
* @returns {RectangularSensorGraphics} The modified result parameter or a new instance if one was not provided.
*/
RectangularSensorGraphics.prototype.clone = function (result) {
if (!defined(result)) {
result = new RectangularSensorGraphics()
}
result.xHalfAngle = this.xHalfAngle
result.yHalfAngle = this.yHalfAngle
result.radius = this.radius
result.show = this.show
result.showIntersection = this.showIntersection
result.intersectionColor = this.intersectionColor
result.intersectionWidth = this.intersectionWidth
result.lateralSurfaceMaterial = this.lateralSurfaceMaterial
return result
}
/**
* Assigns each unassigned property on this object to the value
* of the same property on the provided source object.
*
* @param {RectangularSensorGraphics} source The object to be merged into this object.
*/
RectangularSensorGraphics.prototype.merge = function (source) {
// >>includeStart('debug', pragmas.debug);
if (!defined(source)) {
throw new DeveloperError("source is required.")
}
// >>includeEnd('debug');
this.xHalfAngle = defaultValue(this.xHalfAngle, source.xHalfAngle)
this.yHalfAngle = defaultValue(this.yHalfAngle, source.yHalfAngle)
this.radius = defaultValue(this.radius, source.radius)
this.show = defaultValue(this.show, source.show)
this.showIntersection = defaultValue(this.showIntersection, source.showIntersection)
this.intersectionColor = defaultValue(this.intersectionColor, source.intersectionColor)
this.intersectionWidth = defaultValue(this.intersectionWidth, source.intersectionWidth)
this.lateralSurfaceMaterial = defaultValue(this.lateralSurfaceMaterial, source.lateralSurfaceMaterial)
}
return RectangularSensorGraphics
})
define("rectangular/rectangular-pyramid-sensor-volume", [
"require",
"Cesium/Core/clone",
"Cesium/Core/defaultValue",
"Cesium/Core/defined",
"Cesium/Core/destroyObject",
"Cesium/Core/DeveloperError",
"Cesium/Core/Math",
"Cesium/Core/Spherical",
"../custom/custom-sensor-volume"
], function (require) {
"use strict"
var clone = require("Cesium/Core/clone")
var defaultValue = require("Cesium/Core/defaultValue")
var defined = require("Cesium/Core/defined")
var defineProperties = Object.defineProperties
var destroyObject = require("Cesium/Core/destroyObject")
var DeveloperError = require("Cesium/Core/DeveloperError")
var CesiumMath = require("Cesium/Core/Math")
var Spherical = require("Cesium/Core/Spherical")
var CustomSensorVolume = require("../custom/custom-sensor-volume")
function assignSpherical(index, array, clock, cone) {
var spherical = array[index]
if (!defined(spherical)) {
spherical = new Spherical()
array[index] = spherical
}
spherical.clock = clock
spherical.cone = cone
spherical.magnitude = 1.0
}
function updateDirections(rectangularSensor) {
var directions = rectangularSensor._customSensor.directions
// At 90 degrees the sensor is completely open, and tan() goes to infinity.
var tanX = Math.tan(Math.min(rectangularSensor._xHalfAngle, CesiumMath.toRadians(89.0)))
var tanY = Math.tan(Math.min(rectangularSensor._yHalfAngle, CesiumMath.toRadians(89.0)))
var theta = Math.atan(tanX / tanY)
var cone = Math.atan(Math.sqrt(tanX * tanX + tanY * tanY))
assignSpherical(0, directions, theta, cone)
assignSpherical(1, directions, CesiumMath.toRadians(180.0) - theta, cone)
assignSpherical(2, directions, CesiumMath.toRadians(180.0) + theta, cone)
assignSpherical(3, directions, -theta, cone)
directions.length = 4
rectangularSensor._customSensor.directions = directions
}
var RectangularPyramidSensorVolume = function (options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT)
var customSensorOptions = clone(options)
customSensorOptions._pickPrimitive = defaultValue(options._pickPrimitive, this)
customSensorOptions.directions = undefined
this._customSensor = new CustomSensorVolume(customSensorOptions)
this._xHalfAngle = defaultValue(options.xHalfAngle, CesiumMath.PI_OVER_TWO)
this._yHalfAngle = defaultValue(options.yHalfAngle, CesiumMath.PI_OVER_TWO)
updateDirections(this)
}
defineProperties(RectangularPyramidSensorVolume.prototype, {
xHalfAngle: {
get: function () {
return this._xHalfAngle
},
set: function (value) {
// >>includeStart('debug', pragmas.debug)
if (value > CesiumMath.PI_OVER_TWO) {
throw new DeveloperError("xHalfAngle must be less than or equal to 90 degrees.")
}
// >>includeEnd('debug');
if (this._xHalfAngle !== value) {
this._xHalfAngle = value
updateDirections(this)
}
}
},
yHalfAngle: {
get: function () {
return this._yHalfAngle
},
set: function (value) {
// >>includeStart('debug', pragmas.debug)
if (value > CesiumMath.PI_OVER_TWO) {
throw new DeveloperError("yHalfAngle must be less than or equal to 90 degrees.")
}
// >>includeEnd('debug');
if (this._yHalfAngle !== value) {
this._yHalfAngle = value
updateDirections(this)
}
}
},
show: {
get: function () {
return this._customSensor.show
},
set: function (value) {
this._customSensor.show = value
}
},
showIntersection: {
get: function () {
return this._customSensor.showIntersection
},
set: function (value) {
this._customSensor.showIntersection = value
}
},
showThroughEllipsoid: {
get: function () {
return this._customSensor.showThroughEllipsoid
},
set: function (value) {
this._customSensor.showThroughEllipsoid = value
}
},
modelMatrix: {
get: function () {
return this._customSensor.modelMatrix
},
set: function (value) {
this._customSensor.modelMatrix = value
}
},
radius: {
get: function () {
return this._customSensor.radius
},
set: function (value) {
this._customSensor.radius = value
}
},
lateralSurfaceMaterial: {
get: function () {
return this._customSensor.lateralSurfaceMaterial
},
set: function (value) {
this._customSensor.lateralSurfaceMaterial = value
}
},
intersectionColor: {
get: function () {
return this._customSensor.intersectionColor
},
set: function (value) {
this._customSensor.intersectionColor = value
}
},
intersectionWidth: {
get: function () {
return this._customSensor.intersectionWidth
},
set: function (value) {
this._customSensor.intersectionWidth = value
}
},
id: {
get: function () {
return this._customSensor.id
},
set: function (value) {
this._customSensor.id = value
}
}
})
RectangularPyramidSensorVolume.prototype.update = function (frameState) {
this._customSensor.update(frameState)
}
RectangularPyramidSensorVolume.prototype.isDestroyed = function () {
return false
}
RectangularPyramidSensorVolume.prototype.destroy = function () {
this._customSensor = this._customSensor && this._customSensor.destroy()
return destroyObject(this)
}
return RectangularPyramidSensorVolume
})
define("rectangular/rectangular-sensor-visualizer", [
"require",
"Cesium/Core/AssociativeArray",
"Cesium/Core/Cartesian3",
"Cesium/Core/Color",
"Cesium/Core/defined",
"Cesium/Core/destroyObject",
"Cesium/Core/DeveloperError",
"Cesium/Core/Math",
"Cesium/Core/Matrix3",
"Cesium/Core/Matrix4",
"Cesium/Core/Quaternion",
"Cesium/DataSources/MaterialProperty",
"Cesium/DataSources/Property",
"./rectangular-pyramid-sensor-volume",
"../util/remove-primitive"
], function (require) {
"use strict"
var AssociativeArray = require("Cesium/Core/AssociativeArray")
var Cartesian3 = require("Cesium/Core/Cartesian3")
var Color = require("Cesium/Core/Color")
var defined = require("Cesium/Core/defined")
var destroyObject = require("Cesium/Core/destroyObject")
var DeveloperError = require("Cesium/Core/DeveloperError")
var CesiumMath = require("Cesium/Core/Math")
var Matrix3 = require("Cesium/Core/Matrix3")
var Matrix4 = require("Cesium/Core/Matrix4")
var Quaternion = require("Cesium/Core/Quaternion")
var MaterialProperty = require("Cesium/DataSources/MaterialProperty")
var Property = require("Cesium/DataSources/Property")
var RectangularPyramidSensorVolume = require("./rectangular-pyramid-sensor-volume")
var removePrimitive = require("../util/remove-primitive")
var defaultIntersectionColor = Color.WHITE
var defaultIntersectionWidth = 1.0
var defaultRadius = Number.POSITIVE_INFINITY
var matrix3Scratch = new Matrix3()
var cachedPosition = new Cartesian3()
var cachedOrientation = new Quaternion()
/**
* A {@link Visualizer} which maps {@link Entity#rectangularSensor} to a {@link RectangularSensor}.
* @alias RectangularSensorVisualizer
* @constructor
*
* @param {Scene} scene The scene the primitives will be rendered in.
* @param {EntityCollection} entityCollection The entityCollection to visualize.
*/
var RectangularSensorVisualizer = function (scene, entityCollection) {
// >>includeStart('debug', pragmas.debug);
if (!defined(scene)) {
throw new DeveloperError("scene is required.")
}
if (!defined(entityCollection)) {
throw new DeveloperError("entityCollection is required.")
}
// >>includeEnd('debug');
entityCollection.collectionChanged.addEventListener(RectangularSensorVisualizer.prototype._onCollectionChanged, this)
this._scene = scene
this._primitives = scene.primitives
this._entityCollection = entityCollection
this._hash = {}
this._entitiesToVisualize = new AssociativeArray()
this._onCollectionChanged(entityCollection, entityCollection.values, [], [])
}
/**
* Updates the primitives created by this visualizer to match their
* Entity counterpart at the given time.
*
* @param {JulianDate} time The time to update to.
* @returns {Boolean} This function always returns true.
*/
RectangularSensorVisualizer.prototype.update = function (time) {
// >>includeStart('debug', pragmas.debug);
if (!defined(time)) {
throw new DeveloperError("time is required.")
}
// >>includeEnd('debug');
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = 0, len = entities.length; i < len; i++) {
var entity = entities[i]
var rectangularSensorGraphics = entity._rectangularSensorVoumes
var position
var orientation
var data = hash[entity.id]
var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(rectangularSensorGraphics._show, time, true)
if (show) {
position = Property.getValueOrUndefined(entity._position, time, cachedPosition)
orientation = Property.getValueOrUndefined(entity._orientation, time, cachedOrientation)
show = defined(position) && defined(orientation)
}
if (!show) {
// don't bother creating or updating anything else
if (defined(data)) {
data.primitive.show = false
}
continue
}
var primitive = defined(data) ? data.primitive : undefined
if (!defined(primitive)) {
primitive = new RectangularPyramidSensorVolume()
primitive.id = entity
primitives.add(primitive)
data = {
primitive: primitive,
position: undefined,
orientation: undefined
}
hash[entity.id] = data
}
if (!Cartesian3.equals(position, data.position) || !Quaternion.equals(orientation, data.orientation)) {
Matrix4.fromRotationTranslation(Matrix3.fromQuaternion(orientation, matrix3Scratch), position, primitive.modelMatrix)
data.position = Cartesian3.clone(position, data.position)
data.orientation = Quaternion.clone(orientation, data.orientation)
}
primitive.show = true
primitive.xHalfAngle = Property.getValueOrDefault(rectangularSensorGraphics._xHalfAngle, time, CesiumMath.PI_OVER_TWO)
primitive.yHalfAngle = Property.getValueOrDefault(rectangularSensorGraphics._yHalfAngle, time, CesiumMath.PI_OVER_TWO)
primitive.radius = Property.getValueOrDefault(rectangularSensorGraphics._radius, time, defaultRadius)
primitive.lateralSurfaceMaterial = MaterialProperty.getValue(
time,
rectangularSensorGraphics._lateralSurfaceMaterial,
primitive.lateralSurfaceMaterial
)
primitive.intersectionColor = Property.getValueOrClonedDefault(
rectangularSensorGraphics._intersectionColor,
time,
defaultIntersectionColor,
primitive.intersectionColor
)
primitive.intersectionWidth = Property.getValueOrDefault(rectangularSensorGraphics._intersectionWidth, time, defaultIntersectionWidth)
}
return true
}
/**
* Returns true if this object was destroyed; otherwise, false.
*
* @returns {Boolean} True if this object was destroyed; otherwise, false.
*/
RectangularSensorVisualizer.prototype.isDestroyed = function () {
return false
}
/**
* Removes and destroys all primitives created by this instance.
*/
RectangularSensorVisualizer.prototype.destroy = function () {
var entities = this._entitiesToVisualize.values
var hash = this._hash
var primitives = this._primitives
for (var i = entities.length - 1; i > -1; i--) {
removePrimitive(entities[i], hash, primitives)
}
return destroyObject(this)
}
/**
* @private
*/
RectangularSensorVisualizer.prototype._onCollectionChanged = function (entityCollection, added, removed, changed) {
var i
var entity
var entities = this._entitiesToVisualize
var hash = this._hash
var primitives = this._primitives
for (i = added.length - 1; i > -1; i--) {
entity = added[i]
if (defined(entity._rectangularSensorVoumes) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
}
}
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i]
if (defined(entity._rectangularSensorVoumes) && defined(entity._position) && defined(entity._orientation)) {
entities.set(entity.id, entity)
} else {
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
for (i = removed.length - 1; i > -1; i--) {
entity = removed[i]
removePrimitive(entity, hash, primitives)
entities.remove(entity.id)
}
}
return RectangularSensorVisualizer
})
define("initialize", [
"require",
"Cesium/Core/Cartesian3",
"Cesium/Core/Color",
"Cesium/Core/defined",
"Cesium/Core/Spherical",
"Cesium/Core/TimeInterval",
"Cesium/DataSources/CzmlDataSource",
"Cesium/DataSources/DataSourceDisplay",
"./conic/conic-sensor-graphics",
"./conic/conic-sensor-visualizer",
"./custom/custom-pattern-sensor-graphics",
"./custom/custom-pattern-sensor-visualizer",
"./rectangular/rectangular-sensor-graphics",
"./rectangular/rectangular-sensor-visualizer"
], function (require) {
"use strict"
var Cartesian3 = require("Cesium/Core/Cartesian3")
var Color = require("Cesium/Core/Color")
var defined = require("Cesium/Core/defined")
var Spherical = require("Cesium/Core/Spherical")
var TimeInterval = require("Cesium/Core/TimeInterval")
var CzmlDataSource = require("Cesium/DataSources/CzmlDataSource")
var DataSourceDisplay = require("Cesium/DataSources/DataSourceDisplay")
var ConicSensorGraphics = require("./conic/conic-sensor-graphics")
var ConicSensorVisualizer = require("./conic/conic-sensor-visualizer")
var CustomPatternSensorGraphics = require("./custom/custom-pattern-sensor-graphics")
var CustomPatternSensorVisualizer = require("./custom/custom-pattern-sensor-visualizer")
var RectangularSensorGraphics = require("./rectangular/rectangular-sensor-graphics")
var RectangularSensorVisualizer = require("./rectangular/rectangular-sensor-visualizer")
var processPacketData = CzmlDataSource.processPacketData
var processMaterialPacketData = CzmlDataSource.processMaterialPacketData
function processDirectionData(customPatternSensor, directions, interval, sourceUri, entityCollection) {
var i
var len
var values = []
var unitSphericals = directions.unitSpherical
var sphericals = directions.spherical
var unitCartesians = directions.unitCartesian
var cartesians = directions.cartesian
if (defined(unitSphericals)) {
for (i = 0, len = unitSphericals.length; i < len; i += 2) {
values.push(new Spherical(unitSphericals[i], unitSphericals[i + 1]))
}
directions.array = values
} else if (defined(sphericals)) {
for (i = 0, len = sphericals.length; i < len; i += 3) {
values.push(new Spherical(sphericals[i], sphericals[i + 1], sphericals[i + 2]))
}
directions.array = values
} else if (defined(unitCartesians)) {
for (i = 0, len = unitCartesians.length; i < len; i += 3) {
var tmp = Spherical.fromCartesian3(new Cartesian3(unitCartesians[i], unitCartesians[i + 1], unitCartesians[i + 2]))
Spherical.normalize(tmp, tmp)
values.push(tmp)
}
directions.array = values
} else if (defined(cartesians)) {
for (i = 0, len = cartesians.length; i < len; i += 3) {
values.push(Spherical.fromCartesian3(new Cartesian3(cartesians[i], cartesians[i + 1], cartesians[i + 2])))
}
directions.array = values
}
processPacketData(Array, customPatternSensor, "directions", directions, interval, sourceUri, entityCollection)
}
function processCommonSensorProperties(sensor, sensorData, interval, sourceUri, entityCollection) {
processPacketData(Boolean, sensor, "show", sensorData.show, interval, sourceUri, entityCollection)
processPacketData(Number, sensor, "radius", sensorData.radius, interval, sourceUri, entityCollection)
processPacketData(Boolean, sensor, "showIntersection", sensorData.showIntersection, interval, sourceUri, entityCollection)
processPacketData(Color, sensor, "intersectionColor", sensorData.intersectionColor, interval, sourceUri, entityCollection)
processPacketData(Number, sensor, "intersectionWidth", sensorData.intersectionWidth, interval, sourceUri, entityCollection)
processMaterialPacketData(sensor, "lateralSurfaceMaterial", sensorData.lateralSurfaceMaterial, interval, sourceUri, entityCollection)
}
var iso8601Scratch = {
iso8601: undefined
}
function processConicSensor(entity, packet, entityCollection, sourceUri) {
var conicSensorData = packet.agi_conicSensor
if (!defined(conicSensorData)) {
return
}
var interval
var intervalString = conicSensorData.interval
if (defined(intervalString)) {
iso8601Scratch.iso8601 = intervalString
interval = TimeInterval.fromIso8601(iso8601Scratch)
}
var conicSensor = entity.conicSensor
if (!defined(conicSensor)) {
entity.addProperty("conicSensor")
conicSensor = new ConicSensorGraphics()
entity.conicSensor = conicSensor
}
processCommonSensorProperties(conicSensor, conicSensorData, interval, sourceUri, entityCollection)
processPacketData(Number, conicSensor, "innerHalfAngle", conicSensorData.innerHalfAngle, interval, sourceUri, entityCollection)
processPacketData(Number, conicSensor, "outerHalfAngle", conicSensorData.outerHalfAngle, interval, sourceUri, entityCollection)
processPacketData(Number, conicSensor, "minimumClockAngle", conicSensorData.minimumClockAngle, interval, sourceUri, entityCollection)
processPacketData(Number, conicSensor, "maximumClockAngle", conicSensorData.maximumClockAngle, interval, sourceUri, entityCollection)
}
function processCustomPatternSensor(entity, packet, entityCollection, sourceUri) {
var customPatternSensorData = packet.agi_customPatternSensor
if (!defined(customPatternSensorData)) {
return
}
var interval
var intervalString = customPatternSensorData.interval
if (defined(intervalString)) {
iso8601Scratch.iso8601 = intervalString
interval = TimeInterval.fromIso8601(iso8601Scratch)
}
var customPatternSensor = entity.customPatternSensor
if (!defined(customPatternSensor)) {
entity.addProperty("customPatternSensor")
customPatternSensor = new CustomPatternSensorGraphics()
entity.customPatternSensor = customPatternSensor
}
processCommonSensorProperties(customPatternSensor, customPatternSensorData, interval, sourceUri, entityCollection)
// The directions property is a special case value that can be an array of unitSpherical or unit Cartesians.
// We pre-process this into Spherical instances and then process it like any other array.
var directions = customPatternSensorData.directions
if (defined(directions)) {
if (Array.isArray(directions)) {
var length = directions.length
for (var i = 0; i < length; i++) {
processDirectionData(customPatternSensor, directions[i], interval, sourceUri, entityCollection)
}
} else {
processDirectionData(customPatternSensor, directions, interval, sourceUri, entityCollection)
}
}
}
function processRectangularSensor(entity, packet, entityCollection, sourceUri) {
var rectangularSensorData = packet.agi_rectangularSensor
if (!defined(rectangularSensorData)) {
return
}
var interval
var intervalString = rectangularSensorData.interval
if (defined(intervalString)) {
iso8601Scratch.iso8601 = intervalString
interval = TimeInterval.fromIso8601(iso8601Scratch)
}
var rectangularSensorVoumes = entity.rectangularSensorVoumes
if (!defined(rectangularSensorVoumes)) {
entity.addProperty("rectangularSensorVoumes")
rectangularSensorVoumes = new RectangularSensorGraphics()
entity.rectangularSensorVoumes = rectangularSensorVoumes
}
processCommonSensorProperties(rectangularSensorVoumes, rectangularSensorData, interval, sourceUri, entityCollection)
processPacketData(Number, rectangularSensorVoumes, "xHalfAngle", rectangularSensorData.xHalfAngle, interval, sourceUri, entityCollection)
processPacketData(Number, rectangularSensorVoumes, "yHalfAngle", rectangularSensorData.yHalfAngle, interval, sourceUri, entityCollection)
}
var initialized = false
return function initialize() {
if (initialized) {
return
}
CzmlDataSource.updaters.push(processConicSensor, processCustomPatternSensor, processRectangularSensor)
var originalDefaultVisualizersCallback = DataSourceDisplay.defaultVisualizersCallback
DataSourceDisplay.defaultVisualizersCallback = function (scene, entityCluster, dataSource) {
var entities = dataSource.entities
var array = originalDefaultVisualizersCallback(scene, entityCluster, dataSource)
return array.concat([
new ConicSensorVisualizer(scene, entities),
new CustomPatternSensorVisualizer(scene, entities),
new RectangularSensorVisualizer(scene, entities)
])
}
initialized = true
}
})
define("cesium-sensor-volumes", [
"require",
"./initialize",
"./conic/conic-sensor-graphics",
"./conic/conic-sensor-visualizer",
"./custom/custom-pattern-sensor-graphics",
"./custom/custom-pattern-sensor-visualizer",
"./custom/custom-sensor-volume",
"./rectangular/rectangular-pyramid-sensor-volume",
"./rectangular/rectangular-sensor-graphics",
"./rectangular/rectangular-sensor-visualizer"
], function (require) {
"use strict"
var initialize = require("./initialize")
var ConicSensorGraphics = require("./conic/conic-sensor-graphics")
var ConicSensorVisualizer = require("./conic/conic-sensor-visualizer")
var CustomPatternSensorGraphics = require("./custom/custom-pattern-sensor-graphics")
var CustomPatternSensorVisualizer = require("./custom/custom-pattern-sensor-visualizer")
var CustomSensorVolume = require("./custom/custom-sensor-volume")
var RectangularPyramidSensorVolume = require("./rectangular/rectangular-pyramid-sensor-volume")
var RectangularSensorGraphics = require("./rectangular/rectangular-sensor-graphics")
var RectangularSensorVisualizer = require("./rectangular/rectangular-sensor-visualizer")
initialize()
return {
ConicSensorGraphics: ConicSensorGraphics,
ConicSensorVisualizer: ConicSensorVisualizer,
CustomPatternSensorGraphics: CustomPatternSensorGraphics,
CustomPatternSensorVisualizer: CustomPatternSensorVisualizer,
CustomSensorVolume: CustomSensorVolume,
RectangularPyramidSensorVolume: RectangularPyramidSensorVolume,
RectangularSensorGraphics: RectangularSensorGraphics,
RectangularSensorVisualizer: RectangularSensorVisualizer
}
})
;("use strict")
/* global Cesium */
define("Cesium/Core/Cartesian3", function () {
return Cesium["Cartesian3"]
})
define("Cesium/Core/Color", function () {
return Cesium["Color"]
})
define("Cesium/Core/defined", function () {
return Cesium["defined"]
})
define("Cesium/Core/Spherical", function () {
return Cesium["Spherical"]
})
define("Cesium/Core/TimeInterval", function () {
return Cesium["TimeInterval"]
})
define("Cesium/DataSources/CzmlDataSource", function () {
return Cesium["CzmlDataSource"]
})
define("Cesium/DataSources/DataSourceDisplay", function () {
return Cesium["DataSourceDisplay"]
})
define("Cesium/Core/defaultValue", function () {
return Cesium["defaultValue"]
})
define("Cesium/Core/DeveloperError", function () {
return Cesium["DeveloperError"]
})
define("Cesium/Core/Event", function () {
return Cesium["Event"]
})
define("Cesium/DataSources/createMaterialPropertyDescriptor", function () {
return Cesium["createMaterialPropertyDescriptor"]
})
define("Cesium/DataSources/createPropertyDescriptor", function () {
return Cesium["createPropertyDescriptor"]
})
define("Cesium/Core/AssociativeArray", function () {
return Cesium["AssociativeArray"]
})
define("Cesium/Core/destroyObject", function () {
return Cesium["destroyObject"]
})
define("Cesium/Core/Math", function () {
return Cesium["Math"]
})
define("Cesium/Core/Matrix3", function () {
return Cesium["Matrix3"]
})
define("Cesium/Core/Matrix4", function () {
return Cesium["Matrix4"]
})
define("Cesium/Core/Quaternion", function () {
return Cesium["Quaternion"]
})
define("Cesium/DataSources/MaterialProperty", function () {
return Cesium["MaterialProperty"]
})
define("Cesium/DataSources/Property", function () {
return Cesium["Property"]
})
define("Cesium/Core/BoundingSphere", function () {
return Cesium["BoundingSphere"]
})
define("Cesium/Core/combine", function () {
return Cesium["combine"]
})
define("Cesium/Core/ComponentDatatype", function () {
return Cesium["ComponentDatatype"]
})
define("Cesium/Core/PrimitiveType", function () {
return Cesium["PrimitiveType"]
})
define("Cesium/Renderer/Buffer", function () {
return Cesium["Buffer"]
})
define("Cesium/Renderer/BufferUsage", function () {
return Cesium["BufferUsage"]
})
define("Cesium/Renderer/DrawCommand", function () {
return Cesium["DrawCommand"]
})
define("Cesium/Renderer/Pass", function () {
return Cesium["Pass"]
})
define("Cesium/Renderer/RenderState", function () {
return Cesium["RenderState"]
})
define("Cesium/Renderer/ShaderProgram", function () {
return Cesium["ShaderProgram"]
})
define("Cesium/Renderer/ShaderSource", function () {
return Cesium["ShaderSource"]
})
define("Cesium/Renderer/VertexArray", function () {
return Cesium["VertexArray"]
})
define("Cesium/Scene/BlendingState", function () {
return Cesium["BlendingState"]
})
define("Cesium/Scene/CullFace", function () {
return Cesium["CullFace"]
})
define("Cesium/Scene/Material", function () {
return Cesium["Material"]
})
define("Cesium/Scene/SceneMode", function () {
return Cesium["SceneMode"]
})
define("Cesium/Core/clone", function () {
return Cesium["clone"]
})
// eslint-disable-next-line import/no-dynamic-require
require(["cesium-sensor-volumes"], function (CesiumSensorVolumes) {
"use strict"
/* global window, self */
var scope
if (typeof window === "undefined") {
if (typeof self === "undefined") {
scope = {}
} else {
scope = self
}
} else {
scope = window
}
scope.CesiumSensorVolumes = CesiumSensorVolumes
}, undefined, true)
})()