Merge pull request #13060 from tschaub/less-nodata

Avoid fetching data outside the grid extent
This commit is contained in:
Tim Schaub
2021-12-01 07:12:21 -07:00
committed by GitHub
10 changed files with 111 additions and 7 deletions

View File

@@ -97,6 +97,14 @@ function getRenderExtent(frameState, extent) {
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;
}
@@ -236,11 +244,13 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
* @return {boolean} Layer is ready to be rendered.
*/
prepareFrameInternal(frameState) {
if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
const layer = this.getLayer();
const source = layer.getSource();
if (!source) {
return false;
}
const source = this.getLayer().getSource();
if (!source) {
if (isEmpty(getRenderExtent(frameState, frameState.extent))) {
return false;
}
return source.getState() === State.READY;
@@ -248,7 +258,7 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
/**
* @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 {Object<number, Array<TileTexture>>} tileTexturesByZ The zoom level.
*/
@@ -341,10 +351,10 @@ class WebGLTileLayerRenderer extends WebGLLayerRenderer {
this.preRender(gl, frameState);
const viewState = frameState.viewState;
const extent = getRenderExtent(frameState, frameState.extent);
const tileLayer = this.getLayer();
const tileSource = tileLayer.getSource();
const tileGrid = tileSource.getTileGridForProjection(viewState.projection);
const extent = getRenderExtent(frameState, frameState.extent);
const z = tileGrid.getZForResolution(
viewState.resolution,
tileSource.zDirection

View File

@@ -31,7 +31,7 @@ import {toPromise} from '../functions.js';
* @property {boolean} [opaque=false] Whether the layer is opaque.
* @property {import("./State.js").default} [state] The source state.
* @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} [bandCount=4] Number of bands represented in the data.
*/

View File

@@ -300,6 +300,7 @@ function getMaxForDataType(array) {
* @property {boolean} [opaque=false] Whether the layer is opaque.
* @property {number} [transition=250] Duration of the opacity transition for rendering.
* To disable the opacity transition, pass `transition: 0`.
* @property {boolean} [wrapX=false] Render tiles beyond the tile grid extent.
*/
/**
@@ -318,6 +319,7 @@ class GeoTIFFSource extends DataTile {
projection: null,
opaque: options.opaque,
transition: options.transition,
wrapX: options.wrapX,
});
/**

View File

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

View File

@@ -27,6 +27,29 @@ describe('ol/source/GeoTIFF', function () {
expect(source.readMethod_).to.be('readRGB');
});
it('defaults to wrapX: false', function () {
const source = new GeoTIFFSource({
sources: [
{
url: 'spec/ol/source/images/0-0-0.tif',
},
],
});
expect(source.getWrapX()).to.be(false);
});
it('allows wrapX to be set', function () {
const source = new GeoTIFFSource({
wrapX: true,
sources: [
{
url: 'spec/ol/source/images/0-0-0.tif',
},
],
});
expect(source.getWrapX()).to.be(true);
});
it('generates Float32Array data if normalize is set to false', (done) => {
const source = new GeoTIFFSource({
normalize: false,

View File

@@ -7,6 +7,7 @@ import WebGLArrayBuffer from '../../../../../src/ol/webgl/Buffer.js';
import WebGLTileLayer from '../../../../../src/ol/layer/WebGLTile.js';
import {EXTENT as EPSG3857_EXTENT} from '../../../../../src/ol/proj/epsg3857.js';
import {createCanvasContext2D} from '../../../../../src/ol/dom.js';
import {get as getProjection} from '../../../../../src/ol/proj.js';
describe('ol/webgl/TileTexture', function () {
/** @type {TileTexture} */
@@ -31,6 +32,9 @@ describe('ol/webgl/TileTexture', function () {
renderer = layer.createRenderer();
renderer.prepareFrame({
viewState: {
projection: getProjection('EPSG:3857'),
},
extent: EPSG3857_EXTENT,
layerIndex: 0,
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({
source: new DataTile({
wrapX: true,
loader: function (z, x, y) {
const half = labelCanvasSize / 2;

View File

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