Fix reprojection of raster sources with gutter

This commit is contained in:
Petr Sloup
2016-01-26 17:05:49 +01:00
parent ccf47de448
commit 59574da74c
11 changed files with 53 additions and 16 deletions

View File

@@ -67,7 +67,7 @@ ol.renderer.canvas.TileLayer.prototype.composeFrame = function(
var source = layer.getSource(); var source = layer.getSource();
goog.asserts.assertInstanceof(source, ol.source.Tile, goog.asserts.assertInstanceof(source, ol.source.Tile,
'source is an ol.source.Tile'); 'source is an ol.source.Tile');
var tileGutter = source.getGutter(); var tileGutter = source.getGutter(projection);
var opaque = source.getOpaque(projection); var opaque = source.getOpaque(projection);
var transform = this.getTransform(frameState, 0); var transform = this.getTransform(frameState, 0);

View File

@@ -94,7 +94,7 @@ ol.renderer.dom.TileLayer.prototype.prepareFrame = function(frameState, layerSta
'layer is an instance of ol.layer.Tile'); 'layer is an instance of ol.layer.Tile');
var tileSource = tileLayer.getSource(); var tileSource = tileLayer.getSource();
var tileGrid = tileSource.getTileGridForProjection(projection); var tileGrid = tileSource.getTileGridForProjection(projection);
var tileGutter = tileSource.getGutter(); var tileGutter = tileSource.getGutter(projection);
var z = tileGrid.getZForResolution(viewState.resolution); var z = tileGrid.getZForResolution(viewState.resolution);
var tileResolution = tileGrid.getResolution(z); var tileResolution = tileGrid.getResolution(z);
var center = viewState.center; var center = viewState.center;

View File

@@ -169,7 +169,7 @@ ol.renderer.webgl.TileLayer.prototype.prepareFrame = function(frameState, layerS
var pixelRatio = tilePixelSize[0] / var pixelRatio = tilePixelSize[0] /
ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0]; ol.size.toSize(tileGrid.getTileSize(z), this.tmpSize_)[0];
var tilePixelResolution = tileResolution / pixelRatio; var tilePixelResolution = tileResolution / pixelRatio;
var tileGutter = tileSource.getGutter(); var tileGutter = tileSource.getGutter(projection);
var center = viewState.center; var center = viewState.center;
var extent; var extent;

View File

@@ -163,7 +163,7 @@ ol.reproj.Image.prototype.reproject_ = function() {
this.targetResolution_, this.targetExtent_, this.triangulation_, [{ this.targetResolution_, this.targetExtent_, this.triangulation_, [{
extent: this.sourceImage_.getExtent(), extent: this.sourceImage_.getExtent(),
image: this.sourceImage_.getImage() image: this.sourceImage_.getImage()
}]); }], 0);
} }
this.state = sourceState; this.state = sourceState;
this.changed(); this.changed();

View File

@@ -101,12 +101,13 @@ ol.reproj.enlargeClipPoint_ = function(centroidX, centroidY, x, y) {
* @param {Array.<{extent: ol.Extent, * @param {Array.<{extent: ol.Extent,
* image: (HTMLCanvasElement|Image|HTMLVideoElement)}>} sources * image: (HTMLCanvasElement|Image|HTMLVideoElement)}>} sources
* Array of sources. * Array of sources.
* @param {number} gutter Gutter of the sources.
* @param {boolean=} opt_renderEdges Render reprojection edges. * @param {boolean=} opt_renderEdges Render reprojection edges.
* @return {HTMLCanvasElement} Canvas with reprojected data. * @return {HTMLCanvasElement} Canvas with reprojected data.
*/ */
ol.reproj.render = function(width, height, pixelRatio, ol.reproj.render = function(width, height, pixelRatio,
sourceResolution, sourceExtent, targetResolution, targetExtent, sourceResolution, sourceExtent, targetResolution, targetExtent,
triangulation, sources, opt_renderEdges) { triangulation, sources, gutter, opt_renderEdges) {
var context = ol.dom.createCanvasContext2D(Math.round(pixelRatio * width), var context = ol.dom.createCanvasContext2D(Math.round(pixelRatio * width),
Math.round(pixelRatio * height)); Math.round(pixelRatio * height));
@@ -136,7 +137,10 @@ ol.reproj.render = function(width, height, pixelRatio,
var srcWidth = ol.extent.getWidth(src.extent); var srcWidth = ol.extent.getWidth(src.extent);
var srcHeight = ol.extent.getHeight(src.extent); var srcHeight = ol.extent.getHeight(src.extent);
stitchContext.drawImage(src.image, stitchContext.drawImage(
src.image,
gutter, gutter,
src.image.width - 2 * gutter, src.image.height - 2 * gutter,
xPos * stitchScale, yPos * stitchScale, xPos * stitchScale, yPos * stitchScale,
srcWidth * stitchScale, srcHeight * stitchScale); srcWidth * stitchScale, srcHeight * stitchScale);
}); });

