UNPKG

@signalk/charts-plugin

Version:

Signal K plugin to provide chart support for Signal K server

56 lines 2.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WEB_MERCATOR_MAX_LAT = exports.WEB_MERCATOR_HALF_EXTENT_M = void 0; exports.tileToBBox = tileToBBox; exports.lonLatToMercator = lonLatToMercator; exports.lonLatToTile = lonLatToTile; // EPSG:3857 half the equator circumference, in meters. // Used to scale lon/lat into Web Mercator x/y. exports.WEB_MERCATOR_HALF_EXTENT_M = 20037508.34; // Web Mercator is undefined at the poles. This is the symmetric latitude // where the projection maps to ±WEB_MERCATOR_HALF_EXTENT_M, also the clamp // limit used by OSM / Google / MapBox tile schemes. exports.WEB_MERCATOR_MAX_LAT = 85.0511287798; // Web Mercator tile → WGS84 bounding box. // Input (x=1, y=1, z=2): tile (1,1) at zoom 2 — one of sixteen. // Output: [minLon, minLat, maxLon, maxLat] for that tile in degrees. // x and y must be inside the grid ([0, 2^z)); out-of-range inputs produced // nonsense coordinates that silently fed downstream bbox math. Fail fast. function tileToBBox(x, y, z) { if (!Number.isInteger(z) || z < 0) { throw new RangeError(`tileToBBox: invalid zoom ${z}`); } const n = 2 ** z; if (!Number.isInteger(x) || x < 0 || x >= n) { throw new RangeError(`tileToBBox: x=${x} out of range at z=${z}`); } if (!Number.isInteger(y) || y < 0 || y >= n) { throw new RangeError(`tileToBBox: y=${y} out of range at z=${z}`); } const lon1 = (x / n) * 360 - 180; const lat1 = (Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / n))) * 180) / Math.PI; const lon2 = ((x + 1) / n) * 360 - 180; const lat2 = (Math.atan(Math.sinh(Math.PI * (1 - (2 * (y + 1)) / n))) * 180) / Math.PI; return [lon1, lat2, lon2, lat1]; } function lonLatToMercator(lon, lat) { const x = (lon * exports.WEB_MERCATOR_HALF_EXTENT_M) / 180; const yDeg = Math.log(Math.tan(((90 + lat) * Math.PI) / 360)) / (Math.PI / 180); return [x, (yDeg * exports.WEB_MERCATOR_HALF_EXTENT_M) / 180]; } // Converts lon/lat to an XYZ tile coordinate at the given zoom. Latitude is // clamped to WEB_MERCATOR_MAX_LAT: without that clamp, tan(π/2) at ±90 blows // up to Infinity and floor(NaN) leaks NaN into the tile list. function lonLatToTile(lon, lat, zoom) { const n = 2 ** zoom; const clampedLat = Math.max(-exports.WEB_MERCATOR_MAX_LAT, Math.min(exports.WEB_MERCATOR_MAX_LAT, lat)); const x = Math.floor(((lon + 180) / 360) * n); const y = Math.floor(((1 - Math.log(Math.tan((clampedLat * Math.PI) / 180) + 1 / Math.cos((clampedLat * Math.PI) / 180)) / Math.PI) / 2) * n); return [x, y]; } //# sourceMappingURL=projection.js.map