proj4m
Version:
Handle transformation between mars projections.
531 lines (463 loc) • 13.3 kB
JavaScript
;
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var proj4 = _interopDefault(require('proj4'));
var globals = function (defs) {
defs('EPSG:4326', '+proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees');
defs('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 +no_defs');
defs('GCJ02', '+proj=longlat +datum=GCJ02');
defs('GCJ02MC', '+proj=merc +datum=GCJ02');
defs('BD09LL', '+proj=longlat +datum=BD09');
defs('BD09MC', '+proj=bmerc +datum=BD09');
defs.WGS84 = defs['EPSG:4326'];
};
var Const = {
projNameLatLong: 'longlat',
projNameMerc: 'merc',
projNameBaidu: 'bmerc',
datumCodeWGS84: 'wgs84',
datumCodeGCJ02: 'gcj02',
datumCodeBD09: 'bd09'
};
var Proj = function Proj (projName, datumCode, srsCode) {
this.projName = projName ? projName.toLowerCase() : projName;
this.datumCode = datumCode ? datumCode.toLowerCase() : datumCode;
this.srsCode = srsCode;
fixMarsProj(this);
};
function fixMarsProj (p) {
if (p.datumCode === Const.datumCodeGCJ02 && !isLatLong(p.projName)) {
p.projName = Const.projNameMerc;
}
if (p.datumCode === Const.datumCodeBD09 && !isLatLong(p.projName)) {
p.projName = Const.projNameBaidu;
}
if (p.projName === Const.projNameBaidu) {
p.datumCode = Const.datumCodeBD09;
}
}
function isLatLong (name) {
return name === 'longlat' || name === 'latlong' || name === 'lnglat' || name === 'latlng'
}
var parseProj = function (code) {
var paramObj = code.split('+').map(function (v) { return v.trim(); }).filter(function (a) { return a; }).reduce(function (p, a) {
var split = a.split('=');
split.push(true);
p[split[0].toLowerCase()] = split[1];
return p
}, {});
return new Proj(paramObj.proj, paramObj.datum, code)
};
function defs (name) {
name = name ? name.toUpperCase() : '';
if (arguments.length === 2) {
var def = arguments[1];
if (typeof def === 'string') {
defs[name] = parseProj(def);
} else {
defs[name] = def;
}
} else if (arguments.length === 1) {
if (typeof name === 'string') {
if (name in defs) {
return defs[name]
}
} else {
console.log(name);
}
}
}
globals(defs);
function testObj (code) {
return typeof code === 'string'
}
function testDef (code) {
return code in defs
}
function testProj (code) {
return code[0] === '+'
}
function parse$1 (code) {
if (testObj(code)) {
if (testDef(code)) {
return defs[code]
}
if (testProj(code)) {
return parseProj(code)
}
} else {
return code
}
}
var r = 6378137.0;
var maxLatitude = 85.0511287798;
var deg2Rad = Math.PI / 180.0;
var rad2Deg = 180.0 / Math.PI;
function forward (p) {
var lng = p.x;
var lat = p.y;
var lat1 = Math.max(Math.min(maxLatitude, lat), -maxLatitude);
var sin = Math.sin(lat1 * deg2Rad);
var x = r * lng * deg2Rad;
var y = r * Math.log((1 + sin) / (1 - sin)) / 2;
p.x = x;
p.y = y;
return p
}
function inverse (p) {
var x = p.x;
var y = p.y;
var lng = x * rad2Deg / r;
var lat = ((2 * Math.atan(Math.exp(y / r))) - (Math.PI / 2)) * rad2Deg;
p.x = lng;
p.y = lat;
return p
}
var merc = {
forward: forward,
inverse: inverse,
isLatLong: false
};
function identity (p) {
return p
}
var longlat = {
forward: identity,
inverse: identity,
isLatLong: true
};
function forward$1 (p) {
return convertLL2MC(p)
}
function inverse$1 (p) {
return convertMC2LL(p)
}
function convertLL2MC (p) {
p.x = getLoop(p.x, -180, 180);
p.y = getRange(p.y, -74, 74);
for (var i = 0; i < aLLBAND.length; i++) {
if (p.y >= aLLBAND[i]) {
return convertor(p, aLL2MC[i])
}
}
for (var i$1 = aLLBAND.length - 1; i$1 >= 0; i$1--) {
if (p.y <= -aLLBAND[i$1]) {
return convertor(p, aLL2MC[i$1])
}
}
}
function convertMC2LL (p) {
var yAbs = Math.abs(p.y);
for (var i = 0; i < aMCBAND.length; i++) {
if (yAbs >= aMCBAND[i]) {
return convertor(p, aMC2LL[i])
}
}
}
function convertor (p, table) {
var d = Math.abs(p.y) / table[9];
var x = table[0] + (table[1] * Math.abs(p.x));
var y = table[2];
for (var i = 3; i <= 8; i++) {
y += table[i] * Math.pow(d, i - 2);
}
p.x = x;
p.y = y;
return p
}
function getRange (v, min, max) {
v = Math.max(v, min);
v = Math.min(v, max);
return v
}
function getLoop (v, min, max) {
var d = max - min;
while (v > max) {
v -= d;
}
while (v < min) {
v += d;
}
return v
}
var aMCBAND = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0];
var aLLBAND = [75, 60, 45, 30, 15, 0];
var aMC2LL = [
[1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331,
200.9824383106796, -187.2403703815547, 91.6087516669843,
-23.38765649603339, 2.57121317296198, -0.03801003308653,
17337981.2],
[-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289,
96.32687599759846, -1.85204757529826, -59.36935905485877,
47.40033549296737, -16.50741931063887, 2.28786674699375,
10260144.86],
[-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616,
59.74293618442277, 7.357984074871, -25.38371002664745,
13.45380521110908, -3.29883767235584, 0.32710905363475,
6856817.37],
[-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591,
40.31678527705744, 0.65659298677277, -4.44255534477492,
0.85341911805263, 0.12923347998204, -0.04625736007561,
4482777.06],
[3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062,
23.10934304144901, -0.00023663490511, -0.6321817810242,
-0.00663494467273, 0.03430082397953, -0.00466043876332,
2555164.4],
[2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8,
7.47137025468032, -0.00000353937994, -0.02145144861037,
-0.00001234426596, 0.00010322952773, -0.00000323890364,
826088.5]
];
var aLL2MC = [
[-0.0015702102444, 111320.7020616939, 1704480524535203,
-10338987376042340, 26112667856603880, -35149669176653700,
26595700718403920, -10725012454188240, 1800819912950474,
82.5],
[0.0008277824516172526, 111320.7020463578, 647795574.6671607,
-4082003173.641316, 10774905663.51142, -15171875531.51559,
12053065338.62167, -5124939663.577472, 913311935.9512032,
67.5],
[0.00337398766765, 111320.7020202162, 4481351.045890365,
-23393751.19931662, 79682215.47186455, -115964993.2797253,
97236711.15602145, -43661946.33752821, 8477230.501135234,
52.5],
[0.00220636496208, 111320.7020209128, 51751.86112841131,
3796837.749470245, 992013.7397791013, -1221952.21711287,
1340652.697009075, -620943.6990984312, 144416.9293806241,
37.5],
[-0.0003441963504368392, 111320.7020576856, 278.2353980772752,
2485758.690035394, 6070.750963243378, 54821.18345352118,
9540.606633304236, -2710.55326746645, 1405.483844121726,
22.5],
[-0.0003218135878613132, 111320.7020701615, 0.00369383431289,
823725.6402795718, 0.46104986909093, 2351.343141331292,
1.58060784298199, 8.77738589078284, 0.37238884252424,
7.45]
];
var bmerc = {
forward: forward$1,
inverse: inverse$1,
isLatLong: false
};
var projMap = {};
projMap[Const.projNameLatLong] = longlat;
projMap[Const.projNameMerc] = merc;
projMap[Const.projNameBaidu] = bmerc;
function get (name) {
return projMap[name]
}
var projection = {
get: get
};
function identity$1 (p) {
return p
}
var wgs84$1 = {
fromWGS84: identity$1,
toWGS84: identity$1
};
var axis = 6378245.0;
var offset = 0.00669342162296594323; // (a^2 - b^2) / a^2
function fromWGS84 (p) {
if (outOfChina(p.x, p.y)) {
return p
}
var d = delta(p.x, p.y);
p.x += d.x;
p.y += d.y;
return p
}
function toWGS84 (p) {
if (outOfChina(p.x, p.y)) {
return p
}
var d = delta(p.x, p.y);
p.x -= d.x;
p.y -= d.y;
return p
}
function transformLon (x, y) {
var ret = 300.0 + x + (2.0 * y) + (0.1 * x * x) + (0.1 * x * y) + (0.1 * Math.sqrt(Math.abs(x)));
ret += ((20.0 * Math.sin(6.0 * x * Math.PI)) + (20.0 * Math.sin(2.0 * x * Math.PI))) * 2.0 / 3.0;
ret += ((20.0 * Math.sin(x * Math.PI)) + (40.0 * Math.sin(x / 3.0 * Math.PI))) * 2.0 / 3.0;
ret += ((150.0 * Math.sin(x / 12.0 * Math.PI)) + (300.0 * Math.sin(x / 30.0 * Math.PI))) * 2.0 / 3.0;
return ret
}
function transformLat (x, y) {
var ret = -100.0 + (2.0 * x) + (3.0 * y) + (0.2 * y * y) + (0.1 * x * y) + (0.2 * Math.sqrt(Math.abs(x)));
ret += ((20.0 * Math.sin(6.0 * x * Math.PI)) + (20.0 * Math.sin(2.0 * x * Math.PI))) * 2.0 / 3.0;
ret += ((20.0 * Math.sin(y * Math.PI)) + (40.0 * Math.sin(y / 3.0 * Math.PI))) * 2.0 / 3.0;
ret += ((160.0 * Math.sin(y / 12.0 * Math.PI)) + (320 * Math.sin(y * Math.PI / 30.0))) * 2.0 / 3.0;
return ret
}
function delta (wgLon, wgLat) {
var dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
var dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
var radLat = wgLat / 180.0 * Math.PI;
var magic = Math.sin(radLat);
magic = 1 - (offset * magic * magic);
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((axis * (1 - offset)) / (magic * sqrtMagic) * Math.PI);
dLon = (dLon * 180.0) / (axis / sqrtMagic * Math.cos(radLat) * Math.PI);
return {
x: dLon,
y: dLat
}
}
function outOfChina (lon, lat) {
if (lon < 72.004 || lon > 137.8347) {
return true
}
if (lat < 0.8293 || lat > 55.8271) {
return true
}
return false
}
var gcj02 = {
fromWGS84: fromWGS84,
toWGS84: toWGS84
};
var xPi = Math.PI * 3000.0 / 180.0;
function fromWGS84$1 (p) {
p = gcj02.fromWGS84(p);
return fromGCJ02(p)
}
function toWGS84$1 (p) {
p = toGCJ02(p);
return gcj02.toWGS84(p)
}
function fromGCJ02 (p) {
var x = p.x;
var y = p.y;
var z = Math.sqrt((x * x) + (y * y)) + (0.00002 * Math.sin(y * xPi));
var theta = Math.atan2(y, x) + (0.000003 * Math.cos(x * xPi));
x = (z * Math.cos(theta)) + 0.0065;
y = (z * Math.sin(theta)) + 0.006;
p.x = x;
p.y = y;
return p
}
function toGCJ02 (p) {
var x = p.x;
var y = p.y;
x -= 0.0065;
y -= 0.006;
var z = Math.sqrt((x * x) + (y * y)) - (0.00002 * Math.sin(y * xPi));
var theta = Math.atan2(y, x) - (0.000003 * Math.cos(x * xPi));
x = z * Math.cos(theta);
y = z * Math.sin(theta);
p.x = x;
p.y = y;
return p
}
var bd09 = {
fromGCJ02: fromGCJ02,
toGCJ02: toGCJ02,
fromWGS84: fromWGS84$1,
toWGS84: toWGS84$1
};
var datumMap = {};
datumMap[Const.datumCodeWGS84] = wgs84$1;
datumMap[Const.datumCodeGCJ02] = gcj02;
datumMap[Const.datumCodeBD09] = bd09;
function get$1 (code) {
return datumMap[code]
}
var datum = {
get: get$1
};
function isMarsDatum (code) {
return code === Const.datumCodeGCJ02 || code === Const.datumCodeBD09
}
function needProj4 (srcProj, dstProj) {
return !isMarsDatum(srcProj.datumCode) && !isMarsDatum(dstProj.datumCode)
}
var transform = function (srcProj, dstProj, point) {
if (Array.isArray(point)) {
point = proj4.toPoint(point);
}
if (srcProj.srsCode === dstProj.srsCode) {
return point
}
var useProj4 = needProj4(srcProj, dstProj);
if (useProj4) {
return proj4(srcProj.srsCode, dstProj.srsCode, point)
}
var sProj = projection.get(srcProj.projName);
var dProj = projection.get(dstProj.projName);
if (!sProj.isLatLong) {
point = sProj.inverse(point);
}
if (srcProj.datumCode !== dstProj.datumCode) {
var sDatum = datum.get(srcProj.datumCode);
var dDatum = datum.get(dstProj.datumCode);
if (srcProj.datumCode === Const.datumCodeGCJ02 && dstProj.datumCode === Const.datumCodeBD09) {
point = dDatum.fromGCJ02(point);
} else if (srcProj.datumCode === Const.datumCodeBD09 && dstProj.datumCode === Const.datumCodeGCJ02) {
point = sDatum.toGCJ02(point);
} else {
point = sDatum.toWGS84(point);
point = dDatum.fromWGS84(point);
}
}
if (!dProj.isLatLong) {
point = dProj.forward(point);
}
return point
};
var wgs84 = parse$1('WGS84');
function transformer (from, to, coords) {
if (Array.isArray(coords)) {
var transformed = transform(from, to, coords);
if (coords.length === 3) {
return [transformed.x, transformed.y, transformed.z]
} else {
return [transformed.x, transformed.y]
}
} else {
return transform(from, to, coords)
}
}
function checkProj (item) {
if (item instanceof Proj) {
return item
}
if (item.oProj) {
return item.oProj
}
return parse$1(item)
}
function proj4m$1 (fromProj, toProj, coord) {
fromProj = checkProj(fromProj);
var single = false;
var obj;
if (typeof toProj === 'undefined') {
toProj = fromProj;
fromProj = wgs84;
single = true;
} else if (typeof toProj.x !== 'undefined' || Array.isArray(toProj)) {
coord = toProj;
toProj = fromProj;
fromProj = wgs84;
single = true;
}
toProj = checkProj(toProj);
if (coord) {
return transformer(fromProj, toProj, coord)
} else {
obj = {
forward: function (coords) {
return transformer(fromProj, toProj, coords)
},
inverse: function (coords) {
return transformer(toProj, fromProj, coords)
}
};
if (single) {
obj.oProj = toProj;
}
return obj
}
}
proj4m$1.defs = defs;
proj4m$1.transform = transform;
module.exports = proj4m$1;