【问题标题】:Reprojection issue while trying to recode an OpenLayers function尝试重新编码 OpenLayers 函数时出现重新投影问题
【发布时间】:2019-11-29 13:42:52
【问题描述】:

由于某些库(prototype.js 和 pro4js)之间存在冲突,我需要重写 OpenLayers 的一个函数。但即使我尝试使用与他们的 github 上完全相同的代码,结果也与我在不重写函数的情况下得到的不同。

在我的例子中,想要重新编码的函数是来自ol/proj/proj4register()

这是一个使用此函数的重投影示例:

proj4.defs('EPSG:27572', "+title=NTF (Paris) / Lambert zone II +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs");
ol.proj.proj4.register(proj4);
proj = ol.proj.get('EPSG:27572');

var map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        }),
    ],
    target: 'map',
    view: new ol.View({
        projection: proj,
        center: [0, 0],
        zoom: 1
    })
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Reprojection</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/css/ol.css">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/build/ol.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
    <style>
      .map {
        width: 600px;
        height:400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
  </body>
</html>

但是如果我重新编码这个函数(根据这个来源:https://github.com/openlayers/openlayers/blob/master/src/ol/proj/proj4.js),我定义的投影对 ol 地图没有任何影响,除了完全模糊地图(但我想这是我的副作用主要问题,因为模糊地图大部分时间是由于重投影问题):

ol.proj.proj4.register = function(proj4) {
    const projCodes = Object.keys(proj4.defs);
    const len = projCodes.length;
    let i, j;
    for (i = 0; i < len; ++i) {
        const code = projCodes[i];
        if (!ol.proj.get(code)) {
            const def = proj4.defs(code);
            ol.proj.addProjection(new ol.proj.Projection({
                code: code,
                axisOrientation: def.axis,
                metersPerUnit: def.to_meter,
                units: def.units
            }));
        }
    }
    for (i = 0; i < len; ++i) {
        const code1 = projCodes[i];
        const proj1 = ol.proj.get(code1);
        for (j = 0; j < len; ++j) {
            const code2 = projCodes[j];
            const proj2 = ol.proj.get(code2);
            if (!ol.proj.getTransform(code1, code2)) {
                if (proj4.defs[code1] === proj4.defs[code2]) {
                    ol.proj.addEquivalentProjections([proj1, proj2]);
                } else {
                    const transform = proj4(code1, code2);
                    ol.proj.addCoordinateTransforms(proj1, proj2, transform.forward, transform.inverse);
                }
            }
        }
    }
}

proj4.defs('EPSG:27572', "+title=NTF (Paris) / Lambert zone II +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs");
ol.proj.proj4.register(proj4);
proj = ol.proj.get('EPSG:27572');

var map = new ol.Map({
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        }),
    ],
    target: 'map',
    view: new ol.View({
        projection: proj,
        center: [0, 0],
        zoom: 1
    })
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Reprojection</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/css/ol.css">
    <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/build/ol.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
    <style>
      .map {
        width: 600px;
        height:400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
  </body>
</html>

有人可以向我解释我哪里错了吗?当然,如果您对从库中重写函数有更好的想法,我也会喜欢它!

顺便说一句:出于好奇,我试图面对的冲突是因为prototype.js 为对象添加了额外的属性。我对这个框架知之甚少,我没有手或删除它的选择。由于函数ol.proj.proj4.register() 使用Object.keys() 检索投影代码,因此由于prototype.js,它实际上检索的远比那些代码多。当然会产生错误。

【问题讨论】:

    标签: javascript openlayers proj4js


    【解决方案1】:

    ol.proj.getTransform{get as getTransform} from './transforms.js' 不同(如果它是 API 的一部分,则为 ol.proj.transforms.get)。由于它未在公共 API 中列出,因此无法通过完整构建获得,因此您需要对正在定义的转换使用替代测试,或者干脆不费心测试并始终重新定义。

    ol.proj.proj4.register = function(proj4) {
        const projCodes = Object.keys(proj4.defs);
        const len = projCodes.length;
        let i, j;
        for (i = 0; i < len; ++i) {
            const code = projCodes[i];
            if (!ol.proj.get(code)) {
                const def = proj4.defs(code);
                ol.proj.addProjection(new ol.proj.Projection({
                    code: code,
                    axisOrientation: def.axis,
                    metersPerUnit: def.to_meter,
                    units: def.units
                }));
            }
        }
        for (i = 0; i < len; ++i) {
            const code1 = projCodes[i];
            const proj1 = ol.proj.get(code1);
            for (j = 0; j < len; ++j) {
                const code2 = projCodes[j];
                const proj2 = ol.proj.get(code2);
                //if (!ol.proj.getTransform(code1, code2)) {
                    if (proj4.defs[code1] === proj4.defs[code2]) {
                        ol.proj.addEquivalentProjections([proj1, proj2]);
                    } else {
                        const transform = proj4(code1, code2);
                        ol.proj.addCoordinateTransforms(proj1, proj2, transform.forward, transform.inverse);
                    }
                //}
            }
        }
    }
    
    proj4.defs('EPSG:27572', "+title=NTF (Paris) / Lambert zone II +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515 +towgs84=-168,-60,320,0,0,0,0 +pm=paris +units=m +no_defs");
    ol.proj.proj4.register(proj4);
    proj = ol.proj.get('EPSG:27572');
    
    var map = new ol.Map({
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            }),
        ],
        target: 'map',
        view: new ol.View({
            projection: proj,
            center: [0, 0],
            zoom: 1
        })
    });
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>Reprojection</title>
        <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/css/ol.css">
        <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/build/ol.js"></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
        <style>
          .map {
            width: 600px;
            height:400px;
          }
        </style>
      </head>
      <body>
        <div id="map" class="map"></div>
      </body>
    </html>

    【讨论】:

    • 答案被接受,就像一个魅力:) 你能解释一下你评论的测试可能是必要的情况吗?我用 orthers 预测做了一些测试,没有遇到任何问题
    • 该测试通过避免重做已经完成的工作来提高效率,因此它很有用但不是必需的。然而,OpenLayers 有一个内置的 EPSG:4326/EPSG:3857 变换,它与 proj4 变换 github.com/openlayers/openlayers/issues/9836 略有不同,因此您可能需要检查这些投影以避免覆盖它,
    猜你喜欢
    • 2019-06-09
    • 2012-08-03
    • 2015-12-26
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 2016-07-02
    相关资源
    最近更新 更多