javascriptgismapbox-gl-jswmssatellite-image

How do I use Lantmäteriet's satellite images over Sweden in MapBox GL JS?


I've spent so many hours over many months (on and off) trying to figure out how to get this to work. It never works, yet I highly suspect that the solution is very simple.

I use MapBox GL JS with the MapBox.com satellite images. These are very poor, at least for Sweden. So, since Lantmäteriet (official governmental body) has much better satellites photos, I want to integrate those into my map system instead (for Sweden). The URL to look at their map is: https://minkarta.lantmateriet.se/?e=633856&n=6596096&z=3&profile=flygbild&background=2&boundaries=false

I have very carefully studied these among many more pages:

https://docs.mapbox.com/mapbox-gl-js/example/wms/

https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/

The image slices produced by Lantmäteriet's web application are in this format:

https://minkarta.lantmateriet.se/map/ortofoto/?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=false&LAYERS=Ortofoto_0.5%2COrtofoto_0.4%2COrtofoto_0.25%2COrtofoto_0.16&TILED=true&STYLES=&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3006&BBOX=675968%2C6640416%2C684160%2C6648608

I have tried numerous things related to modifying that URL to use it like this (with many changes to the tiles URL):

// https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addsource
map.addSource('wms-test-source',
{
    'type': 'raster',
    'tiles': [
        'https://minkarta.lantmateriet.se/map/ortofoto/?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=false&LAYERS=Ortofoto_0.5%2COrtofoto_0.4%2COrtofoto_0.25%2COrtofoto_0.16&TILED=true&STYLES=&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3006&bbox={bbox-epsg-3006}'
    ],
    'tileSize': 256
});

// https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addlayer
map.addLayer(
{
    'id': 'wms-test-layer',
    'type': 'raster',
    'source': 'wms-test-source',
    'paint': {}
}
//, 'aeroway-line'
);

I've of course removed the "&BBOX=" stuff, added &bbox=%7Bbbox-epsg-3006%7D (and &bbox={bbox-epsg-3006}), etc. Nothing makes it work. The satellites images don't show up, all show the same image, or the server returns various HTTP errors, clearly because it doesn't understand how MapBox GL JS is trying to fetch them.

Something needs to be added for it to understand the format, but I don't get what.

If this is related to the difference between the coordinate systems used, I already have got help with that (for a different problem in my application) through this code:

proj4.defs("EPSG:3006","+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"); // SWEREF 99 TM
var epsg3006 = proj4("EPSG:3006");
var projCoords = proj4(epsg3006, [ longitud, latitud ]);

projCoords[0] and projCoords[1] now contain verified correct coordinates that Lantmäteriet's map wants. But that doesn't help me in this case... or does it? I don't see how since I'm not actually specifying any coordinates in any manner for this URL.

This is for my personal use only, so I'm not trying to abuse their webserver for my own commercial gain or anything. I'd like to avoid contacting them if possible, because I think anything sent to them is made public, and I'm trying to preserve some amount of privacy. Besides, I don't really think that they would be able to help me any more than you all could. I'd say it's unlikely that they even have thought of somebody using their data at all.

In fact, I already ruled out several other, non-governmental, for-profit services which seem to have a completely proprietary, non-standard mechanism for fetching the satellite images which doesn't seem to follow any kind of known/public standard. That's why I picked this one, which is both "public service" and appears to use something which could be used by my map system without jumping through a bunch of hoops.

Would really appreciate if somebody could tell me what I need to do to instruct it how to use those images.

UPDATE

After reading the answer (which was informative and good), I felt sad, but still tried &bbox={bbox-epsg-3857} for the URL, like this: https://minkarta.lantmateriet.se/map/ortofoto/?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=false&LAYERS=Ortofoto_0.5%2COrtofoto_0.4%2COrtofoto_0.25%2COrtofoto_0.16&TILED=true&STYLES=&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3006&bbox={bbox-epsg-3857}

When I started my application, the entire map soon became 100% white/blank. I thought "oh, well...", but still zoomed out... and kept zooming out... and was surprised to see that the entire country of Sweden was on the blank world map, internally consistent and possible to zoom in all the way with perfect detail, but offset to the left and down, so that it appears to be located near Germany instead!

Very bizarre.

Is there some obvious reason why this would happen? The weird part is that it looks right; it's not just a big mess of tiles that don't fit together. Maybe I can simply "correct" the layer somehow to have it replaced in the right position?

enter image description here


Solution

  • I think most likely your problem is projection related.

    You are fetching data in projection EPSG:3006 (SWEREF99). Mapbox only supports fetching tiles in EPSG:3857 (Web Mercator):

    By providing a URL to a WMS server that supports EPSG:3857 (or EPSG:900913) as a source of tiled data. The server URL should contain a "{bbox-epsg-3857}" replacement token to supply the bbox parameter.

    (EPSG:900913 is a very old designation for EPSG:3857)

    You've tried putting {bbox-epsg-3006} in your URL, but that's actually a substitution token that Mapbox GL JS doesn't recognise, so nothing will get substituted, and therefore the server won't know what tile to send back.

    So, either:

    You can find out what projections a server supports by using the GetCapabilities WMS request:

    It looks like it does support EPSG:3857:

    <Title>Visningstjänst ortofoton</Title>
        <SRS>epsg:3006</SRS>
        <SRS>epsg:3007</SRS>
        <SRS>epsg:3008</SRS>
        <SRS>epsg:3009</SRS>
        <SRS>epsg:3010</SRS>
        <SRS>epsg:3011</SRS>
        <SRS>epsg:3012</SRS>
        <SRS>epsg:3013</SRS>
        <SRS>epsg:3014</SRS>
        <SRS>epsg:3015</SRS>
        <SRS>epsg:3016</SRS>
        <SRS>epsg:3017</SRS>
        <SRS>epsg:3018</SRS>
        <SRS>epsg:3021</SRS>
        <SRS>epsg:3034</SRS>
        <SRS>epsg:3035</SRS>
        <SRS>epsg:3044</SRS>
        <SRS>epsg:3045</SRS>
        <SRS>epsg:3046</SRS>
        <SRS>epsg:3047</SRS>
        <SRS>epsg:3857</SRS>
        <SRS>epsg:4258</SRS>
        <SRS>epsg:4326</SRS>
        <SRS>epsg:4619</SRS>
        <SRS>epsg:25832</SRS>
        <SRS>epsg:25833</SRS>
        <SRS>epsg:25834</SRS>
        <SRS>epsg:25835</SRS>
        <SRS>epsg:32632</SRS>
        <SRS>epsg:32633</SRS>
        <SRS>epsg:32634</SRS>
        <SRS>epsg:32635</SRS>