分享proj4js中經(jīng)緯度和蘭伯特投影的轉(zhuǎn)換代碼
蘭伯特投影簡介參見百科搜索:?
蘭伯特投影在氣象數(shù)據(jù)的處理中,是比較常用的投影坐標(biāo)系,根據(jù)不同區(qū)域、范圍進(jìn)行投影。
proj4是專業(yè)的坐標(biāo)轉(zhuǎn)換類庫,有各種語言版本的,C++,java,js,python版等,可以很方便的將坐標(biāo)從一個(gè)坐標(biāo)系轉(zhuǎn)換到另一個(gè)坐標(biāo)系。在前端使用的時(shí)候,應(yīng)用場景需要轉(zhuǎn)換大量的坐標(biāo),就會(huì)發(fā)現(xiàn)使用proj4js存在性能問題,查看了一下proj4js的源代碼,發(fā)現(xiàn)類庫每次調(diào)用初始化很多不相關(guān)的類型,對象等,所以,在基礎(chǔ)上,進(jìn)行了提取。
轉(zhuǎn)換代碼及說明
//初始化常用的變量,直接換算成弧度,提升計(jì)算性能
var
?EPSLN?=?(
typeof
?Number.EPSILON?===?
'undefined'
)???1.0e-10?:?Number.EPSILON;
var
?conv?=?180?/?Math.PI;
var
?HALF_PI?=?Math.PI?/?2;
var
?SPI?=?3.14159265359;
var
?TWO_PI?=?2?*?Math.PI;
var
?a?=?6378137;
var
?b?=?6356752.314245179;
var
?e?=?0.08181919084262157;
var
?lat1?=?0.52359877559829;
var
?lat2?=?1.04719755119659;?
var
?long0?=?1.8029251173101;
var
?lat0?=?0;
var
?k0?=?1;?
var
?ns;
var
?f0;
var
?rh;
//常用的轉(zhuǎn)換參數(shù),直接提取引用
var
?tsfnz?=?
function
(eccent,?phi,?sinphi)?{
?
var
?con?=?eccent?*?sinphi;
?
var
?com?=?0.5?*?eccent;
?
con?=?Math.pow(((1?-?con)?/?(1?+?con)),?com);
?
return
(Math.tan(0.5?*?(HALF_PI?-?phi))?/?con);
?
};
var
?sign?=?
function
(x)?{
?
return
?x?<?0???-1?:?1;
?
};
?
var
?msfnz?=?
function
(eccent,?sinphi,?cosphi)?{
?
var
?con?=?eccent?*?sinphi;
?
return
?cosphi?/?(Math.sqrt(1?-?con?*?con));
?
};
var
?adjust_lon?=?
function
(x)?{
return
(Math.abs(x)?<=?SPI)???x?:?(x?-?(sign(x)?*?TWO_PI));
?
};
var
?phi2z?=?
function
(eccent,?ts)?{
var
?eccnth?=?0.5?*?eccent;
var
?con,?dphi;
var
?phi?=?HALF_PI?-?2?*?Math.atan(ts);
for
(
var
?i?=?0;?i?<=?15;?i++)?{
con?=?eccent?*?Math.sin(phi);
dphi?=?HALF_PI?-?2?*?Math.atan(ts?*?(Math.pow(((1?-?con)?/?(1?+?con)),?eccnth)))?-?phi;
phi?+=?dphi;
if
(Math.abs(dphi)?<=?0.0000000001)?{
??
return
?phi;
?
}
}
return
?-9999;
};
? ??
?
//根據(jù)proj4的坐標(biāo)系描述字符串,解析其中的參數(shù)
function
?init(prjstr)?{
if
(prjstr.indexOf(
"?"
)?>?-1)?{
var
?_prjArr?=?prjstr.split(
"?"
);
_prjArr.forEach(
function
(item,?index,?input)?{
if
(item.indexOf(
"lat_0"
)?>?-1)?{
?
lat0?=?parseFloat(item.split(
"="
)[1])?/?conv;
?
}
?
})
?
}
var
?sin1?=?Math.sin(lat1);
var
?cos1?=?Math.cos(lat1);
var
?ms1?=?msfnz(e,?sin1,?cos1);
var
?ts1?=?tsfnz(e,?lat1,?sin1);
var
?sin2?=?Math.sin(lat2);
var
?cos2?=?Math.cos(lat2);
var
?ms2?=?msfnz(e,?sin2,?cos2);
var
?ts2?=?tsfnz(e,?lat2,?sin2);
var
?ts0?=?tsfnz(e,?lat0,?Math.sin(lat0));
if
(Math.abs(lat1?-?lat2)?>?EPSLN)?{
?
ns?=?Math.log(ms1?/?ms2)?/?Math.log(ts1?/?ts2);
?
}?
else
?{
? ?
ns?=?sin1;
?
}
if
(isNaN(ns))?{
??
ns?=?sin1;
?
}
f0?=?ms1?/?(ns?*?Math.pow(ts1,?ns));
rh?=?a?*?f0?*?Math.pow(ts0,?ns);
}
? ?
?
//經(jīng)緯度坐標(biāo)轉(zhuǎn)換蘭伯特坐標(biāo)
function
?projCood(lon,?lat)?{
lon?=?lon?/?conv;
lat?=?lat?/?conv;
if
(Math.abs(2?*?Math.abs(lat)?-?Math.PI)?<=?EPSLN)?{
lat?=?sign(lat)?*?(HALF_PI?-?2?*?EPSLN);
}
var
?con?=?Math.abs(Math.abs(lat)?-?HALF_PI);
?
var
?ts,?rh1;
?
if
(con?>?EPSLN)?{
?
ts?=?tsfnz(e,?lat,?Math.sin(lat));
rh1?=?a?*?f0?*?Math.pow(ts,?ns);
}?
else
?{
?
con?=?lat?*?ns;
??
if
(con?<=?0)?{
? ?
return
?null
;
? ?
}
rh1?=?0;
?
}
var
?theta?=?ns?*?adjust_lon(lon?-?long0);
var
?nlon?=?(rh1?*?Math.sin(theta));
var
?nlat?=?(rh?-?rh1?*?Math.cos(theta));
?return
?[nlon,?nlat];
?
}
?
//蘭伯特坐標(biāo)轉(zhuǎn)經(jīng)緯度坐標(biāo)
function
?inverseProj(x1,?y1)?{
var
?rh1,?con,?ts;
var
?lat,?lon;
var
?x?=?x1?/?k0;
var
?y?=?(rh?-?y1?/?k0);
if
(ns?>?0)?{
rh1?=?Math.sqrt(x?*?x?+?y?*?y);
con?=?1;
}?
else
?{
rh1?=?-Math.sqrt(x?*?x?+?y?*?y);
con?=?-1;
?
}
var
?theta?=?0;
if
(rh1?!==?0)?{
theta?=?Math.atan2((con?*?x),?(con?*?y));
??
}
if
((rh1?!==?0)?||?(ns?>?0))?{
?
con?=?1?/?ns;
?
ts?=?Math.pow((rh1?/?(a?*?f0)),?con);
lat?=?phi2z(e,?ts);
if
(lat?===?-9999)?{
return
?null
;
?
}
?
}?
else
?{
??
lat?=?-HALF_PI;
}
?
lon?=?adjust_lon(theta?/?ns?+?long0);
?
return
?[lon?*?conv,?conv?*?lat];
?
}
對于在應(yīng)用中的其他坐標(biāo)系轉(zhuǎn)換,同樣能夠在其中進(jìn)行代碼提取。
https://mp.weixin.qq.com/s?__biz=MzU2ODYzNzc4OQ==&mid=2247485646&idx=1&sn=4f9e87af9be3fe2c2a26a5464953666e&chksm=fc8ba8fccbfc21ea9a069c0dbae33c174bfea5b09b4a0931220f490ebbb3518e2d0fc5e478a9&token=1743499510&lang=zh_CN#rd