UNPKG

ol-cesium

Version:

OpenLayers Cesium integration library

1,620 lines (1,412 loc) 155 kB
/** * 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_