brc-atlas-bigr
Version:
Utility functions for dealing with grid reference systems used in the British Isles.
1,975 lines (1,929 loc) • 216 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bigr = {}));
})(this, (function (exports) { 'use strict';
/** @module src/km100 */
/** @constant
* @description This the array from which the default object is derived. If you
* need to work with an array of objects where the 100 km grid reference is a property
* of the object alongside x, y, and proj, you can use this.
* @type {array}
*/
var a100km = [{
"GridRef": "SV",
"x": 0,
"y": 0,
"proj": "gb"
}, {
"GridRef": "NL",
"x": 0,
"y": 7,
"proj": "gb"
}, {
"GridRef": "NF",
"x": 0,
"y": 8,
"proj": "gb"
}, {
"GridRef": "NA",
"x": 0,
"y": 9,
"proj": "gb"
}, {
"GridRef": "SW",
"x": 1,
"y": 0,
"proj": "gb"
}, {
"GridRef": "SR",
"x": 1,
"y": 1,
"proj": "gb"
}, {
"GridRef": "SM",
"x": 1,
"y": 2,
"proj": "gb"
}, {
"GridRef": "NW",
"x": 1,
"y": 5,
"proj": "gb"
}, {
"GridRef": "NR",
"x": 1,
"y": 6,
"proj": "gb"
}, {
"GridRef": "NM",
"x": 1,
"y": 7,
"proj": "gb"
}, {
"GridRef": "NG",
"x": 1,
"y": 8,
"proj": "gb"
}, {
"GridRef": "NB",
"x": 1,
"y": 9,
"proj": "gb"
}, {
"GridRef": "HW",
"x": 1,
"y": 10,
"proj": "gb"
}, {
"GridRef": "SX",
"x": 2,
"y": 0,
"proj": "gb"
}, {
"GridRef": "SS",
"x": 2,
"y": 1,
"proj": "gb"
}, {
"GridRef": "SN",
"x": 2,
"y": 2,
"proj": "gb"
}, {
"GridRef": "SH",
"x": 2,
"y": 3,
"proj": "gb"
}, {
"GridRef": "SC",
"x": 2,
"y": 4,
"proj": "gb"
}, {
"GridRef": "NX",
"x": 2,
"y": 5,
"proj": "gb"
}, {
"GridRef": "NS",
"x": 2,
"y": 6,
"proj": "gb"
}, {
"GridRef": "NN",
"x": 2,
"y": 7,
"proj": "gb"
}, {
"GridRef": "NH",
"x": 2,
"y": 8,
"proj": "gb"
}, {
"GridRef": "NC",
"x": 2,
"y": 9,
"proj": "gb"
}, {
"GridRef": "HX",
"x": 2,
"y": 10,
"proj": "gb"
}, {
"GridRef": "SY",
"x": 3,
"y": 0,
"proj": "gb"
}, {
"GridRef": "ST",
"x": 3,
"y": 1,
"proj": "gb"
}, {
"GridRef": "SO",
"x": 3,
"y": 2,
"proj": "gb"
}, {
"GridRef": "SJ",
"x": 3,
"y": 3,
"proj": "gb"
}, {
"GridRef": "SD",
"x": 3,
"y": 4,
"proj": "gb"
}, {
"GridRef": "NY",
"x": 3,
"y": 5,
"proj": "gb"
}, {
"GridRef": "NT",
"x": 3,
"y": 6,
"proj": "gb"
}, {
"GridRef": "NO",
"x": 3,
"y": 7,
"proj": "gb"
}, {
"GridRef": "NJ",
"x": 3,
"y": 8,
"proj": "gb"
}, {
"GridRef": "ND",
"x": 3,
"y": 9,
"proj": "gb"
}, {
"GridRef": "HY",
"x": 3,
"y": 10,
"proj": "gb"
}, {
"GridRef": "HT",
"x": 3,
"y": 11,
"proj": "gb"
}, {
"GridRef": "SZ",
"x": 4,
"y": 0,
"proj": "gb"
}, {
"GridRef": "SU",
"x": 4,
"y": 1,
"proj": "gb"
}, {
"GridRef": "SP",
"x": 4,
"y": 2,
"proj": "gb"
}, {
"GridRef": "SK",
"x": 4,
"y": 3,
"proj": "gb"
}, {
"GridRef": "SE",
"x": 4,
"y": 4,
"proj": "gb"
}, {
"GridRef": "NZ",
"x": 4,
"y": 5,
"proj": "gb"
}, {
"GridRef": "NU",
"x": 4,
"y": 6,
"proj": "gb"
}, {
"GridRef": "NK",
"x": 4,
"y": 8,
"proj": "gb"
}, {
"GridRef": "HZ",
"x": 4,
"y": 10,
"proj": "gb"
}, {
"GridRef": "HU",
"x": 4,
"y": 11,
"proj": "gb"
}, {
"GridRef": "HP",
"x": 4,
"y": 12,
"proj": "gb"
}, {
"GridRef": "TV",
"x": 5,
"y": 0,
"proj": "gb"
}, {
"GridRef": "TQ",
"x": 5,
"y": 1,
"proj": "gb"
}, {
"GridRef": "TL",
"x": 5,
"y": 2,
"proj": "gb"
}, {
"GridRef": "TF",
"x": 5,
"y": 3,
"proj": "gb"
}, {
"GridRef": "TA",
"x": 5,
"y": 4,
"proj": "gb"
}, {
"GridRef": "OV",
"x": 5,
"y": 5,
"proj": "gb"
}, {
"GridRef": "TR",
"x": 6,
"y": 1,
"proj": "gb"
}, {
"GridRef": "TM",
"x": 6,
"y": 2,
"proj": "gb"
}, {
"GridRef": "TG",
"x": 6,
"y": 3,
"proj": "gb"
}, {
"GridRef": "V",
"x": 0,
"y": 0,
"proj": "ir"
}, {
"GridRef": "Q",
"x": 0,
"y": 1,
"proj": "ir"
}, {
"GridRef": "L",
"x": 0,
"y": 2,
"proj": "ir"
}, {
"GridRef": "F",
"x": 0,
"y": 3,
"proj": "ir"
}, {
"GridRef": "A",
"x": 0,
"y": 4,
"proj": "ir"
}, {
"GridRef": "W",
"x": 1,
"y": 0,
"proj": "ir"
}, {
"GridRef": "R",
"x": 1,
"y": 1,
"proj": "ir"
}, {
"GridRef": "M",
"x": 1,
"y": 2,
"proj": "ir"
}, {
"GridRef": "G",
"x": 1,
"y": 3,
"proj": "ir"
}, {
"GridRef": "B",
"x": 1,
"y": 4,
"proj": "ir"
}, {
"GridRef": "X",
"x": 2,
"y": 0,
"proj": "ir"
}, {
"GridRef": "S",
"x": 2,
"y": 1,
"proj": "ir"
}, {
"GridRef": "N",
"x": 2,
"y": 2,
"proj": "ir"
}, {
"GridRef": "H",
"x": 2,
"y": 3,
"proj": "ir"
}, {
"GridRef": "C",
"x": 2,
"y": 4,
"proj": "ir"
}, {
"GridRef": "Y",
"x": 3,
"y": 0,
"proj": "ir"
}, {
"GridRef": "T",
"x": 3,
"y": 1,
"proj": "ir"
}, {
"GridRef": "O",
"x": 3,
"y": 2,
"proj": "ir"
}, {
"GridRef": "J",
"x": 3,
"y": 3,
"proj": "ir"
}, {
"GridRef": "D",
"x": 3,
"y": 4,
"proj": "ir"
}, {
"GridRef": "Z",
"x": 4,
"y": 0,
"proj": "ir"
}, {
"GridRef": "U",
"x": 4,
"y": 1,
"proj": "ir"
}, {
"GridRef": "P",
"x": 4,
"y": 2,
"proj": "ir"
}, {
"GridRef": "K",
"x": 4,
"y": 3,
"proj": "ir"
}, {
"GridRef": "E",
"x": 4,
"y": 4,
"proj": "ir"
}, {
"GridRef": "WV",
"x": 5,
"y": 54,
"proj": "ci"
}, {
"GridRef": "WA",
"x": 5,
"y": 55,
"proj": "ci"
}];
/** @constant
* @description The default export from this module is an object with a property
* for every 100 km square reference for Britain (Brtish National Grid),
* Ireland (Irish National Grid) and the Channel Islands (abbreviated UTM 30N).
* Each grid reference references an object that has properties x, y and proj.
* The x and y coordinates represent the centroid of the 100 km square in the
* coordinate reference system corresponding to the aforementioned areas, respectively
* epsg:27700, epsg:29903 and epsg:32630. Another property, proj, indicates the region/CRS
* with two letter codes, respectively gb, ir and ci.
* <p>An example of the object referenced through the property 'SO' is shown below:</p>
* <pre>
* {
* "x": 3,
* "y": 2,
* "proj": "gb"
* }
* </pre>
* @type {object}
*/
var km100s = a100km.reduce(function (acc, km100) {
acc[km100.GridRef] = {
x: km100.x,
y: km100.y,
proj: km100.proj
};
return acc;
}, {});
/** @module src/checkGr */
function invalidGridRef(gr) {
throw "The value '".concat(gr, "' is not recognised as a valid grid reference.");
}
/**
* Given a grid reference (British National Grid, Irish Grid or UTM zone 30N shorthand),
* check that this is a valid GR. If it is, return an object which includes the
* GR precision in metres, the prefix and the two-letter projection code.
* If an invalid grid reference is supplied throws an error.
* @param {string} gr - the grid reference.
* @returns {object} Object of the form {precision: n, prefix: 'prefix', projection: 'code'}.
*/
function checkGr(gr) {
var r100km = RegExp('^[a-zA-Z]{1,2}$');
var rHectad = RegExp('^[a-zA-Z]{1,2}[0-9]{2}$');
var rQuandrant = RegExp('^[a-zA-Z]{1,2}[0-9]{2}[SsNn][WwEe]$');
var rTetrad = RegExp('^[a-zA-Z]{1,2}[0-9]{2}[a-np-zA-NP-Z]$');
var rMonad = RegExp('^[a-zA-Z]{1,2}[0-9]{4}$');
var r6fig = RegExp('^[a-zA-Z]{1,2}[0-9]{6}$');
var r8fig = RegExp('^[a-zA-Z]{1,2}[0-9]{8}$');
var r10fig = RegExp('^[a-zA-Z]{1,2}[0-9]{10}$');
var match = gr.match(/^[A-Za-z]+/);
if (!match) invalidGridRef(gr);
var prefix = match[0].toUpperCase();
var km100 = km100s[prefix];
if (!km100) invalidGridRef(gr);
var ret = {
precision: null,
prefix: prefix,
projection: km100.proj
};
if (r100km.test(gr)) {
// The GR is a 100 km square reference
ret.precision = 100000;
} else if (rHectad.test(gr)) {
// The GR is a hectad
ret.precision = 10000;
} else if (rQuandrant.test(gr)) {
// The GR is a quandrant
ret.precision = 5000;
} else if (rTetrad.test(gr)) {
// The GR is a tetrad
ret.precision = 2000;
} else if (rMonad.test(gr)) {
// The GR is a monad
ret.precision = 1000;
} else if (r6fig.test(gr)) {
// The GR is a 6 figure GR
ret.precision = 100;
} else if (r8fig.test(gr)) {
// The GR is a 8 figure GR
ret.precision = 10;
} else if (r10fig.test(gr)) {
// The GR is a 10 figure GR
ret.precision = 1;
} else {
invalidGridRef(gr);
}
return ret;
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function globals (defs) {
defs('EPSG:4326', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees");
defs('EPSG:4269', "+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees");
defs('EPSG:3857', "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs");
defs.WGS84 = defs['EPSG:4326'];
defs['EPSG:3785'] = defs['EPSG:3857']; // maintain backward compat, official code is 3857
defs.GOOGLE = defs['EPSG:3857'];
defs['EPSG:900913'] = defs['EPSG:3857'];
defs['EPSG:102113'] = defs['EPSG:3857'];
}
var PJD_3PARAM = 1;
var PJD_7PARAM = 2;
var PJD_WGS84 = 4; // WGS84 or equivalent
var PJD_NODATUM = 5; // WGS84 or equivalent
var SEC_TO_RAD = 4.84813681109535993589914102357e-6;
var HALF_PI = Math.PI / 2;
// ellipoid pj_set_ell.c
var SIXTH = 0.1666666666666666667;
/* 1/6 */
var RA4 = 0.04722222222222222222;
/* 17/360 */
var RA6 = 0.02215608465608465608;
var EPSLN = 1.0e-10;
// you'd think you could use Number.EPSILON above but that makes
// Mollweide get into an infinate loop.
var D2R$1 = 0.01745329251994329577;
var R2D = 57.29577951308232088;
var FORTPI = Math.PI / 4;
var TWO_PI = Math.PI * 2;
// SPI is slightly greater than Math.PI, so values that exceed the -180..180
// degree range by a tiny amount don't get wrapped. This prevents points that
// have drifted from their original location along the 180th meridian (due to
// floating point error) from changing their sign.
var SPI = 3.14159265359;
var exports$3 = {};
exports$3.greenwich = 0.0; //"0dE",
exports$3.lisbon = -9.131906111111; //"9d07'54.862\"W",
exports$3.paris = 2.337229166667; //"2d20'14.025\"E",
exports$3.bogota = -74.080916666667; //"74d04'51.3\"W",
exports$3.madrid = -3.687938888889; //"3d41'16.58\"W",
exports$3.rome = 12.452333333333; //"12d27'8.4\"E",
exports$3.bern = 7.439583333333; //"7d26'22.5\"E",
exports$3.jakarta = 106.807719444444; //"106d48'27.79\"E",
exports$3.ferro = -17.666666666667; //"17d40'W",
exports$3.brussels = 4.367975; //"4d22'4.71\"E",
exports$3.stockholm = 18.058277777778; //"18d3'29.8\"E",
exports$3.athens = 23.7163375; //"23d42'58.815\"E",
exports$3.oslo = 10.722916666667; //"10d43'22.5\"E"
var _units = {
ft: {
to_meter: 0.3048
},
'us-ft': {
to_meter: 1200 / 3937
}
};
var ignoredChar = /[\s_\-\/\(\)]/g;
function match(obj, key) {
if (obj[key]) {
return obj[key];
}
var keys = Object.keys(obj);
var lkey = key.toLowerCase().replace(ignoredChar, '');
var i = -1;
var testkey, processedKey;
while (++i < keys.length) {
testkey = keys[i];
processedKey = testkey.toLowerCase().replace(ignoredChar, '');
if (processedKey === lkey) {
return obj[testkey];
}
}
}
function projStr (defData) {
var self = {};
var paramObj = defData.split('+').map(function (v) {
return v.trim();
}).filter(function (a) {
return a;
}).reduce(function (p, a) {
var split = a.split('=');
split.push(true);
p[split[0].toLowerCase()] = split[1];
return p;
}, {});
var paramName, paramVal, paramOutname;
var params = {
proj: 'projName',
datum: 'datumCode',
rf: function rf(v) {
self.rf = parseFloat(v);
},
lat_0: function lat_0(v) {
self.lat0 = v * D2R$1;
},
lat_1: function lat_1(v) {
self.lat1 = v * D2R$1;
},
lat_2: function lat_2(v) {
self.lat2 = v * D2R$1;
},
lat_ts: function lat_ts(v) {
self.lat_ts = v * D2R$1;
},
lon_0: function lon_0(v) {
self.long0 = v * D2R$1;
},
lon_1: function lon_1(v) {
self.long1 = v * D2R$1;
},
lon_2: function lon_2(v) {
self.long2 = v * D2R$1;
},
alpha: function alpha(v) {
self.alpha = parseFloat(v) * D2R$1;
},
lonc: function lonc(v) {
self.longc = v * D2R$1;
},
x_0: function x_0(v) {
self.x0 = parseFloat(v);
},
y_0: function y_0(v) {
self.y0 = parseFloat(v);
},
k_0: function k_0(v) {
self.k0 = parseFloat(v);
},
k: function k(v) {
self.k0 = parseFloat(v);
},
a: function a(v) {
self.a = parseFloat(v);
},
b: function b(v) {
self.b = parseFloat(v);
},
r_a: function r_a() {
self.R_A = true;
},
zone: function zone(v) {
self.zone = parseInt(v, 10);
},
south: function south() {
self.utmSouth = true;
},
towgs84: function towgs84(v) {
self.datum_params = v.split(",").map(function (a) {
return parseFloat(a);
});
},
to_meter: function to_meter(v) {
self.to_meter = parseFloat(v);
},
units: function units(v) {
self.units = v;
var unit = match(_units, v);
if (unit) {
self.to_meter = unit.to_meter;
}
},
from_greenwich: function from_greenwich(v) {
self.from_greenwich = v * D2R$1;
},
pm: function pm(v) {
var pm = match(exports$3, v);
self.from_greenwich = (pm ? pm : parseFloat(v)) * D2R$1;
},
nadgrids: function nadgrids(v) {
if (v === '@null') {
self.datumCode = 'none';
} else {
self.nadgrids = v;
}
},
axis: function axis(v) {
var legalAxis = "ewnsud";
if (v.length === 3 && legalAxis.indexOf(v.substr(0, 1)) !== -1 && legalAxis.indexOf(v.substr(1, 1)) !== -1 && legalAxis.indexOf(v.substr(2, 1)) !== -1) {
self.axis = v;
}
}
};
for (paramName in paramObj) {
paramVal = paramObj[paramName];
if (paramName in params) {
paramOutname = params[paramName];
if (typeof paramOutname === 'function') {
paramOutname(paramVal);
} else {
self[paramOutname] = paramVal;
}
} else {
self[paramName] = paramVal;
}
}
if (typeof self.datumCode === 'string' && self.datumCode !== "WGS84") {
self.datumCode = self.datumCode.toLowerCase();
}
return self;
}
var NEUTRAL = 1;
var KEYWORD = 2;
var NUMBER = 3;
var QUOTED = 4;
var AFTERQUOTE = 5;
var ENDED = -1;
var whitespace = /\s/;
var latin = /[A-Za-z]/;
var keyword = /[A-Za-z84]/;
var endThings = /[,\]]/;
var digets = /[\d\.E\-\+]/;
// const ignoredChar = /[\s_\-\/\(\)]/g;
function Parser(text) {
if (typeof text !== 'string') {
throw new Error('not a string');
}
this.text = text.trim();
this.level = 0;
this.place = 0;
this.root = null;
this.stack = [];
this.currentObject = null;
this.state = NEUTRAL;
}
Parser.prototype.readCharicter = function () {
var _char = this.text[this.place++];
if (this.state !== QUOTED) {
while (whitespace.test(_char)) {
if (this.place >= this.text.length) {
return;
}
_char = this.text[this.place++];
}
}
switch (this.state) {
case NEUTRAL:
return this.neutral(_char);
case KEYWORD:
return this.keyword(_char);
case QUOTED:
return this.quoted(_char);
case AFTERQUOTE:
return this.afterquote(_char);
case NUMBER:
return this.number(_char);
case ENDED:
return;
}
};
Parser.prototype.afterquote = function (_char2) {
if (_char2 === '"') {
this.word += '"';
this.state = QUOTED;
return;
}
if (endThings.test(_char2)) {
this.word = this.word.trim();
this.afterItem(_char2);
return;
}
throw new Error('havn\'t handled "' + _char2 + '" in afterquote yet, index ' + this.place);
};
Parser.prototype.afterItem = function (_char3) {
if (_char3 === ',') {
if (this.word !== null) {
this.currentObject.push(this.word);
}
this.word = null;
this.state = NEUTRAL;
return;
}
if (_char3 === ']') {
this.level--;
if (this.word !== null) {
this.currentObject.push(this.word);
this.word = null;
}
this.state = NEUTRAL;
this.currentObject = this.stack.pop();
if (!this.currentObject) {
this.state = ENDED;
}
return;
}
};
Parser.prototype.number = function (_char4) {
if (digets.test(_char4)) {
this.word += _char4;
return;
}
if (endThings.test(_char4)) {
this.word = parseFloat(this.word);
this.afterItem(_char4);
return;
}
throw new Error('havn\'t handled "' + _char4 + '" in number yet, index ' + this.place);
};
Parser.prototype.quoted = function (_char5) {
if (_char5 === '"') {
this.state = AFTERQUOTE;
return;
}
this.word += _char5;
return;
};
Parser.prototype.keyword = function (_char6) {
if (keyword.test(_char6)) {
this.word += _char6;
return;
}
if (_char6 === '[') {
var newObjects = [];
newObjects.push(this.word);
this.level++;
if (this.root === null) {
this.root = newObjects;
} else {
this.currentObject.push(newObjects);
}
this.stack.push(this.currentObject);
this.currentObject = newObjects;
this.state = NEUTRAL;
return;
}
if (endThings.test(_char6)) {
this.afterItem(_char6);
return;
}
throw new Error('havn\'t handled "' + _char6 + '" in keyword yet, index ' + this.place);
};
Parser.prototype.neutral = function (_char7) {
if (latin.test(_char7)) {
this.word = _char7;
this.state = KEYWORD;
return;
}
if (_char7 === '"') {
this.word = '';
this.state = QUOTED;
return;
}
if (digets.test(_char7)) {
this.word = _char7;
this.state = NUMBER;
return;
}
if (endThings.test(_char7)) {
this.afterItem(_char7);
return;
}
throw new Error('havn\'t handled "' + _char7 + '" in neutral yet, index ' + this.place);
};
Parser.prototype.output = function () {
while (this.place < this.text.length) {
this.readCharicter();
}
if (this.state === ENDED) {
return this.root;
}
throw new Error('unable to parse string "' + this.text + '". State is ' + this.state);
};
function parseString(txt) {
var parser = new Parser(txt);
return parser.output();
}
function mapit(obj, key, value) {
if (Array.isArray(key)) {
value.unshift(key);
key = null;
}
var thing = key ? {} : obj;
var out = value.reduce(function (newObj, item) {
sExpr(item, newObj);
return newObj;
}, thing);
if (key) {
obj[key] = out;
}
}
function sExpr(v, obj) {
if (!Array.isArray(v)) {
obj[v] = true;
return;
}
var key = v.shift();
if (key === 'PARAMETER') {
key = v.shift();
}
if (v.length === 1) {
if (Array.isArray(v[0])) {
obj[key] = {};
sExpr(v[0], obj[key]);
return;
}
obj[key] = v[0];
return;
}
if (!v.length) {
obj[key] = true;
return;
}
if (key === 'TOWGS84') {
obj[key] = v;
return;
}
if (key === 'AXIS') {
if (!(key in obj)) {
obj[key] = [];
}
obj[key].push(v);
return;
}
if (!Array.isArray(key)) {
obj[key] = {};
}
var i;
switch (key) {
case 'UNIT':
case 'PRIMEM':
case 'VERT_DATUM':
obj[key] = {
name: v[0].toLowerCase(),
convert: v[1]
};
if (v.length === 3) {
sExpr(v[2], obj[key]);
}
return;
case 'SPHEROID':
case 'ELLIPSOID':
obj[key] = {
name: v[0],
a: v[1],
rf: v[2]
};
if (v.length === 4) {
sExpr(v[3], obj[key]);
}
return;
case 'PROJECTEDCRS':
case 'PROJCRS':
case 'GEOGCS':
case 'GEOCCS':
case 'PROJCS':
case 'LOCAL_CS':
case 'GEODCRS':
case 'GEODETICCRS':
case 'GEODETICDATUM':
case 'EDATUM':
case 'ENGINEERINGDATUM':
case 'VERT_CS':
case 'VERTCRS':
case 'VERTICALCRS':
case 'COMPD_CS':
case 'COMPOUNDCRS':
case 'ENGINEERINGCRS':
case 'ENGCRS':
case 'FITTED_CS':
case 'LOCAL_DATUM':
case 'DATUM':
v[0] = ['name', v[0]];
mapit(obj, key, v);
return;
default:
i = -1;
while (++i < v.length) {
if (!Array.isArray(v[i])) {
return sExpr(v, obj[key]);
}
}
return mapit(obj, key, v);
}
}
var D2R = 0.01745329251994329577;
function rename(obj, params) {
var outName = params[0];
var inName = params[1];
if (!(outName in obj) && inName in obj) {
obj[outName] = obj[inName];
if (params.length === 3) {
obj[outName] = params[2](obj[outName]);
}
}
}
function d2r(input) {
return input * D2R;
}
function cleanWKT(wkt) {
if (wkt.type === 'GEOGCS') {
wkt.projName = 'longlat';
} else if (wkt.type === 'LOCAL_CS') {
wkt.projName = 'identity';
wkt.local = true;
} else {
if (_typeof(wkt.PROJECTION) === 'object') {
wkt.projName = Object.keys(wkt.PROJECTION)[0];
} else {
wkt.projName = wkt.PROJECTION;
}
}
if (wkt.AXIS) {
var axisOrder = '';
for (var i = 0, ii = wkt.AXIS.length; i < ii; ++i) {
var axis = wkt.AXIS[i];
var descriptor = axis[0].toLowerCase();
if (descriptor.indexOf('north') !== -1) {
axisOrder += 'n';
} else if (descriptor.indexOf('south') !== -1) {
axisOrder += 's';
} else if (descriptor.indexOf('east') !== -1) {
axisOrder += 'e';
} else if (descriptor.indexOf('west') !== -1) {
axisOrder += 'w';
}
}
if (axisOrder.length === 2) {
axisOrder += 'u';
}
if (axisOrder.length === 3) {
wkt.axis = axisOrder;
}
}
if (wkt.UNIT) {
wkt.units = wkt.UNIT.name.toLowerCase();
if (wkt.units === 'metre') {
wkt.units = 'meter';
}
if (wkt.UNIT.convert) {
if (wkt.type === 'GEOGCS') {
if (wkt.DATUM && wkt.DATUM.SPHEROID) {
wkt.to_meter = wkt.UNIT.convert * wkt.DATUM.SPHEROID.a;
}
} else {
wkt.to_meter = wkt.UNIT.convert;
}
}
}
var geogcs = wkt.GEOGCS;
if (wkt.type === 'GEOGCS') {
geogcs = wkt;
}
if (geogcs) {
//if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){
// wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*D2R;
//}
if (geogcs.DATUM) {
wkt.datumCode = geogcs.DATUM.name.toLowerCase();
} else {
wkt.datumCode = geogcs.name.toLowerCase();
}
if (wkt.datumCode.slice(0, 2) === 'd_') {
wkt.datumCode = wkt.datumCode.slice(2);
}
if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') {
wkt.datumCode = 'nzgd49';
}
if (wkt.datumCode === 'wgs_1984' || wkt.datumCode === 'world_geodetic_system_1984') {
if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') {
wkt.sphere = true;
}
wkt.datumCode = 'wgs84';
}
if (wkt.datumCode.slice(-6) === '_ferro') {
wkt.datumCode = wkt.datumCode.slice(0, -6);
}
if (wkt.datumCode.slice(-8) === '_jakarta') {
wkt.datumCode = wkt.datumCode.slice(0, -8);
}
if (~wkt.datumCode.indexOf('belge')) {
wkt.datumCode = 'rnb72';
}
if (geogcs.DATUM && geogcs.DATUM.SPHEROID) {
wkt.ellps = geogcs.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\_18/, 'clrk');
if (wkt.ellps.toLowerCase().slice(0, 13) === 'international') {
wkt.ellps = 'intl';
}
wkt.a = geogcs.DATUM.SPHEROID.a;
wkt.rf = parseFloat(geogcs.DATUM.SPHEROID.rf, 10);
}
if (geogcs.DATUM && geogcs.DATUM.TOWGS84) {
wkt.datum_params = geogcs.DATUM.TOWGS84;
}
if (~wkt.datumCode.indexOf('osgb_1936')) {
wkt.datumCode = 'osgb36';
}
if (~wkt.datumCode.indexOf('osni_1952')) {
wkt.datumCode = 'osni52';
}
if (~wkt.datumCode.indexOf('tm65') || ~wkt.datumCode.indexOf('geodetic_datum_of_1965')) {
wkt.datumCode = 'ire65';
}
if (wkt.datumCode === 'ch1903+') {
wkt.datumCode = 'ch1903';
}
if (~wkt.datumCode.indexOf('israel')) {
wkt.datumCode = 'isr93';
}
}
if (wkt.b && !isFinite(wkt.b)) {
wkt.b = wkt.a;
}
function toMeter(input) {
var ratio = wkt.to_meter || 1;
return input * ratio;
}
var renamer = function renamer(a) {
return rename(wkt, a);
};
var list = [['standard_parallel_1', 'Standard_Parallel_1'], ['standard_parallel_2', 'Standard_Parallel_2'], ['false_easting', 'False_Easting'], ['false_northing', 'False_Northing'], ['central_meridian', 'Central_Meridian'], ['latitude_of_origin', 'Latitude_Of_Origin'], ['latitude_of_origin', 'Central_Parallel'], ['scale_factor', 'Scale_Factor'], ['k0', 'scale_factor'], ['latitude_of_center', 'Latitude_Of_Center'], ['latitude_of_center', 'Latitude_of_center'], ['lat0', 'latitude_of_center', d2r], ['longitude_of_center', 'Longitude_Of_Center'], ['longitude_of_center', 'Longitude_of_center'], ['longc', 'longitude_of_center', d2r], ['x0', 'false_easting', toMeter], ['y0', 'false_northing', toMeter], ['long0', 'central_meridian', d2r], ['lat0', 'latitude_of_origin', d2r], ['lat0', 'standard_parallel_1', d2r], ['lat1', 'standard_parallel_1', d2r], ['lat2', 'standard_parallel_2', d2r], ['azimuth', 'Azimuth'], ['alpha', 'azimuth', d2r], ['srsCode', 'name']];
list.forEach(renamer);
if (!wkt.long0 && wkt.longc && (wkt.projName === 'Albers_Conic_Equal_Area' || wkt.projName === 'Lambert_Azimuthal_Equal_Area')) {
wkt.long0 = wkt.longc;
}
if (!wkt.lat_ts && wkt.lat1 && (wkt.projName === 'Stereographic_South_Pole' || wkt.projName === 'Polar Stereographic (variant B)')) {
wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90);
wkt.lat_ts = wkt.lat1;
}
}
function wkt (wkt) {
var lisp = parseString(wkt);
var type = lisp.shift();
var name = lisp.shift();
lisp.unshift(['name', name]);
lisp.unshift(['type', type]);
var obj = {};
sExpr(lisp, obj);
cleanWKT(obj);
return obj;
}
function defs(name) {
/*global console*/
var that = this;
if (arguments.length === 2) {
var def = arguments[1];
if (typeof def === 'string') {
if (def.charAt(0) === '+') {
defs[name] = projStr(arguments[1]);
} else {
defs[name] = wkt(arguments[1]);
}
} else {
defs[name] = def;
}
} else if (arguments.length === 1) {
if (Array.isArray(name)) {
return name.map(function (v) {
if (Array.isArray(v)) {
defs.apply(that, v);
} else {
defs(v);
}
});
} else if (typeof name === 'string') {
if (name in defs) {
return defs[name];
}
} else if ('EPSG' in name) {
defs['EPSG:' + name.EPSG] = name;
} else if ('ESRI' in name) {
defs['ESRI:' + name.ESRI] = name;
} else if ('IAU2000' in name) {
defs['IAU2000:' + name.IAU2000] = name;
} else {
console.log(name);
}
return;
}
}
globals(defs);
function testObj(code) {
return typeof code === 'string';
}
function testDef(code) {
return code in defs;
}
var codeWords = ['PROJECTEDCRS', 'PROJCRS', 'GEOGCS', 'GEOCCS', 'PROJCS', 'LOCAL_CS', 'GEODCRS', 'GEODETICCRS', 'GEODETICDATUM', 'ENGCRS', 'ENGINEERINGCRS'];
function testWKT(code) {
return codeWords.some(function (word) {
return code.indexOf(word) > -1;
});
}
var codes = ['3857', '900913', '3785', '102113'];
function checkMercator(item) {
var auth = match(item, 'authority');
if (!auth) {
return;
}
var code = match(auth, 'epsg');
return code && codes.indexOf(code) > -1;
}
function checkProjStr(item) {
var ext = match(item, 'extension');
if (!ext) {
return;
}
return match(ext, 'proj4');
}
function testProj(code) {
return code[0] === '+';
}
function parse(code) {
if (testObj(code)) {
//check to see if this is a WKT string
if (testDef(code)) {
return defs[code];
}
if (testWKT(code)) {
var out = wkt(code);
// test of spetial case, due to this being a very common and often malformed
if (checkMercator(out)) {
return defs['EPSG:3857'];
}
var maybeProjStr = checkProjStr(out);
if (maybeProjStr) {
return projStr(maybeProjStr);
}
return out;
}
if (testProj(code)) {
return projStr(code);
}
} else {
return code;
}
}
function extend (destination, source) {
destination = destination || {};
var value, property;
if (!source) {
return destination;
}
for (property in source) {
value = source[property];
if (value !== undefined) {
destination[property] = value;
}
}
return destination;
}
function msfnz (eccent, sinphi, cosphi) {
var con = eccent * sinphi;
return cosphi / Math.sqrt(1 - con * con);
}
function sign (x) {
return x < 0 ? -1 : 1;
}
function adjust_lon (x) {
return Math.abs(x) <= SPI ? x : x - sign(x) * TWO_PI;
}
function tsfnz (eccent, phi, sinphi) {
var con = eccent * sinphi;
var com = 0.5 * eccent;
con = Math.pow((1 - con) / (1 + con), com);
return Math.tan(0.5 * (HALF_PI - phi)) / con;
}
function phi2z (eccent, ts) {
var eccnth = 0.5 * eccent;
var con, dphi;
var phi = HALF_PI - 2 * Math.atan(ts);
for (var i = 0; i <= 15; i++) {
con = eccent * Math.sin(phi);
dphi = HALF_PI - 2 * Math.atan(ts * Math.pow((1 - con) / (1 + con), eccnth)) - phi;
phi += dphi;
if (Math.abs(dphi) <= 0.0000000001) {
return phi;
}
}
//console.log("phi2z has NoConvergence");
return -9999;
}
function init$t() {
var con = this.b / this.a;
this.es = 1 - con * con;
if (!('x0' in this)) {
this.x0 = 0;
}
if (!('y0' in this)) {
this.y0 = 0;
}
this.e = Math.sqrt(this.es);
if (this.lat_ts) {
if (this.sphere) {
this.k0 = Math.cos(this.lat_ts);
} else {
this.k0 = msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts));
}
} else {
if (!this.k0) {
if (this.k) {
this.k0 = this.k;
} else {
this.k0 = 1;
}
}
}
}
/* Mercator forward equations--mapping lat,long to x,y
--------------------------------------------------*/
function forward$s(p) {
var lon = p.x;
var lat = p.y;
// convert to radians
if (lat * R2D > 90 && lat * R2D < -90 && lon * R2D > 180 && lon * R2D < -180) {
return null;
}
var x, y;
if (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN) {
return null;
} else {
if (this.sphere) {
x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0);
y = this.y0 + this.a * this.k0 * Math.log(Math.tan(FORTPI + 0.5 * lat));
} else {
var sinphi = Math.sin(lat);
var ts = tsfnz(this.e, lat, sinphi);
x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0);
y = this.y0 - this.a * this.k0 * Math.log(ts);
}
p.x = x;
p.y = y;
return p;
}
}
/* Mercator inverse equations--mapping x,y to lat/long
--------------------------------------------------*/
function inverse$s(p) {
var x = p.x - this.x0;
var y = p.y - this.y0;
var lon, lat;
if (this.sphere) {
lat = HALF_PI - 2 * Math.atan(Math.exp(-y / (this.a * this.k0)));
} else {
var ts = Math.exp(-y / (this.a * this.k0));
lat = phi2z(this.e, ts);
if (lat === -9999) {
return null;
}
}
lon = adjust_lon(this.long0 + x / (this.a * this.k0));
p.x = lon;
p.y = lat;
return p;
}
var names$u = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"];
var merc = {
init: init$t,
forward: forward$s,
inverse: inverse$s,
names: names$u
};
function init$s() {
//no-op for longlat
}
function identity(pt) {
return pt;
}
var names$t = ["longlat", "identity"];
var longlat = {
init: init$s,
forward: identity,
inverse: identity,
names: names$t
};
var projs = [merc, longlat];
var names$s = {};
var projStore = [];
function add(proj, i) {
var len = projStore.length;
if (!proj.names) {
console.log(i);
return true;
}
projStore[len] = proj;
proj.names.forEach(function (n) {
names$s[n.toLowerCase()] = len;
});
return this;
}
function get(name) {
if (!name) {
return false;
}
var n = name.toLowerCase();
if (typeof names$s[n] !== 'undefined' && projStore[names$s[n]]) {
return projStore[names$s[n]];
}
}
function start() {
projs.forEach(add);
}
var projections$1 = {
start: start,
add: add,
get: get
};
var exports$2 = {};
exports$2.MERIT = {
a: 6378137.0,
rf: 298.257,
ellipseName: "MERIT 1983"
};
exports$2.SGS85 = {
a: 6378136.0,
rf: 298.257,
ellipseName: "Soviet Geodetic System 85"
};
exports$2.GRS80 = {
a: 6378137.0,
rf: 298.257222101,
ellipseName: "GRS 1980(IUGG, 1980)"
};
exports$2.IAU76 = {
a: 6378140.0,
rf: 298.257,
ellipseName: "IAU 1976"
};
exports$2.airy = {
a: 6377563.396,
b: 6356256.910,
ellipseName: "Airy 1830"
};
exports$2.APL4 = {
a: 6378137,
rf: 298.25,
ellipseName: "Appl. Physics. 1965"
};
exports$2.NWL9D = {
a: 6378145.0,
rf: 298.25,
ellipseName: "Naval Weapons Lab., 1965"
};
exports$2.mod_airy = {
a: 6377340.189,
b: 6356034.446,
ellipseName: "Modified Airy"
};
exports$2.andrae = {
a: 6377104.43,
rf: 300.0,
ellipseName: "Andrae 1876 (Den., Iclnd.)"
};
exports$2.aust_SA = {
a: 6378160.0,
rf: 298.25,
ellipseName: "Australian Natl & S. Amer. 1969"
};
exports$2.GRS67 = {
a: 6378160.0,
rf: 298.2471674270,
ellipseName: "GRS 67(IUGG 1967)"
};
exports$2.bessel = {
a: 6377397.155,
rf: 299.1528128,
ellipseName: "Bessel 1841"
};
exports$2.bess_nam = {
a: 6377483.865,
rf: 299.1528128,
ellipseName: "Bessel 1841 (Namibia)"
};
exports$2.clrk66 = {
a: 6378206.4,
b: 6356583.8,
ellipseName: "Clarke 1866"
};
exports$2.clrk80 = {
a: 6378249.145,
rf: 293.4663,
ellipseName: "Clarke 1880 mod."
};
exports$2.clrk58 = {
a: 6378293.645208759,
rf: 294.2606763692654,
ellipseName: "Clarke 1858"
};
exports$2.CPM = {
a: 6375738.7,
rf: 334.29,
ellipseName: "Comm. des Poids et Mesures 1799"
};
exports$2.delmbr = {
a: 6376428.0,
rf: 311.5,
ellipseName: "Delambre 1810 (Belgium)"
};
exports$2.engelis = {
a: 6378136.05,
rf: 298.2566,
ellipseName: "Engelis 1985"
};
exports$2.evrst30 = {
a: 6377276.345,
rf: 300.8017,
ellipseName: "Everest 1830"
};
exports$2.evrst48 = {
a: 6377304.063,
rf: 300.8017,
ellipseName: "Everest 1948"
};
exports$2.evrst56 = {
a: 6377301.243,
rf: 300.8017,
ellipseName: "Everest 1956"
};
exports$2.evrst69 = {
a: 6377295.664,
rf: 300.8017,
ellipseName: "Everest 1969"
};
exports$2.evrstSS = {
a: 6377298.556,
rf: 300.8017,
ellipseName: "Everest (Sabah & Sarawak)"
};
exports$2.fschr60 = {
a: 6378166.0,
rf: 298.3,
ellipseName: "Fischer (Mercury Datum) 1960"
};
exports$2.fschr60m = {
a: 6378155.0,
rf: 298.3,
ellipseName: "Fischer 1960"
};
exports$2.fschr68 = {
a: 6378150.0,
rf: 298.3,
ellipseName: "Fischer 1968"
};
exports$2.helmert = {
a: 6378200.0,
rf: 298.3,
ellipseName: "Helmert 1906"
};
exports$2.hough = {
a: 6378270.0,
rf: 297.0,
ellipseName: "Hough"
};
exports$2.intl = {
a: 6378388.0,
rf: 297.0,
ellipseName: "International 1909 (Hayford)"
};
exports$2.kaula = {
a: 6378163.0,
rf: 298.24,
ellipseName: "Kaula 1961"
};
exports$2.lerch = {
a: 6378139.0,
rf: 298.257,
ellipseName: "Lerch 1979"
};
exports$2.mprts = {
a: 6397300.0,
rf: 191.0,
ellipseName: "Maupertius 1738"
};
exports$2.new_intl = {
a: 6378157.5,
b: 6356772.2,
ellipseName: "New International 1967"
};
exports$2.plessis = {
a: 6376523.0,
rf: 6355863.0,
ellipseName: "Plessis 1817 (France)"
};
exports$2.krass = {
a: 6378245.0,
rf: 298.3,
ellipseName: "Krassovsky, 1942"
};
exports$2.SEasia = {
a: 6378155.0,
b: 6356773.3205,
ellipseName: "Southeast Asia"
};
exports$2.walbeck = {
a: 6376896.0,
b: 6355834.8467,
ellipseName: "Walbeck"
};
exports$2.WGS60 = {
a: 6378165.0,
rf: 298.3,
ellipseName: "WGS 60"
};
exports$2.WGS66 = {
a: 6378145.0,
rf: 298.25,
ellipseName: "WGS 66"
};
exports$2.WGS7 = {
a: 6378135.0,
rf: 298.26,
ellipseName: "WGS 72"
};
var WGS84 = exports$2.WGS84 = {
a: 6378137.0,
rf: 298.257223563,
ellipseName: "WGS 84"
};
exports$2.sphere = {
a: 6370997.0,
b: 6370997.0,
ellipseName: "Normal Sphere (r=6370997)"
};
function eccentricity(a, b, rf, R_A) {
var a2 = a * a; // used in geocentric
var b2 = b * b; // used in geocentric
var es = (a2 - b2) / a2; // e ^ 2
var e = 0;
if (R_A) {
a *= 1 - es * (SIXTH + es * (RA4 + es * RA6));
a2 = a * a;
es = 0;
} else {
e = Math.sqrt(es); // eccentricity
}
var ep2 = (a2 - b2) / b2; // used in geocentric
return {
es: es,
e: e,
ep2: ep2
};
}
function sphere(a, b, rf, ellps, sphere) {
if (!a) {
// do we have an ellipsoid?
var ellipse = match(exports$2, ellps);
if (!ellipse) {
ellipse = WGS84;
}
a = ellipse.a;
b = ellipse.b;
rf = ellipse.rf;
}
if (rf && !b) {
b = (1.0 - 1.0 / rf) * a;
}
if (rf === 0 || Math.abs(a - b) < EPSLN) {
sphere = true;
b = a;
}
return {
a: a,
b: b,
rf: rf,
sphere: sphere
};
}
var exports$1 = {};
exports$1.wgs84 = {
towgs84: "0,0,0",
ellipse: "WGS84",
datumName: "WGS84"
};
exports$1.ch1903 = {
towgs84: "674.374,15.056,405.346",
ellipse: "bessel",
datumName: "swiss"
};
exports$1.ggrs87 = {
towgs84: "-199.87,74.79,246.62",
ellipse: "GRS80",
datumName: "Greek_Geodetic_Reference_System_1987"
};
exports$1.nad83 = {
towgs84: "0,0,0",
ellipse: "GRS80",
datumName: "North_American_Datum_1983"
};
exports$1.nad27 = {
nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",
ellipse: "clrk66",
datumName: "North_American_Datum_1927"
};
exports$1.potsdam = {
towgs84: "606.0,23.0,413.0",
ellipse: "bessel",
datumName: "Potsdam Rauenberg 1950 DHDN"
};
exports$1.carthage = {
towgs84: "-263.0,6.0,431.0",
ellipse: "clark80",
datumName: "Carthage 1934 Tunisia"
};
exports$1.hermannskogel = {
towgs84: "653.0,-212.0,449.0",
ellipse: "bessel",
datumName: "Hermannskogel"
};
exports$1.osni52 = {
towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",
ellipse: "airy",
datumName: "Irish National"
};
exports$1.ire65 = {
towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",
ellipse: "mod_airy",
datumName: "Ireland 1965"
};
exports$1.rassadiran = {
towgs84: "-133.63,-157.5,-158.62",
ellipse: "intl",
datumName: "Rassadiran"
};
exports$1.nzgd49 = {
towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",
ellipse: "intl",
datumName: "New Zealand Geodetic Datum 1949"
};
exports$1.osgb36 = {
towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",
ellipse: "airy",
datumName: "Airy 1830"
};
exports$1.s_jtsk = {
towgs84: "589,76,480",
ellipse: 'bessel',
datumName: 'S-JTSK (Ferro)'
};
exports$1.beduaram = {
towgs84: '-106,-87,188',
ellipse: 'clrk80',
datumName: 'Beduaram'
};
exports$1.gunung_segara = {
towgs84: '-403,684,41',
ellipse: 'bessel',
datumName: 'Gunung Segara Jakarta'
};
exports$1.rnb72 = {
towgs84: "106.869,-52.2978,103.724,-0.33657,0.456955,-1.84218,1",
ellipse: "intl",
datumName: "Reseau National Belge 1972"
};
function datum(datumCode, datum_params, a, b, es, ep2) {
var out = {};
if (datumCode === undefined || datumCode === 'none') {
out.datum_type = PJD_NODATUM;
} else {
out.datum_type = PJD_WGS84;
}
if (datum_params) {
out.datum_params = datum_params.map(parseFloat);
if (out.datum_params[0] !== 0 || out.datum_params[1] !== 0 || out.datum_params[2] !== 0) {
out.datum_type = PJD_3PARAM;
}
if (out.datum_params.length > 3) {
if (out.datum_params[3] !== 0 || out.datum_params[4] !== 0 || out.datum_params[5] !== 0 || out.datum_params[6] !== 0) {
out.datum_type = PJD_7PARAM;
out.datum_params[3] *= SEC_TO_RAD;
out.datum_params[4] *= SEC_TO_RAD;
out.datum_params[5] *= SEC_TO_RAD;
out.datum_params[6] = out.datum_params[6] / 1000000.0 + 1.0;
}
}
}
out.a = a; //datum object also uses these values
out.b = b;
out.es = es;
out.ep2 = ep2;
return out;
}
function Projection(srsCode, callback) {
if (!(this instanceof Projection)) {
return new Projection(srsCode);
}
callback = callback || function (error) {
if (error) {
throw error;
}
};
var json = parse(srsCode);
if (_typeof(json) !== 'object') {
callback(srsCode);
return;
}
var ourProj = Projection.projections.get(json.projName);
if (!ourProj) {
callback(srsCode);
return;
}
if (json.datumCode && json.datumCode !== 'none') {
var datumDef = match(exports$1, json.datumCode);
if (datumDef) {
json.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null;
json.ellps = datumDef.ellipse;
json.datumName = datumDef.datumName ? datumDef.datumName : json.datumCode;
}
}
json.k0 = json.k0 || 1.0;
json.axis = json.axis || 'enu';
json.ellps = json.ellps || 'wgs84';
var sphere_ = sphere(json.a, json.b, json.rf, json.ellps, json.sphere);
var ecc = eccentricity(sphere_.a, sphere_.b, sphere_.rf, json.R_A);
var datumObj = json.datum || datum(json.datumCode, json.datum_params, sphere_.a, sphere_.b, ecc.es, ecc.ep2);
extend(this, json); // transfer everything over from the projection because we don't know what we'll need
extend(this, ourProj); // transfer all the methods from the projection
// copy the 4 things over we calulated in deriveConstants.sphere
this.a = sphere_.a;
this.b = sphere_.b;
this.rf = sphere_.rf;
this.sphere = sphere_.sphere;
// copy the 3 things we calculated in deriveConstants.eccentricity
this.es = ecc.es;
this.e = ecc.e;
this.ep2 = ecc.ep2;
// add in the datum object
this.datum = datumObj;
// init the projection
this.init();
// legecy callback from back in the day when it went to spatialreference.org
callback(null, this);
}
Projection.projections = projections$1;
Projection.projections.start();
function compareDatums(source, dest) {
if (source.datum_type !== dest.datum_type) {
return false; // false, datums are not equal
} else if (source.a !== dest.a || Math.abs(source.es - dest.es) > 0.000000000050) {
// the tolerance for es is to ensure that GRS80 and WGS84
// are considered identical
return false;
} else if (source.datum_type === PJD_3PARAM) {
return source.datum_params[0] === dest.datum_params[0] && source.datum_params[1] === dest.datum_params[1] && source.datum_params[2] === dest.datum_params[2];
} else if (source.datum_type === PJD_7PARAM) {
return source.datum_params[0] === dest.datum_params[0] && source.datum_params[1] === dest.datum_params[1] && source.datum_params[2] === dest.datum_params[2] && source.datum_params[3] === dest.datum_params[3] && source.datum_params[4] === dest.datum_params[4] && source.datum_params[5] === dest.datum_params[5] && source.datum_params[6] === dest.datum_params[6];
} else {
return true; // datums are equal
}
} // cs_compare_datums()
/*
* The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
* (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
* according to the current ellipsoid parameters.
*
* Latitude : Geodetic latitude in radians (input)
* Longitude : Geodetic longitude in radians (input)
* Height : Geodetic height, in meters (input)
* X : Calculated Geocentric X coordinate, in meters (output)
* Y : Calculated Geocentric Y coordinate, in meters (output)
* Z : Calculated Geocentric Z coordinate, in meters (output)
*
*/
function geodeticToGeocentric(p, es, a) {
var Longitude = p.x;
var Latitude = p.y;
var Height = p.z ? p.z : 0; //Z value not always supplied
var Rn; /* Earth radius at location */
var Sin_Lat; /* Math.sin(Latitude) */
var Sin2_Lat; /* Square of Math.sin(Latitude) */
var Cos_Lat; /* Math.cos(Latitude) */
/*
** Don't blow up if Latitude is just a little out of the value
** range as it may just be a rounding issue. Also removed longitude
** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001.
*/
if (Latitude < -HALF_PI && Latitude > -1.001 * HALF_PI) {
Latitude = -HALF_PI;
} else if (Latitude > HALF_PI && Latitude < 1.001 * HALF_PI) {
Latitude = HALF_PI;
} else if (Latitude < -HALF_PI) {
/* Latitude out of range */
//..reportError('geocent:lat out of range:' + Latitude);
return {
x: -Infinity,
y: -Infinity,
z: p.z
};
} else if (Latitude > HALF_PI) {
/* Latitude out of range */
return {
x: Infinity,
y: Infinity,
z: p.z
};
}
if (Longitude > Math.PI) {
Longitude -= 2 * Math.PI;
}
Sin_Lat = Math.sin(Latitude);
Cos_Lat = Math.cos(Latitude);
Sin2_Lat = Sin_Lat * Sin_Lat;
Rn = a / Math.sqrt(1.0e0 - es * Sin2_Lat);
return {
x: (Rn + Height) * Cos_Lat * Math.cos(Longitude),
y: (Rn + Height) * Cos_Lat * Math.sin(Longitude),
z: (Rn * (1 - es) + Height) * Sin_Lat
};
} // cs_geodetic_to_geocentric()
function geocentricToGeodetic(p, es, a, b) {
/* local defintions and variables */
/* end-criterium of loop, accuracy of sin(Latitude) */
var genau = 1e-12;
var genau2 = genau * genau;
var maxiter = 30;
var P; /* distance between semi-minor axis and location */
var RR; /* distance between center and location */
var CT; /* sin of geocentric latitude */
var ST;