text: /**
   * 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/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/Check',[
          './defined',
          './DeveloperError'
      ], function(
          defined,
          DeveloperError) {
      'use strict';
  
      /**
       * Contains functions for checking that supplied arguments are of a specified type
       * or meet specified conditions
       * @private
       */
      var Check = {};
  
      /**
       * Contains type checking functions, all using the typeof operator
       */
      Check.typeOf = {};
  
      function getUndefinedErrorMessage(name) {
          return name + ' is required, actual value was undefined';
      }
  
      function getFailedTypeErrorMessage(actual, expected, name) {
          return 'Expected ' + name + ' to be typeof ' + expected + ', actual typeof was ' + actual;
      }
  
      /**
       * Throws if test is not defined
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value that is to be checked
       * @exception {DeveloperError} test must be defined
       */
      Check.defined = function (name, test) {
          if (!defined(test)) {
              throw new DeveloperError(getUndefinedErrorMessage(name));
          }
      };
  
      /**
       * Throws if test is not typeof 'function'
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @exception {DeveloperError} test must be typeof 'function'
       */
      Check.typeOf.func = function (name, test) {
          if (typeof test !== 'function') {
              throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'function', name));
          }
      };
  
      /**
       * Throws if test is not typeof 'string'
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @exception {DeveloperError} test must be typeof 'string'
       */
      Check.typeOf.string = function (name, test) {
          if (typeof test !== 'string') {
              throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'string', name));
          }
      };
  
      /**
       * Throws if test is not typeof 'number'
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @exception {DeveloperError} test must be typeof 'number'
       */
      Check.typeOf.number = function (name, test) {
          if (typeof test !== 'number') {
              throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'number', name));
          }
      };
  
      /**
       * Throws if test is not typeof 'number' and less than limit
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @param {Number} limit The limit value to compare against
       * @exception {DeveloperError} test must be typeof 'number' and less than limit
       */
      Check.typeOf.number.lessThan = function (name, test, limit) {
          Check.typeOf.number(name, test);
          if (test >= limit) {
              throw new DeveloperError('Expected ' + name + ' to be less than ' + limit + ', actual value was ' + test);
          }
      };
  
      /**
       * Throws if test is not typeof 'number' and less than or equal to limit
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @param {Number} limit The limit value to compare against
       * @exception {DeveloperError} test must be typeof 'number' and less than or equal to limit
       */
      Check.typeOf.number.lessThanOrEquals = function (name, test, limit) {
          Check.typeOf.number(name, test);
          if (test > limit) {
              throw new DeveloperError('Expected ' + name + ' to be less than or equal to ' + limit + ', actual value was ' + test);
          }
      };
  
      /**
       * Throws if test is not typeof 'number' and greater than limit
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @param {Number} limit The limit value to compare against
       * @exception {DeveloperError} test must be typeof 'number' and greater than limit
       */
      Check.typeOf.number.greaterThan = function (name, test, limit) {
          Check.typeOf.number(name, test);
          if (test <= limit) {
              throw new DeveloperError('Expected ' + name + ' to be greater than ' + limit + ', actual value was ' + test);
          }
      };
  
      /**
       * Throws if test is not typeof 'number' and greater than or equal to limit
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @param {Number} limit The limit value to compare against
       * @exception {DeveloperError} test must be typeof 'number' and greater than or equal to limit
       */
      Check.typeOf.number.greaterThanOrEquals = function (name, test, limit) {
          Check.typeOf.number(name, test);
          if (test < limit) {
              throw new DeveloperError('Expected ' + name + ' to be greater than or equal to' + limit + ', actual value was ' + test);
          }
      };
  
      /**
       * Throws if test is not typeof 'object'
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @exception {DeveloperError} test must be typeof 'object'
       */
      Check.typeOf.object = function (name, test) {
          if (typeof test !== 'object') {
              throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'object', name));
          }
      };
  
      /**
       * Throws if test is not typeof 'boolean'
       *
       * @param {String} name The name of the variable being tested
       * @param {*} test The value to test
       * @exception {DeveloperError} test must be typeof 'boolean'
       */
      Check.typeOf.bool = function (name, test) {
          if (typeof test !== 'boolean') {
              throw new DeveloperError(getFailedTypeErrorMessage(typeof test, 'boolean', name));
          }
      };
  
      /**
       * Throws if test1 and test2 is not typeof 'number' and not equal in value
       *
       * @param {String} name1 The name of the first variable being tested
       * @param {String} name2 The name of the second variable being tested against
       * @param {*} test1 The value to test
       * @param {*} test2 The value to test against
       * @exception {DeveloperError} test1 and test2 should be type of 'number' and be equal in value
       */
      Check.typeOf.number.equals = function (name1, name2, test1, test2) {
          Check.typeOf.number(name1, test1);
          Check.typeOf.number(name2, test2);
          if (test1 !== test2) {
              throw new DeveloperError(name1 + ' must be equal to ' + name2 + ', the actual values are ' + test1 + ' and ' + test2);
          }
      };
  
      return Check;
  });
  
  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;
  });
  
  /*
    I've wrapped Makoto Matsumoto and Takuji Nishimura's code in a namespace
    so it's better encapsulated. Now you can have multiple random number generators
    and they won't stomp all over eachother's state.
  
    If you want to use this as a substitute for Math.random(), use the random()
    method like so:
  
    var m = new MersenneTwister();
    var randomNumber = m.random();
  
    You can also call the other genrand_{foo}() methods on the instance.
  
    If you want to use a specific seed in order to get a repeatable random
    sequence, pass an integer into the constructor:
  
    var m = new MersenneTwister(123);
  
    and that will always produce the same random sequence.
  
    Sean McCullough (banksean@gmail.com)
  */
  
  /*
     A C-program for MT19937, with initialization improved 2002/1/26.
     Coded by Takuji Nishimura and Makoto Matsumoto.
  
     Before using, initialize the state by using init_genrand(seed)
     or init_by_array(init_key, key_length).
  */
  /**
  @license
  mersenne-twister.js - https://gist.github.com/banksean/300494
  
     Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
     All rights reserved.
  
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
  
       1. Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
  
       2. Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
  
       3. The names of its contributors may not be used to endorse or promote
          products derived from this software without specific prior written
          permission.
  
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  /*
     Any feedback is very welcome.
     http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
     email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
  */
  define('ThirdParty/mersenne-twister',[],function() {
  var MersenneTwister = function(seed) {
    if (seed == undefined) {
      seed = new Date().getTime();
    }
    /* Period parameters */
    this.N = 624;
    this.M = 397;
    this.MATRIX_A = 0x9908b0df;   /* constant vector a */
    this.UPPER_MASK = 0x80000000; /* most significant w-r bits */
    this.LOWER_MASK = 0x7fffffff; /* least significant r bits */
  
    this.mt = new Array(this.N); /* the array for the state vector */
    this.mti=this.N+1; /* mti==N+1 means mt[N] is not initialized */
  
    this.init_genrand(seed);
  }
  
  /* initializes mt[N] with a seed */
  MersenneTwister.prototype.init_genrand = function(s) {
    this.mt[0] = s >>> 0;
    for (this.mti=1; this.mti<this.N; this.mti++) {
        var s = this.mt[this.mti-1] ^ (this.mt[this.mti-1] >>> 30);
     this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)
    + this.mti;
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array mt[].                        */
        /* 2002/01/09 modified by Makoto Matsumoto             */
        this.mt[this.mti] >>>= 0;
        /* for >32 bit machines */
    }
  }
  
  /* initialize by an array with array-length */
  /* init_key is the array for initializing keys */
  /* key_length is its length */
  /* slight change for C++, 2004/2/26 */
  //MersenneTwister.prototype.init_by_array = function(init_key, key_length) {
  //  var i, j, k;
  //  this.init_genrand(19650218);
  //  i=1; j=0;
  //  k = (this.N>key_length ? this.N : key_length);
  //  for (; k; k--) {
  //    var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30)
  //    this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525)))
  //      + init_key[j] + j; /* non linear */
  //    this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
  //    i++; j++;
  //    if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }
  //    if (j>=key_length) j=0;
  //  }
  //  for (k=this.N-1; k; k--) {
  //    var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30);
  //    this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941))
  //      - i; /* non linear */
  //    this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */
  //    i++;
  //    if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }
  //  }
  //
  //  this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */
  //}
  
  /* generates a random number on [0,0xffffffff]-interval */
  MersenneTwister.prototype.genrand_int32 = function() {
    var y;
    var mag01 = new Array(0x0, this.MATRIX_A);
    /* mag01[x] = x * MATRIX_A  for x=0,1 */
  
    if (this.mti >= this.N) { /* generate N words at one time */
      var kk;
  
      if (this.mti == this.N+1)   /* if init_genrand() has not been called, */
        this.init_genrand(5489); /* a default initial seed is used */
  
      for (kk=0;kk<this.N-this.M;kk++) {
        y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk+1]&this.LOWER_MASK);
        this.mt[kk] = this.mt[kk+this.M] ^ (y >>> 1) ^ mag01[y & 0x1];
      }
      for (;kk<this.N-1;kk++) {
        y = (this.mt[kk]&this.UPPER_MASK)|(this.mt[kk+1]&this.LOWER_MASK);
        this.mt[kk] = this.mt[kk+(this.M-this.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
      }
      y = (this.mt[this.N-1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK);
      this.mt[this.N-1] = this.mt[this.M-1] ^ (y >>> 1) ^ mag01[y & 0x1];
  
      this.mti = 0;
    }
  
    y = this.mt[this.mti++];
  
    /* Tempering */
    y ^= (y >>> 11);
    y ^= (y << 7) & 0x9d2c5680;
    y ^= (y << 15) & 0xefc60000;
    y ^= (y >>> 18);
  
    return y >>> 0;
  }
  
  /* generates a random number on [0,0x7fffffff]-interval */
  //MersenneTwister.prototype.genrand_int31 = function() {
  //  return (this.genrand_int32()>>>1);
  //}
  
  /* generates a random number on [0,1]-real-interval */
  //MersenneTwister.prototype.genrand_real1 = function() {
  //  return this.genrand_int32()*(1.0/4294967295.0);
  //  /* divided by 2^32-1 */
  //}
  
  /* generates a random number on [0,1)-real-interval */
  MersenneTwister.prototype.random = function() {
    return this.genrand_int32()*(1.0/4294967296.0);
    /* divided by 2^32 */
  }
  
  /* generates a random number on (0,1)-real-interval */
  //MersenneTwister.prototype.genrand_real3 = function() {
  //  return (this.genrand_int32() + 0.5)*(1.0/4294967296.0);
  //  /* divided by 2^32 */
  //}
  
  /* generates a random number on [0,1) with 53-bit resolution*/
  //MersenneTwister.prototype.genrand_res53 = function() {
  //  var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6;
  //  return(a*67108864.0+b)*(1.0/9007199254740992.0);
  //}
  
  /* These real versions are due to Isaku Wada, 2002/01/09 added */
  
  return MersenneTwister;
  });
  
  define('Core/Math',[
          '../ThirdParty/mersenne-twister',
          './Check',
          './defaultValue',
          './defined',
          './DeveloperError'
      ], function(
          MersenneTwister,
          Check,
          defaultValue,
          defined,
          DeveloperError) {
      'use strict';
  
      /**
       * Math functions.
       *
       * @exports CesiumMath
       * @alias Math
       */
      var CesiumMath = {};
  
      /**
       * 0.1
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON1 = 0.1;
  
      /**
       * 0.01
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON2 = 0.01;
  
      /**
       * 0.001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON3 = 0.001;
  
      /**
       * 0.0001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON4 = 0.0001;
  
      /**
       * 0.00001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON5 = 0.00001;
  
      /**
       * 0.000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON6 = 0.000001;
  
      /**
       * 0.0000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON7 = 0.0000001;
  
      /**
       * 0.00000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON8 = 0.00000001;
  
      /**
       * 0.000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON9 = 0.000000001;
  
      /**
       * 0.0000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON10 = 0.0000000001;
  
      /**
       * 0.00000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON11 = 0.00000000001;
  
      /**
       * 0.000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON12 = 0.000000000001;
  
      /**
       * 0.0000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON13 = 0.0000000000001;
  
      /**
       * 0.00000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON14 = 0.00000000000001;
  
      /**
       * 0.000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON15 = 0.000000000000001;
  
      /**
       * 0.0000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON16 = 0.0000000000000001;
  
      /**
       * 0.00000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON17 = 0.00000000000000001;
  
      /**
       * 0.000000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON18 = 0.000000000000000001;
  
      /**
       * 0.0000000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON19 = 0.0000000000000000001;
  
      /**
       * 0.00000000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON20 = 0.00000000000000000001;
  
      /**
       * 0.000000000000000000001
       * @type {Number}
       * @constant
       */
      CesiumMath.EPSILON21 = 0.000000000000000000001;
  
      /**
       * The gravitational parameter of the Earth in meters cubed
       * per second squared as defined by the WGS84 model: 3.986004418e14
       * @type {Number}
       * @constant
       */
      CesiumMath.GRAVITATIONALPARAMETER = 3.986004418e14;
  
      /**
       * Radius of the sun in meters: 6.955e8
       * @type {Number}
       * @constant
       */
      CesiumMath.SOLAR_RADIUS = 6.955e8;
  
      /**
       * The mean radius of the moon, according to the "Report of the IAU/IAG Working Group on
       * Cartographic Coordinates and Rotational Elements of the Planets and satellites: 2000",
       * Celestial Mechanics 82: 83-110, 2002.
       * @type {Number}
       * @constant
       */
      CesiumMath.LUNAR_RADIUS = 1737400.0;
  
      /**
       * 64 * 1024
       * @type {Number}
       * @constant
       */
      CesiumMath.SIXTY_FOUR_KILOBYTES = 64 * 1024;
  
      /**
       * Returns the sign of the value; 1 if the value is positive, -1 if the value is
       * negative, or 0 if the value is 0.
       *
       * @function
       * @param {Number} value The value to return the sign of.
       * @returns {Number} The sign of value.
       */
      CesiumMath.sign = defaultValue(Math.sign, function sign(value) {
          value = +value; // coerce to number
          if (value === 0 || value !== value) {
              // zero or NaN
              return value;
          }
          return value > 0 ? 1 : -1;
      });
  
      /**
       * Returns 1.0 if the given value is positive or zero, and -1.0 if it is negative.
       * This is similar to {@link CesiumMath#sign} except that returns 1.0 instead of
       * 0.0 when the input value is 0.0.
       * @param {Number} value The value to return the sign of.
       * @returns {Number} The sign of value.
       */
      CesiumMath.signNotZero = function(value) {
          return value < 0.0 ? -1.0 : 1.0;
      };
  
      /**
       * Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the range [0, rangeMax]
       * @param {Number} value The scalar value in the range [-1.0, 1.0]
       * @param {Number} [rangeMax=255] The maximum value in the mapped range, 255 by default.
       * @returns {Number} A SNORM value, where 0 maps to -1.0 and rangeMax maps to 1.0.
       *
       * @see CesiumMath.fromSNorm
       */
      CesiumMath.toSNorm = function(value, rangeMax) {
          rangeMax = defaultValue(rangeMax, 255);
          return Math.round((CesiumMath.clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMax);
      };
  
      /**
       * Converts a SNORM value in the range [0, rangeMax] to a scalar in the range [-1.0, 1.0].
       * @param {Number} value SNORM value in the range [0, 255]
       * @param {Number} [rangeMax=255] The maximum value in the SNORM range, 255 by default.
       * @returns {Number} Scalar in the range [-1.0, 1.0].
       *
       * @see CesiumMath.toSNorm
       */
      CesiumMath.fromSNorm = function(value, rangeMax) {
          rangeMax = defaultValue(rangeMax, 255);
          return CesiumMath.clamp(value, 0.0, rangeMax) / rangeMax * 2.0 - 1.0;
      };
  
      /**
       * Returns the hyperbolic sine of a number.
       * The hyperbolic sine of <em>value</em> is defined to be
       * (<em>e<sup>x</sup>&nbsp;-&nbsp;e<sup>-x</sup></em>)/2.0
       * where <i>e</i> is Euler's number, approximately 2.71828183.
       *
       * <p>Special cases:
       *   <ul>
       *     <li>If the argument is NaN, then the result is NaN.</li>
       *
       *     <li>If the argument is infinite, then the result is an infinity
       *     with the same sign as the argument.</li>
       *
       *     <li>If the argument is zero, then the result is a zero with the
       *     same sign as the argument.</li>
       *   </ul>
       *</p>
       *
       * @function
       * @param {Number} value The number whose hyperbolic sine is to be returned.
       * @returns {Number} The hyperbolic sine of <code>value</code>.
       */
      CesiumMath.sinh = defaultValue(Math.sinh, function sinh(value) {
          return (Math.exp(value) - Math.exp(-value)) / 2.0;
      });
  
      /**
       * Returns the hyperbolic cosine of a number.
       * The hyperbolic cosine of <strong>value</strong> is defined to be
       * (<em>e<sup>x</sup>&nbsp;+&nbsp;e<sup>-x</sup></em>)/2.0
       * where <i>e</i> is Euler's number, approximately 2.71828183.
       *
       * <p>Special cases:
       *   <ul>
       *     <li>If the argument is NaN, then the result is NaN.</li>
       *
       *     <li>If the argument is infinite, then the result is positive infinity.</li>
       *
       *     <li>If the argument is zero, then the result is 1.0.</li>
       *   </ul>
       *</p>
       *
       * @function
       * @param {Number} value The number whose hyperbolic cosine is to be returned.
       * @returns {Number} The hyperbolic cosine of <code>value</code>.
       */
      CesiumMath.cosh = defaultValue(Math.cosh, function cosh(value) {
          return (Math.exp(value) + Math.exp(-value)) / 2.0;
      });
  
      /**
       * Computes the linear interpolation of two values.
       *
       * @param {Number} p The start value to interpolate.
       * @param {Number} q The end value to interpolate.
       * @param {Number} time The time of interpolation generally in the range <code>[0.0, 1.0]</code>.
       * @returns {Number} The linearly interpolated value.
       *
       * @example
       * var n = Cesium.Math.lerp(0.0, 2.0, 0.5); // returns 1.0
       */
      CesiumMath.lerp = function(p, q, time) {
          return ((1.0 - time) * p) + (time * q);
      };
  
      /**
       * pi
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.PI = Math.PI;
  
      /**
       * 1/pi
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.ONE_OVER_PI = 1.0 / Math.PI;
  
      /**
       * pi/2
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.PI_OVER_TWO = Math.PI / 2.0;
  
      /**
       * pi/3
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.PI_OVER_THREE = Math.PI / 3.0;
  
      /**
       * pi/4
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.PI_OVER_FOUR = Math.PI / 4.0;
  
      /**
       * pi/6
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.PI_OVER_SIX = Math.PI / 6.0;
  
      /**
       * 3pi/2
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.THREE_PI_OVER_TWO = 3.0 * Math.PI / 2.0;
  
      /**
       * 2pi
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.TWO_PI = 2.0 * Math.PI;
  
      /**
       * 1/2pi
       *
       * @type {Number}
       * @constant
       */
      CesiumMath.ONE_OVER_TWO_PI = 1.0 / (2.0 * Math.PI);
  
      /**
       * The number of radians in a degree.
       *
       * @type {Number}
       * @constant
       * @default Math.PI / 180.0
       */
      CesiumMath.RADIANS_PER_DEGREE = Math.PI / 180.0;
  
      /**
       * The number of degrees in a radian.
       *
       * @type {Number}
       * @constant
       * @default 180.0 / Math.PI
       */
      CesiumMath.DEGREES_PER_RADIAN = 180.0 / Math.PI;
  
      /**
       * The number of radians in an arc second.
       *
       * @type {Number}
       * @constant
       * @default {@link CesiumMath.RADIANS_PER_DEGREE} / 3600.0
       */
      CesiumMath.RADIANS_PER_ARCSECOND = CesiumMath.RADIANS_PER_DEGREE / 3600.0;
  
      /**
       * Converts degrees to radians.
       * @param {Number} degrees The angle to convert in degrees.
       * @returns {Number} The corresponding angle in radians.
       */
      CesiumMath.toRadians = function(degrees) {
                  if (!defined(degrees)) {
              throw new DeveloperError('degrees is required.');
          }
                  return degrees * CesiumMath.RADIANS_PER_DEGREE;
      };
  
      /**
       * Converts radians to degrees.
       * @param {Number} radians The angle to convert in radians.
       * @returns {Number} The corresponding angle in degrees.
       */
      CesiumMath.toDegrees = function(radians) {
                  if (!defined(radians)) {
              throw new DeveloperError('radians is required.');
          }
                  return radians * CesiumMath.DEGREES_PER_RADIAN;
      };
  
      /**
       * Converts a longitude value, in radians, to the range [<code>-Math.PI</code>, <code>Math.PI</code>).
       *
       * @param {Number} angle The longitude value, in radians, to convert to the range [<code>-Math.PI</code>, <code>Math.PI</code>).
       * @returns {Number} The equivalent longitude value in the range [<code>-Math.PI</code>, <code>Math.PI</code>).
       *
       * @example
       * // Convert 270 degrees to -90 degrees longitude
       * var longitude = Cesium.Math.convertLongitudeRange(Cesium.Math.toRadians(270.0));
       */
      CesiumMath.convertLongitudeRange = function(angle) {
                  if (!defined(angle)) {
              throw new DeveloperError('angle is required.');
          }
                  var twoPi = CesiumMath.TWO_PI;
  
          var simplified = angle - Math.floor(angle / twoPi) * twoPi;
  
          if (simplified < -Math.PI) {
              return simplified + twoPi;
          }
          if (simplified >= Math.PI) {
              return simplified - twoPi;
          }
  
          return simplified;
      };
  
      /**
       * Convenience function that clamps a latitude value, in radians, to the range [<code>-Math.PI/2</code>, <code>Math.PI/2</code>).
       * Useful for sanitizing data before use in objects requiring correct range.
       *
       * @param {Number} angle The latitude value, in radians, to clamp to the range [<code>-Math.PI/2</code>, <code>Math.PI/2</code>).
       * @returns {Number} The latitude value clamped to the range [<code>-Math.PI/2</code>, <code>Math.PI/2</code>).
       *
       * @example
       * // Clamp 108 degrees latitude to 90 degrees latitude
       * var latitude = Cesium.Math.clampToLatitudeRange(Cesium.Math.toRadians(108.0));
       */
      CesiumMath.clampToLatitudeRange = function(angle) {
                  if (!defined(angle)) {
              throw new DeveloperError('angle is required.');
          }
          
          return CesiumMath.clamp(angle, -1*CesiumMath.PI_OVER_TWO, CesiumMath.PI_OVER_TWO);
      };
  
      /**
       * Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle.
       *
       * @param {Number} angle in radians
       * @returns {Number} The angle in the range [<code>-CesiumMath.PI</code>, <code>CesiumMath.PI</code>].
       */
      CesiumMath.negativePiToPi = function(angle) {
                  if (!defined(angle)) {
              throw new DeveloperError('angle is required.');
          }
                  return CesiumMath.zeroToTwoPi(angle + CesiumMath.PI) - CesiumMath.PI;
      };
  
      /**
       * Produces an angle in the range 0 <= angle <= 2Pi which is equivalent to the provided angle.
       *
       * @param {Number} angle in radians
       * @returns {Number} The angle in the range [0, <code>CesiumMath.TWO_PI</code>].
       */
      CesiumMath.zeroToTwoPi = function(angle) {
                  if (!defined(angle)) {
              throw new DeveloperError('angle is required.');
          }
                  var mod = CesiumMath.mod(angle, CesiumMath.TWO_PI);
          if (Math.abs(mod) < CesiumMath.EPSILON14 && Math.abs(angle) > CesiumMath.EPSILON14) {
              return CesiumMath.TWO_PI;
          }
          return mod;
      };
  
      /**
       * The modulo operation that also works for negative dividends.
       *
       * @param {Number} m The dividend.
       * @param {Number} n The divisor.
       * @returns {Number} The remainder.
       */
      CesiumMath.mod = function(m, n) {
                  if (!defined(m)) {
              throw new DeveloperError('m is required.');
          }
          if (!defined(n)) {
              throw new DeveloperError('n is required.');
          }
                  return ((m % n) + n) % n;
      };
  
      /**
       * Determines if two values are equal using an absolute or relative tolerance test. This is useful
       * to avoid problems due to roundoff error when comparing floating-point values directly. The values are
       * first compared using an absolute tolerance test. If that fails, a relative tolerance test is performed.
       * Use this test if you are unsure of the magnitudes of left and right.
       *
       * @param {Number} left The first value to compare.
       * @param {Number} right The other value to compare.
       * @param {Number} relativeEpsilon The maximum inclusive delta between <code>left</code> and <code>right</code> for the relative tolerance test.
       * @param {Number} [absoluteEpsilon=relativeEpsilon] The maximum inclusive delta between <code>left</code> and <code>right</code> for the absolute tolerance test.
       * @returns {Boolean} <code>true</code> if the values are equal within the epsilon; otherwise, <code>false</code>.
       *
       * @example
       * var a = Cesium.Math.equalsEpsilon(0.0, 0.01, Cesium.Math.EPSILON2); // true
       * var b = Cesium.Math.equalsEpsilon(0.0, 0.1, Cesium.Math.EPSILON2);  // false
       * var c = Cesium.Math.equalsEpsilon(3699175.1634344, 3699175.2, Cesium.Math.EPSILON7); // true
       * var d = Cesium.Math.equalsEpsilon(3699175.1634344, 3699175.2, Cesium.Math.EPSILON9); // false
       */
      CesiumMath.equalsEpsilon = function(left, right, relativeEpsilon, absoluteEpsilon) {
                  if (!defined(left)) {
              throw new DeveloperError('left is required.');
          }
          if (!defined(right)) {
              throw new DeveloperError('right is required.');
          }
          if (!defined(relativeEpsilon)) {
              throw new DeveloperError('relativeEpsilon is required.');
          }
                  absoluteEpsilon = defaultValue(absoluteEpsilon, relativeEpsilon);
          var absDiff = Math.abs(left - right);
          return absDiff <= absoluteEpsilon || absDiff <= relativeEpsilon * Math.max(Math.abs(left), Math.abs(right));
      };
  
      var factorials = [1];
  
      /**
       * Computes the factorial of the provided number.
       *
       * @param {Number} n The number whose factorial is to be computed.
       * @returns {Number} The factorial of the provided number or undefined if the number is less than 0.
       *
       * @exception {DeveloperError} A number greater than or equal to 0 is required.
       *
       *
       * @example
       * //Compute 7!, which is equal to 5040
       * var computedFactorial = Cesium.Math.factorial(7);
       *
       * @see {@link http://en.wikipedia.org/wiki/Factorial|Factorial on Wikipedia}
       */
      CesiumMath.factorial = function(n) {
                  if (typeof n !== 'number' || n < 0) {
              throw new DeveloperError('A number greater than or equal to 0 is required.');
          }
          
          var length = factorials.length;
          if (n >= length) {
              var sum = factorials[length - 1];
              for (var i = length; i <= n; i++) {
                  factorials.push(sum * i);
              }
          }
          return factorials[n];
      };
  
      /**
       * Increments a number with a wrapping to a minimum value if the number exceeds the maximum value.
       *
       * @param {Number} [n] The number to be incremented.
       * @param {Number} [maximumValue] The maximum incremented value before rolling over to the minimum value.
       * @param {Number} [minimumValue=0.0] The number reset to after the maximum value has been exceeded.
       * @returns {Number} The incremented number.
       *
       * @exception {DeveloperError} Maximum value must be greater than minimum value.
       *
       * @example
       * var n = Cesium.Math.incrementWrap(5, 10, 0); // returns 6
       * var n = Cesium.Math.incrementWrap(10, 10, 0); // returns 0
       */
      CesiumMath.incrementWrap = function(n, maximumValue, minimumValue) {
          minimumValue = defaultValue(minimumValue, 0.0);
  
                  if (!defined(n)) {
              throw new DeveloperError('n is required.');
          }
          if (maximumValue <= minimumValue) {
              throw new DeveloperError('maximumValue must be greater than minimumValue.');
          }
          
          ++n;
          if (n > maximumValue) {
              n = minimumValue;
          }
          return n;
      };
  
      /**
       * Determines if a positive integer is a power of two.
       *
       * @param {Number} n The positive integer to test.
       * @returns {Boolean} <code>true</code> if the number if a power of two; otherwise, <code>false</code>.
       *
       * @exception {DeveloperError} A number greater than or equal to 0 is required.
       *
       * @example
       * var t = Cesium.Math.isPowerOfTwo(16); // true
       * var f = Cesium.Math.isPowerOfTwo(20); // false
       */
      CesiumMath.isPowerOfTwo = function(n) {
                  if (typeof n !== 'number' || n < 0) {
              throw new DeveloperError('A number greater than or equal to 0 is required.');
          }
          
          return (n !== 0) && ((n & (n - 1)) === 0);
      };
  
      /**
       * Computes the next power-of-two integer greater than or equal to the provided positive integer.
       *
       * @param {Number} n The positive integer to test.
       * @returns {Number} The next power-of-two integer.
       *
       * @exception {DeveloperError} A number greater than or equal to 0 is required.
       *
       * @example
       * var n = Cesium.Math.nextPowerOfTwo(29); // 32
       * var m = Cesium.Math.nextPowerOfTwo(32); // 32
       */
      CesiumMath.nextPowerOfTwo = function(n) {
                  if (typeof n !== 'number' || n < 0) {
              throw new DeveloperError('A number greater than or equal to 0 is required.');
          }
          
          // From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
          --n;
          n |= n >> 1;
          n |= n >> 2;
          n |= n >> 4;
          n |= n >> 8;
          n |= n >> 16;
          ++n;
  
          return n;
      };
  
      /**
       * Constraint a value to lie between two values.
       *
       * @param {Number} value The value to constrain.
       * @param {Number} min The minimum value.
       * @param {Number} max The maximum value.
       * @returns {Number} The value clamped so that min <= value <= max.
       */
      CesiumMath.clamp = function(value, min, max) {
                  if (!defined(value)) {
              throw new DeveloperError('value is required');
          }
          if (!defined(min)) {
              throw new DeveloperError('min is required.');
          }
          if (!defined(max)) {
              throw new DeveloperError('max is required.');
          }
                  return value < min ? min : value > max ? max : value;
      };
  
      var randomNumberGenerator = new MersenneTwister();
  
      /**
       * Sets the seed used by the random number generator
       * in {@link CesiumMath#nextRandomNumber}.
       *
       * @param {Number} seed An integer used as the seed.
       */
      CesiumMath.setRandomNumberSeed = function(seed) {
                  if (!defined(seed)) {
              throw new DeveloperError('seed is required.');
          }
          
          randomNumberGenerator = new MersenneTwister(seed);
      };
  
      /**
       * Generates a random floating point number in the range of [0.0, 1.0)
       * using a Mersenne twister.
       *
       * @returns {Number} A random number in the range of [0.0, 1.0).
       *
       * @see CesiumMath.setRandomNumberSeed
       * @see {@link http://en.wikipedia.org/wiki/Mersenne_twister|Mersenne twister on Wikipedia}
       */
      CesiumMath.nextRandomNumber = function() {
          return randomNumberGenerator.random();
      };
  
      /**
       * Generates a random number between two numbers.
       *
       * @param {Number} min The minimum value.
       * @param {Number} max The maximum value.
       * @returns {Number} A random number between the min and max.
       */
      CesiumMath.randomBetween = function(min, max) {
          return CesiumMath.nextRandomNumber() * (max - min) + min;
      };
  
      /**
       * Computes <code>Math.acos(value)</code>, but first clamps <code>value</code> to the range [-1.0, 1.0]
       * so that the function will never return NaN.
       *
       * @param {Number} value The value for which to compute acos.
       * @returns {Number} The acos of the value if the value is in the range [-1.0, 1.0], or the acos of -1.0 or 1.0,
       *          whichever is closer, if the value is outside the range.
       */
      CesiumMath.acosClamped = function(value) {
                  if (!defined(value)) {
              throw new DeveloperError('value is required.');
          }
                  return Math.acos(CesiumMath.clamp(value, -1.0, 1.0));
      };
  
      /**
       * Computes <code>Math.asin(value)</code>, but first clamps <code>value</code> to the range [-1.0, 1.0]
       * so that the function will never return NaN.
       *
       * @param {Number} value The value for which to compute asin.
       * @returns {Number} The asin of the value if the value is in the range [-1.0, 1.0], or the asin of -1.0 or 1.0,
       *          whichever is closer, if the value is outside the range.
       */
      CesiumMath.asinClamped = function(value) {
                  if (!defined(value)) {
              throw new DeveloperError('value is required.');
          }
                  return Math.asin(CesiumMath.clamp(value, -1.0, 1.0));
      };
  
      /**
       * Finds the chord length between two points given the circle's radius and the angle between the points.
       *
       * @param {Number} angle The angle between the two points.
       * @param {Number} radius The radius of the circle.
       * @returns {Number} The chord length.
       */
      CesiumMath.chordLength = function(angle, radius) {
                  if (!defined(angle)) {
              throw new DeveloperError('angle is required.');
          }
          if (!defined(radius)) {
              throw new DeveloperError('radius is required.');
          }
                  return 2.0 * radius * Math.sin(angle * 0.5);
      };
  
      /**
       * Finds the logarithm of a number to a base.
       *
       * @param {Number} number The number.
       * @param {Number} base The base.
       * @returns {Number} The result.
       */
      CesiumMath.logBase = function(number, base) {
                  if (!defined(number)) {
              throw new DeveloperError('number is required.');
          }
          if (!defined(base)) {
              throw new DeveloperError('base is required.');
          }
                  return Math.log(number) / Math.log(base);
      };
  
      /**
       * Finds the cube root of a number.
       * Returns NaN if <code>number</code> is not provided.
       *
       * @function
       * @param {Number} [number] The number.
       * @returns {Number} The result.
       */
      CesiumMath.cbrt = defaultValue(Math.cbrt, function cbrt(number) {
          var result = Math.pow(Math.abs(number), 1.0 / 3.0);
          return number < 0.0 ? -result : result;
      });
  
      /**
       * Finds the base 2 logarithm of a number.
       *
       * @function
       * @param {Number} number The number.
       * @returns {Number} The result.
       */
      CesiumMath.log2 = defaultValue(Math.log2, function log2(number) {
          return Math.log(number) * Math.LOG2E;
      });
  
      /**
       * @private
       */
      CesiumMath.fog = function(distanceToCamera, density) {
          var scalar = distanceToCamera * density;
          return 1.0 - Math.exp(-(scalar * scalar));
      };
  
      /**
       * Computes a fast approximation of Atan for input in the range [-1, 1].
       *
       * Based on Michal Drobot's approximation from ShaderFastLibs,
       * which in turn is based on "Efficient approximations for the arctangent function,"
       * Rajan, S. Sichun Wang Inkol, R. Joyal, A., May 2006.
       * Adapted from ShaderFastLibs under MIT License.
       *
       * @param {Number} x An input number in the range [-1, 1]
       * @returns {Number} An approximation of atan(x)
       */
      CesiumMath.fastApproximateAtan = function(x) {
                  Check.typeOf.number('x', x);
          
          return x * (-0.1784 * Math.abs(x) - 0.0663 * x * x + 1.0301);
      };
  
      /**
       * Computes a fast approximation of Atan2(x, y) for arbitrary input scalars.
       *
       * Range reduction math based on nvidia's cg reference implementation: http://developer.download.nvidia.com/cg/atan2.html
       *
       * @param {Number} x An input number that isn't zero if y is zero.
       * @param {Number} y An input number that isn't zero if x is zero.
       * @returns {Number} An approximation of atan2(x, y)
       */
      CesiumMath.fastApproximateAtan2 = function(x, y) {
                  Check.typeOf.number('x', x);
          Check.typeOf.number('y', y);
          
          // atan approximations are usually only reliable over [-1, 1]
          // So reduce the range by flipping whether x or y is on top based on which is bigger.
          var opposite;
          var adjacent;
          var t = Math.abs(x); // t used as swap and atan result.
          opposite = Math.abs(y);
          adjacent = Math.max(t, opposite);
          opposite = Math.min(t, opposite);
  
          var oppositeOverAdjacent = opposite / adjacent;
                  if (isNaN(oppositeOverAdjacent)) {
              throw new DeveloperError('either x or y must be nonzero');
          }
                  t = CesiumMath.fastApproximateAtan(oppositeOverAdjacent);
  
          // Undo range reduction
          t = Math.abs(y) > Math.abs(x) ? CesiumMath.PI_OVER_TWO - t : t;
          t = x < 0.0 ?  CesiumMath.PI - t : t;
          t = y < 0.0 ? -t : t;
          return t;
      };
  
      return CesiumMath;
  });
  
  define('Core/Cartesian2',[
          './Check',
          './defaultValue',
          './defined',
          './DeveloperError',
          './freezeObject',
          './Math'
      ], function(
          Check,
          defaultValue,
          defined,
          DeveloperError,
          freezeObject,
          CesiumMath) {
      'use strict';
  
      /**
       * A 2D Cartesian point.
       * @alias Cartesian2
       * @constructor
       *
       * @param {Number} [x=0.0] The X component.
       * @param {Number} [y=0.0] The Y component.
       *
       * @see Cartesian3
       * @see Cartesian4
       * @see Packable
       */
      function Cartesian2(x, y) {
          /**
           * The X component.
           * @type {Number}
           * @default 0.0
           */
          this.x = defaultValue(x, 0.0);
  
          /**
           * The Y component.
           * @type {Number}
           * @default 0.0
           */
          this.y = defaultValue(y, 0.0);
      }
  
      /**
       * Creates a Cartesian2 instance from x and y coordinates.
       *
       * @param {Number} x The x coordinate.
       * @param {Number} y The y coordinate.
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       */
      Cartesian2.fromElements = function(x, y, result) {
          if (!defined(result)) {
              return new Cartesian2(x, y);
          }
  
          result.x = x;
          result.y = y;
          return result;
      };
  
      /**
       * Duplicates a Cartesian2 instance.
       *
       * @param {Cartesian2} cartesian The Cartesian to duplicate.
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. (Returns undefined if cartesian is undefined)
       */
      Cartesian2.clone = function(cartesian, result) {
          if (!defined(cartesian)) {
              return undefined;
          }
          if (!defined(result)) {
              return new Cartesian2(cartesian.x, cartesian.y);
          }
  
          result.x = cartesian.x;
          result.y = cartesian.y;
          return result;
      };
  
      /**
       * Creates a Cartesian2 instance from an existing Cartesian3.  This simply takes the
       * x and y properties of the Cartesian3 and drops z.
       * @function
       *
       * @param {Cartesian3} cartesian The Cartesian3 instance to create a Cartesian2 instance from.
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       */
      Cartesian2.fromCartesian3 = Cartesian2.clone;
  
      /**
       * Creates a Cartesian2 instance from an existing Cartesian4.  This simply takes the
       * x and y properties of the Cartesian4 and drops z and w.
       * @function
       *
       * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian2 instance from.
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       */
      Cartesian2.fromCartesian4 = Cartesian2.clone;
  
      /**
       * The number of elements used to pack the object into an array.
       * @type {Number}
       */
      Cartesian2.packedLength = 2;
  
      /**
       * Stores the provided instance into the provided array.
       *
       * @param {Cartesian2} value The value to pack.
       * @param {Number[]} array The array to pack into.
       * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
       *
       * @returns {Number[]} The array that was packed into
       */
      Cartesian2.pack = function(value, array, startingIndex) {
                  Check.typeOf.object('value', value);
          Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          array[startingIndex++] = value.x;
          array[startingIndex] = value.y;
  
          return array;
      };
  
      /**
       * Retrieves an instance from a packed array.
       *
       * @param {Number[]} array The packed array.
       * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
       * @param {Cartesian2} [result] The object into which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       */
      Cartesian2.unpack = function(array, startingIndex, result) {
                  Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          if (!defined(result)) {
              result = new Cartesian2();
          }
          result.x = array[startingIndex++];
          result.y = array[startingIndex];
          return result;
      };
  
      /**
       * Flattens an array of Cartesian2s into and array of components.
       *
       * @param {Cartesian2[]} array The array of cartesians to pack.
       * @param {Number[]} result The array onto which to store the result.
       * @returns {Number[]} The packed array.
       */
      Cartesian2.packArray = function(array, result) {
                  Check.defined('array', array);
          
          var length = array.length;
          if (!defined(result)) {
              result = new Array(length * 2);
          } else {
              result.length = length * 2;
          }
  
          for (var i = 0; i < length; ++i) {
              Cartesian2.pack(array[i], result, i * 2);
          }
          return result;
      };
  
      /**
       * Unpacks an array of cartesian components into and array of Cartesian2s.
       *
       * @param {Number[]} array The array of components to unpack.
       * @param {Cartesian2[]} result The array onto which to store the result.
       * @returns {Cartesian2[]} The unpacked array.
       */
      Cartesian2.unpackArray = function(array, result) {
                  Check.defined('array', array);
          
          var length = array.length;
          if (!defined(result)) {
              result = new Array(length / 2);
          } else {
              result.length = length / 2;
          }
  
          for (var i = 0; i < length; i += 2) {
              var index = i / 2;
              result[index] = Cartesian2.unpack(array, i, result[index]);
          }
          return result;
      };
  
      /**
       * Creates a Cartesian2 from two consecutive elements in an array.
       * @function
       *
       * @param {Number[]} array The array whose two consecutive elements correspond to the x and y components, respectively.
       * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       *
       * @example
       * // Create a Cartesian2 with (1.0, 2.0)
       * var v = [1.0, 2.0];
       * var p = Cesium.Cartesian2.fromArray(v);
       *
       * // Create a Cartesian2 with (1.0, 2.0) using an offset into an array
       * var v2 = [0.0, 0.0, 1.0, 2.0];
       * var p2 = Cesium.Cartesian2.fromArray(v2, 2);
       */
      Cartesian2.fromArray = Cartesian2.unpack;
  
      /**
       * Computes the value of the maximum component for the supplied Cartesian.
       *
       * @param {Cartesian2} cartesian The cartesian to use.
       * @returns {Number} The value of the maximum component.
       */
      Cartesian2.maximumComponent = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return Math.max(cartesian.x, cartesian.y);
      };
  
      /**
       * Computes the value of the minimum component for the supplied Cartesian.
       *
       * @param {Cartesian2} cartesian The cartesian to use.
       * @returns {Number} The value of the minimum component.
       */
      Cartesian2.minimumComponent = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return Math.min(cartesian.x, cartesian.y);
      };
  
      /**
       * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.
       *
       * @param {Cartesian2} first A cartesian to compare.
       * @param {Cartesian2} second A cartesian to compare.
       * @param {Cartesian2} result The object into which to store the result.
       * @returns {Cartesian2} A cartesian with the minimum components.
       */
      Cartesian2.minimumByComponent = function(first, second, result) {
                  Check.typeOf.object('first', first);
          Check.typeOf.object('second', second);
          Check.typeOf.object('result', result);
          
          result.x = Math.min(first.x, second.x);
          result.y = Math.min(first.y, second.y);
  
          return result;
      };
  
      /**
       * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.
       *
       * @param {Cartesian2} first A cartesian to compare.
       * @param {Cartesian2} second A cartesian to compare.
       * @param {Cartesian2} result The object into which to store the result.
       * @returns {Cartesian2} A cartesian with the maximum components.
       */
      Cartesian2.maximumByComponent = function(first, second, result) {
                  Check.typeOf.object('first', first);
          Check.typeOf.object('second', second);
          Check.typeOf.object('result', result);
          
          result.x = Math.max(first.x, second.x);
          result.y = Math.max(first.y, second.y);
          return result;
      };
  
      /**
       * Computes the provided Cartesian's squared magnitude.
       *
       * @param {Cartesian2} cartesian The Cartesian instance whose squared magnitude is to be computed.
       * @returns {Number} The squared magnitude.
       */
      Cartesian2.magnitudeSquared = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return cartesian.x * cartesian.x + cartesian.y * cartesian.y;
      };
  
      /**
       * Computes the Cartesian's magnitude (length).
       *
       * @param {Cartesian2} cartesian The Cartesian instance whose magnitude is to be computed.
       * @returns {Number} The magnitude.
       */
      Cartesian2.magnitude = function(cartesian) {
          return Math.sqrt(Cartesian2.magnitudeSquared(cartesian));
      };
  
      var distanceScratch = new Cartesian2();
  
      /**
       * Computes the distance between two points.
       *
       * @param {Cartesian2} left The first point to compute the distance from.
       * @param {Cartesian2} right The second point to compute the distance to.
       * @returns {Number} The distance between two points.
       *
       * @example
       * // Returns 1.0
       * var d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(2.0, 0.0));
       */
      Cartesian2.distance = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian2.subtract(left, right, distanceScratch);
          return Cartesian2.magnitude(distanceScratch);
      };
  
      /**
       * Computes the squared distance between two points.  Comparing squared distances
       * using this function is more efficient than comparing distances using {@link Cartesian2#distance}.
       *
       * @param {Cartesian2} left The first point to compute the distance from.
       * @param {Cartesian2} right The second point to compute the distance to.
       * @returns {Number} The distance between two points.
       *
       * @example
       * // Returns 4.0, not 2.0
       * var d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(3.0, 0.0));
       */
      Cartesian2.distanceSquared = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian2.subtract(left, right, distanceScratch);
          return Cartesian2.magnitudeSquared(distanceScratch);
      };
  
      /**
       * Computes the normalized form of the supplied Cartesian.
       *
       * @param {Cartesian2} cartesian The Cartesian to be normalized.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.normalize = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          var magnitude = Cartesian2.magnitude(cartesian);
  
          result.x = cartesian.x / magnitude;
          result.y = cartesian.y / magnitude;
  
                  if (isNaN(result.x) || isNaN(result.y)) {
              throw new DeveloperError('normalized result is not a number');
          }
          
          return result;
      };
  
      /**
       * Computes the dot (scalar) product of two Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @returns {Number} The dot product.
       */
      Cartesian2.dot = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          return left.x * right.x + left.y * right.y;
      };
  
      /**
       * Computes the componentwise product of two Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.multiplyComponents = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x * right.x;
          result.y = left.y * right.y;
          return result;
      };
  
      /**
       * Computes the componentwise quotient of two Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.divideComponents = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x / right.x;
          result.y = left.y / right.y;
          return result;
      };
  
      /**
       * Computes the componentwise sum of two Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.add = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x + right.x;
          result.y = left.y + right.y;
          return result;
      };
  
      /**
       * Computes the componentwise difference of two Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.subtract = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x - right.x;
          result.y = left.y - right.y;
          return result;
      };
  
      /**
       * Multiplies the provided Cartesian componentwise by the provided scalar.
       *
       * @param {Cartesian2} cartesian The Cartesian to be scaled.
       * @param {Number} scalar The scalar to multiply with.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.multiplyByScalar = function(cartesian, scalar, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.number('scalar', scalar);
          Check.typeOf.object('result', result);
          
          result.x = cartesian.x * scalar;
          result.y = cartesian.y * scalar;
          return result;
      };
  
      /**
       * Divides the provided Cartesian componentwise by the provided scalar.
       *
       * @param {Cartesian2} cartesian The Cartesian to be divided.
       * @param {Number} scalar The scalar to divide by.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.divideByScalar = function(cartesian, scalar, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.number('scalar', scalar);
          Check.typeOf.object('result', result);
          
          result.x = cartesian.x / scalar;
          result.y = cartesian.y / scalar;
          return result;
      };
  
      /**
       * Negates the provided Cartesian.
       *
       * @param {Cartesian2} cartesian The Cartesian to be negated.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.negate = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          result.x = -cartesian.x;
          result.y = -cartesian.y;
          return result;
      };
  
      /**
       * Computes the absolute value of the provided Cartesian.
       *
       * @param {Cartesian2} cartesian The Cartesian whose absolute value is to be computed.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.abs = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          result.x = Math.abs(cartesian.x);
          result.y = Math.abs(cartesian.y);
          return result;
      };
  
      var lerpScratch = new Cartesian2();
      /**
       * Computes the linear interpolation or extrapolation at t using the provided cartesians.
       *
       * @param {Cartesian2} start The value corresponding to t at 0.0.
       * @param {Cartesian2} end The value corresponding to t at 1.0.
       * @param {Number} t The point along t at which to interpolate.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter.
       */
      Cartesian2.lerp = function(start, end, t, result) {
                  Check.typeOf.object('start', start);
          Check.typeOf.object('end', end);
          Check.typeOf.number('t', t);
          Check.typeOf.object('result', result);
          
          Cartesian2.multiplyByScalar(end, t, lerpScratch);
          result = Cartesian2.multiplyByScalar(start, 1.0 - t, result);
          return Cartesian2.add(lerpScratch, result, result);
      };
  
      var angleBetweenScratch = new Cartesian2();
      var angleBetweenScratch2 = new Cartesian2();
      /**
       * Returns the angle, in radians, between the provided Cartesians.
       *
       * @param {Cartesian2} left The first Cartesian.
       * @param {Cartesian2} right The second Cartesian.
       * @returns {Number} The angle between the Cartesians.
       */
      Cartesian2.angleBetween = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian2.normalize(left, angleBetweenScratch);
          Cartesian2.normalize(right, angleBetweenScratch2);
          return CesiumMath.acosClamped(Cartesian2.dot(angleBetweenScratch, angleBetweenScratch2));
      };
  
      var mostOrthogonalAxisScratch = new Cartesian2();
      /**
       * Returns the axis that is most orthogonal to the provided Cartesian.
       *
       * @param {Cartesian2} cartesian The Cartesian on which to find the most orthogonal axis.
       * @param {Cartesian2} result The object onto which to store the result.
       * @returns {Cartesian2} The most orthogonal axis.
       */
      Cartesian2.mostOrthogonalAxis = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          var f = Cartesian2.normalize(cartesian, mostOrthogonalAxisScratch);
          Cartesian2.abs(f, f);
  
          if (f.x <= f.y) {
              result = Cartesian2.clone(Cartesian2.UNIT_X, result);
          } else {
              result = Cartesian2.clone(Cartesian2.UNIT_Y, result);
          }
  
          return result;
      };
  
      /**
       * Compares the provided Cartesians componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartesian2} [left] The first Cartesian.
       * @param {Cartesian2} [right] The second Cartesian.
       * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
       */
      Cartesian2.equals = function(left, right) {
          return (left === right) ||
                 ((defined(left)) &&
                  (defined(right)) &&
                  (left.x === right.x) &&
                  (left.y === right.y));
      };
  
      /**
       * @private
       */
      Cartesian2.equalsArray = function(cartesian, array, offset) {
          return cartesian.x === array[offset] &&
                 cartesian.y === array[offset + 1];
      };
  
      /**
       * Compares the provided Cartesians componentwise and returns
       * <code>true</code> if they pass an absolute or relative tolerance test,
       * <code>false</code> otherwise.
       *
       * @param {Cartesian2} [left] The first Cartesian.
       * @param {Cartesian2} [right] The second Cartesian.
       * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
       * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
       * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartesian2.equalsEpsilon = function(left, right, relativeEpsilon, absoluteEpsilon) {
          return (left === right) ||
                 (defined(left) &&
                  defined(right) &&
                  CesiumMath.equalsEpsilon(left.x, right.x, relativeEpsilon, absoluteEpsilon) &&
                  CesiumMath.equalsEpsilon(left.y, right.y, relativeEpsilon, absoluteEpsilon));
      };
  
      /**
       * An immutable Cartesian2 instance initialized to (0.0, 0.0).
       *
       * @type {Cartesian2}
       * @constant
       */
      Cartesian2.ZERO = freezeObject(new Cartesian2(0.0, 0.0));
  
      /**
       * An immutable Cartesian2 instance initialized to (1.0, 0.0).
       *
       * @type {Cartesian2}
       * @constant
       */
      Cartesian2.UNIT_X = freezeObject(new Cartesian2(1.0, 0.0));
  
      /**
       * An immutable Cartesian2 instance initialized to (0.0, 1.0).
       *
       * @type {Cartesian2}
       * @constant
       */
      Cartesian2.UNIT_Y = freezeObject(new Cartesian2(0.0, 1.0));
  
      /**
       * Duplicates this Cartesian2 instance.
       *
       * @param {Cartesian2} [result] The object onto which to store the result.
       * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.
       */
      Cartesian2.prototype.clone = function(result) {
          return Cartesian2.clone(this, result);
      };
  
      /**
       * Compares this Cartesian against the provided Cartesian componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartesian2} [right] The right hand side Cartesian.
       * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
       */
      Cartesian2.prototype.equals = function(right) {
          return Cartesian2.equals(this, right);
      };
  
      /**
       * Compares this Cartesian against the provided Cartesian componentwise and returns
       * <code>true</code> if they pass an absolute or relative tolerance test,
       * <code>false</code> otherwise.
       *
       * @param {Cartesian2} [right] The right hand side Cartesian.
       * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
       * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
       * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartesian2.prototype.equalsEpsilon = function(right, relativeEpsilon, absoluteEpsilon) {
          return Cartesian2.equalsEpsilon(this, right, relativeEpsilon, absoluteEpsilon);
      };
  
      /**
       * Creates a string representing this Cartesian in the format '(x, y)'.
       *
       * @returns {String} A string representing the provided Cartesian in the format '(x, y)'.
       */
      Cartesian2.prototype.toString = function() {
          return '(' + this.x + ', ' + this.y + ')';
      };
  
      return Cartesian2;
  });
  
  define('Core/Cartesian3',[
          './Check',
          './defaultValue',
          './defined',
          './DeveloperError',
          './freezeObject',
          './Math'
      ], function(
          Check,
          defaultValue,
          defined,
          DeveloperError,
          freezeObject,
          CesiumMath) {
      'use strict';
  
      /**
       * A 3D Cartesian point.
       * @alias Cartesian3
       * @constructor
       *
       * @param {Number} [x=0.0] The X component.
       * @param {Number} [y=0.0] The Y component.
       * @param {Number} [z=0.0] The Z component.
       *
       * @see Cartesian2
       * @see Cartesian4
       * @see Packable
       */
      function Cartesian3(x, y, z) {
          /**
           * The X component.
           * @type {Number}
           * @default 0.0
           */
          this.x = defaultValue(x, 0.0);
  
          /**
           * The Y component.
           * @type {Number}
           * @default 0.0
           */
          this.y = defaultValue(y, 0.0);
  
          /**
           * The Z component.
           * @type {Number}
           * @default 0.0
           */
          this.z = defaultValue(z, 0.0);
      }
  
      /**
       * Converts the provided Spherical into Cartesian3 coordinates.
       *
       * @param {Spherical} spherical The Spherical to be converted to Cartesian3.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       */
      Cartesian3.fromSpherical = function(spherical, result) {
                  Check.typeOf.object('spherical', spherical);
          
          if (!defined(result)) {
              result = new Cartesian3();
          }
  
          var clock = spherical.clock;
          var cone = spherical.cone;
          var magnitude = defaultValue(spherical.magnitude, 1.0);
          var radial = magnitude * Math.sin(cone);
          result.x = radial * Math.cos(clock);
          result.y = radial * Math.sin(clock);
          result.z = magnitude * Math.cos(cone);
          return result;
      };
  
      /**
       * Creates a Cartesian3 instance from x, y and z coordinates.
       *
       * @param {Number} x The x coordinate.
       * @param {Number} y The y coordinate.
       * @param {Number} z The z coordinate.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       */
      Cartesian3.fromElements = function(x, y, z, result) {
          if (!defined(result)) {
              return new Cartesian3(x, y, z);
          }
  
          result.x = x;
          result.y = y;
          result.z = z;
          return result;
      };
  
      /**
       * Duplicates a Cartesian3 instance.
       *
       * @param {Cartesian3} cartesian The Cartesian to duplicate.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. (Returns undefined if cartesian is undefined)
       */
      Cartesian3.clone = function(cartesian, result) {
          if (!defined(cartesian)) {
              return undefined;
          }
          if (!defined(result)) {
              return new Cartesian3(cartesian.x, cartesian.y, cartesian.z);
          }
  
          result.x = cartesian.x;
          result.y = cartesian.y;
          result.z = cartesian.z;
          return result;
      };
  
      /**
       * Creates a Cartesian3 instance from an existing Cartesian4.  This simply takes the
       * x, y, and z properties of the Cartesian4 and drops w.
       * @function
       *
       * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian3 instance from.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       */
      Cartesian3.fromCartesian4 = Cartesian3.clone;
  
      /**
       * The number of elements used to pack the object into an array.
       * @type {Number}
       */
      Cartesian3.packedLength = 3;
  
      /**
       * Stores the provided instance into the provided array.
       *
       * @param {Cartesian3} value The value to pack.
       * @param {Number[]} array The array to pack into.
       * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
       *
       * @returns {Number[]} The array that was packed into
       */
      Cartesian3.pack = function(value, array, startingIndex) {
                  Check.typeOf.object('value', value);
          Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          array[startingIndex++] = value.x;
          array[startingIndex++] = value.y;
          array[startingIndex] = value.z;
  
          return array;
      };
  
      /**
       * Retrieves an instance from a packed array.
       *
       * @param {Number[]} array The packed array.
       * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
       * @param {Cartesian3} [result] The object into which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       */
      Cartesian3.unpack = function(array, startingIndex, result) {
                  Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          if (!defined(result)) {
              result = new Cartesian3();
          }
          result.x = array[startingIndex++];
          result.y = array[startingIndex++];
          result.z = array[startingIndex];
          return result;
      };
  
      /**
       * Flattens an array of Cartesian3s into an array of components.
       *
       * @param {Cartesian3[]} array The array of cartesians to pack.
       * @param {Number[]} result The array onto which to store the result.
       * @returns {Number[]} The packed array.
       */
      Cartesian3.packArray = function(array, result) {
                  Check.defined('array', array);
          
          var length = array.length;
          if (!defined(result)) {
              result = new Array(length * 3);
          } else {
              result.length = length * 3;
          }
  
          for (var i = 0; i < length; ++i) {
              Cartesian3.pack(array[i], result, i * 3);
          }
          return result;
      };
  
      /**
       * Unpacks an array of cartesian components into an array of Cartesian3s.
       *
       * @param {Number[]} array The array of components to unpack.
       * @param {Cartesian3[]} result The array onto which to store the result.
       * @returns {Cartesian3[]} The unpacked array.
       */
      Cartesian3.unpackArray = function(array, result) {
                  Check.defined('array', array);
          Check.typeOf.number.greaterThanOrEquals('array.length', array.length, 3);
          if (array.length % 3 !== 0) {
              throw new DeveloperError('array length must be a multiple of 3.');
          }
          
          var length = array.length;
          if (!defined(result)) {
              result = new Array(length / 3);
          } else {
              result.length = length / 3;
          }
  
          for (var i = 0; i < length; i += 3) {
              var index = i / 3;
              result[index] = Cartesian3.unpack(array, i, result[index]);
          }
          return result;
      };
  
      /**
       * Creates a Cartesian3 from three consecutive elements in an array.
       * @function
       *
       * @param {Number[]} array The array whose three consecutive elements correspond to the x, y, and z components, respectively.
       * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       *
       * @example
       * // Create a Cartesian3 with (1.0, 2.0, 3.0)
       * var v = [1.0, 2.0, 3.0];
       * var p = Cesium.Cartesian3.fromArray(v);
       *
       * // Create a Cartesian3 with (1.0, 2.0, 3.0) using an offset into an array
       * var v2 = [0.0, 0.0, 1.0, 2.0, 3.0];
       * var p2 = Cesium.Cartesian3.fromArray(v2, 2);
       */
      Cartesian3.fromArray = Cartesian3.unpack;
  
      /**
       * Computes the value of the maximum component for the supplied Cartesian.
       *
       * @param {Cartesian3} cartesian The cartesian to use.
       * @returns {Number} The value of the maximum component.
       */
      Cartesian3.maximumComponent = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return Math.max(cartesian.x, cartesian.y, cartesian.z);
      };
  
      /**
       * Computes the value of the minimum component for the supplied Cartesian.
       *
       * @param {Cartesian3} cartesian The cartesian to use.
       * @returns {Number} The value of the minimum component.
       */
      Cartesian3.minimumComponent = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return Math.min(cartesian.x, cartesian.y, cartesian.z);
      };
  
      /**
       * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.
       *
       * @param {Cartesian3} first A cartesian to compare.
       * @param {Cartesian3} second A cartesian to compare.
       * @param {Cartesian3} result The object into which to store the result.
       * @returns {Cartesian3} A cartesian with the minimum components.
       */
      Cartesian3.minimumByComponent = function(first, second, result) {
                  Check.typeOf.object('first', first);
          Check.typeOf.object('second', second);
          Check.typeOf.object('result', result);
          
          result.x = Math.min(first.x, second.x);
          result.y = Math.min(first.y, second.y);
          result.z = Math.min(first.z, second.z);
  
          return result;
      };
  
      /**
       * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.
       *
       * @param {Cartesian3} first A cartesian to compare.
       * @param {Cartesian3} second A cartesian to compare.
       * @param {Cartesian3} result The object into which to store the result.
       * @returns {Cartesian3} A cartesian with the maximum components.
       */
      Cartesian3.maximumByComponent = function(first, second, result) {
                  Check.typeOf.object('first', first);
          Check.typeOf.object('second', second);
          Check.typeOf.object('result', result);
          
          result.x = Math.max(first.x, second.x);
          result.y = Math.max(first.y, second.y);
          result.z = Math.max(first.z, second.z);
          return result;
      };
  
      /**
       * Computes the provided Cartesian's squared magnitude.
       *
       * @param {Cartesian3} cartesian The Cartesian instance whose squared magnitude is to be computed.
       * @returns {Number} The squared magnitude.
       */
      Cartesian3.magnitudeSquared = function(cartesian) {
                  Check.typeOf.object('cartesian', cartesian);
          
          return cartesian.x * cartesian.x + cartesian.y * cartesian.y + cartesian.z * cartesian.z;
      };
  
      /**
       * Computes the Cartesian's magnitude (length).
       *
       * @param {Cartesian3} cartesian The Cartesian instance whose magnitude is to be computed.
       * @returns {Number} The magnitude.
       */
      Cartesian3.magnitude = function(cartesian) {
          return Math.sqrt(Cartesian3.magnitudeSquared(cartesian));
      };
  
      var distanceScratch = new Cartesian3();
  
      /**
       * Computes the distance between two points.
       *
       * @param {Cartesian3} left The first point to compute the distance from.
       * @param {Cartesian3} right The second point to compute the distance to.
       * @returns {Number} The distance between two points.
       *
       * @example
       * // Returns 1.0
       * var d = Cesium.Cartesian3.distance(new Cesium.Cartesian3(1.0, 0.0, 0.0), new Cesium.Cartesian3(2.0, 0.0, 0.0));
       */
      Cartesian3.distance = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian3.subtract(left, right, distanceScratch);
          return Cartesian3.magnitude(distanceScratch);
      };
  
      /**
       * Computes the squared distance between two points.  Comparing squared distances
       * using this function is more efficient than comparing distances using {@link Cartesian3#distance}.
       *
       * @param {Cartesian3} left The first point to compute the distance from.
       * @param {Cartesian3} right The second point to compute the distance to.
       * @returns {Number} The distance between two points.
       *
       * @example
       * // Returns 4.0, not 2.0
       * var d = Cesium.Cartesian3.distanceSquared(new Cesium.Cartesian3(1.0, 0.0, 0.0), new Cesium.Cartesian3(3.0, 0.0, 0.0));
       */
      Cartesian3.distanceSquared = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian3.subtract(left, right, distanceScratch);
          return Cartesian3.magnitudeSquared(distanceScratch);
      };
  
      /**
       * Computes the normalized form of the supplied Cartesian.
       *
       * @param {Cartesian3} cartesian The Cartesian to be normalized.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.normalize = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          var magnitude = Cartesian3.magnitude(cartesian);
  
          result.x = cartesian.x / magnitude;
          result.y = cartesian.y / magnitude;
          result.z = cartesian.z / magnitude;
  
                  if (isNaN(result.x) || isNaN(result.y) || isNaN(result.z)) {
              throw new DeveloperError('normalized result is not a number');
          }
          
          return result;
      };
  
      /**
       * Computes the dot (scalar) product of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @returns {Number} The dot product.
       */
      Cartesian3.dot = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          return left.x * right.x + left.y * right.y + left.z * right.z;
      };
  
      /**
       * Computes the componentwise product of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.multiplyComponents = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x * right.x;
          result.y = left.y * right.y;
          result.z = left.z * right.z;
          return result;
      };
  
      /**
       * Computes the componentwise quotient of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.divideComponents = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x / right.x;
          result.y = left.y / right.y;
          result.z = left.z / right.z;
          return result;
      };
  
      /**
       * Computes the componentwise sum of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.add = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x + right.x;
          result.y = left.y + right.y;
          result.z = left.z + right.z;
          return result;
      };
  
      /**
       * Computes the componentwise difference of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.subtract = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = left.x - right.x;
          result.y = left.y - right.y;
          result.z = left.z - right.z;
          return result;
      };
  
      /**
       * Multiplies the provided Cartesian componentwise by the provided scalar.
       *
       * @param {Cartesian3} cartesian The Cartesian to be scaled.
       * @param {Number} scalar The scalar to multiply with.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.multiplyByScalar = function(cartesian, scalar, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.number('scalar', scalar);
          Check.typeOf.object('result', result);
          
          result.x = cartesian.x * scalar;
          result.y = cartesian.y * scalar;
          result.z = cartesian.z * scalar;
          return result;
      };
  
      /**
       * Divides the provided Cartesian componentwise by the provided scalar.
       *
       * @param {Cartesian3} cartesian The Cartesian to be divided.
       * @param {Number} scalar The scalar to divide by.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.divideByScalar = function(cartesian, scalar, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.number('scalar', scalar);
          Check.typeOf.object('result', result);
          
          result.x = cartesian.x / scalar;
          result.y = cartesian.y / scalar;
          result.z = cartesian.z / scalar;
          return result;
      };
  
      /**
       * Negates the provided Cartesian.
       *
       * @param {Cartesian3} cartesian The Cartesian to be negated.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.negate = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          result.x = -cartesian.x;
          result.y = -cartesian.y;
          result.z = -cartesian.z;
          return result;
      };
  
      /**
       * Computes the absolute value of the provided Cartesian.
       *
       * @param {Cartesian3} cartesian The Cartesian whose absolute value is to be computed.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.abs = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          result.x = Math.abs(cartesian.x);
          result.y = Math.abs(cartesian.y);
          result.z = Math.abs(cartesian.z);
          return result;
      };
  
      var lerpScratch = new Cartesian3();
      /**
       * Computes the linear interpolation or extrapolation at t using the provided cartesians.
       *
       * @param {Cartesian3} start The value corresponding to t at 0.0.
       * @param {Cartesian3} end The value corresponding to t at 1.0.
       * @param {Number} t The point along t at which to interpolate.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter.
       */
      Cartesian3.lerp = function(start, end, t, result) {
                  Check.typeOf.object('start', start);
          Check.typeOf.object('end', end);
          Check.typeOf.number('t', t);
          Check.typeOf.object('result', result);
          
          Cartesian3.multiplyByScalar(end, t, lerpScratch);
          result = Cartesian3.multiplyByScalar(start, 1.0 - t, result);
          return Cartesian3.add(lerpScratch, result, result);
      };
  
      var angleBetweenScratch = new Cartesian3();
      var angleBetweenScratch2 = new Cartesian3();
      /**
       * Returns the angle, in radians, between the provided Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @returns {Number} The angle between the Cartesians.
       */
      Cartesian3.angleBetween = function(left, right) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          
          Cartesian3.normalize(left, angleBetweenScratch);
          Cartesian3.normalize(right, angleBetweenScratch2);
          var cosine = Cartesian3.dot(angleBetweenScratch, angleBetweenScratch2);
          var sine = Cartesian3.magnitude(Cartesian3.cross(angleBetweenScratch, angleBetweenScratch2, angleBetweenScratch));
          return Math.atan2(sine, cosine);
      };
  
      var mostOrthogonalAxisScratch = new Cartesian3();
      /**
       * Returns the axis that is most orthogonal to the provided Cartesian.
       *
       * @param {Cartesian3} cartesian The Cartesian on which to find the most orthogonal axis.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The most orthogonal axis.
       */
      Cartesian3.mostOrthogonalAxis = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          Check.typeOf.object('result', result);
          
          var f = Cartesian3.normalize(cartesian, mostOrthogonalAxisScratch);
          Cartesian3.abs(f, f);
  
          if (f.x <= f.y) {
              if (f.x <= f.z) {
                  result = Cartesian3.clone(Cartesian3.UNIT_X, result);
              } else {
                  result = Cartesian3.clone(Cartesian3.UNIT_Z, result);
              }
          } else if (f.y <= f.z) {
              result = Cartesian3.clone(Cartesian3.UNIT_Y, result);
          } else {
              result = Cartesian3.clone(Cartesian3.UNIT_Z, result);
          }
  
          return result;
      };
  
      /**
       * Projects vector a onto vector b
       * @param {Cartesian3} a The vector that needs projecting
       * @param {Cartesian3} b The vector to project onto
       * @param {Cartesian3} result The result cartesian
       * @returns {Cartesian3} The modified result parameter
       */
      Cartesian3.projectVector = function(a, b, result) {
                  Check.defined('a', a);
          Check.defined('b', b);
          Check.defined('result', result);
          
          var scalar = Cartesian3.dot(a, b) / Cartesian3.dot(b, b);
          return Cartesian3.multiplyByScalar(b, scalar, result);
      };
  
      /**
       * Compares the provided Cartesians componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartesian3} [left] The first Cartesian.
       * @param {Cartesian3} [right] The second Cartesian.
       * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
       */
      Cartesian3.equals = function(left, right) {
              return (left === right) ||
                ((defined(left)) &&
                 (defined(right)) &&
                 (left.x === right.x) &&
                 (left.y === right.y) &&
                 (left.z === right.z));
      };
  
      /**
       * @private
       */
      Cartesian3.equalsArray = function(cartesian, array, offset) {
          return cartesian.x === array[offset] &&
                 cartesian.y === array[offset + 1] &&
                 cartesian.z === array[offset + 2];
      };
  
      /**
       * Compares the provided Cartesians componentwise and returns
       * <code>true</code> if they pass an absolute or relative tolerance test,
       * <code>false</code> otherwise.
       *
       * @param {Cartesian3} [left] The first Cartesian.
       * @param {Cartesian3} [right] The second Cartesian.
       * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
       * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
       * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartesian3.equalsEpsilon = function(left, right, relativeEpsilon, absoluteEpsilon) {
          return (left === right) ||
                 (defined(left) &&
                  defined(right) &&
                  CesiumMath.equalsEpsilon(left.x, right.x, relativeEpsilon, absoluteEpsilon) &&
                  CesiumMath.equalsEpsilon(left.y, right.y, relativeEpsilon, absoluteEpsilon) &&
                  CesiumMath.equalsEpsilon(left.z, right.z, relativeEpsilon, absoluteEpsilon));
      };
  
      /**
       * Computes the cross (outer) product of two Cartesians.
       *
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The cross product.
       */
      Cartesian3.cross = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          var leftX = left.x;
          var leftY = left.y;
          var leftZ = left.z;
          var rightX = right.x;
          var rightY = right.y;
          var rightZ = right.z;
  
          var x = leftY * rightZ - leftZ * rightY;
          var y = leftZ * rightX - leftX * rightZ;
          var z = leftX * rightY - leftY * rightX;
  
          result.x = x;
          result.y = y;
          result.z = z;
          return result;
      };
  
      /**
       * Computes the midpoint between the right and left Cartesian.
       * @param {Cartesian3} left The first Cartesian.
       * @param {Cartesian3} right The second Cartesian.
       * @param {Cartesian3} result The object onto which to store the result.
       * @returns {Cartesian3} The midpoint.
       */
      Cartesian3.midpoint = function(left, right, result) {
                  Check.typeOf.object('left', left);
          Check.typeOf.object('right', right);
          Check.typeOf.object('result', result);
          
          result.x = (left.x + right.x) * 0.5;
          result.y = (left.y + right.y) * 0.5;
          result.z = (left.z + right.z) * 0.5;
  
          return result;
      };
  
      /**
       * Returns a Cartesian3 position from longitude and latitude values given in degrees.
       *
       * @param {Number} longitude The longitude, in degrees
       * @param {Number} latitude The latitude, in degrees
       * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The position
       *
       * @example
       * var position = Cesium.Cartesian3.fromDegrees(-115.0, 37.0);
       */
      Cartesian3.fromDegrees = function(longitude, latitude, height, ellipsoid, result) {
                  Check.typeOf.number('longitude', longitude);
          Check.typeOf.number('latitude', latitude);
          
          longitude = CesiumMath.toRadians(longitude);
          latitude = CesiumMath.toRadians(latitude);
          return Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result);
      };
  
      var scratchN = new Cartesian3();
      var scratchK = new Cartesian3();
      var wgs84RadiiSquared = new Cartesian3(6378137.0 * 6378137.0, 6378137.0 * 6378137.0, 6356752.3142451793 * 6356752.3142451793);
  
      /**
       * Returns a Cartesian3 position from longitude and latitude values given in radians.
       *
       * @param {Number} longitude The longitude, in radians
       * @param {Number} latitude The latitude, in radians
       * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The position
       *
       * @example
       * var position = Cesium.Cartesian3.fromRadians(-2.007, 0.645);
       */
      Cartesian3.fromRadians = function(longitude, latitude, height, ellipsoid, result) {
                  Check.typeOf.number('longitude', longitude);
          Check.typeOf.number('latitude', latitude);
          
          height = defaultValue(height, 0.0);
          var radiiSquared = defined(ellipsoid) ? ellipsoid.radiiSquared : wgs84RadiiSquared;
  
          var cosLatitude = Math.cos(latitude);
          scratchN.x = cosLatitude * Math.cos(longitude);
          scratchN.y = cosLatitude * Math.sin(longitude);
          scratchN.z = Math.sin(latitude);
          scratchN = Cartesian3.normalize(scratchN, scratchN);
  
          Cartesian3.multiplyComponents(radiiSquared, scratchN, scratchK);
          var gamma = Math.sqrt(Cartesian3.dot(scratchN, scratchK));
          scratchK = Cartesian3.divideByScalar(scratchK, gamma, scratchK);
          scratchN = Cartesian3.multiplyByScalar(scratchN, height, scratchN);
  
          if (!defined(result)) {
              result = new Cartesian3();
          }
          return Cartesian3.add(scratchK, scratchN, result);
      };
  
      /**
       * Returns an array of Cartesian3 positions given an array of longitude and latitude values given in degrees.
       *
       * @param {Number[]} coordinates A list of longitude and latitude values. Values alternate [longitude, latitude, longitude, latitude...].
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the coordinates lie.
       * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.
       * @returns {Cartesian3[]} The array of positions.
       *
       * @example
       * var positions = Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0, -107.0, 33.0]);
       */
      Cartesian3.fromDegreesArray = function(coordinates, ellipsoid, result) {
                  Check.defined('coordinates', coordinates);
          if (coordinates.length < 2 || coordinates.length % 2 !== 0) {
              throw new DeveloperError('the number of coordinates must be a multiple of 2 and at least 2');
          }
          
          var length = coordinates.length;
          if (!defined(result)) {
              result = new Array(length / 2);
          } else {
              result.length = length / 2;
          }
  
          for (var i = 0; i < length; i += 2) {
              var longitude = coordinates[i];
              var latitude = coordinates[i + 1];
              var index = i / 2;
              result[index] = Cartesian3.fromDegrees(longitude, latitude, 0, ellipsoid, result[index]);
          }
  
          return result;
      };
  
      /**
       * Returns an array of Cartesian3 positions given an array of longitude and latitude values given in radians.
       *
       * @param {Number[]} coordinates A list of longitude and latitude values. Values alternate [longitude, latitude, longitude, latitude...].
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the coordinates lie.
       * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.
       * @returns {Cartesian3[]} The array of positions.
       *
       * @example
       * var positions = Cesium.Cartesian3.fromRadiansArray([-2.007, 0.645, -1.867, .575]);
       */
      Cartesian3.fromRadiansArray = function(coordinates, ellipsoid, result) {
                  Check.defined('coordinates', coordinates);
          if (coordinates.length < 2 || coordinates.length % 2 !== 0) {
              throw new DeveloperError('the number of coordinates must be a multiple of 2 and at least 2');
          }
          
          var length = coordinates.length;
          if (!defined(result)) {
              result = new Array(length / 2);
          } else {
              result.length = length / 2;
          }
  
          for (var i = 0; i < length; i += 2) {
              var longitude = coordinates[i];
              var latitude = coordinates[i + 1];
              var index = i / 2;
              result[index] = Cartesian3.fromRadians(longitude, latitude, 0, ellipsoid, result[index]);
          }
  
          return result;
      };
  
      /**
       * Returns an array of Cartesian3 positions given an array of longitude, latitude and height values where longitude and latitude are given in degrees.
       *
       * @param {Number[]} coordinates A list of longitude, latitude and height values. Values alternate [longitude, latitude, height, longitude, latitude, height...].
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.
       * @returns {Cartesian3[]} The array of positions.
       *
       * @example
       * var positions = Cesium.Cartesian3.fromDegreesArrayHeights([-115.0, 37.0, 100000.0, -107.0, 33.0, 150000.0]);
       */
      Cartesian3.fromDegreesArrayHeights = function(coordinates, ellipsoid, result) {
                  Check.defined('coordinates', coordinates);
          if (coordinates.length < 3 || coordinates.length % 3 !== 0) {
              throw new DeveloperError('the number of coordinates must be a multiple of 3 and at least 3');
          }
          
          var length = coordinates.length;
          if (!defined(result)) {
              result = new Array(length / 3);
          } else {
              result.length = length / 3;
          }
  
          for (var i = 0; i < length; i += 3) {
              var longitude = coordinates[i];
              var latitude = coordinates[i + 1];
              var height = coordinates[i + 2];
              var index = i / 3;
              result[index] = Cartesian3.fromDegrees(longitude, latitude, height, ellipsoid, result[index]);
          }
  
          return result;
      };
  
      /**
       * Returns an array of Cartesian3 positions given an array of longitude, latitude and height values where longitude and latitude are given in radians.
       *
       * @param {Number[]} coordinates A list of longitude, latitude and height values. Values alternate [longitude, latitude, height, longitude, latitude, height...].
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.
       * @returns {Cartesian3[]} The array of positions.
       *
       * @example
       * var positions = Cesium.Cartesian3.fromRadiansArrayHeights([-2.007, 0.645, 100000.0, -1.867, .575, 150000.0]);
       */
      Cartesian3.fromRadiansArrayHeights = function(coordinates, ellipsoid, result) {
                  Check.defined('coordinates', coordinates);
          if (coordinates.length < 3 || coordinates.length % 3 !== 0) {
              throw new DeveloperError('the number of coordinates must be a multiple of 3 and at least 3');
          }
          
          var length = coordinates.length;
          if (!defined(result)) {
              result = new Array(length / 3);
          } else {
              result.length = length / 3;
          }
  
          for (var i = 0; i < length; i += 3) {
              var longitude = coordinates[i];
              var latitude = coordinates[i + 1];
              var height = coordinates[i + 2];
              var index = i / 3;
              result[index] = Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result[index]);
          }
  
          return result;
      };
  
      /**
       * An immutable Cartesian3 instance initialized to (0.0, 0.0, 0.0).
       *
       * @type {Cartesian3}
       * @constant
       */
      Cartesian3.ZERO = freezeObject(new Cartesian3(0.0, 0.0, 0.0));
  
      /**
       * An immutable Cartesian3 instance initialized to (1.0, 0.0, 0.0).
       *
       * @type {Cartesian3}
       * @constant
       */
      Cartesian3.UNIT_X = freezeObject(new Cartesian3(1.0, 0.0, 0.0));
  
      /**
       * An immutable Cartesian3 instance initialized to (0.0, 1.0, 0.0).
       *
       * @type {Cartesian3}
       * @constant
       */
      Cartesian3.UNIT_Y = freezeObject(new Cartesian3(0.0, 1.0, 0.0));
  
      /**
       * An immutable Cartesian3 instance initialized to (0.0, 0.0, 1.0).
       *
       * @type {Cartesian3}
       * @constant
       */
      Cartesian3.UNIT_Z = freezeObject(new Cartesian3(0.0, 0.0, 1.0));
  
      /**
       * Duplicates this Cartesian3 instance.
       *
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.
       */
      Cartesian3.prototype.clone = function(result) {
          return Cartesian3.clone(this, result);
      };
  
      /**
       * Compares this Cartesian against the provided Cartesian componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartesian3} [right] The right hand side Cartesian.
       * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
       */
      Cartesian3.prototype.equals = function(right) {
          return Cartesian3.equals(this, right);
      };
  
      /**
       * Compares this Cartesian against the provided Cartesian componentwise and returns
       * <code>true</code> if they pass an absolute or relative tolerance test,
       * <code>false</code> otherwise.
       *
       * @param {Cartesian3} [right] The right hand side Cartesian.
       * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.
       * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
       * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartesian3.prototype.equalsEpsilon = function(right, relativeEpsilon, absoluteEpsilon) {
          return Cartesian3.equalsEpsilon(this, right, relativeEpsilon, absoluteEpsilon);
      };
  
      /**
       * Creates a string representing this Cartesian in the format '(x, y, z)'.
       *
       * @returns {String} A string representing this Cartesian in the format '(x, y, z)'.
       */
      Cartesian3.prototype.toString = function() {
          return '(' + this.x + ', ' + this.y + ', ' + this.z + ')';
      };
  
      return Cartesian3;
  });
  
  define('Core/AttributeCompression',[
          './Cartesian2',
          './Cartesian3',
          './Check',
          './defined',
          './DeveloperError',
          './Math'
      ], function(
          Cartesian2,
          Cartesian3,
          Check,
          defined,
          DeveloperError,
          CesiumMath) {
      'use strict';
  
      var RIGHT_SHIFT = 1.0 / 256.0;
      var LEFT_SHIFT = 256.0;
  
      /**
       * Attribute compression and decompression functions.
       *
       * @exports AttributeCompression
       *
       * @private
       */
      var AttributeCompression = {};
  
      /**
       * Encodes a normalized vector into 2 SNORM values in the range of [0-rangeMax] following the 'oct' encoding.
       *
       * Oct encoding is a compact representation of unit length vectors.
       * The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
       * Cigolle et al 2014: {@link http://jcgt.org/published/0003/02/01/}
       *
       * @param {Cartesian3} vector The normalized vector to be compressed into 2 component 'oct' encoding.
       * @param {Cartesian2} result The 2 component oct-encoded unit length vector.
       * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
       * @returns {Cartesian2} The 2 component oct-encoded unit length vector.
       *
       * @exception {DeveloperError} vector must be normalized.
       *
       * @see AttributeCompression.octDecodeInRange
       */
      AttributeCompression.octEncodeInRange = function(vector, rangeMax, result) {
                  Check.defined('vector', vector);
          Check.defined('result', result);
          var magSquared = Cartesian3.magnitudeSquared(vector);
          if (Math.abs(magSquared - 1.0) > CesiumMath.EPSILON6) {
              throw new DeveloperError('vector must be normalized.');
          }
          
          result.x = vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
          result.y = vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
          if (vector.z < 0) {
              var x = result.x;
              var y = result.y;
              result.x = (1.0 - Math.abs(y)) * CesiumMath.signNotZero(x);
              result.y = (1.0 - Math.abs(x)) * CesiumMath.signNotZero(y);
          }
  
          result.x = CesiumMath.toSNorm(result.x, rangeMax);
          result.y = CesiumMath.toSNorm(result.y, rangeMax);
  
          return result;
      };
  
      /**
       * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding.
       *
       * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.
       * @param {Cartesian2} result The 2 byte oct-encoded unit length vector.
       * @returns {Cartesian2} The 2 byte oct-encoded unit length vector.
       *
       * @exception {DeveloperError} vector must be normalized.
       *
       * @see AttributeCompression.octEncodeInRange
       * @see AttributeCompression.octDecode
       */
      AttributeCompression.octEncode = function(vector, result) {
          return AttributeCompression.octEncodeInRange(vector, 255, result);
      };
  
      var octEncodeScratch = new Cartesian2();
      var uint8ForceArray = new Uint8Array(1);
      function forceUint8(value) {
          uint8ForceArray[0] = value;
          return uint8ForceArray[0];
      }
      /**
       * @param {Cartesian3} vector The normalized vector to be compressed into 4 byte 'oct' encoding.
       * @param {Cartesian4} result The 4 byte oct-encoded unit length vector.
       * @returns {Cartesian4} The 4 byte oct-encoded unit length vector.
       *
       * @exception {DeveloperError} vector must be normalized.
       *
       * @see AttributeCompression.octEncodeInRange
       * @see AttributeCompression.octDecodeFromCartesian4
       */
      AttributeCompression.octEncodeToCartesian4 = function(vector, result) {
          AttributeCompression.octEncodeInRange(vector, 65535, octEncodeScratch);
          result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT);
          result.y = forceUint8(octEncodeScratch.x);
          result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT);
          result.w = forceUint8(octEncodeScratch.y);
          return result;
      };
  
      /**
       * Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector.
       *
       * @param {Number} x The x component of the oct-encoded unit length vector.
       * @param {Number} y The y component of the oct-encoded unit length vector.
       * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
       * @param {Cartesian3} result The decoded and normalized vector
       * @returns {Cartesian3} The decoded and normalized vector.
       *
       * @exception {DeveloperError} x and y must be unsigned normalized integers between 0 and rangeMax.
       *
       * @see AttributeCompression.octEncodeInRange
       */
      AttributeCompression.octDecodeInRange = function(x, y, rangeMax, result) {
                  Check.defined('result', result);
          if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {
              throw new DeveloperError('x and y must be unsigned normalized integers between 0 and ' + rangeMax);
          }
          
          result.x = CesiumMath.fromSNorm(x, rangeMax);
          result.y = CesiumMath.fromSNorm(y, rangeMax);
          result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y));
  
          if (result.z < 0.0)
          {
              var oldVX = result.x;
              result.x = (1.0 - Math.abs(result.y)) * CesiumMath.signNotZero(oldVX);
              result.y = (1.0 - Math.abs(oldVX)) * CesiumMath.signNotZero(result.y);
          }
  
          return Cartesian3.normalize(result, result);
      };
  
      /**
       * Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector.
       *
       * @param {Number} x The x component of the oct-encoded unit length vector.
       * @param {Number} y The y component of the oct-encoded unit length vector.
       * @param {Cartesian3} result The decoded and normalized vector.
       * @returns {Cartesian3} The decoded and normalized vector.
       *
       * @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and 255.
       *
       * @see AttributeCompression.octDecodeInRange
       */
      AttributeCompression.octDecode = function(x, y, result) {
          return AttributeCompression.octDecodeInRange(x, y, 255, result);
      };
  
      /**
       * Decodes a unit-length vector in 4 byte 'oct' encoding to a normalized 3-component vector.
       *
       * @param {Cartesian4} encoded The oct-encoded unit length vector.
       * @param {Cartesian3} result The decoded and normalized vector.
       * @returns {Cartesian3} The decoded and normalized vector.
       *
       * @exception {DeveloperError} x, y, z, and w must be unsigned normalized integers between 0 and 255.
       *
       * @see AttributeCompression.octDecodeInRange
       * @see AttributeCompression.octEncodeToCartesian4
       */
      AttributeCompression.octDecodeFromCartesian4 = function(encoded, result) {
                  Check.typeOf.object('encoded', encoded);
          Check.typeOf.object('result', result);
                  var x = encoded.x;
          var y = encoded.y;
          var z = encoded.z;
          var w = encoded.w;
                  if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) {
              throw new DeveloperError('x, y, z, and w must be unsigned normalized integers between 0 and 255');
          }
          
          var xOct16 = x * LEFT_SHIFT + y;
          var yOct16 = z * LEFT_SHIFT + w;
          return AttributeCompression.octDecodeInRange(xOct16, yOct16, 65535, result);
      };
  
      /**
       * Packs an oct encoded vector into a single floating-point number.
       *
       * @param {Cartesian2} encoded The oct encoded vector.
       * @returns {Number} The oct encoded vector packed into a single float.
       *
       */
      AttributeCompression.octPackFloat = function(encoded) {
                  Check.defined('encoded', encoded);
                  return 256.0 * encoded.x + encoded.y;
      };
  
      var scratchEncodeCart2 = new Cartesian2();
  
      /**
       * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding and
       * stores those values in a single float-point number.
       *
       * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.
       * @returns {Number} The 2 byte oct-encoded unit length vector.
       *
       * @exception {DeveloperError} vector must be normalized.
       */
      AttributeCompression.octEncodeFloat = function(vector) {
          AttributeCompression.octEncode(vector, scratchEncodeCart2);
          return AttributeCompression.octPackFloat(scratchEncodeCart2);
      };
  
      /**
       * Decodes a unit-length vector in 'oct' encoding packed in a floating-point number to a normalized 3-component vector.
       *
       * @param {Number} value The oct-encoded unit length vector stored as a single floating-point number.
       * @param {Cartesian3} result The decoded and normalized vector
       * @returns {Cartesian3} The decoded and normalized vector.
       *
       */
      AttributeCompression.octDecodeFloat = function(value, result) {
                  Check.defined('value', value);
          
          var temp = value / 256.0;
          var x = Math.floor(temp);
          var y = (temp - x) * 256.0;
  
          return AttributeCompression.octDecode(x, y, result);
      };
  
      /**
       * Encodes three normalized vectors into 6 SNORM values in the range of [0-255] following the 'oct' encoding and
       * packs those into two floating-point numbers.
       *
       * @param {Cartesian3} v1 A normalized vector to be compressed.
       * @param {Cartesian3} v2 A normalized vector to be compressed.
       * @param {Cartesian3} v3 A normalized vector to be compressed.
       * @param {Cartesian2} result The 'oct' encoded vectors packed into two floating-point numbers.
       * @returns {Cartesian2} The 'oct' encoded vectors packed into two floating-point numbers.
       *
       */
      AttributeCompression.octPack = function(v1, v2, v3, result) {
                  Check.defined('v1', v1);
          Check.defined('v2', v2);
          Check.defined('v3', v3);
          Check.defined('result', result);
          
          var encoded1 = AttributeCompression.octEncodeFloat(v1);
          var encoded2 = AttributeCompression.octEncodeFloat(v2);
  
          var encoded3 = AttributeCompression.octEncode(v3, scratchEncodeCart2);
          result.x = 65536.0 * encoded3.x + encoded1;
          result.y = 65536.0 * encoded3.y + encoded2;
          return result;
      };
  
      /**
       * Decodes three unit-length vectors in 'oct' encoding packed into a floating-point number to a normalized 3-component vector.
       *
       * @param {Cartesian2} packed The three oct-encoded unit length vectors stored as two floating-point number.
       * @param {Cartesian3} v1 One decoded and normalized vector.
       * @param {Cartesian3} v2 One decoded and normalized vector.
       * @param {Cartesian3} v3 One decoded and normalized vector.
       */
      AttributeCompression.octUnpack = function(packed, v1, v2, v3) {
                  Check.defined('packed', packed);
          Check.defined('v1', v1);
          Check.defined('v2', v2);
          Check.defined('v3', v3);
          
          var temp = packed.x / 65536.0;
          var x = Math.floor(temp);
          var encodedFloat1 = (temp - x) * 65536.0;
  
          temp = packed.y / 65536.0;
          var y = Math.floor(temp);
          var encodedFloat2 = (temp - y) * 65536.0;
  
          AttributeCompression.octDecodeFloat(encodedFloat1, v1);
          AttributeCompression.octDecodeFloat(encodedFloat2, v2);
          AttributeCompression.octDecode(x, y, v3);
      };
  
      /**
       * Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision.
       *
       * @param {Cartesian2} textureCoordinates The texture coordinates to compress.  Both coordinates must be in the range 0.0-1.0.
       * @returns {Number} The packed texture coordinates.
       *
       */
      AttributeCompression.compressTextureCoordinates = function(textureCoordinates) {
                  Check.defined('textureCoordinates', textureCoordinates);
          
          // Move x and y to the range 0-4095;
          var x = (textureCoordinates.x * 4095.0) | 0;
          var y = (textureCoordinates.y * 4095.0) | 0;
          return 4096.0 * x + y;
      };
  
      /**
       * Decompresses texture coordinates that were packed into a single float.
       *
       * @param {Number} compressed The compressed texture coordinates.
       * @param {Cartesian2} result The decompressed texture coordinates.
       * @returns {Cartesian2} The modified result parameter.
       *
       */
      AttributeCompression.decompressTextureCoordinates = function(compressed, result) {
                  Check.defined('compressed', compressed);
          Check.defined('result', result);
          
          var temp = compressed / 4096.0;
          var xZeroTo4095 = Math.floor(temp);
          result.x = xZeroTo4095 / 4095.0;
          result.y = (compressed - xZeroTo4095 * 4096) / 4095;
          return result;
      };
  
      function zigZagDecode(value) {
          return (value >> 1) ^ (-(value & 1));
      }
  
      /**
       * Decodes delta and ZigZag encoded vertices. This modifies the buffers in place.
       *
       * @param {Uint16Array} uBuffer The buffer view of u values.
       * @param {Uint16Array} vBuffer The buffer view of v values.
       * @param {Uint16Array} [heightBuffer] The buffer view of height values.
       *
       * @see {@link https://github.com/AnalyticalGraphicsInc/quantized-mesh|quantized-mesh-1.0 terrain format}
       */
      AttributeCompression.zigZagDeltaDecode = function(uBuffer, vBuffer, heightBuffer) {
                  Check.defined('uBuffer', uBuffer);
          Check.defined('vBuffer', vBuffer);
          Check.typeOf.number.equals('uBuffer.length', 'vBuffer.length', uBuffer.length, vBuffer.length);
          if (defined(heightBuffer)) {
              Check.typeOf.number.equals('uBuffer.length', 'heightBuffer.length', uBuffer.length, heightBuffer.length);
          }
          
          var count = uBuffer.length;
  
          var u = 0;
          var v = 0;
          var height = 0;
  
          for (var i = 0; i < count; ++i) {
              u += zigZagDecode(uBuffer[i]);
              v += zigZagDecode(vBuffer[i]);
  
              uBuffer[i] = u;
              vBuffer[i] = v;
  
              if (defined(heightBuffer)) {
                  height += zigZagDecode(heightBuffer[i]);
                  heightBuffer[i] = height;
              }
          }
      };
  
      return AttributeCompression;
  });
  
  define('Core/scaleToGeodeticSurface',[
          './Cartesian3',
          './defined',
          './DeveloperError',
          './Math'
      ], function(
          Cartesian3,
          defined,
          DeveloperError,
          CesiumMath) {
      'use strict';
  
      var scaleToGeodeticSurfaceIntersection = new Cartesian3();
      var scaleToGeodeticSurfaceGradient = new Cartesian3();
  
      /**
       * Scales the provided Cartesian position along the geodetic surface normal
       * so that it is on the surface of this ellipsoid.  If the position is
       * at the center of the ellipsoid, this function returns undefined.
       *
       * @param {Cartesian3} cartesian The Cartesian position to scale.
       * @param {Cartesian3} oneOverRadii One over radii of the ellipsoid.
       * @param {Cartesian3} oneOverRadiiSquared One over radii squared of the ellipsoid.
       * @param {Number} centerToleranceSquared Tolerance for closeness to the center.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter, a new Cartesian3 instance if none was provided, or undefined if the position is at the center.
       *
       * @exports scaleToGeodeticSurface
       *
       * @private
       */
      function scaleToGeodeticSurface(cartesian, oneOverRadii, oneOverRadiiSquared, centerToleranceSquared, result) {
                  if (!defined(cartesian)) {
              throw new DeveloperError('cartesian is required.');
          }
          if (!defined(oneOverRadii)) {
              throw new DeveloperError('oneOverRadii is required.');
          }
          if (!defined(oneOverRadiiSquared)) {
              throw new DeveloperError('oneOverRadiiSquared is required.');
          }
          if (!defined(centerToleranceSquared)) {
              throw new DeveloperError('centerToleranceSquared is required.');
          }
          
          var positionX = cartesian.x;
          var positionY = cartesian.y;
          var positionZ = cartesian.z;
  
          var oneOverRadiiX = oneOverRadii.x;
          var oneOverRadiiY = oneOverRadii.y;
          var oneOverRadiiZ = oneOverRadii.z;
  
          var x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX;
          var y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY;
          var z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ;
  
          // Compute the squared ellipsoid norm.
          var squaredNorm = x2 + y2 + z2;
          var ratio = Math.sqrt(1.0 / squaredNorm);
  
          // As an initial approximation, assume that the radial intersection is the projection point.
          var intersection = Cartesian3.multiplyByScalar(cartesian, ratio, scaleToGeodeticSurfaceIntersection);
  
          // If the position is near the center, the iteration will not converge.
          if (squaredNorm < centerToleranceSquared) {
              return !isFinite(ratio) ? undefined : Cartesian3.clone(intersection, result);
          }
  
          var oneOverRadiiSquaredX = oneOverRadiiSquared.x;
          var oneOverRadiiSquaredY = oneOverRadiiSquared.y;
          var oneOverRadiiSquaredZ = oneOverRadiiSquared.z;
  
          // Use the gradient at the intersection point in place of the true unit normal.
          // The difference in magnitude will be absorbed in the multiplier.
          var gradient = scaleToGeodeticSurfaceGradient;
          gradient.x = intersection.x * oneOverRadiiSquaredX * 2.0;
          gradient.y = intersection.y * oneOverRadiiSquaredY * 2.0;
          gradient.z = intersection.z * oneOverRadiiSquaredZ * 2.0;
  
          // Compute the initial guess at the normal vector multiplier, lambda.
          var lambda = (1.0 - ratio) * Cartesian3.magnitude(cartesian) / (0.5 * Cartesian3.magnitude(gradient));
          var correction = 0.0;
  
          var func;
          var denominator;
          var xMultiplier;
          var yMultiplier;
          var zMultiplier;
          var xMultiplier2;
          var yMultiplier2;
          var zMultiplier2;
          var xMultiplier3;
          var yMultiplier3;
          var zMultiplier3;
  
          do {
              lambda -= correction;
  
              xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredX);
              yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredY);
              zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredZ);
  
              xMultiplier2 = xMultiplier * xMultiplier;
              yMultiplier2 = yMultiplier * yMultiplier;
              zMultiplier2 = zMultiplier * zMultiplier;
  
              xMultiplier3 = xMultiplier2 * xMultiplier;
              yMultiplier3 = yMultiplier2 * yMultiplier;
              zMultiplier3 = zMultiplier2 * zMultiplier;
  
              func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0;
  
              // "denominator" here refers to the use of this expression in the velocity and acceleration
              // computations in the sections to follow.
              denominator = x2 * xMultiplier3 * oneOverRadiiSquaredX + y2 * yMultiplier3 * oneOverRadiiSquaredY + z2 * zMultiplier3 * oneOverRadiiSquaredZ;
  
              var derivative = -2.0 * denominator;
  
              correction = func / derivative;
          } while (Math.abs(func) > CesiumMath.EPSILON12);
  
          if (!defined(result)) {
              return new Cartesian3(positionX * xMultiplier, positionY * yMultiplier, positionZ * zMultiplier);
          }
          result.x = positionX * xMultiplier;
          result.y = positionY * yMultiplier;
          result.z = positionZ * zMultiplier;
          return result;
      }
  
      return scaleToGeodeticSurface;
  });
  
  define('Core/Cartographic',[
          './Cartesian3',
          './Check',
          './defaultValue',
          './defined',
          './freezeObject',
          './Math',
          './scaleToGeodeticSurface'
      ], function(
          Cartesian3,
          Check,
          defaultValue,
          defined,
          freezeObject,
          CesiumMath,
          scaleToGeodeticSurface) {
      'use strict';
  
      /**
       * A position defined by longitude, latitude, and height.
       * @alias Cartographic
       * @constructor
       *
       * @param {Number} [longitude=0.0] The longitude, in radians.
       * @param {Number} [latitude=0.0] The latitude, in radians.
       * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
       *
       * @see Ellipsoid
       */
      function Cartographic(longitude, latitude, height) {
          /**
           * The longitude, in radians.
           * @type {Number}
           * @default 0.0
           */
          this.longitude = defaultValue(longitude, 0.0);
  
          /**
           * The latitude, in radians.
           * @type {Number}
           * @default 0.0
           */
          this.latitude = defaultValue(latitude, 0.0);
  
          /**
           * The height, in meters, above the ellipsoid.
           * @type {Number}
           * @default 0.0
           */
          this.height = defaultValue(height, 0.0);
      }
  
      /**
       * Creates a new Cartographic instance from longitude and latitude
       * specified in radians.
       *
       * @param {Number} longitude The longitude, in radians.
       * @param {Number} latitude The latitude, in radians.
       * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
       */
      Cartographic.fromRadians = function(longitude, latitude, height, result) {
                  Check.typeOf.number('longitude', longitude);
          Check.typeOf.number('latitude', latitude);
          
          height = defaultValue(height, 0.0);
  
          if (!defined(result)) {
              return new Cartographic(longitude, latitude, height);
          }
  
          result.longitude = longitude;
          result.latitude = latitude;
          result.height = height;
          return result;
      };
  
      /**
       * Creates a new Cartographic instance from longitude and latitude
       * specified in degrees.  The values in the resulting object will
       * be in radians.
       *
       * @param {Number} longitude The longitude, in degrees.
       * @param {Number} latitude The latitude, in degrees.
       * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
       */
      Cartographic.fromDegrees = function(longitude, latitude, height, result) {
                  Check.typeOf.number('longitude', longitude);
          Check.typeOf.number('latitude', latitude);
                  longitude = CesiumMath.toRadians(longitude);
          latitude = CesiumMath.toRadians(latitude);
  
          return Cartographic.fromRadians(longitude, latitude, height, result);
      };
  
      var cartesianToCartographicN = new Cartesian3();
      var cartesianToCartographicP = new Cartesian3();
      var cartesianToCartographicH = new Cartesian3();
      var wgs84OneOverRadii = new Cartesian3(1.0 / 6378137.0, 1.0 / 6378137.0, 1.0 / 6356752.3142451793);
      var wgs84OneOverRadiiSquared = new Cartesian3(1.0 / (6378137.0 * 6378137.0), 1.0 / (6378137.0 * 6378137.0), 1.0 / (6356752.3142451793 * 6356752.3142451793));
      var wgs84CenterToleranceSquared = CesiumMath.EPSILON1;
  
      /**
       * Creates a new Cartographic instance from a Cartesian position. The values in the
       * resulting object will be in radians.
       *
       * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter, new Cartographic instance if none was provided, or undefined if the cartesian is at the center of the ellipsoid.
       */
      Cartographic.fromCartesian = function(cartesian, ellipsoid, result) {
          var oneOverRadii = defined(ellipsoid) ? ellipsoid.oneOverRadii : wgs84OneOverRadii;
          var oneOverRadiiSquared = defined(ellipsoid) ? ellipsoid.oneOverRadiiSquared : wgs84OneOverRadiiSquared;
          var centerToleranceSquared = defined(ellipsoid) ? ellipsoid._centerToleranceSquared : wgs84CenterToleranceSquared;
  
          //`cartesian is required.` is thrown from scaleToGeodeticSurface
          var p = scaleToGeodeticSurface(cartesian, oneOverRadii, oneOverRadiiSquared, centerToleranceSquared, cartesianToCartographicP);
  
          if (!defined(p)) {
              return undefined;
          }
  
          var n = Cartesian3.multiplyComponents(p, oneOverRadiiSquared, cartesianToCartographicN);
          n = Cartesian3.normalize(n, n);
  
          var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH);
  
          var longitude = Math.atan2(n.y, n.x);
          var latitude = Math.asin(n.z);
          var height = CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h);
  
          if (!defined(result)) {
              return new Cartographic(longitude, latitude, height);
          }
          result.longitude = longitude;
          result.latitude = latitude;
          result.height = height;
          return result;
      };
  
      /**
       * Creates a new Cartesian3 instance from a Cartographic input. The values in the inputted
       * object should be in radians.
       *
       * @param {Cartographic} cartographic Input to be converted into a Cartesian3 output.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The position
       */
      Cartographic.toCartesian = function(cartographic, ellipsoid, result) {
                  Check.defined('cartographic', cartographic);
          
          return Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height, ellipsoid, result);
      };
  
      /**
       * Duplicates a Cartographic instance.
       *
       * @param {Cartographic} cartographic The cartographic to duplicate.
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. (Returns undefined if cartographic is undefined)
       */
      Cartographic.clone = function(cartographic, result) {
          if (!defined(cartographic)) {
              return undefined;
          }
          if (!defined(result)) {
              return new Cartographic(cartographic.longitude, cartographic.latitude, cartographic.height);
          }
          result.longitude = cartographic.longitude;
          result.latitude = cartographic.latitude;
          result.height = cartographic.height;
          return result;
      };
  
      /**
       * Compares the provided cartographics componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartographic} [left] The first cartographic.
       * @param {Cartographic} [right] The second cartographic.
       * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
       */
      Cartographic.equals = function(left, right) {
          return (left === right) ||
                  ((defined(left)) &&
                   (defined(right)) &&
                   (left.longitude === right.longitude) &&
                   (left.latitude === right.latitude) &&
                   (left.height === right.height));
      };
  
      /**
       * Compares the provided cartographics componentwise and returns
       * <code>true</code> if they are within the provided epsilon,
       * <code>false</code> otherwise.
       *
       * @param {Cartographic} [left] The first cartographic.
       * @param {Cartographic} [right] The second cartographic.
       * @param {Number} epsilon The epsilon to use for equality testing.
       * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartographic.equalsEpsilon = function(left, right, epsilon) {
                  Check.typeOf.number('epsilon', epsilon);
          
          return (left === right) ||
                 ((defined(left)) &&
                  (defined(right)) &&
                  (Math.abs(left.longitude - right.longitude) <= epsilon) &&
                  (Math.abs(left.latitude - right.latitude) <= epsilon) &&
                  (Math.abs(left.height - right.height) <= epsilon));
      };
  
      /**
       * An immutable Cartographic instance initialized to (0.0, 0.0, 0.0).
       *
       * @type {Cartographic}
       * @constant
       */
      Cartographic.ZERO = freezeObject(new Cartographic(0.0, 0.0, 0.0));
  
      /**
       * Duplicates this instance.
       *
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.
       */
      Cartographic.prototype.clone = function(result) {
          return Cartographic.clone(this, result);
      };
  
      /**
       * Compares the provided against this cartographic componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Cartographic} [right] The second cartographic.
       * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
       */
      Cartographic.prototype.equals = function(right) {
          return Cartographic.equals(this, right);
      };
  
      /**
       * Compares the provided against this cartographic componentwise and returns
       * <code>true</code> if they are within the provided epsilon,
       * <code>false</code> otherwise.
       *
       * @param {Cartographic} [right] The second cartographic.
       * @param {Number} epsilon The epsilon to use for equality testing.
       * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
       */
      Cartographic.prototype.equalsEpsilon = function(right, epsilon) {
          return Cartographic.equalsEpsilon(this, right, epsilon);
      };
  
      /**
       * Creates a string representing this cartographic in the format '(longitude, latitude, height)'.
       *
       * @returns {String} A string representing the provided cartographic in the format '(longitude, latitude, height)'.
       */
      Cartographic.prototype.toString = function() {
          return '(' + this.longitude + ', ' + this.latitude + ', ' + this.height + ')';
      };
  
      return Cartographic;
  });
  
  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/Ellipsoid',[
          './Cartesian3',
          './Cartographic',
          './Check',
          './defaultValue',
          './defined',
          './defineProperties',
          './DeveloperError',
          './freezeObject',
          './Math',
          './scaleToGeodeticSurface'
      ], function(
          Cartesian3,
          Cartographic,
          Check,
          defaultValue,
          defined,
          defineProperties,
          DeveloperError,
          freezeObject,
          CesiumMath,
          scaleToGeodeticSurface) {
      'use strict';
  
      function initialize(ellipsoid, x, y, z) {
          x = defaultValue(x, 0.0);
          y = defaultValue(y, 0.0);
          z = defaultValue(z, 0.0);
  
                  Check.typeOf.number.greaterThanOrEquals('x', x, 0.0);
          Check.typeOf.number.greaterThanOrEquals('y', y, 0.0);
          Check.typeOf.number.greaterThanOrEquals('z', z, 0.0);
          
          ellipsoid._radii = new Cartesian3(x, y, z);
  
          ellipsoid._radiiSquared = new Cartesian3(x * x,
                                              y * y,
                                              z * z);
  
          ellipsoid._radiiToTheFourth = new Cartesian3(x * x * x * x,
                                                  y * y * y * y,
                                                  z * z * z * z);
  
          ellipsoid._oneOverRadii = new Cartesian3(x === 0.0 ? 0.0 : 1.0 / x,
                                              y === 0.0 ? 0.0 : 1.0 / y,
                                              z === 0.0 ? 0.0 : 1.0 / z);
  
          ellipsoid._oneOverRadiiSquared = new Cartesian3(x === 0.0 ? 0.0 : 1.0 / (x * x),
                                                     y === 0.0 ? 0.0 : 1.0 / (y * y),
                                                     z === 0.0 ? 0.0 : 1.0 / (z * z));
  
          ellipsoid._minimumRadius = Math.min(x, y, z);
  
          ellipsoid._maximumRadius = Math.max(x, y, z);
  
          ellipsoid._centerToleranceSquared = CesiumMath.EPSILON1;
  
          if (ellipsoid._radiiSquared.z !== 0) {
              ellipsoid._squaredXOverSquaredZ = ellipsoid._radiiSquared.x / ellipsoid._radiiSquared.z;
          }
      }
  
      /**
       * A quadratic surface defined in Cartesian coordinates by the equation
       * <code>(x / a)^2 + (y / b)^2 + (z / c)^2 = 1</code>.  Primarily used
       * by Cesium to represent the shape of planetary bodies.
       *
       * Rather than constructing this object directly, one of the provided
       * constants is normally used.
       * @alias Ellipsoid
       * @constructor
       *
       * @param {Number} [x=0] The radius in the x direction.
       * @param {Number} [y=0] The radius in the y direction.
       * @param {Number} [z=0] The radius in the z direction.
       *
       * @exception {DeveloperError} All radii components must be greater than or equal to zero.
       *
       * @see Ellipsoid.fromCartesian3
       * @see Ellipsoid.WGS84
       * @see Ellipsoid.UNIT_SPHERE
       */
      function Ellipsoid(x, y, z) {
          this._radii = undefined;
          this._radiiSquared = undefined;
          this._radiiToTheFourth = undefined;
          this._oneOverRadii = undefined;
          this._oneOverRadiiSquared = undefined;
          this._minimumRadius = undefined;
          this._maximumRadius = undefined;
          this._centerToleranceSquared = undefined;
          this._squaredXOverSquaredZ = undefined;
  
          initialize(this, x, y, z);
      }
  
      defineProperties(Ellipsoid.prototype, {
          /**
           * Gets the radii of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Cartesian3}
           * @readonly
           */
          radii : {
              get: function() {
                  return this._radii;
              }
          },
          /**
           * Gets the squared radii of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Cartesian3}
           * @readonly
           */
          radiiSquared : {
              get : function() {
                  return this._radiiSquared;
              }
          },
          /**
           * Gets the radii of the ellipsoid raise to the fourth power.
           * @memberof Ellipsoid.prototype
           * @type {Cartesian3}
           * @readonly
           */
          radiiToTheFourth : {
              get : function() {
                  return this._radiiToTheFourth;
              }
          },
          /**
           * Gets one over the radii of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Cartesian3}
           * @readonly
           */
          oneOverRadii : {
              get : function() {
                  return this._oneOverRadii;
              }
          },
          /**
           * Gets one over the squared radii of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Cartesian3}
           * @readonly
           */
          oneOverRadiiSquared : {
              get : function() {
                  return this._oneOverRadiiSquared;
              }
          },
          /**
           * Gets the minimum radius of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Number}
           * @readonly
           */
          minimumRadius : {
              get : function() {
                  return this._minimumRadius;
              }
          },
          /**
           * Gets the maximum radius of the ellipsoid.
           * @memberof Ellipsoid.prototype
           * @type {Number}
           * @readonly
           */
          maximumRadius : {
              get : function() {
                  return this._maximumRadius;
              }
          }
      });
  
      /**
       * Duplicates an Ellipsoid instance.
       *
       * @param {Ellipsoid} ellipsoid The ellipsoid to duplicate.
       * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new
       *                    instance should be created.
       * @returns {Ellipsoid} The cloned Ellipsoid. (Returns undefined if ellipsoid is undefined)
       */
      Ellipsoid.clone = function(ellipsoid, result) {
          if (!defined(ellipsoid)) {
              return undefined;
          }
          var radii = ellipsoid._radii;
  
          if (!defined(result)) {
              return new Ellipsoid(radii.x, radii.y, radii.z);
          }
  
          Cartesian3.clone(radii, result._radii);
          Cartesian3.clone(ellipsoid._radiiSquared, result._radiiSquared);
          Cartesian3.clone(ellipsoid._radiiToTheFourth, result._radiiToTheFourth);
          Cartesian3.clone(ellipsoid._oneOverRadii, result._oneOverRadii);
          Cartesian3.clone(ellipsoid._oneOverRadiiSquared, result._oneOverRadiiSquared);
          result._minimumRadius = ellipsoid._minimumRadius;
          result._maximumRadius = ellipsoid._maximumRadius;
          result._centerToleranceSquared = ellipsoid._centerToleranceSquared;
  
          return result;
      };
  
      /**
       * Computes an Ellipsoid from a Cartesian specifying the radii in x, y, and z directions.
       *
       * @param {Cartesian3} [cartesian=Cartesian3.ZERO] The ellipsoid's radius in the x, y, and z directions.
       * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new
       *                    instance should be created.
       * @returns {Ellipsoid} A new Ellipsoid instance.
       *
       * @exception {DeveloperError} All radii components must be greater than or equal to zero.
       *
       * @see Ellipsoid.WGS84
       * @see Ellipsoid.UNIT_SPHERE
       */
      Ellipsoid.fromCartesian3 = function(cartesian, result) {
          if (!defined(result)) {
              result = new Ellipsoid();
          }
  
          if (!defined(cartesian)) {
              return result;
          }
  
          initialize(result, cartesian.x, cartesian.y, cartesian.z);
          return result;
      };
  
      /**
       * An Ellipsoid instance initialized to the WGS84 standard.
       *
       * @type {Ellipsoid}
       * @constant
       */
      Ellipsoid.WGS84 = freezeObject(new Ellipsoid(6378137.0, 6378137.0, 6356752.3142451793));
  
      /**
       * An Ellipsoid instance initialized to radii of (1.0, 1.0, 1.0).
       *
       * @type {Ellipsoid}
       * @constant
       */
      Ellipsoid.UNIT_SPHERE = freezeObject(new Ellipsoid(1.0, 1.0, 1.0));
  
      /**
       * An Ellipsoid instance initialized to a sphere with the lunar radius.
       *
       * @type {Ellipsoid}
       * @constant
       */
      Ellipsoid.MOON = freezeObject(new Ellipsoid(CesiumMath.LUNAR_RADIUS, CesiumMath.LUNAR_RADIUS, CesiumMath.LUNAR_RADIUS));
  
      /**
       * Duplicates an Ellipsoid instance.
       *
       * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new
       *                    instance should be created.
       * @returns {Ellipsoid} The cloned Ellipsoid.
       */
      Ellipsoid.prototype.clone = function(result) {
          return Ellipsoid.clone(this, result);
      };
  
      /**
       * The number of elements used to pack the object into an array.
       * @type {Number}
       */
      Ellipsoid.packedLength = Cartesian3.packedLength;
  
      /**
       * Stores the provided instance into the provided array.
       *
       * @param {Ellipsoid} value The value to pack.
       * @param {Number[]} array The array to pack into.
       * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
       *
       * @returns {Number[]} The array that was packed into
       */
      Ellipsoid.pack = function(value, array, startingIndex) {
                  Check.typeOf.object('value', value);
          Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          Cartesian3.pack(value._radii, array, startingIndex);
  
          return array;
      };
  
      /**
       * Retrieves an instance from a packed array.
       *
       * @param {Number[]} array The packed array.
       * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
       * @param {Ellipsoid} [result] The object into which to store the result.
       * @returns {Ellipsoid} The modified result parameter or a new Ellipsoid instance if one was not provided.
       */
      Ellipsoid.unpack = function(array, startingIndex, result) {
                  Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          var radii = Cartesian3.unpack(array, startingIndex);
          return Ellipsoid.fromCartesian3(radii, result);
      };
  
      /**
       * Computes the unit vector directed from the center of this ellipsoid toward the provided Cartesian position.
       * @function
       *
       * @param {Cartesian3} cartesian The Cartesian for which to to determine the geocentric normal.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
       */
      Ellipsoid.prototype.geocentricSurfaceNormal = Cartesian3.normalize;
  
      /**
       * Computes the normal of the plane tangent to the surface of the ellipsoid at the provided position.
       *
       * @param {Cartographic} cartographic The cartographic position for which to to determine the geodetic normal.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
       */
      Ellipsoid.prototype.geodeticSurfaceNormalCartographic = function(cartographic, result) {
                  Check.typeOf.object('cartographic', cartographic);
          
          var longitude = cartographic.longitude;
          var latitude = cartographic.latitude;
          var cosLatitude = Math.cos(latitude);
  
          var x = cosLatitude * Math.cos(longitude);
          var y = cosLatitude * Math.sin(longitude);
          var z = Math.sin(latitude);
  
          if (!defined(result)) {
              result = new Cartesian3();
          }
          result.x = x;
          result.y = y;
          result.z = z;
          return Cartesian3.normalize(result, result);
      };
  
      /**
       * Computes the normal of the plane tangent to the surface of the ellipsoid at the provided position.
       *
       * @param {Cartesian3} cartesian The Cartesian position for which to to determine the surface normal.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
       */
      Ellipsoid.prototype.geodeticSurfaceNormal = function(cartesian, result) {
          if (!defined(result)) {
              result = new Cartesian3();
          }
          result = Cartesian3.multiplyComponents(cartesian, this._oneOverRadiiSquared, result);
          return Cartesian3.normalize(result, result);
      };
  
      var cartographicToCartesianNormal = new Cartesian3();
      var cartographicToCartesianK = new Cartesian3();
  
      /**
       * Converts the provided cartographic to Cartesian representation.
       *
       * @param {Cartographic} cartographic The cartographic position.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
       *
       * @example
       * //Create a Cartographic and determine it's Cartesian representation on a WGS84 ellipsoid.
       * var position = new Cesium.Cartographic(Cesium.Math.toRadians(21), Cesium.Math.toRadians(78), 5000);
       * var cartesianPosition = Cesium.Ellipsoid.WGS84.cartographicToCartesian(position);
       */
      Ellipsoid.prototype.cartographicToCartesian = function(cartographic, result) {
          //`cartographic is required` is thrown from geodeticSurfaceNormalCartographic.
          var n = cartographicToCartesianNormal;
          var k = cartographicToCartesianK;
          this.geodeticSurfaceNormalCartographic(cartographic, n);
          Cartesian3.multiplyComponents(this._radiiSquared, n, k);
          var gamma = Math.sqrt(Cartesian3.dot(n, k));
          Cartesian3.divideByScalar(k, gamma, k);
          Cartesian3.multiplyByScalar(n, cartographic.height, n);
  
          if (!defined(result)) {
              result = new Cartesian3();
          }
          return Cartesian3.add(k, n, result);
      };
  
      /**
       * Converts the provided array of cartographics to an array of Cartesians.
       *
       * @param {Cartographic[]} cartographics An array of cartographic positions.
       * @param {Cartesian3[]} [result] The object onto which to store the result.
       * @returns {Cartesian3[]} The modified result parameter or a new Array instance if none was provided.
       *
       * @example
       * //Convert an array of Cartographics and determine their Cartesian representation on a WGS84 ellipsoid.
       * var positions = [new Cesium.Cartographic(Cesium.Math.toRadians(21), Cesium.Math.toRadians(78), 0),
       *                  new Cesium.Cartographic(Cesium.Math.toRadians(21.321), Cesium.Math.toRadians(78.123), 100),
       *                  new Cesium.Cartographic(Cesium.Math.toRadians(21.645), Cesium.Math.toRadians(78.456), 250)];
       * var cartesianPositions = Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions);
       */
      Ellipsoid.prototype.cartographicArrayToCartesianArray = function(cartographics, result) {
                  Check.defined('cartographics', cartographics);
          
          var length = cartographics.length;
          if (!defined(result)) {
              result = new Array(length);
          } else {
              result.length = length;
          }
          for ( var i = 0; i < length; i++) {
              result[i] = this.cartographicToCartesian(cartographics[i], result[i]);
          }
          return result;
      };
  
      var cartesianToCartographicN = new Cartesian3();
      var cartesianToCartographicP = new Cartesian3();
      var cartesianToCartographicH = new Cartesian3();
  
      /**
       * Converts the provided cartesian to cartographic representation.
       * The cartesian is undefined at the center of the ellipsoid.
       *
       * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation.
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter, new Cartographic instance if none was provided, or undefined if the cartesian is at the center of the ellipsoid.
       *
       * @example
       * //Create a Cartesian and determine it's Cartographic representation on a WGS84 ellipsoid.
       * var position = new Cesium.Cartesian3(17832.12, 83234.52, 952313.73);
       * var cartographicPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
       */
      Ellipsoid.prototype.cartesianToCartographic = function(cartesian, result) {
          //`cartesian is required.` is thrown from scaleToGeodeticSurface
          var p = this.scaleToGeodeticSurface(cartesian, cartesianToCartographicP);
  
          if (!defined(p)) {
              return undefined;
          }
  
          var n = this.geodeticSurfaceNormal(p, cartesianToCartographicN);
          var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH);
  
          var longitude = Math.atan2(n.y, n.x);
          var latitude = Math.asin(n.z);
          var height = CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h);
  
          if (!defined(result)) {
              return new Cartographic(longitude, latitude, height);
          }
          result.longitude = longitude;
          result.latitude = latitude;
          result.height = height;
          return result;
      };
  
      /**
       * Converts the provided array of cartesians to an array of cartographics.
       *
       * @param {Cartesian3[]} cartesians An array of Cartesian positions.
       * @param {Cartographic[]} [result] The object onto which to store the result.
       * @returns {Cartographic[]} The modified result parameter or a new Array instance if none was provided.
       *
       * @example
       * //Create an array of Cartesians and determine their Cartographic representation on a WGS84 ellipsoid.
       * var positions = [new Cesium.Cartesian3(17832.12, 83234.52, 952313.73),
       *                  new Cesium.Cartesian3(17832.13, 83234.53, 952313.73),
       *                  new Cesium.Cartesian3(17832.14, 83234.54, 952313.73)]
       * var cartographicPositions = Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray(positions);
       */
      Ellipsoid.prototype.cartesianArrayToCartographicArray = function(cartesians, result) {
                  Check.defined('cartesians', cartesians);
          
          var length = cartesians.length;
          if (!defined(result)) {
              result = new Array(length);
          } else {
              result.length = length;
          }
          for ( var i = 0; i < length; ++i) {
              result[i] = this.cartesianToCartographic(cartesians[i], result[i]);
          }
          return result;
      };
  
      /**
       * Scales the provided Cartesian position along the geodetic surface normal
       * so that it is on the surface of this ellipsoid.  If the position is
       * at the center of the ellipsoid, this function returns undefined.
       *
       * @param {Cartesian3} cartesian The Cartesian position to scale.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter, a new Cartesian3 instance if none was provided, or undefined if the position is at the center.
       */
      Ellipsoid.prototype.scaleToGeodeticSurface = function(cartesian, result) {
          return scaleToGeodeticSurface(cartesian, this._oneOverRadii, this._oneOverRadiiSquared, this._centerToleranceSquared, result);
      };
  
      /**
       * Scales the provided Cartesian position along the geocentric surface normal
       * so that it is on the surface of this ellipsoid.
       *
       * @param {Cartesian3} cartesian The Cartesian position to scale.
       * @param {Cartesian3} [result] The object onto which to store the result.
       * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.
       */
      Ellipsoid.prototype.scaleToGeocentricSurface = function(cartesian, result) {
                  Check.typeOf.object('cartesian', cartesian);
          
          if (!defined(result)) {
              result = new Cartesian3();
          }
  
          var positionX = cartesian.x;
          var positionY = cartesian.y;
          var positionZ = cartesian.z;
          var oneOverRadiiSquared = this._oneOverRadiiSquared;
  
          var beta = 1.0 / Math.sqrt((positionX * positionX) * oneOverRadiiSquared.x +
                                     (positionY * positionY) * oneOverRadiiSquared.y +
                                     (positionZ * positionZ) * oneOverRadiiSquared.z);
  
          return Cartesian3.multiplyByScalar(cartesian, beta, result);
      };
  
      /**
       * Transforms a Cartesian X, Y, Z position to the ellipsoid-scaled space by multiplying
       * its components by the result of {@link Ellipsoid#oneOverRadii}.
       *
       * @param {Cartesian3} position The position to transform.
       * @param {Cartesian3} [result] The position to which to copy the result, or undefined to create and
       *        return a new instance.
       * @returns {Cartesian3} The position expressed in the scaled space.  The returned instance is the
       *          one passed as the result parameter if it is not undefined, or a new instance of it is.
       */
      Ellipsoid.prototype.transformPositionToScaledSpace = function(position, result) {
          if (!defined(result)) {
              result = new Cartesian3();
          }
  
          return Cartesian3.multiplyComponents(position, this._oneOverRadii, result);
      };
  
      /**
       * Transforms a Cartesian X, Y, Z position from the ellipsoid-scaled space by multiplying
       * its components by the result of {@link Ellipsoid#radii}.
       *
       * @param {Cartesian3} position The position to transform.
       * @param {Cartesian3} [result] The position to which to copy the result, or undefined to create and
       *        return a new instance.
       * @returns {Cartesian3} The position expressed in the unscaled space.  The returned instance is the
       *          one passed as the result parameter if it is not undefined, or a new instance of it is.
       */
      Ellipsoid.prototype.transformPositionFromScaledSpace = function(position, result) {
          if (!defined(result)) {
              result = new Cartesian3();
          }
  
          return Cartesian3.multiplyComponents(position, this._radii, result);
      };
  
      /**
       * Compares this Ellipsoid against the provided Ellipsoid componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Ellipsoid} [right] The other Ellipsoid.
       * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
       */
      Ellipsoid.prototype.equals = function(right) {
          return (this === right) ||
                 (defined(right) &&
                  Cartesian3.equals(this._radii, right._radii));
      };
  
      /**
       * Creates a string representing this Ellipsoid in the format '(radii.x, radii.y, radii.z)'.
       *
       * @returns {String} A string representing this ellipsoid in the format '(radii.x, radii.y, radii.z)'.
       */
      Ellipsoid.prototype.toString = function() {
          return this._radii.toString();
      };
  
      /**
       * Computes a point which is the intersection of the surface normal with the z-axis.
       *
       * @param {Cartesian3} position the position. must be on the surface of the ellipsoid.
       * @param {Number} [buffer = 0.0] A buffer to subtract from the ellipsoid size when checking if the point is inside the ellipsoid.
       *                                In earth case, with common earth datums, there is no need for this buffer since the intersection point is always (relatively) very close to the center.
       *                                In WGS84 datum, intersection point is at max z = +-42841.31151331382 (0.673% of z-axis).
       *                                Intersection point could be outside the ellipsoid if the ratio of MajorAxis / AxisOfRotation is bigger than the square root of 2
       * @param {Cartesian3} [result] The cartesian to which to copy the result, or undefined to create and
       *        return a new instance.
       * @returns {Cartesian3 | undefined} the intersection point if it's inside the ellipsoid, undefined otherwise
       *
       * @exception {DeveloperError} position is required.
       * @exception {DeveloperError} Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y).
       * @exception {DeveloperError} Ellipsoid.radii.z must be greater than 0.
       */
      Ellipsoid.prototype.getSurfaceNormalIntersectionWithZAxis = function(position, buffer, result) {
                  Check.typeOf.object('position', position);
  
          if (!CesiumMath.equalsEpsilon(this._radii.x, this._radii.y, CesiumMath.EPSILON15)) {
              throw new DeveloperError('Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)');
          }
  
          Check.typeOf.number.greaterThan('Ellipsoid.radii.z', this._radii.z, 0);
          
          buffer = defaultValue(buffer, 0.0);
  
          var squaredXOverSquaredZ = this._squaredXOverSquaredZ;
  
          if (!defined(result)) {
              result = new Cartesian3();
          }
  
          result.x = 0.0;
          result.y = 0.0;
          result.z = position.z * (1 - squaredXOverSquaredZ);
  
          if (Math.abs(result.z) >= this._radii.z - buffer) {
              return undefined;
          }
  
          return result;
      };
  
      return Ellipsoid;
  });
  
  define('Core/Rectangle',[
          './Cartographic',
          './Check',
          './defaultValue',
          './defined',
          './defineProperties',
          './Ellipsoid',
          './freezeObject',
          './Math'
      ], function(
          Cartographic,
          Check,
          defaultValue,
          defined,
          defineProperties,
          Ellipsoid,
          freezeObject,
          CesiumMath) {
      'use strict';
  
      /**
       * A two dimensional region specified as longitude and latitude coordinates.
       *
       * @alias Rectangle
       * @constructor
       *
       * @param {Number} [west=0.0] The westernmost longitude, in radians, in the range [-Pi, Pi].
       * @param {Number} [south=0.0] The southernmost latitude, in radians, in the range [-Pi/2, Pi/2].
       * @param {Number} [east=0.0] The easternmost longitude, in radians, in the range [-Pi, Pi].
       * @param {Number} [north=0.0] The northernmost latitude, in radians, in the range [-Pi/2, Pi/2].
       *
       * @see Packable
       */
      function Rectangle(west, south, east, north) {
          /**
           * The westernmost longitude in radians in the range [-Pi, Pi].
           *
           * @type {Number}
           * @default 0.0
           */
          this.west = defaultValue(west, 0.0);
  
          /**
           * The southernmost latitude in radians in the range [-Pi/2, Pi/2].
           *
           * @type {Number}
           * @default 0.0
           */
          this.south = defaultValue(south, 0.0);
  
          /**
           * The easternmost longitude in radians in the range [-Pi, Pi].
           *
           * @type {Number}
           * @default 0.0
           */
          this.east = defaultValue(east, 0.0);
  
          /**
           * The northernmost latitude in radians in the range [-Pi/2, Pi/2].
           *
           * @type {Number}
           * @default 0.0
           */
          this.north = defaultValue(north, 0.0);
      }
  
      defineProperties(Rectangle.prototype, {
          /**
           * Gets the width of the rectangle in radians.
           * @memberof Rectangle.prototype
           * @type {Number}
           */
          width : {
              get : function() {
                  return Rectangle.computeWidth(this);
              }
          },
  
          /**
           * Gets the height of the rectangle in radians.
           * @memberof Rectangle.prototype
           * @type {Number}
           */
          height : {
              get : function() {
                  return Rectangle.computeHeight(this);
              }
          }
      });
  
      /**
       * The number of elements used to pack the object into an array.
       * @type {Number}
       */
      Rectangle.packedLength = 4;
  
      /**
       * Stores the provided instance into the provided array.
       *
       * @param {Rectangle} value The value to pack.
       * @param {Number[]} array The array to pack into.
       * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
       *
       * @returns {Number[]} The array that was packed into
       */
      Rectangle.pack = function(value, array, startingIndex) {
                  Check.typeOf.object('value', value);
          Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          array[startingIndex++] = value.west;
          array[startingIndex++] = value.south;
          array[startingIndex++] = value.east;
          array[startingIndex] = value.north;
  
          return array;
      };
  
      /**
       * Retrieves an instance from a packed array.
       *
       * @param {Number[]} array The packed array.
       * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
       * @param {Rectangle} [result] The object into which to store the result.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if one was not provided.
       */
      Rectangle.unpack = function(array, startingIndex, result) {
                  Check.defined('array', array);
          
          startingIndex = defaultValue(startingIndex, 0);
  
          if (!defined(result)) {
              result = new Rectangle();
          }
  
          result.west = array[startingIndex++];
          result.south = array[startingIndex++];
          result.east = array[startingIndex++];
          result.north = array[startingIndex];
          return result;
      };
  
      /**
       * Computes the width of a rectangle in radians.
       * @param {Rectangle} rectangle The rectangle to compute the width of.
       * @returns {Number} The width.
       */
      Rectangle.computeWidth = function(rectangle) {
                  Check.typeOf.object('rectangle', rectangle);
                  var east = rectangle.east;
          var west = rectangle.west;
          if (east < west) {
              east += CesiumMath.TWO_PI;
          }
          return east - west;
      };
  
      /**
       * Computes the height of a rectangle in radians.
       * @param {Rectangle} rectangle The rectangle to compute the height of.
       * @returns {Number} The height.
       */
      Rectangle.computeHeight = function(rectangle) {
                  Check.typeOf.object('rectangle', rectangle);
                  return rectangle.north - rectangle.south;
      };
  
      /**
       * Creates a rectangle given the boundary longitude and latitude in degrees.
       *
       * @param {Number} [west=0.0] The westernmost longitude in degrees in the range [-180.0, 180.0].
       * @param {Number} [south=0.0] The southernmost latitude in degrees in the range [-90.0, 90.0].
       * @param {Number} [east=0.0] The easternmost longitude in degrees in the range [-180.0, 180.0].
       * @param {Number} [north=0.0] The northernmost latitude in degrees in the range [-90.0, 90.0].
       * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       *
       * @example
       * var rectangle = Cesium.Rectangle.fromDegrees(0.0, 20.0, 10.0, 30.0);
       */
      Rectangle.fromDegrees = function(west, south, east, north, result) {
          west = CesiumMath.toRadians(defaultValue(west, 0.0));
          south = CesiumMath.toRadians(defaultValue(south, 0.0));
          east = CesiumMath.toRadians(defaultValue(east, 0.0));
          north = CesiumMath.toRadians(defaultValue(north, 0.0));
  
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
  
          result.west = west;
          result.south = south;
          result.east = east;
          result.north = north;
  
          return result;
      };
  
      /**
       * Creates a rectangle given the boundary longitude and latitude in radians.
       *
       * @param {Number} [west=0.0] The westernmost longitude in radians in the range [-Math.PI, Math.PI].
       * @param {Number} [south=0.0] The southernmost latitude in radians in the range [-Math.PI/2, Math.PI/2].
       * @param {Number} [east=0.0] The easternmost longitude in radians in the range [-Math.PI, Math.PI].
       * @param {Number} [north=0.0] The northernmost latitude in radians in the range [-Math.PI/2, Math.PI/2].
       * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       *
       * @example
       * var rectangle = Cesium.Rectangle.fromRadians(0.0, Math.PI/4, Math.PI/8, 3*Math.PI/4);
       */
      Rectangle.fromRadians = function(west, south, east, north, result) {
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
  
          result.west = defaultValue(west, 0.0);
          result.south = defaultValue(south, 0.0);
          result.east = defaultValue(east, 0.0);
          result.north = defaultValue(north, 0.0);
  
          return result;
      };
  
      /**
       * Creates the smallest possible Rectangle that encloses all positions in the provided array.
       *
       * @param {Cartographic[]} cartographics The list of Cartographic instances.
       * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       */
      Rectangle.fromCartographicArray = function(cartographics, result) {
                  Check.defined('cartographics', cartographics);
          
          var west = Number.MAX_VALUE;
          var east = -Number.MAX_VALUE;
          var westOverIDL = Number.MAX_VALUE;
          var eastOverIDL = -Number.MAX_VALUE;
          var south = Number.MAX_VALUE;
          var north = -Number.MAX_VALUE;
  
          for ( var i = 0, len = cartographics.length; i < len; i++) {
              var position = cartographics[i];
              west = Math.min(west, position.longitude);
              east = Math.max(east, position.longitude);
              south = Math.min(south, position.latitude);
              north = Math.max(north, position.latitude);
  
              var lonAdjusted = position.longitude >= 0 ?  position.longitude : position.longitude +  CesiumMath.TWO_PI;
              westOverIDL = Math.min(westOverIDL, lonAdjusted);
              eastOverIDL = Math.max(eastOverIDL, lonAdjusted);
          }
  
          if(east - west > eastOverIDL - westOverIDL) {
              west = westOverIDL;
              east = eastOverIDL;
  
              if (east > CesiumMath.PI) {
                  east = east - CesiumMath.TWO_PI;
              }
              if (west > CesiumMath.PI) {
                  west = west - CesiumMath.TWO_PI;
              }
          }
  
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
  
          result.west = west;
          result.south = south;
          result.east = east;
          result.north = north;
          return result;
      };
  
      /**
       * Creates the smallest possible Rectangle that encloses all positions in the provided array.
       *
       * @param {Cartesian3[]} cartesians The list of Cartesian instances.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid the cartesians are on.
       * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       */
      Rectangle.fromCartesianArray = function(cartesians, ellipsoid, result) {
                  Check.defined('cartesians', cartesians);
                  ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
  
          var west = Number.MAX_VALUE;
          var east = -Number.MAX_VALUE;
          var westOverIDL = Number.MAX_VALUE;
          var eastOverIDL = -Number.MAX_VALUE;
          var south = Number.MAX_VALUE;
          var north = -Number.MAX_VALUE;
  
          for ( var i = 0, len = cartesians.length; i < len; i++) {
              var position = ellipsoid.cartesianToCartographic(cartesians[i]);
              west = Math.min(west, position.longitude);
              east = Math.max(east, position.longitude);
              south = Math.min(south, position.latitude);
              north = Math.max(north, position.latitude);
  
              var lonAdjusted = position.longitude >= 0 ?  position.longitude : position.longitude +  CesiumMath.TWO_PI;
              westOverIDL = Math.min(westOverIDL, lonAdjusted);
              eastOverIDL = Math.max(eastOverIDL, lonAdjusted);
          }
  
          if(east - west > eastOverIDL - westOverIDL) {
              west = westOverIDL;
              east = eastOverIDL;
  
              if (east > CesiumMath.PI) {
                  east = east - CesiumMath.TWO_PI;
              }
              if (west > CesiumMath.PI) {
                  west = west - CesiumMath.TWO_PI;
              }
          }
  
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
  
          result.west = west;
          result.south = south;
          result.east = east;
          result.north = north;
          return result;
      };
  
      /**
       * Duplicates a Rectangle.
       *
       * @param {Rectangle} rectangle The rectangle to clone.
       * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided. (Returns undefined if rectangle is undefined)
       */
      Rectangle.clone = function(rectangle, result) {
          if (!defined(rectangle)) {
              return undefined;
          }
  
          if (!defined(result)) {
              return new Rectangle(rectangle.west, rectangle.south, rectangle.east, rectangle.north);
          }
  
          result.west = rectangle.west;
          result.south = rectangle.south;
          result.east = rectangle.east;
          result.north = rectangle.north;
          return result;
      };
  
      /**
       * Compares the provided Rectangles componentwise and returns
       * <code>true</code> if they pass an absolute or relative tolerance test,
       * <code>false</code> otherwise.
       *
       * @param {Rectangle} [left] The first Rectangle.
       * @param {Rectangle} [right] The second Rectangle.
       * @param {Number} absoluteEpsilon The absolute epsilon tolerance to use for equality testing.
       * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
       */
      Rectangle.equalsEpsilon = function(left, right, absoluteEpsilon) {
                  Check.typeOf.number('absoluteEpsilon', absoluteEpsilon);
          
          return (left === right) ||
                 (defined(left) &&
                  defined(right) &&
                  (Math.abs(left.west - right.west) <= absoluteEpsilon) &&
                  (Math.abs(left.south - right.south) <= absoluteEpsilon) &&
                  (Math.abs(left.east - right.east) <= absoluteEpsilon) &&
                  (Math.abs(left.north - right.north) <= absoluteEpsilon));
      };
  
      /**
       * Duplicates this Rectangle.
       *
       * @param {Rectangle} [result] The object onto which to store the result.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       */
      Rectangle.prototype.clone = function(result) {
          return Rectangle.clone(this, result);
      };
  
      /**
       * Compares the provided Rectangle with this Rectangle componentwise and returns
       * <code>true</code> if they are equal, <code>false</code> otherwise.
       *
       * @param {Rectangle} [other] The Rectangle to compare.
       * @returns {Boolean} <code>true</code> if the Rectangles are equal, <code>false</code> otherwise.
       */
      Rectangle.prototype.equals = function(other) {
          return Rectangle.equals(this, other);
      };
  
      /**
       * Compares the provided rectangles and returns <code>true</code> if they are equal,
       * <code>false</code> otherwise.
       *
       * @param {Rectangle} [left] The first Rectangle.
       * @param {Rectangle} [right] The second Rectangle.
       * @returns {Boolean} <code>true</code> if left and right are equal; otherwise <code>false</code>.
       */
      Rectangle.equals = function(left, right) {
          return (left === right) ||
                 ((defined(left)) &&
                  (defined(right)) &&
                  (left.west === right.west) &&
                  (left.south === right.south) &&
                  (left.east === right.east) &&
                  (left.north === right.north));
      };
  
      /**
       * Compares the provided Rectangle with this Rectangle componentwise and returns
       * <code>true</code> if they are within the provided epsilon,
       * <code>false</code> otherwise.
       *
       * @param {Rectangle} [other] The Rectangle to compare.
       * @param {Number} epsilon The epsilon to use for equality testing.
       * @returns {Boolean} <code>true</code> if the Rectangles are within the provided epsilon, <code>false</code> otherwise.
       */
      Rectangle.prototype.equalsEpsilon = function(other, epsilon) {
                  Check.typeOf.number('epsilon', epsilon);
          
          return Rectangle.equalsEpsilon(this, other, epsilon);
      };
  
      /**
       * Checks a Rectangle's properties and throws if they are not in valid ranges.
       *
       * @param {Rectangle} rectangle The rectangle to validate
       *
       * @exception {DeveloperError} <code>north</code> must be in the interval [<code>-Pi/2</code>, <code>Pi/2</code>].
       * @exception {DeveloperError} <code>south</code> must be in the interval [<code>-Pi/2</code>, <code>Pi/2</code>].
       * @exception {DeveloperError} <code>east</code> must be in the interval [<code>-Pi</code>, <code>Pi</code>].
       * @exception {DeveloperError} <code>west</code> must be in the interval [<code>-Pi</code>, <code>Pi</code>].
       */
      Rectangle.validate = function(rectangle) {
                  Check.typeOf.object('rectangle', rectangle);
  
          var north = rectangle.north;
          Check.typeOf.number.greaterThanOrEquals('north', north, -CesiumMath.PI_OVER_TWO);
          Check.typeOf.number.lessThanOrEquals('north', north, CesiumMath.PI_OVER_TWO);
  
          var south = rectangle.south;
          Check.typeOf.number.greaterThanOrEquals('south', south, -CesiumMath.PI_OVER_TWO);
          Check.typeOf.number.lessThanOrEquals('south', south, CesiumMath.PI_OVER_TWO);
  
          var west = rectangle.west;
          Check.typeOf.number.greaterThanOrEquals('west', west, -Math.PI);
          Check.typeOf.number.lessThanOrEquals('west', west, Math.PI);
  
          var east = rectangle.east;
          Check.typeOf.number.greaterThanOrEquals('east', east, -Math.PI);
          Check.typeOf.number.lessThanOrEquals('east', east, Math.PI);
              };
  
      /**
       * Computes the southwest corner of a rectangle.
       *
       * @param {Rectangle} rectangle The rectangle for which to find the corner
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.
       */
      Rectangle.southwest = function(rectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          if (!defined(result)) {
              return new Cartographic(rectangle.west, rectangle.south);
          }
          result.longitude = rectangle.west;
          result.latitude = rectangle.south;
          result.height = 0.0;
          return result;
      };
  
      /**
       * Computes the northwest corner of a rectangle.
       *
       * @param {Rectangle} rectangle The rectangle for which to find the corner
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.
       */
      Rectangle.northwest = function(rectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          if (!defined(result)) {
              return new Cartographic(rectangle.west, rectangle.north);
          }
          result.longitude = rectangle.west;
          result.latitude = rectangle.north;
          result.height = 0.0;
          return result;
      };
  
      /**
       * Computes the northeast corner of a rectangle.
       *
       * @param {Rectangle} rectangle The rectangle for which to find the corner
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.
       */
      Rectangle.northeast = function(rectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          if (!defined(result)) {
              return new Cartographic(rectangle.east, rectangle.north);
          }
          result.longitude = rectangle.east;
          result.latitude = rectangle.north;
          result.height = 0.0;
          return result;
      };
  
      /**
       * Computes the southeast corner of a rectangle.
       *
       * @param {Rectangle} rectangle The rectangle for which to find the corner
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.
       */
      Rectangle.southeast = function(rectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          if (!defined(result)) {
              return new Cartographic(rectangle.east, rectangle.south);
          }
          result.longitude = rectangle.east;
          result.latitude = rectangle.south;
          result.height = 0.0;
          return result;
      };
  
      /**
       * Computes the center of a rectangle.
       *
       * @param {Rectangle} rectangle The rectangle for which to find the center
       * @param {Cartographic} [result] The object onto which to store the result.
       * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.
       */
      Rectangle.center = function(rectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          var east = rectangle.east;
          var west = rectangle.west;
  
          if (east < west) {
              east += CesiumMath.TWO_PI;
          }
  
          var longitude = CesiumMath.negativePiToPi((west + east) * 0.5);
          var latitude = (rectangle.south + rectangle.north) * 0.5;
  
          if (!defined(result)) {
              return new Cartographic(longitude, latitude);
          }
  
          result.longitude = longitude;
          result.latitude = latitude;
          result.height = 0.0;
          return result;
      };
  
      /**
       * Computes the intersection of two rectangles.  This function assumes that the rectangle's coordinates are
       * latitude and longitude in radians and produces a correct intersection, taking into account the fact that
       * the same angle can be represented with multiple values as well as the wrapping of longitude at the
       * anti-meridian.  For a simple intersection that ignores these factors and can be used with projected
       * coordinates, see {@link Rectangle.simpleIntersection}.
       *
       * @param {Rectangle} rectangle On rectangle to find an intersection
       * @param {Rectangle} otherRectangle Another rectangle to find an intersection
       * @param {Rectangle} [result] The object onto which to store the result.
       * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.
       */
      Rectangle.intersection = function(rectangle, otherRectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          Check.typeOf.object('otherRectangle', otherRectangle);
          
          var rectangleEast = rectangle.east;
          var rectangleWest = rectangle.west;
  
          var otherRectangleEast = otherRectangle.east;
          var otherRectangleWest = otherRectangle.west;
  
          if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) {
              rectangleEast += CesiumMath.TWO_PI;
          } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) {
              otherRectangleEast += CesiumMath.TWO_PI;
          }
  
          if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) {
              otherRectangleWest += CesiumMath.TWO_PI;
          } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) {
              rectangleWest += CesiumMath.TWO_PI;
          }
  
          var west = CesiumMath.negativePiToPi(Math.max(rectangleWest, otherRectangleWest));
          var east = CesiumMath.negativePiToPi(Math.min(rectangleEast, otherRectangleEast));
  
          if ((rectangle.west < rectangle.east || otherRectangle.west < otherRectangle.east) && east <= west) {
              return undefined;
          }
  
          var south = Math.max(rectangle.south, otherRectangle.south);
          var north = Math.min(rectangle.north, otherRectangle.north);
  
          if (south >= north) {
              return undefined;
          }
  
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
          result.west = west;
          result.south = south;
          result.east = east;
          result.north = north;
          return result;
      };
  
      /**
       * Computes a simple intersection of two rectangles.  Unlike {@link Rectangle.intersection}, this function
       * does not attempt to put the angular coordinates into a consistent range or to account for crossing the
       * anti-meridian.  As such, it can be used for rectangles where the coordinates are not simply latitude
       * and longitude (i.e. projected coordinates).
       *
       * @param {Rectangle} rectangle On rectangle to find an intersection
       * @param {Rectangle} otherRectangle Another rectangle to find an intersection
       * @param {Rectangle} [result] The object onto which to store the result.
       * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.
       */
      Rectangle.simpleIntersection = function(rectangle, otherRectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          Check.typeOf.object('otherRectangle', otherRectangle);
          
          var west = Math.max(rectangle.west, otherRectangle.west);
          var south = Math.max(rectangle.south, otherRectangle.south);
          var east = Math.min(rectangle.east, otherRectangle.east);
          var north = Math.min(rectangle.north, otherRectangle.north);
  
          if (south >= north || west >= east) {
              return undefined;
          }
  
          if (!defined(result)) {
              return new Rectangle(west, south, east, north);
          }
  
          result.west = west;
          result.south = south;
          result.east = east;
          result.north = north;
          return result;
      };
  
      /**
       * Computes a rectangle that is the union of two rectangles.
       *
       * @param {Rectangle} rectangle A rectangle to enclose in rectangle.
       * @param {Rectangle} otherRectangle A rectangle to enclose in a rectangle.
       * @param {Rectangle} [result] The object onto which to store the result.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.
       */
      Rectangle.union = function(rectangle, otherRectangle, result) {
                  Check.typeOf.object('rectangle', rectangle);
          Check.typeOf.object('otherRectangle', otherRectangle);
          
          if (!defined(result)) {
              result = new Rectangle();
          }
  
          var rectangleEast = rectangle.east;
          var rectangleWest = rectangle.west;
  
          var otherRectangleEast = otherRectangle.east;
          var otherRectangleWest = otherRectangle.west;
  
          if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) {
              rectangleEast += CesiumMath.TWO_PI;
          } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) {
              otherRectangleEast += CesiumMath.TWO_PI;
          }
  
          if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) {
              otherRectangleWest += CesiumMath.TWO_PI;
          } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) {
              rectangleWest += CesiumMath.TWO_PI;
          }
  
          var west = CesiumMath.convertLongitudeRange(Math.min(rectangleWest, otherRectangleWest));
          var east = CesiumMath.convertLongitudeRange(Math.max(rectangleEast, otherRectangleEast));
  
          result.west = west;
          result.south = Math.min(rectangle.south, otherRectangle.south);
          result.east = east;
          result.north = Math.max(rectangle.north, otherRectangle.north);
  
          return result;
      };
  
      /**
       * Computes a rectangle by enlarging the provided rectangle until it contains the provided cartographic.
       *
       * @param {Rectangle} rectangle A rectangle to expand.
       * @param {Cartographic} cartographic A cartographic to enclose in a rectangle.
       * @param {Rectangle} [result] The object onto which to store the result.
       * @returns {Rectangle} The modified result parameter or a new Rectangle instance if one was not provided.
       */
      Rectangle.expand = function(rectangle, cartographic, result) {
                  Check.typeOf.object('rectangle', rectangle);
          Check.typeOf.object('cartographic', cartographic);
          
          if (!defined(result)) {
              result = new Rectangle();
          }
  
          result.west = Math.min(rectangle.west, cartographic.longitude);
          result.south = Math.min(rectangle.south, cartographic.latitude);
          result.east = Math.max(rectangle.east, cartographic.longitude);
          result.north = Math.max(rectangle.north, cartographic.latitude);
  
          return result;
      };
  
      /**
       * Returns true if the cartographic is on or inside the rectangle, false otherwise.
       *
       * @param {Rectangle} rectangle The rectangle
       * @param {Cartographic} cartographic The cartographic to test.
       * @returns {Boolean} true if the provided cartographic is inside the rectangle, false otherwise.
       */
      Rectangle.contains = function(rectangle, cartographic) {
                  Check.typeOf.object('rectangle', rectangle);
          Check.typeOf.object('cartographic', cartographic);
          
          var longitude = cartographic.longitude;
          var latitude = cartographic.latitude;
  
          var west = rectangle.west;
          var east = rectangle.east;
  
          if (east < west) {
              east += CesiumMath.TWO_PI;
              if (longitude < 0.0) {
                  longitude += CesiumMath.TWO_PI;
              }
          }
          return (longitude > west || CesiumMath.equalsEpsilon(longitude, west, CesiumMath.EPSILON14)) &&
                 (longitude < east || CesiumMath.equalsEpsilon(longitude, east, CesiumMath.EPSILON14)) &&
                 latitude >= rectangle.south &&
                 latitude <= rectangle.north;
      };
  
      var subsampleLlaScratch = new Cartographic();
      /**
       * Samples a rectangle so that it includes a list of Cartesian points suitable for passing to
       * {@link BoundingSphere#fromPoints}.  Sampling is necessary to account
       * for rectangles that cover the poles or cross the equator.
       *
       * @param {Rectangle} rectangle The rectangle to subsample.
       * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use.
       * @param {Number} [surfaceHeight=0.0] The height of the rectangle above the ellipsoid.
       * @param {Cartesian3[]} [result] The array of Cartesians onto which to store the result.
       * @returns {Cartesian3[]} The modified result parameter or a new Array of Cartesians instances if none was provided.
       */
      Rectangle.subsample = function(rectangle, ellipsoid, surfaceHeight, result) {
                  Check.typeOf.object('rectangle', rectangle);
          
          ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);
          surfaceHeight = defaultValue(surfaceHeight, 0.0);
  
          if (!defined(result)) {
              result = [];
          }
          var length = 0;
  
          var north = rectangle.north;
          var south = rectangle.south;
          var east = rectangle.east;
          var west = rectangle.west;
  
          var lla = subsampleLlaScratch;
          lla.height = surfaceHeight;
  
          lla.longitude = west;
          lla.latitude = north;
          result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
          length++;
  
          lla.longitude = east;
          result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
          length++;
  
          lla.latitude = south;
          result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
          length++;
  
          lla.longitude = west;
          result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
          length++;
  
          if (north < 0.0) {
              lla.latitude = north;
          } else if (south > 0.0) {
              lla.latitude = south;
          } else {
              lla.latitude = 0.0;
          }
  
          for ( var i = 1; i < 8; ++i) {
              lla.longitude = -Math.PI + i * CesiumMath.PI_OVER_TWO;
              if (Rectangle.contains(rectangle, lla)) {
                  result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
                  length++;
              }
          }
  
          if (lla.latitude === 0.0) {
              lla.longitude = west;
              result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
              length++;
              lla.longitude = east;
              result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);
              length++;
          }
          result.length = length;
          return result;
      };
  
      /**
       * The largest possible rectangle.
       *
       * @type {Rectangle}
       * @constant
      */
      Rectangle.MAX_VALUE = freezeObject(new Rectangle(-Math.PI, -CesiumMath.PI_OVER_TWO, Math.PI, CesiumMath.PI_OVER_TWO));
  
      return Rectangle;
  });
  
  /**
    @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/formatError',[
          './defined'
      ], function(
          defined) {
      'use strict';
  
      /**
       * Formats an error object into a String.  If available, uses name, message, and stack
       * properties, otherwise, falls back on toString().
       *
       * @exports formatError
       *
       * @param {*} object The item to find in the array.
       * @returns {String} A string containing the formatted error.
       */
      function formatError(object) {
          var result;
  
          var name = object.name;
          var message = object.message;
          if (defined(name) && defined(message)) {
              result = name + ': ' + message;
          } else {
              result = object.toString();
          }
  
          var stack = object.stack;
          if (defined(stack)) {
              result += '\n' + stack;
          }
  
          return result;
      }
  
      return formatError;
  });
  
  define('Workers/createTaskProcessorWorker',[
          '../ThirdParty/when',
          '../Core/defaultValue',
          '../Core/defined',
          '../Core/formatError'
      ], function(
          when,
          defaultValue,
          defined,
          formatError) {
      'use strict';
  
      // createXXXGeometry functions may return Geometry or a Promise that resolves to Geometry
      // if the function requires access to ApproximateTerrainHeights.
      // For fully synchronous functions, just wrapping the function call in a `when` Promise doesn't
      // handle errors correctly, hence try-catch
      function callAndWrap(workerFunction, parameters, transferableObjects) {
          var resultOrPromise;
          try {
              resultOrPromise = workerFunction(parameters, transferableObjects);
              return resultOrPromise; // errors handled by Promise
          } catch (e) {
              return when.reject(e);
          }
      }
  
      /**
       * Creates an adapter function to allow a calculation function to operate as a Web Worker,
       * paired with TaskProcessor, to receive tasks and return results.
       *
       * @exports createTaskProcessorWorker
       *
       * @param {createTaskProcessorWorker~WorkerFunction} workerFunction The calculation function,
       *        which takes parameters and returns a result.
       * @returns {createTaskProcessorWorker~TaskProcessorWorkerFunction} A function that adapts the
       *          calculation function to work as a Web Worker onmessage listener with TaskProcessor.
       *
       *
       * @example
       * function doCalculation(parameters, transferableObjects) {
       *   // calculate some result using the inputs in parameters
       *   return result;
       * }
       *
       * return Cesium.createTaskProcessorWorker(doCalculation);
       * // the resulting function is compatible with TaskProcessor
       *
       * @see TaskProcessor
       * @see {@link http://www.w3.org/TR/workers/|Web Workers}
       * @see {@link http://www.w3.org/TR/html5/common-dom-interfaces.html#transferable-objects|Transferable objects}
       */
      function createTaskProcessorWorker(workerFunction) {
          var postMessage;
  
          return function(event) {
              /*global self*/
              var data = event.data;
  
              var transferableObjects = [];
              var responseMessage = {
                  id : data.id,
                  result : undefined,
                  error : undefined
              };
  
              return when(callAndWrap(workerFunction, data.parameters, transferableObjects))
                  .then(function(result) {
                      responseMessage.result = result;
                  })
                  .otherwise(function(e) {
                      if (e instanceof Error) {
                          // Errors can't be posted in a message, copy the properties
                          responseMessage.error = {
                              name : e.name,
                              message : e.message,
                              stack : e.stack
                          };
                      } else {
                          responseMessage.error = e;
                      }
                  })
                  .always(function() {
                      if (!defined(postMessage)) {
                          postMessage = defaultValue(self.webkitPostMessage, self.postMessage);
                      }
  
                      if (!data.canTransferArrayBuffer) {
                          transferableObjects.length = 0;
                      }
  
                      try {
                          postMessage(responseMessage, transferableObjects);
                      } catch (e) {
                          // something went wrong trying to post the message, post a simpler
                          // error that we can be sure will be cloneable
                          responseMessage.result = undefined;
                          responseMessage.error = 'postMessage failed with error: ' + formatError(e) + '\n  with responseMessage: ' + JSON.stringify(responseMessage);
                          postMessage(responseMessage);
                      }
                  });
          };
      }
  
      /**
       * A function that performs a calculation in a Web Worker.
       * @callback createTaskProcessorWorker~WorkerFunction
       *
       * @param {Object} parameters Parameters to the calculation.
       * @param {Array} transferableObjects An array that should be filled with references to objects inside
       *        the result that should be transferred back to the main document instead of copied.
       * @returns {Object} The result of the calculation.
       *
       * @example
       * function calculate(parameters, transferableObjects) {
       *   // perform whatever calculation is necessary.
       *   var typedArray = new Float32Array(0);
       *
       *   // typed arrays are transferable
       *   transferableObjects.push(typedArray)
       *
       *   return {
       *      typedArray : typedArray
       *   };
       * }
       */
  
      /**
       * A Web Worker message event handler function that handles the interaction with TaskProcessor,
       * specifically, task ID management and posting a response message containing the result.
       * @callback createTaskProcessorWorker~TaskProcessorWorkerFunction
       *
       * @param {Object} event The onmessage event object.
       */
  
      return createTaskProcessorWorker;
  });
  
  define('Workers/createVectorTilePoints',[
          '../Core/AttributeCompression',
          '../Core/Cartesian3',
          '../Core/Cartographic',
          '../Core/Ellipsoid',
          '../Core/Math',
          '../Core/Rectangle',
          './createTaskProcessorWorker'
      ], function(
          AttributeCompression,
          Cartesian3,
          Cartographic,
          Ellipsoid,
          CesiumMath,
          Rectangle,
          createTaskProcessorWorker) {
      'use strict';
  
      var maxShort = 32767;
  
      var scratchBVCartographic = new Cartographic();
      var scratchEncodedPosition = new Cartesian3();
  
      var scratchRectangle = new Rectangle();
      var scratchEllipsoid = new Ellipsoid();
      var scratchMinMaxHeights = {
          min : undefined,
          max : undefined
      };
  
      function unpackBuffer(packedBuffer) {
          packedBuffer = new Float64Array(packedBuffer);
  
          var offset = 0;
          scratchMinMaxHeights.min = packedBuffer[offset++];
          scratchMinMaxHeights.max = packedBuffer[offset++];
  
          Rectangle.unpack(packedBuffer, offset, scratchRectangle);
          offset += Rectangle.packedLength;
  
          Ellipsoid.unpack(packedBuffer, offset, scratchEllipsoid);
      }
  
      function createVectorTilePoints(parameters, transferableObjects) {
          var positions = new Uint16Array(parameters.positions);
  
          unpackBuffer(parameters.packedBuffer);
          var rectangle = scratchRectangle;
          var ellipsoid = scratchEllipsoid;
          var minimumHeight = scratchMinMaxHeights.min;
          var maximumHeight = scratchMinMaxHeights.max;
  
          var positionsLength = positions.length / 3;
          var uBuffer = positions.subarray(0, positionsLength);
          var vBuffer = positions.subarray(positionsLength, 2 * positionsLength);
          var heightBuffer = positions.subarray(2 * positionsLength, 3 * positionsLength);
          AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
  
          var decoded = new Float64Array(positions.length);
          for (var i = 0; i < positionsLength; ++i) {
              var u = uBuffer[i];
              var v = vBuffer[i];
              var h = heightBuffer[i];
  
              var lon = CesiumMath.lerp(rectangle.west, rectangle.east, u / maxShort);
              var lat = CesiumMath.lerp(rectangle.south, rectangle.north, v / maxShort);
              var alt = CesiumMath.lerp(minimumHeight, maximumHeight, h / maxShort);
  
              var cartographic = Cartographic.fromRadians(lon, lat, alt, scratchBVCartographic);
              var decodedPosition = ellipsoid.cartographicToCartesian(cartographic, scratchEncodedPosition);
              Cartesian3.pack(decodedPosition, decoded, i * 3);
          }
  
          transferableObjects.push(decoded.buffer);
  
          return {
              positions : decoded.buffer
          };
      }
  
      return createTaskProcessorWorker(createVectorTilePoints);
  });
  
  }());