引言
兰伯特投影简介参见百科搜索:
兰伯特投影在气象数据的处理中,是比较常用的投影坐标系,根据不同区域、范围进行投影。
proj4是专业的坐标转换类库,有各种语言版本的,C++,java,js,python版等,可以很方便的将坐标从一个坐标系转换到另一个坐标系。
在前端使用的时候,应用场景需要转换大量的坐标,就会发现使用proj4js存在性能问题,查看了一下proj4js的源代码,发现类库每次调用初始化很多不相关的类型,对象等,所以,在基础上,进行了提取。
转换代码及说明
//初始化常用的变量,直接换算成弧度,提升计算性能
varEPSLN=(typeofNumber.EPSILON==='undefined')?1.0e-10:Number.EPSILON;
varconv=180/Math.PI;
varHALF_PI=Math.PI/2;
varSPI=3.14159265359;
varTWO_PI=2*Math.PI;
vara=6378137;
varb=6356752.314245179;
vare=0.08181919084262157;
varlat1=0.52359877559829;
varlat2=1.04719755119659;
varlong0=1.8029251173101;
varlat0=0;
vark0=1;
varns;
varf0;
varrh;
//常用的转换参数,直接提取引用
vartsfnz=function(eccent,phi,sinphi){
varcon=eccent*sinphi;
varcom=0.5*eccent;
con=Math.pow(((1-con)/(1+con)),com);
return(Math.tan(0.5*(HALF_PI-phi))/con);
};
varsign=function(x){
returnx
};
varmsfnz=function(eccent,sinphi,cosphi){
varcon=eccent*sinphi;
returncosphi/(Math.sqrt(1-con*con));
};
varadjust_lon=function(x){
return(Math.abs(x)<=SPI)?x:(x-(sign(x)*TWO_PI));
};
varphi2z=function(eccent,ts){
vareccnth=0.5*eccent;
varcon,dphi;
varphi=HALF_PI-2*Math.atan(ts);
for(vari=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){
returnphi;
}
}
return-9999;
};
//根据proj4的坐标系描述字符串,解析其中的参数
functioninit(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;
}
})
}
varsin1=Math.sin(lat1);
varcos1=Math.cos(lat1);
varms1=msfnz(e,sin1,cos1);
varts1=tsfnz(e,lat1,sin1);
varsin2=Math.sin(lat2);
varcos2=Math.cos(lat2);
varms2=msfnz(e,sin2,cos2);
varts2=tsfnz(e,lat2,sin2);
varts0=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);
}
//经纬度坐标转换兰伯特坐标
functionprojCood(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);
}
varcon=Math.abs(Math.abs(lat)-HALF_PI);
varts,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){
returnnull;
}
rh1=0;
}
vartheta=ns*adjust_lon(lon-long0);
varnlon=(rh1*Math.sin(theta));
varnlat=(rh-rh1*Math.cos(theta));
return[nlon,nlat];
}
//兰伯特坐标转经纬度坐标
functioninverseProj(x1,y1){
varrh1,con,ts;
varlat,lon;
varx=x1/k0;
vary=(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;
}
vartheta=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){
returnnull;
}
}else{
lat=-HALF_PI;
}
lon=adjust_lon(theta/ns+long0);
return[lon*conv,conv*lat];
}
对于在应用中的其他坐标系转换,同样能够在其中进行代码提取。