Merge pull request #1533 from twpayne/vector-api-tile-hidpi

[vector-api] HiDPI support for tile layers
This commit is contained in:
Tom Payne
2014-01-16 06:55:54 -08:00
16 changed files with 207 additions and 100 deletions

View File

@@ -18,7 +18,7 @@ var projection = ol.proj.configureProj4jsProjection({
var extent = [420000, 30000, 900000, 350000];
var layers = [
new ol.layer.Tile({
source: new ol.source.TileWMS({
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous',
attributions: [new ol.Attribution({
@@ -31,11 +31,12 @@ var layers = [
'LAYERS': 'ch.swisstopo.pixelkarte-farbe-pk1000.noscale',
'FORMAT': 'image/jpeg'
},
extent: extent
})
extent: extent,
serverType: 'mapserver'
}))
}),
new ol.layer.Tile({
source: new ol.source.TileWMS({
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
url: 'http://wms.geo.admin.ch/',
crossOrigin: 'anonymous',
attributions: [new ol.Attribution({
@@ -45,8 +46,9 @@ var layers = [
'National parks / geo.admin.ch</a>'
})],
params: {'LAYERS': 'ch.bafu.schutzgebiete-paerke_nationaler_bedeutung'},
extent: extent
})
extent: extent,
serverType: 'mapserver'
}))
})
];

View File

