kartena / Proj4Leaflet

Smooth Proj4js integration with Leaflet.
http://kartena.github.io/Proj4Leaflet/
BSD 2-Clause "Simplified" License
587 stars 172 forks source link

Tiles near the antemeridian aren't being fetched in EPSG:3338 #149

Closed brucecrevensten closed 7 years ago

brucecrevensten commented 7 years ago

Hi and thanks for all your great work on this plugin! It's been indispensable for my recent work on Arctic-focused web maps.

Leaflet 1.0.3, Proj4js 2.4.3, Proj4Leaflet 1.0.1, trying to render a WMS layer in EPSG:3338 (Alaska Albers); here's an online example demonstrating this behavior. Backend tile source is rendered via a GeoServer cascaded layer to MapProxy/Mapnik/OSM stack configured to emit tiles in the correct projection.

This was working OK with Leaflet ~0.7.x, Proj4js ~2.3.12, Proj4Leaflet ~0.7.1.

The issue appears to be that some tiles aren't getting fetched (they appear as gray tiles as opposed to things outside the scope of the map which are white).

Tried setting noWrap: true on the layer, didn't help.

For what it's worth, I'm also working on a map in the EPSG:3572, and I see this issue (including others, which I'll investigate after clearing this up) there as well.

I'd be glad to try and diagnose what's going on here, but I'm not sure how to proceed.

perliedman commented 7 years ago

Hm, yes something weird going on there.

The tile that isn't loading uses this URL: http://54.70.10.93:8080/geoserver/wms?service=WMS&request=GetMap&layers=alaska_osm&styles=&format=image%2Fpng&transparent=true&version=1.3&srs=EPSG%3A3338&continuousWorld=true&height=256&width=256&crs=EPSG%3A3338&bbox=-460438.7320643104,2318778.9730571406,-1193982.5553407527,2426803.3833586057 - which returns an error since the bbox is out of bounds

The tile just below it (same column, next row) uses this URL: http://54.70.10.93:8080/geoserver/wms?service=WMS&request=GetMap&layers=alaska_osm&styles=&format=image%2Fpng&transparent=true&version=1.3&srs=EPSG%3A3338&continuousWorld=true&height=256&width=256&crs=EPSG%3A3338&bbox=-1048575.999999998,1572863.9999999995,-524288.0000000007,2097152.000000009

To my surprise, those two URLs' bounding boxes does not share a single coordinate, which clearly is weird since they're in the same column (should be same x coordinates).

I don't have time to have a closer look right now, but I would step through Leaflet's WMS code and see how the bbox for the top left tile is generated, I would guess some kind of wrapping or rounding takes place that shouldn't.

MacAndrews21 commented 7 years ago

Hi everybody, I had similar problems with updating my code from Leaflet 0.7.7 to 1.03 (now 1.1.0), but in the arctic [EPSG:3995] and antarctic [EPSG:3031] region. In the 0.7.7 both was displayed right, but in 1.0.3 and 1.1.0 it isn't. Here some screenshots: 0.7.7: epsg3995-leaflet-0 7 7 1.0.3 and 1.1.0: at zoom 0: epsg3995-leaflet-1 0 3-zoom-0 at zoom 1: epsg3995-leaflet-1 0 3-zoom-1

And here is how I define the projection:

L.CRS.EPSG3995 = new L.Proj.CRS('EPSG:3995', '+proj=stere +lat_0=90 +lat_ts=71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'
    , { origin: [ -1, -1 ]
    , resolutions: [ 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5]               
    }
);

I ask @perliedman and he sends me the link to this issue and gives me the hint that the problem could be the way the tile requests are created. So, I dive into the code from Leaflet and compare both versions. I found the difference and try to overwrite the 'L.TileLayer.WMS.getTileUrl()' function from 1.0.0 with the one from 0.7.7 and it works. Here is my overwrite function:

L.TileLayer.WMS.prototype.getTileUrl = function (tilePoint) { // (Point, Number) -> String

    var map = this._map,
        tileSize = this.options.tileSize,

        nwPoint = tilePoint.multiplyBy(tileSize),
        sePoint = nwPoint.add([tileSize, tileSize]),

        nw = this._crs.project(map.unproject(nwPoint, tilePoint.z)),
        se = this._crs.project(map.unproject(sePoint, tilePoint.z)),
        bbox = this._wmsVersion >= 1.3 && this._crs === L.CRS.EPSG4326 ?
            [se.y, nw.x, nw.y, se.x].join(',') :
            [nw.x, se.y, se.x, nw.y].join(','),

        url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)});

    return url + L.Util.getParamString(this.wmsParams, url, true) + '&BBOX=' + bbox;
};

Not the best way, but it works. Sorrily, I can't find the time to fix it properly, but maybe this gives someone else an idea.

cheers!

P.S.: It still doesn't works for EPSG:102017 and EPSG:102020, which both are working in Leaflet 0.7.7. And since Leaflet 1.0.3 there are tiny gaps between the wms tiles in some zoom levels, sometimes.

perliedman commented 7 years ago

I think the problem is that the old code, despite variable naming, did not care which corner was north, south, east or west, but made calculations based on tiles min/max coordinates. The new code, by going through LatLngBounds, assumes that southwest will always be the minimum projected coordinate, which isn't necessarily true, especially not for polar projections.

Anyway, this isn't a Proj4Leaflet issue, it's a problem in Leaflet itself, so we'll have to open a new issue there.

perliedman commented 7 years ago

See https://github.com/Leaflet/Leaflet/issues/5617 and hopefully a fix in https://github.com/Leaflet/Leaflet/issues/5618.

Closing, since not a Proj4Leaflet issue.