Merge pull request #5482 from ischneider/layer-extent

Fix for regression in tile layer extent
This commit is contained in:
Tim Schaub
2016-06-30 15:19:13 -06:00
committed by GitHub
6 changed files with 79 additions and 15 deletions
+6 -7
View File
@@ -4,13 +4,12 @@ title: Limited Layer Extent
shortdesc: Restricting layer rendering to a limited extent. shortdesc: Restricting layer rendering to a limited extent.
docs: > docs: >
This example uses the <code>layer.setExtent()</code> method to This example uses the <code>layer.setExtent()</code> method to
modify the extent of the overlay layer. Use the controls below modify the extent of the overlay layer. Use the controls above
to limit rendering based on an extent. to limit rendering based on an extent (approximate country bounds).
tags: "extent, tilejson" tags: "extent, tilejson"
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
<button type="button" class="btn btn-default" id="northwest">northwest</button> <button type="button" class="btn btn-default" id="India">India</button>
<button type="button" class="btn btn-default" id="northeast">northeast</button> <button type="button" class="btn btn-default" id="Argentina">Argentina</button>
<button type="button" class="btn btn-default" id="southeast">southeast</button> <button type="button" class="btn btn-default" id="Nigeria">Nigeria</button>
<button type="button" class="btn btn-default" id="southwest">southwest</button> <button type="button" class="btn btn-default" id="Sweden">Sweden</button>
<button type="button" class="btn btn-default" id="world">world</button>
+8 -6
View File
@@ -3,17 +3,17 @@ goog.require('ol.View');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.proj'); goog.require('ol.proj');
goog.require('ol.source.TileJSON'); goog.require('ol.source.TileJSON');
goog.require('ol.interaction.DragRotateAndZoom');
function transform(extent) { function transform(extent) {
return ol.proj.transformExtent(extent, 'EPSG:4326', 'EPSG:3857'); return ol.proj.transformExtent(extent, 'EPSG:4326', 'EPSG:3857');
} }
var extents = { var extents = {
northwest: transform([-180, 0, 0, 85]), India: transform([68.17665, 7.96553, 97.40256, 35.49401]),
northeast: transform([0, 0, 180, 85]), Argentina: transform([-73.41544, -55.25, -53.62835, -21.83231]),
southeast: transform([0, -85, 180, 0]), Nigeria: transform([2.6917, 4.24059, 14.57718, 13.86592]),
southwest: transform([-180, -85, 0, 0]), Sweden: transform([11.02737, 55.36174, 23.90338, 69.10625])
world: transform([-180, -85, 180, 85])
}; };
var base = new ol.layer.Tile({ var base = new ol.layer.Tile({
@@ -25,7 +25,7 @@ var base = new ol.layer.Tile({
}); });
var overlay = new ol.layer.Tile({ var overlay = new ol.layer.Tile({
extent: extents.northwest, extent: extents.India,
source: new ol.source.TileJSON({ source: new ol.source.TileJSON({
url: 'http://api.tiles.mapbox.com/v3/' + url: 'http://api.tiles.mapbox.com/v3/' +
'mapbox.world-glass.json', 'mapbox.world-glass.json',
@@ -43,6 +43,8 @@ var map = new ol.Map({
}) })
}); });
map.addInteraction(new ol.interaction.DragRotateAndZoom());
for (var key in extents) { for (var key in extents) {
document.getElementById(key).onclick = function(event) { document.getElementById(key).onclick = function(event) {
overlay.setExtent(extents[event.target.id]); overlay.setExtent(extents[event.target.id]);
@@ -276,6 +276,41 @@ ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, fram
tilesToDraw.reverse(); tilesToDraw.reverse();
pixelExtents = []; pixelExtents = [];
} }
var extent = layerState.extent;
var clipped = extent !== undefined;
if (clipped) {
goog.asserts.assert(extent !== undefined,
'layerState extent is defined');
var topLeft = ol.extent.getTopLeft(extent);
var topRight = ol.extent.getTopRight(extent);
var bottomRight = ol.extent.getBottomRight(extent);
var bottomLeft = ol.extent.getBottomLeft(extent);
ol.vec.Mat4.multVec2(frameState.coordinateToPixelMatrix,
topLeft, topLeft);
ol.vec.Mat4.multVec2(frameState.coordinateToPixelMatrix,
topRight, topRight);
ol.vec.Mat4.multVec2(frameState.coordinateToPixelMatrix,
bottomRight, bottomRight);
ol.vec.Mat4.multVec2(frameState.coordinateToPixelMatrix,
bottomLeft, bottomLeft);
var ox = drawOffsetX || 0;
var oy = drawOffsetY || 0;
renderContext.save();
var cx = (renderContext.canvas.width * pixelRatio) / 2;
var cy = (renderContext.canvas.height * pixelRatio) / 2;
ol.render.canvas.rotateAtOffset(renderContext, -rotation, cx, cy);
renderContext.beginPath();
renderContext.moveTo(topLeft[0] * pixelRatio + ox, topLeft[1] * pixelRatio + oy);
renderContext.lineTo(topRight[0] * pixelRatio + ox, topRight[1] * pixelRatio + oy);
renderContext.lineTo(bottomRight[0] * pixelRatio + ox, bottomRight[1] * pixelRatio + oy);
renderContext.lineTo(bottomLeft[0] * pixelRatio + ox, bottomLeft[1] * pixelRatio + oy);
renderContext.clip();
ol.render.canvas.rotateAtOffset(renderContext, rotation, cx, cy);
}
for (var i = 0, ii = tilesToDraw.length; i < ii; ++i) { for (var i = 0, ii = tilesToDraw.length; i < ii; ++i) {
var tile = tilesToDraw[i]; var tile = tilesToDraw[i];
var tileCoord = tile.getTileCoord(); var tileCoord = tile.getTileCoord();
@@ -324,6 +359,10 @@ ol.renderer.canvas.TileLayer.prototype.renderTileImages = function(context, fram
} }
} }
if (clipped) {
renderContext.restore();
}
if (hasRenderListeners) { if (hasRenderListeners) {
var dX = drawOffsetX - offsetX / drawScale + offsetX; var dX = drawOffsetX - offsetX / drawScale + offsetX;
var dY = drawOffsetY - offsetY / drawScale + offsetY; var dY = drawOffsetY - offsetY / drawScale + offsetY;
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

+26 -2
View File
@@ -29,7 +29,7 @@ describe('ol.rendering.layer.Tile', function() {
} }
}; };
sources.forEach(function(source) { sources.forEach(function(source, i) {
source.on('tileloadstart', function(event) { source.on('tileloadstart', function(event) {
tilesLoading++; tilesLoading++;
}); });
@@ -44,7 +44,7 @@ describe('ol.rendering.layer.Tile', function() {
var options = { var options = {
source: source source: source
}; };
ol.object.assign(options, layerOptions); ol.object.assign(options, layerOptions[i] || layerOptions);
map.addLayer(new ol.layer.Tile(options)); map.addLayer(new ol.layer.Tile(options));
}); });
} }
@@ -112,6 +112,30 @@ describe('ol.rendering.layer.Tile', function() {
IMAGE_TOLERANCE, done); IMAGE_TOLERANCE, done);
}); });
}); });
function centerExtent(map) {
var c = map.getView().calculateExtent(map.getSize());
var qw = ol.extent.getSize(c)[0] / 4;
var qh = ol.extent.getSize(c)[1] / 4;
return [c[0] + qw, c[1] + qh, c[2] - qw, c[3] - qh];
}
it('tests canvas layer extent clipping', function(done) {
map = createMap('canvas');
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
expectResemble(map, 'spec/ol/layer/expected/2-layers-canvas-extent.png',
IMAGE_TOLERANCE, done);
});
});
it('tests canvas layer extent clipping with rotation', function(done) {
map = createMap('canvas');
map.getView().setRotation(Math.PI / 2);
waitForTiles([source1, source2], [{}, {extent: centerExtent(map)}], function() {
expectResemble(map, 'spec/ol/layer/expected/2-layers-canvas-extent-rotate.png',
IMAGE_TOLERANCE, done);
});
});
}); });
describe('tile layer with opacity', function() { describe('tile layer with opacity', function() {