From b7d022f80e952ab75cac4ed5bddd0231d628aebd Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Thu, 17 Feb 2022 18:12:19 +0100 Subject: [PATCH] Use same clipping method for vector and image tiles --- src/ol/renderer/canvas/VectorTileLayer.js | 56 +++++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 1862ee8a9c..724404df98 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -663,20 +663,63 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { const replayTypes = VECTOR_REPLAYS[renderMode]; const viewState = frameState.viewState; const rotation = viewState.rotation; + const tileSource = layer.getSource(); + const tileGrid = tileSource.getTileGridForProjection(viewState.projection); + const z = tileGrid.getZForResolution( + viewState.resolution, + tileSource.zDirection + ); const tiles = this.renderedTiles; + const clips = []; + const clipZs = []; for (let i = tiles.length - 1; i >= 0; --i) { const tile = /** @type {import("../../VectorRenderTile.js").default} */ ( tiles[i] ); + const executorGroups = tile.executorGroups[getUid(layer)].filter( + (group) => group.hasExecutors(replayTypes) + ); + if (executorGroups.length === 0) { + continue; + } const transform = this.getTileRenderTransform(tile, frameState); - const executorGroups = tile.executorGroups[getUid(layer)]; + const currentZ = tile.tileCoord[0]; + let contextSaved = false; + // Clip mask for regions in this tile that already filled by a higher z tile + const currentClip = executorGroups[0].getClipCoords(transform); + for (let j = 0, jj = clips.length; j < jj; ++j) { + if (z !== currentZ && currentZ < clipZs[j]) { + const clip = clips[j]; + if ( + intersects( + [currentClip[0], currentClip[3], currentClip[4], currentClip[7]], + [clip[0], clip[3], clip[4], clip[7]] + ) + ) { + if (!contextSaved) { + context.save(); + contextSaved = true; + } + context.beginPath(); + // counter-clockwise (outer ring) for current tile + context.moveTo(currentClip[0], currentClip[1]); + context.lineTo(currentClip[2], currentClip[3]); + context.lineTo(currentClip[4], currentClip[5]); + context.lineTo(currentClip[6], currentClip[7]); + // clockwise (inner ring) for higher z tile + context.moveTo(clip[6], clip[7]); + context.lineTo(clip[4], clip[5]); + context.lineTo(clip[2], clip[3]); + context.lineTo(clip[0], clip[1]); + context.clip(); + } + } + } + clips.push(currentClip); + clipZs.push(currentZ); for (let t = 0, tt = executorGroups.length; t < tt; ++t) { const executorGroup = executorGroups[t]; - if (!executorGroup.hasExecutors(replayTypes)) { - // sourceTile has no instructions of the types we want to render - continue; - } executorGroup.execute( context, 1, @@ -686,6 +729,9 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { replayTypes ); } + if (contextSaved) { + context.restore(); + } } context.globalAlpha = alpha;