js兰伯特和经纬度转换(提取自proj4js)
阅读原文时间:2021年04月21日阅读:1

       技术交流群:665060698

       proj4是一个非常有用的坐标转换类库,有各种语言版本的,C++,java,js,python版等,可以很方便的将坐标从一个坐标系转换到另一个

坐标系。

       在网页端使用的时候,转换大量的坐标时,发现存在性能有问题,就查看了一下proj4js的源代码,发现初始化很多不相关的类型,对象等,

基于现有的项目,就进行相关代码的提取,以下是提取的兰伯特和经纬度坐标的转换,简略代码说明如下:

        //初始化常用的变量,直接换算成弧度,提升计算性能
        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;

//常用的转换参数,直接提取引用
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&nbsp;x&nbsp;<&nbsp;0&nbsp;?&nbsp;-1&nbsp;:&nbsp;1;
};
var&nbsp;msfnz&nbsp;=&nbsp;function(eccent,&nbsp;sinphi,&nbsp;cosphi)&nbsp;{
    var&nbsp;con&nbsp;=&nbsp;eccent&nbsp;\*&nbsp;sinphi;
    return&nbsp;cosphi&nbsp;/&nbsp;(Math.sqrt(1&nbsp;-&nbsp;con&nbsp;\*&nbsp;con));
};

var&nbsp;adjust\_lon&nbsp;=&nbsp;function(x)&nbsp;{
    return(Math.abs(x)&nbsp;<=&nbsp;SPI)&nbsp;?&nbsp;x&nbsp;:&nbsp;(x&nbsp;-&nbsp;(sign(x)&nbsp;\*&nbsp;TWO\_PI));
};

var&nbsp;phi2z&nbsp;=&nbsp;function(eccent,&nbsp;ts)&nbsp;{
    var&nbsp;eccnth&nbsp;=&nbsp;0.5&nbsp;\*&nbsp;eccent;
    var&nbsp;con,&nbsp;dphi;
    var&nbsp;phi&nbsp;=&nbsp;HALF\_PI&nbsp;-&nbsp;2&nbsp;\*&nbsp;Math.atan(ts);
    for(var&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;<=&nbsp;15;&nbsp;i++)&nbsp;{
        con&nbsp;=&nbsp;eccent&nbsp;\*&nbsp;Math.sin(phi);
        dphi&nbsp;=&nbsp;HALF\_PI&nbsp;-&nbsp;2&nbsp;\*&nbsp;Math.atan(ts&nbsp;\*&nbsp;(Math.pow(((1&nbsp;-&nbsp;con)&nbsp;/&nbsp;(1&nbsp;+&nbsp;con)),&nbsp;eccnth)))&nbsp;-&nbsp;phi;
        phi&nbsp;+=&nbsp;dphi;
        if(Math.abs(dphi)&nbsp;<=&nbsp;0.0000000001)&nbsp;{
            return&nbsp;phi;
        }
    }
    //console.log("phi2z&nbsp;has&nbsp;NoConvergence");
    return&nbsp;-9999;
};

//根据proj4的坐标系描述字符串,解析其中的参数
function&nbsp;init(prjstr)&nbsp;{
    if(prjstr.indexOf("&nbsp;")&nbsp;>&nbsp;-1)&nbsp;{
        var&nbsp;\_prjArr&nbsp;=&nbsp;prjstr.split("&nbsp;");
        \_prjArr.forEach(function(item,&nbsp;index,&nbsp;input)&nbsp;{
            if(item.indexOf("lat\_0")&nbsp;>&nbsp;-1)&nbsp;{
                lat0&nbsp;=&nbsp;parseFloat(item.split("=")\[1\])&nbsp;/&nbsp;conv;
            }
        })
    }
    var&nbsp;sin1&nbsp;=&nbsp;Math.sin(lat1);
    var&nbsp;cos1&nbsp;=&nbsp;Math.cos(lat1);
    var&nbsp;ms1&nbsp;=&nbsp;msfnz(e,&nbsp;sin1,&nbsp;cos1);
    var&nbsp;ts1&nbsp;=&nbsp;tsfnz(e,&nbsp;lat1,&nbsp;sin1);

    var&nbsp;sin2&nbsp;=&nbsp;Math.sin(lat2);
    var&nbsp;cos2&nbsp;=&nbsp;Math.cos(lat2);
    var&nbsp;ms2&nbsp;=&nbsp;msfnz(e,&nbsp;sin2,&nbsp;cos2);
    var&nbsp;ts2&nbsp;=&nbsp;tsfnz(e,&nbsp;lat2,&nbsp;sin2);

    var&nbsp;ts0&nbsp;=&nbsp;tsfnz(e,&nbsp;lat0,&nbsp;Math.sin(lat0));
    if(Math.abs(lat1&nbsp;-&nbsp;lat2)&nbsp;>&nbsp;EPSLN)&nbsp;{
        ns&nbsp;=&nbsp;Math.log(ms1&nbsp;/&nbsp;ms2)&nbsp;/&nbsp;Math.log(ts1&nbsp;/&nbsp;ts2);
    }&nbsp;else&nbsp;{
        ns&nbsp;=&nbsp;sin1;
    }
    if(isNaN(ns))&nbsp;{
        ns&nbsp;=&nbsp;sin1;
    }
    f0&nbsp;=&nbsp;ms1&nbsp;/&nbsp;(ns&nbsp;\*&nbsp;Math.pow(ts1,&nbsp;ns));
    rh&nbsp;=&nbsp;a&nbsp;\*&nbsp;f0&nbsp;\*&nbsp;Math.pow(ts0,&nbsp;ns);
}

