尝试重新编码 OpenLayers 函数时出现重投影问题

Reprojection issue while trying to recode an OpenLayers function

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

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

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

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 的那些代码更多的代码。当然会产生错误。

ol.proj.getTransform{get as getTransform} from './transforms.js' 不同(如果它是 API 的一部分,则为 ol.proj.transforms.get)。由于它未在 public 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>