Falcoa
Falcoa

Reputation: 2720

Difference in y value when using url vs tileUrlFunction in VectorTileSource OpenLayers

I'm using GeoServer MVT layers in OpenLayers and to add them to the map I just do:

const source = new VectorTileSource({
      url:`${geoserverUrl}/gwc/service/tms/1.0.0/myworkspace:mylayer@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf`,
      format: new MVT(),
      wrapX: true,
      tileGrid: createXYZ({ maxZoom: 19 })
    });

const layer = new VectorTileLayer({
    className: "myLayer",
    source: source,
    minResolution: 0,
    maxResolution: 2,
    style: myStyle(),
    visible: true
  });

So far so good. Now I would like to use the tileUrlFunction instead of defining the url attribute as I would like to define a different layer in the url based on the zoom level, and for that I used the following function that I called in the attribute tileUrlFunction of the new VectorTileSource instantiation:

    const tileUrlFunction = (tileCoord) => {
        if (tileCoord[0] > 18) {
          return `${geoserverUrl}/gwc/service/tms/1.0.0/myworkspace:layer1@EPSG%3A900913@pbf/${tileCoord[0]}/${tileCoord[1]}/${tileCoord[2]}.pbf`;
        } else {
return `${geoserverUrl}/gwc/service/tms/1.0.0/myworkspace:layer2@EPSG%3A900913@pbf/${tileCoord[0]}/${tileCoord[1]}/${tileCoord[2]}.pbf`;
         }   
      };
    };

The problem is that when using tileUrlFunction, on render, I get a wrong y value (corresponding to tileCoord[2]). When using ${geoserverUrl}/gwc/service/tms/1.0.0/myworkspace:mylayer@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf I get for instance the coordinates /18/258309/98012.pbf and the tile renders correctly on the map, when I use the tileUrlFunction I get the wrong y 18/2258309/164130.pbf, and the tile fails to render.

I noticed that if I don't put the dash in the y when defining the url "...@EPSG%3A900913@pbf/{z}/{x}/{-y}.pbf", I also get the same wrong value.

Reading the docs I can see that

Grids like TMS where x 0 and y 0 are in the bottom left can be used by using the {-y} placeholder in the URL template, so long as the source does not have a custom tile grid

I'm quite sure this issue is related to the definition of the tileGrid, but I don't know how to make the function tileUrlFunction to work.

Upvotes: 1

Views: 910

Answers (1)

Mike
Mike

Reputation: 17907

OpenLayers will be passing the tile coordinates for an XYZ source. To convert to TMS use

const z = tileCoord[0];
const x = tileCoord[1];
const y = Math.pow(2, z) - tileCoord[2] - 1;

Upvotes: 1

Related Questions