//经纬度坐标转兰伯特坐标
function&nbsp;projCood(lon,&nbsp;lat)&nbsp;{
    lon&nbsp;=&nbsp;lon&nbsp;/&nbsp;conv;
    lat&nbsp;=&nbsp;lat&nbsp;/&nbsp;conv;
    if(Math.abs(2&nbsp;\*&nbsp;Math.abs(lat)&nbsp;-&nbsp;Math.PI)&nbsp;<=&nbsp;EPSLN)&nbsp;{
        lat&nbsp;=&nbsp;sign(lat)&nbsp;\*&nbsp;(HALF\_PI&nbsp;-&nbsp;2&nbsp;\*&nbsp;EPSLN);
    }
    var&nbsp;con&nbsp;=&nbsp;Math.abs(Math.abs(lat)&nbsp;-&nbsp;HALF\_PI);
    var&nbsp;ts,&nbsp;rh1;
    if(con&nbsp;>&nbsp;EPSLN)&nbsp;{
        ts&nbsp;=&nbsp;tsfnz(e,&nbsp;lat,&nbsp;Math.sin(lat));
        rh1&nbsp;=&nbsp;a&nbsp;\*&nbsp;f0&nbsp;\*&nbsp;Math.pow(ts,&nbsp;ns);
    }&nbsp;else&nbsp;{
        con&nbsp;=&nbsp;lat&nbsp;\*&nbsp;ns;
        if(con&nbsp;<=&nbsp;0)&nbsp;{
            return&nbsp;null;
        }
        rh1&nbsp;=&nbsp;0;
    }
    var&nbsp;theta&nbsp;=&nbsp;ns&nbsp;\*&nbsp;adjust\_lon(lon&nbsp;-&nbsp;long0);
    var&nbsp;nlon&nbsp;=&nbsp;(rh1&nbsp;\*&nbsp;Math.sin(theta));
    var&nbsp;nlat&nbsp;=&nbsp;(rh&nbsp;-&nbsp;rh1&nbsp;\*&nbsp;Math.cos(theta));

    return&nbsp;\[nlon,&nbsp;nlat\];
}

//兰伯特坐标转经纬度坐标
function&nbsp;inverseProj(x1,&nbsp;y1)&nbsp;{
    var&nbsp;rh1,&nbsp;con,&nbsp;ts;
    var&nbsp;lat,&nbsp;lon;
    var&nbsp;x&nbsp;=&nbsp;x1&nbsp;/&nbsp;k0;
    var&nbsp;y&nbsp;=&nbsp;(rh&nbsp;-&nbsp;y1&nbsp;/&nbsp;k0);
    if(ns&nbsp;>&nbsp;0)&nbsp;{
        rh1&nbsp;=&nbsp;Math.sqrt(x&nbsp;\*&nbsp;x&nbsp;+&nbsp;y&nbsp;\*&nbsp;y);
        con&nbsp;=&nbsp;1;
    }&nbsp;else&nbsp;{
        rh1&nbsp;=&nbsp;-Math.sqrt(x&nbsp;\*&nbsp;x&nbsp;+&nbsp;y&nbsp;\*&nbsp;y);
        con&nbsp;=&nbsp;-1;
    }
    var&nbsp;theta&nbsp;=&nbsp;0;
    if(rh1&nbsp;!==&nbsp;0)&nbsp;{
        theta&nbsp;=&nbsp;Math.atan2((con&nbsp;\*&nbsp;x),&nbsp;(con&nbsp;\*&nbsp;y));
    }
    if((rh1&nbsp;!==&nbsp;0)&nbsp;||&nbsp;(ns&nbsp;>&nbsp;0))&nbsp;{
        con&nbsp;=&nbsp;1&nbsp;/&nbsp;ns;
        ts&nbsp;=&nbsp;Math.pow((rh1&nbsp;/&nbsp;(a&nbsp;\*&nbsp;f0)),&nbsp;con);
        lat&nbsp;=&nbsp;phi2z(e,&nbsp;ts);
        if(lat&nbsp;===&nbsp;-9999)&nbsp;{
            return&nbsp;null;
        }
    }&nbsp;else&nbsp;{
        lat&nbsp;=&nbsp;-HALF\_PI;
    }
    lon&nbsp;=&nbsp;adjust\_lon(theta&nbsp;/&nbsp;ns&nbsp;+&nbsp;long0);

    return&nbsp;\[lon&nbsp;\*&nbsp;conv,&nbsp;conv&nbsp;\*&nbsp;lat\];
}

转载于:https://blog.51cto.com/speciallst/2128540