130 lines
3.1 KiB
JavaScript
130 lines
3.1 KiB
JavaScript
import adjust_lon from '../common/adjust_lon';
|
|
|
|
import {HALF_PI, EPSLN} from '../constants/values';
|
|
|
|
import asinz from '../common/asinz';
|
|
|
|
/* Initialize the Van Der Grinten projection
|
|
----------------------------------------*/
|
|
export function init() {
|
|
//this.R = 6370997; //Radius of earth
|
|
this.R = this.a;
|
|
}
|
|
|
|
export function forward(p) {
|
|
|
|
var lon = p.x;
|
|
var lat = p.y;
|
|
|
|
/* Forward equations
|
|
-----------------*/
|
|
var dlon = adjust_lon(lon - this.long0);
|
|
var x, y;
|
|
|
|
if (Math.abs(lat) <= EPSLN) {
|
|
x = this.x0 + this.R * dlon;
|
|
y = this.y0;
|
|
}
|
|
var theta = asinz(2 * Math.abs(lat / Math.PI));
|
|
if ((Math.abs(dlon) <= EPSLN) || (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN)) {
|
|
x = this.x0;
|
|
if (lat >= 0) {
|
|
y = this.y0 + Math.PI * this.R * Math.tan(0.5 * theta);
|
|
}
|
|
else {
|
|
y = this.y0 + Math.PI * this.R * -Math.tan(0.5 * theta);
|
|
}
|
|
// return(OK);
|
|
}
|
|
var al = 0.5 * Math.abs((Math.PI / dlon) - (dlon / Math.PI));
|
|
var asq = al * al;
|
|
var sinth = Math.sin(theta);
|
|
var costh = Math.cos(theta);
|
|
|
|
var g = costh / (sinth + costh - 1);
|
|
var gsq = g * g;
|
|
var m = g * (2 / sinth - 1);
|
|
var msq = m * m;
|
|
var con = Math.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq);
|
|
if (dlon < 0) {
|
|
con = -con;
|
|
}
|
|
x = this.x0 + con;
|
|
//con = Math.abs(con / (Math.PI * this.R));
|
|
var q = asq + g;
|
|
con = Math.PI * this.R * (m * q - al * Math.sqrt((msq + asq) * (asq + 1) - q * q)) / (msq + asq);
|
|
if (lat >= 0) {
|
|
//y = this.y0 + Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con);
|
|
y = this.y0 + con;
|
|
}
|
|
else {
|
|
//y = this.y0 - Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con);
|
|
y = this.y0 - con;
|
|
}
|
|
p.x = x;
|
|
p.y = y;
|
|
return p;
|
|
}
|
|
|
|
/* Van Der Grinten inverse equations--mapping x,y to lat/long
|
|
---------------------------------------------------------*/
|
|
export function inverse(p) {
|
|
var lon, lat;
|
|
var xx, yy, xys, c1, c2, c3;
|
|
var a1;
|
|
var m1;
|
|
var con;
|
|
var th1;
|
|
var d;
|
|
|
|
/* inverse equations
|
|
-----------------*/
|
|
p.x -= this.x0;
|
|
p.y -= this.y0;
|
|
con = Math.PI * this.R;
|
|
xx = p.x / con;
|
|
yy = p.y / con;
|
|
xys = xx * xx + yy * yy;
|
|
c1 = -Math.abs(yy) * (1 + xys);
|
|
c2 = c1 - 2 * yy * yy + xx * xx;
|
|
c3 = -2 * c1 + 1 + 2 * yy * yy + xys * xys;
|
|
d = yy * yy / c3 + (2 * c2 * c2 * c2 / c3 / c3 / c3 - 9 * c1 * c2 / c3 / c3) / 27;
|
|
a1 = (c1 - c2 * c2 / 3 / c3) / c3;
|
|
m1 = 2 * Math.sqrt(-a1 / 3);
|
|
con = ((3 * d) / a1) / m1;
|
|
if (Math.abs(con) > 1) {
|
|
if (con >= 0) {
|
|
con = 1;
|
|
}
|
|
else {
|
|
con = -1;
|
|
}
|
|
}
|
|
th1 = Math.acos(con) / 3;
|
|
if (p.y >= 0) {
|
|
lat = (-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI;
|
|
}
|
|
else {
|
|
lat = -(-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI;
|
|
}
|
|
|
|
if (Math.abs(xx) < EPSLN) {
|
|
lon = this.long0;
|
|
}
|
|
else {
|
|
lon = adjust_lon(this.long0 + Math.PI * (xys - 1 + Math.sqrt(1 + 2 * (xx * xx - yy * yy) + xys * xys)) / 2 / xx);
|
|
}
|
|
|
|
p.x = lon;
|
|
p.y = lat;
|
|
return p;
|
|
}
|
|
|
|
export var names = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"];
|
|
export default {
|
|
init: init,
|
|
forward: forward,
|
|
inverse: inverse,
|
|
names: names
|
|
};
|