[proj4js] 02/06: Imported Upstream version 2.3.16+ds
Bas Couwenberg
sebastic at debian.org
Mon Jan 23 21:45:33 UTC 2017
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository proj4js.
commit 7f09e8d348cb92bcc854e777e460f68b70fd1e7c
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Mon Jan 23 22:33:13 2017 +0100
Imported Upstream version 2.3.16+ds
---
.gitignore | 3 +-
Gruntfile.js | 3 +-
README.md | 9 +-
bower.json | 2 +-
component.json | 2 +-
dist/proj4-src.js | 1336 +++++++++++++++++++++------------------------
dist/test.html | 11 -
lib/Proj.js | 54 +-
lib/adjust_axis.js | 15 +-
lib/common/adjust_zone.js | 19 +
lib/datum.js | 413 +-------------
lib/datumUtils.js | 247 +++++++++
lib/datum_transform.js | 96 +---
lib/deriveConstants.js | 89 ++-
lib/index.js | 6 +-
lib/parseCode.js | 15 +-
lib/projString.js | 12 +-
lib/projections/tmerc.js | 142 +++--
lib/projections/utm.js | 11 +-
lib/transform.js | 60 +-
lib/version-browser.js | 1 +
lib/version.js | 1 +
package.json | 16 +-
publish.sh | 3 +-
test/test.js | 9 +-
test/testData.js | 84 ++-
26 files changed, 1269 insertions(+), 1390 deletions(-)
diff --git a/.gitignore b/.gitignore
index 312583b..0f3e170 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ node_modules
coverage
projs.js
.DS_STORE
-dist
\ No newline at end of file
+dist
+lib/version-browser.js
diff --git a/Gruntfile.js b/Gruntfile.js
index ebd05c0..c35d3c4 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -61,7 +61,8 @@ module.exports = function(grunt) {
standalone: 'proj4'
},
alias: [
- './projs:./includedProjections'
+ './projs:./includedProjections',
+ './lib/version-browser:./lib/version'
]
}
}
diff --git a/README.md b/README.md
index 3bb37fe..f4aeae1 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,6 @@ Depending on your preferences
```bash
npm install proj4
bower install proj4
-jam install proj4
component install proj4js/proj4js
```
@@ -114,6 +113,14 @@ proj4.defs can also be used to define a named alias:
proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326'));
```
+## TypeScript
+
+TypeScript implementation was added to the [DefinitelyTyped repository](https://github.com/DefinitelyTyped/DefinitelyTyped).
+
+```bash
+$ npm install --save @types/proj4
+```
+
## Developing
to set up build tools make sure you have node and grunt-cli installed and then run `npm install`
diff --git a/bower.json b/bower.json
index 814d89c..2781321 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "proj4",
- "version": "2.3.15-alpha",
+ "version": "2.3.16-alpha",
"description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
"homepage": "https://github.com/proj4js/proj4js",
"main": "dist/proj4.js",
diff --git a/component.json b/component.json
index e600be3..d5a3a3b 100644
--- a/component.json
+++ b/component.json
@@ -1,6 +1,6 @@
{
"name": "proj4",
- "version": "2.3.15-alpha",
+ "version": "2.3.16-alpha",
"description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
"repo": "proj4js/proj4js",
"keywords": [
diff --git a/dist/proj4-src.js b/dist/proj4-src.js
index 24da1e7..865a89e 100644
--- a/dist/proj4-src.js
+++ b/dist/proj4-src.js
@@ -29,7 +29,10 @@ module.exports = function(proj4){
proj4.Proj.projections.add(proj);
});
}
-},{"./lib/projections/aea":40,"./lib/projections/aeqd":41,"./lib/projections/cass":42,"./lib/projections/cea":43,"./lib/projections/eqc":44,"./lib/projections/eqdc":45,"./lib/projections/gnom":47,"./lib/projections/krovak":48,"./lib/projections/laea":49,"./lib/projections/lcc":50,"./lib/projections/mill":53,"./lib/projections/moll":54,"./lib/projections/nzmg":55,"./lib/projections/omerc":56,"./lib/projections/ortho":57,"./lib/projections/poly":58,"./lib/projections/sinu":59,"./lib/projec [...]
+},{"./lib/projections/aea":42,"./lib/projections/aeqd":43,"./lib/projections/cass":44,"./lib/projections/cea":45,"./lib/projections/eqc":46,"./lib/projections/eqdc":47,"./lib/projections/gnom":49,"./lib/projections/krovak":50,"./lib/projections/laea":51,"./lib/projections/lcc":52,"./lib/projections/mill":55,"./lib/projections/moll":56,"./lib/projections/nzmg":57,"./lib/projections/omerc":58,"./lib/projections/ortho":59,"./lib/projections/poly":60,"./lib/projections/sinu":61,"./lib/projec [...]
+module.exports = '2.3.16';
+
+},{}],1:[function(require,module,exports){
var mgrs = require('mgrs');
function Point(x, y, z) {
@@ -65,11 +68,14 @@ Point.prototype.toMGRS = function(accuracy) {
};
module.exports = Point;
-},{"mgrs":68}],2:[function(require,module,exports){
-var parseCode = require("./parseCode");
+},{"mgrs":70}],2:[function(require,module,exports){
+var parseCode = require('./parseCode');
var extend = require('./extend');
var projections = require('./projections');
var deriveConstants = require('./deriveConstants');
+var Datum = require('./constants/Datum');
+var datum = require('./datum');
+
function Projection(srsCode,callback) {
if (!(this instanceof Projection)) {
@@ -85,27 +91,61 @@ function Projection(srsCode,callback) {
callback(srsCode);
return;
}
- var modifiedJSON = deriveConstants(json);
- var ourProj = Projection.projections.get(modifiedJSON.projName);
- if(ourProj){
- extend(this, modifiedJSON);
- extend(this, ourProj);
- this.init();
- callback(null, this);
- }else{
+ var ourProj = Projection.projections.get(json.projName);
+ if(!ourProj){
callback(srsCode);
+ return;
}
+ if (json.datumCode && json.datumCode !== 'none') {
+ var datumDef = Datum[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';
+
+ var sphere = deriveConstants.sphere(json.a, json.b, json.rf, json.ellps, json.sphere);
+ var ecc = deriveConstants.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;
Projection.projections.start();
module.exports = Projection;
-},{"./deriveConstants":33,"./extend":34,"./parseCode":37,"./projections":39}],3:[function(require,module,exports){
+},{"./constants/Datum":26,"./datum":31,"./deriveConstants":35,"./extend":36,"./parseCode":39,"./projections":41}],3:[function(require,module,exports){
module.exports = function(crs, denorm, point) {
var xin = point.x,
yin = point.y,
zin = point.z || 0.0;
var v, t, i;
+ var out = {};
for (i = 0; i < 3; i++) {
if (denorm && i === 2 && point.z === undefined) {
continue;
@@ -124,25 +164,25 @@ module.exports = function(crs, denorm, point) {
}
switch (crs.axis[i]) {
case 'e':
- point[t] = v;
+ out[t] = v;
break;
case 'w':
- point[t] = -v;
+ out[t] = -v;
break;
case 'n':
- point[t] = v;
+ out[t] = v;
break;
case 's':
- point[t] = -v;
+ out[t] = -v;
break;
case 'u':
if (point[t] !== undefined) {
- point.z = v;
+ out.z = v;
}
break;
case 'd':
if (point[t] !== undefined) {
- point.z = -v;
+ out.z = -v;
}
break;
default:
@@ -150,7 +190,7 @@ module.exports = function(crs, denorm, point) {
return null;
}
}
- return point;
+ return out;
};
},{}],4:[function(require,module,exports){
@@ -160,7 +200,7 @@ var sign = require('./sign');
module.exports = function(x) {
return (Math.abs(x) < HALF_PI) ? x : (x - (sign(x) * Math.PI));
};
-},{"./sign":21}],5:[function(require,module,exports){
+},{"./sign":22}],5:[function(require,module,exports){
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
@@ -172,35 +212,56 @@ var sign = require('./sign');
module.exports = function(x) {
return (Math.abs(x) <= SPI) ? x : (x - (sign(x) * TWO_PI));
};
-},{"./sign":21}],6:[function(require,module,exports){
+},{"./sign":22}],6:[function(require,module,exports){
+var adjust_lon = require('./adjust_lon');
+
+module.exports = function(zone, lon) {
+ if (!zone) {
+ zone = Math.floor((adjust_lon(lon) + Math.PI) * 30 / Math.PI);
+
+ if (zone < 0) {
+ return 0;
+ }
+ else if (zone >= 60) {
+ return 59;
+ }
+ }
+ else {
+ if (zone > 0 && zone <= 60) {
+ return zone - 1;
+ }
+ }
+};
+
+},{"./adjust_lon":5}],7:[function(require,module,exports){
module.exports = function(x) {
if (Math.abs(x) > 1) {
x = (x > 1) ? 1 : -1;
}
return Math.asin(x);
};
-},{}],7:[function(require,module,exports){
+},{}],8:[function(require,module,exports){
module.exports = function(x) {
return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x)));
};
-},{}],8:[function(require,module,exports){
+},{}],9:[function(require,module,exports){
module.exports = function(x) {
return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x)));
};
-},{}],9:[function(require,module,exports){
+},{}],10:[function(require,module,exports){
module.exports = function(x) {
return (0.05859375 * x * x * (1 + 0.75 * x));
};
-},{}],10:[function(require,module,exports){
+},{}],11:[function(require,module,exports){
module.exports = function(x) {
return (x * x * x * (35 / 3072));
};
-},{}],11:[function(require,module,exports){
+},{}],12:[function(require,module,exports){
module.exports = function(a, e, sinphi) {
var temp = e * sinphi;
return a / Math.sqrt(1 - temp * temp);
};
-},{}],12:[function(require,module,exports){
+},{}],13:[function(require,module,exports){
module.exports = function(ml, e0, e1, e2, e3) {
var phi;
var dphi;
@@ -217,7 +278,7 @@ module.exports = function(ml, e0, e1, e2, e3) {
//..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations");
return NaN;
};
-},{}],13:[function(require,module,exports){
+},{}],14:[function(require,module,exports){
var HALF_PI = Math.PI/2;
module.exports = function(eccent, q) {
@@ -250,16 +311,16 @@ module.exports = function(eccent, q) {
//console.log("IQSFN-CONV:Latitude failed to converge after 30 iterations");
return NaN;
};
-},{}],14:[function(require,module,exports){
+},{}],15:[function(require,module,exports){
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));
};
-},{}],15:[function(require,module,exports){
+},{}],16:[function(require,module,exports){
module.exports = function(eccent, sinphi, cosphi) {
var con = eccent * sinphi;
return cosphi / (Math.sqrt(1 - con * con));
};
-},{}],16:[function(require,module,exports){
+},{}],17:[function(require,module,exports){
var HALF_PI = Math.PI/2;
module.exports = function(eccent, ts) {
var eccnth = 0.5 * eccent;
@@ -276,7 +337,7 @@ module.exports = function(eccent, ts) {
//console.log("phi2z has NoConvergence");
return -9999;
};
-},{}],17:[function(require,module,exports){
+},{}],18:[function(require,module,exports){
var C00 = 1;
var C02 = 0.25;
var C04 = 0.046875;
@@ -301,7 +362,7 @@ module.exports = function(es) {
en[4] = t * es * C88;
return en;
};
-},{}],18:[function(require,module,exports){
+},{}],19:[function(require,module,exports){
var pj_mlfn = require("./pj_mlfn");
var EPSLN = 1.0e-10;
var MAX_ITER = 20;
@@ -322,13 +383,13 @@ module.exports = function(arg, es, en) {
//..reportError("cass:pj_inv_mlfn: Convergence error");
return phi;
};
-},{"./pj_mlfn":19}],19:[function(require,module,exports){
+},{"./pj_mlfn":20}],20:[function(require,module,exports){
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]))));
};
-},{}],20:[function(require,module,exports){
+},{}],21:[function(require,module,exports){
module.exports = function(eccent, sinphi) {
var con;
if (eccent > 1.0e-7) {
@@ -339,15 +400,15 @@ module.exports = function(eccent, sinphi) {
return (2 * sinphi);
}
};
-},{}],21:[function(require,module,exports){
+},{}],22:[function(require,module,exports){
module.exports = function(x) {
return x<0 ? -1 : 1;
};
-},{}],22:[function(require,module,exports){
+},{}],23:[function(require,module,exports){
module.exports = function(esinp, exp) {
return (Math.pow((1 - esinp) / (1 + esinp), exp));
};
-},{}],23:[function(require,module,exports){
+},{}],24:[function(require,module,exports){
module.exports = function (array){
var out = {
x: array[0],
@@ -361,7 +422,7 @@ module.exports = function (array){
}
return out;
};
-},{}],24:[function(require,module,exports){
+},{}],25:[function(require,module,exports){
var HALF_PI = Math.PI/2;
module.exports = function(eccent, phi, sinphi) {
@@ -370,7 +431,7 @@ module.exports = function(eccent, phi, sinphi) {
con = Math.pow(((1 - con) / (1 + con)), com);
return (Math.tan(0.5 * (HALF_PI - phi)) / con);
};
-},{}],25:[function(require,module,exports){
+},{}],26:[function(require,module,exports){
exports.wgs84 = {
towgs84: "0,0,0",
ellipse: "WGS84",
@@ -451,7 +512,7 @@ exports.rnb72 = {
ellipse: "intl",
datumName: "Reseau National Belge 1972"
};
-},{}],26:[function(require,module,exports){
+},{}],27:[function(require,module,exports){
exports.MERIT = {
a: 6378137.0,
rf: 298.257,
@@ -667,7 +728,7 @@ exports.sphere = {
b: 6370997.0,
ellipseName: "Normal Sphere (r=6370997)"
};
-},{}],27:[function(require,module,exports){
+},{}],28:[function(require,module,exports){
exports.greenwich = 0.0; //"0dE",
exports.lisbon = -9.131906111111; //"9d07'54.862\"W",
exports.paris = 2.337229166667; //"2d20'14.025\"E",
@@ -681,11 +742,11 @@ exports.brussels = 4.367975; //"4d22'4.71\"E",
exports.stockholm = 18.058277777778; //"18d3'29.8\"E",
exports.athens = 23.7163375; //"23d42'58.815\"E",
exports.oslo = 10.722916666667; //"10d43'22.5\"E"
-},{}],28:[function(require,module,exports){
+},{}],29:[function(require,module,exports){
exports.ft = {to_meter: 0.3048};
exports['us-ft'] = {to_meter: 1200 / 3937};
-},{}],29:[function(require,module,exports){
+},{}],30:[function(require,module,exports){
var proj = require('./Proj');
var transform = require('./transform');
var wgs84 = proj('WGS84');
@@ -750,426 +811,306 @@ function proj4(fromProj, toProj, coord) {
}
}
module.exports = proj4;
-},{"./Proj":2,"./transform":66}],30:[function(require,module,exports){
-var HALF_PI = Math.PI/2;
+},{"./Proj":2,"./transform":68}],31:[function(require,module,exports){
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 SEC_TO_RAD = 4.84813681109535993589914102357e-6;
-var AD_C = 1.0026000;
-var COS_67P5 = 0.38268343236508977;
-var datum = function(proj) {
- if (!(this instanceof datum)) {
- return new datum(proj);
- }
- this.datum_type = PJD_WGS84; //default setting
- if (!proj) {
- return;
- }
- if (proj.datumCode && proj.datumCode === 'none') {
- this.datum_type = PJD_NODATUM;
- }
- if (proj.datum_params) {
- this.datum_params = proj.datum_params.map(parseFloat);
- if (this.datum_params[0] !== 0 || this.datum_params[1] !== 0 || this.datum_params[2] !== 0) {
- this.datum_type = PJD_3PARAM;
- }
- if (this.datum_params.length > 3) {
- if (this.datum_params[3] !== 0 || this.datum_params[4] !== 0 || this.datum_params[5] !== 0 || this.datum_params[6] !== 0) {
- this.datum_type = PJD_7PARAM;
- this.datum_params[3] *= SEC_TO_RAD;
- this.datum_params[4] *= SEC_TO_RAD;
- this.datum_params[5] *= SEC_TO_RAD;
- this.datum_params[6] = (this.datum_params[6] / 1000000.0) + 1.0;
+function datum(datumCode, datum_params, a, b, es, ep2) {
+ var out = {};
+ out.datum_type = PJD_WGS84; //default setting
+ if (datumCode && datumCode === 'none') {
+ out.datum_type = PJD_NODATUM;
+ }
+
+ 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;
}
}
}
- // DGR 2011-03-21 : nadgrids support
- this.datum_type = proj.grids ? PJD_GRIDSHIFT : this.datum_type;
- this.a = proj.a; //datum object also uses these values
- this.b = proj.b;
- this.es = proj.es;
- this.ep2 = proj.ep2;
- if (this.datum_type === PJD_GRIDSHIFT) {
- this.grids = proj.grids;
+ out.a = a; //datum object also uses these values
+ out.b = b;
+ out.es = es;
+ out.ep2 = ep2;
+ return out;
+}
+
+module.exports = datum;
+
+},{}],32:[function(require,module,exports){
+'use strict';
+var PJD_3PARAM = 1;
+var PJD_7PARAM = 2;
+var HALF_PI = Math.PI/2;
+
+exports.compareDatums = function(source, dest) {
+ if (source.datum_type !== dest.datum_type) {
+ return false; // false, datums are not equal
+ } else if (source.a !== dest.a || Math.abs(this.es - dest.es) > 0.000000000050) {
+ // the tolerence for es is to ensure that GRS80 and WGS84
+ // are considered identical
+ return false;
+ } else if (source.datum_type === PJD_3PARAM) {
+ return (this.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
}
-};
-datum.prototype = {
+}; // 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)
+ *
+ */
+exports.geodeticToGeocentric = function(p, es, a) {
+ var Longitude = p.x;
+ var Latitude = p.y;
+ var Height = p.z ? p.z : 0; //Z value not always supplied
- /****************************************************************/
- // cs_compare_datums()
- // Returns TRUE if the two datums match, otherwise FALSE.
- compare_datums: function(dest) {
- if (this.datum_type !== dest.datum_type) {
- return false; // false, datums are not equal
- }
- else if (this.a !== dest.a || Math.abs(this.es - dest.es) > 0.000000000050) {
- // the tolerence for es is to ensure that GRS80 and WGS84
- // are considered identical
- return false;
- }
- else if (this.datum_type === PJD_3PARAM) {
- return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2]);
- }
- else if (this.datum_type === PJD_7PARAM) {
- return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2] && this.datum_params[3] === dest.datum_params[3] && this.datum_params[4] === dest.datum_params[4] && this.datum_params[5] === dest.datum_params[5] && this.datum_params[6] === dest.datum_params[6]);
- }
- else if (this.datum_type === PJD_GRIDSHIFT || dest.datum_type === PJD_GRIDSHIFT) {
- //alert("ERROR: Grid shift transformations are not implemented.");
- //return false
- //DGR 2012-07-29 lazy ...
- return this.nadgrids === dest.nadgrids;
- }
- else {
- return true; // datums are equal
- }
- }, // cs_compare_datums()
+ 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) */
/*
- * 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)
- *
+ ** 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.
*/
- geodetic_to_geocentric: function(p) {
- var Longitude = p.x;
- var Latitude = p.y;
- var Height = p.z ? p.z : 0; //Z value not always supplied
- var X; // output
- var Y;
- var Z;
-
- var Error_Code = 0; // GEOCENT_NO_ERROR;
- 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 > HALF_PI)) {
- /* Latitude out of range */
- //..reportError('geocent:lat out of range:' + Latitude);
- return null;
- }
+ 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 > HALF_PI)) {
+ /* Latitude out of range */
+ //..reportError('geocent:lat out of range:' + Latitude);
+ return null;
+ }
- 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 = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
- X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
- Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
- Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
-
- p.x = X;
- p.y = Y;
- p.z = Z;
- return Error_Code;
- }, // cs_geodetic_to_geocentric()
-
-
- geocentric_to_geodetic: function(p) {
- /* 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; /* cos of geocentric latitude */
- var RX;
- var RK;
- var RN; /* Earth radius at location */
- var CPHI0; /* cos of start or old geodetic latitude in iterations */
- var SPHI0; /* sin of start or old geodetic latitude in iterations */
- var CPHI; /* cos of searched geodetic latitude */
- var SPHI; /* sin of searched geodetic latitude */
- var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
- var At_Pole; /* indicates location is in polar region */
- var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
-
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0.0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
-
- At_Pole = false;
- P = Math.sqrt(X * X + Y * Y);
- RR = Math.sqrt(X * X + Y * Y + Z * Z);
-
- /* special cases for latitude and longitude */
- if (P / this.a < genau) {
-
- /* special case, if P=0. (X=0., Y=0.) */
- At_Pole = true;
- Longitude = 0.0;
-
- /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
- * of ellipsoid (=center of mass), Latitude becomes PI/2 */
- if (RR / this.a < genau) {
- Latitude = HALF_PI;
- Height = -this.b;
- return;
- }
+ 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()
+
+
+exports.geocentricToGeodetic = function(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; /* cos of geocentric latitude */
+ var RX;
+ var RK;
+ var RN; /* Earth radius at location */
+ var CPHI0; /* cos of start or old geodetic latitude in iterations */
+ var SPHI0; /* sin of start or old geodetic latitude in iterations */
+ var CPHI; /* cos of searched geodetic latitude */
+ var SPHI; /* sin of searched geodetic latitude */
+ var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
+ var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
+
+ var X = p.x;
+ var Y = p.y;
+ var Z = p.z ? p.z : 0.0; //Z value not always supplied
+ var Longitude;
+ var Latitude;
+ var Height;
+
+ P = Math.sqrt(X * X + Y * Y);
+ RR = Math.sqrt(X * X + Y * Y + Z * Z);
+
+ /* special cases for latitude and longitude */
+ if (P / a < genau) {
+
+ /* special case, if P=0. (X=0., Y=0.) */
+ Longitude = 0.0;
+
+ /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
+ * of ellipsoid (=center of mass), Latitude becomes PI/2 */
+ if (RR / a < genau) {
+ Latitude = HALF_PI;
+ Height = -b;
+ return {
+ x: p.x,
+ y: p.y,
+ z: p.z
+ };
}
- else {
- /* ellipsoidal (geodetic) longitude
- * interval: -PI < Longitude <= +PI */
- Longitude = Math.atan2(Y, X);
- }
-
- /* --------------------------------------------------------------
- * Following iterative algorithm was developped by
- * "Institut for Erdmessung", University of Hannover, July 1988.
- * Internet: www.ife.uni-hannover.de
- * Iterative computation of CPHI,SPHI and Height.
- * Iteration of CPHI and SPHI to 10**-12 radian resp.
- * 2*10**-7 arcsec.
- * --------------------------------------------------------------
- */
- CT = Z / RR;
- ST = P / RR;
- RX = 1.0 / Math.sqrt(1.0 - this.es * (2.0 - this.es) * ST * ST);
- CPHI0 = ST * (1.0 - this.es) * RX;
- SPHI0 = CT * RX;
- iter = 0;
-
- /* loop to find sin(Latitude) resp. Latitude
- * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
- do {
- iter++;
- RN = this.a / Math.sqrt(1.0 - this.es * SPHI0 * SPHI0);
-
- /* ellipsoidal (geodetic) height */
- Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - this.es * SPHI0 * SPHI0);
-
- RK = this.es * RN / (RN + Height);
- RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST);
- CPHI = ST * (1.0 - RK) * RX;
- SPHI = CT * RX;
- SDPHI = SPHI * CPHI0 - CPHI * SPHI0;
- CPHI0 = CPHI;
- SPHI0 = SPHI;
- }
- while (SDPHI * SDPHI > genau2 && iter < maxiter);
-
- /* ellipsoidal (geodetic) latitude */
- Latitude = Math.atan(SPHI / Math.abs(CPHI));
-
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // cs_geocentric_to_geodetic()
-
- /** Convert_Geocentric_To_Geodetic
- * The method used here is derived from 'An Improved Algorithm for
- * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
+ } else {
+ /* ellipsoidal (geodetic) longitude
+ * interval: -PI < Longitude <= +PI */
+ Longitude = Math.atan2(Y, X);
+ }
+
+ /* --------------------------------------------------------------
+ * Following iterative algorithm was developped by
+ * "Institut for Erdmessung", University of Hannover, July 1988.
+ * Internet: www.ife.uni-hannover.de
+ * Iterative computation of CPHI,SPHI and Height.
+ * Iteration of CPHI and SPHI to 10**-12 radian resp.
+ * 2*10**-7 arcsec.
+ * --------------------------------------------------------------
*/
- geocentric_to_geodetic_noniter: function(p) {
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
-
- var W; /* distance from Z axis */
- var W2; /* square of distance from Z axis */
- var T0; /* initial estimate of vertical component */
- var T1; /* corrected estimate of vertical component */
- var S0; /* initial estimate of horizontal component */
- var S1; /* corrected estimate of horizontal component */
- var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */
- var Sin3_B0; /* cube of Math.sin(B0) */
- var Cos_B0; /* Math.cos(B0) */
- var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */
- var Cos_p1; /* Math.cos(phi1) */
- var Rn; /* Earth radius at location */
- var Sum; /* numerator of Math.cos(phi1) */
- var At_Pole; /* indicates location is in polar region */
-
- X = parseFloat(X); // cast from string to float
- Y = parseFloat(Y);
- Z = parseFloat(Z);
-
- At_Pole = false;
- if (X !== 0.0) {
- Longitude = Math.atan2(Y, X);
- }
- else {
- if (Y > 0) {
- Longitude = HALF_PI;
- }
- else if (Y < 0) {
- Longitude = -HALF_PI;
- }
- else {
- At_Pole = true;
- Longitude = 0.0;
- if (Z > 0.0) { /* north pole */
- Latitude = HALF_PI;
- }
- else if (Z < 0.0) { /* south pole */
- Latitude = -HALF_PI;
- }
- else { /* center of earth */
- Latitude = HALF_PI;
- Height = -this.b;
- return;
- }
- }
- }
- W2 = X * X + Y * Y;
- W = Math.sqrt(W2);
- T0 = Z * AD_C;
- S0 = Math.sqrt(T0 * T0 + W2);
- Sin_B0 = T0 / S0;
- Cos_B0 = W / S0;
- Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
- T1 = Z + this.b * this.ep2 * Sin3_B0;
- Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
- S1 = Math.sqrt(T1 * T1 + Sum * Sum);
- Sin_p1 = T1 / S1;
- Cos_p1 = Sum / S1;
- Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
- if (Cos_p1 >= COS_67P5) {
- Height = W / Cos_p1 - Rn;
- }
- else if (Cos_p1 <= -COS_67P5) {
- Height = W / -Cos_p1 - Rn;
- }
- else {
- Height = Z / Sin_p1 + Rn * (this.es - 1.0);
- }
- if (At_Pole === false) {
- Latitude = Math.atan(Sin_p1 / Cos_p1);
- }
+ CT = Z / RR;
+ ST = P / RR;
+ RX = 1.0 / Math.sqrt(1.0 - es * (2.0 - es) * ST * ST);
+ CPHI0 = ST * (1.0 - es) * RX;
+ SPHI0 = CT * RX;
+ iter = 0;
+
+ /* loop to find sin(Latitude) resp. Latitude
+ * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
+ do {
+ iter++;
+ RN = a / Math.sqrt(1.0 - es * SPHI0 * SPHI0);
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // geocentric_to_geodetic_noniter()
-
- /****************************************************************/
- // pj_geocentic_to_wgs84( p )
- // p = point to transform in geocentric coordinates (x,y,z)
- geocentric_to_wgs84: function(p) {
-
- if (this.datum_type === PJD_3PARAM) {
- // if( x[io] === HUGE_VAL )
- // continue;
- p.x += this.datum_params[0];
- p.y += this.datum_params[1];
- p.z += this.datum_params[2];
-
- }
- else if (this.datum_type === PJD_7PARAM) {
- var Dx_BF = this.datum_params[0];
- var Dy_BF = this.datum_params[1];
- var Dz_BF = this.datum_params[2];
- var Rx_BF = this.datum_params[3];
- var Ry_BF = this.datum_params[4];
- var Rz_BF = this.datum_params[5];
- var M_BF = this.datum_params[6];
- // if( x[io] === HUGE_VAL )
- // continue;
- var x_out = M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF;
- var y_out = M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF;
- var z_out = M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF;
- p.x = x_out;
- p.y = y_out;
- p.z = z_out;
- }
- }, // cs_geocentric_to_wgs84
-
- /****************************************************************/
- // pj_geocentic_from_wgs84()
- // coordinate system definition,
- // point to transform in geocentric coordinates (x,y,z)
- geocentric_from_wgs84: function(p) {
-
- if (this.datum_type === PJD_3PARAM) {
- //if( x[io] === HUGE_VAL )
- // continue;
- p.x -= this.datum_params[0];
- p.y -= this.datum_params[1];
- p.z -= this.datum_params[2];
-
- }
- else if (this.datum_type === PJD_7PARAM) {
- var Dx_BF = this.datum_params[0];
- var Dy_BF = this.datum_params[1];
- var Dz_BF = this.datum_params[2];
- var Rx_BF = this.datum_params[3];
- var Ry_BF = this.datum_params[4];
- var Rz_BF = this.datum_params[5];
- var M_BF = this.datum_params[6];
- var x_tmp = (p.x - Dx_BF) / M_BF;
- var y_tmp = (p.y - Dy_BF) / M_BF;
- var z_tmp = (p.z - Dz_BF) / M_BF;
- //if( x[io] === HUGE_VAL )
- // continue;
-
- p.x = x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp;
- p.y = -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp;
- p.z = Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp;
- } //cs_geocentric_from_wgs84()
+ /* ellipsoidal (geodetic) height */
+ Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - es * SPHI0 * SPHI0);
+
+ RK = es * RN / (RN + Height);
+ RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST);
+ CPHI = ST * (1.0 - RK) * RX;
+ SPHI = CT * RX;
+ SDPHI = SPHI * CPHI0 - CPHI * SPHI0;
+ CPHI0 = CPHI;
+ SPHI0 = SPHI;
}
-};
+ while (SDPHI * SDPHI > genau2 && iter < maxiter);
+
+ /* ellipsoidal (geodetic) latitude */
+ Latitude = Math.atan(SPHI / Math.abs(CPHI));
+ return {
+ x: Longitude,
+ y: Latitude,
+ z: Height
+ };
+}; // cs_geocentric_to_geodetic()
+
+
+/****************************************************************/
+// pj_geocentic_to_wgs84( p )
+// p = point to transform in geocentric coordinates (x,y,z)
+
/** point object, nothing fancy, just allows values to be
passed back and forth by reference rather than by value.
Other point classes may be used as long as they have
x and y properties, which will get modified in the transform method.
*/
-module.exports = datum;
+exports.geocentricToWgs84 = function(p, datum_type, datum_params) {
+
+ if (datum_type === PJD_3PARAM) {
+ // if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: p.x + datum_params[0],
+ y: p.y + datum_params[1],
+ z: p.z + datum_params[2],
+ };
+ } else if (datum_type === PJD_7PARAM) {
+ var Dx_BF = datum_params[0];
+ var Dy_BF = datum_params[1];
+ var Dz_BF = datum_params[2];
+ var Rx_BF = datum_params[3];
+ var Ry_BF = datum_params[4];
+ var Rz_BF = datum_params[5];
+ var M_BF = datum_params[6];
+ // if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF,
+ y: M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF,
+ z: M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF
+ };
+ }
+}; // cs_geocentric_to_wgs84
+
+/****************************************************************/
+// pj_geocentic_from_wgs84()
+// coordinate system definition,
+// point to transform in geocentric coordinates (x,y,z)
+exports.geocentricFromWgs84 = function(p, datum_type, datum_params) {
+
+ if (datum_type === PJD_3PARAM) {
+ //if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: p.x - datum_params[0],
+ y: p.y - datum_params[1],
+ z: p.z - datum_params[2],
+ };
+
+ } else if (datum_type === PJD_7PARAM) {
+ var Dx_BF = datum_params[0];
+ var Dy_BF = datum_params[1];
+ var Dz_BF = datum_params[2];
+ var Rx_BF = datum_params[3];
+ var Ry_BF = datum_params[4];
+ var Rz_BF = datum_params[5];
+ var M_BF = datum_params[6];
+ var x_tmp = (p.x - Dx_BF) / M_BF;
+ var y_tmp = (p.y - Dy_BF) / M_BF;
+ var z_tmp = (p.z - Dz_BF) / M_BF;
+ //if( x[io] === HUGE_VAL )
+ // continue;
+
+ return {
+ x: x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp,
+ y: -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp,
+ z: Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp
+ };
+ } //cs_geocentric_from_wgs84()
+};
-},{}],31:[function(require,module,exports){
+},{}],33:[function(require,module,exports){
var PJD_3PARAM = 1;
var PJD_7PARAM = 2;
-var PJD_GRIDSHIFT = 3;
var PJD_NODATUM = 5; // WGS84 or equivalent
-var SRS_WGS84_SEMIMAJOR = 6378137; // only used in grid shift transforms
-var SRS_WGS84_ESQUARED = 0.006694379990141316; //DGR: 2012-07-29
+var datum = require('./datumUtils');
+function checkParams(type) {
+ return (type === PJD_3PARAM || type === PJD_7PARAM);
+}
module.exports = function(source, dest, point) {
- var wp, i, l;
-
- function checkParams(fallback) {
- return (fallback === PJD_3PARAM || fallback === PJD_7PARAM);
- }
// Short cut if the datums are identical.
- if (source.compare_datums(dest)) {
+ if (datum.compareDatums(source, dest)) {
return point; // in this case, zero is sucess,
// whereas cs_compare_datums returns 1 to indicate TRUE
// confusing, should fix this
@@ -1180,83 +1121,27 @@ module.exports = function(source, dest, point) {
return point;
}
- //DGR: 2012-07-29 : add nadgrids support (begin)
- var src_a = source.a;
- var src_es = source.es;
+ // If this datum requires grid shifts, then apply it to geodetic coordinates.
- var dst_a = dest.a;
- var dst_es = dest.es;
+ // Do we need to go through geocentric coordinates?
+ if (source.es === dest.es && source.a === dest.a && !checkParams(source.datum_type) && !checkParams(dest.datum_type)) {
+ return point;
+ }
- var fallback = source.datum_type;
- // If this datum requires grid shifts, then apply it to geodetic coordinates.
- if (fallback === PJD_GRIDSHIFT) {
- if (this.apply_gridshift(source, 0, point) === 0) {
- source.a = SRS_WGS84_SEMIMAJOR;
- source.es = SRS_WGS84_ESQUARED;
- }
- else {
- // try 3 or 7 params transformation or nothing ?
- if (!source.datum_params) {
- source.a = src_a;
- source.es = source.es;
- return point;
- }
- wp = 1;
- for (i = 0, l = source.datum_params.length; i < l; i++) {
- wp *= source.datum_params[i];
- }
- if (wp === 0) {
- source.a = src_a;
- source.es = source.es;
- return point;
- }
- if (source.datum_params.length > 3) {
- fallback = PJD_7PARAM;
- }
- else {
- fallback = PJD_3PARAM;
- }
- }
+ // Convert to geocentric coordinates.
+ point = datum.geodeticToGeocentric(point, source.es, source.a);
+ // Convert between datums
+ if (checkParams(source.datum_type)) {
+ point = datum.geocentricToWgs84(point, source.datum_type, source.datum_params);
}
- if (dest.datum_type === PJD_GRIDSHIFT) {
- dest.a = SRS_WGS84_SEMIMAJOR;
- dest.es = SRS_WGS84_ESQUARED;
+ if (checkParams(dest.datum_type)) {
+ point = datum.geocentricFromWgs84(point, dest.datum_type, dest.datum_params);
}
- // Do we need to go through geocentric coordinates?
- if (source.es !== dest.es || source.a !== dest.a || checkParams(fallback) || checkParams(dest.datum_type)) {
- //DGR: 2012-07-29 : add nadgrids support (end)
- // Convert to geocentric coordinates.
- source.geodetic_to_geocentric(point);
- // CHECK_RETURN;
- // Convert between datums
- if (checkParams(source.datum_type)) {
- source.geocentric_to_wgs84(point);
- // CHECK_RETURN;
- }
- if (checkParams(dest.datum_type)) {
- dest.geocentric_from_wgs84(point);
- // CHECK_RETURN;
- }
- // Convert back to geodetic coordinates
- dest.geocentric_to_geodetic(point);
- // CHECK_RETURN;
- }
- // Apply grid shift to destination if required
- if (dest.datum_type === PJD_GRIDSHIFT) {
- this.apply_gridshift(dest, 1, point);
- // CHECK_RETURN;
- }
-
- source.a = src_a;
- source.es = src_es;
- dest.a = dst_a;
- dest.es = dst_es;
+ return datum.geocentricToGeodetic(point, dest.es, dest.a, dest.b);
- return point;
};
-
-},{}],32:[function(require,module,exports){
+},{"./datumUtils":32}],34:[function(require,module,exports){
var globals = require('./global');
var parseProj = require('./projString');
var wkt = require('./wkt');
@@ -1313,65 +1198,62 @@ function defs(name) {
globals(defs);
module.exports = defs;
-},{"./global":35,"./projString":38,"./wkt":67}],33:[function(require,module,exports){
-var Datum = require('./constants/Datum');
-var Ellipsoid = require('./constants/Ellipsoid');
-var extend = require('./extend');
-var datum = require('./datum');
-var EPSLN = 1.0e-10;
+},{"./global":37,"./projString":40,"./wkt":69}],35:[function(require,module,exports){
// ellipoid pj_set_ell.c
var SIXTH = 0.1666666666666666667;
/* 1/6 */
var RA4 = 0.04722222222222222222;
/* 17/360 */
var RA6 = 0.02215608465608465608;
-module.exports = function(json) {
- // DGR 2011-03-20 : nagrids -> nadgrids
- if (json.datumCode && json.datumCode !== 'none') {
- var datumDef = Datum[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;
- }
- }
- if (!json.a) { // do we have an ellipsoid?
- var ellipse = Ellipsoid[json.ellps] ? Ellipsoid[json.ellps] : Ellipsoid.WGS84;
- extend(json, ellipse);
- }
- if (json.rf && !json.b) {
- json.b = (1.0 - 1.0 / json.rf) * json.a;
- }
- if (json.rf === 0 || Math.abs(json.a - json.b) < EPSLN) {
- json.sphere = true;
- json.b = json.a;
- }
- json.a2 = json.a * json.a; // used in geocentric
- json.b2 = json.b * json.b; // used in geocentric
- json.es = (json.a2 - json.b2) / json.a2; // e ^ 2
- json.e = Math.sqrt(json.es); // eccentricity
- if (json.R_A) {
- json.a *= 1 - json.es * (SIXTH + json.es * (RA4 + json.es * RA6));
- json.a2 = json.a * json.a;
- json.b2 = json.b * json.b;
- json.es = 0;
- }
- json.ep2 = (json.a2 - json.b2) / json.b2; // used in geocentric
- if (!json.k0) {
- json.k0 = 1.0; //default value
+var EPSLN = 1.0e-10;
+var Ellipsoid = require('./constants/Ellipsoid');
+
+exports.eccentricity = function(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
}
- //DGR 2010-11-12: axis
- if (!json.axis) {
- json.axis = "enu";
+ var ep2 = (a2 - b2) / b2; // used in geocentric
+ return {
+ es: es,
+ e: e,
+ ep2: ep2
+ };
+};
+exports.sphere = function (a, b, rf, ellps, sphere) {
+ if (!a) { // do we have an ellipsoid?
+ var ellipse = Ellipsoid[ellps];
+ if (!ellipse) {
+ ellipse = Ellipsoid.WGS84;
+ }
+ a = ellipse.a;
+ b = ellipse.b;
+ rf = ellipse.rf;
}
- if (!json.datum) {
- json.datum = datum(json);
+ if (rf && !b) {
+ b = (1.0 - 1.0 / rf) * a;
+ }
+ if (rf === 0 || Math.abs(a - b) < EPSLN) {
+ sphere = true;
+ b = a;
}
- return json;
+ return {
+ a: a,
+ b: b,
+ rf: rf,
+ sphere: sphere
+ };
};
-},{"./constants/Datum":25,"./constants/Ellipsoid":26,"./datum":30,"./extend":34}],34:[function(require,module,exports){
+},{"./constants/Ellipsoid":27}],36:[function(require,module,exports){
module.exports = function(destination, source) {
destination = destination || {};
var value, property;
@@ -1387,7 +1269,7 @@ module.exports = function(destination, source) {
return destination;
};
-},{}],35:[function(require,module,exports){
+},{}],37:[function(require,module,exports){
module.exports = 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");
@@ -1400,20 +1282,21 @@ module.exports = function(defs) {
defs['EPSG:102113'] = defs['EPSG:3857'];
};
-},{}],36:[function(require,module,exports){
+},{}],38:[function(require,module,exports){
var proj4 = require('./core');
proj4.defaultDatum = 'WGS84'; //default datum
proj4.Proj = require('./Proj');
proj4.WGS84 = new proj4.Proj('WGS84');
proj4.Point = require('./Point');
-proj4.toPoint = require("./common/toPoint");
+proj4.toPoint = require('./common/toPoint');
proj4.defs = require('./defs');
proj4.transform = require('./transform');
proj4.mgrs = require('mgrs');
-proj4.version = require('../package.json').version;
+proj4.version = require('./version');
require('./includedProjections')(proj4);
module.exports = proj4;
-},{"../package.json":69,"./Point":1,"./Proj":2,"./common/toPoint":23,"./core":29,"./defs":32,"./includedProjections":"./includedProjections","./transform":66,"mgrs":68}],37:[function(require,module,exports){
+
+},{"./Point":1,"./Proj":2,"./common/toPoint":24,"./core":30,"./defs":34,"./includedProjections":"./includedProjections","./transform":68,"./version":"./lib/version","mgrs":70}],39:[function(require,module,exports){
var defs = require('./defs');
var wkt = require('./wkt');
var projStr = require('./projString');
@@ -1423,11 +1306,12 @@ function testObj(code){
function testDef(code){
return code in defs;
}
+var codeWords = ['GEOGCS','GEOCCS','PROJCS','LOCAL_CS'];
+
function testWKT(code){
- var codeWords = ['GEOGCS','GEOCCS','PROJCS','LOCAL_CS'];
- return codeWords.reduce(function(a,b){
- return a+1+code.indexOf(b);
- },0);
+ return codeWords.some(function (word) {
+ return code.indexOf(word) > -1;
+ });
}
function testProj(code){
return code[0] === '+';
@@ -1438,10 +1322,10 @@ function parse(code){
if (testDef(code)) {
return defs[code];
}
- else if (testWKT(code)) {
+ if (testWKT(code)) {
return wkt(code);
}
- else if (testProj(code)) {
+ if (testProj(code)) {
return projStr(code);
}
}else{
@@ -1450,23 +1334,24 @@ function parse(code){
}
module.exports = parse;
-},{"./defs":32,"./projString":38,"./wkt":67}],38:[function(require,module,exports){
+
+},{"./defs":34,"./projString":40,"./wkt":69}],40:[function(require,module,exports){
var D2R = 0.01745329251994329577;
var PrimeMeridian = require('./constants/PrimeMeridian');
var units = require('./constants/units');
module.exports = function(defData) {
var self = {};
- var paramObj = {};
- defData.split("+").map(function(v) {
+ var paramObj = defData.split('+').map(function(v) {
return v.trim();
}).filter(function(a) {
return a;
- }).forEach(function(a) {
- var split = a.split("=");
+ }).reduce(function(p, a) {
+ var split = a.split('=');
split.push(true);
- paramObj[split[0].toLowerCase()] = split[1];
- });
+ p[split[0].toLowerCase()] = split[1];
+ return p;
+ }, {});
var paramName, paramVal, paramOutname;
var params = {
proj: 'projName',
@@ -1584,7 +1469,7 @@ module.exports = function(defData) {
return self;
};
-},{"./constants/PrimeMeridian":27,"./constants/units":28}],39:[function(require,module,exports){
+},{"./constants/PrimeMeridian":28,"./constants/units":29}],41:[function(require,module,exports){
var projs = [
require('./projections/merc'),
require('./projections/longlat')
@@ -1620,7 +1505,7 @@ exports.start = function() {
projs.forEach(add);
};
-},{"./projections/longlat":51,"./projections/merc":52}],40:[function(require,module,exports){
+},{"./projections/longlat":53,"./projections/merc":54}],42:[function(require,module,exports){
var EPSLN = 1.0e-10;
var msfnz = require('../common/msfnz');
var qsfnz = require('../common/qsfnz');
@@ -1743,7 +1628,7 @@ exports.phi1z = function(eccent, qs) {
};
exports.names = ["Albers_Conic_Equal_Area", "Albers", "aea"];
-},{"../common/adjust_lon":5,"../common/asinz":6,"../common/msfnz":15,"../common/qsfnz":20}],41:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/asinz":7,"../common/msfnz":16,"../common/qsfnz":21}],43:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var HALF_PI = Math.PI/2;
var EPSLN = 1.0e-10;
@@ -1942,7 +1827,7 @@ exports.inverse = function(p) {
};
exports.names = ["Azimuthal_Equidistant", "aeqd"];
-},{"../common/adjust_lon":5,"../common/asinz":6,"../common/e0fn":7,"../common/e1fn":8,"../common/e2fn":9,"../common/e3fn":10,"../common/gN":11,"../common/imlfn":12,"../common/mlfn":14}],42:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/asinz":7,"../common/e0fn":8,"../common/e1fn":9,"../common/e2fn":10,"../common/e3fn":11,"../common/gN":12,"../common/imlfn":13,"../common/mlfn":15}],44:[function(require,module,exports){
var mlfn = require('../common/mlfn');
var e0fn = require('../common/e0fn');
var e1fn = require('../common/e1fn');
@@ -2046,7 +1931,7 @@ exports.inverse = function(p) {
};
exports.names = ["Cassini", "Cassini_Soldner", "cass"];
-},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":7,"../common/e1fn":8,"../common/e2fn":9,"../common/e3fn":10,"../common/gN":11,"../common/imlfn":12,"../common/mlfn":14}],43:[function(require,module,exports){
+},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":8,"../common/e1fn":9,"../common/e2fn":10,"../common/e3fn":11,"../common/gN":12,"../common/imlfn":13,"../common/mlfn":15}],45:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var qsfnz = require('../common/qsfnz');
var msfnz = require('../common/msfnz');
@@ -2111,7 +1996,7 @@ exports.inverse = function(p) {
};
exports.names = ["cea"];
-},{"../common/adjust_lon":5,"../common/iqsfnz":13,"../common/msfnz":15,"../common/qsfnz":20}],44:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/iqsfnz":14,"../common/msfnz":16,"../common/qsfnz":21}],46:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var adjust_lat = require('../common/adjust_lat');
exports.init = function() {
@@ -2154,7 +2039,7 @@ exports.inverse = function(p) {
};
exports.names = ["Equirectangular", "Equidistant_Cylindrical", "eqc"];
-},{"../common/adjust_lat":4,"../common/adjust_lon":5}],45:[function(require,module,exports){
+},{"../common/adjust_lat":4,"../common/adjust_lon":5}],47:[function(require,module,exports){
var e0fn = require('../common/e0fn');
var e1fn = require('../common/e1fn');
var e2fn = require('../common/e2fn');
@@ -2266,7 +2151,7 @@ exports.inverse = function(p) {
};
exports.names = ["Equidistant_Conic", "eqdc"];
-},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":7,"../common/e1fn":8,"../common/e2fn":9,"../common/e3fn":10,"../common/imlfn":12,"../common/mlfn":14,"../common/msfnz":15}],46:[function(require,module,exports){
+},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":8,"../common/e1fn":9,"../common/e2fn":10,"../common/e3fn":11,"../common/imlfn":13,"../common/mlfn":15,"../common/msfnz":16}],48:[function(require,module,exports){
var FORTPI = Math.PI/4;
var srat = require('../common/srat');
var HALF_PI = Math.PI/2;
@@ -2313,7 +2198,7 @@ exports.inverse = function(p) {
};
exports.names = ["gauss"];
-},{"../common/srat":22}],47:[function(require,module,exports){
+},{"../common/srat":23}],49:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var EPSLN = 1.0e-10;
var asinz = require('../common/asinz');
@@ -2414,7 +2299,7 @@ exports.inverse = function(p) {
};
exports.names = ["gnom"];
-},{"../common/adjust_lon":5,"../common/asinz":6}],48:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/asinz":7}],50:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
exports.init = function() {
this.a = 6377397.155;
@@ -2514,7 +2399,7 @@ exports.inverse = function(p) {
};
exports.names = ["Krovak", "krovak"];
-},{"../common/adjust_lon":5}],49:[function(require,module,exports){
+},{"../common/adjust_lon":5}],51:[function(require,module,exports){
var HALF_PI = Math.PI/2;
var FORTPI = Math.PI/4;
var EPSLN = 1.0e-10;
@@ -2804,7 +2689,7 @@ exports.authlat = function(beta, APA) {
};
exports.names = ["Lambert Azimuthal Equal Area", "Lambert_Azimuthal_Equal_Area", "laea"];
-},{"../common/adjust_lon":5,"../common/qsfnz":20}],50:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/qsfnz":21}],52:[function(require,module,exports){
var EPSLN = 1.0e-10;
var msfnz = require('../common/msfnz');
var tsfnz = require('../common/tsfnz');
@@ -2941,7 +2826,7 @@ exports.inverse = function(p) {
exports.names = ["Lambert Tangential Conformal Conic Projection", "Lambert_Conformal_Conic", "Lambert_Conformal_Conic_2SP", "lcc"];
-},{"../common/adjust_lon":5,"../common/msfnz":15,"../common/phi2z":16,"../common/sign":21,"../common/tsfnz":24}],51:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/msfnz":16,"../common/phi2z":17,"../common/sign":22,"../common/tsfnz":25}],53:[function(require,module,exports){
exports.init = function() {
//no-op for longlat
};
@@ -2953,7 +2838,7 @@ exports.forward = identity;
exports.inverse = identity;
exports.names = ["longlat", "identity"];
-},{}],52:[function(require,module,exports){
+},{}],54:[function(require,module,exports){
var msfnz = require('../common/msfnz');
var HALF_PI = Math.PI/2;
var EPSLN = 1.0e-10;
@@ -3052,7 +2937,7 @@ exports.inverse = function(p) {
exports.names = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"];
-},{"../common/adjust_lon":5,"../common/msfnz":15,"../common/phi2z":16,"../common/tsfnz":24}],53:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/msfnz":16,"../common/phi2z":17,"../common/tsfnz":25}],55:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
/*
reference
@@ -3099,7 +2984,7 @@ exports.inverse = function(p) {
};
exports.names = ["Miller_Cylindrical", "mill"];
-},{"../common/adjust_lon":5}],54:[function(require,module,exports){
+},{"../common/adjust_lon":5}],56:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var EPSLN = 1.0e-10;
exports.init = function() {};
@@ -3178,7 +3063,7 @@ exports.inverse = function(p) {
};
exports.names = ["Mollweide", "moll"];
-},{"../common/adjust_lon":5}],55:[function(require,module,exports){
+},{"../common/adjust_lon":5}],57:[function(require,module,exports){
var SEC_TO_RAD = 4.84813681109535993589914102357e-6;
/*
reference
@@ -3398,7 +3283,7 @@ exports.inverse = function(p) {
return p;
};
exports.names = ["New_Zealand_Map_Grid", "nzmg"];
-},{}],56:[function(require,module,exports){
+},{}],58:[function(require,module,exports){
var tsfnz = require('../common/tsfnz');
var adjust_lon = require('../common/adjust_lon');
var phi2z = require('../common/phi2z');
@@ -3567,7 +3452,7 @@ exports.inverse = function(p) {
};
exports.names = ["Hotine_Oblique_Mercator", "Hotine Oblique Mercator", "Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "Hotine_Oblique_Mercator_Azimuth_Center", "omerc"];
-},{"../common/adjust_lon":5,"../common/phi2z":16,"../common/tsfnz":24}],57:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/phi2z":17,"../common/tsfnz":25}],59:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var EPSLN = 1.0e-10;
var asinz = require('../common/asinz');
@@ -3655,7 +3540,7 @@ exports.inverse = function(p) {
};
exports.names = ["ortho"];
-},{"../common/adjust_lon":5,"../common/asinz":6}],58:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/asinz":7}],60:[function(require,module,exports){
var e0fn = require('../common/e0fn');
var e1fn = require('../common/e1fn');
var e2fn = require('../common/e2fn');
@@ -3784,7 +3669,7 @@ exports.inverse = function(p) {
return p;
};
exports.names = ["Polyconic", "poly"];
-},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":7,"../common/e1fn":8,"../common/e2fn":9,"../common/e3fn":10,"../common/gN":11,"../common/mlfn":14}],59:[function(require,module,exports){
+},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/e0fn":8,"../common/e1fn":9,"../common/e2fn":10,"../common/e3fn":11,"../common/gN":12,"../common/mlfn":15}],61:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var adjust_lat = require('../common/adjust_lat');
var pj_enfn = require('../common/pj_enfn');
@@ -3891,7 +3776,7 @@ exports.inverse = function(p) {
return p;
};
exports.names = ["Sinusoidal", "sinu"];
-},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/asinz":6,"../common/pj_enfn":17,"../common/pj_inv_mlfn":18,"../common/pj_mlfn":19}],60:[function(require,module,exports){
+},{"../common/adjust_lat":4,"../common/adjust_lon":5,"../common/asinz":7,"../common/pj_enfn":18,"../common/pj_inv_mlfn":19,"../common/pj_mlfn":20}],62:[function(require,module,exports){
/*
references:
Formules et constantes pour le Calcul pour la
@@ -3973,7 +3858,7 @@ exports.inverse = function(p) {
exports.names = ["somerc"];
-},{}],61:[function(require,module,exports){
+},{}],63:[function(require,module,exports){
var HALF_PI = Math.PI/2;
var EPSLN = 1.0e-10;
var sign = require('../common/sign');
@@ -4141,7 +4026,7 @@ exports.inverse = function(p) {
};
exports.names = ["stere", "Stereographic_South_Pole", "Polar Stereographic (variant B)"];
-},{"../common/adjust_lon":5,"../common/msfnz":15,"../common/phi2z":16,"../common/sign":21,"../common/tsfnz":24}],62:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/msfnz":16,"../common/phi2z":17,"../common/sign":22,"../common/tsfnz":25}],64:[function(require,module,exports){
var gauss = require('./gauss');
var adjust_lon = require('../common/adjust_lon');
exports.init = function() {
@@ -4200,24 +4085,28 @@ exports.inverse = function(p) {
exports.names = ["Stereographic_North_Pole", "Oblique_Stereographic", "Polar_Stereographic", "sterea","Oblique Stereographic Alternative"];
-},{"../common/adjust_lon":5,"./gauss":46}],63:[function(require,module,exports){
-var e0fn = require('../common/e0fn');
-var e1fn = require('../common/e1fn');
-var e2fn = require('../common/e2fn');
-var e3fn = require('../common/e3fn');
-var mlfn = require('../common/mlfn');
+},{"../common/adjust_lon":5,"./gauss":48}],65:[function(require,module,exports){
+// Heavily based on this tmerc projection implementation
+// https://github.com/mbloch/mapshaper-proj/blob/master/src/projections/tmerc.js
+
+var pj_enfn = require('../common/pj_enfn');
+var pj_mlfn = require('../common/pj_mlfn');
+var pj_inv_mlfn = require('../common/pj_inv_mlfn');
var adjust_lon = require('../common/adjust_lon');
-var HALF_PI = Math.PI/2;
+var HALF_PI = Math.PI / 2;
var EPSLN = 1.0e-10;
var sign = require('../common/sign');
-var asinz = require('../common/asinz');
exports.init = function() {
- 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);
+ this.x0 = this.x0 !== undefined ? this.x0 : 0;
+ this.y0 = this.y0 !== undefined ? this.y0 : 0;
+ this.long0 = this.long0 !== undefined ? this.long0 : 0;
+ this.lat0 = this.lat0 !== undefined ? this.lat0 : 0;
+
+ if (this.es) {
+ this.en = pj_enfn(this.es);
+ this.ml0 = pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en);
+ }
};
/**
@@ -4234,36 +4123,65 @@ exports.forward = function(p) {
var sin_phi = Math.sin(lat);
var cos_phi = Math.cos(lat);
- if (this.sphere) {
+ if (!this.es) {
var b = cos_phi * Math.sin(delta_lon);
- if ((Math.abs(Math.abs(b) - 1)) < 0.0000000001) {
+
+ if ((Math.abs(Math.abs(b) - 1)) < EPSLN) {
return (93);
}
else {
- x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b));
- con = Math.acos(cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - b * b));
+ x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b)) + this.x0;
+ y = cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - Math.pow(b, 2));
+ b = Math.abs(y);
+
+ if (b >= 1) {
+ if ((b - 1) > EPSLN) {
+ return (93);
+ }
+ else {
+ y = 0;
+ }
+ }
+ else {
+ y = Math.acos(y);
+ }
+
if (lat < 0) {
- con = -con;
+ y = -y;
}
- y = this.a * this.k0 * (con - this.lat0);
+
+ y = this.a * this.k0 * (y - this.lat0) + this.y0;
}
}
else {
var al = cos_phi * delta_lon;
var als = Math.pow(al, 2);
var c = this.ep2 * Math.pow(cos_phi, 2);
- var tq = Math.tan(lat);
+ var cs = Math.pow(c, 2);
+ var tq = Math.abs(cos_phi) > EPSLN ? Math.tan(lat) : 0;
var t = Math.pow(tq, 2);
+ var ts = Math.pow(t, 2);
con = 1 - this.es * Math.pow(sin_phi, 2);
- var n = this.a / Math.sqrt(con);
- var ml = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat);
+ al = al / Math.sqrt(con);
+ var ml = pj_mlfn(lat, sin_phi, cos_phi, this.en);
- x = this.k0 * n * al * (1 + als / 6 * (1 - t + c + als / 20 * (5 - 18 * t + Math.pow(t, 2) + 72 * c - 58 * this.ep2))) + this.x0;
- y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24 * (5 - t + 9 * c + 4 * Math.pow(c, 2) + als / 30 * (61 - 58 * t + Math.pow(t, 2) + 600 * c - 330 * this.ep2))))) + this.y0;
+ x = this.a * (this.k0 * al * (1 +
+ als / 6 * (1 - t + c +
+ als / 20 * (5 - 18 * t + ts + 14 * c - 58 * t * c +
+ als / 42 * (61 + 179 * ts - ts * t - 479 * t))))) +
+ this.x0;
+ y = this.a * (this.k0 * (ml - this.ml0 +
+ sin_phi * delta_lon * al / 2 * (1 +
+ als / 12 * (5 - t + 9 * c + 4 * cs +
+ als / 30 * (61 + ts - 58 * t + 270 * c - 330 * t * c +
+ als / 56 * (1385 + 543 * ts - ts * t - 3111 * t)))))) +
+ this.y0;
}
+
p.x = x;
p.y = y;
+
return p;
};
@@ -4272,81 +4190,84 @@ exports.forward = function(p) {
*/
exports.inverse = function(p) {
var con, phi;
- var delta_phi;
- var i;
- var max_iter = 6;
var lat, lon;
+ var x = (p.x - this.x0) * (1 / this.a);
+ var y = (p.y - this.y0) * (1 / this.a);
- if (this.sphere) {
- var f = Math.exp(p.x / (this.a * this.k0));
+ if (!this.es) {
+ var f = Math.exp(x / this.k0);
var g = 0.5 * (f - 1 / f);
- var temp = this.lat0 + p.y / (this.a * this.k0);
+ var temp = this.lat0 + y / this.k0;
var h = Math.cos(temp);
- con = Math.sqrt((1 - h * h) / (1 + g * g));
- lat = asinz(con);
- if (temp < 0) {
+ con = Math.sqrt((1 - Math.pow(h, 2)) / (1 + Math.pow(g, 2)));
+ lat = Math.asin(con);
+
+ if (y < 0) {
lat = -lat;
}
+
if ((g === 0) && (h === 0)) {
- lon = this.long0;
+ lon = 0;
}
else {
lon = adjust_lon(Math.atan2(g, h) + this.long0);
}
}
else { // ellipsoidal form
- var x = p.x - this.x0;
- var y = p.y - this.y0;
-
- con = (this.ml0 + y / this.k0) / this.a;
- phi = con;
- for (i = 0; true; i++) {
- delta_phi = ((con + this.e1 * Math.sin(2 * phi) - this.e2 * Math.sin(4 * phi) + this.e3 * Math.sin(6 * phi)) / this.e0) - phi;
- phi += delta_phi;
- if (Math.abs(delta_phi) <= EPSLN) {
- break;
- }
- if (i >= max_iter) {
- return (95);
- }
- } // for()
+ con = this.ml0 + y / this.k0;
+ phi = pj_inv_mlfn(con, this.es, this.en);
+
if (Math.abs(phi) < HALF_PI) {
var sin_phi = Math.sin(phi);
var cos_phi = Math.cos(phi);
- var tan_phi = Math.tan(phi);
+ var tan_phi = Math.abs(cos_phi) > EPSLN ? Math.tan(phi) : 0;
var c = this.ep2 * Math.pow(cos_phi, 2);
var cs = Math.pow(c, 2);
var t = Math.pow(tan_phi, 2);
var ts = Math.pow(t, 2);
con = 1 - this.es * Math.pow(sin_phi, 2);
- var n = this.a / Math.sqrt(con);
- var r = n * (1 - this.es) / con;
- var d = x / (n * this.k0);
+ var d = x * Math.sqrt(con) / this.k0;
var ds = Math.pow(d, 2);
- lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24 * (5 + 3 * t + 10 * c - 4 * cs - 9 * this.ep2 - ds / 30 * (61 + 90 * t + 298 * c + 45 * ts - 252 * this.ep2 - 3 * cs)));
- lon = adjust_lon(this.long0 + (d * (1 - ds / 6 * (1 + 2 * t + c - ds / 20 * (5 - 2 * c + 28 * t - 3 * cs + 8 * this.ep2 + 24 * ts))) / cos_phi));
+ con = con * tan_phi;
+
+ lat = phi - (con * ds / (1 - this.es)) * 0.5 * (1 -
+ ds / 12 * (5 + 3 * t - 9 * c * t + c - 4 * cs -
+ ds / 30 * (61 + 90 * t - 252 * c * t + 45 * ts + 46 * c -
+ ds / 56 * (1385 + 3633 * t + 4095 * ts + 1574 * ts * t))));
+
+ lon = adjust_lon(this.long0 + (d * (1 -
+ ds / 6 * (1 + 2 * t + c -
+ ds / 20 * (5 + 28 * t + 24 * ts + 8 * c * t + 6 * c -
+ ds / 42 * (61 + 662 * t + 1320 * ts + 720 * ts * t)))) / cos_phi));
}
else {
lat = HALF_PI * sign(y);
- lon = this.long0;
+ lon = 0;
}
}
+
p.x = lon;
p.y = lat;
+
return p;
};
+
exports.names = ["Transverse_Mercator", "Transverse Mercator", "tmerc"];
-},{"../common/adjust_lon":5,"../common/asinz":6,"../common/e0fn":7,"../common/e1fn":8,"../common/e2fn":9,"../common/e3fn":10,"../common/mlfn":14,"../common/sign":21}],64:[function(require,module,exports){
-var D2R = 0.01745329251994329577;
+},{"../common/adjust_lon":5,"../common/pj_enfn":18,"../common/pj_inv_mlfn":19,"../common/pj_mlfn":20,"../common/sign":22}],66:[function(require,module,exports){
+var adjust_zone = require('../common/adjust_zone');
var tmerc = require('./tmerc');
+
exports.dependsOn = 'tmerc';
+
exports.init = function() {
- if (!this.zone) {
+ var zone = adjust_zone(this.zone, this.long0);
+ if (!zone) {
return;
}
+
this.lat0 = 0;
- this.long0 = ((6 * Math.abs(this.zone)) - 183) * D2R;
+ this.long0 = (zone + 0.5) * Math.PI / 30 - Math.PI;
this.x0 = 500000;
this.y0 = this.utmSouth ? 10000000 : 0;
this.k0 = 0.9996;
@@ -4355,9 +4276,10 @@ exports.init = function() {
this.forward = tmerc.forward;
this.inverse = tmerc.inverse;
};
+
exports.names = ["Universal Transverse Mercator System", "utm"];
-},{"./tmerc":63}],65:[function(require,module,exports){
+},{"../common/adjust_zone":6,"./tmerc":65}],67:[function(require,module,exports){
var adjust_lon = require('../common/adjust_lon');
var HALF_PI = Math.PI/2;
var EPSLN = 1.0e-10;
@@ -4478,7 +4400,7 @@ exports.inverse = function(p) {
return p;
};
exports.names = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"];
-},{"../common/adjust_lon":5,"../common/asinz":6}],66:[function(require,module,exports){
+},{"../common/adjust_lon":5,"../common/asinz":7}],68:[function(require,module,exports){
var D2R = 0.01745329251994329577;
var R2D = 57.29577951308232088;
var PJD_3PARAM = 1;
@@ -4487,36 +4409,40 @@ var datum_transform = require('./datum_transform');
var adjust_axis = require('./adjust_axis');
var proj = require('./Proj');
var toPoint = require('./common/toPoint');
+function checkNotWGS(source, dest) {
+ return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== 'WGS84') || ((dest.datum.datum_type === PJD_3PARAM || dest.datum.datum_type === PJD_7PARAM) && source.datumCode !== 'WGS84');
+}
module.exports = function transform(source, dest, point) {
var wgs84;
if (Array.isArray(point)) {
point = toPoint(point);
}
- function checkNotWGS(source, dest) {
- return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== "WGS84");
- }
// Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
- if (source.datum && dest.datum && (checkNotWGS(source, dest) || checkNotWGS(dest, source))) {
+ if (source.datum && dest.datum && checkNotWGS(source, dest)) {
wgs84 = new proj('WGS84');
- transform(source, wgs84, point);
+ point = transform(source, wgs84, point);
source = wgs84;
}
// DGR, 2010/11/12
- if (source.axis !== "enu") {
- adjust_axis(source, false, point);
+ if (source.axis !== 'enu') {
+ point = adjust_axis(source, false, point);
}
// Transform source points to long/lat, if they aren't already.
- if (source.projName === "longlat") {
- point.x *= D2R; // convert degrees to radians
- point.y *= D2R;
+ if (source.projName === 'longlat') {
+ point = {
+ x: point.x * D2R,
+ y: point.y * D2R
+ };
}
else {
if (source.to_meter) {
- point.x *= source.to_meter;
- point.y *= source.to_meter;
+ point = {
+ x: point.x * source.to_meter,
+ y: point.y * source.to_meter
+ };
}
- source.inverse(point); // Convert Cartesian to longlat
+ point = source.inverse(point); // Convert Cartesian to longlat
}
// Adjust for the prime meridian if necessary
if (source.from_greenwich) {
@@ -4528,30 +4454,37 @@ module.exports = function transform(source, dest, point) {
// Adjust for the prime meridian if necessary
if (dest.from_greenwich) {
- point.x -= dest.from_greenwich;
+ point = {
+ x: point.x - dest.grom_greenwich,
+ y: point.y
+ };
}
- if (dest.projName === "longlat") {
+ if (dest.projName === 'longlat') {
// convert radians to decimal degrees
- point.x *= R2D;
- point.y *= R2D;
- }
- else { // else project
- dest.forward(point);
+ point = {
+ x: point.x * R2D,
+ y: point.y * R2D
+ };
+ } else { // else project
+ point = dest.forward(point);
if (dest.to_meter) {
- point.x /= dest.to_meter;
- point.y /= dest.to_meter;
+ point = {
+ x: point.x / dest.to_meter,
+ y: point.y / dest.to_meter
+ };
}
}
// DGR, 2010/11/12
- if (dest.axis !== "enu") {
- adjust_axis(dest, true, point);
+ if (dest.axis !== 'enu') {
+ return adjust_axis(dest, true, point);
}
return point;
};
-},{"./Proj":2,"./adjust_axis":3,"./common/toPoint":23,"./datum_transform":31}],67:[function(require,module,exports){
+
+},{"./Proj":2,"./adjust_axis":3,"./common/toPoint":24,"./datum_transform":33}],69:[function(require,module,exports){
var D2R = 0.01745329251994329577;
var extend = require('./extend');
@@ -4776,7 +4709,7 @@ module.exports = function(wkt, self) {
return extend(self, obj.output);
};
-},{"./extend":34}],68:[function(require,module,exports){
+},{"./extend":36}],70:[function(require,module,exports){
@@ -5520,52 +5453,5 @@ function getMinNorthing(zoneLetter) {
}
-},{}],69:[function(require,module,exports){
-module.exports={
- "name": "proj4",
- "version": "2.3.15",
- "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
- "main": "lib/index.js",
- "directories": {
- "test": "test",
- "doc": "docs"
- },
- "scripts": {
- "test": "./node_modules/istanbul/lib/cli.js test ./node_modules/mocha/bin/_mocha test/test.js"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/proj4js/proj4js.git"
- },
- "author": "",
- "license": "MIT",
- "jam": {
- "main": "dist/proj4.js",
- "include": [
- "dist/proj4.js",
- "README.md",
- "AUTHORS",
- "LICENSE.md"
- ]
- },
- "devDependencies": {
- "grunt-cli": "~0.1.13",
- "grunt": "~0.4.2",
- "grunt-contrib-connect": "~0.6.0",
- "grunt-contrib-jshint": "~0.8.0",
- "chai": "~1.8.1",
- "mocha": "~1.17.1",
- "grunt-mocha-phantomjs": "~0.4.0",
- "browserify": "~12.0.1",
- "grunt-browserify": "~4.0.1",
- "grunt-contrib-uglify": "~0.11.1",
- "curl": "git://github.com/cujojs/curl.git",
- "istanbul": "~0.2.4",
- "tin": "~0.4.0"
- },
- "dependencies": {
- "mgrs": "~0.0.2"
- }
-}
-},{}]},{},[36])(36)
+},{}]},{},[38])(38)
});
\ No newline at end of file
diff --git a/dist/test.html b/dist/test.html
deleted file mode 100644
index 89f04d8..0000000
--- a/dist/test.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<body>
- <div id="result"></div>
- <script src="proj4-src.js"></script>
- <script>
- document.getElementById('result').innerHTML =
- proj4('EPSG:4326', 'EPSG:3857', [16, 48]);
- </script>
-</body>
-</html>
-
diff --git a/lib/Proj.js b/lib/Proj.js
index f4a55bd..7bc65db 100644
--- a/lib/Proj.js
+++ b/lib/Proj.js
@@ -1,7 +1,10 @@
-var parseCode = require("./parseCode");
+var parseCode = require('./parseCode');
var extend = require('./extend');
var projections = require('./projections');
var deriveConstants = require('./deriveConstants');
+var Datum = require('./constants/Datum');
+var datum = require('./datum');
+
function Projection(srsCode,callback) {
if (!(this instanceof Projection)) {
@@ -17,16 +20,49 @@ function Projection(srsCode,callback) {
callback(srsCode);
return;
}
- var modifiedJSON = deriveConstants(json);
- var ourProj = Projection.projections.get(modifiedJSON.projName);
- if(ourProj){
- extend(this, modifiedJSON);
- extend(this, ourProj);
- this.init();
- callback(null, this);
- }else{
+ var ourProj = Projection.projections.get(json.projName);
+ if(!ourProj){
callback(srsCode);
+ return;
+ }
+ if (json.datumCode && json.datumCode !== 'none') {
+ var datumDef = Datum[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';
+
+ var sphere = deriveConstants.sphere(json.a, json.b, json.rf, json.ellps, json.sphere);
+ var ecc = deriveConstants.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;
Projection.projections.start();
diff --git a/lib/adjust_axis.js b/lib/adjust_axis.js
index 1690be1..8a84296 100644
--- a/lib/adjust_axis.js
+++ b/lib/adjust_axis.js
@@ -3,6 +3,7 @@ module.exports = function(crs, denorm, point) {
yin = point.y,
zin = point.z || 0.0;
var v, t, i;
+ var out = {};
for (i = 0; i < 3; i++) {
if (denorm && i === 2 && point.z === undefined) {
continue;
@@ -21,25 +22,25 @@ module.exports = function(crs, denorm, point) {
}
switch (crs.axis[i]) {
case 'e':
- point[t] = v;
+ out[t] = v;
break;
case 'w':
- point[t] = -v;
+ out[t] = -v;
break;
case 'n':
- point[t] = v;
+ out[t] = v;
break;
case 's':
- point[t] = -v;
+ out[t] = -v;
break;
case 'u':
if (point[t] !== undefined) {
- point.z = v;
+ out.z = v;
}
break;
case 'd':
if (point[t] !== undefined) {
- point.z = -v;
+ out.z = -v;
}
break;
default:
@@ -47,5 +48,5 @@ module.exports = function(crs, denorm, point) {
return null;
}
}
- return point;
+ return out;
};
diff --git a/lib/common/adjust_zone.js b/lib/common/adjust_zone.js
new file mode 100644
index 0000000..861773b
--- /dev/null
+++ b/lib/common/adjust_zone.js
@@ -0,0 +1,19 @@
+var adjust_lon = require('./adjust_lon');
+
+module.exports = function(zone, lon) {
+ if (!zone) {
+ zone = Math.floor((adjust_lon(lon) + Math.PI) * 30 / Math.PI);
+
+ if (zone < 0) {
+ return 0;
+ }
+ else if (zone >= 60) {
+ return 59;
+ }
+ }
+ else {
+ if (zone > 0 && zone <= 60) {
+ return zone - 1;
+ }
+ }
+};
diff --git a/lib/datum.js b/lib/datum.js
index 40d3328..a7391c5 100644
--- a/lib/datum.js
+++ b/lib/datum.js
@@ -1,403 +1,38 @@
-var HALF_PI = Math.PI/2;
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 SEC_TO_RAD = 4.84813681109535993589914102357e-6;
-var AD_C = 1.0026000;
-var COS_67P5 = 0.38268343236508977;
-var datum = function(proj) {
- if (!(this instanceof datum)) {
- return new datum(proj);
- }
- this.datum_type = PJD_WGS84; //default setting
- if (!proj) {
- return;
- }
- if (proj.datumCode && proj.datumCode === 'none') {
- this.datum_type = PJD_NODATUM;
- }
-
- if (proj.datum_params) {
- this.datum_params = proj.datum_params.map(parseFloat);
- if (this.datum_params[0] !== 0 || this.datum_params[1] !== 0 || this.datum_params[2] !== 0) {
- this.datum_type = PJD_3PARAM;
- }
- if (this.datum_params.length > 3) {
- if (this.datum_params[3] !== 0 || this.datum_params[4] !== 0 || this.datum_params[5] !== 0 || this.datum_params[6] !== 0) {
- this.datum_type = PJD_7PARAM;
- this.datum_params[3] *= SEC_TO_RAD;
- this.datum_params[4] *= SEC_TO_RAD;
- this.datum_params[5] *= SEC_TO_RAD;
- this.datum_params[6] = (this.datum_params[6] / 1000000.0) + 1.0;
- }
- }
- }
-
- // DGR 2011-03-21 : nadgrids support
- this.datum_type = proj.grids ? PJD_GRIDSHIFT : this.datum_type;
- this.a = proj.a; //datum object also uses these values
- this.b = proj.b;
- this.es = proj.es;
- this.ep2 = proj.ep2;
- if (this.datum_type === PJD_GRIDSHIFT) {
- this.grids = proj.grids;
+function datum(datumCode, datum_params, a, b, es, ep2) {
+ var out = {};
+ out.datum_type = PJD_WGS84; //default setting
+ if (datumCode && datumCode === 'none') {
+ out.datum_type = PJD_NODATUM;
}
-};
-datum.prototype = {
-
-
- /****************************************************************/
- // cs_compare_datums()
- // Returns TRUE if the two datums match, otherwise FALSE.
- compare_datums: function(dest) {
- if (this.datum_type !== dest.datum_type) {
- return false; // false, datums are not equal
- }
- else if (this.a !== dest.a || Math.abs(this.es - dest.es) > 0.000000000050) {
- // the tolerence for es is to ensure that GRS80 and WGS84
- // are considered identical
- return false;
- }
- else if (this.datum_type === PJD_3PARAM) {
- return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2]);
- }
- else if (this.datum_type === PJD_7PARAM) {
- return (this.datum_params[0] === dest.datum_params[0] && this.datum_params[1] === dest.datum_params[1] && this.datum_params[2] === dest.datum_params[2] && this.datum_params[3] === dest.datum_params[3] && this.datum_params[4] === dest.datum_params[4] && this.datum_params[5] === dest.datum_params[5] && this.datum_params[6] === dest.datum_params[6]);
- }
- else if (this.datum_type === PJD_GRIDSHIFT || dest.datum_type === PJD_GRIDSHIFT) {
- //alert("ERROR: Grid shift transformations are not implemented.");
- //return false
- //DGR 2012-07-29 lazy ...
- return this.nadgrids === dest.nadgrids;
- }
- 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)
- *
- */
- geodetic_to_geocentric: function(p) {
- var Longitude = p.x;
- var Latitude = p.y;
- var Height = p.z ? p.z : 0; //Z value not always supplied
- var X; // output
- var Y;
- var Z;
-
- var Error_Code = 0; // GEOCENT_NO_ERROR;
- 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 > HALF_PI)) {
- /* Latitude out of range */
- //..reportError('geocent:lat out of range:' + Latitude);
- return null;
- }
-
- 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 = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat));
- X = (Rn + Height) * Cos_Lat * Math.cos(Longitude);
- Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude);
- Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat;
-
- p.x = X;
- p.y = Y;
- p.z = Z;
- return Error_Code;
- }, // cs_geodetic_to_geocentric()
-
-
- geocentric_to_geodetic: function(p) {
- /* 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; /* cos of geocentric latitude */
- var RX;
- var RK;
- var RN; /* Earth radius at location */
- var CPHI0; /* cos of start or old geodetic latitude in iterations */
- var SPHI0; /* sin of start or old geodetic latitude in iterations */
- var CPHI; /* cos of searched geodetic latitude */
- var SPHI; /* sin of searched geodetic latitude */
- var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
- var At_Pole; /* indicates location is in polar region */
- var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
-
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0.0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
-
- At_Pole = false;
- P = Math.sqrt(X * X + Y * Y);
- RR = Math.sqrt(X * X + Y * Y + Z * Z);
-
- /* special cases for latitude and longitude */
- if (P / this.a < genau) {
-
- /* special case, if P=0. (X=0., Y=0.) */
- At_Pole = true;
- Longitude = 0.0;
- /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
- * of ellipsoid (=center of mass), Latitude becomes PI/2 */
- if (RR / this.a < genau) {
- Latitude = HALF_PI;
- Height = -this.b;
- return;
+ 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;
}
}
- else {
- /* ellipsoidal (geodetic) longitude
- * interval: -PI < Longitude <= +PI */
- Longitude = Math.atan2(Y, X);
- }
-
- /* --------------------------------------------------------------
- * Following iterative algorithm was developped by
- * "Institut for Erdmessung", University of Hannover, July 1988.
- * Internet: www.ife.uni-hannover.de
- * Iterative computation of CPHI,SPHI and Height.
- * Iteration of CPHI and SPHI to 10**-12 radian resp.
- * 2*10**-7 arcsec.
- * --------------------------------------------------------------
- */
- CT = Z / RR;
- ST = P / RR;
- RX = 1.0 / Math.sqrt(1.0 - this.es * (2.0 - this.es) * ST * ST);
- CPHI0 = ST * (1.0 - this.es) * RX;
- SPHI0 = CT * RX;
- iter = 0;
-
- /* loop to find sin(Latitude) resp. Latitude
- * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
- do {
- iter++;
- RN = this.a / Math.sqrt(1.0 - this.es * SPHI0 * SPHI0);
-
- /* ellipsoidal (geodetic) height */
- Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - this.es * SPHI0 * SPHI0);
-
- RK = this.es * RN / (RN + Height);
- RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST);
- CPHI = ST * (1.0 - RK) * RX;
- SPHI = CT * RX;
- SDPHI = SPHI * CPHI0 - CPHI * SPHI0;
- CPHI0 = CPHI;
- SPHI0 = SPHI;
- }
- while (SDPHI * SDPHI > genau2 && iter < maxiter);
-
- /* ellipsoidal (geodetic) latitude */
- Latitude = Math.atan(SPHI / Math.abs(CPHI));
-
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // cs_geocentric_to_geodetic()
-
- /** Convert_Geocentric_To_Geodetic
- * The method used here is derived from 'An Improved Algorithm for
- * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
- */
- geocentric_to_geodetic_noniter: function(p) {
- var X = p.x;
- var Y = p.y;
- var Z = p.z ? p.z : 0; //Z value not always supplied
- var Longitude;
- var Latitude;
- var Height;
-
- var W; /* distance from Z axis */
- var W2; /* square of distance from Z axis */
- var T0; /* initial estimate of vertical component */
- var T1; /* corrected estimate of vertical component */
- var S0; /* initial estimate of horizontal component */
- var S1; /* corrected estimate of horizontal component */
- var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */
- var Sin3_B0; /* cube of Math.sin(B0) */
- var Cos_B0; /* Math.cos(B0) */
- var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */
- var Cos_p1; /* Math.cos(phi1) */
- var Rn; /* Earth radius at location */
- var Sum; /* numerator of Math.cos(phi1) */
- var At_Pole; /* indicates location is in polar region */
-
- X = parseFloat(X); // cast from string to float
- Y = parseFloat(Y);
- Z = parseFloat(Z);
-
- At_Pole = false;
- if (X !== 0.0) {
- Longitude = Math.atan2(Y, X);
- }
- else {
- if (Y > 0) {
- Longitude = HALF_PI;
- }
- else if (Y < 0) {
- Longitude = -HALF_PI;
- }
- else {
- At_Pole = true;
- Longitude = 0.0;
- if (Z > 0.0) { /* north pole */
- Latitude = HALF_PI;
- }
- else if (Z < 0.0) { /* south pole */
- Latitude = -HALF_PI;
- }
- else { /* center of earth */
- Latitude = HALF_PI;
- Height = -this.b;
- return;
- }
- }
- }
- W2 = X * X + Y * Y;
- W = Math.sqrt(W2);
- T0 = Z * AD_C;
- S0 = Math.sqrt(T0 * T0 + W2);
- Sin_B0 = T0 / S0;
- Cos_B0 = W / S0;
- Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
- T1 = Z + this.b * this.ep2 * Sin3_B0;
- Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0;
- S1 = Math.sqrt(T1 * T1 + Sum * Sum);
- Sin_p1 = T1 / S1;
- Cos_p1 = Sum / S1;
- Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1);
- if (Cos_p1 >= COS_67P5) {
- Height = W / Cos_p1 - Rn;
- }
- else if (Cos_p1 <= -COS_67P5) {
- Height = W / -Cos_p1 - Rn;
- }
- else {
- Height = Z / Sin_p1 + Rn * (this.es - 1.0);
- }
- if (At_Pole === false) {
- Latitude = Math.atan(Sin_p1 / Cos_p1);
- }
-
- p.x = Longitude;
- p.y = Latitude;
- p.z = Height;
- return p;
- }, // geocentric_to_geodetic_noniter()
-
- /****************************************************************/
- // pj_geocentic_to_wgs84( p )
- // p = point to transform in geocentric coordinates (x,y,z)
- geocentric_to_wgs84: function(p) {
-
- if (this.datum_type === PJD_3PARAM) {
- // if( x[io] === HUGE_VAL )
- // continue;
- p.x += this.datum_params[0];
- p.y += this.datum_params[1];
- p.z += this.datum_params[2];
-
- }
- else if (this.datum_type === PJD_7PARAM) {
- var Dx_BF = this.datum_params[0];
- var Dy_BF = this.datum_params[1];
- var Dz_BF = this.datum_params[2];
- var Rx_BF = this.datum_params[3];
- var Ry_BF = this.datum_params[4];
- var Rz_BF = this.datum_params[5];
- var M_BF = this.datum_params[6];
- // if( x[io] === HUGE_VAL )
- // continue;
- var x_out = M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF;
- var y_out = M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF;
- var z_out = M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF;
- p.x = x_out;
- p.y = y_out;
- p.z = z_out;
- }
- }, // cs_geocentric_to_wgs84
-
- /****************************************************************/
- // pj_geocentic_from_wgs84()
- // coordinate system definition,
- // point to transform in geocentric coordinates (x,y,z)
- geocentric_from_wgs84: function(p) {
-
- if (this.datum_type === PJD_3PARAM) {
- //if( x[io] === HUGE_VAL )
- // continue;
- p.x -= this.datum_params[0];
- p.y -= this.datum_params[1];
- p.z -= this.datum_params[2];
+ }
- }
- else if (this.datum_type === PJD_7PARAM) {
- var Dx_BF = this.datum_params[0];
- var Dy_BF = this.datum_params[1];
- var Dz_BF = this.datum_params[2];
- var Rx_BF = this.datum_params[3];
- var Ry_BF = this.datum_params[4];
- var Rz_BF = this.datum_params[5];
- var M_BF = this.datum_params[6];
- var x_tmp = (p.x - Dx_BF) / M_BF;
- var y_tmp = (p.y - Dy_BF) / M_BF;
- var z_tmp = (p.z - Dz_BF) / M_BF;
- //if( x[io] === HUGE_VAL )
- // continue;
- p.x = x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp;
- p.y = -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp;
- p.z = Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp;
- } //cs_geocentric_from_wgs84()
- }
-};
+ out.a = a; //datum object also uses these values
+ out.b = b;
+ out.es = es;
+ out.ep2 = ep2;
+ return out;
+}
-/** point object, nothing fancy, just allows values to be
- passed back and forth by reference rather than by value.
- Other point classes may be used as long as they have
- x and y properties, which will get modified in the transform method.
-*/
module.exports = datum;
diff --git a/lib/datumUtils.js b/lib/datumUtils.js
new file mode 100644
index 0000000..d5a257e
--- /dev/null
+++ b/lib/datumUtils.js
@@ -0,0 +1,247 @@
+'use strict';
+var PJD_3PARAM = 1;
+var PJD_7PARAM = 2;
+var HALF_PI = Math.PI/2;
+
+exports.compareDatums = function(source, dest) {
+ if (source.datum_type !== dest.datum_type) {
+ return false; // false, datums are not equal
+ } else if (source.a !== dest.a || Math.abs(this.es - dest.es) > 0.000000000050) {
+ // the tolerence for es is to ensure that GRS80 and WGS84
+ // are considered identical
+ return false;
+ } else if (source.datum_type === PJD_3PARAM) {
+ return (this.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)
+ *
+ */
+exports.geodeticToGeocentric = function(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 > HALF_PI)) {
+ /* Latitude out of range */
+ //..reportError('geocent:lat out of range:' + Latitude);
+ return null;
+ }
+
+ 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()
+
+
+exports.geocentricToGeodetic = function(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; /* cos of geocentric latitude */
+ var RX;
+ var RK;
+ var RN; /* Earth radius at location */
+ var CPHI0; /* cos of start or old geodetic latitude in iterations */
+ var SPHI0; /* sin of start or old geodetic latitude in iterations */
+ var CPHI; /* cos of searched geodetic latitude */
+ var SPHI; /* sin of searched geodetic latitude */
+ var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
+ var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */
+
+ var X = p.x;
+ var Y = p.y;
+ var Z = p.z ? p.z : 0.0; //Z value not always supplied
+ var Longitude;
+ var Latitude;
+ var Height;
+
+ P = Math.sqrt(X * X + Y * Y);
+ RR = Math.sqrt(X * X + Y * Y + Z * Z);
+
+ /* special cases for latitude and longitude */
+ if (P / a < genau) {
+
+ /* special case, if P=0. (X=0., Y=0.) */
+ Longitude = 0.0;
+
+ /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
+ * of ellipsoid (=center of mass), Latitude becomes PI/2 */
+ if (RR / a < genau) {
+ Latitude = HALF_PI;
+ Height = -b;
+ return {
+ x: p.x,
+ y: p.y,
+ z: p.z
+ };
+ }
+ } else {
+ /* ellipsoidal (geodetic) longitude
+ * interval: -PI < Longitude <= +PI */
+ Longitude = Math.atan2(Y, X);
+ }
+
+ /* --------------------------------------------------------------
+ * Following iterative algorithm was developped by
+ * "Institut for Erdmessung", University of Hannover, July 1988.
+ * Internet: www.ife.uni-hannover.de
+ * Iterative computation of CPHI,SPHI and Height.
+ * Iteration of CPHI and SPHI to 10**-12 radian resp.
+ * 2*10**-7 arcsec.
+ * --------------------------------------------------------------
+ */
+ CT = Z / RR;
+ ST = P / RR;
+ RX = 1.0 / Math.sqrt(1.0 - es * (2.0 - es) * ST * ST);
+ CPHI0 = ST * (1.0 - es) * RX;
+ SPHI0 = CT * RX;
+ iter = 0;
+
+ /* loop to find sin(Latitude) resp. Latitude
+ * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
+ do {
+ iter++;
+ RN = a / Math.sqrt(1.0 - es * SPHI0 * SPHI0);
+
+ /* ellipsoidal (geodetic) height */
+ Height = P * CPHI0 + Z * SPHI0 - RN * (1.0 - es * SPHI0 * SPHI0);
+
+ RK = es * RN / (RN + Height);
+ RX = 1.0 / Math.sqrt(1.0 - RK * (2.0 - RK) * ST * ST);
+ CPHI = ST * (1.0 - RK) * RX;
+ SPHI = CT * RX;
+ SDPHI = SPHI * CPHI0 - CPHI * SPHI0;
+ CPHI0 = CPHI;
+ SPHI0 = SPHI;
+ }
+ while (SDPHI * SDPHI > genau2 && iter < maxiter);
+
+ /* ellipsoidal (geodetic) latitude */
+ Latitude = Math.atan(SPHI / Math.abs(CPHI));
+ return {
+ x: Longitude,
+ y: Latitude,
+ z: Height
+ };
+}; // cs_geocentric_to_geodetic()
+
+
+/****************************************************************/
+// pj_geocentic_to_wgs84( p )
+// p = point to transform in geocentric coordinates (x,y,z)
+
+
+/** point object, nothing fancy, just allows values to be
+ passed back and forth by reference rather than by value.
+ Other point classes may be used as long as they have
+ x and y properties, which will get modified in the transform method.
+*/
+exports.geocentricToWgs84 = function(p, datum_type, datum_params) {
+
+ if (datum_type === PJD_3PARAM) {
+ // if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: p.x + datum_params[0],
+ y: p.y + datum_params[1],
+ z: p.z + datum_params[2],
+ };
+ } else if (datum_type === PJD_7PARAM) {
+ var Dx_BF = datum_params[0];
+ var Dy_BF = datum_params[1];
+ var Dz_BF = datum_params[2];
+ var Rx_BF = datum_params[3];
+ var Ry_BF = datum_params[4];
+ var Rz_BF = datum_params[5];
+ var M_BF = datum_params[6];
+ // if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: M_BF * (p.x - Rz_BF * p.y + Ry_BF * p.z) + Dx_BF,
+ y: M_BF * (Rz_BF * p.x + p.y - Rx_BF * p.z) + Dy_BF,
+ z: M_BF * (-Ry_BF * p.x + Rx_BF * p.y + p.z) + Dz_BF
+ };
+ }
+}; // cs_geocentric_to_wgs84
+
+/****************************************************************/
+// pj_geocentic_from_wgs84()
+// coordinate system definition,
+// point to transform in geocentric coordinates (x,y,z)
+exports.geocentricFromWgs84 = function(p, datum_type, datum_params) {
+
+ if (datum_type === PJD_3PARAM) {
+ //if( x[io] === HUGE_VAL )
+ // continue;
+ return {
+ x: p.x - datum_params[0],
+ y: p.y - datum_params[1],
+ z: p.z - datum_params[2],
+ };
+
+ } else if (datum_type === PJD_7PARAM) {
+ var Dx_BF = datum_params[0];
+ var Dy_BF = datum_params[1];
+ var Dz_BF = datum_params[2];
+ var Rx_BF = datum_params[3];
+ var Ry_BF = datum_params[4];
+ var Rz_BF = datum_params[5];
+ var M_BF = datum_params[6];
+ var x_tmp = (p.x - Dx_BF) / M_BF;
+ var y_tmp = (p.y - Dy_BF) / M_BF;
+ var z_tmp = (p.z - Dz_BF) / M_BF;
+ //if( x[io] === HUGE_VAL )
+ // continue;
+
+ return {
+ x: x_tmp + Rz_BF * y_tmp - Ry_BF * z_tmp,
+ y: -Rz_BF * x_tmp + y_tmp + Rx_BF * z_tmp,
+ z: Ry_BF * x_tmp - Rx_BF * y_tmp + z_tmp
+ };
+ } //cs_geocentric_from_wgs84()
+};
diff --git a/lib/datum_transform.js b/lib/datum_transform.js
index 65173a8..b5a8b3f 100644
--- a/lib/datum_transform.js
+++ b/lib/datum_transform.js
@@ -1,17 +1,13 @@
var PJD_3PARAM = 1;
var PJD_7PARAM = 2;
-var PJD_GRIDSHIFT = 3;
var PJD_NODATUM = 5; // WGS84 or equivalent
-var SRS_WGS84_SEMIMAJOR = 6378137; // only used in grid shift transforms
-var SRS_WGS84_ESQUARED = 0.006694379990141316; //DGR: 2012-07-29
+var datum = require('./datumUtils');
+function checkParams(type) {
+ return (type === PJD_3PARAM || type === PJD_7PARAM);
+}
module.exports = function(source, dest, point) {
- var wp, i, l;
-
- function checkParams(fallback) {
- return (fallback === PJD_3PARAM || fallback === PJD_7PARAM);
- }
// Short cut if the datums are identical.
- if (source.compare_datums(dest)) {
+ if (datum.compareDatums(source, dest)) {
return point; // in this case, zero is sucess,
// whereas cs_compare_datums returns 1 to indicate TRUE
// confusing, should fix this
@@ -22,78 +18,22 @@ module.exports = function(source, dest, point) {
return point;
}
- //DGR: 2012-07-29 : add nadgrids support (begin)
- var src_a = source.a;
- var src_es = source.es;
-
- var dst_a = dest.a;
- var dst_es = dest.es;
-
- var fallback = source.datum_type;
// If this datum requires grid shifts, then apply it to geodetic coordinates.
- if (fallback === PJD_GRIDSHIFT) {
- if (this.apply_gridshift(source, 0, point) === 0) {
- source.a = SRS_WGS84_SEMIMAJOR;
- source.es = SRS_WGS84_ESQUARED;
- }
- else {
- // try 3 or 7 params transformation or nothing ?
- if (!source.datum_params) {
- source.a = src_a;
- source.es = source.es;
- return point;
- }
- wp = 1;
- for (i = 0, l = source.datum_params.length; i < l; i++) {
- wp *= source.datum_params[i];
- }
- if (wp === 0) {
- source.a = src_a;
- source.es = source.es;
- return point;
- }
- if (source.datum_params.length > 3) {
- fallback = PJD_7PARAM;
- }
- else {
- fallback = PJD_3PARAM;
- }
- }
- }
- if (dest.datum_type === PJD_GRIDSHIFT) {
- dest.a = SRS_WGS84_SEMIMAJOR;
- dest.es = SRS_WGS84_ESQUARED;
- }
+
// Do we need to go through geocentric coordinates?
- if (source.es !== dest.es || source.a !== dest.a || checkParams(fallback) || checkParams(dest.datum_type)) {
- //DGR: 2012-07-29 : add nadgrids support (end)
- // Convert to geocentric coordinates.
- source.geodetic_to_geocentric(point);
- // CHECK_RETURN;
- // Convert between datums
- if (checkParams(source.datum_type)) {
- source.geocentric_to_wgs84(point);
- // CHECK_RETURN;
- }
- if (checkParams(dest.datum_type)) {
- dest.geocentric_from_wgs84(point);
- // CHECK_RETURN;
- }
- // Convert back to geodetic coordinates
- dest.geocentric_to_geodetic(point);
- // CHECK_RETURN;
- }
- // Apply grid shift to destination if required
- if (dest.datum_type === PJD_GRIDSHIFT) {
- this.apply_gridshift(dest, 1, point);
- // CHECK_RETURN;
+ if (source.es === dest.es && source.a === dest.a && !checkParams(source.datum_type) && !checkParams(dest.datum_type)) {
+ return point;
}
- source.a = src_a;
- source.es = src_es;
- dest.a = dst_a;
- dest.es = dst_es;
+ // Convert to geocentric coordinates.
+ point = datum.geodeticToGeocentric(point, source.es, source.a);
+ // Convert between datums
+ if (checkParams(source.datum_type)) {
+ point = datum.geocentricToWgs84(point, source.datum_type, source.datum_params);
+ }
+ if (checkParams(dest.datum_type)) {
+ point = datum.geocentricFromWgs84(point, dest.datum_type, dest.datum_params);
+ }
+ return datum.geocentricToGeodetic(point, dest.es, dest.a, dest.b);
- return point;
};
-
diff --git a/lib/deriveConstants.js b/lib/deriveConstants.js
index b8a80a2..38faac0 100644
--- a/lib/deriveConstants.js
+++ b/lib/deriveConstants.js
@@ -1,56 +1,53 @@
-var Datum = require('./constants/Datum');
-var Ellipsoid = require('./constants/Ellipsoid');
-var extend = require('./extend');
-var datum = require('./datum');
-var EPSLN = 1.0e-10;
// ellipoid pj_set_ell.c
var SIXTH = 0.1666666666666666667;
/* 1/6 */
var RA4 = 0.04722222222222222222;
/* 17/360 */
var RA6 = 0.02215608465608465608;
-module.exports = function(json) {
- // DGR 2011-03-20 : nagrids -> nadgrids
- if (json.datumCode && json.datumCode !== 'none') {
- var datumDef = Datum[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;
+var EPSLN = 1.0e-10;
+var Ellipsoid = require('./constants/Ellipsoid');
+
+exports.eccentricity = function(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
+ };
+};
+exports.sphere = function (a, b, rf, ellps, sphere) {
+ if (!a) { // do we have an ellipsoid?
+ var ellipse = Ellipsoid[ellps];
+ if (!ellipse) {
+ ellipse = Ellipsoid.WGS84;
}
- }
- if (!json.a) { // do we have an ellipsoid?
- var ellipse = Ellipsoid[json.ellps] ? Ellipsoid[json.ellps] : Ellipsoid.WGS84;
- extend(json, ellipse);
- }
- if (json.rf && !json.b) {
- json.b = (1.0 - 1.0 / json.rf) * json.a;
- }
- if (json.rf === 0 || Math.abs(json.a - json.b) < EPSLN) {
- json.sphere = true;
- json.b = json.a;
- }
- json.a2 = json.a * json.a; // used in geocentric
- json.b2 = json.b * json.b; // used in geocentric
- json.es = (json.a2 - json.b2) / json.a2; // e ^ 2
- json.e = Math.sqrt(json.es); // eccentricity
- if (json.R_A) {
- json.a *= 1 - json.es * (SIXTH + json.es * (RA4 + json.es * RA6));
- json.a2 = json.a * json.a;
- json.b2 = json.b * json.b;
- json.es = 0;
- }
- json.ep2 = (json.a2 - json.b2) / json.b2; // used in geocentric
- if (!json.k0) {
- json.k0 = 1.0; //default value
- }
- //DGR 2010-11-12: axis
- if (!json.axis) {
- json.axis = "enu";
+ a = ellipse.a;
+ b = ellipse.b;
+ rf = ellipse.rf;
}
- if (!json.datum) {
- json.datum = datum(json);
- }
- return json;
+ 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
+ };
};
diff --git a/lib/index.js b/lib/index.js
index df6c187..a912bc0 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -3,10 +3,10 @@ proj4.defaultDatum = 'WGS84'; //default datum
proj4.Proj = require('./Proj');
proj4.WGS84 = new proj4.Proj('WGS84');
proj4.Point = require('./Point');
-proj4.toPoint = require("./common/toPoint");
+proj4.toPoint = require('./common/toPoint');
proj4.defs = require('./defs');
proj4.transform = require('./transform');
proj4.mgrs = require('mgrs');
-proj4.version = require('../package.json').version;
+proj4.version = require('./version');
require('./includedProjections')(proj4);
-module.exports = proj4;
\ No newline at end of file
+module.exports = proj4;
diff --git a/lib/parseCode.js b/lib/parseCode.js
index 88480a3..87386d9 100644
--- a/lib/parseCode.js
+++ b/lib/parseCode.js
@@ -7,11 +7,12 @@ function testObj(code){
function testDef(code){
return code in defs;
}
+var codeWords = ['GEOGCS','GEOCCS','PROJCS','LOCAL_CS'];
+
function testWKT(code){
- var codeWords = ['GEOGCS','GEOCCS','PROJCS','LOCAL_CS'];
- return codeWords.reduce(function(a,b){
- return a+1+code.indexOf(b);
- },0);
+ return codeWords.some(function (word) {
+ return code.indexOf(word) > -1;
+ });
}
function testProj(code){
return code[0] === '+';
@@ -22,10 +23,10 @@ function parse(code){
if (testDef(code)) {
return defs[code];
}
- else if (testWKT(code)) {
+ if (testWKT(code)) {
return wkt(code);
}
- else if (testProj(code)) {
+ if (testProj(code)) {
return projStr(code);
}
}else{
@@ -33,4 +34,4 @@ function parse(code){
}
}
-module.exports = parse;
\ No newline at end of file
+module.exports = parse;
diff --git a/lib/projString.js b/lib/projString.js
index 53326f2..7affc89 100644
--- a/lib/projString.js
+++ b/lib/projString.js
@@ -4,16 +4,16 @@ var units = require('./constants/units');
module.exports = function(defData) {
var self = {};
- var paramObj = {};
- defData.split("+").map(function(v) {
+ var paramObj = defData.split('+').map(function(v) {
return v.trim();
}).filter(function(a) {
return a;
- }).forEach(function(a) {
- var split = a.split("=");
+ }).reduce(function(p, a) {
+ var split = a.split('=');
split.push(true);
- paramObj[split[0].toLowerCase()] = split[1];
- });
+ p[split[0].toLowerCase()] = split[1];
+ return p;
+ }, {});
var paramName, paramVal, paramOutname;
var params = {
proj: 'projName',
diff --git a/lib/projections/tmerc.js b/lib/projections/tmerc.js
index 10fd51e..2eb3617 100644
--- a/lib/projections/tmerc.js
+++ b/lib/projections/tmerc.js
@@ -1,20 +1,24 @@
-var e0fn = require('../common/e0fn');
-var e1fn = require('../common/e1fn');
-var e2fn = require('../common/e2fn');
-var e3fn = require('../common/e3fn');
-var mlfn = require('../common/mlfn');
+// Heavily based on this tmerc projection implementation
+// https://github.com/mbloch/mapshaper-proj/blob/master/src/projections/tmerc.js
+
+var pj_enfn = require('../common/pj_enfn');
+var pj_mlfn = require('../common/pj_mlfn');
+var pj_inv_mlfn = require('../common/pj_inv_mlfn');
var adjust_lon = require('../common/adjust_lon');
-var HALF_PI = Math.PI/2;
+var HALF_PI = Math.PI / 2;
var EPSLN = 1.0e-10;
var sign = require('../common/sign');
-var asinz = require('../common/asinz');
exports.init = function() {
- 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);
+ this.x0 = this.x0 !== undefined ? this.x0 : 0;
+ this.y0 = this.y0 !== undefined ? this.y0 : 0;
+ this.long0 = this.long0 !== undefined ? this.long0 : 0;
+ this.lat0 = this.lat0 !== undefined ? this.lat0 : 0;
+
+ if (this.es) {
+ this.en = pj_enfn(this.es);
+ this.ml0 = pj_mlfn(this.lat0, Math.sin(this.lat0), Math.cos(this.lat0), this.en);
+ }
};
/**
@@ -31,36 +35,65 @@ exports.forward = function(p) {
var sin_phi = Math.sin(lat);
var cos_phi = Math.cos(lat);
- if (this.sphere) {
+ if (!this.es) {
var b = cos_phi * Math.sin(delta_lon);
- if ((Math.abs(Math.abs(b) - 1)) < 0.0000000001) {
+
+ if ((Math.abs(Math.abs(b) - 1)) < EPSLN) {
return (93);
}
else {
- x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b));
- con = Math.acos(cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - b * b));
+ x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b)) + this.x0;
+ y = cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - Math.pow(b, 2));
+ b = Math.abs(y);
+
+ if (b >= 1) {
+ if ((b - 1) > EPSLN) {
+ return (93);
+ }
+ else {
+ y = 0;
+ }
+ }
+ else {
+ y = Math.acos(y);
+ }
+
if (lat < 0) {
- con = -con;
+ y = -y;
}
- y = this.a * this.k0 * (con - this.lat0);
+
+ y = this.a * this.k0 * (y - this.lat0) + this.y0;
}
}
else {
var al = cos_phi * delta_lon;
var als = Math.pow(al, 2);
var c = this.ep2 * Math.pow(cos_phi, 2);
- var tq = Math.tan(lat);
+ var cs = Math.pow(c, 2);
+ var tq = Math.abs(cos_phi) > EPSLN ? Math.tan(lat) : 0;
var t = Math.pow(tq, 2);
+ var ts = Math.pow(t, 2);
con = 1 - this.es * Math.pow(sin_phi, 2);
- var n = this.a / Math.sqrt(con);
- var ml = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat);
+ al = al / Math.sqrt(con);
+ var ml = pj_mlfn(lat, sin_phi, cos_phi, this.en);
- x = this.k0 * n * al * (1 + als / 6 * (1 - t + c + als / 20 * (5 - 18 * t + Math.pow(t, 2) + 72 * c - 58 * this.ep2))) + this.x0;
- y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24 * (5 - t + 9 * c + 4 * Math.pow(c, 2) + als / 30 * (61 - 58 * t + Math.pow(t, 2) + 600 * c - 330 * this.ep2))))) + this.y0;
+ x = this.a * (this.k0 * al * (1 +
+ als / 6 * (1 - t + c +
+ als / 20 * (5 - 18 * t + ts + 14 * c - 58 * t * c +
+ als / 42 * (61 + 179 * ts - ts * t - 479 * t))))) +
+ this.x0;
+ y = this.a * (this.k0 * (ml - this.ml0 +
+ sin_phi * delta_lon * al / 2 * (1 +
+ als / 12 * (5 - t + 9 * c + 4 * cs +
+ als / 30 * (61 + ts - 58 * t + 270 * c - 330 * t * c +
+ als / 56 * (1385 + 543 * ts - ts * t - 3111 * t)))))) +
+ this.y0;
}
+
p.x = x;
p.y = y;
+
return p;
};
@@ -69,67 +102,66 @@ exports.forward = function(p) {
*/
exports.inverse = function(p) {
var con, phi;
- var delta_phi;
- var i;
- var max_iter = 6;
var lat, lon;
+ var x = (p.x - this.x0) * (1 / this.a);
+ var y = (p.y - this.y0) * (1 / this.a);
- if (this.sphere) {
- var f = Math.exp(p.x / (this.a * this.k0));
+ if (!this.es) {
+ var f = Math.exp(x / this.k0);
var g = 0.5 * (f - 1 / f);
- var temp = this.lat0 + p.y / (this.a * this.k0);
+ var temp = this.lat0 + y / this.k0;
var h = Math.cos(temp);
- con = Math.sqrt((1 - h * h) / (1 + g * g));
- lat = asinz(con);
- if (temp < 0) {
+ con = Math.sqrt((1 - Math.pow(h, 2)) / (1 + Math.pow(g, 2)));
+ lat = Math.asin(con);
+
+ if (y < 0) {
lat = -lat;
}
+
if ((g === 0) && (h === 0)) {
- lon = this.long0;
+ lon = 0;
}
else {
lon = adjust_lon(Math.atan2(g, h) + this.long0);
}
}
else { // ellipsoidal form
- var x = p.x - this.x0;
- var y = p.y - this.y0;
-
- con = (this.ml0 + y / this.k0) / this.a;
- phi = con;
- for (i = 0; true; i++) {
- delta_phi = ((con + this.e1 * Math.sin(2 * phi) - this.e2 * Math.sin(4 * phi) + this.e3 * Math.sin(6 * phi)) / this.e0) - phi;
- phi += delta_phi;
- if (Math.abs(delta_phi) <= EPSLN) {
- break;
- }
- if (i >= max_iter) {
- return (95);
- }
- } // for()
+ con = this.ml0 + y / this.k0;
+ phi = pj_inv_mlfn(con, this.es, this.en);
+
if (Math.abs(phi) < HALF_PI) {
var sin_phi = Math.sin(phi);
var cos_phi = Math.cos(phi);
- var tan_phi = Math.tan(phi);
+ var tan_phi = Math.abs(cos_phi) > EPSLN ? Math.tan(phi) : 0;
var c = this.ep2 * Math.pow(cos_phi, 2);
var cs = Math.pow(c, 2);
var t = Math.pow(tan_phi, 2);
var ts = Math.pow(t, 2);
con = 1 - this.es * Math.pow(sin_phi, 2);
- var n = this.a / Math.sqrt(con);
- var r = n * (1 - this.es) / con;
- var d = x / (n * this.k0);
+ var d = x * Math.sqrt(con) / this.k0;
var ds = Math.pow(d, 2);
- lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24 * (5 + 3 * t + 10 * c - 4 * cs - 9 * this.ep2 - ds / 30 * (61 + 90 * t + 298 * c + 45 * ts - 252 * this.ep2 - 3 * cs)));
- lon = adjust_lon(this.long0 + (d * (1 - ds / 6 * (1 + 2 * t + c - ds / 20 * (5 - 2 * c + 28 * t - 3 * cs + 8 * this.ep2 + 24 * ts))) / cos_phi));
+ con = con * tan_phi;
+
+ lat = phi - (con * ds / (1 - this.es)) * 0.5 * (1 -
+ ds / 12 * (5 + 3 * t - 9 * c * t + c - 4 * cs -
+ ds / 30 * (61 + 90 * t - 252 * c * t + 45 * ts + 46 * c -
+ ds / 56 * (1385 + 3633 * t + 4095 * ts + 1574 * ts * t))));
+
+ lon = adjust_lon(this.long0 + (d * (1 -
+ ds / 6 * (1 + 2 * t + c -
+ ds / 20 * (5 + 28 * t + 24 * ts + 8 * c * t + 6 * c -
+ ds / 42 * (61 + 662 * t + 1320 * ts + 720 * ts * t)))) / cos_phi));
}
else {
lat = HALF_PI * sign(y);
- lon = this.long0;
+ lon = 0;
}
}
+
p.x = lon;
p.y = lat;
+
return p;
};
+
exports.names = ["Transverse_Mercator", "Transverse Mercator", "tmerc"];
diff --git a/lib/projections/utm.js b/lib/projections/utm.js
index 18245cc..5f37300 100644
--- a/lib/projections/utm.js
+++ b/lib/projections/utm.js
@@ -1,12 +1,16 @@
-var D2R = 0.01745329251994329577;
+var adjust_zone = require('../common/adjust_zone');
var tmerc = require('./tmerc');
+
exports.dependsOn = 'tmerc';
+
exports.init = function() {
- if (!this.zone) {
+ var zone = adjust_zone(this.zone, this.long0);
+ if (!zone) {
return;
}
+
this.lat0 = 0;
- this.long0 = ((6 * Math.abs(this.zone)) - 183) * D2R;
+ this.long0 = (zone + 0.5) * Math.PI / 30 - Math.PI;
this.x0 = 500000;
this.y0 = this.utmSouth ? 10000000 : 0;
this.k0 = 0.9996;
@@ -15,4 +19,5 @@ exports.init = function() {
this.forward = tmerc.forward;
this.inverse = tmerc.inverse;
};
+
exports.names = ["Universal Transverse Mercator System", "utm"];
diff --git a/lib/transform.js b/lib/transform.js
index 2ed0fd6..aed86b9 100644
--- a/lib/transform.js
+++ b/lib/transform.js
@@ -6,36 +6,40 @@ var datum_transform = require('./datum_transform');
var adjust_axis = require('./adjust_axis');
var proj = require('./Proj');
var toPoint = require('./common/toPoint');
+function checkNotWGS(source, dest) {
+ return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== 'WGS84') || ((dest.datum.datum_type === PJD_3PARAM || dest.datum.datum_type === PJD_7PARAM) && source.datumCode !== 'WGS84');
+}
module.exports = function transform(source, dest, point) {
var wgs84;
if (Array.isArray(point)) {
point = toPoint(point);
}
- function checkNotWGS(source, dest) {
- return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== "WGS84");
- }
// Workaround for datum shifts towgs84, if either source or destination projection is not wgs84
- if (source.datum && dest.datum && (checkNotWGS(source, dest) || checkNotWGS(dest, source))) {
+ if (source.datum && dest.datum && checkNotWGS(source, dest)) {
wgs84 = new proj('WGS84');
- transform(source, wgs84, point);
+ point = transform(source, wgs84, point);
source = wgs84;
}
// DGR, 2010/11/12
- if (source.axis !== "enu") {
- adjust_axis(source, false, point);
+ if (source.axis !== 'enu') {
+ point = adjust_axis(source, false, point);
}
// Transform source points to long/lat, if they aren't already.
- if (source.projName === "longlat") {
- point.x *= D2R; // convert degrees to radians
- point.y *= D2R;
+ if (source.projName === 'longlat') {
+ point = {
+ x: point.x * D2R,
+ y: point.y * D2R
+ };
}
else {
if (source.to_meter) {
- point.x *= source.to_meter;
- point.y *= source.to_meter;
+ point = {
+ x: point.x * source.to_meter,
+ y: point.y * source.to_meter
+ };
}
- source.inverse(point); // Convert Cartesian to longlat
+ point = source.inverse(point); // Convert Cartesian to longlat
}
// Adjust for the prime meridian if necessary
if (source.from_greenwich) {
@@ -47,26 +51,32 @@ module.exports = function transform(source, dest, point) {
// Adjust for the prime meridian if necessary
if (dest.from_greenwich) {
- point.x -= dest.from_greenwich;
+ point = {
+ x: point.x - dest.grom_greenwich,
+ y: point.y
+ };
}
- if (dest.projName === "longlat") {
+ if (dest.projName === 'longlat') {
// convert radians to decimal degrees
- point.x *= R2D;
- point.y *= R2D;
- }
- else { // else project
- dest.forward(point);
+ point = {
+ x: point.x * R2D,
+ y: point.y * R2D
+ };
+ } else { // else project
+ point = dest.forward(point);
if (dest.to_meter) {
- point.x /= dest.to_meter;
- point.y /= dest.to_meter;
+ point = {
+ x: point.x / dest.to_meter,
+ y: point.y / dest.to_meter
+ };
}
}
// DGR, 2010/11/12
- if (dest.axis !== "enu") {
- adjust_axis(dest, true, point);
+ if (dest.axis !== 'enu') {
+ return adjust_axis(dest, true, point);
}
return point;
-};
\ No newline at end of file
+};
diff --git a/lib/version-browser.js b/lib/version-browser.js
new file mode 100644
index 0000000..8e946b2
--- /dev/null
+++ b/lib/version-browser.js
@@ -0,0 +1 @@
+module.exports = '2.3.16';
diff --git a/lib/version.js b/lib/version.js
new file mode 100644
index 0000000..81f6e78
--- /dev/null
+++ b/lib/version.js
@@ -0,0 +1 @@
+module.exports = require('../package.json').version;
diff --git a/package.json b/package.json
index b0605f5..ea276ae 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "proj4",
- "version": "2.3.15-alpha",
+ "version": "2.3.16-alpha",
"description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.",
"main": "lib/index.js",
"directories": {
@@ -16,15 +16,6 @@
},
"author": "",
"license": "MIT",
- "jam": {
- "main": "dist/proj4.js",
- "include": [
- "dist/proj4.js",
- "README.md",
- "AUTHORS",
- "LICENSE.md"
- ]
- },
"devDependencies": {
"grunt-cli": "~0.1.13",
"grunt": "~0.4.2",
@@ -40,7 +31,10 @@
"istanbul": "~0.2.4",
"tin": "~0.4.0"
},
+ "browser": {
+ "./lib/version.js": "./lib/version-browser.js"
+ },
"dependencies": {
"mgrs": "~0.0.2"
}
-}
\ No newline at end of file
+}
diff --git a/publish.sh b/publish.sh
index 8d9ef84..93d042f 100755
--- a/publish.sh
+++ b/publish.sh
@@ -5,6 +5,8 @@ VERSION=$(npm ls --json=true proj4js | grep version | awk '{ print $2}'| sed -e
# Build
git checkout -b build
+echo "module.exports = '$VERSION';" > ./lib/version-browser.js
+git add ./lib/version-browser.js -f
node_modules/.bin/grunt
git add dist -f
git commit -m "build $VERSION"
@@ -15,7 +17,6 @@ git push --tags git at github.com:proj4js/proj4js.git $VERSION
# Publish
npm publish
-jam publish
# Cleanup
git checkout master
diff --git a/test/test.js b/test/test.js
index 45bfc32..0d8fa5b 100644
--- a/test/test.js
+++ b/test/test.js
@@ -25,17 +25,18 @@ function startTests(chai, proj4, testPoints) {
var sweref99tm = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs';
var rt90 = '+lon_0=15.808277777799999 +lat_0=0.0 +k=1.0 +x_0=1500000.0 +y_0=0.0 +proj=tmerc +ellps=bessel +units=m +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0 +no_defs';
var rslt = proj4(sweref99tm, rt90).forward([319180, 6399862]);
- assert.closeTo(rslt[0], 1271137.927154, 0.000001);
- assert.closeTo(rslt[1], 6404230.291456, 0.000001);
+ assert.closeTo(rslt[0], 1271137.9275601401, 0.000001);
+ assert.closeTo(rslt[1], 6404230.291448903, 0.000001);
});
it('should work with a proj object', function() {
var sweref99tm = proj4('+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs');
var rt90 = proj4('+lon_0=15.808277777799999 +lat_0=0.0 +k=1.0 +x_0=1500000.0 +y_0=0.0 +proj=tmerc +ellps=bessel +units=m +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0 +no_defs');
var rslt = proj4(sweref99tm, rt90).forward([319180, 6399862]);
- assert.closeTo(rslt[0], 1271137.927154, 0.000001);
- assert.closeTo(rslt[1], 6404230.291456, 0.000001);
+ assert.closeTo(rslt[0], 1271137.9275601401, 0.000001);
+ assert.closeTo(rslt[1], 6404230.291448903, 0.000001);
});
});
+
describe('proj4', function() {
describe('core', function() {
testPoints.forEach(function(testPoint) {
diff --git a/test/testData.js b/test/testData.js
index cb9bd80..b3cd064 100644
--- a/test/testData.js
+++ b/test/testData.js
@@ -147,20 +147,20 @@ var testPoints = [
{
code:'PROJCS["Beduaram / TM 13 NE",GEOGCS["Beduaram",DATUM["Beduaram",SPHEROID["Clarke 1880 (IGN)",6378249.2,293.4660212936269,AUTHORITY["EPSG","7011"]],TOWGS84[-106,-87,188,0,0,0,0],AUTHORITY["EPSG","6213"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4213"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",13],PARA [...]
ll:[5, 25],
- xy:[-308919.1462828873, 2788738.252386554],
+ xy:[-308919.1234711099, 2788738.255936392],
acc:{
ll:5
}
},
- {
+ {
code:'PROJCS["Beduaram / TM 13 NE",GEOGCS["Beduaram",DATUM["D_Beduaram",SPHEROID["Clarke_1880_IGN",6378249.2,293.4660212936269]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",13],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["Meter",1]]',
ll:[5, 25],
- xy:[-308919.1462828873, 2788738.252386554],
+ xy:[-308919.1234711099, 2788738.255936392],
acc:{
ll:5
}
- }
- ,{
+ },
+ {
code:'PROJCS["S-JTSK (Ferro) / Krovak",GEOGCS["S-JTSK (Ferro)",DATUM["S_JTSK_Ferro",SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],AUTHORITY["EPSG","6818"]],PRIMEM["Ferro",-17.66666666666667,AUTHORITY["EPSG","8909"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4818"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Krovak"],PARAMETER["latitude_of_center",49.5],PARAMETER["longitude_of_center",42.5],PARAMETER["azimuth",30 [...]
ll:[17.323583231075897, 49.39440725405376],
xy:[-544115.474379, -1144058.330762]
@@ -308,6 +308,80 @@ var testPoints = [
code: 'EPSG:3857',
ll: [180, 0],
xy: [20037508.342789, 0]
+ },
+ // these test cases are taken from mapshaper-proj and the test results match
+ {
+ code: '+proj=tmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5',
+ ll: [2, 1],
+ xy: [222650.79679577847, 110642.2294119271]
+ },
+ {
+ code: '+proj=tmerc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +datum=none',
+ ll: [2, 1],
+ xy: [223413.46640632232, 111769.14504059685]
+ },
+ {
+ code: '+proj=utm +zone=30 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5',
+ ll: [2, 1],
+ xy: [1057002.4052152266, 110955.14117382761]
+ },
+ // these test cases are related to the original issue on GitHub
+ {
+ code: '+proj=utm +zone=33 +datum=WGS84 +units=m +no_defs',
+ ll: [2, 1],
+ xy: [-959006.3439168662, 113457.31706492987],
+ acc: {
+ ll: 5
+ }
+ },
+ {
+ code: '+proj=utm +zone=33 +datum=WGS84 +units=m +no_defs',
+ ll: [31, 70],
+ xy: [1104629.4280255223, 7845845.076400871],
+ acc: {
+ ll: 4
+ }
+ },
+ // these test cases are for Norway snow flake zones
+ {
+ code: '+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs',
+ ll: [59.121778, 1.508527],
+ xy: [8055639.601582392, 297536.7150416747],
+ acc: {
+ ll: 0
+ }
+ },
+ {
+ code: '+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs',
+ ll: [59.121778, 1.508527],
+ xy: [6958363.797581035, 260155.3254079497],
+ acc: {
+ ll: 0
+ }
+ },
+ {
+ code: '+proj=utm +zone=33 +datum=WGS84 +units=m +no_defs',
+ ll: [59.121778, 1.508527],
+ xy: [5980907.454031456, 232674.60895515585],
+ acc: {
+ ll: 1
+ }
+ },
+ {
+ code: '+proj=utm +zone=34 +datum=WGS84 +units=m +no_defs',
+ ll: [79.070672, 20.520579],
+ xy: [7442887.111291251, 3910285.3071145327],
+ acc: {
+ ll: -1.5
+ }
+ },
+ {
+ code: '+proj=utm +zone=35 +datum=WGS84 +units=m +no_defs',
+ ll: [79.070672, 20.520579],
+ xy: [6555309.538050345, 3474309.0216152733],
+ acc: {
+ ll: -0.5
+ }
}
];
if(typeof module !== 'undefined'){
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/proj4js.git
More information about the Pkg-grass-devel
mailing list