UNPKG

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
(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;