import {Extent} from "./Extent";
import {LonLat} from './LonLat';
/**
* Mercator size.
* @const
* @type {number}
*/
export const POLE = 20037508.34;
export const POLE2 = POLE * 2.0;
export const PI_BY_POLE = Math.PI / POLE;
export const POLE_BY_PI = POLE / Math.PI;
const HALF_PI = Math.PI * 0.5;
export const POLE_BY_180 = POLE / 180.0;
export const INV_POLE_BY_180 = 180.0 / POLE;
const PI_BY_360 = Math.PI / 360.0;
const PI_BY_180 = Math.PI / 180.0;
const INV_PI_BY_180 = 180.0 / Math.PI;
/**
* Double mercator size.
* @const
* @type {number}
*/
export const POLE_DOUBLE = 2.0 * POLE;
/**
* One by mercator double size.
* @const
* @type {number}
*/
export const ONE_BY_POLE_DOUBLE = 1.0 / POLE_DOUBLE;
export function forward(lonLat: LonLat): LonLat {
return new LonLat(lonLat.lon * POLE / 180.0, Math.log(Math.tan((90.0 + lonLat.lat) * PI_BY_360)) * POLE_BY_PI, lonLat.height);
}
/**
* Converts degrees longitude to mercator coordinate.
* @function
* @param {number} lon - Degrees geodetic longitude.
* @returns {number} -
*/
export function forward_lon(lon: number): number {
return lon * POLE / 180.0;
}
/**
* Converts degrees latitude to mercator coordinate.
* @function
* @param {number} lat - Degrees geodetic latitude.
* @returns {number} -
*/
export function forward_lat(lat: number): number {
return Math.log(Math.tan((90.0 + lat) * PI_BY_360)) * POLE_BY_PI;
}
/**
* Converts mercator longitude to degrees coordinate.
* @function
* @param {number} lon - Mercator longitude.
* @returns {number} -
*/
export function inverse_lon(lon: number): number {
return 180 * lon / POLE;
}
/**
* Converts mercator latitude to degrees coordinate.
* @function
* @param {number} lon - Mercator latitude.
* @returns {number} -
*/
export function inverse_lat(lat: number): number {
return INV_PI_BY_180 * (2.0 * Math.atan(Math.exp(lat * PI_BY_POLE)) - HALF_PI);
}
/**
* Returns mercator map tile grid horizontal coordinate index by geodetic
* longitude and zoom level. Where top left corner of the grid is 0 coordinate index.
* @function
* @param {number} lon - Geodetic degrees longitude.
* @param {number} zoom - Zoom level.
* @returns {number}
*/
export function getTileX(lon: number, zoom: number): number {
return Math.floor((lon + 180) / 360.0 * Math.pow(2, zoom));
}
/**
* Returns mercator map tile grid vertical coordinate index by geodetic
* latitude and zoom level. Where top left corner of the grid is 0 coordinate index.
* @function
* @param {number} lat - Geodetic degrees latitude.
* @param {number} zoom - Zoom level.
* @returns {number}
*/
export function getTileY(lat: number, zoom: number): number {
return Math.floor((1.0 - Math.log(Math.tan(lat * PI_BY_180) + 1.0 / Math.cos(lat * PI_BY_180)) / Math.PI) * 0.5 * Math.pow(2, zoom));
}
/**
* Converts geodetic coordinate array to mercator coordinate array.
* @function
* @param {Array.<LonLat>} lonLatArr - LonLat array to convert.
* @returns {Array.<LonLat>}
*/
export function forwardArray(lonlatArr: LonLat[]): LonLat[] {
let res: LonLat[] = [];
for (let i = 0; i < lonlatArr.length; i++) {
res.push(lonlatArr[i].forwardMercator());
}
return res;
}
export function getTileExtent(x: number, y: number, z: number): Extent {
let size = POLE2 / (1 << z),//Math.pow(2, z),
sw = new LonLat(-POLE + x * size, POLE - y * size - size);
return new Extent(sw, new LonLat(sw.lon + size, sw.lat + size));
}
/**
* Max mercator latitude.
* @const
* @type {number}
*/
export const MAX_LAT = inverse_lat(POLE);
/**
* Min mercator latitude.
* @const
* @type {number}
*/
export const MIN_LAT = -MAX_LAT;