s2-tools
Version:
A collection of geospatial tools primarily designed for WGS84, Web Mercator, and S2.
152 lines • 4.46 kB
JavaScript
import { EPSLN } from '../constants';
import { ProjectionBase } from '.';
import { adjustLat, adjustLon, e0fn, e1fn, e2fn, e3fn, imlfn, mlfn, msfnz } from '../common';
/**
* # Equidistant Conic
*
* **Classification**: Conic
*
* **Available forms**: Forward and inverse, ellipsoidal
*
* **Defined area**: Global
*
* **Alias**: eqdc
*
* **Domain**: 2D
*
* **Input type**: Geodetic coordinates
*
* **Output type**: Projected coordinates
*
* ## Projection String
* ```
* +proj=eqdc +lat_1=55 +lat_2=60
* ```
*
* ## Parameters
*
* ### Required
* - `+lat_1` (Latitude of the first standard parallel)
* - `+lat_2` (Latitude of the second standard parallel)
*
* ### Optional
* - `+lon_0` (Central meridian)
* - `+ellps` (Ellipsoid name)
* - `+R` (Radius of the sphere)
* - `+x_0` (False easting)
* - `+y_0` (False northing)
*
* 
*/
export class EquidistantConic extends ProjectionBase {
name = 'Equidistant_Conic';
static names = ['Equidistant_Conic', 'eqdc'];
// EquidistantConic specific variables
rh;
temp;
g;
e0;
e1;
e2;
e3;
sinphi;
cosphi;
ms1;
ms2 = 0;
ml0;
ml1;
ml2 = 0;
ns;
/**
* Preps an EquidistantConic projection
* @param params - projection specific parameters
*/
constructor(params) {
const { abs, sin, cos } = Math;
super(params);
if (abs(this.lat1 + this.lat2) < EPSLN)
throw new Error('Standard parallels cannot be equal and on opposite sides of the equator');
this.lat2 = this.lat2 ?? this.lat1;
this.temp = this.b / this.a;
this.es = 1 - Math.pow(this.temp, 2);
this.e = Math.sqrt(this.es);
this.e0 = e0fn(this.es);
this.e1 = e1fn(this.es);
this.e2 = e2fn(this.es);
this.e3 = e3fn(this.es);
this.sinphi = Math.sin(this.lat1);
this.cosphi = Math.cos(this.lat1);
this.ms1 = msfnz(this.e, this.sinphi, this.cosphi);
this.ml1 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat1);
if (abs(this.lat1 - this.lat2) < EPSLN) {
this.ns = this.sinphi;
}
else {
this.sinphi = sin(this.lat2);
this.cosphi = cos(this.lat2);
this.ms2 = msfnz(this.e, this.sinphi, this.cosphi);
this.ml2 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2);
this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1);
}
this.g = this.ml1 + this.ms1 / this.ns;
this.ml0 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0);
this.rh = this.a * (this.g - this.ml0);
}
/**
* EquidistantConic forward equations--mapping lon-lat to x-y
* @param p - lon-lat WGS84 point
*/
forward(p) {
const { sin, cos } = Math;
const { x: lon, y: lat } = p;
let rh1;
if (this.sphere) {
rh1 = this.a * (this.g - lat);
}
else {
const ml = mlfn(this.e0, this.e1, this.e2, this.e3, lat);
rh1 = this.a * (this.g - ml);
}
const theta = this.ns * adjustLon(lon - this.long0);
const x = this.x0 + rh1 * sin(theta);
const y = this.y0 + this.rh - rh1 * cos(theta);
p.x = x;
p.y = y;
}
/**
* EquidistantConic inverse equations--mapping x-y to lon-lat
* @param p - EquidistantConic point
*/
inverse(p) {
const { sqrt, atan2 } = Math;
p.x -= this.x0;
p.y = this.rh - p.y + this.y0;
let con, rh1, lat, lon;
if (this.ns >= 0) {
rh1 = sqrt(p.x * p.x + p.y * p.y);
con = 1;
}
else {
rh1 = -sqrt(p.x * p.x + p.y * p.y);
con = -1;
}
let theta = 0;
if (rh1 !== 0) {
theta = atan2(con * p.x, con * p.y);
}
if (this.sphere) {
lon = adjustLon(this.long0 + theta / this.ns);
lat = adjustLat(this.g - rh1 / this.a);
p.x = lon;
p.y = lat;
}
else {
const ml = this.g - rh1 / this.a;
lat = imlfn(ml, this.e0, this.e1, this.e2, this.e3);
lon = adjustLon(this.long0 + theta / this.ns);
p.x = lon;
p.y = lat;
}
}
}
//# sourceMappingURL=eqdc.js.map