UNPKG

mercator-proj

Version:

[![Build Status](https://img.shields.io/travis/com/sakitam-gis/mercator-proj)](https://travis-ci.com/sakitam-gis/mercator-proj) [![GZIP size](http://img.badgesize.io/https://unpkg.com/mercator-proj/dist/mercator-proj.min.js?compression=gzip&label=gzip%20s

2,408 lines 89.8 kB
/*!
 * author: sakitam-fdd <smilefdd@gmail.com>
 * mercator-proj v0.0.7
 * build-time: 2021-3-4 20:41
 * LICENSE: MIT
 * (c) 2020-2021 https://github.com/sakitam-gis/mercator-proj
 */
(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.mercatorProj = {}));
}(this, (function (exports) { 'use strict';

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }

  function _slicedToArray(arr, i) {
    return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  }

  function _arrayWithHoles(arr) {
    if (Array.isArray(arr)) return arr;
  }

  function _iterableToArrayLimit(arr, i) {
    if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;

    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);

        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"] != null) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }

    return _arr;
  }

  function _unsupportedIterableToArray(o, minLen) {
    if (!o) return;
    if (typeof o === "string") return _arrayLikeToArray(o, minLen);
    var n = Object.prototype.toString.call(o).slice(8, -1);
    if (n === "Object" && o.constructor) n = o.constructor.name;
    if (n === "Map" || n === "Set") return Array.from(o);
    if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  }

  function _arrayLikeToArray(arr, len) {
    if (len == null || len > arr.length) len = arr.length;

    for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

    return arr2;
  }

  function _nonIterableRest() {
    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  /**
   * Common utilities
   * @module glMatrix
   */
  var ARRAY_TYPE = typeof Float32Array !== 'undefined' ? Float32Array : Array;
  if (!Math.hypot) Math.hypot = function () {
    var y = 0,
        i = arguments.length;

    while (i--) {
      y += arguments[i] * arguments[i];
    }

    return Math.sqrt(y);
  };

  /**
   * Inverts a mat4
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the source matrix
   * @returns {mat4} out
   */

  function invert(out, a) {
    var a00 = a[0],
        a01 = a[1],
        a02 = a[2],
        a03 = a[3];
    var a10 = a[4],
        a11 = a[5],
        a12 = a[6],
        a13 = a[7];
    var a20 = a[8],
        a21 = a[9],
        a22 = a[10],
        a23 = a[11];
    var a30 = a[12],
        a31 = a[13],
        a32 = a[14],
        a33 = a[15];
    var b00 = a00 * a11 - a01 * a10;
    var b01 = a00 * a12 - a02 * a10;
    var b02 = a00 * a13 - a03 * a10;
    var b03 = a01 * a12 - a02 * a11;
    var b04 = a01 * a13 - a03 * a11;
    var b05 = a02 * a13 - a03 * a12;
    var b06 = a20 * a31 - a21 * a30;
    var b07 = a20 * a32 - a22 * a30;
    var b08 = a20 * a33 - a23 * a30;
    var b09 = a21 * a32 - a22 * a31;
    var b10 = a21 * a33 - a23 * a31;
    var b11 = a22 * a33 - a23 * a32; // Calculate the determinant

    var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;

    if (!det) {
      return null;
    }

    det = 1.0 / det;
    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
    out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
    out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
    out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
    out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
    out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
    out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
    out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
    out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
    out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
    out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
    out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
    out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
    out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
    out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
    out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
    return out;
  }
  /**
   * Multiplies two mat4s
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the first operand
   * @param {ReadonlyMat4} b the second operand
   * @returns {mat4} out
   */

  function multiply(out, a, b) {
    var a00 = a[0],
        a01 = a[1],
        a02 = a[2],
        a03 = a[3];
    var a10 = a[4],
        a11 = a[5],
        a12 = a[6],
        a13 = a[7];
    var a20 = a[8],
        a21 = a[9],
        a22 = a[10],
        a23 = a[11];
    var a30 = a[12],
        a31 = a[13],
        a32 = a[14],
        a33 = a[15]; // Cache only the current line of the second matrix

    var b0 = b[0],
        b1 = b[1],
        b2 = b[2],
        b3 = b[3];
    out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[4];
    b1 = b[5];
    b2 = b[6];
    b3 = b[7];
    out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[8];
    b1 = b[9];
    b2 = b[10];
    b3 = b[11];
    out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[12];
    b1 = b[13];
    b2 = b[14];
    b3 = b[15];
    out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    return out;
  }
  /**
   * Translate a mat4 by the given vector
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the matrix to translate
   * @param {ReadonlyVec3} v vector to translate by
   * @returns {mat4} out
   */

  function translate(out, a, v) {
    var x = v[0],
        y = v[1],
        z = v[2];
    var a00, a01, a02, a03;
    var a10, a11, a12, a13;
    var a20, a21, a22, a23;

    if (a === out) {
      out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
      out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
      out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
      out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
    } else {
      a00 = a[0];
      a01 = a[1];
      a02 = a[2];
      a03 = a[3];
      a10 = a[4];
      a11 = a[5];
      a12 = a[6];
      a13 = a[7];
      a20 = a[8];
      a21 = a[9];
      a22 = a[10];
      a23 = a[11];
      out[0] = a00;
      out[1] = a01;
      out[2] = a02;
      out[3] = a03;
      out[4] = a10;
      out[5] = a11;
      out[6] = a12;
      out[7] = a13;
      out[8] = a20;
      out[9] = a21;
      out[10] = a22;
      out[11] = a23;
      out[12] = a00 * x + a10 * y + a20 * z + a[12];
      out[13] = a01 * x + a11 * y + a21 * z + a[13];
      out[14] = a02 * x + a12 * y + a22 * z + a[14];
      out[15] = a03 * x + a13 * y + a23 * z + a[15];
    }

    return out;
  }
  /**
   * Scales the mat4 by the dimensions in the given vec3 not using vectorization
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the matrix to scale
   * @param {ReadonlyVec3} v the vec3 to scale the matrix by
   * @returns {mat4} out
   **/

  function scale(out, a, v) {
    var x = v[0],
        y = v[1],
        z = v[2];
    out[0] = a[0] * x;
    out[1] = a[1] * x;
    out[2] = a[2] * x;
    out[3] = a[3] * x;
    out[4] = a[4] * y;
    out[5] = a[5] * y;
    out[6] = a[6] * y;
    out[7] = a[7] * y;
    out[8] = a[8] * z;
    out[9] = a[9] * z;
    out[10] = a[10] * z;
    out[11] = a[11] * z;
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
    return out;
  }
  /**
   * Rotates a matrix by the given angle around the X axis
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */

  function rotateX(out, a, rad) {
    var s = Math.sin(rad);
    var c = Math.cos(rad);
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];
    var a20 = a[8];
    var a21 = a[9];
    var a22 = a[10];
    var a23 = a[11];

    if (a !== out) {
      // If the source and destination differ, copy the unchanged rows
      out[0] = a[0];
      out[1] = a[1];
      out[2] = a[2];
      out[3] = a[3];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
    } // Perform axis-specific matrix multiplication


    out[4] = a10 * c + a20 * s;
    out[5] = a11 * c + a21 * s;
    out[6] = a12 * c + a22 * s;
    out[7] = a13 * c + a23 * s;
    out[8] = a20 * c - a10 * s;
    out[9] = a21 * c - a11 * s;
    out[10] = a22 * c - a12 * s;
    out[11] = a23 * c - a13 * s;
    return out;
  }
  /**
   * Rotates a matrix by the given angle around the Z axis
   *
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the matrix to rotate
   * @param {Number} rad the angle to rotate the matrix by
   * @returns {mat4} out
   */

  function rotateZ(out, a, rad) {
    var s = Math.sin(rad);
    var c = Math.cos(rad);
    var a00 = a[0];
    var a01 = a[1];
    var a02 = a[2];
    var a03 = a[3];
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];

    if (a !== out) {
      // If the source and destination differ, copy the unchanged last row
      out[8] = a[8];
      out[9] = a[9];
      out[10] = a[10];
      out[11] = a[11];
      out[12] = a[12];
      out[13] = a[13];
      out[14] = a[14];
      out[15] = a[15];
    } // Perform axis-specific matrix multiplication


    out[0] = a00 * c + a10 * s;
    out[1] = a01 * c + a11 * s;
    out[2] = a02 * c + a12 * s;
    out[3] = a03 * c + a13 * s;
    out[4] = a10 * c - a00 * s;
    out[5] = a11 * c - a01 * s;
    out[6] = a12 * c - a02 * s;
    out[7] = a13 * c - a03 * s;
    return out;
  }
  /**
   * Generates a perspective projection matrix with the given bounds.
   * Passing null/undefined/no value for far will generate infinite projection matrix.
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} fovy Vertical field of view in radians
   * @param {number} aspect Aspect ratio. typically viewport width/height
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum, can be null or Infinity
   * @returns {mat4} out
   */

  function perspective(out, fovy, aspect, near, far) {
    var f = 1.0 / Math.tan(fovy / 2),
        nf;
    out[0] = f / aspect;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = f;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[11] = -1;
    out[12] = 0;
    out[13] = 0;
    out[15] = 0;

    if (far != null && far !== Infinity) {
      nf = 1 / (near - far);
      out[10] = (far + near) * nf;
      out[14] = 2 * far * near * nf;
    } else {
      out[10] = -1;
      out[14] = -2 * near;
    }

    return out;
  }
  /**
   * Generates a orthogonal projection matrix with the given bounds
   *
   * @param {mat4} out mat4 frustum matrix will be written into
   * @param {number} left Left bound of the frustum
   * @param {number} right Right bound of the frustum
   * @param {number} bottom Bottom bound of the frustum
   * @param {number} top Top bound of the frustum
   * @param {number} near Near bound of the frustum
   * @param {number} far Far bound of the frustum
   * @returns {mat4} out
   */

  function ortho(out, left, right, bottom, top, near, far) {
    var lr = 1 / (left - right);
    var bt = 1 / (bottom - top);
    var nf = 1 / (near - far);
    out[0] = -2 * lr;
    out[1] = 0;
    out[2] = 0;
    out[3] = 0;
    out[4] = 0;
    out[5] = -2 * bt;
    out[6] = 0;
    out[7] = 0;
    out[8] = 0;
    out[9] = 0;
    out[10] = 2 * nf;
    out[11] = 0;
    out[12] = (left + right) * lr;
    out[13] = (top + bottom) * bt;
    out[14] = (far + near) * nf;
    out[15] = 1;
    return out;
  }

  /**
   * 3 Dimensional Vector
   * @module vec3
   */

  /**
   * Creates a new, empty vec3
   *
   * @returns {vec3} a new 3D vector
   */

  function create() {
    var out = new ARRAY_TYPE(3);

    if (ARRAY_TYPE != Float32Array) {
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
    }

    return out;
  }
  /**
   * Negates the components of a vec3
   *
   * @param {vec3} out the receiving vector
   * @param {ReadonlyVec3} a vector to negate
   * @returns {vec3} out
   */

  function negate(out, a) {
    out[0] = -a[0];
    out[1] = -a[1];
    out[2] = -a[2];
    return out;
  }
  /**
   * Transforms the vec3 with a mat4.
   * 4th vector component is implicitly '1'
   *
   * @param {vec3} out the receiving vector
   * @param {ReadonlyVec3} a the vector to transform
   * @param {ReadonlyMat4} m matrix to transform with
   * @returns {vec3} out
   */

  function transformMat4(out, a, m) {
    var x = a[0],
        y = a[1],
        z = a[2];
    var w = m[3] * x + m[7] * y + m[11] * z + m[15];
    w = w || 1.0;
    out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w;
    out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w;
    out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w;
    return out;
  }
  /**
   * Perform some operation over an array of vec3s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec3. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec3s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */

  (function () {
    var vec = create();
    return function (a, stride, offset, count, fn, arg) {
      var i, l;

      if (!stride) {
        stride = 3;
      }

      if (!offset) {
        offset = 0;
      }

      if (count) {
        l = Math.min(count * stride + offset, a.length);
      } else {
        l = a.length;
      }

      for (i = offset; i < l; i += stride) {
        vec[0] = a[i];
        vec[1] = a[i + 1];
        vec[2] = a[i + 2];
        fn(vec, vec, arg);
        a[i] = vec[0];
        a[i + 1] = vec[1];
        a[i + 2] = vec[2];
      }

      return a;
    };
  })();

  /**
   * 2 Dimensional Vector
   * @module vec2
   */

  /**
   * Creates a new, empty vec2
   *
   * @returns {vec2} a new 2D vector
   */

  function create$1() {
    var out = new ARRAY_TYPE(2);

    if (ARRAY_TYPE != Float32Array) {
      out[0] = 0;
      out[1] = 0;
    }

    return out;
  }
  /**
   * Adds two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {ReadonlyVec2} a the first operand
   * @param {ReadonlyVec2} b the second operand
   * @returns {vec2} out
   */

  function add(out, a, b) {
    out[0] = a[0] + b[0];
    out[1] = a[1] + b[1];
    return out;
  }
  /**
   * Negates the components of a vec2
   *
   * @param {vec2} out the receiving vector
   * @param {ReadonlyVec2} a vector to negate
   * @returns {vec2} out
   */

  function negate$1(out, a) {
    out[0] = -a[0];
    out[1] = -a[1];
    return out;
  }
  /**
   * Performs a linear interpolation between two vec2's
   *
   * @param {vec2} out the receiving vector
   * @param {ReadonlyVec2} a the first operand
   * @param {ReadonlyVec2} b the second operand
   * @param {Number} t interpolation amount, in the range [0-1], between the two inputs
   * @returns {vec2} out
   */

  function lerp(out, a, b, t) {
    var ax = a[0],
        ay = a[1];
    out[0] = ax + t * (b[0] - ax);
    out[1] = ay + t * (b[1] - ay);
    return out;
  }
  /**
   * Perform some operation over an array of vec2s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec2. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec2s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */

  (function () {
    var vec = create$1();
    return function (a, stride, offset, count, fn, arg) {
      var i, l;

      if (!stride) {
        stride = 2;
      }

      if (!offset) {
        offset = 0;
      }

      if (count) {
        l = Math.min(count * stride + offset, a.length);
      } else {
        l = a.length;
      }

      for (i = offset; i < l; i += stride) {
        vec[0] = a[i];
        vec[1] = a[i + 1];
        fn(vec, vec, arg);
        a[i] = vec[0];
        a[i + 1] = vec[1];
      }

      return a;
    };
  })();

  function isArray(value) {
    return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
  }
  var EPSILON = 1e-12;
  function equals(a, b, epsilon) {
    var oldEpsilon = EPSILON;

    if (epsilon) {
      EPSILON = epsilon;
    }

    try {
      if (a === b) {
        return true;
      }

      if (isArray(a) && isArray(b) && typeof a !== 'number' && typeof b !== 'number') {
        if ((a === null || a === void 0 ? void 0 : a.length) !== (b === null || b === void 0 ? void 0 : b.length)) {
          return false;
        }

        for (var i = 0; i < a.length; ++i) {
          // eslint-disable-next-line max-depth
          if (!equals(a[i], b[i])) {
            return false;
          }
        }

        return true;
      }

      if (typeof a === 'number' && typeof b === 'number' && Number.isFinite(a) && Number.isFinite(b)) {
        return Math.abs(a - b) <= EPSILON * Math.max(1.0, Math.abs(a), Math.abs(b));
      }

      return false;
    } finally {
      EPSILON = oldEpsilon;
    }
  }

  /**
   * 4 Dimensional Vector
   * @module vec4
   */

  /**
   * Creates a new, empty vec4
   *
   * @returns {vec4} a new 4D vector
   */

  function create$2() {
    var out = new ARRAY_TYPE(4);

    if (ARRAY_TYPE != Float32Array) {
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
    }

    return out;
  }
  /**
   * Scales a vec4 by a scalar number
   *
   * @param {vec4} out the receiving vector
   * @param {ReadonlyVec4} a the vector to scale
   * @param {Number} b amount to scale the vector by
   * @returns {vec4} out
   */

  function scale$1(out, a, b) {
    out[0] = a[0] * b;
    out[1] = a[1] * b;
    out[2] = a[2] * b;
    out[3] = a[3] * b;
    return out;
  }
  /**
   * Transforms the vec4 with a mat4.
   *
   * @param {vec4} out the receiving vector
   * @param {ReadonlyVec4} a the vector to transform
   * @param {ReadonlyMat4} m matrix to transform with
   * @returns {vec4} out
   */

  function transformMat4$1(out, a, m) {
    var x = a[0],
        y = a[1],
        z = a[2],
        w = a[3];
    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
    out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
    return out;
  }
  /**
   * Perform some operation over an array of vec4s.
   *
   * @param {Array} a the array of vectors to iterate over
   * @param {Number} stride Number of elements between the start of each vec4. If 0 assumes tightly packed
   * @param {Number} offset Number of elements to skip at the beginning of the array
   * @param {Number} count Number of vec4s to iterate over. If 0 iterates over entire array
   * @param {Function} fn Function to call for each vector in the array
   * @param {Object} [arg] additional argument to pass to fn
   * @returns {Array} a
   * @function
   */

  (function () {
    var vec = create$2();
    return function (a, stride, offset, count, fn, arg) {
      var i, l;

      if (!stride) {
        stride = 4;
      }

      if (!offset) {
        offset = 0;
      }

      if (count) {
        l = Math.min(count * stride + offset, a.length);
      } else {
        l = a.length;
      }

      for (i = offset; i < l; i += stride) {
        vec[0] = a[i];
        vec[1] = a[i + 1];
        vec[2] = a[i + 2];
        vec[3] = a[i + 3];
        fn(vec, vec, arg);
        a[i] = vec[0];
        a[i + 1] = vec[1];
        a[i + 2] = vec[2];
        a[i + 3] = vec[3];
      }

      return a;
    };
  })();

  // @ts-ignore

  function lengthSquared(arr) {
    var length = 0; // eslint-disable-next-line @typescript-eslint/prefer-for-of

    for (var i = 0; i < arr.length; ++i) {
      length += arr[i] * arr[i];
    }

    return length;
  } // eslint-disable-next-line max-params


  function getFrustumPlane(a, b, c, d) {
    var scratchVector = [a, b, c];
    var L = Math.sqrt(lengthSquared(scratchVector));
    return {
      distance: d / L,
      normal: [-a / L, -b / L, -c / L]
    };
  } // Helper, avoids low-precision 32 bit matrices from gl-matrix mat4.create()


  function createMat4() {
    return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
  }
  function getCameraPosition(viewMatrixInverse) {
    // Read the translation from the inverse view matrix
    return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
  } // https://www.gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf

  function getFrustumPlanes(viewProjectionMatrix) {
    // @ts-ignore
    var planes = {};
    planes.left = getFrustumPlane(viewProjectionMatrix[3] + viewProjectionMatrix[0], viewProjectionMatrix[7] + viewProjectionMatrix[4], viewProjectionMatrix[11] + viewProjectionMatrix[8], viewProjectionMatrix[15] + viewProjectionMatrix[12]);
    planes.right = getFrustumPlane(viewProjectionMatrix[3] - viewProjectionMatrix[0], viewProjectionMatrix[7] - viewProjectionMatrix[4], viewProjectionMatrix[11] - viewProjectionMatrix[8], viewProjectionMatrix[15] - viewProjectionMatrix[12]);
    planes.bottom = getFrustumPlane(viewProjectionMatrix[3] + viewProjectionMatrix[1], viewProjectionMatrix[7] + viewProjectionMatrix[5], viewProjectionMatrix[11] + viewProjectionMatrix[9], viewProjectionMatrix[15] + viewProjectionMatrix[13]);
    planes.top = getFrustumPlane(viewProjectionMatrix[3] - viewProjectionMatrix[1], viewProjectionMatrix[7] - viewProjectionMatrix[5], viewProjectionMatrix[11] - viewProjectionMatrix[9], viewProjectionMatrix[15] - viewProjectionMatrix[13]);
    planes.near = getFrustumPlane(viewProjectionMatrix[3] + viewProjectionMatrix[2], viewProjectionMatrix[7] + viewProjectionMatrix[6], viewProjectionMatrix[11] + viewProjectionMatrix[10], viewProjectionMatrix[15] + viewProjectionMatrix[14]);
    planes.far = getFrustumPlane(viewProjectionMatrix[3] - viewProjectionMatrix[2], viewProjectionMatrix[7] - viewProjectionMatrix[6], viewProjectionMatrix[11] - viewProjectionMatrix[10], viewProjectionMatrix[15] - viewProjectionMatrix[14]);
    return planes;
  }
  function transformVector(matrix, vector) {
    var result = transformMat4$1([], vector, matrix);
    scale$1(result, result, 1 / result[3]);
    return result;
  }

  function assert(condition, message) {
    if (!condition) {
      throw new Error(message || 'mercator-proj: assertion failed.');
    }
  }

  // @ts-ignore
  var DEGREES_TO_RADIANS = Math.PI / 180;
  /*
   * Returns the quad at the intersection of the frustum and the given z plane
   * @param {WebMercatorViewport} viewport
   * @param {Number} z - elevation in meters
   */

  function getBounds(viewport) {
    var z = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var width = viewport.width,
        height = viewport.height,
        unproject = viewport.unproject;
    var unprojectOps = {
      targetZ: z
    };
    var bottomLeft = unproject([0, height], unprojectOps);
    var bottomRight = unproject([width, height], unprojectOps);
    var topLeft;
    var topRight;
    var halfFov = Math.atan(0.5 / viewport.altitude);
    var angleToGround = (90 - viewport.pitch) * DEGREES_TO_RADIANS; // The top plane is parallel to the ground if halfFov == angleToGround

    if (halfFov > angleToGround - 0.01) {
      // intersect with the far plane
      topLeft = unprojectOnFarPlane(viewport, 0, z);
      topRight = unprojectOnFarPlane(viewport, width, z);
    } else {
      // intersect with the top plane
      topLeft = unproject([0, 0], unprojectOps);
      topRight = unproject([width, 0], unprojectOps);
    }

    return [bottomLeft, bottomRight, topRight, topLeft];
  }
  /*
   * Find a point on the far clipping plane of the viewport
   * @param {WebMercatorViewport} viewport
   * @param {Number} x - projected x in screen space
   * @param {Number} targetZ - the elevation of the point in meters
   */

  function unprojectOnFarPlane(viewport, x, targetZ) {
    var pixelUnprojectionMatrix = viewport.pixelUnprojectionMatrix;
    var coord0 = transformVector(pixelUnprojectionMatrix, [x, 0, 1, 1]);
    var coord1 = transformVector(pixelUnprojectionMatrix, [x, viewport.height, 1, 1]);
    var z = targetZ * viewport.distanceScales.unitsPerMeter[2];
    var t = (z - coord0[2]) / (coord1[2] - coord0[2]);
    var coord = lerp([], coord0, coord1, t);
    var result = worldToLngLat(coord);
    result[2] = targetZ;
    return result;
  }

  var PI = Math.PI;
  var PI_4 = PI / 4;
  var DEGREES_TO_RADIANS$1 = PI / 180;
  var RADIANS_TO_DEGREES = 180 / PI;
  var TILE_SIZE = 512; // Average circumference (40075 km equatorial, 40007 km meridional)

  var EARTH_CIRCUMFERENCE = 40.03e6; // Mapbox default altitude

  var DEFAULT_ALTITUDE = 1.5;
  function scaleToZoom(scale) {
    return Math.log2(scale);
  }
  /**
   * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
   * Performs the nonlinear part of the web mercator projection.
   * Remaining projection is done with 4x4 matrices which also handles
   * perspective.
   *
   * @param lngLat - [lng, lat] coordinates
   *   Specifies a point on the sphere to project onto the map.
   * @return [x,y] coordinates.
   */

  function lngLatToWorld(_ref) {
    var _ref2 = _slicedToArray(_ref, 2),
        lng = _ref2[0],
        lat = _ref2[1];

    assert(Number.isFinite(lng));
    assert(Number.isFinite(lat) && lat >= -90 && lat <= 90, 'invalid latitude');
    var lambda2 = lng * DEGREES_TO_RADIANS$1;
    var phi2 = lat * DEGREES_TO_RADIANS$1;
    var x = TILE_SIZE * (lambda2 + PI) / (2 * PI);
    var y = TILE_SIZE * (PI + Math.log(Math.tan(PI_4 + phi2 * 0.5))) / (2 * PI);
    return [x, y];
  } // Unproject world point [x,y] on map onto {lat, lon} on sphere

  function worldToLngLat(_ref3) {
    var _ref4 = _slicedToArray(_ref3, 2),
        x = _ref4[0],
        y = _ref4[1];

    var lambda2 = x / TILE_SIZE * (2 * PI) - PI;
    var phi2 = 2 * (Math.atan(Math.exp(y / TILE_SIZE * (2 * PI) - PI)) - PI_4);
    return [lambda2 * RADIANS_TO_DEGREES, phi2 * RADIANS_TO_DEGREES];
  } // Returns the zoom level that gives a 1 meter pixel at a certain latitude
  // 1 = C*cos(y)/2^z/TILE_SIZE = C*cos(y)/2^(z+9)

  function getMeterZoom(_ref5) {
    var latitude = _ref5.latitude;
    assert(Number.isFinite(latitude));
    var latCosine = Math.cos(latitude * DEGREES_TO_RADIANS$1);
    return scaleToZoom(EARTH_CIRCUMFERENCE * latCosine) - 9;
  }
  /**
   * Calculate distance scales in meters around current lat/lon, both for
   * degrees and pixels.
   * In mercator projection mode, the distance scales vary significantly
   * with latitude.
   */

  function getDistanceScales(_ref6) {
    var latitude = _ref6.latitude,
        longitude = _ref6.longitude,
        _ref6$highPrecision = _ref6.highPrecision,
        highPrecision = _ref6$highPrecision === void 0 ? false : _ref6$highPrecision;
    assert(Number.isFinite(latitude) && Number.isFinite(longitude));
    var result = {
      degreesPerUnit: [],
      metersPerUnit: [],
      unitsPerDegree: [],
      unitsPerMeter: []
    };
    var worldSize = TILE_SIZE;
    var latCosine = Math.cos(latitude * DEGREES_TO_RADIANS$1);
    /**
     * Number of pixels occupied by one degree longitude around current lat/lon:
     unitsPerDegreeX = d(lngLatToWorld([lng, lat])[0])/d(lng)
     = scale * TILE_SIZE * DEGREES_TO_RADIANS / (2 * PI)
     unitsPerDegreeY = d(lngLatToWorld([lng, lat])[1])/d(lat)
     = -scale * TILE_SIZE * DEGREES_TO_RADIANS / cos(lat * DEGREES_TO_RADIANS)  / (2 * PI)
     */

    var unitsPerDegreeX = worldSize / 360;
    var unitsPerDegreeY = unitsPerDegreeX / latCosine;
    /**
     * Number of pixels occupied by one meter around current lat/lon:
     */

    var altUnitsPerMeter = worldSize / EARTH_CIRCUMFERENCE / latCosine;
    /**
     * LngLat: longitude -> east and latitude -> north (bottom left)
     * UTM meter offset: x -> east and y -> north (bottom left)
     * World space: x -> east and y -> south (top left)
     *
     * Y needs to be flipped when converting delta degree/meter to delta pixels
     */

    result.unitsPerMeter = [altUnitsPerMeter, altUnitsPerMeter, altUnitsPerMeter];
    result.metersPerUnit = [1 / altUnitsPerMeter, 1 / altUnitsPerMeter, 1 / altUnitsPerMeter];
    result.unitsPerDegree = [unitsPerDegreeX, unitsPerDegreeY, altUnitsPerMeter];
    result.degreesPerUnit = [1 / unitsPerDegreeX, 1 / unitsPerDegreeY, 1 / altUnitsPerMeter];
    /**
     * Taylor series 2nd order for 1/latCosine
     f'(a) * (x - a)
     = d(1/cos(lat * DEGREES_TO_RADIANS))/d(lat) * dLat
     = DEGREES_TO_RADIANS * tan(lat * DEGREES_TO_RADIANS) / cos(lat * DEGREES_TO_RADIANS) * dLat
     */

    if (highPrecision) {
      var latCosine2 = DEGREES_TO_RADIANS$1 * Math.tan(latitude * DEGREES_TO_RADIANS$1) / latCosine;
      var unitsPerDegreeY2 = unitsPerDegreeX * latCosine2 / 2;
      var altUnitsPerDegree2 = worldSize / EARTH_CIRCUMFERENCE * latCosine2;
      var altUnitsPerMeter2 = altUnitsPerDegree2 / unitsPerDegreeY * altUnitsPerMeter;
      result.unitsPerDegree2 = [0, unitsPerDegreeY2, altUnitsPerDegree2];
      result.unitsPerMeter2 = [altUnitsPerMeter2, 0, altUnitsPerMeter2];
    } // Main results, used for converting meters to latlng deltas and scaling offsets


    return result;
  }
  /**
   * Offset a lng/lat position by meterOffset (northing, easting)
   */

  function addMetersToLngLat(lngLatZ, xyz) {
    var _lngLatZ = _slicedToArray(lngLatZ, 3),
        longitude = _lngLatZ[0],
        latitude = _lngLatZ[1],
        z0 = _lngLatZ[2];

    var _xyz = _slicedToArray(xyz, 3),
        x = _xyz[0],
        y = _xyz[1],
        z = _xyz[2];

    var _getDistanceScales = getDistanceScales({
      longitude: longitude,
      latitude: latitude,
      highPrecision: true
    }),
        unitsPerMeter = _getDistanceScales.unitsPerMeter,
        unitsPerMeter2 = _getDistanceScales.unitsPerMeter2;

    var worldspace = lngLatToWorld(lngLatZ);

    if (unitsPerMeter2) {
      worldspace[0] += x * (unitsPerMeter[0] + unitsPerMeter2[0] * y);
    }

    if (unitsPerMeter2) {
      worldspace[1] += y * (unitsPerMeter[1] + unitsPerMeter2[1] * y);
    } // @ts-ignore


    var newLngLat = worldToLngLat(worldspace);
    var newZ = (z0 || 0) + (z || 0);
    return Number.isFinite(z0) || Number.isFinite(z) ? [newLngLat[0], newLngLat[1], newZ] : newLngLat;
  } // ATTRIBUTION:
  // view and projection matrix creation is intentionally kept compatible with
  // mapbox-gl's implementation to ensure that seamless interoperation
  // with mapbox and react-map-gl. See: https://github.com/mapbox/mapbox-gl-js

  function getViewMatrix(_ref7) {
    var height = _ref7.height,
        pitch = _ref7.pitch,
        bearing = _ref7.bearing,
        altitude = _ref7.altitude,
        scale$1 = _ref7.scale,
        center = _ref7.center;
    // VIEW MATRIX: PROJECTS MERCATOR WORLD COORDINATES
    // Note that mercator world coordinates typically need to be flipped
    //
    // Note: As usual, matrix operation orders should be read in reverse
    // since vectors will be multiplied from the right during transformation
    var vm = createMat4(); // Move camera to altitude (along the pitch & bearing direction)

    translate(vm, vm, [0, 0, -altitude]); // Rotate by bearing, and then by pitch (which tilts the view)

    rotateX(vm, vm, -pitch * DEGREES_TO_RADIANS$1);
    rotateZ(vm, vm, bearing * DEGREES_TO_RADIANS$1);
    scale$1 /= height;
    scale(vm, vm, [scale$1, scale$1, scale$1]);

    if (center) {
      translate(vm, vm, negate([], center));
    }

    return vm;
  } // PROJECTION MATRIX PARAMETERS
  // Variable fov (in radians)

  function getProjectionParameters(_ref8) {
    var width = _ref8.width,
        height = _ref8.height,
        _ref8$altitude = _ref8.altitude,
        altitude = _ref8$altitude === void 0 ? DEFAULT_ALTITUDE : _ref8$altitude,
        _ref8$pitch = _ref8.pitch,
        pitch = _ref8$pitch === void 0 ? 0 : _ref8$pitch,
        _ref8$nearZMultiplier = _ref8.nearZMultiplier,
        nearZMultiplier = _ref8$nearZMultiplier === void 0 ? 1 : _ref8$nearZMultiplier,
        _ref8$farZMultiplier = _ref8.farZMultiplier,
        farZMultiplier = _ref8$farZMultiplier === void 0 ? 1 : _ref8$farZMultiplier;
    // Find the distance from the center point to the center top
    // in altitude units using law of sines.
    var pitchRadians = pitch * DEGREES_TO_RADIANS$1;
    var halfFov = Math.atan(0.5 / altitude);
    var topHalfSurfaceDistance = Math.sin(halfFov) * altitude / Math.sin(Math.min(Math.max(Math.PI / 2 - pitchRadians - halfFov, 0.01), Math.PI - 0.01)); // Calculate z value of the farthest fragment that should be rendered.

    var farZ = Math.sin(pitchRadians) * topHalfSurfaceDistance + altitude;
    return {
      fov: 2 * halfFov,
      aspect: width / height,
      focalDistance: altitude,
      near: nearZMultiplier,
      far: farZ * farZMultiplier
    };
  } // PROJECTION MATRIX: PROJECTS FROM CAMERA (VIEW) SPACE TO CLIPSPACE

  function worldToPixels(xyz, pixelProjectionMatrix) {
    var _xyz2 = _slicedToArray(xyz, 3),
        x = _xyz2[0],
        y = _xyz2[1],
        _xyz2$ = _xyz2[2],
        z = _xyz2$ === void 0 ? 0 : _xyz2$;

    assert(Number.isFinite(x) && Number.isFinite(y) && Number.isFinite(z));
    return transformVector(pixelProjectionMatrix, [x, y, z, 1]);
  } // Unproject pixels on screen to flat coordinates.

  function pixelsToWorld(xyz, pixelUnprojectionMatrix) {
    var targetZ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;

    var _xyz3 = _slicedToArray(xyz, 3),
        x = _xyz3[0],
        y = _xyz3[1],
        z = _xyz3[2];

    assert(Number.isFinite(x) && Number.isFinite(y), 'invalid pixel coordinate');

    if (Number.isFinite(z)) {
      // Has depth component
      var coord = transformVector(pixelUnprojectionMatrix, [x, y, z, 1]);
      return coord;
    } // since we don't know the correct projected z value for the point,
    // unproject two points to get a line and then find the point on that line with z=0


    var coord0 = transformVector(pixelUnprojectionMatrix, [x, y, 0, 1]);
    var coord1 = transformVector(pixelUnprojectionMatrix, [x, y, 1, 1]);
    var z0 = coord0[2];
    var z1 = coord1[2];
    var t = z0 === z1 ? 0 : ((targetZ || 0) - z0) / (z1 - z0);
    return lerp([], coord0, coord1, t);
  }

  var PROJECTION_MODE;

  (function (PROJECTION_MODE) {
    PROJECTION_MODE[PROJECTION_MODE["WEB_MERCATOR"] = 1] = "WEB_MERCATOR";
    PROJECTION_MODE[PROJECTION_MODE["GLOBE"] = 2] = "GLOBE"; // This is automatically assigned by the project module

    PROJECTION_MODE[PROJECTION_MODE["WEB_MERCATOR_AUTO_OFFSET"] = 4] = "WEB_MERCATOR_AUTO_OFFSET";
    PROJECTION_MODE[PROJECTION_MODE["IDENTITY"] = 0] = "IDENTITY";
  })(PROJECTION_MODE || (PROJECTION_MODE = {}));

  var COORDINATE_SYSTEM;

  (function (COORDINATE_SYSTEM) {
    // `LNGLAT` if rendering into a geospatial viewport, `CARTESIAN` otherwise
    COORDINATE_SYSTEM[COORDINATE_SYSTEM["DEFAULT"] = -1] = "DEFAULT"; // Positions are interpreted as [lng, lat, elevation]
    // lng lat are degrees, elevation is meters. distances as meters.

    COORDINATE_SYSTEM[COORDINATE_SYSTEM["LNGLAT"] = 1] = "LNGLAT"; // Positions are interpreted as meter offsets, distances as meters

    COORDINATE_SYSTEM[COORDINATE_SYSTEM["METER_OFFSETS"] = 2] = "METER_OFFSETS"; // Positions are interpreted as lng lat offsets: [deltaLng, deltaLat, elevation]
    // deltaLng, deltaLat are delta degrees, elevation is meters.
    // distances as meters.

    COORDINATE_SYSTEM[COORDINATE_SYSTEM["LNGLAT_OFFSETS"] = 3] = "LNGLAT_OFFSETS"; // Non-geospatial

    COORDINATE_SYSTEM[COORDINATE_SYSTEM["CARTESIAN"] = 0] = "CARTESIAN";
  })(COORDINATE_SYSTEM || (COORDINATE_SYSTEM = {}));

  var DEGREES_TO_RADIANS$2 = Math.PI / 180;
  var IDENTITY = createMat4();
  var ZERO_VECTOR = [0, 0, 0];
  var DEFAULT_ZOOM = 0;
  var DEFAULT_DISTANCE_SCALES = {
    unitsPerMeter: [1, 1, 1],
    metersPerUnit: [1, 1, 1]
  };

  var WebMercatorViewport = /*#__PURE__*/function () {
    /**
     * Manages coordinate system transformations for deck.gl.
     * Note: The WebMercatorViewport is immutable in the sense that it only has accessors.
     * A new viewport instance should be created if any parameters have changed.
     */
    function WebMercatorViewport(opts) {
      _classCallCheck(this, WebMercatorViewport);

      var id = opts.id,
          _opts$x = opts.x,
          x = _opts$x === void 0 ? 0 : _opts$x,
          _opts$y = opts.y,
          y = _opts$y === void 0 ? 0 : _opts$y,
          _opts$latitude = opts.latitude,
          latitude = _opts$latitude === void 0 ? 0 : _opts$latitude,
          _opts$longitude = opts.longitude,
          longitude = _opts$longitude === void 0 ? 0 : _opts$longitude,
          _opts$zoom = opts.zoom,
          zoom = _opts$zoom === void 0 ? 11 : _opts$zoom,
          _opts$pitch = opts.pitch,
          pitch = _opts$pitch === void 0 ? 0 : _opts$pitch,
          _opts$bearing = opts.bearing,
          bearing = _opts$bearing === void 0 ? 0 : _opts$bearing,
          _opts$nearZMultiplier = opts.nearZMultiplier,
          nearZMultiplier = _opts$nearZMultiplier === void 0 ? 0.1 : _opts$nearZMultiplier,
          _opts$farZMultiplier = opts.farZMultiplier,
          farZMultiplier = _opts$farZMultiplier === void 0 ? 1.01 : _opts$farZMultiplier,
          _opts$orthographic = opts.orthographic,
          orthographic = _opts$orthographic === void 0 ? false : _opts$orthographic,
          _opts$repeat = opts.repeat,
          repeat = _opts$repeat === void 0 ? false : _opts$repeat,
          _opts$worldOffset = opts.worldOffset,
          worldOffset = _opts$worldOffset === void 0 ? 0 : _opts$worldOffset,
          _opts$projectOffsetZo = opts.projectOffsetZoom,
          projectOffsetZoom = _opts$projectOffsetZo === void 0 ? 12 : _opts$projectOffsetZo;
      var width = opts.width,
          height = opts.height,
          _opts$altitude = opts.altitude,
          altitude = _opts$altitude === void 0 ? 1.5 : _opts$altitude;
      var scale = Math.pow(2, zoom); // Silently allow apps to send in 0,0 to facilitate isomorphic render etc

      width = width || 1;
      height = height || 1; // Altitude - prevent division by 0
      // TODO - just throw an Error instead?

      altitude = Math.max(0.75, altitude);

      var _getProjectionParamet = getProjectionParameters({
        width: width,
        height: height,
        pitch: pitch,
        altitude: altitude,
        nearZMultiplier: nearZMultiplier,
        farZMultiplier: farZMultiplier
      }),
          fov = _getProjectionParamet.fov,
          aspect = _getProjectionParamet.aspect,
          focalDistance = _getProjectionParamet.focalDistance,
          near = _getProjectionParamet.near,
          far = _getProjectionParamet.far; // The uncentered matrix allows us two move the center addition to the
      // shader (cheap) which gives a coordinate system that has its center in
      // the layer's center position. This makes rotations and other modelMatrx
      // transforms much more useful.


      var viewMatrixUncentered = getViewMatrix({
        height: height,
        pitch: pitch,
        bearing: bearing,
        scale: scale,
        altitude: altitude,
        // @ts-ignore center typedef is incorrect
        center: null
      });

      if (worldOffset) {
        var m = createMat4();
        var viewOffset = translate(m, m, [512 * worldOffset, 0, 0]);
        viewMatrixUncentered = multiply(viewOffset, viewMatrixUncentered, viewOffset);
      }

      this.id = id || 'viewport';
      var viewportOpts = Object.assign({}, opts, {
        // x, y,
        width: width,
        height: height,
        // view matrix
        viewMatrix: viewMatrixUncentered,
        longitude: longitude,
        latitude: latitude,
        zoom: zoom,
        // projection matrix parameters
        orthographic: orthographic,
        fovyRadians: fov,
        aspect: aspect,
        // TODO WebMercatorViewport is already carefully set up to "focus" on ground, so can't use focal distance
        focalDistance: orthographic ? focalDistance : 1,
        near: near,
        far: far
      }); // Save parameters

      this.latitude = latitude;
      this.longitude = longitude;
      this.zoom = zoom;
      this.pitch = pitch;
      this.bearing = bearing;
      this.altitude = altitude;
      this.projectOffsetZoom = projectOffsetZoom;
      this.orthographic = orthographic;
      this._subViewports = repeat ? [] : undefined;
      this.x = x;
      this.y = y; // Silently allow apps to send in w,h = 0,0

      this.width = width || 1;
      this.height = height || 1; // @ts-ignore

      this._initViewMatrix(viewportOpts); // @ts-ignore


      this._initProjectionMatrix(viewportOpts);

      this._initPixelMatrices(); // Bind methods for easy access


      this.equals = this.equals.bind(this);
      this.project = this.project.bind(this);
      this.unproject = this.unproject.bind(this);
      this.projectPosition = this.projectPosition.bind(this);
      this.unprojectPosition = this.unprojectPosition.bind(this);
      this.projectFlat = this.projectFlat.bind(this);
      this.unprojectFlat = this.unprojectFlat.bind(this);
    }

    _createClass(WebMercatorViewport, [{
      key: "metersPerPixel",
      get: function get() {
        return this.distanceScales.metersPerUnit[2] / this.scale;
      }
    }, {
      key: "projectionMode",
      get: function get() {
        if (this.isGeospatial) {
          return this.zoom < this.projectOffsetZoom ? PROJECTION_MODE.WEB_MERCATOR : PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET;
        }

        return PROJECTION_MODE.IDENTITY;
      }
      /**
       * Two viewports are equal if width and height are identical, and if
          their view and projection matrices are (approximately) equal.
       * @param viewport
       */

    }, {
      key: "equals",
      value: function equals$1(viewport) {
        if (!(viewport instanceof WebMercatorViewport)) {
          return false;
        }

        if (this === viewport) {
          return true;
        }

        return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && equals(viewport.projectionMatrix, this.projectionMatrix) && equals(viewport.viewMatrix, this.viewMatrix);
      }
      /**
       * Projects xyz (possibly latitude and longitude) to pixel coordinates in window
       * using viewport projection parameters
       * - [longitude, latitude] to [x, y]
       * - [longitude, latitude, Z] => [x, y, z]
       * Note: By default, returns top-left coordinates for canvas/SVG type render
       *
       * @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
       * @param {Object} opts.topLeft=true - Whether projected coords are top left
       * @return {Array} - [x, y] or [x, y, z] in top left coords
       * @param xyz
       */

    }, {
      key: "project",
      value: function project(xyz) {
        var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
            _ref$topLeft = _ref.topLeft,
            topLeft = _ref$topLeft === void 0 ? true : _ref$topLeft;

        var worldPosition = this.projectPosition(xyz);
        var coord = worldToPixels(worldPosition, this.pixelProjectionMatrix);

        var _coord = _slicedToArray(coord, 2),
            x = _coord[0],
            y = _coord[1];

        var y2 = topLeft ? y : this.height - y;
        return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]];
      }
      /**
       * Unproject pixel coordinates on screen onto world coordinates,
       * (possibly [lon, lat]) on map.
       * - [x, y] => [lng, lat]
       * - [x, y, z] => [lng, lat, Z]
       * @param {Array} xyz -
       * @param {Object} opts - options
       * @param {Object} opts.topLeft=true - Whether origin is top left
       * @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
       */

    }, {
      key: "unproject",
      value: function unproject(xyz) {
        var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
            _ref2$topLeft = _ref2.topLeft,
            topLeft = _ref2$topLeft === void 0 ? true : _ref2$topLeft,
            targetZ = _ref2.targetZ;

        var _xyz = _slicedToArray(xyz, 3),
            x = _xyz[0],
            y = _xyz[1],
            z = _xyz[2];

        var y2 = topLeft ? y : this.height - y;
        var targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2];
        var coord = pixelsToWorld([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld);

        var _this$unprojectPositi = this.unprojectPosition(coord),
            _this$unprojectPositi2 = _slicedToArray(_this$unprojectPositi, 3),
            X = _this$unprojectPositi2[0],
            Y = _this$unprojectPositi2[1],
            Z = _this$unprojectPositi2[2];

        if (Number.isFinite(z)) {
          return [X, Y, Z];
        }

        return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
      } // NON_LINEAR PROJECTION HOOKS
      // Used for web meractor projection

    }, {
      key: "projectPosition",
      value: function projectPosition(xyz) {
        var _this$projectFlat = this.projectFlat(xyz),
            _this$projectFlat2 = _slicedToArray(_this$projectFlat, 2),
            X = _this$projectFlat2[0],
            Y = _this$projectFlat2[1];

        var Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2];
        return [X, Y, Z];
      }
    }, {
      key: "unprojectPosition",
      value: function unprojectPosition(xyz) {
        var _this$unprojectFlat = this.unprojectFlat(xyz),
            _this$unprojectFlat2 = _slicedToArray(_this$unprojectFlat, 2),
            X = _this$unprojectFlat2[0],
            Y = _this$unprojectFlat2[1];

        var Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2];
        return [X, Y, Z];
      }
      /**
       * Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
       * Performs the nonlinear part of the web mercator projection.
       * Remaining projection is done with 4x4 matrices which also handles
       * perspective.
       *   Specifies a point on the sphere to project onto the map.
       * @return {Array} [x,y] coordinates.
       * @param xyz
       */

    }, {
      key: "projectFlat",
      value: function projectFlat(xyz) {
        if (this.isGeospatial) {
          return lngLatToWorld(xyz);
        }

        return xyz;
      }
      /**
       * Unproject world point [x,y] on map onto {lat, lon} on sphere
       *  representing point on projected map plane
       * @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
       *   Has toArray method if you need a GeoJSON Array.
       *   Per cartographic tradition, lat and lon are specified as degrees.
       * @param xyz
       */

    }, {
      key: "unprojectFlat",
      value: function unprojectFlat(xyz) {
        if (this.isGeospatial) {
          return worldToLngLat(xyz);
        }

        return xyz;
      }
    }, {
      key: "getDistanceScales",
      value: function getDistanceScales$1(coordinateOrigin) {
        if (coordinateOrigin && Array.isArray(coordinateOrigin)) {
          return getDistanceScales({
            longitude: coordinateOrigin[0],
            latitude: coordinateOrigin[1],
            highPrecision: true
          });
        }

        return this.distanceScales;
      }
      /**
       * Judge whether the position is in the range
       * @param x
       * @param y
       * @param width
       * @param height
       */

    }, {
      key: "containsPixel",
      value: function containsPixel(_ref3) {
        var x = _ref3.x,
            y = _ref3.y,
            _ref3$width = _ref3.width,
            width = _ref3$width === void 0 ? 1 : _ref3$width,
            _ref3$height = _ref3.height,
            height = _ref3$height === void 0 ? 1 : _ref3$height;
        return x < this.x + this.width && this.x < x + width && y < this.y + this.height && this.y < y + height;
      }
      /**
       * Extract frustum planes in common space
       */

    }, {
      key: "getFrustumPlanes",
      value: function getFrustumPlanes$1() {
        var _this$_frustumPlanes;

        if ((_this$_frustumPlanes = this._frustumPlanes) !== null && _this$_frustumPlanes !== void 0 && _this$_frustumPlanes.near) {
          return this._frustumPlanes;
        }

        this._frustumPlanes = getFrustumPlanes(this.viewProjectionMatrix);
        return this._frustumPlanes;
      } // EXPERIMENTAL METHODS

    }, {
      key: "getCameraPosition",
      value: function getCameraPosition() {
        return this.cameraPosition;
      } // INTERNAL METHODS

    }, {
      key: "_createProjectionMatrix",
      value: function _createProjectionMatrix(_ref4) {
        var orthographic = _ref4.orthographic,
            fovyRadians = _ref4.fovyRadians,
            aspect = _ref4.aspect,
            focalDistance = _ref4.focalDistance,
            near = _ref4.near,
            far = _ref4.far;
        var m = createMat4();

        if (orthographic) {
          if (fovyRadians > Math.PI * 2) {
            throw Error('radians');
          }

          var halfY = fovyRadians / 2;
          var top = focalDistance * Math.tan(halfY); // focus_plane is the distance from the camera

          var right = top * aspect;
          ortho(m, -right, right, -top, top, near, far);
        } else {
          perspective(m, fovyRadians, aspect, near, far);
        }

        return m;
      }
    }, {
      key: "_initViewMatrix",
      value: function _initViewMatrix(opts) {
        var _opts$viewMatrix = opts.viewMatrix,
            viewMatrix = _opts$viewMatrix === void 0 ? IDENTITY : _opts$viewMatrix,
            longitude = opts.longitude,
            latitude = opts.latitude,
            zoom = opts.zoom,
            _opts$position = opts.position,
            position = _opts$position === void 0 ? null : _opts$position,
            _opts$modelMatrix = opts.modelMatrix,
            modelMatrix = _opts$modelMatrix === void 0 ? null : _opts$modelMatrix,
            _opts$focalDistance = opts.focalDistance,
            focalDistance = _opts$focalDistance === void 0 ? 1 : _opts$focalDistance,
            distanceScales = opts.distanceScales; // Check if we have a geospatial anchor

        this.isGeospatial = Number.isFinite(latitude) && Number.isFinite(longitude);
        this.zoom = zoom;

        if (!Number.isFinite(this.zoom)) {
          this.zoom = this.isGeospatial ? getMeterZoom({
            latitude: latitude
          }) + Math.log2(focalDistance) : DEFAULT_ZOOM;
        }

        this.scale = Math.pow(2, this.zoom); // Calculate distance scales if lng/lat/zoom are provided

        this.distanceScales = this.isGeospatial ? getDistanceScales({
          latitude: latitude,
          longitude: longitude
        }) : distanceScales || DEFAULT_DISTANCE_SCALES;
        this.focalDistance = focalDistance;
        this.position = ZERO_VECTOR;
        this.meterOffset = ZERO_VECTOR;

        if (position && modelMatrix) {
          // Apply model matrix if supplied
          this.position = position;
          this.modelMatrix = modelMatrix;
          this.meterOffset = modelMatrix ? transformMat4([-0, -0, -0], position, modelMatrix) : position;
        }

        if (this.isGeospatial) {
          // Determine camera center
          this.longitude = longitude;
          this.latitude = latitude;
          this.center = this._getCenterInWorld({
            longitude: longitude,
            latitude: latitude
          });
        } else {
          this.center = position ? this.projectPosition(position) : [0, 0, 0];
        }

        this.viewMatrixUncentered = viewMatrix; // Make a centered version of the matrix for projection modes without an offset

        this.viewMatrix = createMat4();
        multiply(this.viewMatrix, this.viewMatrixUncentered, this.viewMatrix);
        translate(this.viewMatrix, this.viewMatrix, (this.center || ZERO_VECTOR).map(function (i) {
          return -i;
        }));
      }
    }, {
      key: "_initProjectionMatrix",
      value: function _initProjectionMatrix(opts) {
        var _opts$projectionMatri = opts.projectionMatrix,
            projectionMatrix = _opts$projectionMatri === void 0 ? null : _opts$projectionMatri,
            _opts$orthographic2 = opts.orthographic,
            orthographic = _opts$orthographic2 === void 0 ? false : _opts$orthographic2,
            fovyRadians = opts.fovyRadians,
            _opts$fovy = opts.fovy,
            fovy = _opts$fovy === void 0 ? 75 : _opts$fovy,
            _opts$near = opts.near,
            near = _opts$near === void 0 ? 0.1 : _opts$near,
            _opts$far = opts.far,
            far = _opts$far === void 0 ? 1000 : _opts$far,
            _opts$focalDistance2 = opts.focalDistance,
            focalDistance = _opts$focalDistance2 === void 0 ? 1 : _opts$focalDistance2;
        this.projectionMatrix = projectionMatrix || this._createProjectionMatrix({
          orthographic: orthographic,
          fovyRadians: fovyRadians || fovy * DEGREES_TO_RADIANS$2,
          aspect: this.width / this.height,
          focalDistance: focalDistance,
          near: near,
          far: far
        });
      }
    }, {
      key: "_initPixelMatrices",
      value: function _initPixelMatrices() {
        // Note: As usual, matrix operations should be applied in "reverse" order
        // since vectors will be multiplied in from the right during transformation
        var vpm = createMat4();
        multiply(vpm, vpm, this.projectionMatrix);
        multiply(vpm, vpm, this.viewMatrix);
        this.viewProjectionMatrix = vpm; // console.log('VPM', this.viewMatrix, this.projectionMatrix, this.viewProjectionMatrix);
        // Calculate inverse view matrix

        this.viewMatrixInverse = invert([], this.viewMatrix) || this.viewMatrix; // Decompose camera parameters

        this.cameraPosition = getCameraPosition(this.viewMatrixInverse);
        /*
         * Builds matrices that converts preprojected lngLats to screen pixels
         * and vice versa.
         * Note: Currently returns bottom-left coordinates!
         * Note: Starts with the GL projection matrix and adds steps to the
         *       scale and translate that matrix onto the window.
         * Note: WebGL controls clip space to screen projection with gl.viewport
         *       and does not need this step.
         */
        // matrix for conversion from world location to screen (pixel) coordinates

        var viewportMatrix = createMat4(); // matrix from NDC to viewport.

        var pixelProjectionMatrix = createMat4(); // matrix from world space to viewport.

        scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
        translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
        multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
        this.pixelProjectionMatrix = pixelProjectionMatrix;
        this.viewportMatrix = viewportMatrix;
        var m = createMat4();
        this.pixelUnprojectionMatrix = invert(m, this.pixelProjectionMatrix);

        if (!this.pixelUnprojectionMatrix) {
          console.warn('Pixel project matrix not invertible');
        }
      }
    }, {
      key: "_getCenterInWorld",
      value: function _getCenterInWorld(_ref5) {
        var longitude = _ref5.longitude,
            latitude = _ref5.latitude;
        var meterOffset = this.meterOffset,
            distanceScales = this.distanceScales; // Make a centered version of the matrix for projection modes without an offset

        var center = this.projectPosition([longitude, latitude, 0]);

        if (meterOffset) {
          var commonPosition = meterOffset; // Convert to pixels in current zoom

          for (var i = 0; i < commonPosition.length; ++i) {
            commonPosition[i] *= distanceScales.unitsPerMeter[i];
          }

          for (var _i = 0; _i < center.length; ++_i) {
            center[_i] += commonPosition[_i];
          } // center.add(commonPosition);

        }

        return center;
      }
    }, {
      key: "subViewports",
      get: function get() {
        if (this._subViewports && !this._subViewports.length) {
          // Cache sub viewports so that we only calculate them once
          var bounds = this.getBounds();
          var minOffset = Math.floor((bounds[0] + 180) / 360);
          var maxOffset = Math.ceil((bounds[2] - 180) / 360);

          for (var x = minOffset; x <= maxOffset; x++) {
            var offsetViewport = x // @ts-ignore
            ? new WebMercatorViewport(Object.assign({}, this, {
              worldOffset: x
            })) : this;

            this._subViewports.push(offsetViewport);
          }
        }

        return this._subViewports;
      }
      /**
       * Add a meter delta to a base lnglat coordinate, returning a new lnglat array
       *
       * Note: Uses simple linear approximation around the viewport center
       * Error increases with size of offset (roughly 1% per 100km)
       *
       * @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
       * @param lngLatZ
       * @param xyz
       */

    }, {
      key: "addMetersToLngLat",
      value: function addMetersToLngLat$1(lngLatZ, xyz) {
        return addMetersToLngLat(lngLatZ, xyz);
      }
      /**
       * Get the map center that place a given [lng, lat] coordinate at screen
       * point [x, y]
       *
       * @param {Array} lngLat - [lng,lat] coordinates
       *   Specifies a point on the sphere.
       * @param {Array} pos - [x,y] coordinates
       *   Specifies a point on the screen.
       * @return {Array} [lng,lat] new map center.
       */

    }, {
      key: "getMapCenterByLngLatPosition",
      value: function getMapCenterByLngLatPosition(_ref6) {
        var lngLat = _ref6.lngLat,
            pos = _ref6.pos;
        var fromLocation = pixelsToWorld(pos, this.pixelUnprojectionMatrix);
        var toLocation = this.projectFlat(lngLat);
        var translate = add([], toLocation, negate$1([], fromLocation));
        var newCenter = add([], this.center, translate);
        return this.unprojectFlat(newCenter);
      }
    }, {
      key: "getBounds",
      value: function getBounds$1() {
        var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

        // @ts-ignore
        var corners = getBounds(this, options.z || 0);

        return [Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]), Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]), Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]), Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])];
      }
    }]);

    return WebMercatorViewport;
  }();

  // @from https://github.com/visgl/luma.gl
  var GL_VENDOR = 0x1f00;
  var GL_RENDERER = 0x1f01;
  var GL_VERSION = 0x1f02;
  var GL_SHADING_LANGUAGE_VERSION = 0x8b8c; // Precision prologue to inject before functions are injected in shader
  // TODO - extract any existing prologue in the fragment source and move it up...

  var FRAGMENT_SHADER_PROLOGUE = "precision highp float;\n";

  function identifyGPUVendor(vendor, renderer) {
    if (vendor.match(/NVIDIA/i) || renderer.match(/NVIDIA/i)) {
      return 'NVIDIA';
    }

    if (vendor.match(/INTEL/i) || renderer.match(/INTEL/i)) {
      return 'INTEL';
    }

    if (vendor.match(/AMD/i) || renderer.match(/AMD/i) || vendor.match(/ATI/i) || renderer.match(/ATI/i)) {
      return 'AMD';
    }

    return 'UNKNOWN GPU';
  }

  function getContextInfo(gl) {
    var info = gl.getExtension('WEBGL_debug_renderer_info');
    var vendor = gl.getParameter((info === null || info === void 0 ? void 0 : info.UNMASKED_VENDOR_WEBGL) || GL_VENDOR);
    var renderer = gl.getParameter((info === null || info === void 0 ? void 0 : info.UNMASKED_RENDERER_WEBGL) || GL_RENDERER);
    var gpuVendor = identifyGPUVendor(vendor, renderer);
    return {
      gpuVendor: gpuVendor,
      vendor: vendor,
      renderer: renderer,
      version: gl.getParameter(GL_VERSION),
      shadingLanguageVersion: gl.getParameter(GL_SHADING_LANGUAGE_VERSION)
    };
  }

  function getPlatformShaderDefines(gl) {
    var debugInfo = getContextInfo(gl);

    switch (debugInfo.gpuVendor.toLowerCase()) {
      case 'nvidia':
        return '#define NVIDIA_GPU\n// Nvidia optimizes away the calculation necessary for emulated fp64\n#define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1\n';

      case 'intel':
        return '#define INTEL_GPU\n// Intel optimizes away the calculation necessary for emulated fp64\n#define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1\n// Intel\'s built-in \'tan\' function doesn\'t have acceptable precision\n#define LUMA_FP32_TAN_PRECISION_WORKAROUND 1\n// Intel GPU doesn\'t have full 32 bits precision in same cases, causes overflow\n#define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1\n';

      case 'amd':
        return '#define AMD_GPU\n';

      default:
        return '#define DEFAULT_GPU\n// Prevent driver from optimizing away the calculation necessary for emulated fp64\n#define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1\n// Intel\'s built-in \'tan\' function doesn\'t have acceptable precision\n#define LUMA_FP32_TAN_PRECISION_WORKAROUND 1\n// Intel GPU doesn\'t have full 32 bits precision in same cases, causes overflow\n#define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1\n';
    }
  }
  function getApplicationDefines() {
    var defines = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    var count = 0;
    var sourceText = ''; // eslint-disable-next-line guard-for-in

    for (var define in defines) {
      if (count === 0) {
        sourceText += '\n// APPLICATION DEFINES\n';
      }

      count++;
      var value = defines[define];

      if (value || Number.isFinite(value)) {
        sourceText += "#define ".concat(define.toUpperCase(), " ").concat(defines[define], "\n");
      }
    }

    if (count === 0) {
      sourceText += '\n';
    }

    return sourceText;
  }

  var projectShader = "#define GLSLIFY 1\n#define PROJECT_TILE_SIZE 512.0\n#define PROJECT_PI 3.141592653589793\n#define PROJECT_EARTH_RADIUS 6370972.0\n#define PROJECT_WORLD_SCALE (PROJECT_TILE_SIZE / (PROJECT_PI * 2.0))\n#define PROJECT_EARTH_CIRCUMFRENCE (2.0 * PROJECT_PI * PROJECT_EARTH_RADIUS)\nuniform vec4 project_uCenter;uniform vec3 project_uCoordinateOrigin;uniform float project_uScale;uniform mat4 project_uModelMatrix;uniform mat4 project_uViewProjectionMatrix;uniform vec3 project_uCommonUnitsPerMeter;uniform vec3 project_uCommonUnitsPerWorldUnit;uniform vec3 project_uCommonUnitsPerWorldUnit2;uniform vec2 project_uViewportSize;uniform float project_uDevicePixelRatio;uniform float project_uFocalDistance;uniform bool project_uWrapLongitude;const vec3 ZERO_64_LOW=vec3(0.0);float project_size(float meters){return meters*project_uCommonUnitsPerMeter.z;}vec2 project_size(vec2 meters){return meters*project_uCommonUnitsPerMeter.xy;}vec3 project_size(vec3 meters){return meters*project_uCommonUnitsPerMeter;}vec4 project_size(vec4 meters){return vec4(meters.xyz*project_uCommonUnitsPerMeter,meters.w);}vec3 project_normal(vec3 vector){vec4 normal_modelspace=project_uModelMatrix*vec4(vector,0.0);return normalize(normal_modelspace.xyz*project_uCommonUnitsPerMeter);}vec4 project_offset(vec4 offset){float dy=offset.y;dy=clamp(dy,-1.,1.);vec3 commonUnitsPerWorldUnit=project_uCommonUnitsPerWorldUnit+project_uCommonUnitsPerWorldUnit2*dy;return vec4(offset.xyz*commonUnitsPerWorldUnit,offset.w);}vec2 project_mercator(vec2 lnglat){float x=lnglat.x;if(project_uWrapLongitude){x=mod(x+180.,360.0)-180.;}float y=clamp(lnglat.y,-89.9,89.9);return vec2(radians(x)+PROJECT_PI,PROJECT_PI+log(tan_fp32(PROJECT_PI*0.25+radians(y)*0.5)));}vec4 project_position(vec4 position,vec3 position64Low){vec4 position_world=project_uModelMatrix*position;if(project_uScale<PROJECT_OFFSET_THRESHOLD){vec2 point=project_mercator(position_world.xy)*PROJECT_WORLD_SCALE;return vec4(point,project_size(position_world.z),position_world.w);}position_world.xyz-=project_uCoordinateOrigin;return project_offset(position_world+project_uModelMatrix*vec4(position64Low,0.0));}vec4 project_position(vec4 position){return project_position(position,ZERO_64_LOW);}vec3 project_position(vec3 position,vec3 position64Low){vec4 projected_position=project_position(vec4(position,1.0),position64Low);return projected_position.xyz;}vec3 project_position(vec3 position){vec4 projected_position=project_position(vec4(position,1.0),ZERO_64_LOW);return projected_position.xyz;}vec2 project_position(vec2 position){vec4 projected_position=project_position(vec4(position,0.0,1.0),ZERO_64_LOW);return projected_position.xy;}vec4 project_common_position_to_clipspace(vec4 position,mat4 viewProjectionMatrix,vec4 center){return viewProjectionMatrix*position+center;}vec4 project_common_position_to_clipspace(vec4 position){return project_common_position_to_clipspace(position,project_uViewProjectionMatrix,project_uCenter);}vec2 project_pixel_size_to_clipspace(vec2 pixels){vec2 offset=pixels/project_uViewportSize*project_uDevicePixelRatio*2.0;return offset*project_uFocalDistance;}float project_size_to_pixel(float meters){return project_size(meters)*project_uScale;}float project_pixel_size(float pixels){return pixels/project_uScale;}vec2 project_pixel_size(vec2 pixels){return pixels/project_uScale;}vec4 project_position_to_clipspace(vec3 position,vec3 position64Low,vec3 offset,out vec4 commonPosition){vec3 projectedPosition=project_position(position,position64Low);commonPosition=vec4(projectedPosition+offset,1.0);return project_common_position_to_clipspace(commonPosition);}vec4 project_position_to_clipspace(vec3 position,vec3 position64Low,vec3 offset){vec4 commonPosition;return project_position_to_clipspace(position,position64Low,offset,commonPosition);}float circumferenceAtLatitude(float latitude){return PROJECT_EARTH_CIRCUMFRENCE*cos(latitude*PROJECT_PI/180.0);}float mercatorXfromLng(float lng){return(180.0+lng)/360.0;}float mercatorYfromLat(float lat){return(180.0-degrees(log(tan(PROJECT_PI/4.0+0.5*radians(lat)))))/360.0;}float mercatorZfromAltitude(float altitude,float lat){return altitude/circumferenceAtLatitude(lat);}"; // eslint-disable-line

  var fp32shader = "#define GLSLIFY 1\n#define MODULE_FP32\n#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND\nconst float TWO_PI=6.2831854820251465;const float PI_2=1.5707963705062866;const float PI_16=0.1963495463132858;const float SIN_TABLE_0=0.19509032368659973;const float SIN_TABLE_1=0.3826834261417389;const float SIN_TABLE_2=0.5555702447891235;const float SIN_TABLE_3=0.7071067690849304;const float COS_TABLE_0=0.9807852506637573;const float COS_TABLE_1=0.9238795042037964;const float COS_TABLE_2=0.8314695954322815;const float COS_TABLE_3=0.7071067690849304;const float INVERSE_FACTORIAL_3=1.666666716337204e-01;const float INVERSE_FACTORIAL_5=8.333333767950535e-03;const float INVERSE_FACTORIAL_7=1.9841270113829523e-04;const float INVERSE_FACTORIAL_9=2.75573188446287533e-06;float sin_taylor_fp32(float a){float r,s,t,x;if(a==0.0){return 0.0;}x=-a*a;s=a;r=a;r=r*x;t=r*INVERSE_FACTORIAL_3;s=s+t;r=r*x;t=r*INVERSE_FACTORIAL_5;s=s+t;r=r*x;t=r*INVERSE_FACTORIAL_7;s=s+t;r=r*x;t=r*INVERSE_FACTORIAL_9;s=s+t;return s;}void sincos_taylor_fp32(float a,out float sin_t,out float cos_t){if(a==0.0){sin_t=0.0;cos_t=1.0;}sin_t=sin_taylor_fp32(a);cos_t=sqrt(1.0-sin_t*sin_t);}float tan_taylor_fp32(float a){float sin_a;float cos_a;if(a==0.0){return 0.0;}float z=floor(a/TWO_PI);float r=a-TWO_PI*z;float t;float q=floor(r/PI_2+0.5);int j=int(q);if(j<-2||j>2){return 0.0/0.0;}t=r-PI_2*q;q=floor(t/PI_16+0.5);int k=int(q);int abs_k=int(abs(float(k)));if(abs_k>4){return 0.0/0.0;}else{t=t-PI_16*q;}float u=0.0;float v=0.0;float sin_t,cos_t;float s,c;sincos_taylor_fp32(t,sin_t,cos_t);if(k==0){s=sin_t;c=cos_t;}else{if(abs(float(abs_k)-1.0)<0.5){u=COS_TABLE_0;v=SIN_TABLE_0;}else if(abs(float(abs_k)-2.0)<0.5){u=COS_TABLE_1;v=SIN_TABLE_1;}else if(abs(float(abs_k)-3.0)<0.5){u=COS_TABLE_2;v=SIN_TABLE_2;}else if(abs(float(abs_k)-4.0)<0.5){u=COS_TABLE_3;v=SIN_TABLE_3;}if(k>0){s=u*sin_t+v*cos_t;c=u*cos_t-v*sin_t;}else{s=u*sin_t-v*cos_t;c=u*cos_t+v*sin_t;}}if(j==0){sin_a=s;cos_a=c;}else if(j==1){sin_a=c;cos_a=-s;}else if(j==-1){sin_a=-c;cos_a=s;}else{sin_a=-s;cos_a=-c;}return sin_a/cos_a;}\n#endif\nfloat tan_fp32(float a){\n#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND\nreturn tan_taylor_fp32(a);\n#else\nreturn tan(a);\n#endif\n}"; // eslint-disable-line

  var _window$screen, _window$screen2;

  var ZERO_VECTOR$1 = [0, 0, 0, 0];
  var VECTOR_TO_POINT_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0];
  var IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
  var DEFAULT_COORDINATE_ORIGIN = [0, 0, 0];
  var DEFAULT_PIXELS_PER_UNIT2 = [0, 0, 0];
  var INITIAL_MODULE_OPTIONS = {
    // @ts-ignore
    devicePixelRatio: window.devicePixelRatio || ((_window$screen = window.screen) === null || _window$screen === void 0 ? void 0 : _window$screen.deviceXDPI) / ((_window$screen2 = window.screen) === null || _window$screen2 === void 0 ? void 0 : _window$screen2.logicalXDPI) || 1
  };
  function isEqual(a, b) {
    if (a === b) {
      return true;
    }

    if (Array.isArray(a)) {
      // Special treatment for arrays: compare 1-level deep
      // This is to support equality of matrix/coordinate props
      var len = a.length;

      if (!b || b.length !== len) {
        return false;
      }

      for (var i = 0; i < len; i++) {
        if (a[i] !== b[i]) {
          return false;
        }
      }

      return true;
    }

    return false;
  }
  /**
   * Speed up consecutive function calls by caching the result of calls with identical input
   * https://en.wikipedia.org/wiki/Memoization
   * @param {function} compute - the function to be memoized
   */

  function memoize(compute) {
    var cachedArgs = {};
    var cachedResult;
    return function (args) {
      // eslint-disable-next-line no-restricted-syntax
      for (var key in args) {
        if (!isEqual(args[key], cachedArgs[key])) {
          cachedResult = compute(args);
          cachedArgs = args;
          break;
        }
      }

      return cachedResult;
    };
  }
  /**
   * Multiplies two mat4s
   * @param {mat4} out the receiving matrix
   * @param {ReadonlyMat4} a the first operand
   * @param {ReadonlyMat4} b the second operand
   * @returns {mat4} out
   */

  function multiply$1(out, a, b) {
    var a00 = a[0];
    var a01 = a[1];
    var a02 = a[2];
    var a03 = a[3];
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];
    var a20 = a[8];
    var a21 = a[9];
    var a22 = a[10];
    var a23 = a[11];
    var a30 = a[12];
    var a31 = a[13];
    var a32 = a[14];
    var a33 = a[15]; // Cache only the current line of the second matrix

    var b0 = b[0];
    var b1 = b[1];
    var b2 = b[2];
    var b3 = b[3];
    out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[4];
    b1 = b[5];
    b2 = b[6];
    b3 = b[7];
    out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[8];
    b1 = b[9];
    b2 = b[10];
    b3 = b[11];
    out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    b0 = b[12];
    b1 = b[13];
    b2 = b[14];
    b3 = b[15];
    out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
    out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
    out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
    out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
    return out;
  }
  /**
   * Transforms the vec4 with a mat4.
   * @param {vec4} out the receiving vector
   * @param {ReadonlyVec4} a the vector to transform
   * @param {ReadonlyMat4} m matrix to transform with
   * @returns {vec4} out
   */

  function transformMat4$2(out, a, m) {
    var x = a[0];
    var y = a[1];
    var z = a[2];
    var w = a[3];
    out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
    out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
    out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
    out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
    return out;
  }
  /**
   * Inverts a mat4
   * @param out
   * @param a
   */

  function invert$1(out, a) {
    var a00 = a[0];
    var a01 = a[1];
    var a02 = a[2];
    var a03 = a[3];
    var a10 = a[4];
    var a11 = a[5];
    var a12 = a[6];
    var a13 = a[7];
    var a20 = a[8];
    var a21 = a[9];
    var a22 = a[10];
    var a23 = a[11];
    var a30 = a[12];
    var a31 = a[13];
    var a32 = a[14];
    var a33 = a[15];
    var b00 = a00 * a11 - a01 * a10;
    var b01 = a00 * a12 - a02 * a10;
    var b02 = a00 * a13 - a03 * a10;
    var b03 = a01 * a12 - a02 * a11;
    var b04 = a01 * a13 - a03 * a11;
    var b05 = a02 * a13 - a03 * a12;
    var b06 = a20 * a31 - a21 * a30;
    var b07 = a20 * a32 - a22 * a30;
    var b08 = a20 * a33 - a23 * a30;
    var b09 = a21 * a32 - a22 * a31;
    var b10 = a21 * a33 - a23 * a31;
    var b11 = a22 * a33 - a23 * a32; // Calculate the determinant

    var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;

    if (!det) {
      return null;
    }

    det = 1.0 / det;
    out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
    out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
    out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
    out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
    out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
    out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
    out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
    out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
    out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
    out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
    out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
    out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
    out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
    out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
    out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
    out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
    return out;
  }
  var getMemoizedViewportUniforms = memoize(calculateViewportUniforms);
  function getOffsetOrigin(viewport, coordinateSystem) {
    var coordinateOrigin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_COORDINATE_ORIGIN;
    var shaderCoordinateOrigin = coordinateOrigin;
    var geospatialOrigin;
    var offsetMode = true;

    if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT_OFFSETS || coordinateSystem === COORDINATE_SYSTEM.METER_OFFSETS) {
      geospatialOrigin = coordinateOrigin;
    } else {
      geospatialOrigin = viewport.isGeospatial ? [Math.fround(viewport.longitude), Math.fround(viewport.latitude), 0] : null;
    }

    switch (viewport.projectionMode) {
      case PROJECTION_MODE.WEB_MERCATOR:
        if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT || coordinateSystem === COORDINATE_SYSTEM.CARTESIAN) {
          offsetMode = false;
        }

        break;

      case PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET:
        if (coordinateSystem === COORDINATE_SYSTEM.LNGLAT) {
          // viewport center in world space
          shaderCoordinateOrigin = geospatialOrigin;
        } else if (coordinateSystem === COORDINATE_SYSTEM.CARTESIAN) {
          // viewport center in common space
          shaderCoordinateOrigin = [Math.fround(viewport.center[0]), Math.fround(viewport.center[1]), 0]; // Geospatial origin (wgs84) must match shaderCoordinateOrigin (common)

          geospatialOrigin = viewport.unprojectPosition(shaderCoordinateOrigin);
          shaderCoordinateOrigin[0] -= coordinateOrigin[0];
          shaderCoordinateOrigin[1] -= coordinateOrigin[1];
          shaderCoordinateOrigin[2] -= coordinateOrigin[2];
        }

        break;

      case PROJECTION_MODE.IDENTITY:
        shaderCoordinateOrigin = viewport.position.map(Math.fround);
        break;

      default:
        // Unknown projection mode
        offsetMode = false;
    }

    shaderCoordinateOrigin[2] = shaderCoordinateOrigin[2] || 0;
    return {
      geospatialOrigin: geospatialOrigin,
      shaderCoordinateOrigin: shaderCoordinateOrigin,
      offsetMode: offsetMode
    };
  }

  function calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin) {
    var viewMatrixUncentered = viewport.viewMatrixUncentered,
        projectionMatrix = viewport.projectionMatrix; // eslint-disable-next-line prefer-const

    var viewMatrix = viewport.viewMatrix,
        viewProjectionMatrix = viewport.viewProjectionMatrix;
    var projectionCenter = ZERO_VECTOR$1;
    var cameraPosCommon = viewport.cameraPosition;

    var _getOffsetOrigin = getOffsetOrigin(viewport, coordinateSystem, coordinateOrigin),
        geospatialOrigin = _getOffsetOrigin.geospatialOrigin,
        shaderCoordinateOrigin = _getOffsetOrigin.shaderCoordinateOrigin,
        offsetMode = _getOffsetOrigin.offsetMode;

    if (offsetMode) {
      // Calculate transformed projectionCenter (using 64 bit precision JS)
      // This is the key to offset mode precision
      // (avoids doing this addition in 32 bit precision in GLSL)
      // @ts-ignore
      var positionCommonSpace = viewport === null || viewport === void 0 ? void 0 : viewport.projectPosition(geospatialOrigin || shaderCoordinateOrigin);
      cameraPosCommon = [cameraPosCommon[0] - positionCommonSpace[0], cameraPosCommon[1] - positionCommonSpace[1], cameraPosCommon[2] - positionCommonSpace[2]];
      positionCommonSpace[3] = 1; // projectionCenter = new Matrix4(viewProjectionMatrix)
      //   .transformVector([positionPixels[0], positionPixels[1], 0.0, 1.0]);
      // @ts-ignore

      projectionCenter = transformMat4$2([], positionCommonSpace, viewProjectionMatrix); // Always apply uncentered projection matrix if available (shader adds center)

      viewMatrix = viewMatrixUncentered || viewMatrix; // Zero out 4th coordinate ("after" model matrix) - avoids further translations
      // viewMatrix = new Matrix4(viewMatrixUncentered || viewMatrix)
      //   .multiplyRight(VECTOR_TO_POINT_MATRIX);
      // @ts-ignore

      viewProjectionMatrix = multiply$1(createMat4(), projectionMatrix, viewMatrix); // @ts-ignore

      viewProjectionMatrix = multiply$1(createMat4(), viewProjectionMatrix, VECTOR_TO_POINT_MATRIX);
    }

    return {
      viewMatrix: viewMatrix,
      viewProjectionMatrix: viewProjectionMatrix,
      projectionCenter: projectionCenter,
      geospatialOrigin: geospatialOrigin,
      shaderCoordinateOrigin: shaderCoordinateOrigin,
      cameraPosCommon: cameraPosCommon
    };
  }

  function calculateViewportUniforms(options) {
    var viewport = options.viewport,
        devicePixelRatio = options.devicePixelRatio,
        coordinateSystem = options.coordinateSystem,
        coordinateOrigin = options.coordinateOrigin;

    var _calculateMatrixAndOf = calculateMatrixAndOffset(viewport, coordinateSystem, coordinateOrigin),
        projectionCenter = _calculateMatrixAndOf.projectionCenter,
        viewProjectionMatrix = _calculateMatrixAndOf.viewProjectionMatrix,
        shaderCoordinateOrigin = _calculateMatrixAndOf.shaderCoordinateOrigin,
        geospatialOrigin = _calculateMatrixAndOf.geospatialOrigin,
        cameraPosCommon = _calculateMatrixAndOf.cameraPosCommon; // Calculate projection pixels per unit


    var distanceScales = viewport.distanceScales;
    var viewportSize = [viewport.width * devicePixelRatio, viewport.height * devicePixelRatio];
    var uniforms = {
      project_uCoordinateSystem: coordinateSystem,
      project_uProjectionMode: viewport.projectionMode,
      project_uCoordinateOrigin: shaderCoordinateOrigin,
      project_uCenter: projectionCenter,
      project_uAntimeridian: (viewport.longitude || 0) - 180,
      // Screen size
      project_uViewportSize: viewportSize,
      project_uDevicePixelRatio: devicePixelRatio,
      // Distance at which screen pixels are projected
      // @ts-ignore
      project_uFocalDistance: viewport.focalDistance || 1,
      project_uCommonUnitsPerMeter: distanceScales.unitsPerMeter,
      project_uCommonUnitsPerWorldUnit: distanceScales.unitsPerMeter,
      project_uCommonUnitsPerWorldUnit2: DEFAULT_PIXELS_PER_UNIT2,
      project_uScale: viewport.scale,
      project_uViewProjectionMatrix: viewProjectionMatrix,
      project_uInverseViewProjectionMatrix: invert$1(createMat4(), viewProjectionMatrix),
      // @ts-ignore
      project_metersPerPixel: distanceScales.metersPerUnit[2] / viewport.scale,
      project_uCameraPosition: cameraPosCommon
    };

    if (geospatialOrigin) {
      var distanceScalesAtOrigin = viewport.getDistanceScales(geospatialOrigin);

      if (distanceScalesAtOrigin) {
        switch (coordinateSystem) {
          case COORDINATE_SYSTEM.METER_OFFSETS:
            uniforms.project_uCommonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerMeter;
            uniforms.project_uCommonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerMeter2;
            break;

          case COORDINATE_SYSTEM.LNGLAT:
          case COORDINATE_SYSTEM.LNGLAT_OFFSETS:
            uniforms.project_uCommonUnitsPerWorldUnit = distanceScalesAtOrigin.unitsPerDegree;
            uniforms.project_uCommonUnitsPerWorldUnit2 = distanceScalesAtOrigin.unitsPerDegree2;
            break;
          // a.k.a "preprojected" positions

          case COORDINATE_SYSTEM.CARTESIAN:
            uniforms.project_uCommonUnitsPerWorldUnit = [1, 1, distanceScalesAtOrigin.unitsPerMeter[2]];
            uniforms.project_uCommonUnitsPerWorldUnit2 = [0, 0, // @ts-ignore
            distanceScalesAtOrigin.unitsPerMeter2[2]];
            break;
        }
      }
    }

    return uniforms;
  }
  /**
   * Returns uniforms for shaders based on current projection
   * includes: projection matrix suitable for shaders
   * @param viewport
   * @param devicePixelRatio
   * @param modelMatrix
   * @param coordinateSystem
   * @param coordinateOrigin
   * @param autoWrapLongitude
   * @return {Float32Array} - 4x4 projection matrix that can be used in shaders
   */


  function getUniformsFromViewport(_ref) {
    var viewport = _ref.viewport,
        _ref$devicePixelRatio = _ref.devicePixelRatio,
        devicePixelRatio = _ref$devicePixelRatio === void 0 ? INITIAL_MODULE_OPTIONS.devicePixelRatio : _ref$devicePixelRatio,
        _ref$modelMatrix = _ref.modelMatrix,
        modelMatrix = _ref$modelMatrix === void 0 ? null : _ref$modelMatrix,
        _ref$coordinateSystem = _ref.coordinateSystem,
        coordinateSystem = _ref$coordinateSystem === void 0 ? COORDINATE_SYSTEM.DEFAULT : _ref$coordinateSystem,
        coordinateOrigin = _ref.coordinateOrigin,
        _ref$autoWrapLongitud = _ref.autoWrapLongitude,
        autoWrapLongitude = _ref$autoWrapLongitud === void 0 ? false : _ref$autoWrapLongitud;

    if (coordinateSystem === COORDINATE_SYSTEM.DEFAULT) {
      coordinateSystem = viewport.isGeospatial ? COORDINATE_SYSTEM.LNGLAT : COORDINATE_SYSTEM.CARTESIAN;
    }

    var uniforms = getMemoizedViewportUniforms({
      viewport: viewport,
      devicePixelRatio: devicePixelRatio,
      coordinateSystem: coordinateSystem,
      coordinateOrigin: coordinateOrigin
    });
    uniforms.project_uWrapLongitude = autoWrapLongitude;
    uniforms.project_uModelMatrix = modelMatrix || IDENTITY_MATRIX;
    return uniforms;
  }
  function getUniformKeys() {
    return ['project_uCoordinateSystem', 'project_uProjectionMode', 'project_uCoordinateOrigin', 'project_uCenter', 'project_uAntimeridian', 'project_uViewportSize', 'project_uDevicePixelRatio', 'project_uFocalDistance', 'project_uCommonUnitsPerMeter', 'project_uCommonUnitsPerWorldUnit', 'project_uCommonUnitsPerWorldUnit2', 'project_uScale', 'project_uViewProjectionMatrix', 'project_metersPerPixel', 'project_uModelMatrix', 'project_uWrapLongitude', 'project_uCameraPosition'];
  }
  function getUniforms(opts) {
    if (opts.viewport) {
      return getUniformsFromViewport(opts);
    }

    return {};
  }
  function highPrecisionLngLat(lngLat) {
    var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
    var stride = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2;
    var numElements = Math.ceil((lngLat.length - offset) / stride);
    var precisionData = new Float32Array(numElements * 2);

    for (var i = 0; i < numElements; ++i) {
      var lli = offset + i * stride;
      var pi = i * 2;
      precisionData[pi] = lngLat[lli] - Math.fround(lngLat[lli]);
      precisionData[pi + 1] = lngLat[lli + 1] - Math.fround(lngLat[lli + 1]);
    }

    return precisionData;
  }
  function injectMercatorGLSL(gl, source) {
    var defines = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
      PROJECT_OFFSET_THRESHOLD: '4096.0'
    };
    var versionMatch = source.match(/#version \d+(\s+es)?\s*\n/);
    var versionLine = versionMatch ? versionMatch[0] : '';
    return "".concat(versionLine, "\n").concat(getPlatformShaderDefines(gl), "\n").concat(getApplicationDefines(defines), "\n").concat(FRAGMENT_SHADER_PROLOGUE, "\n").concat(fp32shader, "\n").concat(projectShader, "\n").concat(source.replace(versionLine, ''), "\n");
  }
  var fp32 = {
    name: 'fp32',
    vs: fp32shader,
    fs: null
  };
  var project = {
    name: 'project',
    vs: projectShader,
    fs: null,
    inject: {},
    dependencies: [fp32],
    deprecations: [],
    getUniforms: getUniforms
  };

  exports.WebMercatorViewport = WebMercatorViewport;
  exports.fp32 = fp32;
  exports.getOffsetOrigin = getOffsetOrigin;
  exports.getUniformKeys = getUniformKeys;
  exports.getUniforms = getUniforms;
  exports.getUniformsFromViewport = getUniformsFromViewport;
  exports.highPrecisionLngLat = highPrecisionLngLat;
  exports.injectMercatorGLSL = injectMercatorGLSL;
  exports.invert = invert$1;
  exports.isEqual = isEqual;
  exports.memoize = memoize;
  exports.multiply = multiply$1;
  exports.project = project;
  exports.transformMat4 = transformMat4$2;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=mercator-proj.js.map