ol-cesium
Version:
OpenLayers Cesium integration library
1,620 lines (1,412 loc) • 155 kB
JavaScript
/**
* Cesium - https://github.com/AnalyticalGraphicsInc/cesium
*
* Copyright 2011-2017 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.
*
* Columbus View (Pat. Pend.)
*
* Portions licensed separately.
* See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md for full licensing details.
*/
(function () {
define('Core/defined',[],function() {
'use strict';
/**
* @exports defined
*
* @param {*} value The object.
* @returns {Boolean} Returns true if the object is defined, returns false otherwise.
*
* @example
* if (Cesium.defined(positions)) {
* doSomething();
* } else {
* doSomethingElse();
* }
*/
function defined(value) {
return value !== undefined && value !== null;
}
return defined;
});
define('Core/freezeObject',[
'./defined'
], function(
defined) {
'use strict';
/**
* Freezes an object, using Object.freeze if available, otherwise returns
* the object unchanged. This function should be used in setup code to prevent
* errors from completely halting JavaScript execution in legacy browsers.
*
* @private
*
* @exports freezeObject
*/
var freezeObject = Object.freeze;
if (!defined(freezeObject)) {
freezeObject = function(o) {
return o;
};
}
return freezeObject;
});
define('Core/defaultValue',[
'./freezeObject'
], function(
freezeObject) {
'use strict';
/**
* Returns the first parameter if not undefined, otherwise the second parameter.
* Useful for setting a default value for a parameter.
*
* @exports defaultValue
*
* @param {*} a
* @param {*} b
* @returns {*} Returns the first parameter if not undefined, otherwise the second parameter.
*
* @example
* param = Cesium.defaultValue(param, 'default');
*/
function defaultValue(a, b) {
if (a !== undefined && a !== null) {
return a;
}
return b;
}
/**
* A frozen empty object that can be used as the default value for options passed as
* an object literal.
* @type {Object}
*/
defaultValue.EMPTY_OBJECT = freezeObject({});
return defaultValue;
});
define('Core/DeveloperError',[
'./defined'
], function(
defined) {
'use strict';
/**
* Constructs an exception object that is thrown due to a developer error, e.g., invalid argument,
* argument out of range, etc. This exception should only be thrown during development;
* it usually indicates a bug in the calling code. This exception should never be
* caught; instead the calling code should strive not to generate it.
* <br /><br />
* On the other hand, a {@link RuntimeError} indicates an exception that may
* be thrown at runtime, e.g., out of memory, that the calling code should be prepared
* to catch.
*
* @alias DeveloperError
* @constructor
* @extends Error
*
* @param {String} [message] The error message for this exception.
*
* @see RuntimeError
*/
function DeveloperError(message) {
/**
* 'DeveloperError' indicating that this exception was thrown due to a developer error.
* @type {String}
* @readonly
*/
this.name = 'DeveloperError';
/**
* The explanation for why this exception was thrown.
* @type {String}
* @readonly
*/
this.message = message;
//Browsers such as IE don't have a stack property until you actually throw the error.
var stack;
try {
throw new Error();
} catch (e) {
stack = e.stack;
}
/**
* The stack trace of this exception, if available.
* @type {String}
* @readonly
*/
this.stack = stack;
}
if (defined(Object.create)) {
DeveloperError.prototype = Object.create(Error.prototype);
DeveloperError.prototype.constructor = DeveloperError;
}
DeveloperError.prototype.toString = function() {
var str = this.name + ': ' + this.message;
if (defined(this.stack)) {
str += '\n' + this.stack.toString();
}
return str;
};
/**
* @private
*/
DeveloperError.throwInstantiationError = function() {
throw new DeveloperError('This function defines an interface and should not be called directly.');
};
return DeveloperError;
});
define('Core/defineProperties',[
'./defined'
], function(
defined) {
'use strict';
var definePropertyWorks = (function() {
try {
return 'x' in Object.defineProperty({}, 'x', {});
} catch (e) {
return false;
}
})();
/**
* Defines properties on an object, using Object.defineProperties if available,
* otherwise returns the object unchanged. This function should be used in
* setup code to prevent errors from completely halting JavaScript execution
* in legacy browsers.
*
* @private
*
* @exports defineProperties
*/
var defineProperties = Object.defineProperties;
if (!definePropertyWorks || !defined(defineProperties)) {
defineProperties = function(o) {
return o;
};
}
return defineProperties;
});
define('Core/Fullscreen',[
'./defined',
'./defineProperties'
], function(
defined,
defineProperties) {
'use strict';
var _supportsFullscreen;
var _names = {
requestFullscreen : undefined,
exitFullscreen : undefined,
fullscreenEnabled : undefined,
fullscreenElement : undefined,
fullscreenchange : undefined,
fullscreenerror : undefined
};
/**
* Browser-independent functions for working with the standard fullscreen API.
*
* @exports Fullscreen
* @namespace
*
* @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
*/
var Fullscreen = {};
defineProperties(Fullscreen, {
/**
* The element that is currently fullscreen, if any. To simply check if the
* browser is in fullscreen mode or not, use {@link Fullscreen#fullscreen}.
* @memberof Fullscreen
* @type {Object}
* @readonly
*/
element : {
get : function() {
if (!Fullscreen.supportsFullscreen()) {
return undefined;
}
return document[_names.fullscreenElement];
}
},
/**
* The name of the event on the document that is fired when fullscreen is
* entered or exited. This event name is intended for use with addEventListener.
* In your event handler, to determine if the browser is in fullscreen mode or not,
* use {@link Fullscreen#fullscreen}.
* @memberof Fullscreen
* @type {String}
* @readonly
*/
changeEventName : {
get : function() {
if (!Fullscreen.supportsFullscreen()) {
return undefined;
}
return _names.fullscreenchange;
}
},
/**
* The name of the event that is fired when a fullscreen error
* occurs. This event name is intended for use with addEventListener.
* @memberof Fullscreen
* @type {String}
* @readonly
*/
errorEventName : {
get : function() {
if (!Fullscreen.supportsFullscreen()) {
return undefined;
}
return _names.fullscreenerror;
}
},
/**
* Determine whether the browser will allow an element to be made fullscreen, or not.
* For example, by default, iframes cannot go fullscreen unless the containing page
* adds an "allowfullscreen" attribute (or prefixed equivalent).
* @memberof Fullscreen
* @type {Boolean}
* @readonly
*/
enabled : {
get : function() {
if (!Fullscreen.supportsFullscreen()) {
return undefined;
}
return document[_names.fullscreenEnabled];
}
},
/**
* Determines if the browser is currently in fullscreen mode.
* @memberof Fullscreen
* @type {Boolean}
* @readonly
*/
fullscreen : {
get : function() {
if (!Fullscreen.supportsFullscreen()) {
return undefined;
}
return Fullscreen.element !== null;
}
}
});
/**
* Detects whether the browser supports the standard fullscreen API.
*
* @returns {Boolean} <code>true</code> if the browser supports the standard fullscreen API,
* <code>false</code> otherwise.
*/
Fullscreen.supportsFullscreen = function() {
if (defined(_supportsFullscreen)) {
return _supportsFullscreen;
}
_supportsFullscreen = false;
var body = document.body;
if (typeof body.requestFullscreen === 'function') {
// go with the unprefixed, standard set of names
_names.requestFullscreen = 'requestFullscreen';
_names.exitFullscreen = 'exitFullscreen';
_names.fullscreenEnabled = 'fullscreenEnabled';
_names.fullscreenElement = 'fullscreenElement';
_names.fullscreenchange = 'fullscreenchange';
_names.fullscreenerror = 'fullscreenerror';
_supportsFullscreen = true;
return _supportsFullscreen;
}
//check for the correct combination of prefix plus the various names that browsers use
var prefixes = ['webkit', 'moz', 'o', 'ms', 'khtml'];
var name;
for (var i = 0, len = prefixes.length; i < len; ++i) {
var prefix = prefixes[i];
// casing of Fullscreen differs across browsers
name = prefix + 'RequestFullscreen';
if (typeof body[name] === 'function') {
_names.requestFullscreen = name;
_supportsFullscreen = true;
} else {
name = prefix + 'RequestFullScreen';
if (typeof body[name] === 'function') {
_names.requestFullscreen = name;
_supportsFullscreen = true;
}
}
// disagreement about whether it's "exit" as per spec, or "cancel"
name = prefix + 'ExitFullscreen';
if (typeof document[name] === 'function') {
_names.exitFullscreen = name;
} else {
name = prefix + 'CancelFullScreen';
if (typeof document[name] === 'function') {
_names.exitFullscreen = name;
}
}
// casing of Fullscreen differs across browsers
name = prefix + 'FullscreenEnabled';
if (document[name] !== undefined) {
_names.fullscreenEnabled = name;
} else {
name = prefix + 'FullScreenEnabled';
if (document[name] !== undefined) {
_names.fullscreenEnabled = name;
}
}
// casing of Fullscreen differs across browsers
name = prefix + 'FullscreenElement';
if (document[name] !== undefined) {
_names.fullscreenElement = name;
} else {
name = prefix + 'FullScreenElement';
if (document[name] !== undefined) {
_names.fullscreenElement = name;
}
}
// thankfully, event names are all lowercase per spec
name = prefix + 'fullscreenchange';
// event names do not have 'on' in the front, but the property on the document does
if (document['on' + name] !== undefined) {
//except on IE
if (prefix === 'ms') {
name = 'MSFullscreenChange';
}
_names.fullscreenchange = name;
}
name = prefix + 'fullscreenerror';
if (document['on' + name] !== undefined) {
//except on IE
if (prefix === 'ms') {
name = 'MSFullscreenError';
}
_names.fullscreenerror = name;
}
}
return _supportsFullscreen;
};
/**
* Asynchronously requests the browser to enter fullscreen mode on the given element.
* If fullscreen mode is not supported by the browser, does nothing.
*
* @param {Object} element The HTML element which will be placed into fullscreen mode.
* @param {HMDVRDevice} [vrDevice] The VR device.
*
* @example
* // Put the entire page into fullscreen.
* Cesium.Fullscreen.requestFullscreen(document.body)
*
* // Place only the Cesium canvas into fullscreen.
* Cesium.Fullscreen.requestFullscreen(scene.canvas)
*/
Fullscreen.requestFullscreen = function(element, vrDevice) {
if (!Fullscreen.supportsFullscreen()) {
return;
}
element[_names.requestFullscreen]({ vrDisplay: vrDevice });
};
/**
* Asynchronously exits fullscreen mode. If the browser is not currently
* in fullscreen, or if fullscreen mode is not supported by the browser, does nothing.
*/
Fullscreen.exitFullscreen = function() {
if (!Fullscreen.supportsFullscreen()) {
return;
}
document[_names.exitFullscreen]();
};
return Fullscreen;
});
/**
@license
when.js - https://github.com/cujojs/when
MIT License (c) copyright B Cavalier & J Hann
* A lightweight CommonJS Promises/A and when() implementation
* when is part of the cujo.js family of libraries (http://cujojs.com/)
*
* Licensed under the MIT License at:
* http://www.opensource.org/licenses/mit-license.php
*
* @version 1.7.1
*/
(function(define) { 'use strict';
define('ThirdParty/when',[],function () {
var reduceArray, slice, undef;
//
// Public API
//
when.defer = defer; // Create a deferred
when.resolve = resolve; // Create a resolved promise
when.reject = reject; // Create a rejected promise
when.join = join; // Join 2 or more promises
when.all = all; // Resolve a list of promises
when.map = map; // Array.map() for promises
when.reduce = reduce; // Array.reduce() for promises
when.any = any; // One-winner race
when.some = some; // Multi-winner race
when.chain = chain; // Make a promise trigger another resolver
when.isPromise = isPromise; // Determine if a thing is a promise
/**
* Register an observer for a promise or immediate value.
*
* @param {*} promiseOrValue
* @param {function?} [onFulfilled] callback to be called when promiseOrValue is
* successfully fulfilled. If promiseOrValue is an immediate value, callback
* will be invoked immediately.
* @param {function?} [onRejected] callback to be called when promiseOrValue is
* rejected.
* @param {function?} [onProgress] callback to be called when progress updates
* are issued for promiseOrValue.
* @returns {Promise} a new {@link Promise} that will complete with the return
* value of callback or errback or the completion value of promiseOrValue if
* callback and/or errback is not supplied.
*/
function when(promiseOrValue, onFulfilled, onRejected, onProgress) {
// Get a trusted promise for the input promiseOrValue, and then
// register promise handlers
return resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);
}
/**
* Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if
* promiseOrValue is a foreign promise, or a new, already-fulfilled {@link Promise}
* whose value is promiseOrValue if promiseOrValue is an immediate value.
*
* @param {*} promiseOrValue
* @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise}
* returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise}
* whose resolution value is:
* * the resolution value of promiseOrValue if it's a foreign promise, or
* * promiseOrValue if it's a value
*/
function resolve(promiseOrValue) {
var promise, deferred;
if(promiseOrValue instanceof Promise) {
// It's a when.js promise, so we trust it
promise = promiseOrValue;
} else {
// It's not a when.js promise. See if it's a foreign promise or a value.
if(isPromise(promiseOrValue)) {
// It's a thenable, but we don't know where it came from, so don't trust
// its implementation entirely. Introduce a trusted middleman when.js promise
deferred = defer();
// IMPORTANT: This is the only place when.js should ever call .then() on an
// untrusted promise. Don't expose the return value to the untrusted promise
promiseOrValue.then(
function(value) { deferred.resolve(value); },
function(reason) { deferred.reject(reason); },
function(update) { deferred.progress(update); }
);
promise = deferred.promise;
} else {
// It's a value, not a promise. Create a resolved promise for it.
promise = fulfilled(promiseOrValue);
}
}
return promise;
}
/**
* Returns a rejected promise for the supplied promiseOrValue. The returned
* promise will be rejected with:
* - promiseOrValue, if it is a value, or
* - if promiseOrValue is a promise
* - promiseOrValue's value after it is fulfilled
* - promiseOrValue's reason after it is rejected
* @param {*} promiseOrValue the rejected value of the returned {@link Promise}
* @returns {Promise} rejected {@link Promise}
*/
function reject(promiseOrValue) {
return when(promiseOrValue, rejected);
}
/**
* Trusted Promise constructor. A Promise created from this constructor is
* a trusted when.js promise. Any other duck-typed promise is considered
* untrusted.
* @constructor
* @name Promise
*/
function Promise(then) {
this.then = then;
}
Promise.prototype = {
/**
* Register a callback that will be called when a promise is
* fulfilled or rejected. Optionally also register a progress handler.
* Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress)
* @param {function?} [onFulfilledOrRejected]
* @param {function?} [onProgress]
* @returns {Promise}
*/
always: function(onFulfilledOrRejected, onProgress) {
return this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);
},
/**
* Register a rejection handler. Shortcut for .then(undefined, onRejected)
* @param {function?} onRejected
* @returns {Promise}
*/
otherwise: function(onRejected) {
return this.then(undef, onRejected);
},
/**
* Shortcut for .then(function() { return value; })
* @param {*} value
* @returns {Promise} a promise that:
* - is fulfilled if value is not a promise, or
* - if value is a promise, will fulfill with its value, or reject
* with its reason.
*/
yield: function(value) {
return this.then(function() {
return value;
});
},
/**
* Assumes that this promise will fulfill with an array, and arranges
* for the onFulfilled to be called with the array as its argument list
* i.e. onFulfilled.spread(undefined, array).
* @param {function} onFulfilled function to receive spread arguments
* @returns {Promise}
*/
spread: function(onFulfilled) {
return this.then(function(array) {
// array may contain promises, so resolve its contents.
return all(array, function(array) {
return onFulfilled.apply(undef, array);
});
});
}
};
/**
* Create an already-resolved promise for the supplied value
* @private
*
* @param {*} value
* @returns {Promise} fulfilled promise
*/
function fulfilled(value) {
var p = new Promise(function(onFulfilled) {
// TODO: Promises/A+ check typeof onFulfilled
try {
return resolve(onFulfilled ? onFulfilled(value) : value);
} catch(e) {
return rejected(e);
}
});
return p;
}
/**
* Create an already-rejected {@link Promise} with the supplied
* rejection reason.
* @private
*
* @param {*} reason
* @returns {Promise} rejected promise
*/
function rejected(reason) {
var p = new Promise(function(_, onRejected) {
// TODO: Promises/A+ check typeof onRejected
try {
return onRejected ? resolve(onRejected(reason)) : rejected(reason);
} catch(e) {
return rejected(e);
}
});
return p;
}
/**
* Creates a new, Deferred with fully isolated resolver and promise parts,
* either or both of which may be given out safely to consumers.
* The Deferred itself has the full API: resolve, reject, progress, and
* then. The resolver has resolve, reject, and progress. The promise
* only has then.
*
* @returns {Deferred}
*/
function defer() {
var deferred, promise, handlers, progressHandlers,
_then, _progress, _resolve;
/**
* The promise for the new deferred
* @type {Promise}
*/
promise = new Promise(then);
/**
* The full Deferred object, with {@link Promise} and {@link Resolver} parts
* @class Deferred
* @name Deferred
*/
deferred = {
then: then, // DEPRECATED: use deferred.promise.then
resolve: promiseResolve,
reject: promiseReject,
// TODO: Consider renaming progress() to notify()
progress: promiseProgress,
promise: promise,
resolver: {
resolve: promiseResolve,
reject: promiseReject,
progress: promiseProgress
}
};
handlers = [];
progressHandlers = [];
/**
* Pre-resolution then() that adds the supplied callback, errback, and progback
* functions to the registered listeners
* @private
*
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
*/
_then = function(onFulfilled, onRejected, onProgress) {
// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
var deferred, progressHandler;
deferred = defer();
progressHandler = typeof onProgress === 'function'
? function(update) {
try {
// Allow progress handler to transform progress event
deferred.progress(onProgress(update));
} catch(e) {
// Use caught value as progress
deferred.progress(e);
}
}
: function(update) { deferred.progress(update); };
handlers.push(function(promise) {
promise.then(onFulfilled, onRejected)
.then(deferred.resolve, deferred.reject, progressHandler);
});
progressHandlers.push(progressHandler);
return deferred.promise;
};
/**
* Issue a progress event, notifying all progress listeners
* @private
* @param {*} update progress event payload to pass to all listeners
*/
_progress = function(update) {
processQueue(progressHandlers, update);
return update;
};
/**
* Transition from pre-resolution state to post-resolution state, notifying
* all listeners of the resolution or rejection
* @private
* @param {*} value the value of this deferred
*/
_resolve = function(value) {
value = resolve(value);
// Replace _then with one that directly notifies with the result.
_then = value.then;
// Replace _resolve so that this Deferred can only be resolved once
_resolve = resolve;
// Make _progress a noop, to disallow progress for the resolved promise.
_progress = noop;
// Notify handlers
processQueue(handlers, value);
// Free progressHandlers array since we'll never issue progress events
progressHandlers = handlers = undef;
return value;
};
return deferred;
/**
* Wrapper to allow _then to be replaced safely
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} new promise
*/
function then(onFulfilled, onRejected, onProgress) {
// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress
return _then(onFulfilled, onRejected, onProgress);
}
/**
* Wrapper to allow _resolve to be replaced
*/
function promiseResolve(val) {
return _resolve(val);
}
/**
* Wrapper to allow _reject to be replaced
*/
function promiseReject(err) {
return _resolve(rejected(err));
}
/**
* Wrapper to allow _progress to be replaced
*/
function promiseProgress(update) {
return _progress(update);
}
}
/**
* Determines if promiseOrValue is a promise or not. Uses the feature
* test from http://wiki.commonjs.org/wiki/Promises/A to determine if
* promiseOrValue is a promise.
*
* @param {*} promiseOrValue anything
* @returns {boolean} true if promiseOrValue is a {@link Promise}
*/
function isPromise(promiseOrValue) {
return promiseOrValue && typeof promiseOrValue.then === 'function';
}
/**
* Initiates a competitive race, returning a promise that will resolve when
* howMany of the supplied promisesOrValues have resolved, or will reject when
* it becomes impossible for howMany to resolve, for example, when
* (promisesOrValues.length - howMany) + 1 input promises reject.
*
* @param {Array} promisesOrValues array of anything, may contain a mix
* of promises and values
* @param howMany {number} number of promisesOrValues to resolve
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} promise that will resolve to an array of howMany values that
* resolved first, or will reject with an array of (promisesOrValues.length - howMany) + 1
* rejection reasons.
*/
function some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {
checkCallbacks(2, arguments);
return when(promisesOrValues, function(promisesOrValues) {
var toResolve, toReject, values, reasons, deferred, fulfillOne, rejectOne, progress, len, i;
len = promisesOrValues.length >>> 0;
toResolve = Math.max(0, Math.min(howMany, len));
values = [];
toReject = (len - toResolve) + 1;
reasons = [];
deferred = defer();
// No items in the input, resolve immediately
if (!toResolve) {
deferred.resolve(values);
} else {
progress = deferred.progress;
rejectOne = function(reason) {
reasons.push(reason);
if(!--toReject) {
fulfillOne = rejectOne = noop;
deferred.reject(reasons);
}
};
fulfillOne = function(val) {
// This orders the values based on promise resolution order
// Another strategy would be to use the original position of
// the corresponding promise.
values.push(val);
if (!--toResolve) {
fulfillOne = rejectOne = noop;
deferred.resolve(values);
}
};
for(i = 0; i < len; ++i) {
if(i in promisesOrValues) {
when(promisesOrValues[i], fulfiller, rejecter, progress);
}
}
}
return deferred.then(onFulfilled, onRejected, onProgress);
function rejecter(reason) {
rejectOne(reason);
}
function fulfiller(val) {
fulfillOne(val);
}
});
}
/**
* Initiates a competitive race, returning a promise that will resolve when
* any one of the supplied promisesOrValues has resolved or will reject when
* *all* promisesOrValues have rejected.
*
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise} promise that will resolve to the value that resolved first, or
* will reject with an array of all rejected inputs.
*/
function any(promisesOrValues, onFulfilled, onRejected, onProgress) {
function unwrapSingleResult(val) {
return onFulfilled ? onFulfilled(val[0]) : val[0];
}
return some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);
}
/**
* Return a promise that will resolve only once all the supplied promisesOrValues
* have resolved. The resolution value of the returned promise will be an array
* containing the resolution values of each of the promisesOrValues.
* @memberOf when
*
* @param {Array|Promise} promisesOrValues array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function?} [onFulfilled] resolution handler
* @param {function?} [onRejected] rejection handler
* @param {function?} [onProgress] progress handler
* @returns {Promise}
*/
function all(promisesOrValues, onFulfilled, onRejected, onProgress) {
checkCallbacks(1, arguments);
return map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);
}
/**
* Joins multiple promises into a single returned promise.
* @returns {Promise} a promise that will fulfill when *all* the input promises
* have fulfilled, or will reject when *any one* of the input promises rejects.
*/
function join(/* ...promises */) {
return map(arguments, identity);
}
/**
* Traditional map function, similar to `Array.prototype.map()`, but allows
* input to contain {@link Promise}s and/or values, and mapFunc may return
* either a value or a {@link Promise}
*
* @param {Array|Promise} promise array of anything, may contain a mix
* of {@link Promise}s and values
* @param {function} mapFunc mapping function mapFunc(value) which may return
* either a {@link Promise} or value
* @returns {Promise} a {@link Promise} that will resolve to an array containing
* the mapped output values.
*/
function map(promise, mapFunc) {
return when(promise, function(array) {
var results, len, toResolve, resolve, i, d;
// Since we know the resulting length, we can preallocate the results
// array to avoid array expansions.
toResolve = len = array.length >>> 0;
results = [];
d = defer();
if(!toResolve) {
d.resolve(results);
} else {
resolve = function resolveOne(item, i) {
when(item, mapFunc).then(function(mapped) {
results[i] = mapped;
if(!--toResolve) {
d.resolve(results);
}
}, d.reject);
};
// Since mapFunc may be async, get all invocations of it into flight
for(i = 0; i < len; i++) {
if(i in array) {
resolve(array[i], i);
} else {
--toResolve;
}
}
}
return d.promise;
});
}
/**
* Traditional reduce function, similar to `Array.prototype.reduce()`, but
* input may contain promises and/or values, and reduceFunc
* may return either a value or a promise, *and* initialValue may
* be a promise for the starting value.
*
* @param {Array|Promise} promise array or promise for an array of anything,
* may contain a mix of promises and values.
* @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),
* where total is the total number of items being reduced, and will be the same
* in each call to reduceFunc.
* @returns {Promise} that will resolve to the final reduced value
*/
function reduce(promise, reduceFunc /*, initialValue */) {
var args = slice.call(arguments, 1);
return when(promise, function(array) {
var total;
total = array.length;
// Wrap the supplied reduceFunc with one that handles promises and then
// delegates to the supplied.
args[0] = function (current, val, i) {
return when(current, function (c) {
return when(val, function (value) {
return reduceFunc(c, value, i, total);
});
});
};
return reduceArray.apply(array, args);
});
}
/**
* Ensure that resolution of promiseOrValue will trigger resolver with the
* value or reason of promiseOrValue, or instead with resolveValue if it is provided.
*
* @param promiseOrValue
* @param {Object} resolver
* @param {function} resolver.resolve
* @param {function} resolver.reject
* @param {*} [resolveValue]
* @returns {Promise}
*/
function chain(promiseOrValue, resolver, resolveValue) {
var useResolveValue = arguments.length > 2;
return when(promiseOrValue,
function(val) {
val = useResolveValue ? resolveValue : val;
resolver.resolve(val);
return val;
},
function(reason) {
resolver.reject(reason);
return rejected(reason);
},
resolver.progress
);
}
//
// Utility functions
//
/**
* Apply all functions in queue to value
* @param {Array} queue array of functions to execute
* @param {*} value argument passed to each function
*/
function processQueue(queue, value) {
var handler, i = 0;
while (handler = queue[i++]) {
handler(value);
}
}
/**
* Helper that checks arrayOfCallbacks to ensure that each element is either
* a function, or null or undefined.
* @private
* @param {number} start index at which to start checking items in arrayOfCallbacks
* @param {Array} arrayOfCallbacks array to check
* @throws {Error} if any element of arrayOfCallbacks is something other than
* a functions, null, or undefined.
*/
function checkCallbacks(start, arrayOfCallbacks) {
// TODO: Promises/A+ update type checking and docs
var arg, i = arrayOfCallbacks.length;
while(i > start) {
arg = arrayOfCallbacks[--i];
if (arg != null && typeof arg != 'function') {
throw new Error('arg '+i+' must be a function');
}
}
}
/**
* No-Op function used in method replacement
* @private
*/
function noop() {}
slice = [].slice;
// ES5 reduce implementation if native not available
// See: http://es5.github.com/#x15.4.4.21 as there are many
// specifics and edge cases.
reduceArray = [].reduce ||
function(reduceFunc /*, initialValue */) {
/*jshint maxcomplexity: 7*/
// ES5 dictates that reduce.length === 1
// This implementation deviates from ES5 spec in the following ways:
// 1. It does not check if reduceFunc is a Callable
var arr, args, reduced, len, i;
i = 0;
// This generates a jshint warning, despite being valid
// "Missing 'new' prefix when invoking a constructor."
// See https://github.com/jshint/jshint/issues/392
arr = Object(this);
len = arr.length >>> 0;
args = arguments;
// If no initialValue, use first item of array (we know length !== 0 here)
// and adjust i to start at second item
if(args.length <= 1) {
// Skip to the first real element in the array
for(;;) {
if(i in arr) {
reduced = arr[i++];
break;
}
// If we reached the end of the array without finding any real
// elements, it's a TypeError
if(++i >= len) {
throw new TypeError();
}
}
} else {
// If initialValue provided, use it
reduced = args[1];
}
// Do the actual reduce
for(;i < len; ++i) {
// Skip holes
if(i in arr) {
reduced = reduceFunc(reduced, arr[i], i, arr);
}
}
return reduced;
};
function identity(x) {
return x;
}
return when;
});
})(typeof define == 'function' && define.amd
? define
: function (factory) { typeof exports === 'object'
? (module.exports = factory())
: (this.when = factory());
}
// Boilerplate for AMD, Node, and browser global
);
define('Core/FeatureDetection',[
'./defaultValue',
'./defined',
'./defineProperties',
'./DeveloperError',
'./Fullscreen',
'../ThirdParty/when'
], function(
defaultValue,
defined,
defineProperties,
DeveloperError,
Fullscreen,
when) {
'use strict';
/*global CanvasPixelArray*/
var theNavigator;
if (typeof navigator !== 'undefined') {
theNavigator = navigator;
} else {
theNavigator = {};
}
function extractVersion(versionString) {
var parts = versionString.split('.');
for (var i = 0, len = parts.length; i < len; ++i) {
parts[i] = parseInt(parts[i], 10);
}
return parts;
}
var isChromeResult;
var chromeVersionResult;
function isChrome() {
if (!defined(isChromeResult)) {
isChromeResult = false;
// Edge contains Chrome in the user agent too
if (!isEdge()) {
var fields = (/ Chrome\/([\.0-9]+)/).exec(theNavigator.userAgent);
if (fields !== null) {
isChromeResult = true;
chromeVersionResult = extractVersion(fields[1]);
}
}
}
return isChromeResult;
}
function chromeVersion() {
return isChrome() && chromeVersionResult;
}
var isSafariResult;
var safariVersionResult;
function isSafari() {
if (!defined(isSafariResult)) {
isSafariResult = false;
// Chrome and Edge contain Safari in the user agent too
if (!isChrome() && !isEdge() && (/ Safari\/[\.0-9]+/).test(theNavigator.userAgent)) {
var fields = (/ Version\/([\.0-9]+)/).exec(theNavigator.userAgent);
if (fields !== null) {
isSafariResult = true;
safariVersionResult = extractVersion(fields[1]);
}
}
}
return isSafariResult;
}
function safariVersion() {
return isSafari() && safariVersionResult;
}
var isWebkitResult;
var webkitVersionResult;
function isWebkit() {
if (!defined(isWebkitResult)) {
isWebkitResult = false;
var fields = (/ AppleWebKit\/([\.0-9]+)(\+?)/).exec(theNavigator.userAgent);
if (fields !== null) {
isWebkitResult = true;
webkitVersionResult = extractVersion(fields[1]);
webkitVersionResult.isNightly = !!fields[2];
}
}
return isWebkitResult;
}
function webkitVersion() {
return isWebkit() && webkitVersionResult;
}
var isInternetExplorerResult;
var internetExplorerVersionResult;
function isInternetExplorer() {
if (!defined(isInternetExplorerResult)) {
isInternetExplorerResult = false;
var fields;
if (theNavigator.appName === 'Microsoft Internet Explorer') {
fields = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
if (fields !== null) {
isInternetExplorerResult = true;
internetExplorerVersionResult = extractVersion(fields[1]);
}
} else if (theNavigator.appName === 'Netscape') {
fields = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
if (fields !== null) {
isInternetExplorerResult = true;
internetExplorerVersionResult = extractVersion(fields[1]);
}
}
}
return isInternetExplorerResult;
}
function internetExplorerVersion() {
return isInternetExplorer() && internetExplorerVersionResult;
}
var isEdgeResult;
var edgeVersionResult;
function isEdge() {
if (!defined(isEdgeResult)) {
isEdgeResult = false;
var fields = (/ Edge\/([\.0-9]+)/).exec(theNavigator.userAgent);
if (fields !== null) {
isEdgeResult = true;
edgeVersionResult = extractVersion(fields[1]);
}
}
return isEdgeResult;
}
function edgeVersion() {
return isEdge() && edgeVersionResult;
}
var isFirefoxResult;
var firefoxVersionResult;
function isFirefox() {
if (!defined(isFirefoxResult)) {
isFirefoxResult = false;
var fields = /Firefox\/([\.0-9]+)/.exec(theNavigator.userAgent);
if (fields !== null) {
isFirefoxResult = true;
firefoxVersionResult = extractVersion(fields[1]);
}
}
return isFirefoxResult;
}
var isWindowsResult;
function isWindows() {
if (!defined(isWindowsResult)) {
isWindowsResult = /Windows/i.test(theNavigator.appVersion);
}
return isWindowsResult;
}
function firefoxVersion() {
return isFirefox() && firefoxVersionResult;
}
var hasPointerEvents;
function supportsPointerEvents() {
if (!defined(hasPointerEvents)) {
//While navigator.pointerEnabled is deprecated in the W3C specification
//we still need to use it if it exists in order to support browsers
//that rely on it, such as the Windows WebBrowser control which defines
//PointerEvent but sets navigator.pointerEnabled to false.
//Firefox disabled because of https://github.com/AnalyticalGraphicsInc/cesium/issues/6372
hasPointerEvents = !isFirefox() && typeof PointerEvent !== 'undefined' && (!defined(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);
}
return hasPointerEvents;
}
var imageRenderingValueResult;
var supportsImageRenderingPixelatedResult;
function supportsImageRenderingPixelated() {
if (!defined(supportsImageRenderingPixelatedResult)) {
var canvas = document.createElement('canvas');
canvas.setAttribute('style',
'image-rendering: -moz-crisp-edges;' +
'image-rendering: pixelated;');
//canvas.style.imageRendering will be undefined, null or an empty string on unsupported browsers.
var tmp = canvas.style.imageRendering;
supportsImageRenderingPixelatedResult = defined(tmp) && tmp !== '';
if (supportsImageRenderingPixelatedResult) {
imageRenderingValueResult = tmp;
}
}
return supportsImageRenderingPixelatedResult;
}
function imageRenderingValue() {
return supportsImageRenderingPixelated() ? imageRenderingValueResult : undefined;
}
function supportsWebP() {
if (!supportsWebP.initialized) {
throw new DeveloperError('You must call FeatureDetection.supportsWebP.initialize and wait for the promise to resolve before calling FeatureDetection.supportsWebP');
}
return supportsWebP._result;
}
supportsWebP._promise = undefined;
supportsWebP._result = undefined;
supportsWebP.initialize = function() {
// From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp
if (defined(supportsWebP._promise)) {
return supportsWebP._promise;
}
var supportsWebPDeferred = when.defer();
supportsWebP._promise = supportsWebPDeferred.promise;
if (isEdge()) {
// Edge's WebP support with WebGL is incomplete.
// See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/
supportsWebP._result = false;
supportsWebPDeferred.resolve(supportsWebP._result);
return supportsWebPDeferred.promise;
}
var image = new Image();
image.onload = function () {
supportsWebP._result = (image.width > 0) && (image.height > 0);
supportsWebPDeferred.resolve(supportsWebP._result);
};
image.onerror = function () {
supportsWebP._result = false;
supportsWebPDeferred.resolve(supportsWebP._result);
};
image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
return supportsWebPDeferred.promise;
};
defineProperties(supportsWebP, {
initialized: {
get: function() {
return defined(supportsWebP._result);
}
}
});
var typedArrayTypes = [];
if (typeof ArrayBuffer !== 'undefined') {
typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
if (typeof Uint8ClampedArray !== 'undefined') {
typedArrayTypes.push(Uint8ClampedArray);
}
if (typeof CanvasPixelArray !== 'undefined') {
typedArrayTypes.push(CanvasPixelArray);
}
}
/**
* A set of functions to detect whether the current browser supports
* various features.
*
* @exports FeatureDetection
*/
var FeatureDetection = {
isChrome : isChrome,
chromeVersion : chromeVersion,
isSafari : isSafari,
safariVersion : safariVersion,
isWebkit : isWebkit,
webkitVersion : webkitVersion,
isInternetExplorer : isInternetExplorer,
internetExplorerVersion : internetExplorerVersion,
isEdge : isEdge,
edgeVersion : edgeVersion,
isFirefox : isFirefox,
firefoxVersion : firefoxVersion,
isWindows : isWindows,
hardwareConcurrency : defaultValue(theNavigator.hardwareConcurrency, 3),
supportsPointerEvents : supportsPointerEvents,
supportsImageRenderingPixelated: supportsImageRenderingPixelated,
supportsWebP: supportsWebP,
imageRenderingValue: imageRenderingValue,
typedArrayTypes: typedArrayTypes
};
/**
* Detects whether the current browser supports the full screen standard.
*
* @returns {Boolean} true if the browser supports the full screen standard, false if not.
*
* @see Fullscreen
* @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
*/
FeatureDetection.supportsFullscreen = function() {
return Fullscreen.supportsFullscreen();
};
/**
* Detects whether the current browser supports typed arrays.
*
* @returns {Boolean} true if the browser supports typed arrays, false if not.
*
* @see {@link http://www.khronos.org/registry/typedarray/specs/latest/|Typed Array Specification}
*/
FeatureDetection.supportsTypedArrays = function() {
return typeof ArrayBuffer !== 'undefined';
};
/**
* Detects whether the current browser supports Web Workers.
*
* @returns {Boolean} true if the browsers supports Web Workers, false if not.
*
* @see {@link http://www.w3.org/TR/workers/}
*/
FeatureDetection.supportsWebWorkers = function() {
return typeof Worker !== 'undefined';
};
/**
* Detects whether the current browser supports Web Assembly.
*
* @returns {Boolean} true if the browsers supports Web Assembly, false if not.
*
* @see {@link https://developer.mozilla.org/en-US/docs/WebAssembly}
*/
FeatureDetection.supportsWebAssembly = function() {
return typeof WebAssembly !== 'undefined' && !FeatureDetection.isEdge();
};
return FeatureDetection;
});
define('Core/WebGLConstants',[
'./freezeObject'
], function(
freezeObject) {
'use strict';
/**
* Enum containing WebGL Constant values by name.
* for use without an active WebGL context, or in cases where certain constants are unavailable using the WebGL context
* (For example, in [Safari 9]{@link https://github.com/AnalyticalGraphicsInc/cesium/issues/2989}).
*
* These match the constants from the [WebGL 1.0]{@link https://www.khronos.org/registry/webgl/specs/latest/1.0/}
* and [WebGL 2.0]{@link https://www.khronos.org/registry/webgl/specs/latest/2.0/}
* specifications.
*
* @exports WebGLConstants
*/
var WebGLConstants = {
DEPTH_BUFFER_BIT : 0x00000100,
STENCIL_BUFFER_BIT : 0x00000400,
COLOR_BUFFER_BIT : 0x00004000,
POINTS : 0x0000,
LINES : 0x0001,
LINE_LOOP : 0x0002,
LINE_STRIP : 0x0003,
TRIANGLES : 0x0004,
TRIANGLE_STRIP : 0x0005,
TRIANGLE_FAN : 0x0006,
ZERO : 0,
ONE : 1,
SRC_COLOR : 0x0300,
ONE_MINUS_SRC_COLOR : 0x0301,
SRC_ALPHA : 0x0302,
ONE_MINUS_SRC_ALPHA : 0x0303,
DST_ALPHA : 0x0304,
ONE_MINUS_DST_ALPHA : 0x0305,
DST_COLOR : 0x0306,
ONE_MINUS_DST_COLOR : 0x0307,
SRC_ALPHA_SATURATE : 0x0308,
FUNC_ADD : 0x8006,
BLEND_EQUATION : 0x8009,
BLEND_EQUATION_RGB : 0x8009, // same as BLEND_EQUATION
BLEND_EQUATION_ALPHA : 0x883D,
FUNC_SUBTRACT : 0x800A,
FUNC_REVERSE_SUBTRACT : 0x800B,
BLEND_DST_RGB : 0x80C8,
BLEND_SRC_RGB : 0x80C9,
BLEND_DST_ALPHA : 0x80CA,
BLEND_SRC_ALPHA : 0x80CB,
CONSTANT_COLOR : 0x8001,
ONE_MINUS_