OpenLayers 3 – How to Arrange Your Own Tiles Without Projection

extentsopenlayersresolution

I have own tiles (.png) of 512×512 pixels and I would like to display them in OpenLayers 3 without projection (for now). Therefore I found a way to use the ZOOMIFY projection but with a "ol.layer.Tile"-Layer.
(original source: https://groups.google.com/forum/#!topic/ol3-dev/VVdNXHwiZEk)

So far it works more or less, but I am encountering problems providing the right extent of the layer.
I have a map DIV of 1024×512 pixels and strangely for zoom level 0: only the left tile is displayed (the right one is missing).

Zoom level 0 has a resolution of 2 (check the variable resolutions) and therefore I thought that I need an extent of 2048(x) and 1024(y) to display 2 tiles of zoom level 0. [1][2]

My guess is that the provided extent causes the problems.

Any ideas how to improve on this?

Here's a jsfiddle: http://jsfiddle.net/vb53xz20/

[1]tile1: services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/0/0/0.png

[2]tile2: services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/0/0/1.png

And the code:

tileSize = 512;

projection = new ol.proj.Projection({
    code: 'ZOOMIFY',
    units: 'pixels',
    extent: [0, 0, 1024, 1024]
});

projectionExtent = projection.getExtent();

var maxResolution = ol.extent.getWidth(projectionExtent) / tileSize;
window.resolutions = [];
for (var z = 0; z <= 10; z++) {
    resolutions[z] = maxResolution / Math.pow(2, z);

}

urlTemplate = 'http://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}';

tileLayer = new ol.layer.Tile({
    source: new ol.source.TileImage({
        tileUrlFunction: function(tileCoord, pixelRatio, projection) {
            tileCoordGlobal = tileCoord;

            return urlTemplate
                .replace('{z}', (tileCoord[0]).toString())
                .replace('{x}', (tileCoord[1]).toString())
                .replace('{y}', (((-tileCoord[2])-1)).toString())
            ;
        },
        wrapX: true,
        projection: projection,
        tileGrid: new ol.tilegrid.TileGrid({
            origin: ol.extent.getTopLeft(projectionExtent),
            resolutions: resolutions,
            tileSize: tileSize
        }),
    }),
    extent: projectionExtent        
});

view = new ol.View ({
    projection: projection,
    center: [1024, 512],
    extent: projectionExtent,
    zoom: 0,
    resolutions: resolutions
});

window.map = new ol.Map({
    layers: [tileLayer],
    target: 'map',
    view: view
});

Best Answer

Alrighty, I finally found out how to set the parameters. The problems were due to the resolution and the extent arrays.

I) The resolution array needed a "z+1" instead of "z":

for (var z = 0; z <= 16; z++) {
    resolutions[z] = maxResolution / Math.pow(2, z+1);
}

(btw: the number of z in the for-loop defines the number of available zoom levels)


II) And the extent array some adaptions.

The 4 values of the extent array are: [MinX, MinY, MaxX, MaxY]. We can start with 0s for both min-values. The max values depend on:

a) the number of tiles
b) the resolutions
c) the tilesize

I found that this formula worked well for my purposes:
MaxX(MaxY) = No of tiles x resolution[0] x tilesize

For the example above this would mean:

MaxX = 2 x 2 x 512 = 2048
MaxY = 1 x 2 x 512 = 1024

var minX = 0;
var minY = 0;
var maxX = 2048;
var maxY = 1024;

extent: [minX, minY, maxX, maxY]


III) The center can be set to [MaxX/2, MaxY/2]

center: [maxX/2, maxY/2]


Here is the updated jsfiddle: http://jsfiddle.net/vb53xz20/2/

Related Question