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,
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 dy = (resolution * size[1]) / 2;
const cosRotation = Math.cos(rotation);
@@ -541,21 +564,18 @@ export function getForViewAndSize(
const ySin = dy * sinRotation;
const x = center[0];
const y = center[1];
const x0 = x - xCos + ySin;
const x1 = x - xCos - ySin;
const x2 = x + xCos - ySin;
const x3 = x + xCos + ySin;
const y0 = y - xSin - yCos;
const y1 = y - xSin + yCos;
const y2 = y + xSin + yCos;
const y3 = y + xSin - yCos;
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
);
return [
x - xCos + ySin,
y - xSin - yCos,
x - xCos - ySin,
y - xSin + yCos,
x + xCos - ySin,
y + xSin + yCos,
x + xCos + ySin,
y + xSin - yCos,
x - xCos + ySin,
y - xSin - yCos,
];
}
/**

View File

@@ -20,6 +20,7 @@ import {
equals,
getHeight,
getIntersection,
getRotatedViewport,
getTopLeft,
getWidth,
intersects,
@@ -308,8 +309,22 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const tmpExtent = this.tmpExtent;
const tmpTileRange = this.tmpTileRange_;
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 y = tileRange.minY; y <= tileRange.maxY; ++y) {
if (
rotation &&
!tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)
) {
continue;
}
const tile = this.getTile(z, x, y, frameState);
if (this.isDrawableTile(tile)) {
const uid = getUid(this);
@@ -709,6 +724,15 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const wantedTiles = frameState.wantedTiles[tileSourceKey];
const tileQueue = frameState.tileQueue;
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 tile, tileRange, tileResolution, x, y, z;
for (z = minZoom; z <= currentZ; ++z) {
@@ -716,6 +740,12 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
tileResolution = tileGrid.getResolution(z);
for (x = tileRange.minX; x <= tileRange.maxX; ++x) {
for (y = tileRange.minY; y <= tileRange.maxY; ++y) {
if (
rotation &&
!tileGrid.tileCoordIntersectsViewport([z, x, y], viewport)
) {
continue;
}
if (currentZ - z <= preload) {
++tileCount;
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 {createOrUpdate, getTopLeft} from '../extent.js';
import {createOrUpdate as createOrUpdateTileCoord} from '../tilecoord.js';
import {intersectsLinearRing} from '../geom/flat/intersectsextent.js';
import {isSorted, linearFindNearest} from '../array.js';
import {toSize} from '../size.js';
@@ -656,6 +657,22 @@ class TileGrid {
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.
* @private