@@ -11,11 +11,12 @@ var layers = [
source: new ol.source.MapQuest({layer: 'sat'})
}),
new ol.layer.Tile({
source: new ol.source.TileWMS({
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
url: 'http://demo.opengeo.org/geoserver/wms',
params: {'LAYERS': 'topp:states', 'TILED': true},
extent: [-13884991, 2870341, -7455066, 6338219]
})
extent: [-13884991, 2870341, -7455066, 6338219],
serverType: 'geoserver'
}))
})
];
var map = new ol.Map({

View File

@@ -755,10 +755,15 @@
* edges" issues by properly configuring the WMS service. For example, MapServer
* has a `tile_map_edge_buffer` configuration parameter for this. See
* http://mapserver.org/output/tile_mode.html.
* @property {boolean|undefined} hidpi Use the `ol.Map#pixelRatio` value when
* requesting the image from the remote server. Default is `true`.
* @property {string|undefined} logo Logo.
* @property {ol.tilegrid.TileGrid|undefined} tileGrid Tile grid.
* @property {number|undefined} maxZoom Maximum zoom.
* @property {ol.proj.ProjectionLike} projection Projection.
* @property {ol.source.wms.ServerType|undefined} serverType The type of the remote WMS
* server: `mapserver`, `geoserver` or `qgis`. Only needed if `hidpi` is `true`.
* Default is `undefined`.
* @property {ol.TileLoadFunctionType|undefined} tileLoadFunction Optional
* function to load a tile given a URL.
* @property {string|undefined} url WMS service URL.

View File

@@ -164,6 +164,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
// composition and positioning.
//
var pixelRatio = frameState.pixelRatio;
var view2DState = frameState.view2DState;
var projection = view2DState.projection;
@@ -171,14 +172,14 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
goog.asserts.assertInstanceof(tileLayer, ol.layer.Tile);
var tileSource = tileLayer.getSource();
goog.asserts.assertInstanceof(tileSource, ol.source.Tile);
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var tileGrid = tileSource.getTileGridForProjection(projection);
var tileGutter = tileSource.getGutter();
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileSize = tileGrid.getTileSize(z);
var tilePixelSize =
tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
var tilePixelRatio = tilePixelSize / tileGrid.getTileSize(z);
var tileResolution = tileGrid.getResolution(z);
var tilePixelResolution = tileResolution / tilePixelRatio;
var center = view2DState.center;
var extent;
if (tileResolution == view2DState.resolution) {
@@ -191,8 +192,8 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var tileRange = tileGrid.getTileRangeForExtentAndResolution(
extent, tileResolution);
var canvasWidth = tileSize * tileRange.getWidth();
var canvasHeight = tileSize * tileRange.getHeight();
var canvasWidth = tilePixelSize * tileRange.getWidth();
var canvasHeight = tilePixelSize * tileRange.getHeight();
var canvas, context;
if (goog.isNull(this.canvas_)) {
@@ -231,8 +232,8 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var canvasTileRange, canvasTileRangeWidth, minX, minY;
if (goog.isNull(this.renderedCanvasTileRange_)) {
canvasTileRangeWidth = canvasWidth / tileSize;
var canvasTileRangeHeight = canvasHeight / tileSize;
canvasTileRangeWidth = canvasWidth / tilePixelSize;
var canvasTileRangeHeight = canvasHeight / tilePixelSize;
minX = tileRange.minX -
Math.floor((canvasTileRangeWidth - tileRange.getWidth()) / 2);
minY = tileRange.minY -
@@ -261,7 +262,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
}, tileSource, projection);
}, tileSource, pixelRatio, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, getTileIfLoaded);
@@ -271,7 +272,7 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tile = tileSource.getTile(z, x, y, projection);
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
tileState = tile.getState();
if (tileState == ol.TileState.LOADED ||
tileState == ol.TileState.EMPTY ||
@@ -299,9 +300,9 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var i, ii;
for (i = 0, ii = tilesToClear.length; i < ii; ++i) {
tile = tilesToClear[i];
x = tileSize * (tile.tileCoord.x - canvasTileRange.minX);
y = tileSize * (canvasTileRange.maxY - tile.tileCoord.y);
context.clearRect(x, y, tileSize, tileSize);
x = tilePixelSize * (tile.tileCoord.x - canvasTileRange.minX);
y = tilePixelSize * (canvasTileRange.maxY - tile.tileCoord.y);
context.clearRect(x, y, tilePixelSize, tilePixelSize);
}
/** @type {Array.<number>} */
@@ -316,7 +317,8 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
var height, width;
for (i = 0, ii = zs.length; i < ii; ++i) {
currentZ = zs[i];
tileSize = tileGrid.getTileSize(currentZ);
tilePixelSize =
tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
tilesToDraw = tilesToDrawByZ[currentZ];
if (currentZ == z) {
for (tileCoordKey in tilesToDraw) {
@@ -325,18 +327,18 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
(tile.tileCoord.y - canvasTileRange.minY) * canvasTileRangeWidth +
(tile.tileCoord.x - canvasTileRange.minX);
if (this.renderedTiles_[index] != tile) {
x = tileSize * (tile.tileCoord.x - canvasTileRange.minX);
y = tileSize * (canvasTileRange.maxY - tile.tileCoord.y);
x = tilePixelSize * (tile.tileCoord.x - canvasTileRange.minX);
y = tilePixelSize * (canvasTileRange.maxY - tile.tileCoord.y);
tileState = tile.getState();
if (tileState == ol.TileState.EMPTY ||
tileState == ol.TileState.ERROR ||
!opaque) {
context.clearRect(x, y, tileSize, tileSize);
context.clearRect(x, y, tilePixelSize, tilePixelSize);
}
if (tileState == ol.TileState.LOADED) {
context.drawImage(tile.getImage(),
tileGutter, tileGutter, tileSize, tileSize,
x, y, tileSize, tileSize);
tileGutter, tileGutter, tilePixelSize, tilePixelSize,
x, y, tilePixelSize, tilePixelSize);
}
this.renderedTiles_[index] = tile;
}
@@ -346,17 +348,17 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
for (tileCoordKey in tilesToDraw) {
tile = tilesToDraw[tileCoordKey];
tileExtent = tileGrid.getTileCoordExtent(tile.tileCoord, tmpExtent);
x = (tileExtent[0] - origin[0]) / tileResolution;
y = (origin[1] - tileExtent[3]) / tileResolution;
width = scale * tileSize;
height = scale * tileSize;
x = (tileExtent[0] - origin[0]) / tilePixelResolution;
y = (origin[1] - tileExtent[3]) / tilePixelResolution;
width = scale * tilePixelSize;
height = scale * tilePixelSize;
tileState = tile.getState();
if (tileState == ol.TileState.EMPTY || !opaque) {
context.clearRect(x, y, width, height);
}
if (tileState == ol.TileState.LOADED) {
context.drawImage(tile.getImage(),
tileGutter, tileGutter, tileSize, tileSize,
tileGutter, tileGutter, tilePixelSize, tilePixelSize,
x, y, width, height);
}
interimTileRange =
@@ -377,19 +379,18 @@ ol.renderer.canvas.TileLayer.prototype.prepareFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
this.manageTilePyramid(frameState, tileSource, tileGrid, projection, extent,
z, tileLayer.getPreload());
this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,
projection, extent, z, tileLayer.getPreload());
this.scheduleExpireCache(frameState, tileSource);
this.updateLogos(frameState, tileSource);
var pixelRatio = frameState.pixelRatio;
ol.vec.Mat4.makeTransform2D(this.imageTransform_,
pixelRatio * frameState.size[0] / 2,
pixelRatio * frameState.size[1] / 2,
pixelRatio * tileResolution / view2DState.resolution,
pixelRatio * tileResolution / view2DState.resolution,
pixelRatio * tilePixelResolution / view2DState.resolution,
pixelRatio * tilePixelResolution / view2DState.resolution,
view2DState.rotation,
(origin[0] - center[0]) / tileResolution,
(center[1] - origin[1]) / tileResolution);
(origin[0] - center[0]) / tilePixelResolution,
(center[1] - origin[1]) / tilePixelResolution);
};

View File

@@ -81,6 +81,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
return;
}
var pixelRatio = frameState.pixelRatio;
var view2DState = frameState.view2DState;
var projection = view2DState.projection;
@@ -88,10 +89,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
goog.asserts.assertInstanceof(tileLayer, ol.layer.Tile);
var tileSource = tileLayer.getSource();
goog.asserts.assertInstanceof(tileSource, ol.source.Tile);
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var tileGrid = tileSource.getTileGridForProjection(projection);
var tileGutter = tileSource.getGutter();
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileResolution = tileGrid.getResolution(z);
@@ -113,7 +111,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED;
}, tileSource, projection);
}, tileSource, pixelRatio, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, getTileIfLoaded);
@@ -123,7 +121,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tile = tileSource.getTile(z, x, y, projection);
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
tileState = tile.getState();
if (tileState == ol.TileState.LOADED) {
tilesToDrawByZ[z][tile.tileCoord.toString()] = tile;
@@ -241,8 +239,8 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame =
}
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
this.manageTilePyramid(frameState, tileSource, tileGrid, projection, extent,
z, tileLayer.getPreload());
this.manageTilePyramid(frameState, tileSource, tileGrid, pixelRatio,
projection, extent, z, tileLayer.getPreload());
this.scheduleExpireCache(frameState, tileSource);
this.updateLogos(frameState, tileSource);
@@ -339,8 +337,12 @@ ol.renderer.dom.TileLayerZ_.prototype.addTile = function(tile, tileGutter) {
imageStyle.position = 'absolute';
imageStyle.left = -tileGutter + 'px';
imageStyle.top = -tileGutter + 'px';
imageStyle.width = (tileSize + 2 * tileGutter) + 'px';
imageStyle.height = (tileSize + 2 * tileGutter) + 'px';
goog.dom.appendChild(tileElement, image);
} else {
imageStyle.width = tileSize + 'px';
imageStyle.height = tileSize + 'px';
tileElement = image;
tileElementStyle = imageStyle;
}

