openlayers

Get the center (or extent) for an XYZ source in Openlayers


Is is possible to get the center (or extent) of an XYZ source in Openlayers? (I am not talking about getting the center of a view, but obtaining the center of the map defined by the source itself.) The VectorSource does have a getExtent function, but unfortunately XYZ has no such method.

Using source.getTileGrid().getExtent() unfortunately does not seem to work; here is a minimal reproducible example:

<!DOCTYPE html>
<html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <script src="https://cdn.jsdelivr.net/npm/ol@v10.3.1/dist/ol.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.3.1/ol.css">
</head>
<body>
    <div id="map" class="map"></div>
    <script type="text/javascript">
        const src = new ol.source.XYZ({
            url: 'https://s3.eu-central-1.amazonaws.com/old-maps/the-hague-1944/tiles/{z}/{x}/{y}.jpg'
        })
        const ext = src.getTileGrid().getExtent();
        console.log(ext);
    </script>
</body>
</html>

(I used this map.)

This returns [-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244] as if the center was [0, 0, 0, 0]. Which is of course not the case and if I used a different map, the result was the exact same extent.


Solution

  • Your code uses the default global tile grid and will attempt to load tiles anywhere in the world at any zoom level. Unless you are ablw to run the script

    # Get the geographic coordinates of the file's left top and right bottom 
    lt = mercantile.lnglat(gt[0], gt[3])
    rb = mercantile.lnglat(gt[0] + (ds.RasterXSize * gt[1]), 
                           gt[3] + (ds.RasterYSize * gt[5]))
    

    you would need to use a test map to see where tiles are being loaded and a which zoom levels, by overlaying it with a TileDebug layer. That shows tiles are available from zoom levels 10 to 16, and at level 16 X values range from 33503 to 33583 and Y values from 21602 to 21655.

    With that information you can set up a constrained tile grid where only valid tiles should be requested:

    const tilegrid = ol.tilegrid.createXYZ({maxZoom: 16});
    const extent = ol.extent.createEmpty();
    ol.extent.extend(extent, tilegrid.getTileCoordExtent([16, 33504, 21602]))
    ol.extent.extend(extent, tilegrid.getTileCoordExtent([16, 33583, 21655]))
    
    const src =new ol.source.XYZ({
          url: 'https://s3.eu-central-1.amazonaws.com/old-maps/the-hague-1944/tiles/{z}/{x}/{y}.jpg',
          tileGrid: new ol.tilegrid.TileGrid({
            origins: tilegrid.getResolutions().map((r, i) => tilegrid.getOrigin(i)),
            resolutions: tilegrid.getResolutions(),
            tileSizes: tilegrid.getResolutions().map((r, i) => tilegrid.getTileSize(i)),
            minZoom: 10,
            extent: extent,
          })
    });
    

    The extent will be in EPSG:3857 coordinates, you could use transformExtent to convert to LonLat if you need to.