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

1,697 lines 68.6 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
 */
'use strict';

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

var mat4 = require('gl-matrix/mat4');
var vec3 = require('gl-matrix/vec3');
var vec2 = require('gl-matrix/vec2');
var vec4 = require('gl-matrix/vec4');

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.");
}

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;
  }
}

// @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 = vec4.transformMat4([], vector, matrix);
  vec4.scale(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 = vec2.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 = _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)

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

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

  if (center) {
    mat4.translate(vm, vm, vec3.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 vec2.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 = mat4.translate(m, m, [512 * worldOffset, 0, 0]);
      viewMatrixUncentered = mat4.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;
        mat4.ortho(m, -right, right, -top, top, near, far);
      } else {
        mat4.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 ? vec3.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();
      mat4.multiply(this.viewMatrix, this.viewMatrixUncentered, this.viewMatrix);
      mat4.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();
      mat4.multiply(vpm, vpm, this.projectionMatrix);
      mat4.multiply(vpm, vpm, this.viewMatrix);
      this.viewProjectionMatrix = vpm; // console.log('VPM', this.viewMatrix, this.projectionMatrix, this.viewProjectionMatrix);
      // Calculate inverse view matrix

      this.viewMatrixInverse = mat4.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.

      mat4.scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
      mat4.translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
      mat4.multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
      this.pixelProjectionMatrix = pixelProjectionMatrix;
      this.viewportMatrix = viewportMatrix;
      var m = createMat4();
      this.pixelUnprojectionMatrix = mat4.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 = vec2.add([], toLocation, vec2.negate([], fromLocation));
      var newCenter = vec2.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(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(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(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([], 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(createMat4(), projectionMatrix, viewMatrix); // @ts-ignore

    viewProjectionMatrix = multiply(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(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;
exports.isEqual = isEqual;
exports.memoize = memoize;
exports.multiply = multiply;
exports.project = project;
exports.transformMat4 = transformMat4;
//# sourceMappingURL=mercator-proj.cjs.js.map