View File

@@ -197,13 +197,14 @@ ol.renderer.Layer.prototype.updateUsedTiles =
* @param {function(ol.Tile): boolean} isLoadedFunction Function to
* determine if the tile is loaded.
* @param {ol.source.Tile} tileSource Tile source.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @protected
* @return {function(number, number, number): ol.Tile} Returns a tile if it is
* loaded.
*/
ol.renderer.Layer.prototype.createGetTileIfLoadedFunction =
function(isLoadedFunction, tileSource, projection) {
function(isLoadedFunction, tileSource, pixelRatio, projection) {
return (
/**
* @param {number} z Z.
@@ -212,7 +213,7 @@ ol.renderer.Layer.prototype.createGetTileIfLoadedFunction =
* @return {ol.Tile} Tile.
*/
function(z, x, y) {
var tile = tileSource.getTile(z, x, y, projection);
var tile = tileSource.getTile(z, x, y, pixelRatio, projection);
return isLoadedFunction(tile) ? tile : null;
});
};
@@ -244,6 +245,7 @@ ol.renderer.Layer.prototype.snapCenterToPixel =
* @param {ol.FrameState} frameState Frame state.
* @param {ol.source.Tile} tileSource Tile source.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @param {ol.Extent} extent Extent.
* @param {number} currentZ Current Z.
@@ -254,8 +256,8 @@ ol.renderer.Layer.prototype.snapCenterToPixel =
* @template T
*/
ol.renderer.Layer.prototype.manageTilePyramid = function(
frameState, tileSource, tileGrid, projection, extent, currentZ, preload,
opt_tileCallback, opt_this) {
frameState, tileSource, tileGrid, pixelRatio, projection, extent,
currentZ, preload, opt_tileCallback, opt_this) {
var tileSourceKey = goog.getUid(tileSource).toString();
if (!(tileSourceKey in frameState.wantedTiles)) {
frameState.wantedTiles[tileSourceKey] = {};
@@ -270,7 +272,7 @@ ol.renderer.Layer.prototype.manageTilePyramid = function(
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
if (currentZ - z <= preload) {
tile = tileSource.getTile(z, x, y, projection);
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
if (tile.getState() == ol.TileState.IDLE) {
wantedTiles[tile.tileCoord.toString()] = true;
if (!tileQueue.isKeyQueued(tile.getKey())) {

View File

@@ -473,10 +473,11 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
layerRenderer.prepareFrame(frameState, layerState);
}
var size = frameState.size;
if (this.canvas_.width != size[0] || this.canvas_.height != size[1]) {
this.canvas_.width = size[0];
this.canvas_.height = size[1];
var width = frameState.size[0] * frameState.pixelRatio;
var height = frameState.size[1] * frameState.pixelRatio;
if (this.canvas_.width != width || this.canvas_.height != height) {
this.canvas_.width = width;
this.canvas_.height = height;
}
gl.bindFramebuffer(goog.webgl.FRAMEBUFFER, null);

View File

@@ -121,14 +121,14 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
goog.asserts.assertInstanceof(tileLayer, ol.layer.Tile);
var tileSource = tileLayer.getSource();
goog.asserts.assertInstanceof(tileSource, ol.source.Tile);
var tileGrid = tileSource.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
}
var tileGrid = tileSource.getTileGridForProjection(projection);
var z = tileGrid.getZForResolution(view2DState.resolution);
var tileResolution = tileGrid.getResolution(z);
var tileSize = tileGrid.getTileSize(z);
var tilePixelSize =
tileSource.getTilePixelSize(z, frameState.pixelRatio, projection);
var pixelRatio = tilePixelSize / tileGrid.getTileSize(z);
var tilePixelResolution = tileResolution / pixelRatio;
var tileGutter = tileSource.getGutter();
var center = view2DState.center;
@@ -152,13 +152,13 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
var tileRangeSize = tileRange.getSize();
var maxDimension =
Math.max(tileRangeSize[0] * tileSize, tileRangeSize[1] * tileSize);
var maxDimension = Math.max(
tileRangeSize[0] * tilePixelSize, tileRangeSize[1] * tilePixelSize);
var framebufferDimension = ol.math.roundUpToPowerOfTwo(maxDimension);
var framebufferExtentDimension = tileResolution * framebufferDimension;
var framebufferExtentDimension = tilePixelResolution * framebufferDimension;
var origin = tileGrid.getOrigin(z);
var minX = origin[0] + tileRange.minX * tileSize * tileResolution;
var minY = origin[1] + tileRange.minY * tileSize * tileResolution;
var minX = origin[0] + tileRange.minX * tilePixelSize * tilePixelResolution;
var minY = origin[1] + tileRange.minY * tilePixelSize * tilePixelResolution;
framebufferExtent = [
minX, minY,
minX + framebufferExtentDimension, minY + framebufferExtentDimension
@@ -196,7 +196,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
var getTileIfLoaded = this.createGetTileIfLoadedFunction(function(tile) {
return !goog.isNull(tile) && tile.getState() == ol.TileState.LOADED &&
mapRenderer.isTileTextureLoaded(tile);
}, tileSource, projection);
}, tileSource, pixelRatio, projection);
var findLoadedTiles = goog.bind(tileSource.findLoadedTiles, tileSource,
tilesToDrawByZ, getTileIfLoaded);
@@ -207,7 +207,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
tile = tileSource.getTile(z, x, y, projection);
tile = tileSource.getTile(z, x, y, pixelRatio, projection);
tileState = tile.getState();
if (tileState == ol.TileState.LOADED) {
if (mapRenderer.isTileTextureLoaded(tile)) {
@@ -254,8 +254,8 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
framebufferExtentDimension - 1;
goog.vec.Vec4.setFromValues(u_tileOffset, sx, sy, tx, ty);
gl.uniform4fv(this.locations_.u_tileOffset, u_tileOffset);
mapRenderer.bindTileTexture(tile, tileSize, tileGutter,
goog.webgl.LINEAR, goog.webgl.LINEAR);
mapRenderer.bindTileTexture(tile, tilePixelSize,
tileGutter * pixelRatio, goog.webgl.LINEAR, goog.webgl.LINEAR);
gl.drawArrays(goog.webgl.TRIANGLE_STRIP, 0, 4);
}
}
@@ -276,7 +276,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
this.updateUsedTiles(frameState.usedTiles, tileSource, z, tileRange);
var tileTextureQueue = mapRenderer.getTileTextureQueue();
this.manageTilePyramid(
frameState, tileSource, tileGrid, projection, extent, z,
frameState, tileSource, tileGrid, pixelRatio, projection, extent, z,
tileLayer.getPreload(),
/**
* @param {ol.Tile} tile Tile.
@@ -289,7 +289,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame =
tile,
tileGrid.getTileCoordCenter(tile.tileCoord),
tileGrid.getResolution(tile.tileCoord.z),
tileSize, tileGutter
tilePixelSize, tileGutter * pixelRatio
]);
}
}, this);

View File

@@ -101,10 +101,11 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
/**
* @this {ol.source.BingMaps}
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
goog.asserts.assert(ol.proj.equivalent(
projection, this.getProjection()));
if (goog.isNull(tileCoord)) {

View File

@@ -119,14 +119,15 @@ ol.source.TileImage.prototype.expireCache = function(usedTiles) {
/**
* @inheritDoc
*/
ol.source.TileImage.prototype.getTile = function(z, x, y, projection) {
ol.source.TileImage.prototype.getTile =
function(z, x, y, pixelRatio, projection) {
var tileCoordKey = this.getKeyZXY(z, x, y);
if (this.tileCache.containsKey(tileCoordKey)) {
return /** @type {!ol.Tile} */ (this.tileCache.get(tileCoordKey));
} else {
goog.asserts.assert(projection);
var tileCoord = new ol.TileCoord(z, x, y);
var tileUrl = this.tileUrlFunction(tileCoord, projection);
var tileUrl = this.tileUrlFunction(tileCoord, pixelRatio, projection);
var tile = new this.tileClass(
tileCoord,
goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY,

View File

@@ -144,6 +144,7 @@ ol.source.Tile.prototype.getResolutions = function() {
* @param {number} z Tile coordinate z.
* @param {number} x Tile coordinate x.
* @param {number} y Tile coordinate y.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection=} opt_projection Projection.
* @return {!ol.Tile} Tile.
*/
@@ -158,6 +159,32 @@ ol.source.Tile.prototype.getTileGrid = function() {
};
/**
* @param {ol.proj.Projection} projection Projection.
* @return {ol.tilegrid.TileGrid} Tile grid.
*/
ol.source.Tile.prototype.getTileGridForProjection = function(projection) {
if (goog.isNull(this.tileGrid)) {
return ol.tilegrid.getForProjection(projection);
} else {
return this.tileGrid;
}
};
/**
* @param {number} z Z.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {number} Tile size.
*/
ol.source.Tile.prototype.getTilePixelSize =
function(z, pixelRatio, projection) {
var tileGrid = this.getTileGridForProjection(projection);
return tileGrid.getTileSize(z);
};
/**
* Marks a tile coord as being used, without triggering a load.
* @param {number} z Tile coordinate z.

View File

@@ -4,6 +4,7 @@
goog.provide('ol.source.TileWMS');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('goog.object');
goog.require('goog.string');
@@ -13,6 +14,7 @@ goog.require('ol.TileUrlFunction');
goog.require('ol.extent');
goog.require('ol.source.TileImage');
goog.require('ol.source.wms');
goog.require('ol.source.wms.ServerType');
@@ -71,6 +73,18 @@ ol.source.TileWMS = function(opt_options) {
*/
this.v13_ = true;
/**
* @private
* @type {ol.source.wms.ServerType|undefined}
*/
this.serverType_ = options.serverType;
/**
* @private
* @type {boolean}
*/
this.hidpi_ = goog.isDef(options.hidpi) ? options.hidpi : true;
/**
* @private
* @type {string}
@@ -117,6 +131,23 @@ ol.source.TileWMS.prototype.getParams = function() {
};
/**
* @param {number} z Z.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {number} Size.
*/
ol.source.TileWMS.prototype.getTilePixelSize =
function(z, pixelRatio, projection) {
var tileSize = goog.base(this, 'getTilePixelSize', z, pixelRatio, projection);
if (pixelRatio == 1 || !this.hidpi_ || !goog.isDef(this.serverType_)) {
return tileSize;
} else {
return (tileSize * pixelRatio + 0.5) | 0;
}
};
/**
* @private
*/
@@ -132,11 +163,13 @@ ol.source.TileWMS.prototype.resetCoordKeyPrefix_ = function() {
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @private
* @return {string|undefined} Tile URL.
*/
ol.source.TileWMS.prototype.tileUrlFunction_ = function(tileCoord, projection) {
ol.source.TileWMS.prototype.tileUrlFunction_ =
function(tileCoord, pixelRatio, projection) {
var urls = this.urls_;
if (!goog.isDef(urls) || goog.array.isEmpty(urls)) {
@@ -145,7 +178,7 @@ ol.source.TileWMS.prototype.tileUrlFunction_ = function(tileCoord, projection) {
var tileGrid = this.getTileGrid();
if (goog.isNull(tileGrid)) {
tileGrid = ol.tilegrid.getForProjection(projection);
tileGrid = this.getTileGridForProjection(projection);
}
if (tileGrid.getResolutions().length <= tileCoord.z) {
@@ -164,17 +197,21 @@ ol.source.TileWMS.prototype.tileUrlFunction_ = function(tileCoord, projection) {
goog.object.extend(params, this.params_);
var tileResolution = tileGrid.getResolution(tileCoord.z);
if (pixelRatio != 1 && (!this.hidpi_ || !goog.isDef(this.serverType_))) {
pixelRatio = 1;
}
var tileSize = tileGrid.getTileSize(tileCoord.z);
var gutter = this.gutter_;
if (gutter === 0) {
goog.object.set(params, 'WIDTH', tileSize);
goog.object.set(params, 'HEIGHT', tileSize);
} else {
goog.object.set(params, 'WIDTH', tileSize + 2 * gutter);
goog.object.set(params, 'HEIGHT', tileSize + 2 * gutter);
if (gutter !== 0) {
tileSize += 2 * gutter;
tileExtent =
ol.extent.buffer(tileExtent, tileResolution * gutter, this.tmpExtent_);
}
if (pixelRatio != 1) {
tileSize = (tileSize * pixelRatio + 0.5) | 0;
}
goog.object.set(params, 'WIDTH', tileSize);
goog.object.set(params, 'HEIGHT', tileSize);
params[this.v13_ ? 'CRS' : 'SRS'] = projection.getCode();
@@ -182,6 +219,24 @@ ol.source.TileWMS.prototype.tileUrlFunction_ = function(tileCoord, projection) {
goog.object.set(params, 'STYLES', new String(''));
}
if (pixelRatio != 1) {
switch (this.serverType_) {
case ol.source.wms.ServerType.GEOSERVER:
var dpi = (90 * pixelRatio + 0.5) | 0;
goog.object.set(params, 'FORMAT_OPTIONS', 'dpi:' + dpi);
break;
case ol.source.wms.ServerType.MAPSERVER:
goog.object.set(params, 'MAP_RESOLUTION', 90 * pixelRatio);
break;
case ol.source.wms.ServerType.QGIS:
goog.object.set(params, 'DPI', 90 * pixelRatio);
break;
default:
goog.asserts.fail();
break;
}
}
var axisOrientation = projection.getAxisOrientation();
var bbox;
if (this.v13_ && axisOrientation.substr(0, 2) == 'ne') {

View File

@@ -96,10 +96,11 @@ ol.source.WMTS = function(options) {
/**
* @this {ol.source.WMTS}
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {

View File

@@ -61,10 +61,11 @@ ol.source.Zoomify = function(opt_options) {
/**
* @this {ol.source.TileImage}
* @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {

View File

@@ -8,7 +8,7 @@ goog.require('ol.TileCoord');
/**
* @typedef {function(this: ol.source.TileImage, ol.TileCoord,
* ol.proj.Projection): (string|undefined)}
* number, ol.proj.Projection): (string|undefined)}
*/
ol.TileUrlFunctionType;
@@ -29,10 +29,11 @@ ol.TileUrlFunction.createFromTemplate = function(template) {
/**
* @this {ol.source.TileImage}
* @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
@@ -66,16 +67,18 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
/**
* @this {ol.source.TileImage}
* @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
var index =
goog.math.modulo(tileCoord.hash(), tileUrlFunctions.length);
return tileUrlFunctions[index].call(this, tileCoord, projection);
return tileUrlFunctions[index].call(
this, tileCoord, pixelRatio, projection);
}
});
};
@@ -84,10 +87,12 @@ ol.TileUrlFunction.createFromTileUrlFunctions = function(tileUrlFunctions) {
/**
* @this {ol.source.TileImage}
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
ol.TileUrlFunction.nullTileUrlFunction = function(tileCoord, projection) {
ol.TileUrlFunction.nullTileUrlFunction =
function(tileCoord, pixelRatio, projection) {
return undefined;
};
@@ -104,16 +109,18 @@ ol.TileUrlFunction.withTileCoordTransform =
/**
* @this {ol.source.TileImage}
* @param {ol.TileCoord} tileCoord Tile Coordinate.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {string|undefined} Tile URL.
*/
function(tileCoord, projection) {
function(tileCoord, pixelRatio, projection) {
if (goog.isNull(tileCoord)) {
return undefined;
} else {
return tileUrlFunction.call(
this,
transformFn.call(this, tileCoord, projection, tmpTileCoord),
pixelRatio,
projection);
}
});

View File

@@ -17,7 +17,7 @@ describe('ol.source.TileWMS', function() {
it('returns a tile with the expected URL', function() {
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:3857'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:3857'));
expect(tile).to.be.an(ol.ImageTile);
var uri = new goog.Uri(tile.src_);
expect(uri.getScheme()).to.be('http');
@@ -44,7 +44,7 @@ describe('ol.source.TileWMS', function() {
it('returns a larger tile when a gutter is specified', function() {
options.gutter = 16;
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:3857'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:3857'));
expect(tile).to.be.an(ol.ImageTile);
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
@@ -58,7 +58,7 @@ describe('ol.source.TileWMS', function() {
it('sets the SRS query value instead of CRS if version < 1.3', function() {
options.params.VERSION = '1.2';
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:4326'));
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
expect(queryData.get('CRS')).to.be(undefined);
@@ -69,7 +69,7 @@ describe('ol.source.TileWMS', function() {
options.params.FORMAT = 'image/jpeg';
options.params.TRANSPARENT = false;
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:4326'));
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
expect(queryData.get('FORMAT')).to.be('image/jpeg');
@@ -79,7 +79,7 @@ describe('ol.source.TileWMS', function() {
it('does not add a STYLES= option if one is specified', function() {
options.params.STYLES = 'foo';
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:4326'));
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
expect(queryData.get('STYLES')).to.be('foo');
@@ -87,7 +87,7 @@ describe('ol.source.TileWMS', function() {
it('changes the BBOX order for EN axis orientations', function() {
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('EPSG:4326'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('EPSG:4326'));
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
expect(queryData.get('BBOX')).to.be('-45,-90,0,-45');
@@ -96,7 +96,7 @@ describe('ol.source.TileWMS', function() {
it('uses EN BBOX order if version < 1.3', function() {
options.params.VERSION = '1.1.0';
var source = new ol.source.TileWMS(options);
var tile = source.getTile(3, 2, 1, ol.proj.get('CRS:84'));
var tile = source.getTile(3, 2, 1, 1, ol.proj.get('CRS:84'));
var uri = new goog.Uri(tile.src_);
var queryData = uri.getQueryData();
expect(queryData.get('BBOX')).to.be('-90,-45,-45,0');