UNPKG

mapbox-gl

Version:
69 lines (60 loc) 2.94 kB
// @flow import LngLat from '../lng_lat.js'; import {clamp, degToRad, radToDeg} from '../../util/util.js'; import {MAX_MERCATOR_LATITUDE} from '../mercator_coordinate.js'; import Projection from './projection.js'; import type {ProjectedPoint} from './projection.js'; const maxPhi = degToRad(MAX_MERCATOR_LATITUDE); export default class WinkelTripel extends Projection { project(lng: number, lat: number): ProjectedPoint { lat = degToRad(lat); lng = degToRad(lng); const cosLat = Math.cos(lat); const twoOverPi = 2 / Math.PI; const alpha = Math.acos(cosLat * Math.cos(lng / 2)); const sinAlphaOverAlpha = Math.sin(alpha) / alpha; const x = 0.5 * (lng * twoOverPi + (2 * cosLat * Math.sin(lng / 2)) / sinAlphaOverAlpha) || 0; const y = 0.5 * (lat + Math.sin(lat) / sinAlphaOverAlpha) || 0; return { x: (x / Math.PI + 0.5) * 0.5, y: 1 - (y / Math.PI + 1) * 0.5, z: 0 }; } unproject(x: number, y: number): LngLat { // based on https://github.com/d3/d3-geo-projection, MIT-licensed x = (2 * x - 0.5) * Math.PI; y = (2 * (1 - y) - 1) * Math.PI; let lambda = x; let phi = y; let i = 25; const epsilon = 1e-6; let dlambda = 0, dphi = 0; do { const cosphi = Math.cos(phi), sinphi = Math.sin(phi), sinphi2 = 2 * sinphi * cosphi, sin2phi = sinphi * sinphi, cos2phi = cosphi * cosphi, coslambda2 = Math.cos(lambda / 2), sinlambda2 = Math.sin(lambda / 2), sinlambda = 2 * coslambda2 * sinlambda2, sin2lambda2 = sinlambda2 * sinlambda2, C = 1 - cos2phi * coslambda2 * coslambda2, F = C ? 1 / C : 0, E = C ? Math.acos(cosphi * coslambda2) * Math.sqrt(1 / C) : 0, fx = 0.5 * (2 * E * cosphi * sinlambda2 + lambda * 2 / Math.PI) - x, fy = 0.5 * (E * sinphi + phi) - y, dxdlambda = 0.5 * F * (cos2phi * sin2lambda2 + E * cosphi * coslambda2 * sin2phi) + 1 / Math.PI, dxdphi = F * (sinlambda * sinphi2 / 4 - E * sinphi * sinlambda2), dydlambda = 0.125 * F * (sinphi2 * sinlambda2 - E * sinphi * cos2phi * sinlambda), dydphi = 0.5 * F * (sin2phi * coslambda2 + E * sin2lambda2 * cosphi) + 0.5, denominator = dxdphi * dydlambda - dydphi * dxdlambda; dlambda = (fy * dxdphi - fx * dydphi) / denominator; dphi = (fx * dydlambda - fy * dxdlambda) / denominator; lambda = clamp(lambda - dlambda, -Math.PI, Math.PI); phi = clamp(phi - dphi, -maxPhi, maxPhi); } while ((Math.abs(dlambda) > epsilon || Math.abs(dphi) > epsilon) && --i > 0); return new LngLat(radToDeg(lambda), radToDeg(phi)); } }