Search code examples
javascriptleafletgisproj4js

Proj4Leaflet orign on custom projection


I've set up a Leaflet map using the fabulous Proj4Leaflet plugin. Within my map I'm using a custom reference system (EPSG:28533). The map tiles (WMTSCapabilities) are fetched and rendered. But I have encountered that the tiles are transformed to the wrong location. The offset is approximately +9° lat and +7° lng. I expect, that I've set the wrong origin within the definition of the reference system (fiddle).

var rs25832 = new L.Proj.CRS(
    'EPSG:25832',
    '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs', {
        origin: [
            // I suppose the error is here!
            265948.8191,
            7288831.7014
        ],
        resolutions: [
            // TileMatrixScaleDenominator * OGC_PixelWidth
            17471320.7509   * 0.00028,
            8735660.37545   * 0.00028,
            4367830.18772   * 0.00028,
            2183915.09386   * 0.00028,
            1091957.54693   * 0.00028,
            545978.773466   * 0.00028,
            272989.386733   * 0.00028,
            136494.693366   * 0.00028,
            68247.3466832   * 0.00028,
            34123.6733416   * 0.00028,
            17061.8366708   * 0.00028,
            8530.9183354    * 0.00028,
            4265.4591677    * 0.00028,
            2132.72958385   * 0.00028
        ]
    }
);

var url = 'http://sg.geodatenzentrum.de/wmts_webatlasde/tile/1.0.0/webatlasde/default/DE_EPSG_25832_ADV/{z}/{y}/{x}.png';      
var layer = L.tileLayer(url, {
        maxZoom: rs25832.options.resolutions.length,
        continuousWorld: true
    }
);

var map = L.map('map', {
    crs: rs25832,
    center: [ 50.5881112, 7.2676084 ],
    zoom: 0,
    maxZoom: rs25832.options.resolutions.length,
    layers: [ layer ]
});

map.on('click', function(e) {
    alert('lat: ' + e.latlng.lat + ' lng: ' + e.latlng.lng)
});

As far as I understood the origin setting it defines the upper left corner of the projected bounds of the refernce system. According to the spatialreference.org definition the bounds of this specific reference system are:

265948.8191, 6421521.2254, 677786.3629, 7288831.7014

Am I using the wrong approach to determine the CRS origin?


Solution

  • I've solved the issue! The problem was as expected the dermination approach of the origin property. I'd thought the origin of the reference system was supposed to equal the top left point of the projected bounds of the reference system. But I was wrong. The correct approach is to use the top left corner of the layers BBox. Based on the WMTSCapabilities of the server I was abled to calculate the projected origin using proj4js. Here is my updated code (fiddle):

    // Proj4js EPSG:25832 definition
    var proj4rs25832def = '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs';
    
    // Calc origin
    var orign = proj4(
        proj4rs25832def,
        // Upper left corner of the tile orign based on the WMTSCapabilities layer BBox
        [ 0.105946948013, 56.8478734515 ]
    );
    
    // Set resolutions
    var resolutions = [ 17471320.7509, 8735660.37545, 4367830.18772, 2183915.09386, 1091957.54693, 545978.773466, 272989.386733, 136494.693366, 68247.3466832, 34123.6733416, 17061.8366708, 8530.9183354, 4265.4591677, 2132.72958385 ];
    
    // Define CRS
    var rs25832 = new L.Proj.CRS(
        'EPSG:25832',
        proj4rs25832def, 
        {
            origin: [ orign[0], orign[1] ],
            resolutions: resolutions.map(function (value) {
                return value * 0.00028;
            })
        }
    );
    
    // Create layer
    var url = 'http://sg.geodatenzentrum.de/wmts_webatlasde/tile/1.0.0/webatlasde/default/DE_EPSG_25832_ADV/{z}/{y}/{x}.png';      
    var layer = L.tileLayer(
        url, 
        {
            continuousWorld: true,
            bounds: [[ 45.2375, 0.1059 ],[ 56.8478, 20.4488 ]],
            maxZoom: resolutions.length
        }
    );
    
    // Setup map
    var map = L.map('map', {
        crs: rs25832,
        center: [ 50.8805, 7.3389 ],
        zoom: 0,
        maxZoom: resolutions.length,
        layers: [ layer ]
    });
    
    // Setup click hander
    map.on('click', function(e) {
      alert('lat: ' + e.latlng.lat + ' lng: ' + e.latlng.lng);
      console.log(e.latlng);
    });