UNPKG

s2maps-gpu

Version:

S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.

104 lines (103 loc) 3.26 kB
import { MAXLAT, llToPX, pxToLL } from 'gis-tools/index.js'; // https://github.com/proj4js/proj4js/blob/master/lib/projections/ortho.js const EPSLN = 1.0e-10; const D2R = 0.017453292519943295; const R2D = 57.29577951308232; /** * Get the longitude and latitude of the cursor position in the S2 Geometry Projection. * centerLon and centerlat is where the center of the sphere is currently located * x is the distance from center * @param centerLon - center longitude * @param centerLat - center latitude * @param xOffset - distance from center * @param yOffset - distance from center * @param radius - the radius of the sphere * @returns longitude and latitude */ export function cursorToLonLatS2(centerLon, centerLat, xOffset, yOffset, radius) { // pre adjust to radians centerLon *= D2R; centerLat *= D2R; // prep const { PI, sqrt, sin, cos, abs, atan2 } = Math; const rh = sqrt(xOffset * xOffset + yOffset * yOffset); // corner case, the x+y is too far if (rh > radius) return; const z = asinz(rh / radius); const sinP14 = sin(centerLat); const cosP14 = cos(centerLat); const sinz = sin(z); const cosz = cos(z); let lon = centerLon; let lat = centerLat; const con = abs(centerLat) - PI / 2; // corner case: basically on the dot center if (abs(rh) <= EPSLN) return { x: lon * R2D, y: lat * R2D }; // build lat lat = asinz(cosz * sinP14 + (yOffset * sinz * cosP14) / rh); // negative angles if (abs(con) <= EPSLN) { if (centerLat >= 0) lon = adjustLon(centerLon + atan2(xOffset, -yOffset)); else lon = adjustLon(centerLon - atan2(-xOffset, yOffset)); } else { // positive angles lon = adjustLon(centerLon + atan2(xOffset * sinz, rh * cosP14 * cosz - yOffset * sinP14 * sinz)); } return { x: lon * R2D, y: lat * R2D }; } /** * Get the longitude and latitude of the cursor position in the web mercator projection. * @param lon - center longitude * @param lat - center latitude * @param xOffset - x offset * @param yOffset - y offset * @param zoom - zoom * @param tileSize - tile size * @returns longitude and latitude */ export function cursorToLonLatWM(lon, lat, xOffset, yOffset, zoom, tileSize) { // grab the px position of lon lat const px = llToPX({ x: lon, y: lat }, zoom, false, tileSize); // if px + offset is outside of min and max, return undefined // adjust by the offset px.x += xOffset; px.y -= yOffset; // convert back to lon lat const ll = pxToLL(px, zoom, tileSize); if (ll.x > 180 || ll.x < -180 || ll.y > MAXLAT || ll.y < -MAXLAT) return; return ll; } /** * Arcsine * @param x - input * @returns the arcsine(x) */ function asinz(x) { const { abs, asin } = Math; if (abs(x) > 1) x = x > 1 ? 1 : -1; return asin(x); } /** * Adjust longitude to be between -180 and 180 * @param x - longitude * @returns adjusted longitude */ function adjustLon(x) { const { PI, abs } = Math; return abs(x) <= 3.14159265359 ? x : x - sign(x) * PI * 2; } /** * Get the sign of a number * @param x - input * @returns the sign(x) */ function sign(x) { return x < 0 ? -1 : 1; }