From 5cdc96b1b928bb82c29b860875f27b2cd1b8e2ff Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Wed, 8 May 2024 21:23:50 +0200 Subject: [PATCH] Hit detect symbols with declutterMode: 'none' --- src/ol/render/canvas/Executor.js | 8 +++- src/ol/render/canvas/ExecutorGroup.js | 4 +- .../renderer/canvas/vectortilelayer.test.js | 47 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/ol/render/canvas/Executor.js b/src/ol/render/canvas/Executor.js index 4e83a886c74..091ede3e417 100644 --- a/src/ol/render/canvas/Executor.js +++ b/src/ol/render/canvas/Executor.js @@ -52,7 +52,7 @@ import {transform2D} from '../../geom/flat/transform.js'; /** * @template T - * @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default): T} FeatureCallback + * @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default, import("../../style/Style.js").DeclutterMode): T} FeatureCallback */ /** @@ -1155,7 +1155,11 @@ class Executor { feature = /** @type {import("../../Feature.js").FeatureLike} */ ( instruction[1] ); - const result = featureCallback(feature, currentGeometry); + const result = featureCallback( + feature, + currentGeometry, + declutterMode, + ); if (result) { return result; } diff --git a/src/ol/render/canvas/ExecutorGroup.js b/src/ol/render/canvas/ExecutorGroup.js index d9c7c3ef58e..95b11409ed6 100644 --- a/src/ol/render/canvas/ExecutorGroup.js +++ b/src/ol/render/canvas/ExecutorGroup.js @@ -255,9 +255,10 @@ class ExecutorGroup { /** * @param {import("../../Feature.js").FeatureLike} feature Feature. * @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry. + * @param {import('../../style/Style.js').DeclutterMode} declutterMode Declutter mode. * @return {T|undefined} Callback result. */ - function featureCallback(feature, geometry) { + function featureCallback(feature, geometry, declutterMode) { const imageData = context.getImageData( 0, 0, @@ -268,6 +269,7 @@ class ExecutorGroup { if (imageData[indexes[i]] > 0) { if ( !declutteredFeatures || + declutterMode === 'none' || (builderType !== 'Image' && builderType !== 'Text') || declutteredFeatures.includes(feature) ) { diff --git a/test/browser/spec/ol/renderer/canvas/vectortilelayer.test.js b/test/browser/spec/ol/renderer/canvas/vectortilelayer.test.js index f77da5a5671..663b849fbbf 100644 --- a/test/browser/spec/ol/renderer/canvas/vectortilelayer.test.js +++ b/test/browser/spec/ol/renderer/canvas/vectortilelayer.test.js @@ -14,6 +14,7 @@ import VectorTileLayer from '../../../../../../src/ol/layer/VectorTile.js'; import VectorTileSource from '../../../../../../src/ol/source/VectorTile.js'; import View from '../../../../../../src/ol/View.js'; import XYZ from '../../../../../../src/ol/source/XYZ.js'; +import {Circle, Fill} from '../../../../../../src/ol/style.js'; import {VOID} from '../../../../../../src/ol/functions.js'; import {checkedFonts} from '../../../../../../src/ol/render/canvas.js'; import {create} from '../../../../../../src/ol/transform.js'; @@ -756,5 +757,51 @@ describe('ol/renderer/canvas/VectorTileLayer', function () { done(); }); }); + + it('detects symbols with `declutterMode: "none"`', (done) => { + const target = document.createElement('div'); + target.style.width = '100px'; + target.style.height = '100px'; + document.body.appendChild(target); + const extent = [ + 1824704.739223726, 6141868.096770482, 1827150.7241288517, + 6144314.081675608, + ]; + const source = new VectorTileSource({ + format: new MVT(), + url: 'spec/ol/data/14-8938-5680.vector.pbf', + minZoom: 14, + maxZoom: 14, + }); + const layer = new VectorTileLayer({ + declutter: true, + extent: extent, + source: source, + style: new Style({ + image: new Circle({ + declutterMode: 'none', + radius: 5, + fill: new Fill({color: 'red'}), + }), + }), + }); + const map = new Map({ + target: target, + layers: [layer], + view: new View({ + center: getCenter(extent), + zoom: 14, + }), + }); + map.once('rendercomplete', () => { + setTimeout(() => { + map.setTarget(null); + document.body.removeChild(target); + }, 0); + const features = map.getFeaturesAtPixel([11, 75]); + expect(features).to.have.length(1); + done(); + }); + }); }); });