├── .gitattributes ├── src ├── main │ ├── resources │ │ └── proj4js │ │ │ ├── .npmignore │ │ │ ├── test │ │ │ ├── package.json.js │ │ │ ├── opt.html │ │ │ └── amd.html │ │ │ ├── .travis.yml │ │ │ ├── lib │ │ │ ├── common │ │ │ │ ├── sign.js │ │ │ │ ├── e3fn.js │ │ │ │ ├── atanh.js │ │ │ │ ├── e2fn.js │ │ │ │ ├── e0fn.js │ │ │ │ ├── e1fn.js │ │ │ │ ├── srat.js │ │ │ │ ├── cosh.js │ │ │ │ ├── sinh.js │ │ │ │ ├── acosh.js │ │ │ │ ├── tanh.js │ │ │ │ ├── gN.js │ │ │ │ ├── fL.js │ │ │ │ ├── asinz.js │ │ │ │ ├── asinh.js │ │ │ │ ├── msfnz.js │ │ │ │ ├── mlfn.js │ │ │ │ ├── adjust_lat.js │ │ │ │ ├── pj_mlfn.js │ │ │ │ ├── tsfnz.js │ │ │ │ ├── toPoint.js │ │ │ │ ├── qsfnz.js │ │ │ │ ├── invlatiso.js │ │ │ │ ├── latiso.js │ │ │ │ ├── adjust_lon.js │ │ │ │ ├── phi2z.js │ │ │ │ ├── imlfn.js │ │ │ │ ├── nadInterBreakout.js │ │ │ │ ├── pj_inv_mlfn.js │ │ │ │ ├── pj_enfn.js │ │ │ │ ├── nad_cvt.js │ │ │ │ ├── inverseNadCvt.js │ │ │ │ ├── iqsfnz.js │ │ │ │ └── nad_intr.js │ │ │ ├── constants │ │ │ │ ├── units.js │ │ │ │ ├── PrimeMeridian.js │ │ │ │ ├── grids.js │ │ │ │ ├── Datum.js │ │ │ │ └── Ellipsoid.js │ │ │ ├── projections │ │ │ │ ├── longlat.js │ │ │ │ ├── utm.js │ │ │ │ ├── equi.js │ │ │ │ ├── eqc.js │ │ │ │ ├── mill.js │ │ │ │ ├── gauss.js │ │ │ │ ├── sterea.js │ │ │ │ ├── cea.js │ │ │ │ ├── gstmerc.js │ │ │ │ ├── moll.js │ │ │ │ ├── ortho.js │ │ │ │ ├── merc.js │ │ │ │ ├── sinu.js │ │ │ │ ├── somerc.js │ │ │ │ ├── gnom.js │ │ │ │ ├── cass.js │ │ │ │ ├── eqdc.js │ │ │ │ ├── krovak.js │ │ │ │ ├── vandg.js │ │ │ │ ├── aea.js │ │ │ │ ├── lcc.js │ │ │ │ ├── poly.js │ │ │ │ ├── tmerc.js │ │ │ │ ├── omerc.js │ │ │ │ ├── stere.js │ │ │ │ ├── nzmg.js │ │ │ │ └── aeqd.js │ │ │ ├── extend.js │ │ │ ├── index.js │ │ │ ├── global.js │ │ │ ├── projections.js │ │ │ ├── parseCode.js │ │ │ ├── Proj.js │ │ │ ├── includedProjections.js │ │ │ ├── Point.js │ │ │ ├── adjust_axis.js │ │ │ ├── defs.js │ │ │ ├── core.js │ │ │ ├── deriveConstants.js │ │ │ ├── transform.js │ │ │ ├── datum_transform.js │ │ │ ├── projString.js │ │ │ └── wkt.js │ │ │ ├── .gitignore │ │ │ ├── .jshintrc │ │ │ ├── component.json │ │ │ ├── publish.sh │ │ │ ├── PUBLISHING.md │ │ │ ├── bower.json │ │ │ ├── AUTHORS │ │ │ ├── changelog.md │ │ │ ├── package.json │ │ │ ├── LICENSE.md │ │ │ ├── REFERENCES.md │ │ │ ├── Gruntfile.js │ │ │ └── README.md │ └── java │ │ └── org │ │ └── maptalks │ │ └── proj4 │ │ ├── projection │ │ ├── ProjectionType.java │ │ ├── Projection.java │ │ ├── LonLat.java │ │ ├── SphericalMercator.java │ │ └── BaiduMercator.java │ │ ├── Point.java │ │ ├── WKTParser.java │ │ ├── Proj4Exception.java │ │ ├── PointAdaptor.java │ │ ├── datum │ │ ├── Datum.java │ │ ├── WGS84.java │ │ ├── CGCS2000.java │ │ ├── BD09LL.java │ │ └── GCJ02.java │ │ ├── SimplePoint.java │ │ ├── ProjString.java │ │ ├── Proj.java │ │ ├── Parser.java │ │ ├── DatumTransform.java │ │ ├── Transform.java │ │ ├── DatumCache.java │ │ ├── ProjectionCache.java │ │ ├── Global.java │ │ ├── rhino │ │ └── JsonModuleScriptProvider.java │ │ └── Proj4.java └── test │ └── java │ └── org │ └── maptalks │ └── proj4 │ └── Proj4Test.java ├── .editorconfig ├── README.md ├── LICENSE ├── .gitignore └── pom.xml /.gitattributes: -------------------------------------------------------------------------------- 1 | pom.xml binary 2 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/.npmignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .c9revisions 3 | coverage 4 | projs.js -------------------------------------------------------------------------------- /src/main/resources/proj4js/test/package.json.js: -------------------------------------------------------------------------------- 1 | define({version : "curl is dumb"}); -------------------------------------------------------------------------------- /src/main/resources/proj4js/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "0.10" -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/sign.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return x<0 ? -1 : 1; 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | node_modules 3 | .c9revisions 4 | coverage 5 | projs.js 6 | .DS_STORE 7 | dist -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/e3fn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return (x * x * x * (35 / 3072)); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/atanh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return Math.log((x - 1) / (x + 1)) / 2; 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/e2fn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return (0.05859375 * x * x * (1 + 0.75 * x)); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/constants/units.js: -------------------------------------------------------------------------------- 1 | exports.ft = {to_meter: 0.3048}; 2 | exports['us-ft'] = {to_meter: 1200 / 3937}; 3 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/e0fn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return (1 - 0.25 * x * (1 + x / 16 * (3 + 1.25 * x))); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/e1fn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return (0.375 * x * (1 + 0.25 * x * (1 + 0.46875 * x))); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/srat.js: -------------------------------------------------------------------------------- 1 | module.exports = function(esinp, exp) { 2 | return (Math.pow((1 - esinp) / (1 + esinp), exp)); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/cosh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | var r = Math.exp(x); 3 | r = (r + 1 / r) / 2; 4 | return r; 5 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/sinh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | var r = Math.exp(x); 3 | r = (r - 1 / r) / 2; 4 | return r; 5 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/acosh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | return 2 * Math.log(Math.sqrt((x + 1) / 2) + Math.sqrt((x - 1) / 2)); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/tanh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | var r = Math.exp(x); 3 | r = (r - 1 / r) / (r + 1 / r); 4 | return r; 5 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/gN.js: -------------------------------------------------------------------------------- 1 | module.exports = function(a, e, sinphi) { 2 | var temp = e * sinphi; 3 | return a / Math.sqrt(1 - temp * temp); 4 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/fL.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | 3 | module.exports = function(x, L) { 4 | return 2 * Math.atan(x * Math.exp(L)) - HALF_PI; 5 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/asinz.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | if (Math.abs(x) > 1) { 3 | x = (x > 1) ? 1 : -1; 4 | } 5 | return Math.asin(x); 6 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/asinh.js: -------------------------------------------------------------------------------- 1 | module.exports = function(x) { 2 | var s = (x >= 0 ? 1 : -1); 3 | return s * (Math.log(Math.abs(x) + Math.sqrt(x * x + 1))); 4 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/msfnz.js: -------------------------------------------------------------------------------- 1 | module.exports = function(eccent, sinphi, cosphi) { 2 | var con = eccent * sinphi; 3 | return cosphi / (Math.sqrt(1 - con * con)); 4 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/mlfn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(e0, e1, e2, e3, phi) { 2 | return (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi)); 3 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/adjust_lat.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | var sign = require('./sign'); 3 | 4 | module.exports = function(x) { 5 | return (Math.abs(x) < HALF_PI) ? x : (x - (sign(x) * Math.PI)); 6 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/pj_mlfn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(phi, sphi, cphi, en) { 2 | cphi *= sphi; 3 | sphi *= sphi; 4 | return (en[0] * phi - cphi * (en[1] + sphi * (en[2] + sphi * (en[3] + sphi * en[4])))); 5 | }; -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/projection/ProjectionType.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.projection; 2 | 3 | public enum ProjectionType { 4 | 5 | GEOGRAPHIC, 6 | 7 | GEOCENTRIC, 8 | 9 | PROJECTED 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Point.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | public interface Point { 4 | double getX(); 5 | 6 | void setX(double x); 7 | 8 | double getY(); 9 | 10 | void setY(double y); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/WKTParser.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | class WKTParser { 4 | static Proj parse(String wkt) { 5 | // TODO: parse wkt to an instance of Proj 6 | return new Proj(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Proj4Exception.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | public class Proj4Exception extends Exception { 4 | 5 | public Proj4Exception(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "latedef": "nofunc", 5 | "undef": true, 6 | "unused": true, 7 | "trailing": true, 8 | "indent": 2, 9 | "browser": true, 10 | "node": true 11 | } -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/PointAdaptor.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | public interface PointAdaptor { 4 | double getX(T point); 5 | 6 | double getY(T point); 7 | 8 | void setX(T point, double x); 9 | 10 | void setY(T point, double y); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/longlat.js: -------------------------------------------------------------------------------- 1 | exports.init = function() { 2 | //no-op for longlat 3 | }; 4 | 5 | function identity(pt) { 6 | return pt; 7 | } 8 | exports.forward = identity; 9 | exports.inverse = identity; 10 | exports.names = ["longlat", "identity"]; 11 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/tsfnz.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | 3 | module.exports = function(eccent, phi, sinphi) { 4 | var con = eccent * sinphi; 5 | var com = 0.5 * eccent; 6 | con = Math.pow(((1 - con) / (1 + con)), com); 7 | return (Math.tan(0.5 * (HALF_PI - phi)) / con); 8 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/toPoint.js: -------------------------------------------------------------------------------- 1 | module.exports = function (array){ 2 | var out = { 3 | x: array[0], 4 | y: array[1] 5 | }; 6 | if (array.length>2) { 7 | out.z = array[2]; 8 | } 9 | if (array.length>3) { 10 | out.m = array[3]; 11 | } 12 | return out; 13 | }; -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/datum/Datum.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.datum; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public interface Datum { 6 | 7 | T toWGS84(T point, PointAdaptor pointAdaptor); 8 | 9 | T fromWGS84(T point, PointAdaptor pointAdaptor); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/qsfnz.js: -------------------------------------------------------------------------------- 1 | module.exports = function(eccent, sinphi) { 2 | var con; 3 | if (eccent > 1.0e-7) { 4 | con = eccent * sinphi; 5 | return ((1 - eccent * eccent) * (sinphi / (1 - con * con) - (0.5 / eccent) * Math.log((1 - con) / (1 + con)))); 6 | } 7 | else { 8 | return (2 * sinphi); 9 | } 10 | }; -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | # MacOSX: Icon must end with two \r 15 | [.gitignore] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/projection/Projection.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.projection; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public interface Projection { 6 | 7 | T forward(T point, PointAdaptor pointAdaptor); 8 | 9 | T inverse(T point, PointAdaptor pointAdaptor); 10 | 11 | ProjectionType getType(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/invlatiso.js: -------------------------------------------------------------------------------- 1 | var fL = require('./fL'); 2 | 3 | module.exports = function(eccent, ts) { 4 | var phi = fL(1, ts); 5 | var Iphi = 0; 6 | var con = 0; 7 | do { 8 | Iphi = phi; 9 | con = eccent * Math.sin(Iphi); 10 | phi = fL(Math.exp(eccent * Math.log((1 + con) / (1 - con)) / 2), ts); 11 | } while (Math.abs(phi - Iphi) > 1.0e-12); 12 | return phi; 13 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/extend.js: -------------------------------------------------------------------------------- 1 | module.exports = function(destination, source) { 2 | destination = destination || {}; 3 | var value, property; 4 | if (!source) { 5 | return destination; 6 | } 7 | for (property in source) { 8 | value = source[property]; 9 | if (value !== undefined) { 10 | destination[property] = value; 11 | } 12 | } 13 | return destination; 14 | }; 15 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/datum/WGS84.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.datum; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class WGS84 implements Datum { 6 | 7 | public T toWGS84(T point, PointAdaptor pointAdaptor) { 8 | return point; 9 | } 10 | 11 | public T fromWGS84(T point, PointAdaptor pointAdaptor) { 12 | return point; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/datum/CGCS2000.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.datum; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class CGCS2000 implements Datum { 6 | 7 | public T toWGS84(T point, PointAdaptor pointAdaptor) { 8 | return point; 9 | } 10 | 11 | public T fromWGS84(T point, PointAdaptor pointAdaptor) { 12 | return point; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/index.js: -------------------------------------------------------------------------------- 1 | var proj4 = require('./core'); 2 | proj4.defaultDatum = 'WGS84'; //default datum 3 | proj4.Proj = require('./Proj'); 4 | proj4.WGS84 = new proj4.Proj('WGS84'); 5 | proj4.toPoint = require("./common/toPoint"); 6 | proj4.defs = require('./defs'); 7 | proj4.transform = require('./transform'); 8 | proj4.version = require('../package.json').version; 9 | require('./includedProjections')(proj4); 10 | module.exports = proj4; 11 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proj4", 3 | "version": "2.3.15-alpha", 4 | "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.", 5 | "repo": "proj4js/proj4js", 6 | "keywords": [ 7 | "projections", 8 | "proj4", 9 | "transform", 10 | "crs" 11 | ], 12 | "license": "MIT", 13 | "main": "dist/proj4.js", 14 | "scripts": [ 15 | "dist/proj4.js" 16 | ] 17 | } -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/latiso.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | 3 | module.exports = function(eccent, phi, sinphi) { 4 | if (Math.abs(phi) > HALF_PI) { 5 | return Number.NaN; 6 | } 7 | if (phi === HALF_PI) { 8 | return Number.POSITIVE_INFINITY; 9 | } 10 | if (phi === -1 * HALF_PI) { 11 | return Number.NEGATIVE_INFINITY; 12 | } 13 | 14 | var con = eccent * sinphi; 15 | return Math.log(Math.tan((HALF_PI + phi) / 2)) + eccent * Math.log((1 - con) / (1 + con)) / 2; 16 | }; -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/projection/LonLat.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.projection; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class LonLat implements Projection { 6 | 7 | public T forward(T point, PointAdaptor pointAdaptor) { 8 | return point; 9 | } 10 | 11 | public T inverse(T point, PointAdaptor pointAdaptor) { 12 | return point; 13 | } 14 | 15 | public ProjectionType getType() { 16 | return ProjectionType.GEOGRAPHIC; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/adjust_lon.js: -------------------------------------------------------------------------------- 1 | var TWO_PI = Math.PI * 2; 2 | // SPI is slightly greater than Math.PI, so values that exceed the -180..180 3 | // degree range by a tiny amount don't get wrapped. This prevents points that 4 | // have drifted from their original location along the 180th meridian (due to 5 | // floating point error) from changing their sign. 6 | var SPI = 3.14159265359; 7 | var sign = require('./sign'); 8 | 9 | module.exports = function(x) { 10 | return (Math.abs(x) <= SPI) ? x : (x - (sign(x) * TWO_PI)); 11 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get current version 4 | VERSION=$(npm ls --json=true proj4js | grep version | awk '{ print $2}'| sed -e 's/^"//' -e 's/"$//') 5 | 6 | # Build 7 | git checkout -b build 8 | node_modules/.bin/grunt 9 | git add dist -f 10 | git commit -m "build $VERSION" 11 | 12 | # Tag and push 13 | git tag $VERSION 14 | git push --tags git@github.com:proj4js/proj4js.git $VERSION 15 | 16 | # Publish 17 | npm publish 18 | jam publish 19 | 20 | # Cleanup 21 | git checkout master 22 | git branch -D build 23 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/PUBLISHING.md: -------------------------------------------------------------------------------- 1 | Publishing 2 | === 3 | 4 | Use `tin` to update the version number in the `package.json`, `component.json` & `bower.json`. 5 | 6 | tin -v x.y.z 7 | 8 | Then run the publish script 9 | 10 | ./publish.sh 11 | 12 | afterwards don't forget to update the versions to be a prerelease of the next version, so if you just published 1.1.1 then: 13 | 14 | tin -v 1.1.2-alpha 15 | git add package.json component.json bower.json 16 | git commit -m 'update version to 1.1.2-alpha' 17 | git push origin master -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/phi2z.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | module.exports = function(eccent, ts) { 3 | var eccnth = 0.5 * eccent; 4 | var con, dphi; 5 | var phi = HALF_PI - 2 * Math.atan(ts); 6 | for (var i = 0; i <= 15; i++) { 7 | con = eccent * Math.sin(phi); 8 | dphi = HALF_PI - 2 * Math.atan(ts * (Math.pow(((1 - con) / (1 + con)), eccnth))) - phi; 9 | phi += dphi; 10 | if (Math.abs(dphi) <= 0.0000000001) { 11 | return phi; 12 | } 13 | } 14 | //console.log("phi2z has NoConvergence"); 15 | return -9999; 16 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/utm.js: -------------------------------------------------------------------------------- 1 | var D2R = 0.01745329251994329577; 2 | var tmerc = require('./tmerc'); 3 | exports.dependsOn = 'tmerc'; 4 | exports.init = function() { 5 | if (!this.zone) { 6 | return; 7 | } 8 | this.lat0 = 0; 9 | this.long0 = ((6 * Math.abs(this.zone)) - 183) * D2R; 10 | this.x0 = 500000; 11 | this.y0 = this.utmSouth ? 10000000 : 0; 12 | this.k0 = 0.9996; 13 | 14 | tmerc.init.apply(this); 15 | this.forward = tmerc.forward; 16 | this.inverse = tmerc.inverse; 17 | }; 18 | exports.names = ["Universal Transverse Mercator System", "utm"]; 19 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/SimplePoint.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | public class SimplePoint implements Point { 4 | private double x; 5 | private double y; 6 | 7 | public SimplePoint(double x, double y) { 8 | this.x = x; 9 | this.y = y; 10 | } 11 | 12 | public double getX() { 13 | return x; 14 | } 15 | 16 | public void setX(double x) { 17 | this.x = x; 18 | } 19 | 20 | public double getY() { 21 | return y; 22 | } 23 | 24 | public void setY(double y) { 25 | this.y = y; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/imlfn.js: -------------------------------------------------------------------------------- 1 | module.exports = function(ml, e0, e1, e2, e3) { 2 | var phi; 3 | var dphi; 4 | 5 | phi = ml / e0; 6 | for (var i = 0; i < 15; i++) { 7 | dphi = (ml - (e0 * phi - e1 * Math.sin(2 * phi) + e2 * Math.sin(4 * phi) - e3 * Math.sin(6 * phi))) / (e0 - 2 * e1 * Math.cos(2 * phi) + 4 * e2 * Math.cos(4 * phi) - 6 * e3 * Math.cos(6 * phi)); 8 | phi += dphi; 9 | if (Math.abs(dphi) <= 0.0000000001) { 10 | return phi; 11 | } 12 | } 13 | 14 | //..reportError("IMLFN-CONV:Latitude failed to converge after 15 iterations"); 15 | return NaN; 16 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proj4", 3 | "version": "2.3.15-alpha", 4 | "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.", 5 | "homepage": "https://github.com/proj4js/proj4js", 6 | "main": "dist/proj4.js", 7 | "keywords": [ 8 | "gis", 9 | "projections", 10 | "geospatial", 11 | "transform", 12 | "datum" 13 | ], 14 | "license": "MIT", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests", 21 | "almond", 22 | "src" 23 | ] 24 | } -------------------------------------------------------------------------------- /src/main/resources/proj4js/AUTHORS: -------------------------------------------------------------------------------- 1 | Mike Adair 2 | Richard Greenwood 3 | Calvin Metcalf 4 | Richard Marsden (http://www.winwaed.com) 5 | #credit for 6 | #src/projCode/gnom.js 7 | #src/projCode/cea.js 8 | T. Mittan 9 | #credit for 10 | #src/projCode/eqdc.js 11 | #src/projCode/equi.js 12 | #src/projCode/merc.js 13 | #src/projCode/mill.js 14 | #src/projCode/omerc.js 15 | #src/projCode/ortho.js 16 | #src/projCode/poly.js 17 | #src/projCode/poly.js 18 | D. Steinwand 19 | #credit for 20 | #src/projCode/merc.js 21 | #src/projCode/laea.js 22 | #src/projCode/moll.js 23 | S. Nelson 24 | #credit for 25 | #src/projCode/moll.js -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/nadInterBreakout.js: -------------------------------------------------------------------------------- 1 | module.exports = function(indx, frct, letter, number, ct) { 2 | var inx; 3 | if (indx[letter] < 0) { 4 | if (!(indx[letter] === -1 && frct[letter] > 0.99999999999)) { 5 | return false; 6 | } 7 | indx[letter]++; 8 | frct[letter] = 0; 9 | } 10 | else { 11 | inx = indx[letter] + 1; 12 | if (inx >= ct.lim[number]) { 13 | if (!(inx === ct.lim[number] && frct[letter] < 1e-11)) { 14 | return false; 15 | } 16 | if (letter === 'x') { 17 | indx[letter]--; 18 | } 19 | else { 20 | indx[letter]++; 21 | } 22 | frct[letter] = 1; 23 | } 24 | } 25 | return [indx, frct]; 26 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/pj_inv_mlfn.js: -------------------------------------------------------------------------------- 1 | var pj_mlfn = require("./pj_mlfn"); 2 | var EPSLN = 1.0e-10; 3 | var MAX_ITER = 20; 4 | module.exports = function(arg, es, en) { 5 | var k = 1 / (1 - es); 6 | var phi = arg; 7 | for (var i = MAX_ITER; i; --i) { /* rarely goes over 2 iterations */ 8 | var s = Math.sin(phi); 9 | var t = 1 - es * s * s; 10 | //t = this.pj_mlfn(phi, s, Math.cos(phi), en) - arg; 11 | //phi -= t * (t * Math.sqrt(t)) * k; 12 | t = (pj_mlfn(phi, s, Math.cos(phi), en) - arg) * (t * Math.sqrt(t)) * k; 13 | phi -= t; 14 | if (Math.abs(t) < EPSLN) { 15 | return phi; 16 | } 17 | } 18 | //..reportError("cass:pj_inv_mlfn: Convergence error"); 19 | return phi; 20 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/constants/PrimeMeridian.js: -------------------------------------------------------------------------------- 1 | exports.greenwich = 0.0; //"0dE", 2 | exports.lisbon = -9.131906111111; //"9d07'54.862\"W", 3 | exports.paris = 2.337229166667; //"2d20'14.025\"E", 4 | exports.bogota = -74.080916666667; //"74d04'51.3\"W", 5 | exports.madrid = -3.687938888889; //"3d41'16.58\"W", 6 | exports.rome = 12.452333333333; //"12d27'8.4\"E", 7 | exports.bern = 7.439583333333; //"7d26'22.5\"E", 8 | exports.jakarta = 106.807719444444; //"106d48'27.79\"E", 9 | exports.ferro = -17.666666666667; //"17d40'W", 10 | exports.brussels = 4.367975; //"4d22'4.71\"E", 11 | exports.stockholm = 18.058277777778; //"18d3'29.8\"E", 12 | exports.athens = 23.7163375; //"23d42'58.815\"E", 13 | exports.oslo = 10.722916666667; //"10d43'22.5\"E" -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/pj_enfn.js: -------------------------------------------------------------------------------- 1 | var C00 = 1; 2 | var C02 = 0.25; 3 | var C04 = 0.046875; 4 | var C06 = 0.01953125; 5 | var C08 = 0.01068115234375; 6 | var C22 = 0.75; 7 | var C44 = 0.46875; 8 | var C46 = 0.01302083333333333333; 9 | var C48 = 0.00712076822916666666; 10 | var C66 = 0.36458333333333333333; 11 | var C68 = 0.00569661458333333333; 12 | var C88 = 0.3076171875; 13 | 14 | module.exports = function(es) { 15 | var en = []; 16 | en[0] = C00 - es * (C02 + es * (C04 + es * (C06 + es * C08))); 17 | en[1] = es * (C22 - es * (C04 + es * (C06 + es * C08))); 18 | var t = es * es; 19 | en[2] = t * (C44 - es * (C46 + es * C48)); 20 | t *= es; 21 | en[3] = t * (C66 - es * C68); 22 | en[4] = t * es * C88; 23 | return en; 24 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # proj4m 2 | 3 | [![Circle CI](https://circleci.com/gh/MapTalks/proj4m.svg?style=svg)](https://circleci.com/gh/MapTalks/proj4m) 4 | 5 | proj 4 mapresty 6 | 7 | ## supported projection 8 | - Normal 9 | - EPSG:3857, `+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs` 10 | - EPSG:4326, `+proj=longlat +datum=WGS84 +no_defs` 11 | - GCJ02 12 | - GCJ02, `+proj=longlat +dataum=GCJ02` 13 | - GCJ02MC, `+proj=merc +datum=GCJ02` 14 | - BD09 15 | - BD09LL, `+proj=longlat +datum=BD09` 16 | - BD09MC, `+proj=bmerc +datum=BD09` 17 | 18 | ## Usage 19 | ``` 20 | Proj4 proj = new Proj4("GCJ02", "+proj=merc +datum=GCJ02"); 21 | proj.forward(new double[]{120.0, 30.0}); 22 | ``` 23 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/global.js: -------------------------------------------------------------------------------- 1 | module.exports = function(defs) { 2 | defs('EPSG:4326', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"); 3 | defs('EPSG:4269', "+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees"); 4 | defs('EPSG:3857', "+title=WGS 84 / Pseudo-Mercator +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs"); 5 | 6 | defs.WGS84 = defs['EPSG:4326']; 7 | defs['EPSG:3785'] = defs['EPSG:3857']; // maintain backward compat, official code is 3857 8 | defs.GOOGLE = defs['EPSG:3857']; 9 | defs['EPSG:900913'] = defs['EPSG:3857']; 10 | defs['EPSG:102113'] = defs['EPSG:3857']; 11 | }; 12 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/nad_cvt.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('./adjust_lon'); 2 | var nad_intr = require('./nad_intr'); 3 | var inverseNadCvt = require('./inverseNadCvt'); 4 | 5 | module.exports = function(pin, inverse, ct) { 6 | var val = { 7 | "x": Number.NaN, 8 | "y": Number.NaN 9 | }; 10 | if (isNaN(pin.x)) { 11 | return val; 12 | } 13 | var tb = { 14 | "x": pin.x, 15 | "y": pin.y 16 | }; 17 | tb.x -= ct.ll[0]; 18 | tb.y -= ct.ll[1]; 19 | tb.x = adjust_lon(tb.x - Math.PI) + Math.PI; 20 | var t = nad_intr(tb, ct); 21 | if (inverse) { 22 | return inverseNadCvt(t, val, tb, ct); 23 | } 24 | else { 25 | if (!isNaN(t.x)) { 26 | val.x = pin.x - t.x; 27 | val.y = pin.y + t.y; 28 | } 29 | } 30 | return val; 31 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/inverseNadCvt.js: -------------------------------------------------------------------------------- 1 | var nad_intr = require('./nad_intr'); 2 | var adjust_lon = require('./adjust_lon'); 3 | module.exports = function(t, val, tb, ct) { 4 | if (isNaN(t.x)) { 5 | return val; 6 | } 7 | t.x = tb.x + t.x; 8 | t.y = tb.y - t.y; 9 | var i = 9, 10 | tol = 1e-12; 11 | var dif, del; 12 | do { 13 | del = nad_intr(t, ct); 14 | if (isNaN(del.x)) { 15 | break; 16 | } 17 | dif = { 18 | "x": t.x - del.x - tb.x, 19 | "y": t.y + del.y - tb.y 20 | }; 21 | t.x -= dif.x; 22 | t.y -= dif.y; 23 | } while (i-- && Math.abs(dif.x) > tol && Math.abs(dif.y) > tol); 24 | if (i < 0) { 25 | return val; 26 | } 27 | val.x = adjust_lon(t.x + ct.ll[0]); 28 | val.y = t.y + ct.ll[1]; 29 | return val; 30 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections.js: -------------------------------------------------------------------------------- 1 | var projs = [ 2 | require('./projections/merc'), 3 | require('./projections/longlat') 4 | ]; 5 | var names = {}; 6 | var projStore = []; 7 | 8 | function add(proj, i) { 9 | var len = projStore.length; 10 | if (!proj.names) { 11 | console.log(i); 12 | return true; 13 | } 14 | projStore[len] = proj; 15 | proj.names.forEach(function(n) { 16 | names[n.toLowerCase()] = len; 17 | }); 18 | return this; 19 | } 20 | 21 | exports.add = add; 22 | 23 | exports.get = function(name) { 24 | if (!name) { 25 | return false; 26 | } 27 | var n = name.toLowerCase(); 28 | if (typeof names[n] !== 'undefined' && projStore[names[n]]) { 29 | return projStore[names[n]]; 30 | } 31 | }; 32 | exports.start = function() { 33 | projs.forEach(add); 34 | }; 35 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/test/opt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha Tests 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/ProjString.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | class ProjString { 4 | 5 | static Proj parse(String srs) { 6 | Proj proj = new Proj(); 7 | String projName = null; 8 | String datumCode = null; 9 | String[] parts = srs.split("\\+"); 10 | for (String part : parts) { 11 | String s = part.trim(); 12 | String[] kv = s.split("="); 13 | if (kv.length != 2) continue; 14 | String k = kv[0]; 15 | String v = kv[1]; 16 | if ("proj".equals(k)) { 17 | projName = v; 18 | } else if ("datum".equals(k)) { 19 | datumCode = v; 20 | } 21 | } 22 | proj.setProjName(projName); 23 | proj.setDatumCode(datumCode); 24 | 25 | return proj; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/changelog.md: -------------------------------------------------------------------------------- 1 | Change log 2 | === 3 | - 2.2.1: Documentation fixes and added proj4.defs('name') as an alias for proj4.defs['name']; 4 | 5 | - 2.1.4: dist folder is added back in after accidentally omitting it in 2.1.1 6 | 7 | - 2.1.3: skipped as issues with the dist folder are ironed out. 8 | 9 | - 2.1.2: added sensible defaults for false eastings/northings 10 | 11 | - 2.1.1: tweaks to how we publish it, fixes related to errors with the OSGB36 and Reseau National Belge 1972 datums, we took the first steps towards depreciating the proj4.Point class. 12 | 13 | - 2.1.0: targeted builds for projections are now supported, and internally projection creation is more modular. 14 | 15 | - 2.0.3: mgrs is broken out into it's own module loaded via npm. 16 | 17 | - 2.0.2: module common is broken up into a collection of smaller modules. 18 | 19 | - 2.0.1: fix typo in eqc projection. 20 | 21 | - 2.0.0: we start the change log. -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/parseCode.js: -------------------------------------------------------------------------------- 1 | var defs = require('./defs'); 2 | var wkt = require('./wkt'); 3 | var projStr = require('./projString'); 4 | function testObj(code){ 5 | return typeof code === 'string'; 6 | } 7 | function testDef(code){ 8 | return code in defs; 9 | } 10 | function testWKT(code){ 11 | var codeWords = ['GEOGCS','GEOCCS','PROJCS','LOCAL_CS']; 12 | return codeWords.reduce(function(a,b){ 13 | return a+1+code.indexOf(b); 14 | },0); 15 | } 16 | function testProj(code){ 17 | return code[0] === '+'; 18 | } 19 | function parse(code){ 20 | if (testObj(code)) { 21 | //check to see if this is a WKT string 22 | if (testDef(code)) { 23 | return defs[code]; 24 | } 25 | else if (testWKT(code)) { 26 | return wkt(code); 27 | } 28 | else if (testProj(code)) { 29 | return projStr(code); 30 | } 31 | }else{ 32 | return code; 33 | } 34 | } 35 | 36 | module.exports = parse; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/Proj.js: -------------------------------------------------------------------------------- 1 | var parseCode = require("./parseCode"); 2 | var extend = require('./extend'); 3 | var projections = require('./projections'); 4 | var deriveConstants = require('./deriveConstants'); 5 | 6 | function Projection(srsCode,callback) { 7 | if (!(this instanceof Projection)) { 8 | return new Projection(srsCode); 9 | } 10 | callback = callback || function(error){ 11 | if(error){ 12 | throw error; 13 | } 14 | }; 15 | var json = parseCode(srsCode); 16 | if(typeof json !== 'object'){ 17 | callback(srsCode); 18 | return; 19 | } 20 | var modifiedJSON = deriveConstants(json); 21 | var ourProj = Projection.projections.get(modifiedJSON.projName); 22 | if(ourProj){ 23 | extend(this, modifiedJSON); 24 | extend(this, ourProj); 25 | this.init(); 26 | callback(null, this); 27 | }else{ 28 | callback(srsCode); 29 | } 30 | } 31 | Projection.projections = projections; 32 | Projection.projections.start(); 33 | module.exports = Projection; 34 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/includedProjections.js: -------------------------------------------------------------------------------- 1 | var projs = [ 2 | require('./projections/tmerc'), 3 | require('./projections/utm'), 4 | require('./projections/sterea'), 5 | require('./projections/stere'), 6 | require('./projections/somerc'), 7 | require('./projections/omerc'), 8 | require('./projections/lcc'), 9 | require('./projections/krovak'), 10 | require('./projections/cass'), 11 | require('./projections/laea'), 12 | require('./projections/aea'), 13 | require('./projections/gnom'), 14 | require('./projections/cea'), 15 | require('./projections/eqc'), 16 | require('./projections/poly'), 17 | require('./projections/nzmg'), 18 | require('./projections/mill'), 19 | require('./projections/sinu'), 20 | require('./projections/moll'), 21 | require('./projections/eqdc'), 22 | require('./projections/vandg'), 23 | require('./projections/aeqd') 24 | ]; 25 | module.exports = function(proj4){ 26 | projs.forEach(function(proj){ 27 | proj4.Proj.projections.add(proj); 28 | }); 29 | }; -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Proj.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | class Proj { 4 | 5 | private String projName; 6 | private String datumCode; 7 | 8 | String getProjName() { 9 | return projName; 10 | } 11 | 12 | void setProjName(String projName) { 13 | this.projName = projName; 14 | } 15 | 16 | String getDatumCode() { 17 | return datumCode; 18 | } 19 | 20 | void setDatumCode(String datumCode) { 21 | this.datumCode = datumCode; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object obj) { 26 | if (!(obj instanceof Proj)) { 27 | return false; 28 | } 29 | Proj o = ((Proj) obj); 30 | return eql(this.projName, o.projName) && eql(this.datumCode, o.datumCode); 31 | } 32 | 33 | private boolean eql(Object a, Object b) { 34 | if (a != null) { 35 | return b != null && a.equals(b); 36 | } else { 37 | return b == null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/iqsfnz.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | 3 | module.exports = function(eccent, q) { 4 | var temp = 1 - (1 - eccent * eccent) / (2 * eccent) * Math.log((1 - eccent) / (1 + eccent)); 5 | if (Math.abs(Math.abs(q) - temp) < 1.0E-6) { 6 | if (q < 0) { 7 | return (-1 * HALF_PI); 8 | } 9 | else { 10 | return HALF_PI; 11 | } 12 | } 13 | //var phi = 0.5* q/(1-eccent*eccent); 14 | var phi = Math.asin(0.5 * q); 15 | var dphi; 16 | var sin_phi; 17 | var cos_phi; 18 | var con; 19 | for (var i = 0; i < 30; i++) { 20 | sin_phi = Math.sin(phi); 21 | cos_phi = Math.cos(phi); 22 | con = eccent * sin_phi; 23 | dphi = Math.pow(1 - con * con, 2) / (2 * cos_phi) * (q / (1 - eccent * eccent) - sin_phi / (1 - con * con) + 0.5 / eccent * Math.log((1 - con) / (1 + con))); 24 | phi += dphi; 25 | if (Math.abs(dphi) <= 0.0000000001) { 26 | return phi; 27 | } 28 | } 29 | 30 | //console.log("IQSFN-CONV:Latitude failed to converge after 30 iterations"); 31 | return NaN; 32 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/Point.js: -------------------------------------------------------------------------------- 1 | var mgrs = require('mgrs'); 2 | 3 | function Point(x, y, z) { 4 | if (!(this instanceof Point)) { 5 | return new Point(x, y, z); 6 | } 7 | if (Array.isArray(x)) { 8 | this.x = x[0]; 9 | this.y = x[1]; 10 | this.z = x[2] || 0.0; 11 | } else if(typeof x === 'object') { 12 | this.x = x.x; 13 | this.y = x.y; 14 | this.z = x.z || 0.0; 15 | } else if (typeof x === 'string' && typeof y === 'undefined') { 16 | var coords = x.split(','); 17 | this.x = parseFloat(coords[0], 10); 18 | this.y = parseFloat(coords[1], 10); 19 | this.z = parseFloat(coords[2], 10) || 0.0; 20 | } else { 21 | this.x = x; 22 | this.y = y; 23 | this.z = z || 0.0; 24 | } 25 | console.warn('proj4.Point will be removed in version 3, use proj4.toPoint'); 26 | } 27 | 28 | Point.fromMGRS = function(mgrsStr) { 29 | return new Point(mgrs.toPoint(mgrsStr)); 30 | }; 31 | Point.prototype.toMGRS = function(accuracy) { 32 | return mgrs.forward([this.x, this.y], accuracy); 33 | }; 34 | module.exports = Point; 35 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Parser.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | class Parser { 4 | 5 | private static final String[] codeWords = new String[]{ 6 | "GEOGCS", "GEOCCS", "PROJCS", "LOCAL_CS" 7 | }; 8 | 9 | static Proj parseCode(String code) throws Proj4Exception { 10 | if (testDef(code)) { 11 | return Global.def(code); 12 | } 13 | 14 | if (testWKT(code)) { 15 | return WKTParser.parse(code); 16 | } 17 | 18 | if (testProj(code)) { 19 | return ProjString.parse(code); 20 | } 21 | 22 | throw new Proj4Exception(String.format("Unknown code: '%s'", code)); 23 | } 24 | 25 | private static boolean testDef(String name) { 26 | return Global.has(name); 27 | } 28 | 29 | static boolean testWKT(String code) { 30 | int a = 0; 31 | for (String word : codeWords) { 32 | a = a + 1 + code.indexOf(word); 33 | } 34 | return a > 0; 35 | } 36 | 37 | static boolean testProj(String code) { 38 | return code.startsWith("+"); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/DatumTransform.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | import org.maptalks.proj4.datum.BD09LL; 4 | import org.maptalks.proj4.datum.Datum; 5 | 6 | class DatumTransform { 7 | 8 | static T transform(String srcCode, String dstCode, T point, PointAdaptor pointAdaptor) throws Proj4Exception { 9 | if (srcCode == null || dstCode == null) { 10 | return point; 11 | } 12 | 13 | if (srcCode.equals(dstCode)) { 14 | return point; 15 | } 16 | 17 | Datum srcDatum = DatumCache.get(srcCode); 18 | Datum dstDatum = DatumCache.get(dstCode); 19 | 20 | if (srcCode.equalsIgnoreCase("GCJ02") && dstCode.equalsIgnoreCase("BD09")) { 21 | return BD09LL.fromGCJ02(point, pointAdaptor); 22 | } 23 | 24 | if (dstCode.equalsIgnoreCase("GCJ02") && srcCode.equalsIgnoreCase("BD09")) { 25 | return BD09LL.toGCJ02(point, pointAdaptor); 26 | } 27 | 28 | T wgs84 = srcDatum.toWGS84(point, pointAdaptor); 29 | 30 | return dstDatum.fromWGS84(wgs84, pointAdaptor); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/constants/grids.js: -------------------------------------------------------------------------------- 1 | // Based on . CTABLE structure : 2 | // FIXME: better to have array instead of object holding longitudes, latitudes members 3 | // In the former case, one has to document index 0 is longitude and 4 | // 1 is latitude ... 5 | // In the later case, grid object gets bigger !!!! 6 | // Solution 1 is chosen based on pj_gridinfo.c 7 | exports.null = { // name of grid's file 8 | "ll": [-3.14159265, - 1.57079633], // lower-left coordinates in radians (longitude, latitude): 9 | "del": [3.14159265, 1.57079633], // cell's size in radians (longitude, latitude): 10 | "lim": [3, 3], // number of nodes in longitude, latitude (including edges): 11 | "count": 9, // total number of nodes 12 | "cvs": [ // shifts : in ntv2 reverse order : lon, lat in radians ... 13 | [0.0, 0.0], 14 | [0.0, 0.0], 15 | [0.0, 0.0], // for (lon= 0; lon T transform(Proj srcProj, Proj dstProj, T point, PointAdaptor pointAdaptor) throws Proj4Exception { 9 | String srcProjName = srcProj.getProjName(); 10 | String dstProjName = dstProj.getProjName(); 11 | Projection srcProjection = ProjectionCache.get(srcProjName); 12 | Projection dstProjection = ProjectionCache.get(dstProjName); 13 | if (srcProjection.getType() == ProjectionType.PROJECTED) { 14 | point = srcProjection.inverse(point, pointAdaptor); 15 | } 16 | 17 | String srcDatumCode = srcProj.getDatumCode(); 18 | String dstDatumCode = dstProj.getDatumCode(); 19 | point = DatumTransform.transform(srcDatumCode, dstDatumCode, point, pointAdaptor); 20 | 21 | if (dstProjection.getType() == ProjectionType.PROJECTED) { 22 | point = dstProjection.forward(point, pointAdaptor); 23 | } 24 | 25 | return point; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/equi.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | exports.init = function() { 3 | this.x0 = this.x0 || 0; 4 | this.y0 = this.y0 || 0; 5 | this.lat0 = this.lat0 || 0; 6 | this.long0 = this.long0 || 0; 7 | ///this.t2; 8 | }; 9 | 10 | 11 | 12 | /* Equirectangular forward equations--mapping lat,long to x,y 13 | ---------------------------------------------------------*/ 14 | exports.forward = function(p) { 15 | 16 | var lon = p.x; 17 | var lat = p.y; 18 | 19 | var dlon = adjust_lon(lon - this.long0); 20 | var x = this.x0 + this.a * dlon * Math.cos(this.lat0); 21 | var y = this.y0 + this.a * lat; 22 | 23 | this.t1 = x; 24 | this.t2 = Math.cos(this.lat0); 25 | p.x = x; 26 | p.y = y; 27 | return p; 28 | }; 29 | 30 | 31 | 32 | /* Equirectangular inverse equations--mapping x,y to lat/long 33 | ---------------------------------------------------------*/ 34 | exports.inverse = function(p) { 35 | 36 | p.x -= this.x0; 37 | p.y -= this.y0; 38 | var lat = p.y / this.a; 39 | 40 | var lon = adjust_lon(this.long0 + p.x / (this.a * Math.cos(this.lat0))); 41 | p.x = lon; 42 | p.y = lat; 43 | }; 44 | exports.names = ["equi"]; 45 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/adjust_axis.js: -------------------------------------------------------------------------------- 1 | module.exports = function(crs, denorm, point) { 2 | var xin = point.x, 3 | yin = point.y, 4 | zin = point.z || 0.0; 5 | var v, t, i; 6 | for (i = 0; i < 3; i++) { 7 | if (denorm && i === 2 && point.z === undefined) { 8 | continue; 9 | } 10 | if (i === 0) { 11 | v = xin; 12 | t = 'x'; 13 | } 14 | else if (i === 1) { 15 | v = yin; 16 | t = 'y'; 17 | } 18 | else { 19 | v = zin; 20 | t = 'z'; 21 | } 22 | switch (crs.axis[i]) { 23 | case 'e': 24 | point[t] = v; 25 | break; 26 | case 'w': 27 | point[t] = -v; 28 | break; 29 | case 'n': 30 | point[t] = v; 31 | break; 32 | case 's': 33 | point[t] = -v; 34 | break; 35 | case 'u': 36 | if (point[t] !== undefined) { 37 | point.z = v; 38 | } 39 | break; 40 | case 'd': 41 | if (point[t] !== undefined) { 42 | point.z = -v; 43 | } 44 | break; 45 | default: 46 | //console.log("ERROR: unknow axis ("+crs.axis[i]+") - check definition of "+crs.projName); 47 | return null; 48 | } 49 | } 50 | return point; 51 | }; 52 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/DatumCache.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import org.maptalks.proj4.datum.BD09LL; 6 | import org.maptalks.proj4.datum.CGCS2000; 7 | import org.maptalks.proj4.datum.Datum; 8 | import org.maptalks.proj4.datum.GCJ02; 9 | import org.maptalks.proj4.datum.WGS84; 10 | 11 | class DatumCache { 12 | 13 | private static Map cache = new HashMap(); 14 | 15 | static { 16 | Datum wgs84 = new WGS84(); 17 | Datum gcj02 = new GCJ02(); 18 | Datum bd09ll = new BD09LL(); 19 | Datum cgcs2000 = new CGCS2000(); 20 | cache.put("wgs84", wgs84); 21 | cache.put("gcj02", gcj02); 22 | cache.put("bd09", bd09ll); 23 | cache.put("cgcs2000", cgcs2000); 24 | } 25 | 26 | public static Datum get(String name) throws Proj4Exception { 27 | if (name == null || name.trim().length() == 0) { 28 | return cache.get("wgs84"); 29 | } 30 | name = name.toLowerCase(); 31 | if (cache.containsKey(name)) { 32 | return cache.get(name); 33 | } else { 34 | throw new Proj4Exception(String.format("No such datum: %s", name)); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/eqc.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var adjust_lat = require('../common/adjust_lat'); 3 | exports.init = function() { 4 | 5 | this.x0 = this.x0 || 0; 6 | this.y0 = this.y0 || 0; 7 | this.lat0 = this.lat0 || 0; 8 | this.long0 = this.long0 || 0; 9 | this.lat_ts = this.lat_ts || 0; 10 | this.title = this.title || "Equidistant Cylindrical (Plate Carre)"; 11 | 12 | this.rc = Math.cos(this.lat_ts); 13 | }; 14 | 15 | 16 | // forward equations--mapping lat,long to x,y 17 | // ----------------------------------------------------------------- 18 | exports.forward = function(p) { 19 | 20 | var lon = p.x; 21 | var lat = p.y; 22 | 23 | var dlon = adjust_lon(lon - this.long0); 24 | var dlat = adjust_lat(lat - this.lat0); 25 | p.x = this.x0 + (this.a * dlon * this.rc); 26 | p.y = this.y0 + (this.a * dlat); 27 | return p; 28 | }; 29 | 30 | // inverse equations--mapping x,y to lat/long 31 | // ----------------------------------------------------------------- 32 | exports.inverse = function(p) { 33 | 34 | var x = p.x; 35 | var y = p.y; 36 | 37 | p.x = adjust_lon(this.long0 + ((x - this.x0) / (this.a * this.rc))); 38 | p.y = adjust_lat(this.lat0 + ((y - this.y0) / (this.a))); 39 | return p; 40 | }; 41 | exports.names = ["Equirectangular", "Equidistant_Cylindrical", "eqc"]; 42 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "proj4", 3 | "version": "2.3.15-alpha", 4 | "description": "Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations.", 5 | "main": "lib/index.js", 6 | "directories": { 7 | "test": "test", 8 | "doc": "docs" 9 | }, 10 | "scripts": { 11 | "test": "./node_modules/istanbul/lib/cli.js test ./node_modules/mocha/bin/_mocha test/test.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git://github.com/proj4js/proj4js.git" 16 | }, 17 | "author": "", 18 | "license": "MIT", 19 | "jam": { 20 | "main": "dist/proj4.js", 21 | "include": [ 22 | "dist/proj4.js", 23 | "README.md", 24 | "AUTHORS", 25 | "LICENSE.md" 26 | ] 27 | }, 28 | "devDependencies": { 29 | "grunt-cli": "~0.1.13", 30 | "grunt": "~0.4.2", 31 | "grunt-contrib-connect": "~0.6.0", 32 | "grunt-contrib-jshint": "~0.8.0", 33 | "chai": "~1.8.1", 34 | "mocha": "~1.17.1", 35 | "grunt-mocha-phantomjs": "~0.4.0", 36 | "browserify": "~12.0.1", 37 | "grunt-browserify": "~4.0.1", 38 | "grunt-contrib-uglify": "~0.11.1", 39 | "curl": "git://github.com/cujojs/curl.git", 40 | "istanbul": "~0.2.4", 41 | "tin": "~0.4.0" 42 | }, 43 | "dependencies": { 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/projection/SphericalMercator.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.projection; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class SphericalMercator implements Projection { 6 | 7 | private static final double R = 6378137; 8 | private static final double MAX_LATITUDE = 85.0511287798; 9 | 10 | public T forward(T point, PointAdaptor pointAdaptor) { 11 | double d = Math.PI / 180; 12 | double max = MAX_LATITUDE; 13 | double lat = Math.max(Math.min(max, pointAdaptor.getY(point)), -max); 14 | double sin = Math.sin(lat * d); 15 | 16 | double x = R * pointAdaptor.getX(point) * d; 17 | double y = R * Math.log((1 + sin) / (1 - sin)) / 2; 18 | 19 | pointAdaptor.setX(point, x); 20 | pointAdaptor.setY(point, y); 21 | 22 | return point; 23 | } 24 | 25 | public T inverse(T point, PointAdaptor pointAdaptor) { 26 | double d = 180 / Math.PI; 27 | double lng = pointAdaptor.getX(point) * d / R; 28 | double lat = (2 * Math.atan(Math.exp(pointAdaptor.getY(point) / R)) - (Math.PI / 2)) * d; 29 | 30 | pointAdaptor.setX(point, lng); 31 | pointAdaptor.setY(point, lat); 32 | 33 | return point; 34 | } 35 | 36 | public ProjectionType getType() { 37 | return ProjectionType.PROJECTED; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/defs.js: -------------------------------------------------------------------------------- 1 | var globals = require('./global'); 2 | var parseProj = require('./projString'); 3 | var wkt = require('./wkt'); 4 | 5 | function defs(name) { 6 | /*global console*/ 7 | var that = this; 8 | if (arguments.length === 2) { 9 | var def = arguments[1]; 10 | if (typeof def === 'string') { 11 | if (def.charAt(0) === '+') { 12 | defs[name] = parseProj(arguments[1]); 13 | } 14 | else { 15 | defs[name] = wkt(arguments[1]); 16 | } 17 | } else { 18 | defs[name] = def; 19 | } 20 | } 21 | else if (arguments.length === 1) { 22 | if (Array.isArray(name)) { 23 | return name.map(function(v) { 24 | if (Array.isArray(v)) { 25 | defs.apply(that, v); 26 | } 27 | else { 28 | defs(v); 29 | } 30 | }); 31 | } 32 | else if (typeof name === 'string') { 33 | if (name in defs) { 34 | return defs[name]; 35 | } 36 | } 37 | else if ('EPSG' in name) { 38 | defs['EPSG:' + name.EPSG] = name; 39 | } 40 | else if ('ESRI' in name) { 41 | defs['ESRI:' + name.ESRI] = name; 42 | } 43 | else if ('IAU2000' in name) { 44 | defs['IAU2000:' + name.IAU2000] = name; 45 | } 46 | else { 47 | console.log(name); 48 | } 49 | return; 50 | } 51 | 52 | 53 | } 54 | globals(defs); 55 | module.exports = defs; 56 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/ProjectionCache.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import org.maptalks.proj4.projection.BaiduMercator; 6 | import org.maptalks.proj4.projection.LonLat; 7 | import org.maptalks.proj4.projection.Projection; 8 | import org.maptalks.proj4.projection.SphericalMercator; 9 | 10 | class ProjectionCache { 11 | 12 | private static Map cache = new HashMap(); 13 | 14 | static { 15 | Projection merc = new SphericalMercator(); 16 | Projection baidu = new BaiduMercator(); 17 | Projection longlat = new LonLat(); 18 | cache.put("merc", merc); 19 | cache.put("bmerc", baidu); 20 | cache.put("longlat", longlat); 21 | cache.put("latlong", longlat); 22 | cache.put("lnglat", longlat); 23 | cache.put("latlng", longlat); 24 | cache.put("identity", longlat); 25 | } 26 | 27 | public static Projection get(String name) throws Proj4Exception { 28 | if (name == null || name.trim().length() == 0) { 29 | return cache.get("merc"); 30 | } 31 | name = name.toLowerCase(); 32 | if (cache.containsKey(name)) { 33 | return cache.get(name); 34 | } else { 35 | throw new Proj4Exception(String.format("No such projection: %s", name)); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/mill.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | /* 3 | reference 4 | "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, 5 | The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. 6 | */ 7 | 8 | 9 | /* Initialize the Miller Cylindrical projection 10 | -------------------------------------------*/ 11 | exports.init = function() { 12 | //no-op 13 | }; 14 | 15 | 16 | /* Miller Cylindrical forward equations--mapping lat,long to x,y 17 | ------------------------------------------------------------*/ 18 | exports.forward = function(p) { 19 | var lon = p.x; 20 | var lat = p.y; 21 | /* Forward equations 22 | -----------------*/ 23 | var dlon = adjust_lon(lon - this.long0); 24 | var x = this.x0 + this.a * dlon; 25 | var y = this.y0 + this.a * Math.log(Math.tan((Math.PI / 4) + (lat / 2.5))) * 1.25; 26 | 27 | p.x = x; 28 | p.y = y; 29 | return p; 30 | }; 31 | 32 | /* Miller Cylindrical inverse equations--mapping x,y to lat/long 33 | ------------------------------------------------------------*/ 34 | exports.inverse = function(p) { 35 | p.x -= this.x0; 36 | p.y -= this.y0; 37 | 38 | var lon = adjust_lon(this.long0 + p.x / this.a); 39 | var lat = 2.5 * (Math.atan(Math.exp(0.8 * p.y / this.a)) - Math.PI / 4); 40 | 41 | p.x = lon; 42 | p.y = lat; 43 | return p; 44 | }; 45 | exports.names = ["Miller_Cylindrical", "mill"]; 46 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/gauss.js: -------------------------------------------------------------------------------- 1 | var FORTPI = Math.PI/4; 2 | var srat = require('../common/srat'); 3 | var HALF_PI = Math.PI/2; 4 | var MAX_ITER = 20; 5 | exports.init = function() { 6 | var sphi = Math.sin(this.lat0); 7 | var cphi = Math.cos(this.lat0); 8 | cphi *= cphi; 9 | this.rc = Math.sqrt(1 - this.es) / (1 - this.es * sphi * sphi); 10 | this.C = Math.sqrt(1 + this.es * cphi * cphi / (1 - this.es)); 11 | this.phic0 = Math.asin(sphi / this.C); 12 | this.ratexp = 0.5 * this.C * this.e; 13 | this.K = Math.tan(0.5 * this.phic0 + FORTPI) / (Math.pow(Math.tan(0.5 * this.lat0 + FORTPI), this.C) * srat(this.e * sphi, this.ratexp)); 14 | }; 15 | 16 | exports.forward = function(p) { 17 | var lon = p.x; 18 | var lat = p.y; 19 | 20 | p.y = 2 * Math.atan(this.K * Math.pow(Math.tan(0.5 * lat + FORTPI), this.C) * srat(this.e * Math.sin(lat), this.ratexp)) - HALF_PI; 21 | p.x = this.C * lon; 22 | return p; 23 | }; 24 | 25 | exports.inverse = function(p) { 26 | var DEL_TOL = 1e-14; 27 | var lon = p.x / this.C; 28 | var lat = p.y; 29 | var num = Math.pow(Math.tan(0.5 * lat + FORTPI) / this.K, 1 / this.C); 30 | for (var i = MAX_ITER; i > 0; --i) { 31 | lat = 2 * Math.atan(num * srat(this.e * Math.sin(p.y), - 0.5 * this.e)) - HALF_PI; 32 | if (Math.abs(lat - p.y) < DEL_TOL) { 33 | break; 34 | } 35 | p.y = lat; 36 | } 37 | /* convergence failed */ 38 | if (!i) { 39 | return null; 40 | } 41 | p.x = lon; 42 | p.y = lat; 43 | return p; 44 | }; 45 | exports.names = ["gauss"]; 46 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Global.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | public class Global { 6 | 7 | private static ConcurrentHashMap defs = new ConcurrentHashMap(); 8 | 9 | static { 10 | def("EPSG:4326", "+proj=longlat +datum=WGS84 +no_defs"); 11 | def("WGS84", "+proj=longlat +datum=WGS84 +no_defs"); 12 | def("EPSG:3857", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"); 13 | def("GCJ02", "+proj=longlat +datum=GCJ02"); 14 | def("GCJ02MC", "+proj=merc +datum=GCJ02"); 15 | def("BD09LL", "+proj=longlat +datum=BD09"); 16 | def("BD09MC", "+proj=bmerc +datum=BD09"); 17 | def("IDENTITY", "+proj=identity +no_defs"); 18 | } 19 | 20 | private static String normalize(String name) { 21 | return name.toUpperCase(); 22 | } 23 | 24 | static boolean has(String name) { 25 | String key = normalize(name); 26 | return defs.containsKey(key); 27 | } 28 | 29 | static Proj def(String name) { 30 | String key = normalize(name); 31 | return defs.get(key); 32 | } 33 | 34 | public static void def(String name, String code) { 35 | String key = normalize(name); 36 | if (code.startsWith("+")) { 37 | defs.put(key, ProjString.parse(code)); 38 | } else { 39 | defs.put(key, WKTParser.parse(code)); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/LICENSE.md: -------------------------------------------------------------------------------- 1 | ##Proj4js -- Javascript reprojection library. 2 | 3 | Authors: 4 | - Mike Adair madairATdmsolutions.ca 5 | - Richard Greenwood richATgreenwoodmap.com 6 | - Didier Richard didier.richardATign.fr 7 | - Stephen Irons stephen.ironsATclear.net.nz 8 | - Olivier Terral oterralATgmail.com 9 | - Calvin Metcalf cmetcalfATappgeo.com 10 | 11 | Copyright (c) 2014, Mike Adair, Richard Greenwood, Didier Richard, Stephen Irons, Olivier Terral and Calvin Metcalf 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a 14 | copy of this software and associated documentation files (the "Software"), 15 | to deal in the Software without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included 21 | in all copies or substantial portions of the Software. 22 | 23 | _THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 | DEALINGS IN THE SOFTWARE._ -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/core.js: -------------------------------------------------------------------------------- 1 | var proj = require('./Proj'); 2 | var transform = require('./transform'); 3 | var wgs84 = proj('WGS84'); 4 | 5 | function transformer(from, to, coords) { 6 | var transformedArray; 7 | if (Array.isArray(coords)) { 8 | transformedArray = transform(from, to, coords); 9 | if (coords.length === 3) { 10 | return [transformedArray.x, transformedArray.y, transformedArray.z]; 11 | } 12 | else { 13 | return [transformedArray.x, transformedArray.y]; 14 | } 15 | } 16 | else { 17 | return transform(from, to, coords); 18 | } 19 | } 20 | 21 | function checkProj(item) { 22 | if (item instanceof proj) { 23 | return item; 24 | } 25 | if (item.oProj) { 26 | return item.oProj; 27 | } 28 | return proj(item); 29 | } 30 | function proj4(fromProj, toProj, coord) { 31 | fromProj = checkProj(fromProj); 32 | var single = false; 33 | var obj; 34 | if (typeof toProj === 'undefined') { 35 | toProj = fromProj; 36 | fromProj = wgs84; 37 | single = true; 38 | } 39 | else if (typeof toProj.x !== 'undefined' || Array.isArray(toProj)) { 40 | coord = toProj; 41 | toProj = fromProj; 42 | fromProj = wgs84; 43 | single = true; 44 | } 45 | toProj = checkProj(toProj); 46 | if (coord) { 47 | return transformer(fromProj, toProj, coord); 48 | } 49 | else { 50 | obj = { 51 | forward: function(coords) { 52 | return transformer(fromProj, toProj, coords); 53 | }, 54 | inverse: function(coords) { 55 | return transformer(toProj, fromProj, coords); 56 | } 57 | }; 58 | if (single) { 59 | obj.oProj = toProj; 60 | } 61 | return obj; 62 | } 63 | } 64 | module.exports = proj4; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/common/nad_intr.js: -------------------------------------------------------------------------------- 1 | var nadInterBreakout = require("./nadInterBreakout"); 2 | 3 | module.exports = function(pin, ct) { 4 | // force computation by decreasing by 1e-7 to be as closed as possible 5 | // from computation under C:C++ by leveraging rounding problems ... 6 | var t = { 7 | x: (pin.x - 1e-7) / ct.del[0], 8 | y: (pin.y - 1e-7) / ct.del[1] 9 | }; 10 | var indx = { 11 | x: Math.floor(t.x), 12 | y: Math.floor(t.y) 13 | }; 14 | var frct = { 15 | x: t.x - 1 * indx.x, 16 | y: t.y - 1 * indx.y 17 | }; 18 | var val = { 19 | x: Number.NaN, 20 | y: Number.NaN 21 | }; 22 | 23 | 24 | var temp = nadInterBreakout(indx, frct, 'x', 0, ct); 25 | if (temp) { 26 | indx = temp[0]; 27 | frct = temp[1]; 28 | } 29 | else { 30 | return val; 31 | } 32 | temp = nadInterBreakout(indx, frct, 'y', 1, ct); 33 | if (temp) { 34 | indx = temp[0]; 35 | frct = temp[1]; 36 | } 37 | else { 38 | return val; 39 | } 40 | var inx = (indx.y * ct.lim[0]) + indx.x; 41 | var f00 = { 42 | x: ct.cvs[inx][0], 43 | y: ct.cvs[inx][1] 44 | }; 45 | inx++; 46 | var f10 = { 47 | x: ct.cvs[inx][0], 48 | y: ct.cvs[inx][1] 49 | }; 50 | inx += ct.lim[0]; 51 | var f11 = { 52 | x: ct.cvs[inx][0], 53 | y: ct.cvs[inx][1] 54 | }; 55 | inx--; 56 | var f01 = { 57 | x: ct.cvs[inx][0], 58 | y: ct.cvs[inx][1] 59 | }; 60 | var m11 = frct.x * frct.y, 61 | m10 = frct.x * (1 - frct.y), 62 | m00 = (1 - frct.x) * (1 - frct.y), 63 | m01 = (1 - frct.x) * frct.y; 64 | val.x = (m00 * f00.x + m10 * f10.x + m01 * f01.x + m11 * f11.x); 65 | val.y = (m00 * f00.y + m10 * f10.y + m01 * f01.y + m11 * f11.y); 66 | return val; 67 | }; -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/datum/BD09LL.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.datum; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class BD09LL implements Datum { 6 | 7 | private static double PI = Math.PI; 8 | private static double X_PI = PI * 3000.0 / 180.0; 9 | 10 | private Datum gcj02 = new GCJ02(); 11 | 12 | public T toWGS84(T point, PointAdaptor pointAdaptor) { 13 | return gcj02.toWGS84(toGCJ02(point, pointAdaptor), pointAdaptor); 14 | } 15 | 16 | public T fromWGS84(T point, PointAdaptor pointAdaptor) { 17 | return fromGCJ02(gcj02.fromWGS84(point, pointAdaptor), pointAdaptor); 18 | } 19 | 20 | public static T toGCJ02(T point, PointAdaptor pointAdaptor) { 21 | double x = pointAdaptor.getX(point); 22 | double y = pointAdaptor.getY(point); 23 | x = x - 0.0065; 24 | y = y - 0.006; 25 | double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI); 26 | double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI); 27 | x = z * Math.cos(theta); 28 | y = z * Math.sin(theta); 29 | pointAdaptor.setX(point, x); 30 | pointAdaptor.setY(point, y); 31 | 32 | return point; 33 | } 34 | 35 | public static T fromGCJ02(T point, PointAdaptor pointAdaptor) { 36 | double x = pointAdaptor.getX(point); 37 | double y = pointAdaptor.getY(point); 38 | double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * X_PI); 39 | double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * X_PI); 40 | y = z * Math.sin(theta) + 0.006; 41 | x = z * Math.cos(theta) + 0.0065; 42 | pointAdaptor.setX(point, x); 43 | pointAdaptor.setY(point, y); 44 | return point; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/test/amd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Mocha Tests 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/sterea.js: -------------------------------------------------------------------------------- 1 | var gauss = require('./gauss'); 2 | var adjust_lon = require('../common/adjust_lon'); 3 | exports.init = function() { 4 | gauss.init.apply(this); 5 | if (!this.rc) { 6 | return; 7 | } 8 | this.sinc0 = Math.sin(this.phic0); 9 | this.cosc0 = Math.cos(this.phic0); 10 | this.R2 = 2 * this.rc; 11 | if (!this.title) { 12 | this.title = "Oblique Stereographic Alternative"; 13 | } 14 | }; 15 | 16 | exports.forward = function(p) { 17 | var sinc, cosc, cosl, k; 18 | p.x = adjust_lon(p.x - this.long0); 19 | gauss.forward.apply(this, [p]); 20 | sinc = Math.sin(p.y); 21 | cosc = Math.cos(p.y); 22 | cosl = Math.cos(p.x); 23 | k = this.k0 * this.R2 / (1 + this.sinc0 * sinc + this.cosc0 * cosc * cosl); 24 | p.x = k * cosc * Math.sin(p.x); 25 | p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl); 26 | p.x = this.a * p.x + this.x0; 27 | p.y = this.a * p.y + this.y0; 28 | return p; 29 | }; 30 | 31 | exports.inverse = function(p) { 32 | var sinc, cosc, lon, lat, rho; 33 | p.x = (p.x - this.x0) / this.a; 34 | p.y = (p.y - this.y0) / this.a; 35 | 36 | p.x /= this.k0; 37 | p.y /= this.k0; 38 | if ((rho = Math.sqrt(p.x * p.x + p.y * p.y))) { 39 | var c = 2 * Math.atan2(rho, this.R2); 40 | sinc = Math.sin(c); 41 | cosc = Math.cos(c); 42 | lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho); 43 | lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc); 44 | } 45 | else { 46 | lat = this.phic0; 47 | lon = 0; 48 | } 49 | 50 | p.x = lon; 51 | p.y = lat; 52 | gauss.inverse.apply(this, [p]); 53 | p.x = adjust_lon(p.x + this.long0); 54 | return p; 55 | }; 56 | 57 | exports.names = ["Stereographic_North_Pole", "Oblique_Stereographic", "Polar_Stereographic", "sterea","Oblique Stereographic Alternative"]; 58 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/deriveConstants.js: -------------------------------------------------------------------------------- 1 | var Datum = require('./constants/Datum'); 2 | var Ellipsoid = require('./constants/Ellipsoid'); 3 | var extend = require('./extend'); 4 | var datum = require('./datum'); 5 | var EPSLN = 1.0e-10; 6 | // ellipoid pj_set_ell.c 7 | var SIXTH = 0.1666666666666666667; 8 | /* 1/6 */ 9 | var RA4 = 0.04722222222222222222; 10 | /* 17/360 */ 11 | var RA6 = 0.02215608465608465608; 12 | module.exports = function(json) { 13 | // DGR 2011-03-20 : nagrids -> nadgrids 14 | if (json.datumCode && json.datumCode !== 'none') { 15 | var datumDef = Datum[json.datumCode]; 16 | if (datumDef) { 17 | json.datum_params = datumDef.towgs84 ? datumDef.towgs84.split(',') : null; 18 | json.ellps = datumDef.ellipse; 19 | json.datumName = datumDef.datumName ? datumDef.datumName : json.datumCode; 20 | } 21 | } 22 | if (!json.a) { // do we have an ellipsoid? 23 | var ellipse = Ellipsoid[json.ellps] ? Ellipsoid[json.ellps] : Ellipsoid.WGS84; 24 | extend(json, ellipse); 25 | } 26 | if (json.rf && !json.b) { 27 | json.b = (1.0 - 1.0 / json.rf) * json.a; 28 | } 29 | if (json.rf === 0 || Math.abs(json.a - json.b) < EPSLN) { 30 | json.sphere = true; 31 | json.b = json.a; 32 | } 33 | json.a2 = json.a * json.a; // used in geocentric 34 | json.b2 = json.b * json.b; // used in geocentric 35 | json.es = (json.a2 - json.b2) / json.a2; // e ^ 2 36 | json.e = Math.sqrt(json.es); // eccentricity 37 | if (json.R_A) { 38 | json.a *= 1 - json.es * (SIXTH + json.es * (RA4 + json.es * RA6)); 39 | json.a2 = json.a * json.a; 40 | json.b2 = json.b * json.b; 41 | json.es = 0; 42 | } 43 | json.ep2 = (json.a2 - json.b2) / json.b2; // used in geocentric 44 | if (!json.k0) { 45 | json.k0 = 1.0; //default value 46 | } 47 | //DGR 2010-11-12: axis 48 | if (!json.axis) { 49 | json.axis = "enu"; 50 | } 51 | 52 | if (!json.datum) { 53 | json.datum = datum(json); 54 | } 55 | return json; 56 | }; 57 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/REFERENCES.md: -------------------------------------------------------------------------------- 1 | 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological Survey 2 | Professional Paper 1395 (Supersedes USGS Bulletin 1532), 3 | United State Government Printing Office, Washington D.C., 1987. 4 | 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", 5 | U.S. Geological Survey Professional Paper 1453 , 6 | United State Government Printing Office, Washington D.C., 1989. 7 | 3. "Cartographic Projection Procedures for the UNIX Environment- 8 | A User's Manual" by Gerald I. Evenden, 9 | USGS Open File Report 90-284and Release 4 Interim Reports (2003) 10 | 4. Snyder, John P., "Flattening the Earth - 11 | Two Thousand Years of Map Projections", Univ. Chicago Press, 1993 12 | 5. Wolfram Mathworld "Gnomonic Projection" 13 | http://mathworld.wolfram.com/GnomonicProjection.html 14 | Accessed: 12th November 2009 15 | 6. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, 16 | The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. 17 | 7. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological 18 | Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United 19 | State Government Printing Office, Washington D.C., 1987. 20 | 8. "Software Documentation for GCTP General Cartographic Transformation 21 | Package", U.S. Geological Survey National Mapping Division, May 1982. 22 | 9. Department of Land and Survey Technical Circular 1973/32 23 | http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf 24 | 10. OSG Technical Report 4.1 25 | http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf 26 | 11. Formules et constantes pour le Calcul pour la 27 | projection cylindrique conforme à axe oblique et pour la transformation entre 28 | des systèmes de référence. 29 | http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/cea.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var qsfnz = require('../common/qsfnz'); 3 | var msfnz = require('../common/msfnz'); 4 | var iqsfnz = require('../common/iqsfnz'); 5 | /* 6 | reference: 7 | "Cartographic Projection Procedures for the UNIX Environment- 8 | A User's Manual" by Gerald I. Evenden, 9 | USGS Open File Report 90-284and Release 4 Interim Reports (2003) 10 | */ 11 | exports.init = function() { 12 | //no-op 13 | if (!this.sphere) { 14 | this.k0 = msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); 15 | } 16 | }; 17 | 18 | 19 | /* Cylindrical Equal Area forward equations--mapping lat,long to x,y 20 | ------------------------------------------------------------*/ 21 | exports.forward = function(p) { 22 | var lon = p.x; 23 | var lat = p.y; 24 | var x, y; 25 | /* Forward equations 26 | -----------------*/ 27 | var dlon = adjust_lon(lon - this.long0); 28 | if (this.sphere) { 29 | x = this.x0 + this.a * dlon * Math.cos(this.lat_ts); 30 | y = this.y0 + this.a * Math.sin(lat) / Math.cos(this.lat_ts); 31 | } 32 | else { 33 | var qs = qsfnz(this.e, Math.sin(lat)); 34 | x = this.x0 + this.a * this.k0 * dlon; 35 | y = this.y0 + this.a * qs * 0.5 / this.k0; 36 | } 37 | 38 | p.x = x; 39 | p.y = y; 40 | return p; 41 | }; 42 | 43 | /* Cylindrical Equal Area inverse equations--mapping x,y to lat/long 44 | ------------------------------------------------------------*/ 45 | exports.inverse = function(p) { 46 | p.x -= this.x0; 47 | p.y -= this.y0; 48 | var lon, lat; 49 | 50 | if (this.sphere) { 51 | lon = adjust_lon(this.long0 + (p.x / this.a) / Math.cos(this.lat_ts)); 52 | lat = Math.asin((p.y / this.a) * Math.cos(this.lat_ts)); 53 | } 54 | else { 55 | lat = iqsfnz(this.e, 2 * p.y * this.k0 / this.a); 56 | lon = adjust_lon(this.long0 + p.x / (this.a * this.k0)); 57 | } 58 | 59 | p.x = lon; 60 | p.y = lat; 61 | return p; 62 | }; 63 | exports.names = ["cea"]; 64 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/gstmerc.js: -------------------------------------------------------------------------------- 1 | var latiso = require('../common/latiso'); 2 | var sinh = require('../common/sinh'); 3 | var cosh = require('../common/cosh'); 4 | var invlatiso = require('../common/invlatiso'); 5 | exports.init = function() { 6 | 7 | // array of: a, b, lon0, lat0, k0, x0, y0 8 | var temp = this.b / this.a; 9 | this.e = Math.sqrt(1 - temp * temp); 10 | this.lc = this.long0; 11 | this.rs = Math.sqrt(1 + this.e * this.e * Math.pow(Math.cos(this.lat0), 4) / (1 - this.e * this.e)); 12 | var sinz = Math.sin(this.lat0); 13 | var pc = Math.asin(sinz / this.rs); 14 | var sinzpc = Math.sin(pc); 15 | this.cp = latiso(0, pc, sinzpc) - this.rs * latiso(this.e, this.lat0, sinz); 16 | this.n2 = this.k0 * this.a * Math.sqrt(1 - this.e * this.e) / (1 - this.e * this.e * sinz * sinz); 17 | this.xs = this.x0; 18 | this.ys = this.y0 - this.n2 * pc; 19 | 20 | if (!this.title) { 21 | this.title = "Gauss Schreiber transverse mercator"; 22 | } 23 | }; 24 | 25 | 26 | // forward equations--mapping lat,long to x,y 27 | // ----------------------------------------------------------------- 28 | exports.forward = function(p) { 29 | 30 | var lon = p.x; 31 | var lat = p.y; 32 | 33 | var L = this.rs * (lon - this.lc); 34 | var Ls = this.cp + (this.rs * latiso(this.e, lat, Math.sin(lat))); 35 | var lat1 = Math.asin(Math.sin(L) / cosh(Ls)); 36 | var Ls1 = latiso(0, lat1, Math.sin(lat1)); 37 | p.x = this.xs + (this.n2 * Ls1); 38 | p.y = this.ys + (this.n2 * Math.atan(sinh(Ls) / Math.cos(L))); 39 | return p; 40 | }; 41 | 42 | // inverse equations--mapping x,y to lat/long 43 | // ----------------------------------------------------------------- 44 | exports.inverse = function(p) { 45 | 46 | var x = p.x; 47 | var y = p.y; 48 | 49 | var L = Math.atan(sinh((x - this.xs) / this.n2) / Math.cos((y - this.ys) / this.n2)); 50 | var lat1 = Math.asin(Math.sin((y - this.ys) / this.n2) / cosh((x - this.xs) / this.n2)); 51 | var LC = latiso(0, lat1, Math.sin(lat1)); 52 | p.x = this.lc + L / this.rs; 53 | p.y = invlatiso(this.e, (LC - this.cp) / this.rs); 54 | return p; 55 | }; 56 | exports.names = ["gstmerg"]; 57 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/rhino/JsonModuleScriptProvider.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.rhino; 2 | 3 | import org.mozilla.javascript.*; 4 | import org.mozilla.javascript.commonjs.module.ModuleScript; 5 | import org.mozilla.javascript.commonjs.module.ModuleScriptProvider; 6 | import org.mozilla.javascript.json.JsonParser; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.File; 11 | import java.io.FileInputStream; 12 | import java.net.URI; 13 | import java.util.Map; 14 | 15 | public class JsonModuleScriptProvider implements ModuleScriptProvider { 16 | 17 | public ModuleScript getModuleScript(Context cx, String moduleId, URI moduleUri, 18 | URI baseUri, Scriptable paths) throws Exception { 19 | if (!moduleId.endsWith(".json")) { 20 | return null; 21 | } 22 | 23 | BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(moduleUri))); 24 | byte[] buf = new byte[1024]; 25 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 26 | int n; 27 | while ((n = in.read(buf, 0, buf.length)) != -1) { 28 | baos.write(buf, 0, n); 29 | } 30 | String json = baos.toString("UTF-8"); 31 | 32 | JsonParser parser = new JsonParser(cx, new TopLevel()); 33 | Object obj = parser.parseValue(json); 34 | 35 | JsonScript script = new JsonScript(obj); 36 | 37 | return new ModuleScript(script, moduleUri, baseUri); 38 | } 39 | 40 | private class JsonScript implements Script { 41 | 42 | private Object obj; 43 | 44 | JsonScript(Object obj) { 45 | this.obj = obj; 46 | } 47 | 48 | public Object exec(Context cx, Scriptable scope) { 49 | Object exports = ScriptableObject.getProperty(scope, "exports"); 50 | NativeObject nobj = (NativeObject) obj; 51 | for (Map.Entry entry : nobj.entrySet()) { 52 | ScriptRuntime.setObjectProp(exports, (String) entry.getKey(), entry.getValue(), cx); 53 | } 54 | return Undefined.instance; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/constants/Datum.js: -------------------------------------------------------------------------------- 1 | exports.wgs84 = { 2 | towgs84: "0,0,0", 3 | ellipse: "WGS84", 4 | datumName: "WGS84" 5 | }; 6 | exports.ch1903 = { 7 | towgs84: "674.374,15.056,405.346", 8 | ellipse: "bessel", 9 | datumName: "swiss" 10 | }; 11 | exports.ggrs87 = { 12 | towgs84: "-199.87,74.79,246.62", 13 | ellipse: "GRS80", 14 | datumName: "Greek_Geodetic_Reference_System_1987" 15 | }; 16 | exports.nad83 = { 17 | towgs84: "0,0,0", 18 | ellipse: "GRS80", 19 | datumName: "North_American_Datum_1983" 20 | }; 21 | exports.nad27 = { 22 | nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", 23 | ellipse: "clrk66", 24 | datumName: "North_American_Datum_1927" 25 | }; 26 | exports.potsdam = { 27 | towgs84: "606.0,23.0,413.0", 28 | ellipse: "bessel", 29 | datumName: "Potsdam Rauenberg 1950 DHDN" 30 | }; 31 | exports.carthage = { 32 | towgs84: "-263.0,6.0,431.0", 33 | ellipse: "clark80", 34 | datumName: "Carthage 1934 Tunisia" 35 | }; 36 | exports.hermannskogel = { 37 | towgs84: "653.0,-212.0,449.0", 38 | ellipse: "bessel", 39 | datumName: "Hermannskogel" 40 | }; 41 | exports.ire65 = { 42 | towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", 43 | ellipse: "mod_airy", 44 | datumName: "Ireland 1965" 45 | }; 46 | exports.rassadiran = { 47 | towgs84: "-133.63,-157.5,-158.62", 48 | ellipse: "intl", 49 | datumName: "Rassadiran" 50 | }; 51 | exports.nzgd49 = { 52 | towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", 53 | ellipse: "intl", 54 | datumName: "New Zealand Geodetic Datum 1949" 55 | }; 56 | exports.osgb36 = { 57 | towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", 58 | ellipse: "airy", 59 | datumName: "Airy 1830" 60 | }; 61 | exports.s_jtsk = { 62 | towgs84: "589,76,480", 63 | ellipse: 'bessel', 64 | datumName: 'S-JTSK (Ferro)' 65 | }; 66 | exports.beduaram = { 67 | towgs84: '-106,-87,188', 68 | ellipse: 'clrk80', 69 | datumName: 'Beduaram' 70 | }; 71 | exports.gunung_segara = { 72 | towgs84: '-403,684,41', 73 | ellipse: 'bessel', 74 | datumName: 'Gunung Segara Jakarta' 75 | }; 76 | exports.rnb72 = { 77 | towgs84: "106.869,-52.2978,103.724,-0.33657,0.456955,-1.84218,1", 78 | ellipse: "intl", 79 | datumName: "Reseau National Belge 1972" 80 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/transform.js: -------------------------------------------------------------------------------- 1 | var D2R = 0.01745329251994329577; 2 | var R2D = 57.29577951308232088; 3 | var PJD_3PARAM = 1; 4 | var PJD_7PARAM = 2; 5 | var datum_transform = require('./datum_transform'); 6 | var adjust_axis = require('./adjust_axis'); 7 | var proj = require('./Proj'); 8 | var toPoint = require('./common/toPoint'); 9 | module.exports = function transform(source, dest, point) { 10 | var wgs84; 11 | if (Array.isArray(point)) { 12 | point = toPoint(point); 13 | } 14 | function checkNotWGS(source, dest) { 15 | return ((source.datum.datum_type === PJD_3PARAM || source.datum.datum_type === PJD_7PARAM) && dest.datumCode !== "WGS84"); 16 | } 17 | 18 | // Workaround for datum shifts towgs84, if either source or destination projection is not wgs84 19 | if (source.datum && dest.datum && (checkNotWGS(source, dest) || checkNotWGS(dest, source))) { 20 | wgs84 = new proj('WGS84'); 21 | transform(source, wgs84, point); 22 | source = wgs84; 23 | } 24 | // DGR, 2010/11/12 25 | if (source.axis !== "enu") { 26 | adjust_axis(source, false, point); 27 | } 28 | // Transform source points to long/lat, if they aren't already. 29 | if (source.projName === "longlat") { 30 | point.x *= D2R; // convert degrees to radians 31 | point.y *= D2R; 32 | } 33 | else { 34 | if (source.to_meter) { 35 | point.x *= source.to_meter; 36 | point.y *= source.to_meter; 37 | } 38 | source.inverse(point); // Convert Cartesian to longlat 39 | } 40 | // Adjust for the prime meridian if necessary 41 | if (source.from_greenwich) { 42 | point.x += source.from_greenwich; 43 | } 44 | 45 | // Convert datums if needed, and if possible. 46 | point = datum_transform(source.datum, dest.datum, point); 47 | 48 | // Adjust for the prime meridian if necessary 49 | if (dest.from_greenwich) { 50 | point.x -= dest.from_greenwich; 51 | } 52 | 53 | if (dest.projName === "longlat") { 54 | // convert radians to decimal degrees 55 | point.x *= R2D; 56 | point.y *= R2D; 57 | } 58 | else { // else project 59 | dest.forward(point); 60 | if (dest.to_meter) { 61 | point.x /= dest.to_meter; 62 | point.y /= dest.to_meter; 63 | } 64 | } 65 | 66 | // DGR, 2010/11/12 67 | if (dest.axis !== "enu") { 68 | adjust_axis(dest, true, point); 69 | } 70 | 71 | return point; 72 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/moll.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var EPSLN = 1.0e-10; 3 | exports.init = function() {}; 4 | 5 | /* Mollweide forward equations--mapping lat,long to x,y 6 | ----------------------------------------------------*/ 7 | exports.forward = function(p) { 8 | 9 | /* Forward equations 10 | -----------------*/ 11 | var lon = p.x; 12 | var lat = p.y; 13 | 14 | var delta_lon = adjust_lon(lon - this.long0); 15 | var theta = lat; 16 | var con = Math.PI * Math.sin(lat); 17 | 18 | /* Iterate using the Newton-Raphson method to find theta 19 | -----------------------------------------------------*/ 20 | for (var i = 0; true; i++) { 21 | var delta_theta = -(theta + Math.sin(theta) - con) / (1 + Math.cos(theta)); 22 | theta += delta_theta; 23 | if (Math.abs(delta_theta) < EPSLN) { 24 | break; 25 | } 26 | } 27 | theta /= 2; 28 | 29 | /* If the latitude is 90 deg, force the x coordinate to be "0 + false easting" 30 | this is done here because of precision problems with "cos(theta)" 31 | --------------------------------------------------------------------------*/ 32 | if (Math.PI / 2 - Math.abs(lat) < EPSLN) { 33 | delta_lon = 0; 34 | } 35 | var x = 0.900316316158 * this.a * delta_lon * Math.cos(theta) + this.x0; 36 | var y = 1.4142135623731 * this.a * Math.sin(theta) + this.y0; 37 | 38 | p.x = x; 39 | p.y = y; 40 | return p; 41 | }; 42 | 43 | exports.inverse = function(p) { 44 | var theta; 45 | var arg; 46 | 47 | /* Inverse equations 48 | -----------------*/ 49 | p.x -= this.x0; 50 | p.y -= this.y0; 51 | arg = p.y / (1.4142135623731 * this.a); 52 | 53 | /* Because of division by zero problems, 'arg' can not be 1. Therefore 54 | a number very close to one is used instead. 55 | -------------------------------------------------------------------*/ 56 | if (Math.abs(arg) > 0.999999999999) { 57 | arg = 0.999999999999; 58 | } 59 | theta = Math.asin(arg); 60 | var lon = adjust_lon(this.long0 + (p.x / (0.900316316158 * this.a * Math.cos(theta)))); 61 | if (lon < (-Math.PI)) { 62 | lon = -Math.PI; 63 | } 64 | if (lon > Math.PI) { 65 | lon = Math.PI; 66 | } 67 | arg = (2 * theta + Math.sin(2 * theta)) / Math.PI; 68 | if (Math.abs(arg) > 1) { 69 | arg = 1; 70 | } 71 | var lat = Math.asin(arg); 72 | 73 | p.x = lon; 74 | p.y = lat; 75 | return p; 76 | }; 77 | exports.names = ["Mollweide", "moll"]; 78 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/ortho.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var EPSLN = 1.0e-10; 3 | var asinz = require('../common/asinz'); 4 | var HALF_PI = Math.PI/2; 5 | exports.init = function() { 6 | //double temp; /* temporary variable */ 7 | 8 | /* Place parameters in static storage for common use 9 | -------------------------------------------------*/ 10 | this.sin_p14 = Math.sin(this.lat0); 11 | this.cos_p14 = Math.cos(this.lat0); 12 | }; 13 | 14 | 15 | /* Orthographic forward equations--mapping lat,long to x,y 16 | ---------------------------------------------------*/ 17 | exports.forward = function(p) { 18 | var sinphi, cosphi; /* sin and cos value */ 19 | var dlon; /* delta longitude value */ 20 | var coslon; /* cos of longitude */ 21 | var ksp; /* scale factor */ 22 | var g, x, y; 23 | var lon = p.x; 24 | var lat = p.y; 25 | /* Forward equations 26 | -----------------*/ 27 | dlon = adjust_lon(lon - this.long0); 28 | 29 | sinphi = Math.sin(lat); 30 | cosphi = Math.cos(lat); 31 | 32 | coslon = Math.cos(dlon); 33 | g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; 34 | ksp = 1; 35 | if ((g > 0) || (Math.abs(g) <= EPSLN)) { 36 | x = this.a * ksp * cosphi * Math.sin(dlon); 37 | y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); 38 | } 39 | p.x = x; 40 | p.y = y; 41 | return p; 42 | }; 43 | 44 | 45 | exports.inverse = function(p) { 46 | var rh; /* height above ellipsoid */ 47 | var z; /* angle */ 48 | var sinz, cosz; /* sin of z and cos of z */ 49 | var con; 50 | var lon, lat; 51 | /* Inverse equations 52 | -----------------*/ 53 | p.x -= this.x0; 54 | p.y -= this.y0; 55 | rh = Math.sqrt(p.x * p.x + p.y * p.y); 56 | z = asinz(rh / this.a); 57 | 58 | sinz = Math.sin(z); 59 | cosz = Math.cos(z); 60 | 61 | lon = this.long0; 62 | if (Math.abs(rh) <= EPSLN) { 63 | lat = this.lat0; 64 | p.x = lon; 65 | p.y = lat; 66 | return p; 67 | } 68 | lat = asinz(cosz * this.sin_p14 + (p.y * sinz * this.cos_p14) / rh); 69 | con = Math.abs(this.lat0) - HALF_PI; 70 | if (Math.abs(con) <= EPSLN) { 71 | if (this.lat0 >= 0) { 72 | lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y)); 73 | } 74 | else { 75 | lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y)); 76 | } 77 | p.x = lon; 78 | p.y = lat; 79 | return p; 80 | } 81 | lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz), rh * this.cos_p14 * cosz - p.y * this.sin_p14 * sinz)); 82 | p.x = lon; 83 | p.y = lat; 84 | return p; 85 | }; 86 | exports.names = ["ortho"]; 87 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/merc.js: -------------------------------------------------------------------------------- 1 | var msfnz = require('../common/msfnz'); 2 | var HALF_PI = Math.PI/2; 3 | var EPSLN = 1.0e-10; 4 | var R2D = 57.29577951308232088; 5 | var adjust_lon = require('../common/adjust_lon'); 6 | var FORTPI = Math.PI/4; 7 | var tsfnz = require('../common/tsfnz'); 8 | var phi2z = require('../common/phi2z'); 9 | exports.init = function() { 10 | var con = this.b / this.a; 11 | this.es = 1 - con * con; 12 | if(!('x0' in this)){ 13 | this.x0 = 0; 14 | } 15 | if(!('y0' in this)){ 16 | this.y0 = 0; 17 | } 18 | this.e = Math.sqrt(this.es); 19 | if (this.lat_ts) { 20 | if (this.sphere) { 21 | this.k0 = Math.cos(this.lat_ts); 22 | } 23 | else { 24 | this.k0 = msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)); 25 | } 26 | } 27 | else { 28 | if (!this.k0) { 29 | if (this.k) { 30 | this.k0 = this.k; 31 | } 32 | else { 33 | this.k0 = 1; 34 | } 35 | } 36 | } 37 | }; 38 | 39 | /* Mercator forward equations--mapping lat,long to x,y 40 | --------------------------------------------------*/ 41 | 42 | exports.forward = function(p) { 43 | var lon = p.x; 44 | var lat = p.y; 45 | // convert to radians 46 | if (lat * R2D > 90 && lat * R2D < -90 && lon * R2D > 180 && lon * R2D < -180) { 47 | return null; 48 | } 49 | 50 | var x, y; 51 | if (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN) { 52 | return null; 53 | } 54 | else { 55 | if (this.sphere) { 56 | x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0); 57 | y = this.y0 + this.a * this.k0 * Math.log(Math.tan(FORTPI + 0.5 * lat)); 58 | } 59 | else { 60 | var sinphi = Math.sin(lat); 61 | var ts = tsfnz(this.e, lat, sinphi); 62 | x = this.x0 + this.a * this.k0 * adjust_lon(lon - this.long0); 63 | y = this.y0 - this.a * this.k0 * Math.log(ts); 64 | } 65 | p.x = x; 66 | p.y = y; 67 | return p; 68 | } 69 | }; 70 | 71 | 72 | /* Mercator inverse equations--mapping x,y to lat/long 73 | --------------------------------------------------*/ 74 | exports.inverse = function(p) { 75 | 76 | var x = p.x - this.x0; 77 | var y = p.y - this.y0; 78 | var lon, lat; 79 | 80 | if (this.sphere) { 81 | lat = HALF_PI - 2 * Math.atan(Math.exp(-y / (this.a * this.k0))); 82 | } 83 | else { 84 | var ts = Math.exp(-y / (this.a * this.k0)); 85 | lat = phi2z(this.e, ts); 86 | if (lat === -9999) { 87 | return null; 88 | } 89 | } 90 | lon = adjust_lon(this.long0 + x / (this.a * this.k0)); 91 | 92 | p.x = lon; 93 | p.y = lat; 94 | return p; 95 | }; 96 | 97 | exports.names = ["Mercator", "Popular Visualisation Pseudo Mercator", "Mercator_1SP", "Mercator_Auxiliary_Sphere", "merc"]; 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Eclipse template 2 | *.pydevproject 3 | .metadata 4 | .gradle 5 | bin/ 6 | tmp/ 7 | *.tmp 8 | *.bak 9 | *.swp 10 | *~.nib 11 | local.properties 12 | .settings/ 13 | .loadpath 14 | 15 | # Eclipse Core 16 | .project 17 | 18 | # External tool builders 19 | .externalToolBuilders/ 20 | 21 | # Locally stored "Eclipse launch configurations" 22 | *.launch 23 | 24 | # CDT-specific 25 | .cproject 26 | 27 | # JDT-specific (Eclipse Java Development Tools) 28 | .classpath 29 | 30 | # Java annotation processor (APT) 31 | .factorypath 32 | 33 | # PDT-specific 34 | .buildpath 35 | 36 | # sbteclipse plugin 37 | .target 38 | 39 | # TeXlipse plugin 40 | .texlipse 41 | 42 | 43 | ### JetBrains template 44 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 45 | 46 | *.iml 47 | 48 | ## Directory-based project format: 49 | .idea/ 50 | # if you remove the above rule, at least ignore the following: 51 | 52 | # User-specific stuff: 53 | # .idea/workspace.xml 54 | # .idea/tasks.xml 55 | # .idea/dictionaries 56 | 57 | # Sensitive or high-churn files: 58 | # .idea/dataSources.ids 59 | # .idea/dataSources.xml 60 | # .idea/sqlDataSources.xml 61 | # .idea/dynamic.xml 62 | # .idea/uiDesigner.xml 63 | 64 | # Gradle: 65 | # .idea/gradle.xml 66 | # .idea/libraries 67 | 68 | # Mongo Explorer plugin: 69 | # .idea/mongoSettings.xml 70 | 71 | ## File-based project format: 72 | *.ipr 73 | *.iws 74 | 75 | ## Plugin-specific files: 76 | 77 | # IntelliJ 78 | /out/ 79 | 80 | # mpeltonen/sbt-idea plugin 81 | .idea_modules/ 82 | 83 | # JIRA plugin 84 | atlassian-ide-plugin.xml 85 | 86 | # Crashlytics plugin (for Android Studio and IntelliJ) 87 | com_crashlytics_export_strings.xml 88 | crashlytics.properties 89 | crashlytics-build.properties 90 | 91 | 92 | ### Maven template 93 | target/ 94 | pom.xml.tag 95 | pom.xml.releaseBackup 96 | pom.xml.versionsBackup 97 | pom.xml.next 98 | release.properties 99 | dependency-reduced-pom.xml 100 | buildNumber.properties 101 | .mvn/timing.properties 102 | 103 | 104 | ### OSX template 105 | .DS_Store 106 | .AppleDouble 107 | .LSOverride 108 | 109 | # Icon must end with two \r 110 | Icon 111 | 112 | # Thumbnails 113 | ._* 114 | 115 | # Files that might appear in the root of a volume 116 | .DocumentRevisions-V100 117 | .fseventsd 118 | .Spotlight-V100 119 | .TemporaryItems 120 | .Trashes 121 | .VolumeIcon.icns 122 | 123 | # Directories potentially created on remote AFP share 124 | .AppleDB 125 | .AppleDesktop 126 | Network Trash Folder 127 | Temporary Items 128 | .apdisk 129 | 130 | 131 | ### Windows template 132 | # Windows image file caches 133 | Thumbs.db 134 | ehthumbs.db 135 | 136 | # Folder config file 137 | Desktop.ini 138 | 139 | # Recycle Bin used on file shares 140 | $RECYCLE.BIN/ 141 | 142 | # Windows Installer files 143 | *.cab 144 | *.msi 145 | *.msm 146 | *.msp 147 | 148 | # Windows shortcuts 149 | *.lnk 150 | 151 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/sinu.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var adjust_lat = require('../common/adjust_lat'); 3 | var pj_enfn = require('../common/pj_enfn'); 4 | var MAX_ITER = 20; 5 | var pj_mlfn = require('../common/pj_mlfn'); 6 | var pj_inv_mlfn = require('../common/pj_inv_mlfn'); 7 | var HALF_PI = Math.PI/2; 8 | var EPSLN = 1.0e-10; 9 | var asinz = require('../common/asinz'); 10 | exports.init = function() { 11 | /* Place parameters in static storage for common use 12 | -------------------------------------------------*/ 13 | 14 | 15 | if (!this.sphere) { 16 | this.en = pj_enfn(this.es); 17 | } 18 | else { 19 | this.n = 1; 20 | this.m = 0; 21 | this.es = 0; 22 | this.C_y = Math.sqrt((this.m + 1) / this.n); 23 | this.C_x = this.C_y / (this.m + 1); 24 | } 25 | 26 | }; 27 | 28 | /* Sinusoidal forward equations--mapping lat,long to x,y 29 | -----------------------------------------------------*/ 30 | exports.forward = function(p) { 31 | var x, y; 32 | var lon = p.x; 33 | var lat = p.y; 34 | /* Forward equations 35 | -----------------*/ 36 | lon = adjust_lon(lon - this.long0); 37 | 38 | if (this.sphere) { 39 | if (!this.m) { 40 | lat = this.n !== 1 ? Math.asin(this.n * Math.sin(lat)) : lat; 41 | } 42 | else { 43 | var k = this.n * Math.sin(lat); 44 | for (var i = MAX_ITER; i; --i) { 45 | var V = (this.m * lat + Math.sin(lat) - k) / (this.m + Math.cos(lat)); 46 | lat -= V; 47 | if (Math.abs(V) < EPSLN) { 48 | break; 49 | } 50 | } 51 | } 52 | x = this.a * this.C_x * lon * (this.m + Math.cos(lat)); 53 | y = this.a * this.C_y * lat; 54 | 55 | } 56 | else { 57 | 58 | var s = Math.sin(lat); 59 | var c = Math.cos(lat); 60 | y = this.a * pj_mlfn(lat, s, c, this.en); 61 | x = this.a * lon * c / Math.sqrt(1 - this.es * s * s); 62 | } 63 | 64 | p.x = x; 65 | p.y = y; 66 | return p; 67 | }; 68 | 69 | exports.inverse = function(p) { 70 | var lat, temp, lon, s; 71 | 72 | p.x -= this.x0; 73 | lon = p.x / this.a; 74 | p.y -= this.y0; 75 | lat = p.y / this.a; 76 | 77 | if (this.sphere) { 78 | lat /= this.C_y; 79 | lon = lon / (this.C_x * (this.m + Math.cos(lat))); 80 | if (this.m) { 81 | lat = asinz((this.m * lat + Math.sin(lat)) / this.n); 82 | } 83 | else if (this.n !== 1) { 84 | lat = asinz(Math.sin(lat) / this.n); 85 | } 86 | lon = adjust_lon(lon + this.long0); 87 | lat = adjust_lat(lat); 88 | } 89 | else { 90 | lat = pj_inv_mlfn(p.y / this.a, this.es, this.en); 91 | s = Math.abs(lat); 92 | if (s < HALF_PI) { 93 | s = Math.sin(lat); 94 | temp = this.long0 + p.x * Math.sqrt(1 - this.es * s * s) / (this.a * Math.cos(lat)); 95 | //temp = this.long0 + p.x / (this.a * Math.cos(lat)); 96 | lon = adjust_lon(temp); 97 | } 98 | else if ((s - EPSLN) < HALF_PI) { 99 | lon = this.long0; 100 | } 101 | } 102 | p.x = lon; 103 | p.y = lat; 104 | return p; 105 | }; 106 | exports.names = ["Sinusoidal", "sinu"]; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/somerc.js: -------------------------------------------------------------------------------- 1 | /* 2 | references: 3 | Formules et constantes pour le Calcul pour la 4 | projection cylindrique conforme à axe oblique et pour la transformation entre 5 | des systèmes de référence. 6 | http://www.swisstopo.admin.ch/internet/swisstopo/fr/home/topics/survey/sys/refsys/switzerland.parsysrelated1.31216.downloadList.77004.DownloadFile.tmp/swissprojectionfr.pdf 7 | */ 8 | exports.init = function() { 9 | var phy0 = this.lat0; 10 | this.lambda0 = this.long0; 11 | var sinPhy0 = Math.sin(phy0); 12 | var semiMajorAxis = this.a; 13 | var invF = this.rf; 14 | var flattening = 1 / invF; 15 | var e2 = 2 * flattening - Math.pow(flattening, 2); 16 | var e = this.e = Math.sqrt(e2); 17 | this.R = this.k0 * semiMajorAxis * Math.sqrt(1 - e2) / (1 - e2 * Math.pow(sinPhy0, 2)); 18 | this.alpha = Math.sqrt(1 + e2 / (1 - e2) * Math.pow(Math.cos(phy0), 4)); 19 | this.b0 = Math.asin(sinPhy0 / this.alpha); 20 | var k1 = Math.log(Math.tan(Math.PI / 4 + this.b0 / 2)); 21 | var k2 = Math.log(Math.tan(Math.PI / 4 + phy0 / 2)); 22 | var k3 = Math.log((1 + e * sinPhy0) / (1 - e * sinPhy0)); 23 | this.K = k1 - this.alpha * k2 + this.alpha * e / 2 * k3; 24 | }; 25 | 26 | 27 | exports.forward = function(p) { 28 | var Sa1 = Math.log(Math.tan(Math.PI / 4 - p.y / 2)); 29 | var Sa2 = this.e / 2 * Math.log((1 + this.e * Math.sin(p.y)) / (1 - this.e * Math.sin(p.y))); 30 | var S = -this.alpha * (Sa1 + Sa2) + this.K; 31 | 32 | // spheric latitude 33 | var b = 2 * (Math.atan(Math.exp(S)) - Math.PI / 4); 34 | 35 | // spheric longitude 36 | var I = this.alpha * (p.x - this.lambda0); 37 | 38 | // psoeudo equatorial rotation 39 | var rotI = Math.atan(Math.sin(I) / (Math.sin(this.b0) * Math.tan(b) + Math.cos(this.b0) * Math.cos(I))); 40 | 41 | var rotB = Math.asin(Math.cos(this.b0) * Math.sin(b) - Math.sin(this.b0) * Math.cos(b) * Math.cos(I)); 42 | 43 | p.y = this.R / 2 * Math.log((1 + Math.sin(rotB)) / (1 - Math.sin(rotB))) + this.y0; 44 | p.x = this.R * rotI + this.x0; 45 | return p; 46 | }; 47 | 48 | exports.inverse = function(p) { 49 | var Y = p.x - this.x0; 50 | var X = p.y - this.y0; 51 | 52 | var rotI = Y / this.R; 53 | var rotB = 2 * (Math.atan(Math.exp(X / this.R)) - Math.PI / 4); 54 | 55 | var b = Math.asin(Math.cos(this.b0) * Math.sin(rotB) + Math.sin(this.b0) * Math.cos(rotB) * Math.cos(rotI)); 56 | var I = Math.atan(Math.sin(rotI) / (Math.cos(this.b0) * Math.cos(rotI) - Math.sin(this.b0) * Math.tan(rotB))); 57 | 58 | var lambda = this.lambda0 + I / this.alpha; 59 | 60 | var S = 0; 61 | var phy = b; 62 | var prevPhy = -1000; 63 | var iteration = 0; 64 | while (Math.abs(phy - prevPhy) > 0.0000001) { 65 | if (++iteration > 20) { 66 | //...reportError("omercFwdInfinity"); 67 | return; 68 | } 69 | //S = Math.log(Math.tan(Math.PI / 4 + phy / 2)); 70 | S = 1 / this.alpha * (Math.log(Math.tan(Math.PI / 4 + b / 2)) - this.K) + this.e * Math.log(Math.tan(Math.PI / 4 + Math.asin(this.e * Math.sin(phy)) / 2)); 71 | prevPhy = phy; 72 | phy = 2 * Math.atan(Math.exp(S)) - Math.PI / 2; 73 | } 74 | 75 | p.x = lambda; 76 | p.y = phy; 77 | return p; 78 | }; 79 | 80 | exports.names = ["somerc"]; 81 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/gnom.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var EPSLN = 1.0e-10; 3 | var asinz = require('../common/asinz'); 4 | 5 | /* 6 | reference: 7 | Wolfram Mathworld "Gnomonic Projection" 8 | http://mathworld.wolfram.com/GnomonicProjection.html 9 | Accessed: 12th November 2009 10 | */ 11 | exports.init = function() { 12 | 13 | /* Place parameters in static storage for common use 14 | -------------------------------------------------*/ 15 | this.sin_p14 = Math.sin(this.lat0); 16 | this.cos_p14 = Math.cos(this.lat0); 17 | // Approximation for projecting points to the horizon (infinity) 18 | this.infinity_dist = 1000 * this.a; 19 | this.rc = 1; 20 | }; 21 | 22 | 23 | /* Gnomonic forward equations--mapping lat,long to x,y 24 | ---------------------------------------------------*/ 25 | exports.forward = function(p) { 26 | var sinphi, cosphi; /* sin and cos value */ 27 | var dlon; /* delta longitude value */ 28 | var coslon; /* cos of longitude */ 29 | var ksp; /* scale factor */ 30 | var g; 31 | var x, y; 32 | var lon = p.x; 33 | var lat = p.y; 34 | /* Forward equations 35 | -----------------*/ 36 | dlon = adjust_lon(lon - this.long0); 37 | 38 | sinphi = Math.sin(lat); 39 | cosphi = Math.cos(lat); 40 | 41 | coslon = Math.cos(dlon); 42 | g = this.sin_p14 * sinphi + this.cos_p14 * cosphi * coslon; 43 | ksp = 1; 44 | if ((g > 0) || (Math.abs(g) <= EPSLN)) { 45 | x = this.x0 + this.a * ksp * cosphi * Math.sin(dlon) / g; 46 | y = this.y0 + this.a * ksp * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon) / g; 47 | } 48 | else { 49 | 50 | // Point is in the opposing hemisphere and is unprojectable 51 | // We still need to return a reasonable point, so we project 52 | // to infinity, on a bearing 53 | // equivalent to the northern hemisphere equivalent 54 | // This is a reasonable approximation for short shapes and lines that 55 | // straddle the horizon. 56 | 57 | x = this.x0 + this.infinity_dist * cosphi * Math.sin(dlon); 58 | y = this.y0 + this.infinity_dist * (this.cos_p14 * sinphi - this.sin_p14 * cosphi * coslon); 59 | 60 | } 61 | p.x = x; 62 | p.y = y; 63 | return p; 64 | }; 65 | 66 | 67 | exports.inverse = function(p) { 68 | var rh; /* Rho */ 69 | var sinc, cosc; 70 | var c; 71 | var lon, lat; 72 | 73 | /* Inverse equations 74 | -----------------*/ 75 | p.x = (p.x - this.x0) / this.a; 76 | p.y = (p.y - this.y0) / this.a; 77 | 78 | p.x /= this.k0; 79 | p.y /= this.k0; 80 | 81 | if ((rh = Math.sqrt(p.x * p.x + p.y * p.y))) { 82 | c = Math.atan2(rh, this.rc); 83 | sinc = Math.sin(c); 84 | cosc = Math.cos(c); 85 | 86 | lat = asinz(cosc * this.sin_p14 + (p.y * sinc * this.cos_p14) / rh); 87 | lon = Math.atan2(p.x * sinc, rh * this.cos_p14 * cosc - p.y * this.sin_p14 * sinc); 88 | lon = adjust_lon(this.long0 + lon); 89 | } 90 | else { 91 | lat = this.phic0; 92 | lon = 0; 93 | } 94 | 95 | p.x = lon; 96 | p.y = lat; 97 | return p; 98 | }; 99 | exports.names = ["gnom"]; 100 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/Gruntfile.js: -------------------------------------------------------------------------------- 1 | var projs = [ 2 | 'tmerc', 3 | 'utm', 4 | 'sterea', 5 | 'stere', 6 | 'somerc', 7 | 'omerc', 8 | 'lcc', 9 | 'krovak', 10 | 'cass', 11 | 'laea', 12 | 'aea', 13 | 'gnom', 14 | 'cea', 15 | 'eqc', 16 | 'poly', 17 | 'nzmg', 18 | 'mill', 19 | 'sinu', 20 | 'moll', 21 | 'eqdc', 22 | 'vandg', 23 | 'aeqd' 24 | ]; 25 | module.exports = function(grunt) { 26 | grunt.initConfig({ 27 | pkg: grunt.file.readJSON('package.json'), 28 | connect: { 29 | server: { 30 | options: { 31 | port: process.env.PORT || 8080, 32 | base: '.' 33 | } 34 | } 35 | }, 36 | mocha_phantomjs: { 37 | all: { 38 | options: { 39 | reporter: "dot", 40 | urls: [ //my ide requries process.env.IP and PORT 41 | "http://" + (process.env.IP || "127.0.0.1") + ":" + (process.env.PORT || "8080") + "/test/amd.html", 42 | "http://" + (process.env.IP || "127.0.0.1") + ":" + (process.env.PORT || "8080") + "/test/opt.html" 43 | ] 44 | } 45 | } 46 | }, 47 | jshint: { 48 | options: { 49 | jshintrc: "./.jshintrc" 50 | }, 51 | all: ['./lib/*.js', './lib/*/*.js'] 52 | }, 53 | browserify: { 54 | all: { 55 | files: { 56 | 'dist/proj4-src.js': ['lib/index.js'], 57 | }, 58 | options: { 59 | standalone: 'proj4', 60 | alias: [ 61 | './projs:./includedProjections' 62 | ] 63 | } 64 | } 65 | }, 66 | uglify: { 67 | options: { 68 | report: 'gzip', 69 | mangle:{ 70 | except: ['proj4','Projection','Point'] 71 | }, 72 | }, 73 | all: { 74 | src: 'dist/proj4-src.js', 75 | dest: 'dist/proj4.js' 76 | } 77 | } 78 | }); 79 | grunt.loadNpmTasks('grunt-browserify'); 80 | grunt.loadNpmTasks('grunt-contrib-uglify'); 81 | grunt.loadNpmTasks('grunt-contrib-jshint'); 82 | grunt.loadNpmTasks('grunt-contrib-connect'); 83 | grunt.loadNpmTasks('grunt-mocha-phantomjs'); 84 | grunt.registerTask('custom',function(){ 85 | grunt.task.run('browserify', 'uglify'); 86 | var projections = this.args; 87 | if(projections[0]==='default'){ 88 | grunt.file.write('./projs.js','module.exports = function(){}'); 89 | return; 90 | } 91 | if(projections[0]==='all'){ 92 | projections = projs; 93 | } 94 | grunt.file.write('./projs.js',[ 95 | "var projs = [", 96 | " require('./lib/projections/"+projections.join("'),\n\trequire('./lib/projections/")+"')", 97 | "];", 98 | "module.exports = function(proj4){", 99 | " projs.forEach(function(proj){", 100 | " proj4.Proj.projections.add(proj);", 101 | " });", 102 | "}" 103 | ].join("\n")); 104 | }); 105 | grunt.registerTask('build',function(){ 106 | var args = this.args.length?this.args[0].split(','):['default']; 107 | grunt.task.run('jshint', 'custom:'+args.join(':')); 108 | }); 109 | grunt.registerTask('default', ['build:all', 'connect','mocha_phantomjs']); 110 | }; 111 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/datum/GCJ02.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.datum; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class GCJ02 implements Datum { 6 | 7 | private static double PI = Math.PI; 8 | private static double AXIS = 6378245.0; // 9 | private static double OFFSET = 0.00669342162296594323; //(a^2 - b^2) / a^2 10 | 11 | public T toWGS84(T point, PointAdaptor pointAdaptor) { 12 | double lng = pointAdaptor.getX(point); 13 | double lat = pointAdaptor.getY(point); 14 | 15 | if (outOfChina(lng, lat)) { 16 | return point; 17 | } 18 | 19 | double[] deltaD = delta(lng, lat); 20 | lng = lng - deltaD[0]; 21 | lat = lat - deltaD[1]; 22 | 23 | pointAdaptor.setX(point, lng); 24 | pointAdaptor.setY(point, lat); 25 | 26 | return point; 27 | } 28 | 29 | public T fromWGS84(T point, PointAdaptor pointAdaptor) { 30 | double lng = pointAdaptor.getX(point); 31 | double lat = pointAdaptor.getY(point); 32 | 33 | if (outOfChina(lng, lat)) { 34 | return point; 35 | } 36 | 37 | double[] deltaD = delta(lng, lat); 38 | lng = lng + deltaD[0]; 39 | lat = lat + deltaD[1]; 40 | 41 | pointAdaptor.setX(point, lng); 42 | pointAdaptor.setY(point, lat); 43 | 44 | return point; 45 | } 46 | 47 | private static double[] delta(double wgLon, double wgLat) { 48 | double[] lngLat = new double[2]; 49 | double dLat = transformLat(wgLon - 105.0, wgLat - 35.0); 50 | double dLon = transformLon(wgLon - 105.0, wgLat - 35.0); 51 | double radLat = wgLat / 180.0 * PI; 52 | double magic = Math.sin(radLat); 53 | magic = 1 - OFFSET * magic * magic; 54 | double sqrtMagic = Math.sqrt(magic); 55 | dLat = (dLat * 180.0) / ((AXIS * (1 - OFFSET)) / (magic * sqrtMagic) * PI); 56 | dLon = (dLon * 180.0) / (AXIS / sqrtMagic * Math.cos(radLat) * PI); 57 | lngLat[1] = dLat; 58 | lngLat[0] = dLon; 59 | return lngLat; 60 | } 61 | 62 | private static boolean outOfChina(double lon, double lat) { 63 | if (lon < 72.004 || lon > 137.8347) 64 | return true; 65 | if (lat < 0.8293 || lat > 55.8271) 66 | return true; 67 | return false; 68 | } 69 | 70 | private static double transformLat(double x, double y) { 71 | double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x)); 72 | ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0; 73 | ret += (20.0 * Math.sin(y * PI) + 40.0 * Math.sin(y / 3.0 * PI)) * 2.0 / 3.0; 74 | ret += (160.0 * Math.sin(y / 12.0 * PI) + 320 * Math.sin(y * PI / 30.0)) * 2.0 / 3.0; 75 | return ret; 76 | } 77 | 78 | private static double transformLon(double x, double y) { 79 | double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x)); 80 | ret += (20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0 / 3.0; 81 | ret += (20.0 * Math.sin(x * PI) + 40.0 * Math.sin(x / 3.0 * PI)) * 2.0 / 3.0; 82 | ret += (150.0 * Math.sin(x / 12.0 * PI) + 300.0 * Math.sin(x / 30.0 * PI)) * 2.0 / 3.0; 83 | return ret; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/cass.js: -------------------------------------------------------------------------------- 1 | var mlfn = require('../common/mlfn'); 2 | var e0fn = require('../common/e0fn'); 3 | var e1fn = require('../common/e1fn'); 4 | var e2fn = require('../common/e2fn'); 5 | var e3fn = require('../common/e3fn'); 6 | var gN = require('../common/gN'); 7 | var adjust_lon = require('../common/adjust_lon'); 8 | var adjust_lat = require('../common/adjust_lat'); 9 | var imlfn = require('../common/imlfn'); 10 | var HALF_PI = Math.PI/2; 11 | var EPSLN = 1.0e-10; 12 | exports.init = function() { 13 | if (!this.sphere) { 14 | this.e0 = e0fn(this.es); 15 | this.e1 = e1fn(this.es); 16 | this.e2 = e2fn(this.es); 17 | this.e3 = e3fn(this.es); 18 | this.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); 19 | } 20 | }; 21 | 22 | 23 | 24 | /* Cassini forward equations--mapping lat,long to x,y 25 | -----------------------------------------------------------------------*/ 26 | exports.forward = function(p) { 27 | 28 | /* Forward equations 29 | -----------------*/ 30 | var x, y; 31 | var lam = p.x; 32 | var phi = p.y; 33 | lam = adjust_lon(lam - this.long0); 34 | 35 | if (this.sphere) { 36 | x = this.a * Math.asin(Math.cos(phi) * Math.sin(lam)); 37 | y = this.a * (Math.atan2(Math.tan(phi), Math.cos(lam)) - this.lat0); 38 | } 39 | else { 40 | //ellipsoid 41 | var sinphi = Math.sin(phi); 42 | var cosphi = Math.cos(phi); 43 | var nl = gN(this.a, this.e, sinphi); 44 | var tl = Math.tan(phi) * Math.tan(phi); 45 | var al = lam * Math.cos(phi); 46 | var asq = al * al; 47 | var cl = this.es * cosphi * cosphi / (1 - this.es); 48 | var ml = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, phi); 49 | 50 | x = nl * al * (1 - asq * tl * (1 / 6 - (8 - tl + 8 * cl) * asq / 120)); 51 | y = ml - this.ml0 + nl * sinphi / cosphi * asq * (0.5 + (5 - tl + 6 * cl) * asq / 24); 52 | 53 | 54 | } 55 | 56 | p.x = x + this.x0; 57 | p.y = y + this.y0; 58 | return p; 59 | }; 60 | 61 | /* Inverse equations 62 | -----------------*/ 63 | exports.inverse = function(p) { 64 | p.x -= this.x0; 65 | p.y -= this.y0; 66 | var x = p.x / this.a; 67 | var y = p.y / this.a; 68 | var phi, lam; 69 | 70 | if (this.sphere) { 71 | var dd = y + this.lat0; 72 | phi = Math.asin(Math.sin(dd) * Math.cos(x)); 73 | lam = Math.atan2(Math.tan(x), Math.cos(dd)); 74 | } 75 | else { 76 | /* ellipsoid */ 77 | var ml1 = this.ml0 / this.a + y; 78 | var phi1 = imlfn(ml1, this.e0, this.e1, this.e2, this.e3); 79 | if (Math.abs(Math.abs(phi1) - HALF_PI) <= EPSLN) { 80 | p.x = this.long0; 81 | p.y = HALF_PI; 82 | if (y < 0) { 83 | p.y *= -1; 84 | } 85 | return p; 86 | } 87 | var nl1 = gN(this.a, this.e, Math.sin(phi1)); 88 | 89 | var rl1 = nl1 * nl1 * nl1 / this.a / this.a * (1 - this.es); 90 | var tl1 = Math.pow(Math.tan(phi1), 2); 91 | var dl = x * this.a / nl1; 92 | var dsq = dl * dl; 93 | phi = phi1 - nl1 * Math.tan(phi1) / rl1 * dl * dl * (0.5 - (1 + 3 * tl1) * dl * dl / 24); 94 | lam = dl * (1 - dsq * (tl1 / 3 + (1 + 3 * tl1) * tl1 * dsq / 15)) / Math.cos(phi1); 95 | 96 | } 97 | 98 | p.x = adjust_lon(lam + this.long0); 99 | p.y = adjust_lat(phi); 100 | return p; 101 | 102 | }; 103 | exports.names = ["Cassini", "Cassini_Soldner", "cass"]; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/datum_transform.js: -------------------------------------------------------------------------------- 1 | var PJD_3PARAM = 1; 2 | var PJD_7PARAM = 2; 3 | var PJD_GRIDSHIFT = 3; 4 | var PJD_NODATUM = 5; // WGS84 or equivalent 5 | var SRS_WGS84_SEMIMAJOR = 6378137; // only used in grid shift transforms 6 | var SRS_WGS84_ESQUARED = 0.006694379990141316; //DGR: 2012-07-29 7 | module.exports = function(source, dest, point) { 8 | var wp, i, l; 9 | 10 | function checkParams(fallback) { 11 | return (fallback === PJD_3PARAM || fallback === PJD_7PARAM); 12 | } 13 | // Short cut if the datums are identical. 14 | if (source.compare_datums(dest)) { 15 | return point; // in this case, zero is sucess, 16 | // whereas cs_compare_datums returns 1 to indicate TRUE 17 | // confusing, should fix this 18 | } 19 | 20 | // Explicitly skip datum transform by setting 'datum=none' as parameter for either source or dest 21 | if (source.datum_type === PJD_NODATUM || dest.datum_type === PJD_NODATUM) { 22 | return point; 23 | } 24 | 25 | //DGR: 2012-07-29 : add nadgrids support (begin) 26 | var src_a = source.a; 27 | var src_es = source.es; 28 | 29 | var dst_a = dest.a; 30 | var dst_es = dest.es; 31 | 32 | var fallback = source.datum_type; 33 | // If this datum requires grid shifts, then apply it to geodetic coordinates. 34 | if (fallback === PJD_GRIDSHIFT) { 35 | if (this.apply_gridshift(source, 0, point) === 0) { 36 | source.a = SRS_WGS84_SEMIMAJOR; 37 | source.es = SRS_WGS84_ESQUARED; 38 | } 39 | else { 40 | // try 3 or 7 params transformation or nothing ? 41 | if (!source.datum_params) { 42 | source.a = src_a; 43 | source.es = source.es; 44 | return point; 45 | } 46 | wp = 1; 47 | for (i = 0, l = source.datum_params.length; i < l; i++) { 48 | wp *= source.datum_params[i]; 49 | } 50 | if (wp === 0) { 51 | source.a = src_a; 52 | source.es = source.es; 53 | return point; 54 | } 55 | if (source.datum_params.length > 3) { 56 | fallback = PJD_7PARAM; 57 | } 58 | else { 59 | fallback = PJD_3PARAM; 60 | } 61 | } 62 | } 63 | if (dest.datum_type === PJD_GRIDSHIFT) { 64 | dest.a = SRS_WGS84_SEMIMAJOR; 65 | dest.es = SRS_WGS84_ESQUARED; 66 | } 67 | // Do we need to go through geocentric coordinates? 68 | if (source.es !== dest.es || source.a !== dest.a || checkParams(fallback) || checkParams(dest.datum_type)) { 69 | //DGR: 2012-07-29 : add nadgrids support (end) 70 | // Convert to geocentric coordinates. 71 | source.geodetic_to_geocentric(point); 72 | // CHECK_RETURN; 73 | // Convert between datums 74 | if (checkParams(source.datum_type)) { 75 | source.geocentric_to_wgs84(point); 76 | // CHECK_RETURN; 77 | } 78 | if (checkParams(dest.datum_type)) { 79 | dest.geocentric_from_wgs84(point); 80 | // CHECK_RETURN; 81 | } 82 | // Convert back to geodetic coordinates 83 | dest.geocentric_to_geodetic(point); 84 | // CHECK_RETURN; 85 | } 86 | // Apply grid shift to destination if required 87 | if (dest.datum_type === PJD_GRIDSHIFT) { 88 | this.apply_gridshift(dest, 1, point); 89 | // CHECK_RETURN; 90 | } 91 | 92 | source.a = src_a; 93 | source.es = src_es; 94 | dest.a = dst_a; 95 | dest.es = dst_es; 96 | 97 | return point; 98 | }; 99 | 100 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/eqdc.js: -------------------------------------------------------------------------------- 1 | var e0fn = require('../common/e0fn'); 2 | var e1fn = require('../common/e1fn'); 3 | var e2fn = require('../common/e2fn'); 4 | var e3fn = require('../common/e3fn'); 5 | var msfnz = require('../common/msfnz'); 6 | var mlfn = require('../common/mlfn'); 7 | var adjust_lon = require('../common/adjust_lon'); 8 | var adjust_lat = require('../common/adjust_lat'); 9 | var imlfn = require('../common/imlfn'); 10 | var EPSLN = 1.0e-10; 11 | exports.init = function() { 12 | 13 | /* Place parameters in static storage for common use 14 | -------------------------------------------------*/ 15 | // Standard Parallels cannot be equal and on opposite sides of the equator 16 | if (Math.abs(this.lat1 + this.lat2) < EPSLN) { 17 | return; 18 | } 19 | this.lat2 = this.lat2 || this.lat1; 20 | this.temp = this.b / this.a; 21 | this.es = 1 - Math.pow(this.temp, 2); 22 | this.e = Math.sqrt(this.es); 23 | this.e0 = e0fn(this.es); 24 | this.e1 = e1fn(this.es); 25 | this.e2 = e2fn(this.es); 26 | this.e3 = e3fn(this.es); 27 | 28 | this.sinphi = Math.sin(this.lat1); 29 | this.cosphi = Math.cos(this.lat1); 30 | 31 | this.ms1 = msfnz(this.e, this.sinphi, this.cosphi); 32 | this.ml1 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat1); 33 | 34 | if (Math.abs(this.lat1 - this.lat2) < EPSLN) { 35 | this.ns = this.sinphi; 36 | } 37 | else { 38 | this.sinphi = Math.sin(this.lat2); 39 | this.cosphi = Math.cos(this.lat2); 40 | this.ms2 = msfnz(this.e, this.sinphi, this.cosphi); 41 | this.ml2 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat2); 42 | this.ns = (this.ms1 - this.ms2) / (this.ml2 - this.ml1); 43 | } 44 | this.g = this.ml1 + this.ms1 / this.ns; 45 | this.ml0 = mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); 46 | this.rh = this.a * (this.g - this.ml0); 47 | }; 48 | 49 | 50 | /* Equidistant Conic forward equations--mapping lat,long to x,y 51 | -----------------------------------------------------------*/ 52 | exports.forward = function(p) { 53 | var lon = p.x; 54 | var lat = p.y; 55 | var rh1; 56 | 57 | /* Forward equations 58 | -----------------*/ 59 | if (this.sphere) { 60 | rh1 = this.a * (this.g - lat); 61 | } 62 | else { 63 | var ml = mlfn(this.e0, this.e1, this.e2, this.e3, lat); 64 | rh1 = this.a * (this.g - ml); 65 | } 66 | var theta = this.ns * adjust_lon(lon - this.long0); 67 | var x = this.x0 + rh1 * Math.sin(theta); 68 | var y = this.y0 + this.rh - rh1 * Math.cos(theta); 69 | p.x = x; 70 | p.y = y; 71 | return p; 72 | }; 73 | 74 | /* Inverse equations 75 | -----------------*/ 76 | exports.inverse = function(p) { 77 | p.x -= this.x0; 78 | p.y = this.rh - p.y + this.y0; 79 | var con, rh1, lat, lon; 80 | if (this.ns >= 0) { 81 | rh1 = Math.sqrt(p.x * p.x + p.y * p.y); 82 | con = 1; 83 | } 84 | else { 85 | rh1 = -Math.sqrt(p.x * p.x + p.y * p.y); 86 | con = -1; 87 | } 88 | var theta = 0; 89 | if (rh1 !== 0) { 90 | theta = Math.atan2(con * p.x, con * p.y); 91 | } 92 | 93 | if (this.sphere) { 94 | lon = adjust_lon(this.long0 + theta / this.ns); 95 | lat = adjust_lat(this.g - rh1 / this.a); 96 | p.x = lon; 97 | p.y = lat; 98 | return p; 99 | } 100 | else { 101 | var ml = this.g - rh1 / this.a; 102 | lat = imlfn(ml, this.e0, this.e1, this.e2, this.e3); 103 | lon = adjust_lon(this.long0 + theta / this.ns); 104 | p.x = lon; 105 | p.y = lat; 106 | return p; 107 | } 108 | 109 | }; 110 | exports.names = ["Equidistant_Conic", "eqdc"]; 111 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/krovak.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | exports.init = function() { 3 | this.a = 6377397.155; 4 | this.es = 0.006674372230614; 5 | this.e = Math.sqrt(this.es); 6 | if (!this.lat0) { 7 | this.lat0 = 0.863937979737193; 8 | } 9 | if (!this.long0) { 10 | this.long0 = 0.7417649320975901 - 0.308341501185665; 11 | } 12 | /* if scale not set default to 0.9999 */ 13 | if (!this.k0) { 14 | this.k0 = 0.9999; 15 | } 16 | this.s45 = 0.785398163397448; /* 45 */ 17 | this.s90 = 2 * this.s45; 18 | this.fi0 = this.lat0; 19 | this.e2 = this.es; 20 | this.e = Math.sqrt(this.e2); 21 | this.alfa = Math.sqrt(1 + (this.e2 * Math.pow(Math.cos(this.fi0), 4)) / (1 - this.e2)); 22 | this.uq = 1.04216856380474; 23 | this.u0 = Math.asin(Math.sin(this.fi0) / this.alfa); 24 | this.g = Math.pow((1 + this.e * Math.sin(this.fi0)) / (1 - this.e * Math.sin(this.fi0)), this.alfa * this.e / 2); 25 | this.k = Math.tan(this.u0 / 2 + this.s45) / Math.pow(Math.tan(this.fi0 / 2 + this.s45), this.alfa) * this.g; 26 | this.k1 = this.k0; 27 | this.n0 = this.a * Math.sqrt(1 - this.e2) / (1 - this.e2 * Math.pow(Math.sin(this.fi0), 2)); 28 | this.s0 = 1.37008346281555; 29 | this.n = Math.sin(this.s0); 30 | this.ro0 = this.k1 * this.n0 / Math.tan(this.s0); 31 | this.ad = this.s90 - this.uq; 32 | }; 33 | 34 | /* ellipsoid */ 35 | /* calculate xy from lat/lon */ 36 | /* Constants, identical to inverse transform function */ 37 | exports.forward = function(p) { 38 | var gfi, u, deltav, s, d, eps, ro; 39 | var lon = p.x; 40 | var lat = p.y; 41 | var delta_lon = adjust_lon(lon - this.long0); 42 | /* Transformation */ 43 | gfi = Math.pow(((1 + this.e * Math.sin(lat)) / (1 - this.e * Math.sin(lat))), (this.alfa * this.e / 2)); 44 | u = 2 * (Math.atan(this.k * Math.pow(Math.tan(lat / 2 + this.s45), this.alfa) / gfi) - this.s45); 45 | deltav = -delta_lon * this.alfa; 46 | s = Math.asin(Math.cos(this.ad) * Math.sin(u) + Math.sin(this.ad) * Math.cos(u) * Math.cos(deltav)); 47 | d = Math.asin(Math.cos(u) * Math.sin(deltav) / Math.cos(s)); 48 | eps = this.n * d; 49 | ro = this.ro0 * Math.pow(Math.tan(this.s0 / 2 + this.s45), this.n) / Math.pow(Math.tan(s / 2 + this.s45), this.n); 50 | p.y = ro * Math.cos(eps) / 1; 51 | p.x = ro * Math.sin(eps) / 1; 52 | 53 | if (!this.czech) { 54 | p.y *= -1; 55 | p.x *= -1; 56 | } 57 | return (p); 58 | }; 59 | 60 | /* calculate lat/lon from xy */ 61 | exports.inverse = function(p) { 62 | var u, deltav, s, d, eps, ro, fi1; 63 | var ok; 64 | 65 | /* Transformation */ 66 | /* revert y, x*/ 67 | var tmp = p.x; 68 | p.x = p.y; 69 | p.y = tmp; 70 | if (!this.czech) { 71 | p.y *= -1; 72 | p.x *= -1; 73 | } 74 | ro = Math.sqrt(p.x * p.x + p.y * p.y); 75 | eps = Math.atan2(p.y, p.x); 76 | d = eps / Math.sin(this.s0); 77 | s = 2 * (Math.atan(Math.pow(this.ro0 / ro, 1 / this.n) * Math.tan(this.s0 / 2 + this.s45)) - this.s45); 78 | u = Math.asin(Math.cos(this.ad) * Math.sin(s) - Math.sin(this.ad) * Math.cos(s) * Math.cos(d)); 79 | deltav = Math.asin(Math.cos(s) * Math.sin(d) / Math.cos(u)); 80 | p.x = this.long0 - deltav / this.alfa; 81 | fi1 = u; 82 | ok = 0; 83 | var iter = 0; 84 | do { 85 | p.y = 2 * (Math.atan(Math.pow(this.k, - 1 / this.alfa) * Math.pow(Math.tan(u / 2 + this.s45), 1 / this.alfa) * Math.pow((1 + this.e * Math.sin(fi1)) / (1 - this.e * Math.sin(fi1)), this.e / 2)) - this.s45); 86 | if (Math.abs(fi1 - p.y) < 0.0000000001) { 87 | ok = 1; 88 | } 89 | fi1 = p.y; 90 | iter += 1; 91 | } while (ok === 0 && iter < 15); 92 | if (iter >= 15) { 93 | return null; 94 | } 95 | 96 | return (p); 97 | }; 98 | exports.names = ["Krovak", "krovak"]; 99 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/vandg.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var HALF_PI = Math.PI/2; 3 | var EPSLN = 1.0e-10; 4 | var asinz = require('../common/asinz'); 5 | /* Initialize the Van Der Grinten projection 6 | ----------------------------------------*/ 7 | exports.init = function() { 8 | //this.R = 6370997; //Radius of earth 9 | this.R = this.a; 10 | }; 11 | 12 | exports.forward = function(p) { 13 | 14 | var lon = p.x; 15 | var lat = p.y; 16 | 17 | /* Forward equations 18 | -----------------*/ 19 | var dlon = adjust_lon(lon - this.long0); 20 | var x, y; 21 | 22 | if (Math.abs(lat) <= EPSLN) { 23 | x = this.x0 + this.R * dlon; 24 | y = this.y0; 25 | } 26 | var theta = asinz(2 * Math.abs(lat / Math.PI)); 27 | if ((Math.abs(dlon) <= EPSLN) || (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN)) { 28 | x = this.x0; 29 | if (lat >= 0) { 30 | y = this.y0 + Math.PI * this.R * Math.tan(0.5 * theta); 31 | } 32 | else { 33 | y = this.y0 + Math.PI * this.R * -Math.tan(0.5 * theta); 34 | } 35 | // return(OK); 36 | } 37 | var al = 0.5 * Math.abs((Math.PI / dlon) - (dlon / Math.PI)); 38 | var asq = al * al; 39 | var sinth = Math.sin(theta); 40 | var costh = Math.cos(theta); 41 | 42 | var g = costh / (sinth + costh - 1); 43 | var gsq = g * g; 44 | var m = g * (2 / sinth - 1); 45 | var msq = m * m; 46 | var con = Math.PI * this.R * (al * (g - msq) + Math.sqrt(asq * (g - msq) * (g - msq) - (msq + asq) * (gsq - msq))) / (msq + asq); 47 | if (dlon < 0) { 48 | con = -con; 49 | } 50 | x = this.x0 + con; 51 | //con = Math.abs(con / (Math.PI * this.R)); 52 | var q = asq + g; 53 | con = Math.PI * this.R * (m * q - al * Math.sqrt((msq + asq) * (asq + 1) - q * q)) / (msq + asq); 54 | if (lat >= 0) { 55 | //y = this.y0 + Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con); 56 | y = this.y0 + con; 57 | } 58 | else { 59 | //y = this.y0 - Math.PI * this.R * Math.sqrt(1 - con * con - 2 * al * con); 60 | y = this.y0 - con; 61 | } 62 | p.x = x; 63 | p.y = y; 64 | return p; 65 | }; 66 | 67 | /* Van Der Grinten inverse equations--mapping x,y to lat/long 68 | ---------------------------------------------------------*/ 69 | exports.inverse = function(p) { 70 | var lon, lat; 71 | var xx, yy, xys, c1, c2, c3; 72 | var a1; 73 | var m1; 74 | var con; 75 | var th1; 76 | var d; 77 | 78 | /* inverse equations 79 | -----------------*/ 80 | p.x -= this.x0; 81 | p.y -= this.y0; 82 | con = Math.PI * this.R; 83 | xx = p.x / con; 84 | yy = p.y / con; 85 | xys = xx * xx + yy * yy; 86 | c1 = -Math.abs(yy) * (1 + xys); 87 | c2 = c1 - 2 * yy * yy + xx * xx; 88 | c3 = -2 * c1 + 1 + 2 * yy * yy + xys * xys; 89 | d = yy * yy / c3 + (2 * c2 * c2 * c2 / c3 / c3 / c3 - 9 * c1 * c2 / c3 / c3) / 27; 90 | a1 = (c1 - c2 * c2 / 3 / c3) / c3; 91 | m1 = 2 * Math.sqrt(-a1 / 3); 92 | con = ((3 * d) / a1) / m1; 93 | if (Math.abs(con) > 1) { 94 | if (con >= 0) { 95 | con = 1; 96 | } 97 | else { 98 | con = -1; 99 | } 100 | } 101 | th1 = Math.acos(con) / 3; 102 | if (p.y >= 0) { 103 | lat = (-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI; 104 | } 105 | else { 106 | lat = -(-m1 * Math.cos(th1 + Math.PI / 3) - c2 / 3 / c3) * Math.PI; 107 | } 108 | 109 | if (Math.abs(xx) < EPSLN) { 110 | lon = this.long0; 111 | } 112 | else { 113 | lon = adjust_lon(this.long0 + Math.PI * (xys - 1 + Math.sqrt(1 + 2 * (xx * xx - yy * yy) + xys * xys)) / 2 / xx); 114 | } 115 | 116 | p.x = lon; 117 | p.y = lat; 118 | return p; 119 | }; 120 | exports.names = ["Van_der_Grinten_I", "VanDerGrinten", "vandg"]; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projString.js: -------------------------------------------------------------------------------- 1 | var D2R = 0.01745329251994329577; 2 | var PrimeMeridian = require('./constants/PrimeMeridian'); 3 | var units = require('./constants/units'); 4 | 5 | module.exports = function(defData) { 6 | var self = {}; 7 | var paramObj = {}; 8 | defData.split("+").map(function(v) { 9 | return v.trim(); 10 | }).filter(function(a) { 11 | return a; 12 | }).forEach(function(a) { 13 | var split = a.split("="); 14 | split.push(true); 15 | paramObj[split[0].toLowerCase()] = split[1]; 16 | }); 17 | var paramName, paramVal, paramOutname; 18 | var params = { 19 | proj: 'projName', 20 | datum: 'datumCode', 21 | rf: function(v) { 22 | self.rf = parseFloat(v); 23 | }, 24 | lat_0: function(v) { 25 | self.lat0 = v * D2R; 26 | }, 27 | lat_1: function(v) { 28 | self.lat1 = v * D2R; 29 | }, 30 | lat_2: function(v) { 31 | self.lat2 = v * D2R; 32 | }, 33 | lat_ts: function(v) { 34 | self.lat_ts = v * D2R; 35 | }, 36 | lon_0: function(v) { 37 | self.long0 = v * D2R; 38 | }, 39 | lon_1: function(v) { 40 | self.long1 = v * D2R; 41 | }, 42 | lon_2: function(v) { 43 | self.long2 = v * D2R; 44 | }, 45 | alpha: function(v) { 46 | self.alpha = parseFloat(v) * D2R; 47 | }, 48 | lonc: function(v) { 49 | self.longc = v * D2R; 50 | }, 51 | x_0: function(v) { 52 | self.x0 = parseFloat(v); 53 | }, 54 | y_0: function(v) { 55 | self.y0 = parseFloat(v); 56 | }, 57 | k_0: function(v) { 58 | self.k0 = parseFloat(v); 59 | }, 60 | k: function(v) { 61 | self.k0 = parseFloat(v); 62 | }, 63 | a: function(v) { 64 | self.a = parseFloat(v); 65 | }, 66 | b: function(v) { 67 | self.b = parseFloat(v); 68 | }, 69 | r_a: function() { 70 | self.R_A = true; 71 | }, 72 | zone: function(v) { 73 | self.zone = parseInt(v, 10); 74 | }, 75 | south: function() { 76 | self.utmSouth = true; 77 | }, 78 | towgs84: function(v) { 79 | self.datum_params = v.split(",").map(function(a) { 80 | return parseFloat(a); 81 | }); 82 | }, 83 | to_meter: function(v) { 84 | self.to_meter = parseFloat(v); 85 | }, 86 | units: function(v) { 87 | self.units = v; 88 | if (units[v]) { 89 | self.to_meter = units[v].to_meter; 90 | } 91 | }, 92 | from_greenwich: function(v) { 93 | self.from_greenwich = v * D2R; 94 | }, 95 | pm: function(v) { 96 | self.from_greenwich = (PrimeMeridian[v] ? PrimeMeridian[v] : parseFloat(v)) * D2R; 97 | }, 98 | nadgrids: function(v) { 99 | if (v === '@null') { 100 | self.datumCode = 'none'; 101 | } 102 | else { 103 | self.nadgrids = v; 104 | } 105 | }, 106 | axis: function(v) { 107 | var legalAxis = "ewnsud"; 108 | if (v.length === 3 && legalAxis.indexOf(v.substr(0, 1)) !== -1 && legalAxis.indexOf(v.substr(1, 1)) !== -1 && legalAxis.indexOf(v.substr(2, 1)) !== -1) { 109 | self.axis = v; 110 | } 111 | } 112 | }; 113 | for (paramName in paramObj) { 114 | paramVal = paramObj[paramName]; 115 | if (paramName in params) { 116 | paramOutname = params[paramName]; 117 | if (typeof paramOutname === 'function') { 118 | paramOutname(paramVal); 119 | } 120 | else { 121 | self[paramOutname] = paramVal; 122 | } 123 | } 124 | else { 125 | self[paramName] = paramVal; 126 | } 127 | } 128 | if(typeof self.datumCode === 'string' && self.datumCode !== "WGS84"){ 129 | self.datumCode = self.datumCode.toLowerCase(); 130 | } 131 | return self; 132 | }; 133 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/aea.js: -------------------------------------------------------------------------------- 1 | var EPSLN = 1.0e-10; 2 | var msfnz = require('../common/msfnz'); 3 | var qsfnz = require('../common/qsfnz'); 4 | var adjust_lon = require('../common/adjust_lon'); 5 | var asinz = require('../common/asinz'); 6 | exports.init = function() { 7 | 8 | if (Math.abs(this.lat1 + this.lat2) < EPSLN) { 9 | return; 10 | } 11 | this.temp = this.b / this.a; 12 | this.es = 1 - Math.pow(this.temp, 2); 13 | this.e3 = Math.sqrt(this.es); 14 | 15 | this.sin_po = Math.sin(this.lat1); 16 | this.cos_po = Math.cos(this.lat1); 17 | this.t1 = this.sin_po; 18 | this.con = this.sin_po; 19 | this.ms1 = msfnz(this.e3, this.sin_po, this.cos_po); 20 | this.qs1 = qsfnz(this.e3, this.sin_po, this.cos_po); 21 | 22 | this.sin_po = Math.sin(this.lat2); 23 | this.cos_po = Math.cos(this.lat2); 24 | this.t2 = this.sin_po; 25 | this.ms2 = msfnz(this.e3, this.sin_po, this.cos_po); 26 | this.qs2 = qsfnz(this.e3, this.sin_po, this.cos_po); 27 | 28 | this.sin_po = Math.sin(this.lat0); 29 | this.cos_po = Math.cos(this.lat0); 30 | this.t3 = this.sin_po; 31 | this.qs0 = qsfnz(this.e3, this.sin_po, this.cos_po); 32 | 33 | if (Math.abs(this.lat1 - this.lat2) > EPSLN) { 34 | this.ns0 = (this.ms1 * this.ms1 - this.ms2 * this.ms2) / (this.qs2 - this.qs1); 35 | } 36 | else { 37 | this.ns0 = this.con; 38 | } 39 | this.c = this.ms1 * this.ms1 + this.ns0 * this.qs1; 40 | this.rh = this.a * Math.sqrt(this.c - this.ns0 * this.qs0) / this.ns0; 41 | }; 42 | 43 | /* Albers Conical Equal Area forward equations--mapping lat,long to x,y 44 | -------------------------------------------------------------------*/ 45 | exports.forward = function(p) { 46 | 47 | var lon = p.x; 48 | var lat = p.y; 49 | 50 | this.sin_phi = Math.sin(lat); 51 | this.cos_phi = Math.cos(lat); 52 | 53 | var qs = qsfnz(this.e3, this.sin_phi, this.cos_phi); 54 | var rh1 = this.a * Math.sqrt(this.c - this.ns0 * qs) / this.ns0; 55 | var theta = this.ns0 * adjust_lon(lon - this.long0); 56 | var x = rh1 * Math.sin(theta) + this.x0; 57 | var y = this.rh - rh1 * Math.cos(theta) + this.y0; 58 | 59 | p.x = x; 60 | p.y = y; 61 | return p; 62 | }; 63 | 64 | 65 | exports.inverse = function(p) { 66 | var rh1, qs, con, theta, lon, lat; 67 | 68 | p.x -= this.x0; 69 | p.y = this.rh - p.y + this.y0; 70 | if (this.ns0 >= 0) { 71 | rh1 = Math.sqrt(p.x * p.x + p.y * p.y); 72 | con = 1; 73 | } 74 | else { 75 | rh1 = -Math.sqrt(p.x * p.x + p.y * p.y); 76 | con = -1; 77 | } 78 | theta = 0; 79 | if (rh1 !== 0) { 80 | theta = Math.atan2(con * p.x, con * p.y); 81 | } 82 | con = rh1 * this.ns0 / this.a; 83 | if (this.sphere) { 84 | lat = Math.asin((this.c - con * con) / (2 * this.ns0)); 85 | } 86 | else { 87 | qs = (this.c - con * con) / this.ns0; 88 | lat = this.phi1z(this.e3, qs); 89 | } 90 | 91 | lon = adjust_lon(theta / this.ns0 + this.long0); 92 | p.x = lon; 93 | p.y = lat; 94 | return p; 95 | }; 96 | 97 | /* Function to compute phi1, the latitude for the inverse of the 98 | Albers Conical Equal-Area projection. 99 | -------------------------------------------*/ 100 | exports.phi1z = function(eccent, qs) { 101 | var sinphi, cosphi, con, com, dphi; 102 | var phi = asinz(0.5 * qs); 103 | if (eccent < EPSLN) { 104 | return phi; 105 | } 106 | 107 | var eccnts = eccent * eccent; 108 | for (var i = 1; i <= 25; i++) { 109 | sinphi = Math.sin(phi); 110 | cosphi = Math.cos(phi); 111 | con = eccent * sinphi; 112 | com = 1 - con * con; 113 | dphi = 0.5 * com * com / cosphi * (qs / (1 - eccnts) - sinphi / com + 0.5 / eccent * Math.log((1 - con) / (1 + con))); 114 | phi = phi + dphi; 115 | if (Math.abs(dphi) <= 1e-7) { 116 | return phi; 117 | } 118 | } 119 | return null; 120 | }; 121 | exports.names = ["Albers_Conic_Equal_Area", "Albers", "aea"]; 122 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/lcc.js: -------------------------------------------------------------------------------- 1 | var EPSLN = 1.0e-10; 2 | var msfnz = require('../common/msfnz'); 3 | var tsfnz = require('../common/tsfnz'); 4 | var HALF_PI = Math.PI/2; 5 | var sign = require('../common/sign'); 6 | var adjust_lon = require('../common/adjust_lon'); 7 | var phi2z = require('../common/phi2z'); 8 | exports.init = function() { 9 | 10 | // array of: r_maj,r_min,lat1,lat2,c_lon,c_lat,false_east,false_north 11 | //double c_lat; /* center latitude */ 12 | //double c_lon; /* center longitude */ 13 | //double lat1; /* first standard parallel */ 14 | //double lat2; /* second standard parallel */ 15 | //double r_maj; /* major axis */ 16 | //double r_min; /* minor axis */ 17 | //double false_east; /* x offset in meters */ 18 | //double false_north; /* y offset in meters */ 19 | 20 | if (!this.lat2) { 21 | this.lat2 = this.lat1; 22 | } //if lat2 is not defined 23 | if (!this.k0) { 24 | this.k0 = 1; 25 | } 26 | this.x0 = this.x0 || 0; 27 | this.y0 = this.y0 || 0; 28 | // Standard Parallels cannot be equal and on opposite sides of the equator 29 | if (Math.abs(this.lat1 + this.lat2) < EPSLN) { 30 | return; 31 | } 32 | 33 | var temp = this.b / this.a; 34 | this.e = Math.sqrt(1 - temp * temp); 35 | 36 | var sin1 = Math.sin(this.lat1); 37 | var cos1 = Math.cos(this.lat1); 38 | var ms1 = msfnz(this.e, sin1, cos1); 39 | var ts1 = tsfnz(this.e, this.lat1, sin1); 40 | 41 | var sin2 = Math.sin(this.lat2); 42 | var cos2 = Math.cos(this.lat2); 43 | var ms2 = msfnz(this.e, sin2, cos2); 44 | var ts2 = tsfnz(this.e, this.lat2, sin2); 45 | 46 | var ts0 = tsfnz(this.e, this.lat0, Math.sin(this.lat0)); 47 | 48 | if (Math.abs(this.lat1 - this.lat2) > EPSLN) { 49 | this.ns = Math.log(ms1 / ms2) / Math.log(ts1 / ts2); 50 | } 51 | else { 52 | this.ns = sin1; 53 | } 54 | if (isNaN(this.ns)) { 55 | this.ns = sin1; 56 | } 57 | this.f0 = ms1 / (this.ns * Math.pow(ts1, this.ns)); 58 | this.rh = this.a * this.f0 * Math.pow(ts0, this.ns); 59 | if (!this.title) { 60 | this.title = "Lambert Conformal Conic"; 61 | } 62 | }; 63 | 64 | 65 | // Lambert Conformal conic forward equations--mapping lat,long to x,y 66 | // ----------------------------------------------------------------- 67 | exports.forward = function(p) { 68 | 69 | var lon = p.x; 70 | var lat = p.y; 71 | 72 | // singular cases : 73 | if (Math.abs(2 * Math.abs(lat) - Math.PI) <= EPSLN) { 74 | lat = sign(lat) * (HALF_PI - 2 * EPSLN); 75 | } 76 | 77 | var con = Math.abs(Math.abs(lat) - HALF_PI); 78 | var ts, rh1; 79 | if (con > EPSLN) { 80 | ts = tsfnz(this.e, lat, Math.sin(lat)); 81 | rh1 = this.a * this.f0 * Math.pow(ts, this.ns); 82 | } 83 | else { 84 | con = lat * this.ns; 85 | if (con <= 0) { 86 | return null; 87 | } 88 | rh1 = 0; 89 | } 90 | var theta = this.ns * adjust_lon(lon - this.long0); 91 | p.x = this.k0 * (rh1 * Math.sin(theta)) + this.x0; 92 | p.y = this.k0 * (this.rh - rh1 * Math.cos(theta)) + this.y0; 93 | 94 | return p; 95 | }; 96 | 97 | // Lambert Conformal Conic inverse equations--mapping x,y to lat/long 98 | // ----------------------------------------------------------------- 99 | exports.inverse = function(p) { 100 | 101 | var rh1, con, ts; 102 | var lat, lon; 103 | var x = (p.x - this.x0) / this.k0; 104 | var y = (this.rh - (p.y - this.y0) / this.k0); 105 | if (this.ns > 0) { 106 | rh1 = Math.sqrt(x * x + y * y); 107 | con = 1; 108 | } 109 | else { 110 | rh1 = -Math.sqrt(x * x + y * y); 111 | con = -1; 112 | } 113 | var theta = 0; 114 | if (rh1 !== 0) { 115 | theta = Math.atan2((con * x), (con * y)); 116 | } 117 | if ((rh1 !== 0) || (this.ns > 0)) { 118 | con = 1 / this.ns; 119 | ts = Math.pow((rh1 / (this.a * this.f0)), con); 120 | lat = phi2z(this.e, ts); 121 | if (lat === -9999) { 122 | return null; 123 | } 124 | } 125 | else { 126 | lat = -HALF_PI; 127 | } 128 | lon = adjust_lon(theta / this.ns + this.long0); 129 | 130 | p.x = lon; 131 | p.y = lat; 132 | return p; 133 | }; 134 | 135 | exports.names = ["Lambert Tangential Conformal Conic Projection", "Lambert_Conformal_Conic", "Lambert_Conformal_Conic_2SP", "lcc"]; 136 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/poly.js: -------------------------------------------------------------------------------- 1 | var e0fn = require('../common/e0fn'); 2 | var e1fn = require('../common/e1fn'); 3 | var e2fn = require('../common/e2fn'); 4 | var e3fn = require('../common/e3fn'); 5 | var adjust_lon = require('../common/adjust_lon'); 6 | var adjust_lat = require('../common/adjust_lat'); 7 | var mlfn = require('../common/mlfn'); 8 | var EPSLN = 1.0e-10; 9 | var gN = require('../common/gN'); 10 | var MAX_ITER = 20; 11 | exports.init = function() { 12 | /* Place parameters in static storage for common use 13 | -------------------------------------------------*/ 14 | this.temp = this.b / this.a; 15 | this.es = 1 - Math.pow(this.temp, 2); // devait etre dans tmerc.js mais n y est pas donc je commente sinon retour de valeurs nulles 16 | this.e = Math.sqrt(this.es); 17 | this.e0 = e0fn(this.es); 18 | this.e1 = e1fn(this.es); 19 | this.e2 = e2fn(this.es); 20 | this.e3 = e3fn(this.es); 21 | this.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); //si que des zeros le calcul ne se fait pas 22 | }; 23 | 24 | 25 | /* Polyconic forward equations--mapping lat,long to x,y 26 | ---------------------------------------------------*/ 27 | exports.forward = function(p) { 28 | var lon = p.x; 29 | var lat = p.y; 30 | var x, y, el; 31 | var dlon = adjust_lon(lon - this.long0); 32 | el = dlon * Math.sin(lat); 33 | if (this.sphere) { 34 | if (Math.abs(lat) <= EPSLN) { 35 | x = this.a * dlon; 36 | y = -1 * this.a * this.lat0; 37 | } 38 | else { 39 | x = this.a * Math.sin(el) / Math.tan(lat); 40 | y = this.a * (adjust_lat(lat - this.lat0) + (1 - Math.cos(el)) / Math.tan(lat)); 41 | } 42 | } 43 | else { 44 | if (Math.abs(lat) <= EPSLN) { 45 | x = this.a * dlon; 46 | y = -1 * this.ml0; 47 | } 48 | else { 49 | var nl = gN(this.a, this.e, Math.sin(lat)) / Math.tan(lat); 50 | x = nl * Math.sin(el); 51 | y = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat) - this.ml0 + nl * (1 - Math.cos(el)); 52 | } 53 | 54 | } 55 | p.x = x + this.x0; 56 | p.y = y + this.y0; 57 | return p; 58 | }; 59 | 60 | 61 | /* Inverse equations 62 | -----------------*/ 63 | exports.inverse = function(p) { 64 | var lon, lat, x, y, i; 65 | var al, bl; 66 | var phi, dphi; 67 | x = p.x - this.x0; 68 | y = p.y - this.y0; 69 | 70 | if (this.sphere) { 71 | if (Math.abs(y + this.a * this.lat0) <= EPSLN) { 72 | lon = adjust_lon(x / this.a + this.long0); 73 | lat = 0; 74 | } 75 | else { 76 | al = this.lat0 + y / this.a; 77 | bl = x * x / this.a / this.a + al * al; 78 | phi = al; 79 | var tanphi; 80 | for (i = MAX_ITER; i; --i) { 81 | tanphi = Math.tan(phi); 82 | dphi = -1 * (al * (phi * tanphi + 1) - phi - 0.5 * (phi * phi + bl) * tanphi) / ((phi - al) / tanphi - 1); 83 | phi += dphi; 84 | if (Math.abs(dphi) <= EPSLN) { 85 | lat = phi; 86 | break; 87 | } 88 | } 89 | lon = adjust_lon(this.long0 + (Math.asin(x * Math.tan(phi) / this.a)) / Math.sin(lat)); 90 | } 91 | } 92 | else { 93 | if (Math.abs(y + this.ml0) <= EPSLN) { 94 | lat = 0; 95 | lon = adjust_lon(this.long0 + x / this.a); 96 | } 97 | else { 98 | 99 | al = (this.ml0 + y) / this.a; 100 | bl = x * x / this.a / this.a + al * al; 101 | phi = al; 102 | var cl, mln, mlnp, ma; 103 | var con; 104 | for (i = MAX_ITER; i; --i) { 105 | con = this.e * Math.sin(phi); 106 | cl = Math.sqrt(1 - con * con) * Math.tan(phi); 107 | mln = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, phi); 108 | mlnp = this.e0 - 2 * this.e1 * Math.cos(2 * phi) + 4 * this.e2 * Math.cos(4 * phi) - 6 * this.e3 * Math.cos(6 * phi); 109 | ma = mln / this.a; 110 | dphi = (al * (cl * ma + 1) - ma - 0.5 * cl * (ma * ma + bl)) / (this.es * Math.sin(2 * phi) * (ma * ma + bl - 2 * al * ma) / (4 * cl) + (al - ma) * (cl * mlnp - 2 / Math.sin(2 * phi)) - mlnp); 111 | phi -= dphi; 112 | if (Math.abs(dphi) <= EPSLN) { 113 | lat = phi; 114 | break; 115 | } 116 | } 117 | 118 | //lat=phi4z(this.e,this.e0,this.e1,this.e2,this.e3,al,bl,0,0); 119 | cl = Math.sqrt(1 - this.es * Math.pow(Math.sin(lat), 2)) * Math.tan(lat); 120 | lon = adjust_lon(this.long0 + Math.asin(x * cl / this.a) / Math.sin(lat)); 121 | } 122 | } 123 | 124 | p.x = lon; 125 | p.y = lat; 126 | return p; 127 | }; 128 | exports.names = ["Polyconic", "poly"]; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/tmerc.js: -------------------------------------------------------------------------------- 1 | var e0fn = require('../common/e0fn'); 2 | var e1fn = require('../common/e1fn'); 3 | var e2fn = require('../common/e2fn'); 4 | var e3fn = require('../common/e3fn'); 5 | var mlfn = require('../common/mlfn'); 6 | var adjust_lon = require('../common/adjust_lon'); 7 | var HALF_PI = Math.PI/2; 8 | var EPSLN = 1.0e-10; 9 | var sign = require('../common/sign'); 10 | var asinz = require('../common/asinz'); 11 | 12 | exports.init = function() { 13 | this.e0 = e0fn(this.es); 14 | this.e1 = e1fn(this.es); 15 | this.e2 = e2fn(this.es); 16 | this.e3 = e3fn(this.es); 17 | this.ml0 = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); 18 | }; 19 | 20 | /** 21 | Transverse Mercator Forward - long/lat to x/y 22 | long/lat in radians 23 | */ 24 | exports.forward = function(p) { 25 | var lon = p.x; 26 | var lat = p.y; 27 | 28 | var delta_lon = adjust_lon(lon - this.long0); 29 | var con; 30 | var x, y; 31 | var sin_phi = Math.sin(lat); 32 | var cos_phi = Math.cos(lat); 33 | 34 | if (this.sphere) { 35 | var b = cos_phi * Math.sin(delta_lon); 36 | if ((Math.abs(Math.abs(b) - 1)) < 0.0000000001) { 37 | return (93); 38 | } 39 | else { 40 | x = 0.5 * this.a * this.k0 * Math.log((1 + b) / (1 - b)); 41 | con = Math.acos(cos_phi * Math.cos(delta_lon) / Math.sqrt(1 - b * b)); 42 | if (lat < 0) { 43 | con = -con; 44 | } 45 | y = this.a * this.k0 * (con - this.lat0); 46 | } 47 | } 48 | else { 49 | var al = cos_phi * delta_lon; 50 | var als = Math.pow(al, 2); 51 | var c = this.ep2 * Math.pow(cos_phi, 2); 52 | var tq = Math.tan(lat); 53 | var t = Math.pow(tq, 2); 54 | con = 1 - this.es * Math.pow(sin_phi, 2); 55 | var n = this.a / Math.sqrt(con); 56 | var ml = this.a * mlfn(this.e0, this.e1, this.e2, this.e3, lat); 57 | 58 | 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; 59 | 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; 60 | 61 | } 62 | p.x = x; 63 | p.y = y; 64 | return p; 65 | }; 66 | 67 | /** 68 | Transverse Mercator Inverse - x/y to long/lat 69 | */ 70 | exports.inverse = function(p) { 71 | var con, phi; 72 | var delta_phi; 73 | var i; 74 | var max_iter = 6; 75 | var lat, lon; 76 | 77 | if (this.sphere) { 78 | var f = Math.exp(p.x / (this.a * this.k0)); 79 | var g = 0.5 * (f - 1 / f); 80 | var temp = this.lat0 + p.y / (this.a * this.k0); 81 | var h = Math.cos(temp); 82 | con = Math.sqrt((1 - h * h) / (1 + g * g)); 83 | lat = asinz(con); 84 | if (temp < 0) { 85 | lat = -lat; 86 | } 87 | if ((g === 0) && (h === 0)) { 88 | lon = this.long0; 89 | } 90 | else { 91 | lon = adjust_lon(Math.atan2(g, h) + this.long0); 92 | } 93 | } 94 | else { // ellipsoidal form 95 | var x = p.x - this.x0; 96 | var y = p.y - this.y0; 97 | 98 | con = (this.ml0 + y / this.k0) / this.a; 99 | phi = con; 100 | for (i = 0; true; i++) { 101 | delta_phi = ((con + this.e1 * Math.sin(2 * phi) - this.e2 * Math.sin(4 * phi) + this.e3 * Math.sin(6 * phi)) / this.e0) - phi; 102 | phi += delta_phi; 103 | if (Math.abs(delta_phi) <= EPSLN) { 104 | break; 105 | } 106 | if (i >= max_iter) { 107 | return (95); 108 | } 109 | } // for() 110 | if (Math.abs(phi) < HALF_PI) { 111 | var sin_phi = Math.sin(phi); 112 | var cos_phi = Math.cos(phi); 113 | var tan_phi = Math.tan(phi); 114 | var c = this.ep2 * Math.pow(cos_phi, 2); 115 | var cs = Math.pow(c, 2); 116 | var t = Math.pow(tan_phi, 2); 117 | var ts = Math.pow(t, 2); 118 | con = 1 - this.es * Math.pow(sin_phi, 2); 119 | var n = this.a / Math.sqrt(con); 120 | var r = n * (1 - this.es) / con; 121 | var d = x / (n * this.k0); 122 | var ds = Math.pow(d, 2); 123 | 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))); 124 | 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)); 125 | } 126 | else { 127 | lat = HALF_PI * sign(y); 128 | lon = this.long0; 129 | } 130 | } 131 | p.x = lon; 132 | p.y = lat; 133 | return p; 134 | }; 135 | exports.names = ["Transverse_Mercator", "Transverse Mercator", "tmerc"]; 136 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/constants/Ellipsoid.js: -------------------------------------------------------------------------------- 1 | exports.MERIT = { 2 | a: 6378137.0, 3 | rf: 298.257, 4 | ellipseName: "MERIT 1983" 5 | }; 6 | exports.SGS85 = { 7 | a: 6378136.0, 8 | rf: 298.257, 9 | ellipseName: "Soviet Geodetic System 85" 10 | }; 11 | exports.GRS80 = { 12 | a: 6378137.0, 13 | rf: 298.257222101, 14 | ellipseName: "GRS 1980(IUGG, 1980)" 15 | }; 16 | exports.IAU76 = { 17 | a: 6378140.0, 18 | rf: 298.257, 19 | ellipseName: "IAU 1976" 20 | }; 21 | exports.airy = { 22 | a: 6377563.396, 23 | b: 6356256.910, 24 | ellipseName: "Airy 1830" 25 | }; 26 | exports.APL4 = { 27 | a: 6378137, 28 | rf: 298.25, 29 | ellipseName: "Appl. Physics. 1965" 30 | }; 31 | exports.NWL9D = { 32 | a: 6378145.0, 33 | rf: 298.25, 34 | ellipseName: "Naval Weapons Lab., 1965" 35 | }; 36 | exports.mod_airy = { 37 | a: 6377340.189, 38 | b: 6356034.446, 39 | ellipseName: "Modified Airy" 40 | }; 41 | exports.andrae = { 42 | a: 6377104.43, 43 | rf: 300.0, 44 | ellipseName: "Andrae 1876 (Den., Iclnd.)" 45 | }; 46 | exports.aust_SA = { 47 | a: 6378160.0, 48 | rf: 298.25, 49 | ellipseName: "Australian Natl & S. Amer. 1969" 50 | }; 51 | exports.GRS67 = { 52 | a: 6378160.0, 53 | rf: 298.2471674270, 54 | ellipseName: "GRS 67(IUGG 1967)" 55 | }; 56 | exports.bessel = { 57 | a: 6377397.155, 58 | rf: 299.1528128, 59 | ellipseName: "Bessel 1841" 60 | }; 61 | exports.bess_nam = { 62 | a: 6377483.865, 63 | rf: 299.1528128, 64 | ellipseName: "Bessel 1841 (Namibia)" 65 | }; 66 | exports.clrk66 = { 67 | a: 6378206.4, 68 | b: 6356583.8, 69 | ellipseName: "Clarke 1866" 70 | }; 71 | exports.clrk80 = { 72 | a: 6378249.145, 73 | rf: 293.4663, 74 | ellipseName: "Clarke 1880 mod." 75 | }; 76 | exports.clrk58 = { 77 | a: 6378293.645208759, 78 | rf: 294.2606763692654, 79 | ellipseName: "Clarke 1858" 80 | }; 81 | exports.CPM = { 82 | a: 6375738.7, 83 | rf: 334.29, 84 | ellipseName: "Comm. des Poids et Mesures 1799" 85 | }; 86 | exports.delmbr = { 87 | a: 6376428.0, 88 | rf: 311.5, 89 | ellipseName: "Delambre 1810 (Belgium)" 90 | }; 91 | exports.engelis = { 92 | a: 6378136.05, 93 | rf: 298.2566, 94 | ellipseName: "Engelis 1985" 95 | }; 96 | exports.evrst30 = { 97 | a: 6377276.345, 98 | rf: 300.8017, 99 | ellipseName: "Everest 1830" 100 | }; 101 | exports.evrst48 = { 102 | a: 6377304.063, 103 | rf: 300.8017, 104 | ellipseName: "Everest 1948" 105 | }; 106 | exports.evrst56 = { 107 | a: 6377301.243, 108 | rf: 300.8017, 109 | ellipseName: "Everest 1956" 110 | }; 111 | exports.evrst69 = { 112 | a: 6377295.664, 113 | rf: 300.8017, 114 | ellipseName: "Everest 1969" 115 | }; 116 | exports.evrstSS = { 117 | a: 6377298.556, 118 | rf: 300.8017, 119 | ellipseName: "Everest (Sabah & Sarawak)" 120 | }; 121 | exports.fschr60 = { 122 | a: 6378166.0, 123 | rf: 298.3, 124 | ellipseName: "Fischer (Mercury Datum) 1960" 125 | }; 126 | exports.fschr60m = { 127 | a: 6378155.0, 128 | rf: 298.3, 129 | ellipseName: "Fischer 1960" 130 | }; 131 | exports.fschr68 = { 132 | a: 6378150.0, 133 | rf: 298.3, 134 | ellipseName: "Fischer 1968" 135 | }; 136 | exports.helmert = { 137 | a: 6378200.0, 138 | rf: 298.3, 139 | ellipseName: "Helmert 1906" 140 | }; 141 | exports.hough = { 142 | a: 6378270.0, 143 | rf: 297.0, 144 | ellipseName: "Hough" 145 | }; 146 | exports.intl = { 147 | a: 6378388.0, 148 | rf: 297.0, 149 | ellipseName: "International 1909 (Hayford)" 150 | }; 151 | exports.kaula = { 152 | a: 6378163.0, 153 | rf: 298.24, 154 | ellipseName: "Kaula 1961" 155 | }; 156 | exports.lerch = { 157 | a: 6378139.0, 158 | rf: 298.257, 159 | ellipseName: "Lerch 1979" 160 | }; 161 | exports.mprts = { 162 | a: 6397300.0, 163 | rf: 191.0, 164 | ellipseName: "Maupertius 1738" 165 | }; 166 | exports.new_intl = { 167 | a: 6378157.5, 168 | b: 6356772.2, 169 | ellipseName: "New International 1967" 170 | }; 171 | exports.plessis = { 172 | a: 6376523.0, 173 | rf: 6355863.0, 174 | ellipseName: "Plessis 1817 (France)" 175 | }; 176 | exports.krass = { 177 | a: 6378245.0, 178 | rf: 298.3, 179 | ellipseName: "Krassovsky, 1942" 180 | }; 181 | exports.SEasia = { 182 | a: 6378155.0, 183 | b: 6356773.3205, 184 | ellipseName: "Southeast Asia" 185 | }; 186 | exports.walbeck = { 187 | a: 6376896.0, 188 | b: 6355834.8467, 189 | ellipseName: "Walbeck" 190 | }; 191 | exports.WGS60 = { 192 | a: 6378165.0, 193 | rf: 298.3, 194 | ellipseName: "WGS 60" 195 | }; 196 | exports.WGS66 = { 197 | a: 6378145.0, 198 | rf: 298.25, 199 | ellipseName: "WGS 66" 200 | }; 201 | exports.WGS7 = { 202 | a: 6378135.0, 203 | rf: 298.26, 204 | ellipseName: "WGS 72" 205 | }; 206 | exports.WGS84 = { 207 | a: 6378137.0, 208 | rf: 298.257223563, 209 | ellipseName: "WGS 84" 210 | }; 211 | exports.sphere = { 212 | a: 6370997.0, 213 | b: 6370997.0, 214 | ellipseName: "Normal Sphere (r=6370997)" 215 | }; -------------------------------------------------------------------------------- /src/main/resources/proj4js/README.md: -------------------------------------------------------------------------------- 1 | # PROJ4JS [![Build Status](https://travis-ci.org/proj4js/proj4js.svg)](https://travis-ci.org/proj4js/proj4js) 2 | 3 | Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations. 4 | Originally a port of [PROJ.4](http://trac.osgeo.org/proj/) and [GCTCP C](http://edcftp.cr.usgs.gov/pub//software/gctpc) it is 5 | a part of the [MetaCRS](http://wiki.osgeo.org/wiki/MetaCRS) group of projects. 6 | 7 | ## Installing 8 | 9 | Depending on your preferences 10 | 11 | ```bash 12 | npm install proj4 13 | bower install proj4 14 | jam install proj4 15 | component install proj4js/proj4js 16 | ``` 17 | 18 | or just manually grab the file `proj4.js` from the [latest release](https://github.com/proj4js/proj4js/releases)'s `dist/` folder. 19 | 20 | if you do not want to download anything, Proj4js is also hosted on [cdnjs](http://www.cdnjs.com/libraries/proj4js) for direct use in your browser applications. 21 | 22 | ## Using 23 | 24 | the basic signature is: 25 | 26 | ```javascript 27 | proj4(fromProjection[, toProjection, coordinates]) 28 | ``` 29 | 30 | Projections can be proj or wkt strings. 31 | 32 | Coordinates may an object of the form `{x:x,y:y}` or an array of the form `[x,y]`. 33 | 34 | When all 3 arguments are given, the result is that the coordinates are transformed from projection1 to projection 2. And returned in the same format that they were given in. 35 | 36 | ```javascript 37 | var firstProjection = 'PROJCS["NAD83 / Massachusetts Mainland",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",42.68333333333333],PARAMETER["standard_parallel_2",41.71666666666667],PARAMETER["latitude_of_origin",41],PARAMETER["central_meridian",-71.5],PARAMETER["false_easting",200000],PARAMETER["false_northing",750000],AUTHORITY["EPSG","26986"],AXIS["X",EAST],AXIS["Y",NORTH]]'; 38 | var secondProjection = "+proj=gnom +lat_0=90 +lon_0=0 +x_0=6300000 +y_0=6300000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"; 39 | //I'm not going to redefine those two in latter examples. 40 | proj4(firstProjection,secondProjection,[2,5]); 41 | // [-2690666.2977344505, 3662659.885459918] 42 | ``` 43 | 44 | If only 1 projection is given then it is assumed that it is being projected *from* WGS84 (fromProjection is WGS84). 45 | 46 | ```javascript 47 | proj4(firstProjection,[-71,41]); 48 | // [242075.00535055372, 750123.32090043] 49 | ``` 50 | 51 | If no coordinates are given an object with two methods is returned, its methods are `forward` which projects from the first projection to the second and `inverse` which projects from the second to the first. 52 | 53 | ```javascript 54 | proj4(firstProjection,secondProjection).forward([2,5]); 55 | // [-2690666.2977344505, 3662659.885459918] 56 | proj4(secondProjection,firstProjection).inverse([2,5]); 57 | // [-2690666.2977344505, 3662659.885459918] 58 | ``` 59 | 60 | and as above if only one projection is given, it's assumed to be coming from wgs84 61 | 62 | ```javascript 63 | proj4(firstProjection).forward([-71,41]); 64 | // [242075.00535055372, 750123.32090043] 65 | proj4(firstProjection).inverse([242075.00535055372, 750123.32090043]); 66 | //[-71, 40.99999999999986] 67 | //the floating points to answer your question 68 | ``` 69 | 70 | ## Named Projections 71 | 72 | If you prefer to define a projection as a string and reference it that way, you may use the proj4.defs method which can be called 2 ways, with a name and projection: 73 | 74 | ```js 75 | proj4.defs('WGS84', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"); 76 | ``` 77 | 78 | or with an array 79 | 80 | ```js 81 | proj4.defs([ 82 | [ 83 | 'EPSG:4326', 84 | '+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees'], 85 | [ 86 | 'EPSG:4269', 87 | '+title=NAD83 (long/lat) +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees' 88 | ] 89 | ]); 90 | ``` 91 | 92 | you can then do 93 | 94 | ```js 95 | proj4('EPSG:4326'); 96 | ``` 97 | 98 | instead of writing out the whole proj definition, by default proj4 has the following projections predefined: 99 | 100 | - 'EPSG:4326', which has the following alias 101 | - 'WGS84' 102 | - 'EPSG:4269' 103 | - 'EPSG:3857', which has the following aliases 104 | - 'EPSG:3785' 105 | - 'GOOGLE' 106 | - 'EPSG:900913' 107 | - 'EPSG:102113' 108 | 109 | defined projections can also be accessed through the proj4.defs function (`proj4.defs('EPSG:4326')`). 110 | 111 | proj4.defs can also be used to define a named alias: 112 | 113 | ```javascript 114 | proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326')); 115 | ``` 116 | 117 | ## Developing 118 | to set up build tools make sure you have node and grunt-cli installed and then run `npm install` 119 | 120 | to do the complete build and browser tests run 121 | 122 | ```bash 123 | node_modules/.bin/grunt 124 | ``` 125 | 126 | to run node tests run 127 | 128 | ```bash 129 | npm test 130 | ``` 131 | 132 | to run node tests with coverage run 133 | 134 | ```bash 135 | npm test --coverage 136 | ``` 137 | 138 | to create a build with only default projections (latlon and Mercator) run 139 | 140 | ```bash 141 | node_modules/.bin/grunt build 142 | ``` 143 | 144 | to create a build with only custom projections include a comma separated list of projections codes (the file name in 'lib/projections' without the '.js') after a colon, e.g. 145 | 146 | ```bash 147 | node_modules/.bin/grunt build:tmerc 148 | #includes transverse Mercator 149 | node_modules/.bin/grunt build:lcc 150 | #includes lambert conformal conic 151 | node_modules/.bin/grunt build:omerc,moll 152 | #includes oblique Mercator and Mollweide 153 | ``` 154 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/omerc.js: -------------------------------------------------------------------------------- 1 | var tsfnz = require('../common/tsfnz'); 2 | var adjust_lon = require('../common/adjust_lon'); 3 | var phi2z = require('../common/phi2z'); 4 | var HALF_PI = Math.PI/2; 5 | var FORTPI = Math.PI/4; 6 | var EPSLN = 1.0e-10; 7 | 8 | /* Initialize the Oblique Mercator projection 9 | ------------------------------------------*/ 10 | exports.init = function() { 11 | this.no_off = this.no_off || false; 12 | this.no_rot = this.no_rot || false; 13 | 14 | if (isNaN(this.k0)) { 15 | this.k0 = 1; 16 | } 17 | var sinlat = Math.sin(this.lat0); 18 | var coslat = Math.cos(this.lat0); 19 | var con = this.e * sinlat; 20 | 21 | this.bl = Math.sqrt(1 + this.es / (1 - this.es) * Math.pow(coslat, 4)); 22 | this.al = this.a * this.bl * this.k0 * Math.sqrt(1 - this.es) / (1 - con * con); 23 | var t0 = tsfnz(this.e, this.lat0, sinlat); 24 | var dl = this.bl / coslat * Math.sqrt((1 - this.es) / (1 - con * con)); 25 | if (dl * dl < 1) { 26 | dl = 1; 27 | } 28 | var fl; 29 | var gl; 30 | if (!isNaN(this.longc)) { 31 | //Central point and azimuth method 32 | 33 | if (this.lat0 >= 0) { 34 | fl = dl + Math.sqrt(dl * dl - 1); 35 | } 36 | else { 37 | fl = dl - Math.sqrt(dl * dl - 1); 38 | } 39 | this.el = fl * Math.pow(t0, this.bl); 40 | gl = 0.5 * (fl - 1 / fl); 41 | this.gamma0 = Math.asin(Math.sin(this.alpha) / dl); 42 | this.long0 = this.longc - Math.asin(gl * Math.tan(this.gamma0)) / this.bl; 43 | 44 | } 45 | else { 46 | //2 points method 47 | var t1 = tsfnz(this.e, this.lat1, Math.sin(this.lat1)); 48 | var t2 = tsfnz(this.e, this.lat2, Math.sin(this.lat2)); 49 | if (this.lat0 >= 0) { 50 | this.el = (dl + Math.sqrt(dl * dl - 1)) * Math.pow(t0, this.bl); 51 | } 52 | else { 53 | this.el = (dl - Math.sqrt(dl * dl - 1)) * Math.pow(t0, this.bl); 54 | } 55 | var hl = Math.pow(t1, this.bl); 56 | var ll = Math.pow(t2, this.bl); 57 | fl = this.el / hl; 58 | gl = 0.5 * (fl - 1 / fl); 59 | var jl = (this.el * this.el - ll * hl) / (this.el * this.el + ll * hl); 60 | var pl = (ll - hl) / (ll + hl); 61 | var dlon12 = adjust_lon(this.long1 - this.long2); 62 | this.long0 = 0.5 * (this.long1 + this.long2) - Math.atan(jl * Math.tan(0.5 * this.bl * (dlon12)) / pl) / this.bl; 63 | this.long0 = adjust_lon(this.long0); 64 | var dlon10 = adjust_lon(this.long1 - this.long0); 65 | this.gamma0 = Math.atan(Math.sin(this.bl * (dlon10)) / gl); 66 | this.alpha = Math.asin(dl * Math.sin(this.gamma0)); 67 | } 68 | 69 | if (this.no_off) { 70 | this.uc = 0; 71 | } 72 | else { 73 | if (this.lat0 >= 0) { 74 | this.uc = this.al / this.bl * Math.atan2(Math.sqrt(dl * dl - 1), Math.cos(this.alpha)); 75 | } 76 | else { 77 | this.uc = -1 * this.al / this.bl * Math.atan2(Math.sqrt(dl * dl - 1), Math.cos(this.alpha)); 78 | } 79 | } 80 | 81 | }; 82 | 83 | 84 | /* Oblique Mercator forward equations--mapping lat,long to x,y 85 | ----------------------------------------------------------*/ 86 | exports.forward = function(p) { 87 | var lon = p.x; 88 | var lat = p.y; 89 | var dlon = adjust_lon(lon - this.long0); 90 | var us, vs; 91 | var con; 92 | if (Math.abs(Math.abs(lat) - HALF_PI) <= EPSLN) { 93 | if (lat > 0) { 94 | con = -1; 95 | } 96 | else { 97 | con = 1; 98 | } 99 | vs = this.al / this.bl * Math.log(Math.tan(FORTPI + con * this.gamma0 * 0.5)); 100 | us = -1 * con * HALF_PI * this.al / this.bl; 101 | } 102 | else { 103 | var t = tsfnz(this.e, lat, Math.sin(lat)); 104 | var ql = this.el / Math.pow(t, this.bl); 105 | var sl = 0.5 * (ql - 1 / ql); 106 | var tl = 0.5 * (ql + 1 / ql); 107 | var vl = Math.sin(this.bl * (dlon)); 108 | var ul = (sl * Math.sin(this.gamma0) - vl * Math.cos(this.gamma0)) / tl; 109 | if (Math.abs(Math.abs(ul) - 1) <= EPSLN) { 110 | vs = Number.POSITIVE_INFINITY; 111 | } 112 | else { 113 | vs = 0.5 * this.al * Math.log((1 - ul) / (1 + ul)) / this.bl; 114 | } 115 | if (Math.abs(Math.cos(this.bl * (dlon))) <= EPSLN) { 116 | us = this.al * this.bl * (dlon); 117 | } 118 | else { 119 | us = this.al * Math.atan2(sl * Math.cos(this.gamma0) + vl * Math.sin(this.gamma0), Math.cos(this.bl * dlon)) / this.bl; 120 | } 121 | } 122 | 123 | if (this.no_rot) { 124 | p.x = this.x0 + us; 125 | p.y = this.y0 + vs; 126 | } 127 | else { 128 | 129 | us -= this.uc; 130 | p.x = this.x0 + vs * Math.cos(this.alpha) + us * Math.sin(this.alpha); 131 | p.y = this.y0 + us * Math.cos(this.alpha) - vs * Math.sin(this.alpha); 132 | } 133 | return p; 134 | }; 135 | 136 | exports.inverse = function(p) { 137 | var us, vs; 138 | if (this.no_rot) { 139 | vs = p.y - this.y0; 140 | us = p.x - this.x0; 141 | } 142 | else { 143 | vs = (p.x - this.x0) * Math.cos(this.alpha) - (p.y - this.y0) * Math.sin(this.alpha); 144 | us = (p.y - this.y0) * Math.cos(this.alpha) + (p.x - this.x0) * Math.sin(this.alpha); 145 | us += this.uc; 146 | } 147 | var qp = Math.exp(-1 * this.bl * vs / this.al); 148 | var sp = 0.5 * (qp - 1 / qp); 149 | var tp = 0.5 * (qp + 1 / qp); 150 | var vp = Math.sin(this.bl * us / this.al); 151 | var up = (vp * Math.cos(this.gamma0) + sp * Math.sin(this.gamma0)) / tp; 152 | var ts = Math.pow(this.el / Math.sqrt((1 + up) / (1 - up)), 1 / this.bl); 153 | if (Math.abs(up - 1) < EPSLN) { 154 | p.x = this.long0; 155 | p.y = HALF_PI; 156 | } 157 | else if (Math.abs(up + 1) < EPSLN) { 158 | p.x = this.long0; 159 | p.y = -1 * HALF_PI; 160 | } 161 | else { 162 | p.y = phi2z(this.e, ts); 163 | p.x = adjust_lon(this.long0 - Math.atan2(sp * Math.cos(this.gamma0) - vp * Math.sin(this.gamma0), Math.cos(this.bl * us / this.al)) / this.bl); 164 | } 165 | return p; 166 | }; 167 | 168 | exports.names = ["Hotine_Oblique_Mercator", "Hotine Oblique Mercator", "Hotine_Oblique_Mercator_Azimuth_Natural_Origin", "Hotine_Oblique_Mercator_Azimuth_Center", "omerc"]; -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.maptalks 6 | proj4m 7 | 2.0.0-SNAPSHOT 8 | 9 | proj4m 10 | An Proj4 extension with supports for Chinese projections. 11 | https://github.com/MapTalks/proj4m 12 | 13 | 14 | The MIT License (MIT) 15 | http://opensource.org/licenses/MIT 16 | repo 17 | 18 | 19 | 20 | https://github.com/MapTalks/proj4m/issues 21 | 22 | 23 | 24 | wsw0108 25 | Wang Shi Wei 26 | 27 | 28 | 29 | 30 | UTF-8 31 | 1.5 32 | 33 | 34 | 35 | scm:git:https://github.com/MapTalks/proj4m 36 | scm:git:git@github.com:MapTalks/proj4m.git 37 | https://github.com/MapTalks/proj4m 38 | HEAD 39 | 40 | 41 | 42 | 43 | org.mozilla 44 | rhino 45 | 1.7R5 46 | 47 | 48 | junit 49 | junit 50 | 4.11 51 | test 52 | 53 | 54 | 55 | 56 | 57 | ossrh 58 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 59 | 60 | 61 | ossrh 62 | https://oss.sonatype.org/content/repositories/snapshots 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.sonatype.plugins 70 | nexus-staging-maven-plugin 71 | 1.6.7 72 | true 73 | 74 | ossrh 75 | https://oss.sonatype.org/ 76 | true 77 | 78 | 79 | 80 | maven-compiler-plugin 81 | 2.5.1 82 | 83 | ${jdk.version} 84 | ${jdk.version} 85 | 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-surefire-plugin 90 | 2.18.1 91 | 92 | false 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | release 101 | 102 | 103 | 104 | org.apache.maven.plugins 105 | maven-source-plugin 106 | 2.2.1 107 | 108 | 109 | attach-sources 110 | 111 | jar-no-fork 112 | 113 | 114 | 115 | 116 | 117 | org.apache.maven.plugins 118 | maven-javadoc-plugin 119 | 2.10.3 120 | 121 | 122 | attach-javadocs 123 | 124 | jar 125 | 126 | 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-gpg-plugin 132 | 1.5 133 | 134 | 135 | sign-artifacts 136 | verify 137 | 138 | sign 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/stere.js: -------------------------------------------------------------------------------- 1 | var HALF_PI = Math.PI/2; 2 | var EPSLN = 1.0e-10; 3 | var sign = require('../common/sign'); 4 | var msfnz = require('../common/msfnz'); 5 | var tsfnz = require('../common/tsfnz'); 6 | var phi2z = require('../common/phi2z'); 7 | var adjust_lon = require('../common/adjust_lon'); 8 | exports.ssfn_ = function(phit, sinphi, eccen) { 9 | sinphi *= eccen; 10 | return (Math.tan(0.5 * (HALF_PI + phit)) * Math.pow((1 - sinphi) / (1 + sinphi), 0.5 * eccen)); 11 | }; 12 | 13 | exports.init = function() { 14 | this.coslat0 = Math.cos(this.lat0); 15 | this.sinlat0 = Math.sin(this.lat0); 16 | if (this.sphere) { 17 | if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= EPSLN) { 18 | this.k0 = 0.5 * (1 + sign(this.lat0) * Math.sin(this.lat_ts)); 19 | } 20 | } 21 | else { 22 | if (Math.abs(this.coslat0) <= EPSLN) { 23 | if (this.lat0 > 0) { 24 | //North pole 25 | //trace('stere:north pole'); 26 | this.con = 1; 27 | } 28 | else { 29 | //South pole 30 | //trace('stere:south pole'); 31 | this.con = -1; 32 | } 33 | } 34 | this.cons = Math.sqrt(Math.pow(1 + this.e, 1 + this.e) * Math.pow(1 - this.e, 1 - this.e)); 35 | if (this.k0 === 1 && !isNaN(this.lat_ts) && Math.abs(this.coslat0) <= EPSLN) { 36 | this.k0 = 0.5 * this.cons * msfnz(this.e, Math.sin(this.lat_ts), Math.cos(this.lat_ts)) / tsfnz(this.e, this.con * this.lat_ts, this.con * Math.sin(this.lat_ts)); 37 | } 38 | this.ms1 = msfnz(this.e, this.sinlat0, this.coslat0); 39 | this.X0 = 2 * Math.atan(this.ssfn_(this.lat0, this.sinlat0, this.e)) - HALF_PI; 40 | this.cosX0 = Math.cos(this.X0); 41 | this.sinX0 = Math.sin(this.X0); 42 | } 43 | }; 44 | 45 | // Stereographic forward equations--mapping lat,long to x,y 46 | exports.forward = function(p) { 47 | var lon = p.x; 48 | var lat = p.y; 49 | var sinlat = Math.sin(lat); 50 | var coslat = Math.cos(lat); 51 | var A, X, sinX, cosX, ts, rh; 52 | var dlon = adjust_lon(lon - this.long0); 53 | 54 | if (Math.abs(Math.abs(lon - this.long0) - Math.PI) <= EPSLN && Math.abs(lat + this.lat0) <= EPSLN) { 55 | //case of the origine point 56 | //trace('stere:this is the origin point'); 57 | p.x = NaN; 58 | p.y = NaN; 59 | return p; 60 | } 61 | if (this.sphere) { 62 | //trace('stere:sphere case'); 63 | A = 2 * this.k0 / (1 + this.sinlat0 * sinlat + this.coslat0 * coslat * Math.cos(dlon)); 64 | p.x = this.a * A * coslat * Math.sin(dlon) + this.x0; 65 | p.y = this.a * A * (this.coslat0 * sinlat - this.sinlat0 * coslat * Math.cos(dlon)) + this.y0; 66 | return p; 67 | } 68 | else { 69 | X = 2 * Math.atan(this.ssfn_(lat, sinlat, this.e)) - HALF_PI; 70 | cosX = Math.cos(X); 71 | sinX = Math.sin(X); 72 | if (Math.abs(this.coslat0) <= EPSLN) { 73 | ts = tsfnz(this.e, lat * this.con, this.con * sinlat); 74 | rh = 2 * this.a * this.k0 * ts / this.cons; 75 | p.x = this.x0 + rh * Math.sin(lon - this.long0); 76 | p.y = this.y0 - this.con * rh * Math.cos(lon - this.long0); 77 | //trace(p.toString()); 78 | return p; 79 | } 80 | else if (Math.abs(this.sinlat0) < EPSLN) { 81 | //Eq 82 | //trace('stere:equateur'); 83 | A = 2 * this.a * this.k0 / (1 + cosX * Math.cos(dlon)); 84 | p.y = A * sinX; 85 | } 86 | else { 87 | //other case 88 | //trace('stere:normal case'); 89 | A = 2 * this.a * this.k0 * this.ms1 / (this.cosX0 * (1 + this.sinX0 * sinX + this.cosX0 * cosX * Math.cos(dlon))); 90 | p.y = A * (this.cosX0 * sinX - this.sinX0 * cosX * Math.cos(dlon)) + this.y0; 91 | } 92 | p.x = A * cosX * Math.sin(dlon) + this.x0; 93 | } 94 | //trace(p.toString()); 95 | return p; 96 | }; 97 | 98 | 99 | //* Stereographic inverse equations--mapping x,y to lat/long 100 | exports.inverse = function(p) { 101 | p.x -= this.x0; 102 | p.y -= this.y0; 103 | var lon, lat, ts, ce, Chi; 104 | var rh = Math.sqrt(p.x * p.x + p.y * p.y); 105 | if (this.sphere) { 106 | var c = 2 * Math.atan(rh / (0.5 * this.a * this.k0)); 107 | lon = this.long0; 108 | lat = this.lat0; 109 | if (rh <= EPSLN) { 110 | p.x = lon; 111 | p.y = lat; 112 | return p; 113 | } 114 | lat = Math.asin(Math.cos(c) * this.sinlat0 + p.y * Math.sin(c) * this.coslat0 / rh); 115 | if (Math.abs(this.coslat0) < EPSLN) { 116 | if (this.lat0 > 0) { 117 | lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y)); 118 | } 119 | else { 120 | lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y)); 121 | } 122 | } 123 | else { 124 | lon = adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(c), rh * this.coslat0 * Math.cos(c) - p.y * this.sinlat0 * Math.sin(c))); 125 | } 126 | p.x = lon; 127 | p.y = lat; 128 | return p; 129 | } 130 | else { 131 | if (Math.abs(this.coslat0) <= EPSLN) { 132 | if (rh <= EPSLN) { 133 | lat = this.lat0; 134 | lon = this.long0; 135 | p.x = lon; 136 | p.y = lat; 137 | //trace(p.toString()); 138 | return p; 139 | } 140 | p.x *= this.con; 141 | p.y *= this.con; 142 | ts = rh * this.cons / (2 * this.a * this.k0); 143 | lat = this.con * phi2z(this.e, ts); 144 | lon = this.con * adjust_lon(this.con * this.long0 + Math.atan2(p.x, - 1 * p.y)); 145 | } 146 | else { 147 | ce = 2 * Math.atan(rh * this.cosX0 / (2 * this.a * this.k0 * this.ms1)); 148 | lon = this.long0; 149 | if (rh <= EPSLN) { 150 | Chi = this.X0; 151 | } 152 | else { 153 | Chi = Math.asin(Math.cos(ce) * this.sinX0 + p.y * Math.sin(ce) * this.cosX0 / rh); 154 | lon = adjust_lon(this.long0 + Math.atan2(p.x * Math.sin(ce), rh * this.cosX0 * Math.cos(ce) - p.y * this.sinX0 * Math.sin(ce))); 155 | } 156 | lat = -1 * phi2z(this.e, Math.tan(0.5 * (HALF_PI + Chi))); 157 | } 158 | } 159 | p.x = lon; 160 | p.y = lat; 161 | 162 | //trace(p.toString()); 163 | return p; 164 | 165 | }; 166 | exports.names = ["stere", "Stereographic_South_Pole", "Polar Stereographic (variant B)"]; 167 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/Proj4.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import org.maptalks.proj4.rhino.JsonModuleScriptProvider; 9 | import org.mozilla.javascript.Context; 10 | import org.mozilla.javascript.Function; 11 | import org.mozilla.javascript.Scriptable; 12 | import org.mozilla.javascript.ScriptableObject; 13 | import org.mozilla.javascript.commonjs.module.ModuleScriptProvider; 14 | import org.mozilla.javascript.commonjs.module.Require; 15 | import org.mozilla.javascript.commonjs.module.RequireBuilder; 16 | import org.mozilla.javascript.commonjs.module.provider.MultiModuleScriptProvider; 17 | import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider; 18 | import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider; 19 | 20 | public class Proj4 implements Closeable { 21 | 22 | private static Context cx; 23 | private static ScriptableObject scope; 24 | private static Function proj4; 25 | private final PointAdaptor pointAdaptor; 26 | private final Proj srcProj; 27 | private final Proj dstProj; 28 | private String srcSRS; 29 | private String dstSRS; 30 | 31 | public Proj4(String srcSRS, String dstSRS) throws Proj4Exception { 32 | this.srcSRS = srcSRS; 33 | this.dstSRS = dstSRS; 34 | this.srcProj = Parser.parseCode(srcSRS); 35 | this.dstProj = Parser.parseCode(dstSRS); 36 | this.pointAdaptor = new PointAdaptor() { 37 | public double getX(T point) { 38 | return ((Point) point).getX(); 39 | } 40 | 41 | public double getY(T point) { 42 | return ((Point) point).getY(); 43 | } 44 | 45 | public void setX(T point, double x) { 46 | ((Point) point).setX(x); 47 | } 48 | 49 | public void setY(T point, double y) { 50 | ((Point) point).setY(y); 51 | } 52 | }; 53 | } 54 | 55 | public Proj4(String srcSRS, String dstSRS, PointAdaptor pointAdaptor) throws Proj4Exception { 56 | this.srcSRS = srcSRS; 57 | this.dstSRS = dstSRS; 58 | this.srcProj = Parser.parseCode(srcSRS); 59 | this.dstProj = Parser.parseCode(dstSRS); 60 | this.pointAdaptor = pointAdaptor; 61 | } 62 | 63 | public Proj4(Proj srcSRS, Proj dstSRS) throws Proj4Exception { 64 | this.srcProj = srcSRS; 65 | this.dstProj = dstSRS; 66 | this.pointAdaptor = new PointAdaptor() { 67 | public double getX(T point) { 68 | return ((Point) point).getX(); 69 | } 70 | 71 | public double getY(T point) { 72 | return ((Point) point).getY(); 73 | } 74 | 75 | public void setX(T point, double x) { 76 | ((Point) point).setX(x); 77 | } 78 | 79 | public void setY(T point, double y) { 80 | ((Point) point).setY(y); 81 | } 82 | }; 83 | } 84 | 85 | public Proj4(Proj srcSRS, Proj dstSRS, PointAdaptor pointExtractor) throws Proj4Exception { 86 | this.srcProj = srcSRS; 87 | this.dstProj = dstSRS; 88 | this.pointAdaptor = pointExtractor; 89 | } 90 | 91 | private static void loadProj4() { 92 | if (proj4 != null) { 93 | return; 94 | } 95 | 96 | cx = Context.enter(); 97 | scope = cx.initStandardObjects(); 98 | 99 | RequireBuilder rb = new RequireBuilder(); 100 | ModuleScriptProvider jsonModuleScriptProvider = new JsonModuleScriptProvider(); 101 | ModuleScriptProvider genericModuleScriptProvider = new SoftCachingModuleScriptProvider( 102 | new UrlModuleSourceProvider(null, null) 103 | ); 104 | List providers = new ArrayList(); 105 | providers.add(jsonModuleScriptProvider); 106 | providers.add(genericModuleScriptProvider); 107 | rb.setModuleScriptProvider(new MultiModuleScriptProvider(providers)); 108 | rb.setSandboxed(false); 109 | Require require = rb.createRequire(cx, scope); 110 | require.install(scope); 111 | 112 | URL base = Proj4.class.getResource("/proj4js"); 113 | Scriptable script = require.requireMain(cx, base + "/lib/index"); 114 | 115 | proj4 = (Function) script; 116 | } 117 | 118 | private static boolean isMarsDatum(String datum) { 119 | return "BD09".equalsIgnoreCase(datum) || "GCJ02".equalsIgnoreCase(datum); 120 | } 121 | 122 | private static boolean needProj4js(Proj srcProj, Proj dstProj) { 123 | return (!isMarsDatum(srcProj.getDatumCode()) && !isMarsDatum(dstProj.getDatumCode())); 124 | } 125 | 126 | public T forward(T point) throws IllegalArgumentException, Proj4Exception { 127 | if (srcProj.equals(dstProj)) { 128 | return point; 129 | } 130 | if (needProj4js(srcProj, dstProj)) { 131 | loadProj4(); 132 | return forwardUsingProj4js(point); 133 | } 134 | point = Transform.transform(srcProj, dstProj, point, pointAdaptor); 135 | return point; 136 | } 137 | 138 | public T inverse(T point) throws IllegalArgumentException, Proj4Exception { 139 | if (srcProj.equals(dstProj)) { 140 | return point; 141 | } 142 | if (needProj4js(srcProj, dstProj)) { 143 | loadProj4(); 144 | return inverseUsingProj4js(point); 145 | } 146 | point = Transform.transform(dstProj, srcProj, point, pointAdaptor); 147 | return point; 148 | } 149 | 150 | public void close() throws IOException { 151 | if (proj4 != null) { 152 | Context.exit(); 153 | } 154 | } 155 | 156 | private T proj4js(String srcSRS, String dstSRS, T point) { 157 | SimplePoint input = new SimplePoint(pointAdaptor.getX(point), pointAdaptor.getY(point)); 158 | Object result = proj4.call(cx, scope, scope, new Object[] { 159 | Context.javaToJS(srcSRS, scope), 160 | Context.javaToJS(dstSRS, scope), 161 | Context.javaToJS(input, scope) 162 | }); 163 | SimplePoint output = (SimplePoint) Context.jsToJava(result, SimplePoint.class); 164 | pointAdaptor.setX(point, output.getX()); 165 | pointAdaptor.setY(point, output.getY()); 166 | return point; 167 | } 168 | 169 | private T forwardUsingProj4js(T point) { 170 | return proj4js(srcSRS, dstSRS, point); 171 | } 172 | 173 | private T inverseUsingProj4js(T point) { 174 | return proj4js(dstSRS, srcSRS, point); 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/org/maptalks/proj4/projection/BaiduMercator.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4.projection; 2 | 3 | import org.maptalks.proj4.PointAdaptor; 4 | 5 | public class BaiduMercator implements Projection { 6 | 7 | private static double[] MCBAND = new double[] {12890594.86, 8362377.87, 8 | 5591021, 3481989.83, 1678043.12, 0}; 9 | private static int[] LLBAND = new int[] {75, 60, 45, 30, 15, 0}; 10 | private static double[][] MC2LL = new double[][] { 11 | {1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 12 | 200.9824383106796, -187.2403703815547, 91.6087516669843, 13 | -23.38765649603339, 2.57121317296198, -0.03801003308653, 14 | 17337981.2}, 15 | {-7.435856389565537e-9, 0.000008983055097726239, 16 | -0.78625201886289, 96.32687599759846, -1.85204757529826, 17 | -59.36935905485877, 47.40033549296737, -16.50741931063887, 18 | 2.28786674699375, 10260144.86}, 19 | {-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 20 | 59.74293618442277, 7.357984074871, -25.38371002664745, 21 | 13.45380521110908, -3.29883767235584, 0.32710905363475, 22 | 6856817.37}, 23 | {-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 24 | 40.31678527705744, 0.65659298677277, -4.44255534477492, 25 | 0.85341911805263, 0.12923347998204, -0.04625736007561, 26 | 4482777.06}, 27 | {3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 28 | 23.10934304144901, -0.00023663490511, -0.6321817810242, 29 | -0.00663494467273, 0.03430082397953, -0.00466043876332, 30 | 2555164.4}, 31 | {2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 32 | 7.47137025468032, -0.00000353937994, -0.02145144861037, 33 | -0.00001234426596, 0.00010322952773, -0.00000323890364, 34 | 826088.5}}; 35 | private static double[][] LL2MC = new double[][] { 36 | {-0.0015702102444, 111320.7020616939, 1704480524535203d, 37 | -10338987376042340d, 26112667856603880d, 38 | -35149669176653700d, 26595700718403920d, 39 | -10725012454188240d, 1800819912950474d, 82.5}, 40 | {0.0008277824516172526, 111320.7020463578, 647795574.6671607, 41 | -4082003173.641316, 10774905663.51142, -15171875531.51559, 42 | 12053065338.62167, -5124939663.577472, 913311935.9512032, 43 | 67.5}, 44 | {0.00337398766765, 111320.7020202162, 4481351.045890365, 45 | -23393751.19931662, 79682215.47186455, -115964993.2797253, 46 | 97236711.15602145, -43661946.33752821, 8477230.501135234, 47 | 52.5}, 48 | {0.00220636496208, 111320.7020209128, 51751.86112841131, 49 | 3796837.749470245, 992013.7397791013, -1221952.21711287, 50 | 1340652.697009075, -620943.6990984312, 144416.9293806241, 51 | 37.5}, 52 | {-0.0003441963504368392, 111320.7020576856, 278.2353980772752, 53 | 2485758.690035394, 6070.750963243378, 54821.18345352118, 54 | 9540.606633304236, -2710.55326746645, 1405.483844121726, 55 | 22.5}, 56 | {-0.0003218135878613132, 111320.7020701615, 0.00369383431289, 57 | 823725.6402795718, 0.46104986909093, 2351.343141331292, 58 | 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45}}; 59 | 60 | public T forward(T point, PointAdaptor pointAdaptor) { 61 | return this.convertLL2MC(point, pointAdaptor); 62 | } 63 | 64 | public T inverse(T point, PointAdaptor pointAdaptor) { 65 | return this.convertMC2LL(point, pointAdaptor); 66 | } 67 | 68 | public ProjectionType getType() { 69 | return ProjectionType.PROJECTED; 70 | } 71 | 72 | private T convertMC2LL(T point, PointAdaptor pointAdaptor) { 73 | double y_abs = Math.abs(pointAdaptor.getY(point)); 74 | 75 | double[] table = null; 76 | for (int i = 0; i < MCBAND.length; i++) { 77 | if (y_abs >= MCBAND[i]) { 78 | table = MC2LL[i]; 79 | break; 80 | } 81 | } 82 | 83 | return this.convertor(point, table, pointAdaptor); 84 | } 85 | 86 | private T convertLL2MC(T point, PointAdaptor pointAdaptor) { 87 | double lng = pointAdaptor.getX(point); 88 | double lat = pointAdaptor.getY(point); 89 | lng = this.getLoop(lng, -180, 180); 90 | lat = this.getRange(lat, -74, 74); 91 | pointAdaptor.setX(point, lng); 92 | pointAdaptor.setY(point, lat); 93 | 94 | double[] table = null; 95 | for (int i = 0; i < LLBAND.length; i++) { 96 | if (lat >= LLBAND[i]) { 97 | table = LL2MC[i]; 98 | break; 99 | } 100 | } 101 | if (table == null) { 102 | for (int i = LLBAND.length - 1; i >= 0; i--) { 103 | if (lat <= -LLBAND[i]) { 104 | table = LL2MC[i]; 105 | break; 106 | } 107 | } 108 | } 109 | 110 | return this.convertor(point, table, pointAdaptor); 111 | } 112 | 113 | private T convertor(T point, double[] table, PointAdaptor pointAdaptor) { 114 | double px = pointAdaptor.getX(point); 115 | double py = pointAdaptor.getY(point); 116 | double x = table[0] + table[1] * Math.abs(px); 117 | double d = Math.abs(py) / table[9]; 118 | double y = table[2] 119 | + table[3] 120 | * d 121 | + table[4] 122 | * d 123 | * d 124 | + table[5] 125 | * d 126 | * d 127 | * d 128 | + table[6] 129 | * d 130 | * d 131 | * d 132 | * d 133 | + table[7] 134 | * d 135 | * d 136 | * d 137 | * d 138 | * d 139 | + table[8] 140 | * d 141 | * d 142 | * d 143 | * d 144 | * d 145 | * d; 146 | 147 | x *= (px < 0 ? -1 : 1); 148 | y *= (py < 0 ? -1 : 1); 149 | 150 | pointAdaptor.setX(point, x); 151 | pointAdaptor.setY(point, y); 152 | 153 | return point; 154 | } 155 | 156 | private double getRange(double v, double min, double max) { 157 | v = Math.max(v, min); 158 | v = Math.min(v, max); 159 | 160 | return v; 161 | } 162 | 163 | private double getLoop(double v, double min, double max) { 164 | double d = max - min; 165 | while (v > max) { 166 | v -= d; 167 | } 168 | while (v < min) { 169 | v += d; 170 | } 171 | 172 | return v; 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/nzmg.js: -------------------------------------------------------------------------------- 1 | var SEC_TO_RAD = 4.84813681109535993589914102357e-6; 2 | /* 3 | reference 4 | Department of Land and Survey Technical Circular 1973/32 5 | http://www.linz.govt.nz/docs/miscellaneous/nz-map-definition.pdf 6 | OSG Technical Report 4.1 7 | http://www.linz.govt.nz/docs/miscellaneous/nzmg.pdf 8 | */ 9 | 10 | /** 11 | * iterations: Number of iterations to refine inverse transform. 12 | * 0 -> km accuracy 13 | * 1 -> m accuracy -- suitable for most mapping applications 14 | * 2 -> mm accuracy 15 | */ 16 | exports.iterations = 1; 17 | 18 | exports.init = function() { 19 | this.A = []; 20 | this.A[1] = 0.6399175073; 21 | this.A[2] = -0.1358797613; 22 | this.A[3] = 0.063294409; 23 | this.A[4] = -0.02526853; 24 | this.A[5] = 0.0117879; 25 | this.A[6] = -0.0055161; 26 | this.A[7] = 0.0026906; 27 | this.A[8] = -0.001333; 28 | this.A[9] = 0.00067; 29 | this.A[10] = -0.00034; 30 | 31 | this.B_re = []; 32 | this.B_im = []; 33 | this.B_re[1] = 0.7557853228; 34 | this.B_im[1] = 0; 35 | this.B_re[2] = 0.249204646; 36 | this.B_im[2] = 0.003371507; 37 | this.B_re[3] = -0.001541739; 38 | this.B_im[3] = 0.041058560; 39 | this.B_re[4] = -0.10162907; 40 | this.B_im[4] = 0.01727609; 41 | this.B_re[5] = -0.26623489; 42 | this.B_im[5] = -0.36249218; 43 | this.B_re[6] = -0.6870983; 44 | this.B_im[6] = -1.1651967; 45 | 46 | this.C_re = []; 47 | this.C_im = []; 48 | this.C_re[1] = 1.3231270439; 49 | this.C_im[1] = 0; 50 | this.C_re[2] = -0.577245789; 51 | this.C_im[2] = -0.007809598; 52 | this.C_re[3] = 0.508307513; 53 | this.C_im[3] = -0.112208952; 54 | this.C_re[4] = -0.15094762; 55 | this.C_im[4] = 0.18200602; 56 | this.C_re[5] = 1.01418179; 57 | this.C_im[5] = 1.64497696; 58 | this.C_re[6] = 1.9660549; 59 | this.C_im[6] = 2.5127645; 60 | 61 | this.D = []; 62 | this.D[1] = 1.5627014243; 63 | this.D[2] = 0.5185406398; 64 | this.D[3] = -0.03333098; 65 | this.D[4] = -0.1052906; 66 | this.D[5] = -0.0368594; 67 | this.D[6] = 0.007317; 68 | this.D[7] = 0.01220; 69 | this.D[8] = 0.00394; 70 | this.D[9] = -0.0013; 71 | }; 72 | 73 | /** 74 | New Zealand Map Grid Forward - long/lat to x/y 75 | long/lat in radians 76 | */ 77 | exports.forward = function(p) { 78 | var n; 79 | var lon = p.x; 80 | var lat = p.y; 81 | 82 | var delta_lat = lat - this.lat0; 83 | var delta_lon = lon - this.long0; 84 | 85 | // 1. Calculate d_phi and d_psi ... // and d_lambda 86 | // For this algorithm, delta_latitude is in seconds of arc x 10-5, so we need to scale to those units. Longitude is radians. 87 | var d_phi = delta_lat / SEC_TO_RAD * 1E-5; 88 | var d_lambda = delta_lon; 89 | var d_phi_n = 1; // d_phi^0 90 | 91 | var d_psi = 0; 92 | for (n = 1; n <= 10; n++) { 93 | d_phi_n = d_phi_n * d_phi; 94 | d_psi = d_psi + this.A[n] * d_phi_n; 95 | } 96 | 97 | // 2. Calculate theta 98 | var th_re = d_psi; 99 | var th_im = d_lambda; 100 | 101 | // 3. Calculate z 102 | var th_n_re = 1; 103 | var th_n_im = 0; // theta^0 104 | var th_n_re1; 105 | var th_n_im1; 106 | 107 | var z_re = 0; 108 | var z_im = 0; 109 | for (n = 1; n <= 6; n++) { 110 | th_n_re1 = th_n_re * th_re - th_n_im * th_im; 111 | th_n_im1 = th_n_im * th_re + th_n_re * th_im; 112 | th_n_re = th_n_re1; 113 | th_n_im = th_n_im1; 114 | z_re = z_re + this.B_re[n] * th_n_re - this.B_im[n] * th_n_im; 115 | z_im = z_im + this.B_im[n] * th_n_re + this.B_re[n] * th_n_im; 116 | } 117 | 118 | // 4. Calculate easting and northing 119 | p.x = (z_im * this.a) + this.x0; 120 | p.y = (z_re * this.a) + this.y0; 121 | 122 | return p; 123 | }; 124 | 125 | 126 | /** 127 | New Zealand Map Grid Inverse - x/y to long/lat 128 | */ 129 | exports.inverse = function(p) { 130 | var n; 131 | var x = p.x; 132 | var y = p.y; 133 | 134 | var delta_x = x - this.x0; 135 | var delta_y = y - this.y0; 136 | 137 | // 1. Calculate z 138 | var z_re = delta_y / this.a; 139 | var z_im = delta_x / this.a; 140 | 141 | // 2a. Calculate theta - first approximation gives km accuracy 142 | var z_n_re = 1; 143 | var z_n_im = 0; // z^0 144 | var z_n_re1; 145 | var z_n_im1; 146 | 147 | var th_re = 0; 148 | var th_im = 0; 149 | for (n = 1; n <= 6; n++) { 150 | z_n_re1 = z_n_re * z_re - z_n_im * z_im; 151 | z_n_im1 = z_n_im * z_re + z_n_re * z_im; 152 | z_n_re = z_n_re1; 153 | z_n_im = z_n_im1; 154 | th_re = th_re + this.C_re[n] * z_n_re - this.C_im[n] * z_n_im; 155 | th_im = th_im + this.C_im[n] * z_n_re + this.C_re[n] * z_n_im; 156 | } 157 | 158 | // 2b. Iterate to refine the accuracy of the calculation 159 | // 0 iterations gives km accuracy 160 | // 1 iteration gives m accuracy -- good enough for most mapping applications 161 | // 2 iterations bives mm accuracy 162 | for (var i = 0; i < this.iterations; i++) { 163 | var th_n_re = th_re; 164 | var th_n_im = th_im; 165 | var th_n_re1; 166 | var th_n_im1; 167 | 168 | var num_re = z_re; 169 | var num_im = z_im; 170 | for (n = 2; n <= 6; n++) { 171 | th_n_re1 = th_n_re * th_re - th_n_im * th_im; 172 | th_n_im1 = th_n_im * th_re + th_n_re * th_im; 173 | th_n_re = th_n_re1; 174 | th_n_im = th_n_im1; 175 | num_re = num_re + (n - 1) * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); 176 | num_im = num_im + (n - 1) * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); 177 | } 178 | 179 | th_n_re = 1; 180 | th_n_im = 0; 181 | var den_re = this.B_re[1]; 182 | var den_im = this.B_im[1]; 183 | for (n = 2; n <= 6; n++) { 184 | th_n_re1 = th_n_re * th_re - th_n_im * th_im; 185 | th_n_im1 = th_n_im * th_re + th_n_re * th_im; 186 | th_n_re = th_n_re1; 187 | th_n_im = th_n_im1; 188 | den_re = den_re + n * (this.B_re[n] * th_n_re - this.B_im[n] * th_n_im); 189 | den_im = den_im + n * (this.B_im[n] * th_n_re + this.B_re[n] * th_n_im); 190 | } 191 | 192 | // Complex division 193 | var den2 = den_re * den_re + den_im * den_im; 194 | th_re = (num_re * den_re + num_im * den_im) / den2; 195 | th_im = (num_im * den_re - num_re * den_im) / den2; 196 | } 197 | 198 | // 3. Calculate d_phi ... // and d_lambda 199 | var d_psi = th_re; 200 | var d_lambda = th_im; 201 | var d_psi_n = 1; // d_psi^0 202 | 203 | var d_phi = 0; 204 | for (n = 1; n <= 9; n++) { 205 | d_psi_n = d_psi_n * d_psi; 206 | d_phi = d_phi + this.D[n] * d_psi_n; 207 | } 208 | 209 | // 4. Calculate latitude and longitude 210 | // d_phi is calcuated in second of arc * 10^-5, so we need to scale back to radians. d_lambda is in radians. 211 | var lat = this.lat0 + (d_phi * SEC_TO_RAD * 1E5); 212 | var lon = this.long0 + d_lambda; 213 | 214 | p.x = lon; 215 | p.y = lat; 216 | 217 | return p; 218 | }; 219 | exports.names = ["New_Zealand_Map_Grid", "nzmg"]; -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/wkt.js: -------------------------------------------------------------------------------- 1 | var D2R = 0.01745329251994329577; 2 | var extend = require('./extend'); 3 | 4 | function mapit(obj, key, v) { 5 | obj[key] = v.map(function(aa) { 6 | var o = {}; 7 | sExpr(aa, o); 8 | return o; 9 | }).reduce(function(a, b) { 10 | return extend(a, b); 11 | }, {}); 12 | } 13 | 14 | function sExpr(v, obj) { 15 | var key; 16 | if (!Array.isArray(v)) { 17 | obj[v] = true; 18 | return; 19 | } 20 | else { 21 | key = v.shift(); 22 | if (key === 'PARAMETER') { 23 | key = v.shift(); 24 | } 25 | if (v.length === 1) { 26 | if (Array.isArray(v[0])) { 27 | obj[key] = {}; 28 | sExpr(v[0], obj[key]); 29 | } 30 | else { 31 | obj[key] = v[0]; 32 | } 33 | } 34 | else if (!v.length) { 35 | obj[key] = true; 36 | } 37 | else if (key === 'TOWGS84') { 38 | obj[key] = v; 39 | } 40 | else { 41 | obj[key] = {}; 42 | if (['UNIT', 'PRIMEM', 'VERT_DATUM'].indexOf(key) > -1) { 43 | obj[key] = { 44 | name: v[0].toLowerCase(), 45 | convert: v[1] 46 | }; 47 | if (v.length === 3) { 48 | obj[key].auth = v[2]; 49 | } 50 | } 51 | else if (key === 'SPHEROID') { 52 | obj[key] = { 53 | name: v[0], 54 | a: v[1], 55 | rf: v[2] 56 | }; 57 | if (v.length === 4) { 58 | obj[key].auth = v[3]; 59 | } 60 | } 61 | else if (['GEOGCS', 'GEOCCS', 'DATUM', 'VERT_CS', 'COMPD_CS', 'LOCAL_CS', 'FITTED_CS', 'LOCAL_DATUM'].indexOf(key) > -1) { 62 | v[0] = ['name', v[0]]; 63 | mapit(obj, key, v); 64 | } 65 | else if (v.every(function(aa) { 66 | return Array.isArray(aa); 67 | })) { 68 | mapit(obj, key, v); 69 | } 70 | else { 71 | sExpr(v, obj[key]); 72 | } 73 | } 74 | } 75 | } 76 | 77 | function rename(obj, params) { 78 | var outName = params[0]; 79 | var inName = params[1]; 80 | if (!(outName in obj) && (inName in obj)) { 81 | obj[outName] = obj[inName]; 82 | if (params.length === 3) { 83 | obj[outName] = params[2](obj[outName]); 84 | } 85 | } 86 | } 87 | 88 | function d2r(input) { 89 | return input * D2R; 90 | } 91 | 92 | function cleanWKT(wkt) { 93 | if (wkt.type === 'GEOGCS') { 94 | wkt.projName = 'longlat'; 95 | } 96 | else if (wkt.type === 'LOCAL_CS') { 97 | wkt.projName = 'identity'; 98 | wkt.local = true; 99 | } 100 | else { 101 | if (typeof wkt.PROJECTION === "object") { 102 | wkt.projName = Object.keys(wkt.PROJECTION)[0]; 103 | } 104 | else { 105 | wkt.projName = wkt.PROJECTION; 106 | } 107 | } 108 | if (wkt.UNIT) { 109 | wkt.units = wkt.UNIT.name.toLowerCase(); 110 | if (wkt.units === 'metre') { 111 | wkt.units = 'meter'; 112 | } 113 | if (wkt.UNIT.convert) { 114 | if (wkt.type === 'GEOGCS') { 115 | if (wkt.DATUM && wkt.DATUM.SPHEROID) { 116 | wkt.to_meter = parseFloat(wkt.UNIT.convert, 10)*wkt.DATUM.SPHEROID.a; 117 | } 118 | } else { 119 | wkt.to_meter = parseFloat(wkt.UNIT.convert, 10); 120 | } 121 | } 122 | } 123 | 124 | if (wkt.GEOGCS) { 125 | //if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){ 126 | // wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*D2R; 127 | //} 128 | if (wkt.GEOGCS.DATUM) { 129 | wkt.datumCode = wkt.GEOGCS.DATUM.name.toLowerCase(); 130 | } 131 | else { 132 | wkt.datumCode = wkt.GEOGCS.name.toLowerCase(); 133 | } 134 | if (wkt.datumCode.slice(0, 2) === 'd_') { 135 | wkt.datumCode = wkt.datumCode.slice(2); 136 | } 137 | if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') { 138 | wkt.datumCode = 'nzgd49'; 139 | } 140 | if (wkt.datumCode === "wgs_1984") { 141 | if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') { 142 | wkt.sphere = true; 143 | } 144 | wkt.datumCode = 'wgs84'; 145 | } 146 | if (wkt.datumCode.slice(-6) === '_ferro') { 147 | wkt.datumCode = wkt.datumCode.slice(0, - 6); 148 | } 149 | if (wkt.datumCode.slice(-8) === '_jakarta') { 150 | wkt.datumCode = wkt.datumCode.slice(0, - 8); 151 | } 152 | if (~wkt.datumCode.indexOf('belge')) { 153 | wkt.datumCode = "rnb72"; 154 | } 155 | if (wkt.GEOGCS.DATUM && wkt.GEOGCS.DATUM.SPHEROID) { 156 | wkt.ellps = wkt.GEOGCS.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\_18/, 'clrk'); 157 | if (wkt.ellps.toLowerCase().slice(0, 13) === "international") { 158 | wkt.ellps = 'intl'; 159 | } 160 | 161 | wkt.a = wkt.GEOGCS.DATUM.SPHEROID.a; 162 | wkt.rf = parseFloat(wkt.GEOGCS.DATUM.SPHEROID.rf, 10); 163 | } 164 | if (~wkt.datumCode.indexOf('osgb_1936')) { 165 | wkt.datumCode = "osgb36"; 166 | } 167 | } 168 | if (wkt.b && !isFinite(wkt.b)) { 169 | wkt.b = wkt.a; 170 | } 171 | 172 | function toMeter(input) { 173 | var ratio = wkt.to_meter || 1; 174 | return parseFloat(input, 10) * ratio; 175 | } 176 | var renamer = function(a) { 177 | return rename(wkt, a); 178 | }; 179 | var list = [ 180 | ['standard_parallel_1', 'Standard_Parallel_1'], 181 | ['standard_parallel_2', 'Standard_Parallel_2'], 182 | ['false_easting', 'False_Easting'], 183 | ['false_northing', 'False_Northing'], 184 | ['central_meridian', 'Central_Meridian'], 185 | ['latitude_of_origin', 'Latitude_Of_Origin'], 186 | ['latitude_of_origin', 'Central_Parallel'], 187 | ['scale_factor', 'Scale_Factor'], 188 | ['k0', 'scale_factor'], 189 | ['latitude_of_center', 'Latitude_of_center'], 190 | ['lat0', 'latitude_of_center', d2r], 191 | ['longitude_of_center', 'Longitude_Of_Center'], 192 | ['longc', 'longitude_of_center', d2r], 193 | ['x0', 'false_easting', toMeter], 194 | ['y0', 'false_northing', toMeter], 195 | ['long0', 'central_meridian', d2r], 196 | ['lat0', 'latitude_of_origin', d2r], 197 | ['lat0', 'standard_parallel_1', d2r], 198 | ['lat1', 'standard_parallel_1', d2r], 199 | ['lat2', 'standard_parallel_2', d2r], 200 | ['alpha', 'azimuth', d2r], 201 | ['srsCode', 'name'] 202 | ]; 203 | list.forEach(renamer); 204 | if (!wkt.long0 && wkt.longc && (wkt.projName === 'Albers_Conic_Equal_Area' || wkt.projName === "Lambert_Azimuthal_Equal_Area")) { 205 | wkt.long0 = wkt.longc; 206 | } 207 | if (!wkt.lat_ts && wkt.lat1 && (wkt.projName === 'Stereographic_South_Pole' || wkt.projName === 'Polar Stereographic (variant B)')) { 208 | wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90); 209 | wkt.lat_ts = wkt.lat1; 210 | } 211 | } 212 | module.exports = function(wkt, self) { 213 | var lisp = JSON.parse(("," + wkt).replace(/\s*\,\s*([A-Z_0-9]+?)(\[)/g, ',["$1",').slice(1).replace(/\s*\,\s*([A-Z_0-9]+?)\]/g, ',"$1"]').replace(/,\["VERTCS".+/,'')); 214 | var type = lisp.shift(); 215 | var name = lisp.shift(); 216 | lisp.unshift(['name', name]); 217 | lisp.unshift(['type', type]); 218 | lisp.unshift('output'); 219 | var obj = {}; 220 | sExpr(lisp, obj); 221 | cleanWKT(obj.output); 222 | return extend(self, obj.output); 223 | }; 224 | -------------------------------------------------------------------------------- /src/main/resources/proj4js/lib/projections/aeqd.js: -------------------------------------------------------------------------------- 1 | var adjust_lon = require('../common/adjust_lon'); 2 | var HALF_PI = Math.PI/2; 3 | var EPSLN = 1.0e-10; 4 | var mlfn = require('../common/mlfn'); 5 | var e0fn = require('../common/e0fn'); 6 | var e1fn = require('../common/e1fn'); 7 | var e2fn = require('../common/e2fn'); 8 | var e3fn = require('../common/e3fn'); 9 | var gN = require('../common/gN'); 10 | var asinz = require('../common/asinz'); 11 | var imlfn = require('../common/imlfn'); 12 | exports.init = function() { 13 | this.sin_p12 = Math.sin(this.lat0); 14 | this.cos_p12 = Math.cos(this.lat0); 15 | }; 16 | 17 | exports.forward = function(p) { 18 | var lon = p.x; 19 | var lat = p.y; 20 | var sinphi = Math.sin(p.y); 21 | var cosphi = Math.cos(p.y); 22 | var dlon = adjust_lon(lon - this.long0); 23 | var e0, e1, e2, e3, Mlp, Ml, tanphi, Nl1, Nl, psi, Az, G, H, GH, Hs, c, kp, cos_c, s, s2, s3, s4, s5; 24 | if (this.sphere) { 25 | if (Math.abs(this.sin_p12 - 1) <= EPSLN) { 26 | //North Pole case 27 | p.x = this.x0 + this.a * (HALF_PI - lat) * Math.sin(dlon); 28 | p.y = this.y0 - this.a * (HALF_PI - lat) * Math.cos(dlon); 29 | return p; 30 | } 31 | else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { 32 | //South Pole case 33 | p.x = this.x0 + this.a * (HALF_PI + lat) * Math.sin(dlon); 34 | p.y = this.y0 + this.a * (HALF_PI + lat) * Math.cos(dlon); 35 | return p; 36 | } 37 | else { 38 | //default case 39 | cos_c = this.sin_p12 * sinphi + this.cos_p12 * cosphi * Math.cos(dlon); 40 | c = Math.acos(cos_c); 41 | kp = c / Math.sin(c); 42 | p.x = this.x0 + this.a * kp * cosphi * Math.sin(dlon); 43 | p.y = this.y0 + this.a * kp * (this.cos_p12 * sinphi - this.sin_p12 * cosphi * Math.cos(dlon)); 44 | return p; 45 | } 46 | } 47 | else { 48 | e0 = e0fn(this.es); 49 | e1 = e1fn(this.es); 50 | e2 = e2fn(this.es); 51 | e3 = e3fn(this.es); 52 | if (Math.abs(this.sin_p12 - 1) <= EPSLN) { 53 | //North Pole case 54 | Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); 55 | Ml = this.a * mlfn(e0, e1, e2, e3, lat); 56 | p.x = this.x0 + (Mlp - Ml) * Math.sin(dlon); 57 | p.y = this.y0 - (Mlp - Ml) * Math.cos(dlon); 58 | return p; 59 | } 60 | else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { 61 | //South Pole case 62 | Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); 63 | Ml = this.a * mlfn(e0, e1, e2, e3, lat); 64 | p.x = this.x0 + (Mlp + Ml) * Math.sin(dlon); 65 | p.y = this.y0 + (Mlp + Ml) * Math.cos(dlon); 66 | return p; 67 | } 68 | else { 69 | //Default case 70 | tanphi = sinphi / cosphi; 71 | Nl1 = gN(this.a, this.e, this.sin_p12); 72 | Nl = gN(this.a, this.e, sinphi); 73 | psi = Math.atan((1 - this.es) * tanphi + this.es * Nl1 * this.sin_p12 / (Nl * cosphi)); 74 | Az = Math.atan2(Math.sin(dlon), this.cos_p12 * Math.tan(psi) - this.sin_p12 * Math.cos(dlon)); 75 | if (Az === 0) { 76 | s = Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); 77 | } 78 | else if (Math.abs(Math.abs(Az) - Math.PI) <= EPSLN) { 79 | s = -Math.asin(this.cos_p12 * Math.sin(psi) - this.sin_p12 * Math.cos(psi)); 80 | } 81 | else { 82 | s = Math.asin(Math.sin(dlon) * Math.cos(psi) / Math.sin(Az)); 83 | } 84 | G = this.e * this.sin_p12 / Math.sqrt(1 - this.es); 85 | H = this.e * this.cos_p12 * Math.cos(Az) / Math.sqrt(1 - this.es); 86 | GH = G * H; 87 | Hs = H * H; 88 | s2 = s * s; 89 | s3 = s2 * s; 90 | s4 = s3 * s; 91 | s5 = s4 * s; 92 | c = Nl1 * s * (1 - s2 * Hs * (1 - Hs) / 6 + s3 / 8 * GH * (1 - 2 * Hs) + s4 / 120 * (Hs * (4 - 7 * Hs) - 3 * G * G * (1 - 7 * Hs)) - s5 / 48 * GH); 93 | p.x = this.x0 + c * Math.sin(Az); 94 | p.y = this.y0 + c * Math.cos(Az); 95 | return p; 96 | } 97 | } 98 | 99 | 100 | }; 101 | 102 | exports.inverse = function(p) { 103 | p.x -= this.x0; 104 | p.y -= this.y0; 105 | var rh, z, sinz, cosz, lon, lat, con, e0, e1, e2, e3, Mlp, M, N1, psi, Az, cosAz, tmp, A, B, D, Ee, F; 106 | if (this.sphere) { 107 | rh = Math.sqrt(p.x * p.x + p.y * p.y); 108 | if (rh > (2 * HALF_PI * this.a)) { 109 | return; 110 | } 111 | z = rh / this.a; 112 | 113 | sinz = Math.sin(z); 114 | cosz = Math.cos(z); 115 | 116 | lon = this.long0; 117 | if (Math.abs(rh) <= EPSLN) { 118 | lat = this.lat0; 119 | } 120 | else { 121 | lat = asinz(cosz * this.sin_p12 + (p.y * sinz * this.cos_p12) / rh); 122 | con = Math.abs(this.lat0) - HALF_PI; 123 | if (Math.abs(con) <= EPSLN) { 124 | if (this.lat0 >= 0) { 125 | lon = adjust_lon(this.long0 + Math.atan2(p.x, - p.y)); 126 | } 127 | else { 128 | lon = adjust_lon(this.long0 - Math.atan2(-p.x, p.y)); 129 | } 130 | } 131 | else { 132 | /*con = cosz - this.sin_p12 * Math.sin(lat); 133 | if ((Math.abs(con) < EPSLN) && (Math.abs(p.x) < EPSLN)) { 134 | //no-op, just keep the lon value as is 135 | } else { 136 | var temp = Math.atan2((p.x * sinz * this.cos_p12), (con * rh)); 137 | lon = adjust_lon(this.long0 + Math.atan2((p.x * sinz * this.cos_p12), (con * rh))); 138 | }*/ 139 | lon = adjust_lon(this.long0 + Math.atan2(p.x * sinz, rh * this.cos_p12 * cosz - p.y * this.sin_p12 * sinz)); 140 | } 141 | } 142 | 143 | p.x = lon; 144 | p.y = lat; 145 | return p; 146 | } 147 | else { 148 | e0 = e0fn(this.es); 149 | e1 = e1fn(this.es); 150 | e2 = e2fn(this.es); 151 | e3 = e3fn(this.es); 152 | if (Math.abs(this.sin_p12 - 1) <= EPSLN) { 153 | //North pole case 154 | Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); 155 | rh = Math.sqrt(p.x * p.x + p.y * p.y); 156 | M = Mlp - rh; 157 | lat = imlfn(M / this.a, e0, e1, e2, e3); 158 | lon = adjust_lon(this.long0 + Math.atan2(p.x, - 1 * p.y)); 159 | p.x = lon; 160 | p.y = lat; 161 | return p; 162 | } 163 | else if (Math.abs(this.sin_p12 + 1) <= EPSLN) { 164 | //South pole case 165 | Mlp = this.a * mlfn(e0, e1, e2, e3, HALF_PI); 166 | rh = Math.sqrt(p.x * p.x + p.y * p.y); 167 | M = rh - Mlp; 168 | 169 | lat = imlfn(M / this.a, e0, e1, e2, e3); 170 | lon = adjust_lon(this.long0 + Math.atan2(p.x, p.y)); 171 | p.x = lon; 172 | p.y = lat; 173 | return p; 174 | } 175 | else { 176 | //default case 177 | rh = Math.sqrt(p.x * p.x + p.y * p.y); 178 | Az = Math.atan2(p.x, p.y); 179 | N1 = gN(this.a, this.e, this.sin_p12); 180 | cosAz = Math.cos(Az); 181 | tmp = this.e * this.cos_p12 * cosAz; 182 | A = -tmp * tmp / (1 - this.es); 183 | B = 3 * this.es * (1 - A) * this.sin_p12 * this.cos_p12 * cosAz / (1 - this.es); 184 | D = rh / N1; 185 | Ee = D - A * (1 + A) * Math.pow(D, 3) / 6 - B * (1 + 3 * A) * Math.pow(D, 4) / 24; 186 | F = 1 - A * Ee * Ee / 2 - D * Ee * Ee * Ee / 6; 187 | psi = Math.asin(this.sin_p12 * Math.cos(Ee) + this.cos_p12 * Math.sin(Ee) * cosAz); 188 | lon = adjust_lon(this.long0 + Math.asin(Math.sin(Az) * Math.sin(Ee) / Math.cos(psi))); 189 | lat = Math.atan((1 - this.es * F * this.sin_p12 / Math.sin(psi)) * Math.tan(psi) / (1 - this.es)); 190 | p.x = lon; 191 | p.y = lat; 192 | return p; 193 | } 194 | } 195 | 196 | }; 197 | exports.names = ["Azimuthal_Equidistant", "aeqd"]; 198 | -------------------------------------------------------------------------------- /src/test/java/org/maptalks/proj4/Proj4Test.java: -------------------------------------------------------------------------------- 1 | package org.maptalks.proj4; 2 | 3 | 4 | import static org.junit.Assert.assertEquals; 5 | import static org.junit.Assert.assertTrue; 6 | 7 | import java.util.Arrays; 8 | import org.junit.Test; 9 | 10 | public class Proj4Test { 11 | 12 | private static final String EPSG3857 = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"; 13 | private static final String EPSG4326 = "+proj=longlat +datum=WGS84 +no_defs"; 14 | 15 | private static PointAdaptor pointAdaptor = new PointAdaptor() { 16 | public double getX(double[] point) { 17 | return point[0]; 18 | } 19 | 20 | public double getY(double[] point) { 21 | return point[1]; 22 | } 23 | 24 | public void setX(double[] point, double x) { 25 | point[0] = x; 26 | } 27 | 28 | public void setY(double[] point, double y) { 29 | point[1] = y; 30 | } 31 | }; 32 | 33 | @Test 34 | public void testForward() throws Exception { 35 | Proj4 proj = new Proj4(EPSG4326, EPSG3857, pointAdaptor); 36 | double[] coord = proj.forward(new double[] {120.0, 30.0}); 37 | double tolerance = 1e-3; 38 | assertEquals(coord[0], 13358338.895192828, tolerance); 39 | assertEquals(coord[1], 3503549.843504374, tolerance); 40 | } 41 | 42 | @Test 43 | public void testInverse() throws Exception { 44 | Proj4 proj = new Proj4(EPSG4326, EPSG3857, pointAdaptor); 45 | double[] coord = proj.inverse(new double[] {13358338.89, 3503549.84}); 46 | double tolerance = 1e-7; 47 | assertEquals(coord[0], 120.0, tolerance); 48 | assertEquals(coord[1], 30.0, tolerance); 49 | } 50 | 51 | @Test 52 | public void testForwardWithDef() throws Exception { 53 | Proj4 proj = new Proj4("EPSG:4326", "EPSG:3857", pointAdaptor); 54 | double[] coord = proj.forward(new double[] {120.0, 30.0}); 55 | double tolerance = 1e-3; 56 | assertEquals(coord[0], 13358338.895192828, tolerance); 57 | assertEquals(coord[1], 3503549.843504374, tolerance); 58 | } 59 | 60 | @Test 61 | public void testInverseWithDef() throws Exception { 62 | Proj4 proj = new Proj4("EPSG:4326", "EPSG:3857", pointAdaptor); 63 | double[] coord = proj.inverse(new double[] {13358338.89, 3503549.84}); 64 | double tolerance = 1e-7; 65 | assertEquals(coord[0], 120.0, tolerance); 66 | assertEquals(coord[1], 30.0, tolerance); 67 | } 68 | 69 | @Test 70 | public void testForwardWithMixed() throws Exception { 71 | Proj4 proj = new Proj4(EPSG4326, "EPSG:3857", pointAdaptor); 72 | double[] coord = proj.forward(new double[] {120.0, 30.0}); 73 | double tolerance = 1e-3; 74 | assertEquals(coord[0], 13358338.895192828, tolerance); 75 | assertEquals(coord[1], 3503549.843504374, tolerance); 76 | } 77 | 78 | @Test 79 | public void testInverseWithMixed() throws Exception { 80 | Proj4 proj = new Proj4("EPSG:4326", EPSG3857, pointAdaptor); 81 | double[] coord = proj.inverse(new double[] {13358338.89, 3503549.84}); 82 | double tolerance = 1e-7; 83 | assertEquals(coord[0], 120.0, tolerance); 84 | assertEquals(coord[1], 30.0, tolerance); 85 | } 86 | 87 | @Test 88 | public void testSameProj() throws Exception { 89 | Proj4 proj = new Proj4("GCJ02", "GCJ02"); 90 | double[] o = new double[] {121.8999, 21.3333}; 91 | double[] iv = proj.inverse(o); 92 | double[] fw = proj.forward(o); 93 | double tolerance = 0; 94 | assertEquals(o[0], iv[0], tolerance); 95 | assertEquals(o[0], fw[0], tolerance); 96 | assertEquals(o[1], iv[1], tolerance); 97 | assertEquals(o[1], fw[1], tolerance); 98 | } 99 | 100 | @Test 101 | public void testGcj02ToBaidu() throws Exception { 102 | double[][] expected = new double[][] { 103 | {114.69490414027017, 33.639096507711685}, 104 | {114.69488614273101, 33.63804850387785}, 105 | {114.69500713986416, 33.63794251496537}, 106 | {114.69578412001135, 33.63793958798685}, 107 | {114.6959281162725, 33.637965601694006}, 108 | {114.69751307493384, 33.637957753486745} 109 | }; 110 | 111 | 112 | Proj4 proj = new Proj4("GCJ02", "BD09LL", pointAdaptor); 113 | double[][] lonlats = new double[][] { 114 | {114.68837663801743, 33.63312016454496}, 115 | {114.68835840204522, 33.632072446353945}, 116 | {114.68848002806972, 33.63196427051657}, 117 | {114.68926112541861, 33.63194729708501}, 118 | {114.68940588838505, 33.6319707051534}, 119 | {114.69099925796665, 33.63193416046613} 120 | }; 121 | 122 | for (int i = 0; i < lonlats.length; i++) { 123 | double[] coord = proj.forward(lonlats[i]); 124 | assertTrue(Arrays.equals(expected[i], coord)); 125 | } 126 | } 127 | 128 | @Test 129 | public void testGlobalDef() throws Exception { 130 | Global.def("mars", "+proj=longlat +datum=GCJ02"); 131 | 132 | assertTrue(Global.has("mars")); 133 | assertTrue(Global.has("MARS")); 134 | 135 | Proj mars = Global.def("MARS"); 136 | assertEquals(Global.def("gcj02"), mars); 137 | } 138 | 139 | @Test 140 | public void testTestProj() throws Exception { 141 | assertTrue(Parser.testProj("+proj=longlat +datum=GCJ02")); 142 | assertTrue(!Parser.testProj("not proj4 string")); 143 | } 144 | 145 | @Test 146 | public void testTestWKT() throws Exception { 147 | String wkt = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0]]"; 148 | assertTrue(Parser.testWKT(wkt)); 149 | assertTrue(!Parser.testWKT("+proj=longlat +datum=GCJ02")); 150 | } 151 | 152 | @Test 153 | public void testProj4() throws Exception { 154 | String firstProjection = "PROJCS[\"NAD83 / Massachusetts Mainland\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",42.68333333333333],PARAMETER[\"standard_parallel_2\",41.71666666666667],PARAMETER[\"latitude_of_origin\",41],PARAMETER[\"central_meridian\",-71.5],PARAMETER[\"false_easting\",200000],PARAMETER[\"false_northing\",750000],AUTHORITY[\"EPSG\",\"26986\"],AXIS[\"X\",EAST],AXIS[\"Y\",NORTH]]"; 155 | String secondProjection = "+proj=gnom +lat_0=90 +lon_0=0 +x_0=6300000 +y_0=6300000 +ellps=WGS84 +datum=WGS84 +units=m +no_defs"; 156 | 157 | Proj4 proj = new Proj4(firstProjection, secondProjection, pointAdaptor); 158 | double[] result = proj.forward(new double[] {2, 5}); 159 | assertEquals(-2690666.2977344505, result[0], 1E-6); 160 | assertEquals(3662659.885459918, result[1], 1E-6); 161 | } 162 | 163 | } 164 | --------------------------------------------------------------------------------