Only create and load tiles within the viewport

This commit is contained in:
Andreas Hocevar
2022-07-08 17:56:44 +02:00
parent 6ffbfa1a4a
commit 239487e9f0
3 changed files with 82 additions and 15 deletions

View File

@@ -531,6 +531,29 @@ export function getForViewAndSize(
size, size,
opt_extent opt_extent
) { ) {
const [x0, y0, x1, y1, x2, y2, x3, y3] = getRotatedViewport(
center,
resolution,
rotation,
size
);
return createOrUpdate(
Math.min(x0, x1, x2, x3),
Math.min(y0, y1, y2, y3),
Math.max(x0, x1, x2, x3),
Math.max(y0, y1, y2, y3),
opt_extent
);
}
/**
* @param {import("./coordinate.js").Coordinate} center Center.
* @param {number} resolution Resolution.
* @param {number} rotation Rotation.
* @param {import("./size.js").Size} size Size.
* @return {Array<number>} Linear ring representing the viewport.
*/
export function getRotatedViewport(center, resolution, rotation, size) {
const dx = (resolution * size[0]) / 2; const dx = (resolution * size[0]) / 2;
const dy = (resolution * size[1]) / 2; const dy = (resolution * size[1]) / 2;
const cosRotation = Math.cos(rotation); const cosRotation = Math.cos(rotation);
@@ -541,21 +564,18 @@ export function getForViewAndSize(
const ySin = dy * sinRotation; const ySin = dy * sinRotation;
const x = center[0]; const x = center[0];
const y = center[1]; const y = center[1];
const x0 = x - xCos + ySin; return [
const x1 = x - xCos - ySin; x - xCos + ySin,
const x2 = x + xCos - ySin; y - xSin - yCos,
const x3 = x + xCos + ySin; x - xCos - ySin,
const y0 = y - xSin - yCos; y - xSin + yCos,
const y1 = y - xSin + yCos; x + xCos - ySin,
const y2 = y + xSin + yCos; y + xSin + yCos,
const y3 = y + xSin - yCos; x + xCos + ySin,
return createOrUpdate( y + xSin - yCos,
Math.min(x0, x1, x2, x3), x - xCos + ySin,
Math.min(y0, y1, y2, y3), y - xSin - yCos,
Math.max(x0, x1, x2, x3), ];
Math.max(y0, y1, y2, y3),
opt_extent
);
} }
/** /**

View File

@@ -20,6 +20,7 @@ import {
equals, equals,
getHeight, getHeight,
getIntersection, getIntersection,
getRotatedViewport,
getTopLeft, getTopLeft,
getWidth, getWidth,
intersects, intersects,
@@ -308,8 +309,22 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const tmpExtent = this.tmpExtent; const tmpExtent = this.tmpExtent;
const tmpTileRange = this.tmpTileRange_; const tmpTileRange = this.tmpTileRange_;
this.newTiles_ = false; this.newTiles_ = false;
const viewport = rotation
? getRotatedViewport(
viewState.center,
resolution,
rotation,
frameState.size
)
: undefined;
for (let x = tileRange.minX; x <= tileRange.maxX; ++x) { for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (let y = tileRange.minY; y <= tileRange.maxY; ++y) { for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {
if (
rotation &&
!tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)
) {
continue;
}
const tile = this.getTile(z, x, y, frameState); const tile = this.getTile(z, x, y, frameState);
if (this.isDrawableTile(tile)) { if (this.isDrawableTile(tile)) {
const uid = getUid(this); const uid = getUid(this);
@@ -709,6 +724,15 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const wantedTiles = frameState.wantedTiles[tileSourceKey]; const wantedTiles = frameState.wantedTiles[tileSourceKey];
const tileQueue = frameState.tileQueue; const tileQueue = frameState.tileQueue;
const minZoom = tileGrid.getMinZoom(); const minZoom = tileGrid.getMinZoom();
const rotation = frameState.viewState.rotation;
const viewport = rotation
? getRotatedViewport(
frameState.viewState.center,
frameState.viewState.resolution,
rotation,
frameState.size
)
: undefined;
let tileCount = 0; let tileCount = 0;
let tile, tileRange, tileResolution, x, y, z; let tile, tileRange, tileResolution, x, y, z;
for (z = minZoom; z <= currentZ; ++z) { for (z = minZoom; z <= currentZ; ++z) {
@@ -716,6 +740,12 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
tileResolution = tileGrid.getResolution(z); tileResolution = tileGrid.getResolution(z);
for (x = tileRange.minX; x <= tileRange.maxX; ++x) { for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) { for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
if (
rotation &&
!tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)
) {
continue;
}
if (currentZ - z <= preload) { if (currentZ - z <= preload) {
++tileCount; ++tileCount;
tile = tileSource.getTile(z, x, y, pixelRatio, projection); tile = tileSource.getTile(z, x, y, pixelRatio, projection);

View File

@@ -9,6 +9,7 @@ import {assert} from '../asserts.js';
import {ceil, clamp, floor} from '../math.js'; import {ceil, clamp, floor} from '../math.js';
import {createOrUpdate, getTopLeft} from '../extent.js'; import {createOrUpdate, getTopLeft} from '../extent.js';
import {createOrUpdate as createOrUpdateTileCoord} from '../tilecoord.js'; import {createOrUpdate as createOrUpdateTileCoord} from '../tilecoord.js';
import {intersectsLinearRing} from '../geom/flat/intersectsextent.js';
import {isSorted, linearFindNearest} from '../array.js'; import {isSorted, linearFindNearest} from '../array.js';
import {toSize} from '../size.js'; import {toSize} from '../size.js';
@@ -656,6 +657,22 @@ class TileGrid {
return clamp(z, this.minZoom, this.maxZoom); return clamp(z, this.minZoom, this.maxZoom);
} }
/**
* The tile with the provided tile coordinate intersects the given viewport.
* @param {import('../tilecoord.js').TileCoord} tileCoord Tile coordinate.
* @param {Array<number>} viewport Viewport as returned from {@link module:ol/extent.getRotatedViewport}.
* @return {boolean} The tile with the provided tile coordinate intersects the given viewport.
*/
tileCoordIntersectsViewport(tileCoord, viewport) {
return intersectsLinearRing(
viewport,
0,
viewport.length,
2,
this.getTileCoordExtent(tileCoord)
);
}
/** /**
* @param {!import("../extent.js").Extent} extent Extent for this tile grid. * @param {!import("../extent.js").Extent} extent Extent for this tile grid.
* @private * @private