UNPKG

covutils

Version:

Utilities for creating, transforming, and handling Coverage Data objects.

1,713 lines (1,514 loc) 349 kB
(function (exports) { 'use strict'; function minMax(arr) { var len = arr.length; var min = Infinity; var max = -Infinity; while (len--) { var el = arr[len]; if (el == null) { // do nothing } else if (el < min) { min = el; } else if (el > max) { max = el; } } if (min === Infinity) { min = max; } else if (max === -Infinity) { max = min; } if (min === Infinity || min === -Infinity) { // all values were null min = null; max = null; } return [min, max]; } /** * Return the indices of the two neighbors in the sorted array closest to the given number. * * @example * var a = [2,5,8,12,13] * var i = CovUtils.indicesOfNearest(a, 6) * // i == [1,2] * var j = CovUtils.indicesOfNearest(a, 5) * // j == [1,1] * var k = CovUtils.indicesOfNearest(a, 50) * // k == [4,4] * * @param {Array<number>} a The array to search through. Must be sorted, ascending or descending. * @param {number} x The target number. * @return {[lo,hi]} The indices of the two closest values, may be equal. * If `x` exists in the array, both neighbors point to `x`. * If `x` is lower (greater if descending) than the first value, both neighbors point to 0. * If `x` is greater (lower if descending) than the last value, both neighbors point to the last index. */ function indicesOfNearest(a, x) { if (a.length === 0) { throw new Error('Array must have at least one element'); } var lo = -1; var hi = a.length; var ascending = a.length === 1 || a[0] < a[1]; // we have two separate code paths to help the runtime optimize the loop if (ascending) { while (hi - lo > 1) { var mid = Math.round((lo + hi) / 2); if (a[mid] <= x) { lo = mid; } else { hi = mid; } } } else { while (hi - lo > 1) { var _mid = Math.round((lo + hi) / 2); if (a[_mid] >= x) { // here's the difference lo = _mid; } else { hi = _mid; } } } if (a[lo] === x) hi = lo; if (lo === -1) lo = hi; if (hi === a.length) hi = lo; return [lo, hi]; } /** * Return the index of the value closest to the given number in a sorted array. * * @example * var a = [2,5,8,12,13] * var i = CovUtils.indexOfNearest(a, 6) * // i == 1 * var j = CovUtils.indexOfNearest(a, 7) * // j == 2 * var k = CovUtils.indexOfNearest(a, 50) * // k == 4 * * @param {Array<number>} a The array to search through. Must be sorted, ascending or descending. * @param {number} x The target number. * @return {number} The array index whose value is closest to `x`. * If `x` happens to be exactly between two values, then the lower index is returned. */ function indexOfNearest(a, x) { var i = indicesOfNearest(a, x); var lo = i[0]; var hi = i[1]; if (Math.abs(x - a[lo]) <= Math.abs(x - a[hi])) { return lo; } else { return hi; } } var DOMAIN = 'Domain'; var COVERAGE = 'Coverage'; var COVERAGECOLLECTION = COVERAGE + 'Collection'; var COVJSON_NS = 'http://covjson.org/def/core#'; var COVJSON_DATATYPE_TUPLE = COVJSON_NS + 'tuple'; var COVJSON_DATATYPE_POLYGON = COVJSON_NS + 'polygon'; var DEFAULT_LANGUAGE = 'en'; /** * @example * var labels = {'en': 'Temperature', 'de': 'Temperatur'} * var tag = CovUtils.getLanguageTag(labels, 'en-GB') * // tag == 'en' * * @param {object} map An object that maps language tags to strings. * @param {string} [preferredLanguage='en'] The preferred language as a language tag, e.g. 'de'. * @return {string} The best matched language tag of the input map. * If no match was found then this is an arbitrary tag of the map. */ function getLanguageTag(map) { var preferredLanguage = arguments.length <= 1 || arguments[1] === undefined ? DEFAULT_LANGUAGE : arguments[1]; if (preferredLanguage in map) { return preferredLanguage; } // cut off any subtags following the language subtag and try to find a match var prefTag = preferredLanguage.split('-')[0]; var matches = Object.keys(map).filter(function (tag) { return prefTag === tag.split('-')[0]; }); if (matches.length) { return matches[0]; } // no luck, return a random tag return Object.keys(map)[0]; } /** * @example * var labels = {'en': 'Temperature', 'de': 'Temperatur'} * var label = CovUtils.getLanguageString(labels, 'en-GB') * // label == 'Temperature' * * @param {object} map An object that maps language tags to strings. * @param {string} [preferredLanguage='en'] The preferred language as a language tag, e.g. 'de'. * @return {string} The string within the input map whose language tag best matched. * If no match was found then this is an arbitrary string of the map. */ function getLanguageString(map) { var preferredLanguage = arguments.length <= 1 || arguments[1] === undefined ? DEFAULT_LANGUAGE : arguments[1]; var tag = getLanguageTag(map, preferredLanguage); return map[tag]; } /** * Converts a unit object to a human-readable symbol or label, where symbols are preferred. * * @example * var unit = { * symbol: '°C' * } * var str = CovUtils.stringifyUnit(unit) // str == '°C' * * @example * var unit = { * symbol: { * value: 'Cel', * type: 'http://www.opengis.net/def/uom/UCUM/' * }, * label: { * en: 'Degree Celsius' * } * } * var str = CovUtils.stringifyUnit(unit) // str == '°C' * * @example * var unit = { * label: { * en: 'Degree Celsius', * de: 'Grad Celsius' * } * } * var str = CovUtils.stringifyUnit(unit, 'en') // str == 'Degree Celsius' */ function stringifyUnit(unit, language) { if (!unit) { return ''; } if (unit.symbol) { var symbol = unit.symbol.value || unit.symbol; var scheme = unit.symbol.type; if (scheme === 'http://www.opengis.net/def/uom/UCUM/') { if (symbol === 'Cel') { symbol = '°C'; } else if (symbol === '1') { symbol = ''; } } return symbol; } else { return getLanguageString(unit.label, language); } } var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; /** * @external {Range} https://github.com/Reading-eScience-Centre/coverage-jsapi/blob/master/Range.md */ /** * Return the minimum/maximum across all range values, ignoring null's. * * @param {Range<number>} range The numeric coverage data range. * @return {[min,max]} The minimum and maximum values of the range, * or [undefined, undefined] if the range contains only `null` values. */ function minMaxOfRange(range) { var min = Infinity; var max = -Infinity; var fn = function fn(val) { if (val === null) return; if (val < min) min = val; if (val > max) max = val; }; iterateRange(range, fn); return min === Infinity ? [undefined, undefined] : [min, max]; } /** * Apply a reduce function over the range values. * * @param {Range} range The coverage data range. * @param {function} callback Function to execute on each value in the array with arguments `(previousValue, currentValue)`. * @param start Value to use as the first argument to the first call of the `callback`. * @return The reduced value. */ function reduceRange(range, callback, start) { var v1 = start; var iterFn = function iterFn(v2) { v1 = callback(v1, v2); }; iterateRange(range, iterFn); return v1; } /** * Iterate over all range values and run a function for each value. * No particular iteration order must be assumed. */ function iterateRange(range, fn) { // We use a precompiled function here for efficiency. // See below for a slower recursive version. // Benchmarks compared to recursive version: // Chrome 46: around 1.03x faster // Firefox 42: around 2x faster (and around 6x faster than Chrome 46!) // nest loops from smallest to biggest var shape = [].concat(toConsumableArray(range.shape)); shape.sort(function (_ref, _ref2) { var _ref4 = slicedToArray(_ref, 2); var size1 = _ref4[1]; var _ref3 = slicedToArray(_ref2, 2); var size2 = _ref3[1]; return size1 - size2; }); var begin = 'var obj = {}'; var end = ''; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = shape[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = slicedToArray(_step.value, 2); var axis = _step$value[0]; var size = _step$value[1]; begin += '\n for (var i' + axis + '=0; i' + axis + ' < ' + size + '; ++i' + axis + ') {\n obj[\'' + axis + '\'] = i' + axis + '\n '; end += '}'; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } begin += '\n fn(get(obj))\n '; var iterateLoop = new Function('return function iterRange (get, fn) { ' + begin + ' ' + end + ' }')(); // eslint-disable-line iterateLoop(range.get, fn); } /** * Returns the category of the given parameter corresponding to the encoded integer value. * * @param {Parameter} parameter * @param {number} val * @return {Category} */ function getCategory(parameter, val) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { var _loop = function _loop() { var _step$value = slicedToArray(_step.value, 2); var catId = _step$value[0]; var vals = _step$value[1]; if (vals.indexOf(val) !== -1) { var cat = parameter.observedProperty.categories.filter(function (c) { return c.id === catId; })[0]; return { v: cat }; } }; for (var _iterator = parameter.categoryEncoding[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _ret = _loop(); if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } } function isCoverage(obj) { return obj.type === COVERAGE; } function checkCoverage(obj) { if (!isCoverage(obj)) { throw new Error('must be a Coverage'); } } function isDomain(obj) { return obj.type === DOMAIN; } function checkDomain(obj) { if (!isDomain(obj)) { throw new Error('must be a Domain'); } } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var imlfn = createCommonjsModule(function (module) { module.exports = function(ml, e0, e1, e2, e3) { var phi; var dphi; phi = ml / e0; for (var i = 0; i < 15; i++) { dphi = (ml - (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi))) / (e0 - 2 * e1 * Math.cos(2 * phi) + 4 * e2 * Math.cos(4 * phi) - 6 * e3 * Math.cos(6 * phi)); phi += dphi; if (Math.abs(dphi) <= 0.0000000001) { return phi; } } //..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations"); return NaN; }; }); var require$$0$3 = (imlfn && typeof imlfn === 'object' && 'default' in imlfn ? imlfn['default'] : imlfn); var asinz = createCommonjsModule(function (module) { module.exports = function(x) { if (Math.abs(x) > 1) { x = (x > 1) ? 1 : -1; } return Math.asin(x); }; }); var require$$0$4 = (asinz && typeof asinz === 'object' && 'default' in asinz ? asinz['default'] : asinz); var gN = createCommonjsModule(function (module) { module.exports = function(a, e, sinphi) { var temp = e * sinphi; return a / Math.sqrt(1 - temp * temp); }; }); var require$$3 = (gN && typeof gN === 'object' && 'default' in gN ? gN['default'] : gN); var e3fn = createCommonjsModule(function (module) { module.exports = function(x) { return (x * x * x * (35 / 3072)); }; }); var require$$4 = (e3fn && typeof e3fn === 'object' && 'default' in e3fn ? e3fn['default'] : e3fn); var e2fn = createCommonjsModule(function (module) { module.exports = function(x) { return (0.05859375 * x * x * (1 + 0.75 * x)); }; }); var require$$5 = (e2fn && typeof e2fn === 'object' && 'default' in e2fn ? e2fn['default'] : e2fn); var e1fn = createCommonjsModule(function (module) { module.exports = function(x) { return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x))); }; }); var require$$6 = (e1fn && typeof e1fn === 'object' && 'default' in e1fn ? e1fn['default'] : e1fn); var e0fn = createCommonjsModule(function (module) { module.exports = function(x) { return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x))); }; }); var require$$7 = (e0fn && typeof e0fn === 'object' && 'default' in e0fn ? e0fn['default'] : e0fn); var mlfn = createCommonjsModule(function (module) { module.exports = function(e0, e1, e2, e3, phi) { return (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi)); }; }); var require$$3$1 = (mlfn && typeof mlfn === 'object' && 'default' in mlfn ? mlfn['default'] : mlfn); var sign = createCommonjsModule(function (module) { module.exports = function(x) { return x<0 ? -1 : 1; }; }); var require$$1 = (sign && typeof sign === 'object' && 'default' in sign ? sign['default'] : sign); var adjust_lon = createCommonjsModule(function (module) { 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 sign = require$$1; module.exports = function(x) { return (Math.abs(x) <= SPI) ? x : (x - (sign(x) * TWO_PI)); }; }); var require$$2 = (adjust_lon && typeof adjust_lon === 'object' && 'default' in adjust_lon ? adjust_lon['default'] : adjust_lon); var aeqd = createCommonjsModule(function (module, exports) { var adjust_lon = require$$2; var HALF_PI = Math.PI/2; var EPSLN = 1.0e-10; var mlfn = require$$3$1; var e0fn = require$$7; var e1fn = require$$6; var e2fn = require$$5; var e3fn = require$$4; var gN = require$$3; var asinz = require$$0$4; var imlfn = require$$0$3; exports.init = function() { this.sin_p12 = Math.sin(this.lat0); this.cos_p12 = Math.cos(this.lat0); }; exports.forward = function(p) { var lon = p.x; var lat = p.y; var sinphi = Math.sin(p.y); var cosphi = Math.cos(p.y); var dlon = adjust_lon(lon - this.long0); var e0, e1, e2, e3, Mlp, Ml, tanphi, Nl1, Nl, psi, Az, G, H, GH, Hs, c, kp, cos_c, s, s2, s3, s4, s5; if (this.sphere) { if (Math.abs(this.sin_p12 - 1) <= EPSLN) { //North Pole case p.x = this.x0 + this.a * (HALF_PI - lat) * Math.sin(dlon); p.y = this.y0 - this.a * (HALF_PI - lat) * Math.cos(dlon); return p; } else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { //South Pole case p.x = this.x0 + this.a * (HALF_PI + lat) * Math.sin(dlon); p.y = this.y0 + this.a * (HALF_PI + lat) * Math.cos(dlon); return p; } else { //default case cos_c = this.sin_p12 * sinphi + this.cos_p12 * cosphi * Math.cos(dlon); c = Math.acos(cos_c); kp = c / Math.sin(c); p.x = this.x0 + this.a * kp * cosphi * Math.sin(dlon); p.y = this.y0 + this.a * kp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * Math.cos(dlon)); return p; } } else { e0 = e0fn(this.es); e1 = e1fn(this.es); e2 = e2fn(this.es); e3 = e3fn(this.es); if (Math.abs(this.sin_p12 - 1) <= EPSLN) { //North Pole case Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); Ml = this.a * mlfn(e0, e1, e2, e3, lat); p.x = this.x0 + (Mlp - Ml) * Math.sin(dlon); p.y = this.y0 - (Mlp - Ml) * Math.cos(dlon); return p; } else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { //South Pole case Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); Ml = this.a * mlfn(e0, e1, e2, e3, lat); p.x = this.x0 + (Mlp + Ml) * Math.sin(dlon); p.y = this.y0 + (Mlp + Ml) * Math.cos(dlon); return p; } else { //Default case tanphi = sinphi / cosphi; Nl1 = gN(this.a, this.e, this.sin_p12); Nl = gN(this.a, this.e, sinphi); psi = Math.atan((1 - this.es) * tanphi + this.es * Nl1 * this.sin_p12 / (Nl * cosphi)); Az = Math.atan2(Math.sin(dlon), this.cos_p12 * Math.tan(psi) - this.sin_p12 * Math.cos(dlon)); if (Az === 0) { s = Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); } else if (Math.abs(Math.abs(Az) - Math.PI) <= EPSLN) { s = -Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); } else { s = Math.asin(Math.sin(dlon) * Math.cos(psi) / Math.sin(Az)); } G = this.e * this.sin_p12 / Math.sqrt(1 - this.es); H = this.e * this.cos_p12 * Math.cos(Az) / Math.sqrt(1 - this.es); GH = G * H; Hs = H * H; s2 = s * s; s3 = s2 * s; s4 = s3 * s; s5 = s4 * s; c = Nl1 * s * (1 - s2 * Hs * (1 - Hs) / 6 + s3 / 8 * GH * (1 - 2 * Hs) + s4 / 120 * (Hs * (4 - 7 * Hs) - 3 * G * G * (1 - 7 * Hs)) - s5 / 48 * GH); p.x = this.x0 + c * Math.sin(Az); p.y = this.y0 + c * Math.cos(Az); return p; } } }; exports.inverse = function(p) { p.x -= this.x0; p.y -= this.y0; var rh, z, sinz, cosz, lon, lat, con, e0, e1, e2, e3, Mlp, M, N1, psi, Az, cosAz, tmp, A, B, D, Ee, F; if (this.sphere) { rh = Math.sqrt(p.x * p.x + p.y * p.y); if (rh > (2 * HALF_PI * this.a)) { return; } z = rh / this.a; sinz = Math.sin(z); cosz = Math.cos(z); lon = this.long0; if (Math.abs(rh) <= EPSLN) { lat = this.lat0; } else { lat = asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); con = Math.abs(this.lat0) - HALF_PI; if (Math.abs(con) <= EPSLN) { if (this.lat0 >= 0) { lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y)); } else { lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y)); } } else { /*con = cosz - this.sin_p12 * Math.sin(lat); if ((Math.abs(con) < EPSLN) && (Math.abs(p.x) < EPSLN)) { //no-op, just keep the lon value as is } else { var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); }*/ lon = adjust_lon(this.long0 + Math.atan2(p.x * sinz, rh * this.cos_p12 * cosz - p.y * this.sin_p12 * sinz)); } } p.x = lon; p.y = lat; return p; } else { e0 = e0fn(this.es); e1 = e1fn(this.es); e2 = e2fn(this.es); e3 = e3fn(this.es); if (Math.abs(this.sin_p12 - 1) <= EPSLN) { //North pole case Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); rh = Math.sqrt(p.x * p.x + p.y * p.y); M = Mlp - rh; lat = imlfn(M / this.a, e0, e1, e2, e3); lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y)); p.x = lon; p.y = lat; return p; } else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { //South pole case Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); rh = Math.sqrt(p.x * p.x + p.y * p.y); M = rh - Mlp; lat = imlfn(M / this.a, e0, e1, e2, e3); lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y)); p.x = lon; p.y = lat; return p; } else { //default case rh = Math.sqrt(p.x * p.x + p.y * p.y); Az = Math.atan2(p.x, p.y); N1 = gN(this.a, this.e, this.sin_p12); cosAz = Math.cos(Az); tmp = this.e * this.cos_p12 * cosAz; A = -tmp * tmp / (1 - this.es); B = 3 * this.es * (1 - A) * this.sin_p12 * this.cos_p12 * cosAz / (1 - this.es); D = rh / N1; Ee = D - A * (1 + A) * Math.pow(D, 3) / 6 - B * (1 + 3 * A) * Math.pow(D, 4) / 24; F = 1 - A * Ee * Ee / 2 - D * Ee * Ee * Ee / 6; psi = Math.asin(this.sin_p12 * Math.cos(Ee) + this.cos_p12 * Math.sin(Ee) * cosAz); lon = adjust_lon(this.long0 + Math.asin(Math.sin(Az) * Math.sin(Ee) / Math.cos(psi))); lat = Math.atan((1 - this.es * F * this.sin_p12 / Math.sin(psi)) * Math.tan(psi) / (1 - this.es)); p.x = lon; p.y = lat; return p; } } }; exports.names = ["Azimuthal_Equidistant", "aeqd"]; }); var require$$0$2 = (aeqd && typeof aeqd === 'object' && 'default' in aeqd ? aeqd['default'] : aeqd); var vandg = createCommonjsModule(function (module, exports) { var adjust_lon = require$$2; var HALF_PI = Math.PI/2; var EPSLN = 1.0e-10; var asinz = require$$0$4; /* Initialize the Van Der Grinten projection ----------------------------------------*/ exports.init = function() { //this.R = 6370997; //Radius of earth this.R = this.a; }; exports.forward = function(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 ---------------------------------------------------------*/ exports.inverse = function(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; }; exports.names = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"]; }); var require$$1$1 = (vandg && typeof vandg === 'object' && 'default' in vandg ? vandg['default'] : vandg); var adjust_lat = createCommonjsModule(function (module) { var HALF_PI = Math.PI/2; var sign = require$$1; module.exports = function(x) { return (Math.abs(x) < HALF_PI) ? x : (x - (sign(x) * Math.PI)); }; }); var require$$1$2 = (adjust_lat && typeof adjust_lat === 'object' && 'default' in adjust_lat ? adjust_lat['default'] : adjust_lat); var msfnz = createCommonjsModule(function (module) { module.exports = function(eccent, sinphi, cosphi) { var con = eccent * sinphi; return cosphi / (Math.sqrt(1 - con * con)); }; }); var require$$3$2 = (msfnz && typeof msfnz === 'object' && 'default' in msfnz ? msfnz['default'] : msfnz); var eqdc = createCommonjsModule(function (module, exports) { var e0fn = require$$7; var e1fn = require$$6; var e2fn = require$$5; var e3fn = require$$4; var msfnz = require$$3$2; var mlfn = require$$3$1; var adjust_lon = require$$2; var adjust_lat = require$$1$2; var imlfn = require$$0$3; var EPSLN = 1.0e-10; exports.init = function() { /* Place parameters in static storage for common use -------------------------------------------------*/ // Standard Parallels cannot be equal and on opposite sides of the equator if (Math.abs(this.lat1 + this.lat2) < EPSLN) { return; } 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 (Math.abs(this.lat1 - this.lat2) < EPSLN) { this.ns = this.sinphi; } else { this.sinphi = Math.sin(this.lat2); this.cosphi = Math.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); }; /* Equidistant Conic forward equations--mapping lat,long to x,y -----------------------------------------------------------*/ exports.forward = function(p) { var lon = p.x; var lat = p.y; var rh1; /* Forward equations -----------------*/ if (this.sphere) { rh1 = this.a * (this.g - lat); } else { var ml = mlfn(this.e0, this.e1, this.e2, this.e3, lat); rh1 = this.a * (this.g - ml); } var theta = this.ns * adjust_lon(lon - this.long0); var x = this.x0 + rh1 * Math.sin(theta); var y = this.y0 + this.rh - rh1 * Math.cos(theta); p.x = x; p.y = y; return p; }; /* Inverse equations -----------------*/ exports.inverse = function(p) { p.x -= this.x0; p.y = this.rh - p.y + this.y0; var con, rh1, lat, lon; if (this.ns >= 0) { rh1 = Math.sqrt(p.x * p.x + p.y * p.y); con = 1; } else { rh1 = -Math.sqrt(p.x * p.x + p.y * p.y); con = -1; } var theta = 0; if (rh1 !== 0) { theta = Math.atan2(con * p.x, con * p.y); } if (this.sphere) { lon = adjust_lon(this.long0 + theta / this.ns); lat = adjust_lat(this.g - rh1 / this.a); p.x = lon; p.y = lat; return p; } else { var ml = this.g - rh1 / this.a; lat = imlfn(ml, this.e0, this.e1, this.e2, this.e3); lon = adjust_lon(this.long0 + theta / this.ns); p.x = lon; p.y = lat; return p; } }; exports.names = ["Equidistant_Conic", "eqdc"]; }); var require$$2$1 = (eqdc && typeof eqdc === 'object' && 'default' in eqdc ? eqdc['default'] : eqdc); var moll = createCommonjsModule(function (module, exports) { var adjust_lon = require$$2; var EPSLN = 1.0e-10; exports.init = function() {}; /* Mollweide forward equations--mapping lat,long to x,y ----------------------------------------------------*/ exports.forward = function(p) { /* Forward equations -----------------*/ var lon = p.x; var lat = p.y; var delta_lon = adjust_lon(lon - this.long0); var theta = lat; var con = Math.PI * Math.sin(lat); /* Iterate using the Newton-Raphson method to find theta -----------------------------------------------------*/ for (var i = 0; true; i++) { var delta_theta = -(theta + Math.sin(theta) - con) / (1 + Math.cos(theta)); theta += delta_theta; if (Math.abs(delta_theta) < EPSLN) { break; } } theta /= 2; /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" this is done here because of precision problems with "cos(theta)" --------------------------------------------------------------------------*/ if (Math.PI / 2 - Math.abs(lat) < EPSLN) { delta_lon = 0; } var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; p.x = x; p.y = y; return p; }; exports.inverse = function(p) { var theta; var arg; /* Inverse equations -----------------*/ p.x -= this.x0; p.y -= this.y0; arg = p.y / (1.4142135623731 * this.a); /* Because of division by zero problems, 'arg' can not be 1. Therefore a number very close to one is used instead. -------------------------------------------------------------------*/ if (Math.abs(arg) > 0.999999999999) { arg = 0.999999999999; } theta = Math.asin(arg); var lon = adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); if (lon < (-Math.PI)) { lon = -Math.PI; } if (lon > Math.PI) { lon = Math.PI; } arg = (2 * theta + Math.sin(2 * theta)) / Math.PI; if (Math.abs(arg) > 1) { arg = 1; } var lat = Math.asin(arg); p.x = lon; p.y = lat; return p; }; exports.names = ["Mollweide", "moll"]; }); var require$$3$3 = (moll && typeof moll === 'object' && 'default' in moll ? moll['default'] : moll); var pj_mlfn = createCommonjsModule(function (module) { module.exports = function(phi, sphi, cphi, en) { cphi *= sphi; sphi *= sphi; return (en[0] * phi - cphi * (en[1] + sphi * (en[2] + sphi * (en[3] + sphi * en[4])))); }; }); var require$$0$5 = (pj_mlfn && typeof pj_mlfn === 'object' && 'default' in pj_mlfn ? pj_mlfn['default'] : pj_mlfn); var pj_inv_mlfn = createCommonjsModule(function (module) { var pj_mlfn = require$$0$5; var EPSLN = 1.0e-10; var MAX_ITER = 20; module.exports = function(arg, es, en) { var k = 1 / (1 - es); var phi = arg; for (var i = MAX_ITER; i; --i) { /* rarely goes over 2 iterations */ var s = Math.sin(phi); var t = 1 - es * s * s; //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; //phi -= t * (t * Math.sqrt(t)) * k; t = (pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; phi -= t; if (Math.abs(t) < EPSLN) { return phi; } } //..reportError("cass:pj_inv_mlfn: Convergence error"); return phi; }; }); var require$$1$3 = (pj_inv_mlfn && typeof pj_inv_mlfn === 'object' && 'default' in pj_inv_mlfn ? pj_inv_mlfn['default'] : pj_inv_mlfn); var pj_enfn = createCommonjsModule(function (module) { var C00 = 1; var C02 = 0.25; var C04 = 0.046875; var C06 = 0.01953125; var C08 = 0.01068115234375; var C22 = 0.75; var C44 = 0.46875; var C46 = 0.01302083333333333333; var C48 = 0.00712076822916666666; var C66 = 0.36458333333333333333; var C68 = 0.00569661458333333333; var C88 = 0.3076171875; module.exports = function(es) { var en = []; en[0] = C00 - es * (C02 + es * (C04 + es * (C06 + es * C08))); en[1] = es * (C22 - es * (C04 + es * (C06 + es * C08))); var t = es * es; en[2] = t * (C44 - es * (C46 + es * C48)); t *= es; en[3] = t * (C66 - es * C68); en[4] = t * es * C88; return en; }; }); var require$$3$4 = (pj_enfn && typeof pj_enfn === 'object' && 'default' in pj_enfn ? pj_enfn['default'] : pj_enfn); var sinu = createCommonjsModule(function (module, exports) { var adjust_lon = require$$2; var adjust_lat = require$$1$2; var pj_enfn = require$$3$4; var MAX_ITER = 20; var pj_mlfn = require$$0$5; var pj_inv_mlfn = require$$1$3; var HALF_PI = Math.PI/2; var EPSLN = 1.0e-10; var asinz = require$$0$4; exports.init = function() { /* Place parameters in static storage for common use -------------------------------------------------*/ if (!this.sphere) { this.en = pj_enfn(this.es); } else { this.n = 1; this.m = 0; this.es = 0; this.C_y = Math.sqrt((this.m + 1) / this.n); this.C_x = this.C_y / (this.m + 1); } }; /* Sinusoidal forward equations--mapping lat,long to x,y -----------------------------------------------------*/ exports.forward = function(p) { var x, y; var lon = p.x; var lat = p.y; /* Forward equations -----------------*/ lon = adjust_lon(lon - this.long0); if (this.sphere) { if (!this.m) { lat = this.n !== 1 ? Math.asin(this.n * Math.sin(lat)) : lat; } else { var k = this.n * Math.sin(lat); for (var i = MAX_ITER; i; --i) { var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat)); lat -= V; if (Math.abs(V) < EPSLN) { break; } } } x = this.a * this.C_x * lon * (this.m + Math.cos(lat)); y = this.a * this.C_y * lat; } else { var s = Math.sin(lat); var c = Math.cos(lat); y = this.a * pj_mlfn(lat, s, c, this.en); x = this.a * lon * c / Math.sqrt(1 - this.es * s * s); } p.x = x; p.y = y; return p; }; exports.inverse = function(p) { var lat, temp, lon, s; p.x -= this.x0; lon = p.x / this.a; p.y -= this.y0; lat = p.y / this.a; if (this.sphere) { lat /= this.C_y; lon = lon / (this.C_x * (this.m + Math.cos(lat))); if (this.m) { lat = asinz((this.m * lat + Math.sin(lat)) / this.n); } else if (this.n !== 1) { lat = asinz(Math.sin(lat) / this.n); } lon = adjust_lon(lon + this.long0); lat = adjust_lat(lat); } else { lat = pj_inv_mlfn(p.y / this.a, this.es, this.en); s = Math.abs(lat); if (s < HALF_PI) { s = Math.sin(lat); temp = this.long0 + p.x * Math.sqrt(1 - this.es * s * s) / (this.a * Math.cos(lat)); //temp = this.long0 + p.x / (this.a * Math.cos(lat)); lon = adjust_lon(temp); } else if ((s - EPSLN) < HALF_PI) { lon = this.long0; } } p.x = lon; p.y = lat; return p; }; exports.names = ["Sinusoidal", "sinu"]; }); var require$$4$1 = (sinu && typeof sinu === 'object' && 'default' in sinu ? sinu['default'] : sinu); var mill = createCommonjsModule(function (module, exports) { var adjust_lon = require$$2; /* reference "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. */ /* Initialize the Miller Cylindrical projection -------------------------------------------*/ exports.init = function() { //no-op }; /* Miller Cylindrical forward equations--mapping lat,long to x,y ------------------------------------------------------------*/ exports.forward = function(p) { var lon = p.x; var lat = p.y; /* Forward equations -----------------*/ var dlon = adjust_lon(lon - this.long0); var x = this.x0 + this.a * dlon; var y = this.y0 + this.a * Math.log(Math.tan((Math.PI / 4) + (lat / 2.5))) * 1.25; p.x = x; p.y = y; return p; }; /* Miller Cylindrical inverse equations--mapping x,y to lat/long ------------------------------------------------------------*/ exports.inverse = function(p) { p.x -= this.x0; p.y -= this.y0; var lon = adjust_lon(this.long0 + p.x / this.a); var lat = 2.5 * (Math.atan(Math.exp(0.8 * p.y / this.a)) - Math.PI / 4); p.x = lon; p.y = lat; return p; }; exports.names = ["Miller_Cylindrical", "mill"]; }); var require$$5$1 = (mill && typeof mill === 'object' && 'default' in mill ? mill['default'] : mill); var nzmg = createCommonjsModule(function (module, exports) { var SEC_TO_RAD = 4.84813681109535993589914102357e-6; /* reference Department of Land and Survey Technical Circular 1973/32 http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf OSG Technical Report 4.1 http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf */ /** * iterations: Number of iterations to refine inverse transform. * 0 -> km accuracy * 1 -> m accuracy -- suitable for most mapping applications * 2 -> mm accuracy */ exports.iterations = 1; exports.init = function() { this.A = []; this.A[1] = 0.6399175073; this.A[2] = -0.1358797613; this.A[3] = 0.063294409; this.A[4] = -0.02526853; this.A[5] = 0.0117879; this.A[6] = -0.0055161; this.A[7] = 0.0026906; this.A[8] = -0.001333; this.A[9] = 0.00067; this.A[10] = -0.00034; this.B_re = []; this.B_im = []; this.B_re[1] = 0.7557853228; this.B_im[1] = 0; this.B_re[2] = 0.249204646; this.B_im[2] = 0.003371507; this.B_re[3] = -0.001541739; this.B_im[3] = 0.041058560; this.B_re[4] = -0.10162907; this.B_im[4] = 0.01727609; this.B_re[5] = -0.26623489; this.B_im[5] = -0.36249218; this.B_re[6] = -0.6870983; this.B_im[6] = -1.1651967; this.C_re = []; this.C_im = []; this.C_re[1] = 1.3231270439; this.C_im[1] = 0; this.C_re[2] = -0.577245789; this.C_im[2] = -0.007809598; this.C_re[3] = 0.508307513; this.C_im[3] = -0.112208952; this.C_re[4] = -0.15094762; this.C_im[4] = 0.18200602; this.C_re[5] = 1.01418179; this.C_im[5] = 1.64497696; this.C_re[6] = 1.9660549; this.C_im[6] = 2.5127645; this.D = []; this.D[1] = 1.5627014243; this.D[2] = 0.5185406398; this.D[3] = -0.03333098; this.D[4] = -0.1052906; this.D[5] = -0.0368594; this.D[6] = 0.007317; this.D[7] = 0.01220; this.D[8] = 0.00394; this.D[9] = -0.0013; }; /** New Zealand Map Grid Forward - long/lat to x/y long/lat in radians */ exports.forward = function(p) { var n; var lon = p.x; var lat = p.y; var delta_lat = lat - this.lat0; var delta_lon = lon - this.long0; // 1. Calculate d_phi and d_psi ... // and d_lambda // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. var d_phi = delta_lat / SEC_TO_RAD * 1E-5; var d_lambda = delta_lon; var d_phi_n = 1; // d_phi^0 var d_psi = 0; for (n = 1; n <= 10; n++) { d_phi_n = d_phi_n * d_phi; d_psi = d_psi + this.A[n] * d_phi_n; } // 2. Calculate theta var th_re = d_psi; var th_im = d_lambda; // 3. Calculate z var th_n_re = 1; var th_n_im = 0; // theta^0 var th_n_re1; var th_n_im1; var z_re = 0; var z_im = 0; for (n = 1; n <= 6; n++) { th_n_re1 = th_n_re * th_re - th_n_im * th_im; th_n_im1 = th_n_im * th_re + th_n_re * th_im; th_n_re = th_n_re1; th_n_im = th_n_im1; z_re = z_re + this.B_re[n] * th_n_re - this.B_im[n] * th_n_im; z_im = z_im + this.B_im[n] * th_n_re + this.B_re[n] * th_n_im; } // 4. Calculate easting and northing p.x = (z_im * this.a) + this.x0; p.y = (z_re * this.a) + this.y0; return p; }; /** New Zealand Map Grid Inverse - x/y to long/lat */ exports.inverse = function(p) { var n; var x = p.x; var y = p.y; var delta_x = x - this.x0; var delta_y = y - this.y0; // 1. Calculate z var z_re = delta_y / this.a; var z_im = delta_x / this.a; // 2a. Calculate theta - first approximation gives km accuracy var z_n_re = 1; var z_n_im = 0; // z^0 var z_n_re1; var z_n_im1; var th_re = 0; var th_im = 0; for (n = 1; n <= 6; n++) { z_n_re1 = z_n_re * z_re - z_n_im * z_im; z_n_im1 = z_n_im * z_re + z_n_re * z_im; z_n_re = z_n_re1; z_n_im = z_n_im1; th_re = th_re + this.C_re[n] * z_n_re - this.C_im[n] * z_n_im; th_im = th_im + this.C_im[n] * z_n_re + this.C_re[n] * z_n_im; } // 2b. Iterate to refine the accuracy of the calculation // 0 iterations gives km accuracy // 1 iteration gives m accuracy -- good enough for most mapping applications // 2 iterations bives mm accuracy for (var i = 0; i < this.iterations; i++) { var th_n_re = th_re; var th_n_im = th_im; var th_n_re1; var th_n_im1; var num_re = z_re; var num_im = z_im; for (n = 2; n <= 6; n++) { th_n_re1 = th_n_re * th_re - th_n_im * th_im; th_n_im1 = th_n_im * th_re + th_n_re * th_im; th_n_re = th_n_re1; th_n_im = th_n_im1; num_re = num_re + (n - 1) * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); num_im = num_im + (n - 1) * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); } th_n_re = 1; th_n_im = 0; var den_re = this.B_re[1]; var den_im = this.B_im[1]; for (n = 2; n <= 6; n++) { th_n_re1 = th_n_re * th_re - th_n_im * th_im; th_n_im1 = th_n_im * th_re + th_n_re * th_im; th_n_re = th_n_re1; th_n_im = th_n_im1; den_re = den_re + n * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); den_im = den_im + n * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); } // Complex division var den2 = den_re * den_re + den_im * den_im; th_re = (num_re * den_re + num_im * den_im) / den2; th_im = (num_im * den_re - num_re * den_im) / den2; } // 3. Calculate d_phi ... // and d_lambda var d_psi = th_re; var d_lambda = th_im; var d_psi_n = 1; // d_psi^0 var d_phi = 0; for (n = 1; n <= 9; n++) { d_psi_n = d_psi_n * d_psi; d_phi = d_phi + this.D[n] * d_psi_n; } // 4. Calculate latitude and longitude // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. var lat = this.lat0 + (d_phi * SEC_TO_RAD * 1E5); var lon = this.long0 + d_lambda; p.x = lon; p.y = lat; return p; }; exports.names = ["New_Zealand_Map_Grid", "nzmg"]; }); var require$$6$1 = (nzmg && typeof nzmg === 'object' && 'default' in nzmg ? nzmg['default'] : nzmg); var poly = createCommonjsModule(function (module, exports) { var e0fn = require$$7; var e1fn = require$$6; var e2fn = require$$5; var e3fn = require$$4; var adjust_lon = require$$2; var adjust_lat = require$$1$2; var mlfn = require$$3$1; var EPSLN = 1.0e-10; var gN = require$$3; var MAX_ITER = 20; exports.init = function() { /* Place parameters in static storage for common use -------------------------------------------------*/ this.temp = this.b / this.a; this.es = 1 - Math.pow(this.temp, 2); // devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles 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.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); //si que des zeros le calcul ne se fait pas }; /* Polyconic forward equations--mapping lat,long to x,y ---------------------------------------------------*/ exports.forward = function(p) { var lon = p.x; var lat = p.y; var x, y, el; var dlon = adjust_lon(lon - this.long0); el = dlon * Math.sin(lat); if (this.sphere) { if (Math.abs(lat) <= EPSLN) { x = this.a * dlon; y = -1 * this.a * this.lat0; } else { x = this.a * Math.sin(el) / Math.tan(lat); y = this.a * (adjust_lat(lat - this.lat0) + (1 - Math.cos(el)) / Math.tan(lat)); } } else { if (Math.abs(lat) <= EPSLN) { x = this.a * dlon; y = -1 * this.ml0; } else { var nl = gN(this.a, this.e, Math.sin(lat)) / Math.tan(lat); x = nl * Math.sin(el); y = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat) - this.ml0 + nl * (1 - Math.cos(el)); } } p.x = x + this.x0; p.y = y + this.y0; return p; }; /* Inverse equations -----------------*/ exports.inverse = function(p) { var lon, lat, x, y, i; var al, bl; var phi, dphi; x = p.x - this.x0; y = p.y - this.y0; if (this.sphere) { if (Math.abs(y + this.a * this.lat0) <= EPSLN) { lon = adjust_lon(x / this.a + this.long0); lat = 0; } else { al = this.lat0 + y / this.a; bl = x * x / this.a / this.a + al * al; phi = al; var tanphi; for (i = MAX_ITER; i; --i) { tanphi = Math.tan(phi); dphi = -1 * (al * (phi * tanphi + 1) - phi - 0.5 * (phi * phi + bl) * tanphi) / ((phi - al) / tanphi - 1); phi += dphi; if (Math.abs(dphi) <= EPSLN) { lat = phi; break; } } lon = adjust_lon(this.long0 + (Math.asin(x * Math.tan(phi) / this.a)) / Math.sin(lat)); } } else { if (Math.abs(y + this.ml0) <= EPSLN) { lat = 0; lon = adjust_lon(this.long0 + x / this.a); } else { al = (this.ml0 + y) / this.a; bl = x * x / this.a / this.a + al * al; phi = al; var cl, mln, mlnp, ma; var con; for (i = MAX_ITER; i; --i) { con = this.e * Math.sin(phi); cl = Math.sqrt(1 - con * con) * Math.tan(phi); mln = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, phi); mlnp = this.e0 - 2 * this.e1 * Math.cos(2 * phi) + 4 * this.e2 * Math.cos(4 * phi) - 6 * this.e3 * Math.cos(6 * phi); ma = mln / this.a; dphi = (al * (cl * ma + 1) - ma - 0.5 * cl * (ma * ma + bl)) / (this.es * Math.sin(2 * phi) * (ma * ma + bl - 2 * al * ma) / (4 * cl) + (al - ma) * (cl * mlnp - 2 / Math.sin(2 * phi)) - mlnp); phi -= dphi; if (Math.abs(dphi) <= EPSLN) { lat = phi; break; } } //lat=phi4z(this.e,this.e0,this.e1,this.e2,this.e3,al,bl,0,0); cl = Math.sqrt(1 - this.es * Math.pow(Math.sin(lat), 2)) * Math.tan(lat); lon = adjust_lon(this.long0 + Math.asin(x * cl / this.a) / Math.sin(lat)); } }