View File

@@ -35,6 +35,7 @@ ol.reproj.TileFunctionType;
* @param {ol.TileCoord} tileCoord Coordinate of the tile. * @param {ol.TileCoord} tileCoord Coordinate of the tile.
* @param {ol.TileCoord} wrappedTileCoord Coordinate of the tile wrapped in X. * @param {ol.TileCoord} wrappedTileCoord Coordinate of the tile wrapped in X.
* @param {number} pixelRatio Pixel ratio. * @param {number} pixelRatio Pixel ratio.
* @param {number} gutter Gutter of the source tiles.
* @param {ol.reproj.TileFunctionType} getTileFunction * @param {ol.reproj.TileFunctionType} getTileFunction
* Function returning source tiles (z, x, y, pixelRatio). * Function returning source tiles (z, x, y, pixelRatio).
* @param {number=} opt_errorThreshold Acceptable reprojection error (in px). * @param {number=} opt_errorThreshold Acceptable reprojection error (in px).
@@ -42,7 +43,7 @@ ol.reproj.TileFunctionType;
*/ */
ol.reproj.Tile = function(sourceProj, sourceTileGrid, ol.reproj.Tile = function(sourceProj, sourceTileGrid,
targetProj, targetTileGrid, tileCoord, wrappedTileCoord, targetProj, targetTileGrid, tileCoord, wrappedTileCoord,
pixelRatio, getTileFunction, pixelRatio, gutter, getTileFunction,
opt_errorThreshold, opt_errorThreshold,
opt_renderEdges) { opt_renderEdges) {
goog.base(this, tileCoord, ol.TileState.IDLE); goog.base(this, tileCoord, ol.TileState.IDLE);
@@ -59,6 +60,12 @@ ol.reproj.Tile = function(sourceProj, sourceTileGrid,
*/ */
this.pixelRatio_ = pixelRatio; this.pixelRatio_ = pixelRatio;
/**
* @private
* @type {number}
*/
this.gutter_ = gutter;
/** /**
* @private * @private
* @type {HTMLCanvasElement} * @type {HTMLCanvasElement}
@@ -269,7 +276,7 @@ ol.reproj.Tile.prototype.reproject_ = function() {
this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_, this.canvas_ = ol.reproj.render(width, height, this.pixelRatio_,
sourceResolution, this.sourceTileGrid_.getExtent(), sourceResolution, this.sourceTileGrid_.getExtent(),
targetResolution, targetExtent, this.triangulation_, sources, targetResolution, targetExtent, this.triangulation_, sources,
this.renderEdges_); this.gutter_, this.renderEdges_);
this.state = ol.TileState.LOADED; this.state = ol.TileState.LOADED;
} }

View File

@@ -120,6 +120,29 @@ ol.source.TileImage.prototype.expireCache = function(projection, usedTiles) {
}; };
/**
* @inheritDoc
*/
ol.source.TileImage.prototype.getGutter = function(projection) {
if (ol.ENABLE_RASTER_REPROJECTION &&
this.getProjection() && projection &&
!ol.proj.equivalent(this.getProjection(), projection)) {
return 0;
} else {
return this.getGutterInternal();
}
};
/**
* @protected
* @return {number} Gutter.
*/
ol.source.TileImage.prototype.getGutterInternal = function() {
return 0;
};
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -230,6 +253,7 @@ ol.source.TileImage.prototype.getTile = function(z, x, y, pixelRatio, projection
sourceProjection, sourceTileGrid, sourceProjection, sourceTileGrid,
projection, targetTileGrid, projection, targetTileGrid,
tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio), tileCoord, wrappedTileCoord, this.getTilePixelRatio(pixelRatio),
this.getGutterInternal(),
function(z, x, y, pixelRatio) { function(z, x, y, pixelRatio) {
return this.getTileInternal(z, x, y, pixelRatio, sourceProjection); return this.getTileInternal(z, x, y, pixelRatio, sourceProjection);
}.bind(this), this.reprojectionErrorThreshold_, }.bind(this), this.reprojectionErrorThreshold_,

View File

@@ -147,9 +147,10 @@ ol.source.Tile.prototype.forEachLoadedTile = function(projection, z, tileRange,
/** /**
* @param {ol.proj.Projection} projection Projection.
* @return {number} Gutter. * @return {number} Gutter.
*/ */
ol.source.Tile.prototype.getGutter = function() { ol.source.Tile.prototype.getGutter = function(projection) {
return 0; return 0;
}; };

View File

@@ -177,7 +177,7 @@ ol.source.TileWMS.prototype.getGetFeatureInfoUrl = function(coordinate, resoluti
/** /**
* @inheritDoc * @inheritDoc
*/ */
ol.source.TileWMS.prototype.getGutter = function() { ol.source.TileWMS.prototype.getGutterInternal = function() {
return this.gutter_; return this.gutter_;
}; };

View File

@@ -21,7 +21,7 @@ describe('ol.reproj.Tile', function() {
return new ol.reproj.Tile( return new ol.reproj.Tile(
proj3857, ol.tilegrid.createForProjection(proj3857), proj4326, proj3857, ol.tilegrid.createForProjection(proj3857), proj4326,
ol.tilegrid.createForProjection(proj4326, 3, opt_tileSize), ol.tilegrid.createForProjection(proj4326, 3, opt_tileSize),
[3, 2, -2], null, pixelRatio, function(z, x, y, pixelRatio) { [3, 2, -2], null, pixelRatio, 0, function(z, x, y, pixelRatio) {
return new ol.ImageTile([z, x, y], ol.TileState.IDLE, return new ol.ImageTile([z, x, y], ol.TileState.IDLE,
'data:image/gif;base64,' + 'data:image/gif;base64,' +
'R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=', null, 'R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=', null,
@@ -48,7 +48,7 @@ describe('ol.reproj.Tile', function() {
var tile = new ol.reproj.Tile( var tile = new ol.reproj.Tile(
proj3857, ol.tilegrid.createForProjection(proj3857), proj3857, ol.tilegrid.createForProjection(proj3857),
proj4326, ol.tilegrid.createForProjection(proj4326), proj4326, ol.tilegrid.createForProjection(proj4326),
[0, -1, 0], null, 1, function() { [0, -1, 0], null, 1, 0, function() {
expect().fail('No tiles should be required'); expect().fail('No tiles should be required');
}); });
expect(tile.getState()).to.be(ol.TileState.EMPTY); expect(tile.getState()).to.be(ol.TileState.EMPTY);
@@ -60,7 +60,7 @@ describe('ol.reproj.Tile', function() {
var tile = new ol.reproj.Tile( var tile = new ol.reproj.Tile(
proj27700, ol.tilegrid.createForProjection(proj27700), proj27700, ol.tilegrid.createForProjection(proj27700),
proj4326, ol.tilegrid.createForProjection(proj4326), proj4326, ol.tilegrid.createForProjection(proj4326),
[3, 2, -2], null, 1, function() { [3, 2, -2], null, 1, 0, function() {
expect().fail('No tiles should be required'); expect().fail('No tiles should be required');
}); });
expect(tile.getState()).to.be(ol.TileState.EMPTY); expect(tile.getState()).to.be(ol.TileState.EMPTY);

View File

@@ -5,12 +5,13 @@ describe('ol.rendering.reproj.Tile', function() {
function testSingleTile(source, targetProjection, targetTileGrid, z, x, y, function testSingleTile(source, targetProjection, targetTileGrid, z, x, y,
pixelRatio, expectedUrl, expectedRequests, done) { pixelRatio, expectedUrl, expectedRequests, done) {
var sourceProjection = source.getProjection(); var sourceProjection = source.getProjection();
var sourceGutter = source.getGutter(sourceProjection);
var tilesRequested = 0; var tilesRequested = 0;
var tile = new ol.reproj.Tile(sourceProjection, source.getTileGrid(), var tile = new ol.reproj.Tile(sourceProjection, source.getTileGrid(),
ol.proj.get(targetProjection), targetTileGrid, ol.proj.get(targetProjection), targetTileGrid,
[z, x, y], null, pixelRatio, [z, x, y], null, pixelRatio, sourceGutter,
function(z, x, y, pixelRatio) { function(z, x, y, pixelRatio) {
tilesRequested++; tilesRequested++;
return source.getTile(z, x, y, pixelRatio, sourceProjection); return source.getTile(z, x, y, pixelRatio, sourceProjection);