Avoid loading tiles outside the grid extent

This commit is contained in:
Tim Schaub
2021-11-29 10:55:55 -07:00
parent a788c9bd1e
commit 3bf1aef8e2
8 changed files with 86 additions and 7 deletions

View File

@@ -97,6 +97,14 @@ function getRenderExtent(frameState, extent) {
fromUserExtent(layerState.extent, frameState.viewState.projection) fromUserExtent(layerState.extent, frameState.viewState.projection)
); );
} }
const source =
/** {import("../../source/Tile.js").default} */ layerState.layer.getSource();
if (!source.getWrapX()) {
const gridExtent = source.tileGrid.getExtent();
if (gridExtent) {
extent = getIntersection(extent, gridExtent);
}
}
return extent; return extent;
} }
@@ -236,11 +244,13 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
* @return {boolean} Layer is ready to be rendered. * @return {boolean} Layer is ready to be rendered.
*/ */
prepareFrameInternal(frameState) { prepareFrameInternal(frameState) {
if (isEmpty(getRenderExtent(frameState, frameState.extent))) { const layer = this.getLayer();
const source = layer.getSource();
if (!source) {
return false; return false;
} }
const source = this.getLayer().getSource();
if (!source) { if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
return false; return false;
} }
return source.getState() === State.READY; return source.getState() === State.READY;
@@ -248,7 +258,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
/** /**
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state. * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @param {import("../../extent.js").Extent} extent The extent. * @param {import("../../extent.js").Extent} extent The extent to be rendered.
* @param {number} z The zoom level. * @param {number} z The zoom level.
* @param {Object<number, Array<TileTexture>>} tileTexturesByZ The zoom level. * @param {Object<number, Array<TileTexture>>} tileTexturesByZ The zoom level.
*/ */
@@ -341,10 +351,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
this.preRender(gl, frameState); this.preRender(gl, frameState);
const viewState = frameState.viewState; const viewState = frameState.viewState;
const extent = getRenderExtent(frameState, frameState.extent);
const tileLayer = this.getLayer(); const tileLayer = this.getLayer();
const tileSource = tileLayer.getSource(); const tileSource = tileLayer.getSource();
const tileGrid = tileSource.getTileGridForProjection(viewState.projection); const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
const extent = getRenderExtent(frameState, frameState.extent);
const z = tileGrid.getZForResolution( const z = tileGrid.getZForResolution(
viewState.resolution, viewState.resolution,
tileSource.zDirection tileSource.zDirection

View File

@@ -31,7 +31,7 @@ import {toPromise} from '../functions.js';
* @property {boolean} [opaque=false] Whether the layer is opaque. * @property {boolean} [opaque=false] Whether the layer is opaque.
* @property {import("./State.js").default} [state] The source state. * @property {import("./State.js").default} [state] The source state.
* @property {number} [tilePixelRatio] Tile pixel ratio. * @property {number} [tilePixelRatio] Tile pixel ratio.
* @property {boolean} [wrapX=true] Render tiles beyond the antimeridian. * @property {boolean} [wrapX=false] Render tiles beyond the antimeridian.
* @property {number} [transition] Transition time when fading in new tiles (in miliseconds). * @property {number} [transition] Transition time when fading in new tiles (in miliseconds).
* @property {number} [bandCount=4] Number of bands represented in the data. * @property {number} [bandCount=4] Number of bands represented in the data.
*/ */

View File

@@ -34,7 +34,7 @@ import {scale as scaleSize, toSize} from '../size.js';
* @property {import("../proj.js").ProjectionLike} [projection] Projection. * @property {import("../proj.js").ProjectionLike} [projection] Projection.
* @property {import("./State.js").default} [state] State. * @property {import("./State.js").default} [state] State.
* @property {import("../tilegrid/TileGrid.js").default} [tileGrid] TileGrid. * @property {import("../tilegrid/TileGrid.js").default} [tileGrid] TileGrid.
* @property {boolean} [wrapX=true] WrapX. * @property {boolean} [wrapX=false] WrapX.
* @property {number} [transition] Transition. * @property {number} [transition] Transition.
* @property {string} [key] Key. * @property {string} [key] Key.
* @property {number|import("../array.js").NearestDirectionFunction} [zDirection=0] ZDirection. * @property {number|import("../array.js").NearestDirectionFunction} [zDirection=0] ZDirection.

View File

@@ -7,6 +7,7 @@ import WebGLArrayBuffer from '../../../../../src/ol/webgl/Buffer.js';
import WebGLTileLayer from '../../../../../src/ol/layer/WebGLTile.js'; import WebGLTileLayer from '../../../../../src/ol/layer/WebGLTile.js';
import {EXTENT as EPSG3857_EXTENT} from '../../../../../src/ol/proj/epsg3857.js'; import {EXTENT as EPSG3857_EXTENT} from '../../../../../src/ol/proj/epsg3857.js';
import {createCanvasContext2D} from '../../../../../src/ol/dom.js'; import {createCanvasContext2D} from '../../../../../src/ol/dom.js';
import {get as getProjection} from '../../../../../src/ol/proj.js';
describe('ol/webgl/TileTexture', function () { describe('ol/webgl/TileTexture', function () {
/** @type {TileTexture} */ /** @type {TileTexture} */
@@ -31,6 +32,9 @@ describe('ol/webgl/TileTexture', function () {
renderer = layer.createRenderer(); renderer = layer.createRenderer();
renderer.prepareFrame({ renderer.prepareFrame({
viewState: {
projection: getProjection('EPSG:3857'),
},
extent: EPSG3857_EXTENT, extent: EPSG3857_EXTENT,
layerIndex: 0, layerIndex: 0,
layerStatesArray: [layer.getLayerState()], layerStatesArray: [layer.getLayerState()],

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

View File

@@ -0,0 +1,63 @@
import DataTile from '../../../../src/ol/source/DataTile.js';
import Map from '../../../../src/ol/Map.js';
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
import View from '../../../../src/ol/View.js';
import XYZ from '../../../../src/ol/source/XYZ.js';
const labelCanvasSize = 256;
const labelCanvas = document.createElement('canvas');
labelCanvas.width = labelCanvasSize;
labelCanvas.height = labelCanvasSize;
const labelContext = labelCanvas.getContext('2d');
labelContext.textAlign = 'center';
labelContext.font = '16px sans-serif';
const labelLineHeight = 16;
new Map({
layers: [
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
transition: 0,
}),
}),
new TileLayer({
source: new DataTile({
loader: function (z, x, y) {
const half = labelCanvasSize / 2;
labelContext.clearRect(0, 0, labelCanvasSize, labelCanvasSize);
labelContext.fillStyle = 'white';
labelContext.fillText(`z: ${z}`, half, half - labelLineHeight);
labelContext.fillText(`x: ${x}`, half, half);
labelContext.fillText(`y: ${y}`, half, half + labelLineHeight);
labelContext.strokeStyle = 'white';
labelContext.lineWidth = 2;
labelContext.strokeRect(0, 0, labelCanvasSize, labelCanvasSize);
const data = labelContext.getImageData(
0,
0,
labelCanvasSize,
labelCanvasSize
).data;
return new Uint8Array(data.buffer);
},
transition: 0,
}),
}),
],
target: 'map',
view: new View({
center: [15700000, 2700000],
zoom: 2,
}),
});
render({
message: 'data tiles outside the world are not rendered',
});

View File

@@ -46,6 +46,7 @@ new Map({
}), }),
new TileLayer({ new TileLayer({
source: new DataTile({ source: new DataTile({
wrapX: true,
loader: function (z, x, y) { loader: function (z, x, y) {
const half = labelCanvasSize / 2; const half = labelCanvasSize / 2;

View File

@@ -44,6 +44,7 @@ new Map({
}), }),
new TileLayer({ new TileLayer({
source: new DataTile({ source: new DataTile({
wrapX: true,
loader: function (z, x, y) { loader: function (z, x, y) {
const half = labelCanvasSize / 2; const half = labelCanvasSize / 2;