UNPKG

reproject-geojson

Version:
1,735 lines (1,590 loc) 412 kB
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ module.exports = function getDepth(arr) { const isArray = (arr) => Array.isArray(arr) || arr instanceof Int8Array || arr instanceof Uint8Array || arr instanceof Uint8ClampedArray || arr instanceof Int16Array || arr instanceof Uint16Array || arr instanceof Int32Array || arr instanceof Uint32Array || arr instanceof Float32Array || arr instanceof Float64Array || arr instanceof BigInt64Array || arr instanceof BigUint64Array; let depth = 0; let part = arr; while (isArray(part)) { depth++; part = part[0]; } return depth; }; },{}],2:[function(require,module,exports){ let proj4 = require("proj4"); const defs = require("proj4js-definitions"); // - inside an Angular project, proj4 could be an object // - inside a Vite project, proj4 could be the proj4 function // but with the defs property/function mysteriously removed if ((typeof proj4 === "object" || typeof proj4 === "function") && typeof proj4.defs !== "function" && typeof proj4.default === "function" && typeof proj4.default.defs === "function") { proj4 = proj4.default; } proj4.defs(defs); if (typeof define === "function" && define.amd) { define(function() { return proj4; }); } if (typeof module === "object") { module.exports = proj4; module.exports.default = proj4; } },{"proj4":3,"proj4js-definitions":4}],3:[function(require,module,exports){ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.proj4 = factory()); }(this, (function () { 'use strict'; var globals = function(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_GRIDSHIFT = 3; var PJD_WGS84 = 4; // WGS84 or equivalent var PJD_NODATUM = 5; // WGS84 or equivalent var SRS_WGS84_SEMIMAJOR = 6378137.0; // only used in grid shift transforms var SRS_WGS84_SEMIMINOR = 6356752.314; // only used in grid shift transforms var SRS_WGS84_ESQUARED = 0.0066943799901413165; // only used in grid shift transforms 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 = 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$1 = {}; exports$1.greenwich = 0.0; //"0dE", exports$1.lisbon = -9.131906111111; //"9d07'54.862\"W", exports$1.paris = 2.337229166667; //"2d20'14.025\"E", exports$1.bogota = -74.080916666667; //"74d04'51.3\"W", exports$1.madrid = -3.687938888889; //"3d41'16.58\"W", exports$1.rome = 12.452333333333; //"12d27'8.4\"E", exports$1.bern = 7.439583333333; //"7d26'22.5\"E", exports$1.jakarta = 106.807719444444; //"106d48'27.79\"E", exports$1.ferro = -17.666666666667; //"17d40'W", exports$1.brussels = 4.367975; //"4d22'4.71\"E", exports$1.stockholm = 18.058277777778; //"18d3'29.8\"E", exports$1.athens = 23.7163375; //"23d42'58.815\"E", exports$1.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]; } } } var parseProj = function(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(v) { self.rf = parseFloat(v); }, lat_0: function(v) { self.lat0 = v * D2R; }, lat_1: function(v) { self.lat1 = v * D2R; }, lat_2: function(v) { self.lat2 = v * D2R; }, lat_ts: function(v) { self.lat_ts = v * D2R; }, lon_0: function(v) { self.long0 = v * D2R; }, lon_1: function(v) { self.long1 = v * D2R; }, lon_2: function(v) { self.long2 = v * D2R; }, alpha: function(v) { self.alpha = parseFloat(v) * D2R; }, gamma: function(v) { self.rectified_grid_angle = parseFloat(v); }, lonc: function(v) { self.longc = v * D2R; }, x_0: function(v) { self.x0 = parseFloat(v); }, y_0: function(v) { self.y0 = parseFloat(v); }, k_0: function(v) { self.k0 = parseFloat(v); }, k: function(v) { self.k0 = parseFloat(v); }, a: function(v) { self.a = parseFloat(v); }, b: function(v) { self.b = parseFloat(v); }, r_a: function() { self.R_A = true; }, zone: function(v) { self.zone = parseInt(v, 10); }, south: function() { self.utmSouth = true; }, towgs84: function(v) { self.datum_params = v.split(",").map(function(a) { return parseFloat(a); }); }, to_meter: function(v) { self.to_meter = parseFloat(v); }, units: function(v) { self.units = v; var unit = match(units, v); if (unit) { self.to_meter = unit.to_meter; } }, from_greenwich: function(v) { self.from_greenwich = v * D2R; }, pm: function(v) { var pm = match(exports$1, v); self.from_greenwich = (pm ? pm : parseFloat(v)) * D2R; }, nadgrids: function(v) { if (v === '@null') { self.datumCode = 'none'; } else { self.nadgrids = v; } }, axis: function(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; } }, approx: function() { self.approx = true; } }; 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(char) { if (char === '"') { this.word += '"'; this.state = QUOTED; return; } if (endThings.test(char)) { this.word = this.word.trim(); this.afterItem(char); return; } throw new Error('havn\'t handled "' +char + '" in afterquote yet, index ' + this.place); }; Parser.prototype.afterItem = function(char) { if (char === ',') { if (this.word !== null) { this.currentObject.push(this.word); } this.word = null; this.state = NEUTRAL; return; } if (char === ']') { 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(char) { if (digets.test(char)) { this.word += char; return; } if (endThings.test(char)) { this.word = parseFloat(this.word); this.afterItem(char); return; } throw new Error('havn\'t handled "' +char + '" in number yet, index ' + this.place); }; Parser.prototype.quoted = function(char) { if (char === '"') { this.state = AFTERQUOTE; return; } this.word += char; return; }; Parser.prototype.keyword = function(char) { if (keyword.test(char)) { this.word += char; return; } if (char === '[') { 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(char)) { this.afterItem(char); return; } throw new Error('havn\'t handled "' +char + '" in keyword yet, index ' + this.place); }; Parser.prototype.neutral = function(char) { if (latin.test(char)) { this.word = char; this.state = KEYWORD; return; } if (char === '"') { this.word = ''; this.state = QUOTED; return; } if (digets.test(char)) { this.word = char; this.state = NUMBER; return; } if (endThings.test(char)) { this.afterItem(char); return; } throw new Error('havn\'t handled "' +char + '" 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$1 = 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$1; } 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][0].toLowerCase(), wkt.AXIS[i][1].toLowerCase()]; if (axis[0].indexOf('north') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'north')) { axisOrder += 'n'; } else if (axis[0].indexOf('south') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'south')) { axisOrder += 's'; } else if (axis[0].indexOf('east') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'east')) { axisOrder += 'e'; } else if (axis[0].indexOf('west') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'west')) { 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(a) { return rename(wkt, a); }; var list = [ ['standard_parallel_1', 'Standard_Parallel_1'], ['standard_parallel_1', 'Latitude of 1st standard parallel'], ['standard_parallel_2', 'Standard_Parallel_2'], ['standard_parallel_2', 'Latitude of 2nd standard parallel'], ['false_easting', 'False_Easting'], ['false_easting', 'False easting'], ['false-easting', 'Easting at false origin'], ['false_northing', 'False_Northing'], ['false_northing', 'False northing'], ['false_northing', 'Northing at false origin'], ['central_meridian', 'Central_Meridian'], ['central_meridian', 'Longitude of natural origin'], ['central_meridian', 'Longitude of false origin'], ['latitude_of_origin', 'Latitude_Of_Origin'], ['latitude_of_origin', 'Central_Parallel'], ['latitude_of_origin', 'Latitude of natural origin'], ['latitude_of_origin', 'Latitude of false origin'], ['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; } else if (!wkt.lat_ts && wkt.lat0 && wkt.projName === 'Polar_Stereographic') { wkt.lat_ts = wkt.lat0; wkt.lat0 = d2r(wkt.lat0 > 0 ? 90 : -90); } } var wkt = function(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] = parseProj(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 parseProj(maybeProjStr); } return out; } if (testProj(code)) { return parseProj(code); } }else{ return code; } } var extend = function(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; }; var msfnz = function(eccent, sinphi, cosphi) { var con = eccent * sinphi; return cosphi / (Math.sqrt(1 - con * con)); }; var sign = function(x) { return x<0 ? -1 : 1; }; var adjust_lon = function(x) { return (Math.abs(x) <= SPI) ? x : (x - (sign(x) * TWO_PI)); }; var tsfnz = function(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); }; var phi2z = function(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() { 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(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(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$1 = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"]; var merc = { init: init, forward: forward, inverse: inverse, names: names$1 }; function init$1() { //no-op for longlat } function identity(pt) { return pt; } var names$2 = ["longlat", "identity"]; var longlat = { init: init$1, forward: identity, inverse: identity, names: names$2 }; var projs = [merc, longlat]; var names = {}; 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[n.toLowerCase()] = len; }); return this; } function get(name) { if (!name) { return false; } var n = name.toLowerCase(); if (typeof names[n] !== 'undefined' && projStore[names[n]]) { return projStore[names[n]]; } } function start() { projs.forEach(add); } var projections = { 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.clrk80ign = { a: 6378249.2, b: 6356515, rf: 293.4660213, ellipseName: "Clarke 1880 (IGN)" }; 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$3 = {}; exports$3.wgs84 = { towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84" }; exports$3.ch1903 = { towgs84: "674.374,15.056,405.346", ellipse: "bessel", datumName: "swiss" }; exports$3.ggrs87 = { towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987" }; exports$3.nad83 = { towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983" }; exports$3.nad27 = { nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927" }; exports$3.potsdam = { towgs84: "598.1,73.7,418.2,0.202,0.045,-2.455,6.7", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN" }; exports$3.carthage = { towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia" }; exports$3.hermannskogel = { towgs84: "577.326,90.129,463.919,5.137,1.474,5.297,2.4232", ellipse: "bessel", datumName: "Hermannskogel" }; exports$3.osni52 = { towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "airy", datumName: "Irish National" }; exports$3.ire65 = { towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965" }; exports$3.rassadiran = { towgs84: "-133.63,-157.5,-158.62", ellipse: "intl", datumName: "Rassadiran" }; exports$3.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$3.osgb36 = { towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830" }; exports$3.s_jtsk = { towgs84: "589,76,480", ellipse: 'bessel', datumName: 'S-JTSK (Ferro)' }; exports$3.beduaram = { towgs84: '-106,-87,188', ellipse: 'clrk80', datumName: 'Beduaram' }; exports$3.gunung_segara = { towgs84: '-403,684,41', ellipse: 'bessel', datumName: 'Gunung Segara Jakarta' }; exports$3.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, nadgrids) { 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; } } } if (nadgrids) { out.datum_type = PJD_GRIDSHIFT; out.grids = nadgrids; } out.a = a; //datum object also uses these values out.b = b; out.es = es; out.ep2 = ep2; return out; } /** * Resources for details of NTv2 file formats: * - https://web.archive.org/web/20140127204822if_/http://www.mgs.gov.on.ca:80/stdprodconsume/groups/content/@mgs/@iandit/documents/resourcelist/stel02_047447.pdf * - http://mimaka.com/help/gs/html/004_NTV2%20Data%20Format.htm */ var loadedNadgrids = {}; /** * Load a binary NTv2 file (.gsb) to a key that can be used in a proj string like +nadgrids=<key>. Pass the NTv2 file * as an ArrayBuffer. */ function nadgrid(key, data) { var view = new DataView(data); var isLittleEndian = detectLittleEndian(view); var header = readHeader(view, isLittleEndian); if (header.nSubgrids > 1) { console.log('Only single NTv2 subgrids are currently supported, subsequent sub grids are ignored'); } var subgrids = readSubgrids(view, header, isLittleEndian); var nadgrid = {header: header, subgrids: subgrids}; loadedNadgrids[key] = nadgrid; return nadgrid; } /** * Given a proj4 value for nadgrids, return an array of loaded grids */ function getNadgrids(nadgrids) { // Format details: http://proj.maptools.org/gen_parms.html if (nadgrids === undefined) { return null; } var grids = nadgrids.split(','); return grids.map(parseNadgridString); } function parseNadgridString(value) { if (value.length === 0) { return null; } var optional = value[0] === '@'; if (optional) { value = value.slice(1); } if (value === 'null') { return {name: 'null', mandatory: !optional, grid: null, isNull: true}; } return { name: value, mandatory: !optional, grid: loadedNadgrids[value] || null, isNull: false }; } function secondsToRadians(seconds) { return (seconds / 3600) * Math.PI / 180; } function detectLittleEndian(view) { var nFields = view.getInt32(8, false); if (nFields === 11) { return false; } nFields = view.getInt32(8, true); if (nFields !== 11) { console.warn('Failed to detect nadgrid endian-ness, defaulting to little-endian'); } return true; } function readHeader(view, isLittleEndian) { return { nFields: view.getInt32(8, isLittleEndian), nSubgridFields: view.getInt32(24, isLittleEndian), nSubgrids: view.getInt32(40, isLittleEndian), shiftType: decodeString(view, 56, 56 + 8).trim(), fromSemiMajorAxis: view.getFloat64(120, isLittleEndian), fromSemiMinorAxis: view.getFloat64(136, isLittleEndian), toSemiMajorAxis: view.getFloat64(152, isLittleEndian), toSemiMinorAxis: view.getFloat64(168, isLittleEndian), }; } function decodeString(view, start, end) { return String.fromCharCode.apply(null, new Uint8Array(view.buffer.slice(start, end))); } function readSubgrids(view, header, isLittleEndian) { var gridOffset = 176; var grids = []; for (var i = 0; i < header.nSubgrids; i++) { var subHeader = readGridHeader(view, gridOffset, isLittleEndian); var nodes = readGridNodes(view, gridOffset, subHeader, isLittleEndian); var lngColumnCount = Math.round( 1 + (subHeader.upperLongitude - subHeader.lowerLongitude) / subHeader.longitudeInterval); var latColumnCount = Math.round( 1 + (subHeader.upperLatitude - subHeader.lowerLatitude) / subHeader.latitudeInterval); // Proj4 operates on radians whereas the coordinates are in seconds in the grid grids.push({ ll: [secondsToRadians(subHeader.lowerLongitude), secondsToRadians(subHeader.lowerLatitude)], del: [secondsToRadians(subHeader.longitudeInterval), secondsToRadians(subHeader.latitudeInterval)], lim: [lngColumnCount, latColumnCount], count: subHeader.gridNodeCount, cvs: mapNodes(nodes) }); } return grids; } function mapNodes(nodes) { return nodes.map(function (r) {return [secondsToRadians(r.longitudeShift), secondsToRadians(r.latitudeShift)];}); } function readGridHeader(view, offset, isLittleEndian) { return { name: decodeString(view, offset + 8, offset + 16).trim(), parent: decodeString(view, offset + 24, offset + 24 + 8).trim(), lowerLatitude: view.getFloat64(offset + 72, isLittleEndian), upperLatitude: view.getFloat64(offset + 88, isLittleEndian), lowerLongitude: view.getFloat64(offset + 104, isLittleEndian), upperLongitude: view.getFloat64(offset + 120, isLittleEndian), latitudeInterval: view.getFloat64(offset + 136, isLittleEndian), longitudeInterval: view.getFloat64(offset + 152, isLittleEndian), gridNodeCount: view.getInt32(offset + 168, isLittleEndian) }; } function readGridNodes(view, offset, gridHeader, isLittleEndian) { var nodesOffset = offset + 176; var gridRecordLength = 16; var gridShiftRecords = []; for (var i = 0; i < gridHeader.gridNodeCount; i++) { var record = { latitudeShift: view.getFloat32(nodesOffset + i * gridRecordLength, isLittleEndian), longitudeShift: view.getFloat32(nodesOffset + i * gridRecordLength + 4, isLittleEndian), latitudeAccuracy: view.getFloat32(nodesOffset + i * gridRecordLength + 8, isLittleEndian), longitudeAccuracy: view.getFloat32(nodesOffset + i * gridRecordLength + 12, isLittleEndian), }; gridShiftRecords.push(record); } return gridShiftRecords; } 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$3, json.datumCode); if (datumDef) { json.datum_params = 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'; json.lat1 = json.lat1 || json.lat0; // Lambert_Conformal_Conic_1SP, for example, needs this 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 nadgrids = getNadgrids(json.nadgrids); var datumObj = json.datum || datum(json.datumCode, json.datum_params, sphere_.a, sphere_.b, ecc.es, ecc.ep2, nadgrids); 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 calculated 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; Projection.projections.start(); 'use strict'; 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 Conve