mercator-proj
Version:
[](https://travis-ci.com/sakitam-gis/mercator-proj) [ 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