From 12289b8ef9ba03fa656e759272974dcf3475a06c Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 12:20:38 +0200 Subject: [PATCH 1/7] Declutter in correct order and for all layers --- changelog/upgrade-notes.md | 8 ++++ src/ol/PluggableMap.js | 2 + src/ol/layer/BaseVector.js | 5 +- src/ol/layer/VectorTile.js | 5 +- src/ol/render/canvas/Executor.js | 30 +++++++----- src/ol/render/canvas/ExecutorGroup.js | 46 ++++++------------- src/ol/renderer/Composite.js | 1 + src/ol/renderer/Layer.js | 3 +- src/ol/renderer/Map.js | 26 +++++++++-- src/ol/renderer/canvas/VectorImageLayer.js | 6 +-- src/ol/renderer/canvas/VectorLayer.js | 35 ++++++-------- src/ol/renderer/canvas/VectorTileLayer.js | 30 ++++-------- .../spec/ol/render/canvas/textbuilder.test.js | 2 +- test/spec/ol/renderer/canvas/builder.test.js | 2 +- 14 files changed, 105 insertions(+), 96 deletions(-) diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index fd31ad4fec..7740f1e13d 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -98,6 +98,14 @@ If you were previously using `VectorTile` layers with `renderMode: 'vector'`, yo If you were previously using `Vector` layers with `renderMode: 'image'`, you have to remove this configuration option. Instead, use the new `ol/layer/VectorImage` layer with your `ol/source/Vector`. +##### New declutter behavior + +If a map has more than one layer with `declutter` set to true, decluttering now considers all layers instead of decluttering each layer separately. The higher the z-index of the layer, the higher the priority of decluttered items. + +Within a layer, the declutter order has changed. Previously, styles with a lower `zIndex` were prioritized over those with a higher `zIndex`. Now the opposite order is used. + +On vector layers, even if decluttered images or texts have a lower z-Index than polygons or lines, they will now be rendered on top of the polygons or lines. For vector tile layers, this was the case already in previous releases. + ##### New `prerender` and `postrender` layer events replace old `precompose`, `render` and `postcompose` events If you were previously registering for `precompose` and `postcompose` events, you should now register for `prerender` and `postrender` events on layers. Instead of the previous `render` event, you should now listen for `postrender`. Layers are no longer composed to a single Canvas element. Instead, they are added to the map viewport as individual elements. diff --git a/src/ol/PluggableMap.js b/src/ol/PluggableMap.js index 6cf34cbf21..9ab36d6b55 100644 --- a/src/ol/PluggableMap.js +++ b/src/ol/PluggableMap.js @@ -39,6 +39,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js * @property {boolean} animate * @property {import("./transform.js").Transform} coordinateToPixelTransform * @property {null|import("./extent.js").Extent} extent + * @property {Array<*>} declutterItems * @property {import("./coordinate.js").Coordinate} focus * @property {number} index * @property {Array} layerStatesArray @@ -1175,6 +1176,7 @@ class PluggableMap extends BaseObject { frameState = /** @type {FrameState} */ ({ animate: false, coordinateToPixelTransform: this.coordinateToPixelTransform_, + declutterItems: previousFrameState ? previousFrameState.declutterItems : [], extent: extent, focus: this.focus_ ? this.focus_ : viewState.center, index: this.frameIndex_++, diff --git a/src/ol/layer/BaseVector.js b/src/ol/layer/BaseVector.js index fd6255f4a9..6974eeddf1 100644 --- a/src/ol/layer/BaseVector.js +++ b/src/ol/layer/BaseVector.js @@ -32,8 +32,9 @@ import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style. * temporary layers. The standard way to add a layer to a map and have it managed by the map is to * use {@link module:ol/Map#addLayer}. * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all - * image and text styles, and the priority is defined by the z-index of the style. Lower z-index - * means higher priority. + * image and text styles of all layers that have set this to `true`. The priority is defined by the z-index + * of the layer, the `zIndex` of the style and the render order of features. Higher z-index means higher + * priority. Within the same z-index, a feature rendered before another has higher priority. * @property {import("../style/Style.js").StyleLike} [style] Layer style. See * {@link module:ol/style} for default style which will be used if this is not defined. * @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will diff --git a/src/ol/layer/VectorTile.js b/src/ol/layer/VectorTile.js index 9bf96d8128..e53dd9741a 100644 --- a/src/ol/layer/VectorTile.js +++ b/src/ol/layer/VectorTile.js @@ -46,8 +46,9 @@ import {assign} from '../obj.js'; * temporary layers. The standard way to add a layer to a map and have it managed by the map is to * use {@link module:ol/Map#addLayer}. * @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all - * image and text styles, and the priority is defined by the z-index of the style. Lower z-index - * means higher priority. + * image and text styles of all layers that have set this to `true`. The priority is defined by the z-index + * of the layer, the `zIndex` of the style and the render order of features. Higher z-index means higher + * priority. Within the same z-index, a feature rendered before another has higher priority. * @property {import("../style/Style.js").StyleLike} [style] Layer style. See * {@link module:ol/style} for default style which will be used if this is not defined. * @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will be diff --git a/src/ol/render/canvas/Executor.js b/src/ol/render/canvas/Executor.js index 162eac03a9..be254c38e3 100644 --- a/src/ol/render/canvas/Executor.js +++ b/src/ol/render/canvas/Executor.js @@ -21,6 +21,7 @@ import { import {createCanvasContext2D} from '../../dom.js'; import {labelCache, defaultTextAlign, measureTextHeight, measureAndCacheTextWidth, measureTextWidths} from '../canvas.js'; import Disposable from '../../Disposable.js'; +import rbush from 'rbush'; /** @@ -58,15 +59,10 @@ class Executor extends Disposable { * @param {number} resolution Resolution. * @param {number} pixelRatio Pixel ratio. * @param {boolean} overlaps The replay can have overlapping geometries. - * @param {?} declutterTree Declutter tree. * @param {SerializableInstructions} instructions The serializable instructions */ - constructor(resolution, pixelRatio, overlaps, declutterTree, instructions) { + constructor(resolution, pixelRatio, overlaps, instructions) { super(); - /** - * @type {?} - */ - this.declutterTree = declutterTree; /** * @protected @@ -93,6 +89,11 @@ class Executor extends Disposable { */ this.alignFill_; + /** + * @type {Array<*>} + */ + this.declutterItems = []; + /** * @protected * @type {Array<*>} @@ -412,8 +413,10 @@ class Executor extends Disposable { /** * @param {import("../canvas.js").DeclutterGroup} declutterGroup Declutter group. * @param {import("../../Feature.js").FeatureLike} feature Feature. + * @param {?} declutterTree Declutter tree. + * @return {?} Declutter tree. */ - renderDeclutter_(declutterGroup, feature) { + renderDeclutter(declutterGroup, feature, declutterTree) { if (declutterGroup && declutterGroup.length > 5) { const groupCount = declutterGroup[4]; if (groupCount == 1 || groupCount == declutterGroup.length - 5) { @@ -425,8 +428,11 @@ class Executor extends Disposable { maxY: /** @type {number} */ (declutterGroup[3]), value: feature }; - if (!this.declutterTree.collides(box)) { - this.declutterTree.insert(box); + if (!declutterTree) { + declutterTree = rbush(9, undefined); + } + if (!declutterTree.collides(box)) { + declutterTree.insert(box); for (let j = 5, jj = declutterGroup.length; j < jj; ++j) { const declutterData = /** @type {Array} */ (declutterGroup[j]); if (declutterData) { @@ -443,6 +449,7 @@ class Executor extends Disposable { createOrUpdateEmpty(declutterGroup); } } + return declutterTree; } /** @@ -497,6 +504,7 @@ class Executor extends Disposable { featureCallback, opt_hitExtent ) { + this.declutterItems.length = 0; /** @type {Array} */ let pixelCoordinates; if (this.pixelCoordinates_ && equals(transform, this.renderedTransform_)) { @@ -670,7 +678,7 @@ class Executor extends Disposable { backgroundFill ? /** @type {Array<*>} */ (lastFillInstruction) : null, backgroundStroke ? /** @type {Array<*>} */ (lastStrokeInstruction) : null); } - this.renderDeclutter_(declutterGroup, feature); + this.declutterItems.push(this, declutterGroup, feature); ++i; break; case CanvasInstruction.DRAW_CHARS: @@ -739,7 +747,7 @@ class Executor extends Disposable { } } } - this.renderDeclutter_(declutterGroup, feature); + this.declutterItems.push(this, declutterGroup, feature); ++i; break; case CanvasInstruction.END_GEOMETRY: diff --git a/src/ol/render/canvas/ExecutorGroup.js b/src/ol/render/canvas/ExecutorGroup.js index 362de136f1..371f3f3c5d 100644 --- a/src/ol/render/canvas/ExecutorGroup.js +++ b/src/ol/render/canvas/ExecutorGroup.js @@ -35,18 +35,12 @@ class ExecutorGroup extends Disposable { * @param {number} resolution Resolution. * @param {number} pixelRatio Pixel ratio. * @param {boolean} overlaps The executor group can have overlapping geometries. - * @param {?} declutterTree Declutter tree for declutter processing in postrender. * @param {!Object>} allInstructions * The serializable instructions. * @param {number=} opt_renderBuffer Optional rendering buffer. */ - constructor(maxExtent, resolution, pixelRatio, overlaps, declutterTree, allInstructions, opt_renderBuffer) { + constructor(maxExtent, resolution, pixelRatio, overlaps, allInstructions, opt_renderBuffer) { super(); - /** - * Declutter tree. - * @private - */ - this.declutterTree_ = declutterTree; /** * @private @@ -128,7 +122,7 @@ class ExecutorGroup extends Disposable { for (const builderType in instructionByZindex) { const instructions = instructionByZindex[builderType]; executors[builderType] = new Executor( - this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_, instructions); + this.resolution_, this.pixelRatio_, this.overlaps_, instructions); } } } @@ -172,7 +166,7 @@ class ExecutorGroup extends Disposable { * @param {number} hitTolerance Hit tolerance in pixels. * @param {Object} skippedFeaturesHash Ids of features to skip. * @param {function(import("../../Feature.js").FeatureLike): T} callback Feature callback. - * @param {Object} declutterReplays Declutter replays. + * @param {Array} declutteredFeatures Decluttered features. * @return {T|undefined} Callback result. * @template T */ @@ -183,7 +177,7 @@ class ExecutorGroup extends Disposable { hitTolerance, skippedFeaturesHash, callback, - declutterReplays + declutteredFeatures ) { hitTolerance = Math.round(hitTolerance); @@ -213,12 +207,6 @@ class ExecutorGroup extends Disposable { } const mask = getCircleArray(hitTolerance); - let declutteredFeatures; - if (this.declutterTree_) { - declutteredFeatures = this.declutterTree_.all().map(function(entry) { - return entry.value; - }); - } let builderType; @@ -261,20 +249,10 @@ class ExecutorGroup extends Disposable { builderType = ORDER[j]; executor = executors[builderType]; if (executor !== undefined) { - if (declutterReplays && - (builderType == BuilderType.IMAGE || builderType == BuilderType.TEXT)) { - const declutter = declutterReplays[zIndexKey]; - if (!declutter) { - declutterReplays[zIndexKey] = [executor, transform.slice(0)]; - } else { - declutter.push(executor, transform.slice(0)); - } - } else { - result = executor.executeHitDetection(context, transform, rotation, - skippedFeaturesHash, featureCallback, hitExtent); - if (result) { - return result; - } + result = executor.executeHitDetection(context, transform, rotation, + skippedFeaturesHash, featureCallback, hitExtent); + if (result) { + return result; } } } @@ -446,14 +424,20 @@ export function getCircleArray(radius) { * @param {CanvasRenderingContext2D} context Context. * @param {number} rotation Rotation. * @param {boolean} snapToPixel Snap point symbols and text to integer pixels. + * @param {Array>} declutterItems Declutter items. */ -export function replayDeclutter(declutterReplays, context, rotation, snapToPixel) { +export function replayDeclutter(declutterReplays, context, rotation, snapToPixel, declutterItems) { const zs = Object.keys(declutterReplays).map(Number).sort(numberSafeCompareFunction); const skippedFeatureUids = {}; for (let z = 0, zz = zs.length; z < zz; ++z) { const executorData = declutterReplays[zs[z].toString()]; + let currentExecutor; for (let i = 0, ii = executorData.length; i < ii;) { const executor = executorData[i++]; + if (executor !== currentExecutor) { + currentExecutor = executor; + declutterItems.push(executor.declutterItems); + } const transform = executorData[i++]; executor.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); } diff --git a/src/ol/renderer/Composite.js b/src/ol/renderer/Composite.js index fa1e3b2716..c32ad2175e 100644 --- a/src/ol/renderer/Composite.js +++ b/src/ol/renderer/Composite.js @@ -99,6 +99,7 @@ class CompositeMapRenderer extends MapRenderer { this.children_.push(element); } } + super.renderFrame(frameState); replaceChildren(this.element_, this.children_); diff --git a/src/ol/renderer/Layer.js b/src/ol/renderer/Layer.js index b65c917e73..b63ea42195 100644 --- a/src/ol/renderer/Layer.js +++ b/src/ol/renderer/Layer.js @@ -89,10 +89,11 @@ class LayerRenderer extends Observable { * @param {import("../PluggableMap.js").FrameState} frameState Frame state. * @param {number} hitTolerance Hit tolerance in pixels. * @param {function(import("../Feature.js").FeatureLike, import("../layer/Layer.js").default): T} callback Feature callback. + * @param {Array} declutteredFeatures Decluttered features. * @return {T|void} Callback result. * @template T */ - forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) {} + forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures) {} /** * @abstract diff --git a/src/ol/renderer/Map.js b/src/ol/renderer/Map.js index 093a6fe85f..488698d081 100644 --- a/src/ol/renderer/Map.js +++ b/src/ol/renderer/Map.js @@ -28,6 +28,11 @@ class MapRenderer extends Disposable { */ this.map_ = map; + /** + * @private + */ + this.declutterTree_ = null; + /** * @private * @type {!Object} @@ -133,6 +138,12 @@ class MapRenderer extends Disposable { const layerStates = frameState.layerStatesArray; const numLayers = layerStates.length; + let declutteredFeatures; + if (this.declutterTree_) { + declutteredFeatures = this.declutterTree_.all().map(function(entry) { + return entry.value; + }); + } let i; for (i = numLayers - 1; i >= 0; --i) { const layerState = layerStates[i]; @@ -144,7 +155,7 @@ class MapRenderer extends Disposable { const callback = forEachFeatureAtCoordinate.bind(null, layerState.managed); result = layerRenderer.forEachFeatureAtCoordinate( source.getWrapX() ? translatedCoordinate : coordinate, - frameState, hitTolerance, callback); + frameState, hitTolerance, callback, declutteredFeatures); } if (result) { return result; @@ -252,11 +263,20 @@ class MapRenderer extends Disposable { /** * Render. - * @abstract * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. */ renderFrame(frameState) { - abstract(); + if (this.declutterTree_) { + this.declutterTree_.clear(); + } + const items = frameState.declutterItems; + for (let z = items.length - 1; z >= 0; --z) { + const zIndexItems = items[z]; + for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) { + this.declutterTree_ = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], this.declutterTree_); + } + } + items.length = 0; } /** diff --git a/src/ol/renderer/canvas/VectorImageLayer.js b/src/ol/renderer/canvas/VectorImageLayer.js index f35397bbdb..c92c36885e 100644 --- a/src/ol/renderer/canvas/VectorImageLayer.js +++ b/src/ol/renderer/canvas/VectorImageLayer.js @@ -123,11 +123,11 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { /** * @inheritDoc */ - forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback) { + forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures) { if (this.vectorRenderer_) { - return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback); + return this.vectorRenderer_.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures); } else { - return super.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback); + return super.forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures); } } } diff --git a/src/ol/renderer/canvas/VectorLayer.js b/src/ol/renderer/canvas/VectorLayer.js index 26271e7f41..aa79c35644 100644 --- a/src/ol/renderer/canvas/VectorLayer.js +++ b/src/ol/renderer/canvas/VectorLayer.js @@ -5,11 +5,10 @@ import {getUid} from '../../util.js'; import ViewHint from '../../ViewHint.js'; import {listen, unlisten} from '../../events.js'; import EventType from '../../events/EventType.js'; -import rbush from 'rbush'; import {buffer, createEmpty, containsExtent, getWidth} from '../../extent.js'; import {labelCache} from '../../render/canvas.js'; import CanvasBuilderGroup from '../../render/canvas/BuilderGroup.js'; -import ExecutorGroup from '../../render/canvas/ExecutorGroup.js'; +import ExecutorGroup, {replayDeclutter} from '../../render/canvas/ExecutorGroup.js'; import CanvasLayerRenderer from './Layer.js'; import {defaultOrder as defaultRenderOrder, getTolerance as getRenderTolerance, getSquaredTolerance as getSquaredRenderTolerance, renderFeature} from '../vector.js'; import {toString as transformToString, makeScale, makeInverse} from '../../transform.js'; @@ -28,12 +27,6 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { super(vectorLayer); - /** - * Declutter tree. - * @private - */ - this.declutterTree_ = vectorLayer.getDeclutter() ? rbush(9, undefined) : null; - /** * @private * @type {boolean} @@ -138,17 +131,14 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { this.clip(context, frameState, clipExtent); } - if (this.declutterTree_) { - this.declutterTree_.clear(); - } - const viewHints = frameState.viewHints; const snapToPixel = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]); const transform = this.getRenderTransform(frameState, width, height, 0); const skippedFeatureUids = layerState.managed ? frameState.skippedFeatureUids : {}; - replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); + const declutterReplays = /** @type {import("../../layer/Vector.js").default} */ (this.getLayer()).getDeclutter() ? {} : null; + replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel, undefined, declutterReplays); if (vectorSource.getWrapX() && projection.canWrapX() && !containsExtent(projectionExtent, extent)) { let startX = extent[0]; @@ -159,7 +149,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { --world; offsetX = worldWidth * world; const transform = this.getRenderTransform(frameState, width, height, offsetX); - replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); + replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel, undefined, declutterReplays); startX += worldWidth; } world = 0; @@ -168,10 +158,15 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { ++world; offsetX = worldWidth * world; const transform = this.getRenderTransform(frameState, width, height, offsetX); - replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel); + replayGroup.execute(context, transform, rotation, skippedFeatureUids, snapToPixel, undefined, declutterReplays); startX -= worldWidth; } } + if (declutterReplays) { + const viewHints = frameState.viewHints; + const hifi = !(viewHints[ViewHint.ANIMATING] || viewHints[ViewHint.INTERACTING]); + replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems); + } if (clipped) { context.restore(); @@ -190,7 +185,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { /** * @inheritDoc */ - forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg) { + forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures) { if (!this.replayGroup_) { return undefined; } else { @@ -208,9 +203,9 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { const key = getUid(feature); if (!(key in features)) { features[key] = true; - return callback.call(thisArg, feature, layer); + return callback(feature, layer); } - }, null); + }, declutteredFeatures); return result; } } @@ -299,7 +294,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { const replayGroup = new CanvasBuilderGroup( getRenderTolerance(resolution, pixelRatio), extent, resolution, - pixelRatio, !!this.declutterTree_); + pixelRatio, vectorLayer.getDeclutter()); vectorSource.loadFeatures(extent, resolution, projection); @@ -339,7 +334,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer { const replayGroupInstructions = replayGroup.finish(); const executorGroup = new ExecutorGroup(extent, resolution, - pixelRatio, vectorSource.getOverlaps(), this.declutterTree_, + pixelRatio, vectorSource.getOverlaps(), replayGroupInstructions, vectorLayer.getRenderBuffer()); this.renderedResolution_ = resolution; diff --git a/src/ol/renderer/canvas/VectorTileLayer.js b/src/ol/renderer/canvas/VectorTileLayer.js index 454b9b0ca8..1b74d9e4ba 100644 --- a/src/ol/renderer/canvas/VectorTileLayer.js +++ b/src/ol/renderer/canvas/VectorTileLayer.js @@ -7,7 +7,6 @@ import TileState from '../../TileState.js'; import ViewHint from '../../ViewHint.js'; import {listen, unlisten, unlistenByKey} from '../../events.js'; import EventType from '../../events/EventType.js'; -import rbush from 'rbush'; import {buffer, containsCoordinate, equals, getIntersection, getTopLeft, intersects} from '../../extent.js'; import VectorTileRenderType from '../../layer/VectorTileRenderType.js'; import ReplayType from '../../render/canvas/BuilderType.js'; @@ -103,12 +102,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { */ this.inverseOverlayPixelTransform_ = createTransform(); - /** - * Declutter tree. - * @private - */ - this.declutterTree_ = layer.getDeclutter() ? rbush(9, undefined) : null; - /** * @private * @type {boolean} @@ -274,7 +267,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { buffer(sharedExtent, layer.getRenderBuffer() * resolution, this.tmpExtent); builderState.dirty = false; const builderGroup = new CanvasBuilderGroup(0, sharedExtent, resolution, - pixelRatio, !!this.declutterTree_); + pixelRatio, layer.getDeclutter()); const squaredTolerance = getSquaredRenderTolerance(resolution, pixelRatio); /** @@ -310,7 +303,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { null : sharedExtent; const renderingReplayGroup = new CanvasExecutorGroup(replayExtent, resolution, - pixelRatio, source.getOverlaps(), this.declutterTree_, executorGroupInstructions, layer.getRenderBuffer()); + pixelRatio, source.getOverlaps(), executorGroupInstructions, layer.getRenderBuffer()); tile.executorGroups[layerUid].push(renderingReplayGroup); } builderState.renderedRevision = revision; @@ -322,11 +315,12 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { /** * @inheritDoc */ - forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, thisArg) { + forEachFeatureAtCoordinate(coordinate, frameState, hitTolerance, callback, declutteredFeatures) { const resolution = frameState.viewState.resolution; const rotation = frameState.viewState.rotation; hitTolerance = hitTolerance == undefined ? 0 : hitTolerance; - const layer = this.getLayer(); + const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer()); + const declutter = layer.getDeclutter(); const source = layer.getSource(); const tileGrid = source.getTileGridForProjection(frameState.viewState.projection); /** @type {!Object} */ @@ -338,7 +332,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { let i, ii; for (i = 0, ii = renderedTiles.length; i < ii; ++i) { const tile = renderedTiles[i]; - if (!this.declutterTree_) { + if (!declutter) { // When not decluttering, we only need to consider the tile that contains the given // coordinate, because each feature will be rendered for each tile that contains it. const tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord); @@ -361,9 +355,9 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { } if (!(key in features)) { features[key] = true; - return callback.call(thisArg, feature, layer); + return callback(feature, layer); } - }, null); + }, declutteredFeatures); } } return found; @@ -464,9 +458,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { context.clearRect(0, 0, width, height); } - if (declutterReplays) { - this.declutterTree_.clear(); - } const tiles = this.renderedTiles; const tileGrid = source.getTileGridForProjection(frameState.viewState.projection); const clips = []; @@ -522,7 +513,7 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { } } if (declutterReplays) { - replayDeclutter(declutterReplays, context, rotation, hifi); + replayDeclutter(declutterReplays, context, rotation, hifi, frameState.declutterItems); } const opacity = layerState.opacity; @@ -552,9 +543,6 @@ class CanvasVectorTileLayerRenderer extends CanvasTileLayerRenderer { frameState.animate = true; delete this.renderTileImageQueue_[uid]; const layer = /** @type {import("../../layer/VectorTile.js").default} */ (this.getLayer()); - if (this.declutterTree_ && layer.getRenderMode() === VectorTileRenderType.IMAGE) { - this.declutterTree_.clear(); - } const viewState = frameState.viewState; const tileGrid = layer.getSource().getTileGridForProjection(viewState.projection); const tileResolution = tileGrid.getResolution(tile.tileCoord[0]); diff --git a/test/spec/ol/render/canvas/textbuilder.test.js b/test/spec/ol/render/canvas/textbuilder.test.js index 18f61732f3..850134b675 100644 --- a/test/spec/ol/render/canvas/textbuilder.test.js +++ b/test/spec/ol/render/canvas/textbuilder.test.js @@ -28,7 +28,7 @@ function createContext() { function executeInstructions(builder, expectedDrawTextImageCalls, expectedBuilderImageCalls) { const transform = createTransform(); const context = createContext(); - const executor = new Executor(0.02, 1, false, null, builder.finish()); + const executor = new Executor(0.02, 1, false, builder.finish()); sinon.spy(executor, 'drawTextImageWithPointPlacement_'); const replayImageStub = sinon.stub(executor, 'replayImage_'); executor.execute(context, transform); diff --git a/test/spec/ol/renderer/canvas/builder.test.js b/test/spec/ol/renderer/canvas/builder.test.js index da26600c2f..754cf7b3e2 100644 --- a/test/spec/ol/renderer/canvas/builder.test.js +++ b/test/spec/ol/renderer/canvas/builder.test.js @@ -35,7 +35,7 @@ describe('ol.render.canvas.BuilderGroup', function() { */ function execute(builder, skippedUids, pixelRatio, overlaps) { const executor = new ExecutorGroup([-180, -90, 180, 90], 1, - pixelRatio || 1, !!overlaps, null, builder.finish()); + pixelRatio || 1, !!overlaps, builder.finish()); executor.execute(context, transform, 0, skippedUids || {}); } From 1142caf5e847e657d81b2a52056e074379a386d8 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 14:31:01 +0200 Subject: [PATCH 2/7] Modify render tests to catch regressions --- .../layer-vector-decluttering/expected.png | Bin 5898 -> 6393 bytes .../cases/layer-vector-decluttering/main.js | 29 ++- .../expected.png | Bin 6107 -> 6192 bytes .../layer-vectorimage-decluttering/main.js | 212 +++++++++++++----- 4 files changed, 167 insertions(+), 74 deletions(-) diff --git a/rendering/cases/layer-vector-decluttering/expected.png b/rendering/cases/layer-vector-decluttering/expected.png index 7c067a94893b0cf31a426fff1a626860e5cfcf28..f81cac79e07124739b423c5d84fbb7b7a5ea0409 100644 GIT binary patch literal 6393 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 literal 5898 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 C8ze^n diff --git a/rendering/cases/layer-vector-decluttering/main.js b/rendering/cases/layer-vector-decluttering/main.js index 65e809b1e8..1af3a6f395 100644 --- a/rendering/cases/layer-vector-decluttering/main.js +++ b/rendering/cases/layer-vector-decluttering/main.js @@ -7,6 +7,7 @@ import Point from '../../../src/ol/geom/Point.js'; import Style from '../../../src/ol/style/Style.js'; import Text from '../../../src/ol/style/Text.js'; import CircleStyle from '../../../src/ol/style/Circle.js'; +import Fill from '../../../src/ol/style/Fill.js'; import Stroke from '../../../src/ol/style/Stroke.js'; import LineString from '../../../src/ol/geom/LineString.js'; @@ -59,9 +60,10 @@ source1.addFeature(new Feature({ })); layer1.setStyle(function(feature) { return new Style({ + zIndex: feature.get('zIndex'), image: new CircleStyle({ radius: 15, - stroke: new Stroke({ + fill: new Fill({ color: 'blue' }) }) @@ -88,15 +90,16 @@ source2.addFeature(new Feature({ })); layer2.setStyle(function(feature) { return new Style({ + zIndex: feature.get('zIndex'), text: new Text({ text: feature.get('text'), - font: '16px Ubuntu' + font: 'italic bold 18px Ubuntu' }) }); }); map.addLayer(layer2); -center = [center[0] + 500, center[1] + 500]; +center = [center[0] + 500, center[1] + 300]; source3.addFeature(new Feature({ geometry: new Point(center), text: 'center' @@ -112,16 +115,17 @@ source3.addFeature(new Feature({ layer3.setStyle(function(feature) { return new Style({ image: new CircleStyle({ - radius: 5, + radius: 10, stroke: new Stroke({ - color: 'red' + color: 'red', + width: 8 }) }), text: new Text({ text: feature.get('text'), - font: '16px Ubuntu', + font: 'italic bold 18px Ubuntu', textBaseline: 'bottom', - offsetY: -5 + offsetY: -12 }) }); }); @@ -130,11 +134,12 @@ map.addLayer(layer3); center = [center[0] - 2000, center[1] - 2000]; const point = new Feature(new Point(center)); point.setStyle(new Style({ - zIndex: 2, + zIndex: 1, image: new CircleStyle({ radius: 8, stroke: new Stroke({ - color: 'blue' + color: 'blue', + width: 4 }) }) })); @@ -143,7 +148,7 @@ const line = new Feature(new LineString([ [center[0] + 650, center[1] - 200] ])); line.setStyle(new Style({ - zIndex: 1, + zIndex: 2, stroke: new Stroke({ color: '#CCC', width: 12 @@ -151,7 +156,7 @@ line.setStyle(new Style({ text: new Text({ placement: 'line', text: 'east-west', - font: '16px Ubuntu', + font: 'italic bold 18px Ubuntu', overflow: true }) })); @@ -159,4 +164,4 @@ source4.addFeature(point); source4.addFeature(line); map.addLayer(layer4); -render({tolerance: 0.02}); +render({tolerance: 0.007}); diff --git a/rendering/cases/layer-vectorimage-decluttering/expected.png b/rendering/cases/layer-vectorimage-decluttering/expected.png index 5c3a16c967d3ca5c623178d24cb83a7aec17fc6d..7b907f8ba89832a669c27a16d7830126036e7af1 100644 GIT binary patch literal 6192 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 diff --git a/rendering/cases/layer-vectorimage-decluttering/main.js b/rendering/cases/layer-vectorimage-decluttering/main.js index 05cb3406c0..43d45ff972 100644 --- a/rendering/cases/layer-vectorimage-decluttering/main.js +++ b/rendering/cases/layer-vectorimage-decluttering/main.js @@ -1,72 +1,19 @@ -import Feature from '../../../src/ol/Feature.js'; import Map from '../../../src/ol/Map.js'; import View from '../../../src/ol/View.js'; import VectorSource from '../../../src/ol/source/Vector.js'; -import Style from '../../../src/ol/style/Style.js'; -import Stroke from '../../../src/ol/style/Stroke.js'; import VectorImageLayer from '../../../src/ol/layer/VectorImage.js'; -import CircleStyle from '../../../src/ol/style/Circle.js'; +import Feature from '../../../src/ol/Feature.js'; import Point from '../../../src/ol/geom/Point.js'; -import LineString from '../../../src/ol/geom/LineString.js'; +import Style from '../../../src/ol/style/Style.js'; import Text from '../../../src/ol/style/Text.js'; +import CircleStyle from '../../../src/ol/style/Circle.js'; +import Fill from '../../../src/ol/style/Fill.js'; +import Stroke from '../../../src/ol/style/Stroke.js'; +import LineString from '../../../src/ol/geom/LineString.js'; -const center = [1825927.7316762917, 6143091.089223046]; - -const source = new VectorSource(); -const vectorLayer1 = new VectorImageLayer({ - source: source, - style: function(feature) { - return new Style({ - image: new CircleStyle({ - radius: 15, - stroke: new Stroke({ - color: 'blue' - }) - }), - text: new Text({ - text: feature.get('text'), - font: '16px Ubuntu' - }) - }); - } -}); - -const centerFeature = new Feature({ - geometry: new Point(center), - text: 'center' -}); -source.addFeature(centerFeature); -source.addFeature(new Feature({ - geometry: new Point([center[0] - 540, center[1]]), - text: 'west' -})); -source.addFeature(new Feature({ - geometry: new Point([center[0] + 540, center[1]]), - text: 'east' -})); - -const line = new Feature(new LineString([ - [center[0] - 650, center[1] - 200], - [center[0] + 650, center[1] - 200] -])); -line.setStyle(new Style({ - stroke: new Stroke({ - color: '#CCC', - width: 12 - }), - text: new Text({ - placement: 'line', - text: 'east-west', - font: '16px Ubuntu' - }) -})); -source.addFeature(line); - +let center = [1825927.7316762917, 6143091.089223046]; const map = new Map({ pixelRatio: 1, - layers: [ - vectorLayer1 - ], target: 'map', view: new View({ center: center, @@ -74,6 +21,147 @@ const map = new Map({ }) }); -map.getView().fit(source.getExtent()); +const source1 = new VectorSource(); +const layer1 = new VectorImageLayer({ + declutter: true, + source: source1 +}); -render({tolerance: 0.02}); +const source2 = new VectorSource(); +const layer2 = new VectorImageLayer({ + declutter: true, + source: source2 +}); + +const source3 = new VectorSource(); +const layer3 = new VectorImageLayer({ + declutter: true, + source: source3 +}); + +const source4 = new VectorSource(); +const layer4 = new VectorImageLayer({ + declutter: true, + source: source4 +}); + +const feature1 = new Feature({ + geometry: new Point(center), + zIndex: 2 +}); +source1.addFeature(feature1); +source1.addFeature(new Feature({ + geometry: new Point([center[0] - 540, center[1]]), + zIndex: 3 +})); +source1.addFeature(new Feature({ + geometry: new Point([center[0] + 540, center[1]]), + zIndex: 1 +})); +layer1.setStyle(function(feature) { + return new Style({ + zIndex: feature.get('zIndex'), + image: new CircleStyle({ + radius: 15, + fill: new Fill({ + color: 'blue' + }) + }) + }); +}); +map.addLayer(layer1); + +center = [center[0] + 500, center[1] + 500]; +const feature2 = new Feature({ + geometry: new Point(center), + text: 'center', + zIndex: 2 +}); +source2.addFeature(feature2); +source2.addFeature(new Feature({ + geometry: new Point([center[0] - 540, center[1]]), + text: 'west', + zIndex: 3 +})); +source2.addFeature(new Feature({ + geometry: new Point([center[0] + 540, center[1]]), + text: 'east', + zIndex: 1 +})); +layer2.setStyle(function(feature) { + return new Style({ + zIndex: feature.get('zIndex'), + text: new Text({ + text: feature.get('text'), + font: 'italic bold 16px Ubuntu' + }) + }); +}); +map.addLayer(layer2); + +center = [center[0] + 500, center[1] + 300]; +source3.addFeature(new Feature({ + geometry: new Point(center), + text: 'center' +})); +source3.addFeature(new Feature({ + geometry: new Point([center[0] - 540, center[1]]), + text: 'west' +})); +source3.addFeature(new Feature({ + geometry: new Point([center[0] + 540, center[1]]), + text: 'east' +})); +layer3.setStyle(function(feature) { + return new Style({ + image: new CircleStyle({ + radius: 10, + stroke: new Stroke({ + color: 'red', + width: 8 + }) + }), + text: new Text({ + text: feature.get('text'), + font: 'italic bold 16px Ubuntu', + textBaseline: 'bottom', + offsetY: -12 + }) + }); +}); +map.addLayer(layer3); + +center = [center[0] - 2000, center[1] - 2000]; +const point = new Feature(new Point(center)); +point.setStyle(new Style({ + zIndex: 1, + image: new CircleStyle({ + radius: 8, + stroke: new Stroke({ + color: 'blue', + width: 4 + }) + }) +})); +const line = new Feature(new LineString([ + [center[0] - 650, center[1] - 200], + [center[0] + 650, center[1] - 200] +])); +line.setStyle(new Style({ + zIndex: 2, + stroke: new Stroke({ + color: '#CCC', + width: 12 + }), + text: new Text({ + placement: 'line', + text: 'east-west', + font: 'italic bold 16px Ubuntu', + overflow: true + }) +})); +source4.addFeature(point); +source4.addFeature(line); +map.addLayer(layer4); + +render({tolerance: 0.007}); From 6c8c8a64770ba1e7b1789116465055ead83f594f Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 14:34:17 +0200 Subject: [PATCH 3/7] Fix decluttering on VectorImage layers --- changelog/upgrade-notes.md | 2 +- .../expected.png | Bin 6192 -> 6841 bytes .../layer-vectorimage-decluttering/main.js | 6 +++--- src/ol/layer/BaseVector.js | 7 ++++--- src/ol/layer/VectorImage.js | 6 +++--- src/ol/layer/VectorTile.js | 7 ++++--- src/ol/render.js | 15 +++++++++++++++ src/ol/renderer/Map.js | 13 ++----------- src/ol/renderer/canvas/VectorImageLayer.js | 3 +++ 9 files changed, 35 insertions(+), 24 deletions(-) diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 7740f1e13d..25ed045ef9 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -100,7 +100,7 @@ If you were previously using `Vector` layers with `renderMode: 'image'`, you hav ##### New declutter behavior -If a map has more than one layer with `declutter` set to true, decluttering now considers all layers instead of decluttering each layer separately. The higher the z-index of the layer, the higher the priority of decluttered items. +If a map has more than one layer with `declutter` set to true, decluttering now considers all `Vector` and `VectorTile` instead of decluttering each layer separately. Only `VectorImage` layers continue to be decluttered separately. The higher the z-index of the layer, the higher the priority of decluttered items. Within a layer, the declutter order has changed. Previously, styles with a lower `zIndex` were prioritized over those with a higher `zIndex`. Now the opposite order is used. diff --git a/rendering/cases/layer-vectorimage-decluttering/expected.png b/rendering/cases/layer-vectorimage-decluttering/expected.png index 7b907f8ba89832a669c27a16d7830126036e7af1..5ccebf610e8df3494230a7860df838968de8ea54 100644 GIT binary patch literal 6841 zcmdsc`9D-|{Pr1JQBr8JD_Ue}v9BWvm8FR6OSWW>F_w&}?2=Z>mL!U?$JmER$}-lm zj-fCZTNr~eJokK_=ZEL@{0HCXr*q~$_c`Z%-{<|luIqhG+%02$ZZ1JC2!gn;8(cMo zAQ(7>LHjwt!S>-7H|DPZQ+*w%s7rVbf&>GuU%hfCIDL^A;m1Ec`STyrKu1ShGKG|? zz2u*@oNS_6fxY{A*4&g8usBHx^_%b*v|Q7MDv z$Ypy-G<^MbZ*Q;K9l~SQedo@do0w>NddJ*+(obb`_ES>LR5@49VXVi?v&5x76ZrH? zebJA(xw)NXwDGVc7%Rt03!h0z$l8ojd&K%DvC?}#xFDa}MWx^E?W3}PhuuH8evjmY z#sd3{7LzNSe;%^7ww9~GXohX1=jAq;XhL(QiHV6C>)pC4!iS);va)viN3K|Wh*yNp%ij>ln+-;C)=Epk(uiLs0(=w zmql^%ow;Ra=dFlJ>ujwUv_GJI;|ABumoG)m7Zep08Ce+_8QIZ3vcF)_uIZ-~<9rl% z;X3+(n~tK*|0G;?d~2S)U0_C^upSW`HSxG$Iks@F>tWZz8M;1Sh0 zu_6Yo7a^rwGXzd)W`L!3y#Lz?Hub8$KD|>tWHm=o)AcuhG`Eo6!-tm#Z3DRD;^GMO zI`THyUP2Fw)DTVxtLLUBTxfta$V>nJ{Y$Y;MxuN_(xII8$mr--nVCNI_GK=dY0AF2 zSy^bKG$q)Jory@K>CYxDW8lX_S*WN0+b-e4MUwjf73iW=T>B?yD{d^NPREsP|810UD7Q2po z^XN!bOaS{MgkBuQmWR`WDD~177;#zI&gJx-`GR7Oi8VYNI}>6e`~Ca(w%@Z2MZ z&a?)2;C*7K6wPHT-1u7P4=()bnpO2`FRdcRlsU<5raI}*rAwJYkGm9KfGw!5&Qxc| zn|HmGIF9?E`7RXVO;_uUawwbH`LwC3N?yJ`w3xYiFb8@u5!mn;_w3noo(WmoS*tzM z-;~e%U~(PLMtWzIJq}LVo`=P*i)V;H{~eEqwrG*IqsRZd^-WsX(zF(7VDKdQ0Ho{7 zX#pAdsgaHh`z&u#>2Ia+5!af!MbS&FFD4KTbVzMg+eBYf@^_mGEhT>a9&^{!NFLhW zg?avPx);6uZqdS!StNEm)So_hfVnjkolN$&4llZlwtmt)2mC-5h*rt{P~GZ{iOL8X zQ7=L@mPK3cUHkOCzpaTwi$U}A^On6YV}j%?ybH-+#(U1v<*w>Q=jBbvLqnet2UxZ( z9IG8&U0r2tDi5LoJaJT(3|Zp)!pUJ-WSt)^!IfdHvk@r-+5PtqcRPyA?Nng90B~dG zdOqnR=d~)N&;FFp8hoiArhe)S$LgvdwtU&n9_y1Us?D?7v`?(W|F0f2)0yVZxH#ik zT(9TkbP{BIU0ud>%3ANQ*Xzh?xzMo0xHuUh^<cdEVvG6x{?L(rDNa&TgbqZ#p zwmop(%nKtU*2iQlp~g(jFpTTlw{P!QSOndZ#oe{H@5;WGpz3j(6Kq1+nZ1T7@3G9v5TKS9}h?* zGd`Y6GoWmeOUn}j0|Wj2{g5Ld zu8k2-_1aVm#v`GWhO6E5RTJZ85EUFOPs|#7H zB4>uF`2S&Jh6PRDwdYLIY~9n-Gi`8U?U9w;xi@8iQh31M)qP78#XzKg{1}-i&|Gk# zt`V!Kc*P9sn0=*DR8mW8Jau=ec6q48iSP%G*S#`0MJI*8|h4b;ny?p}MP(>LloypCA3yIH}V@w)iGbcWYW69bV zmyl4ND}DYvrb%i!7-~%OZSX)ilkp$$jgMIYXwycG?d?U?kxOhEcEmx4h>XZcHURX& zOV#8ZJsc^VX17#Nv!}diM!x7!-#0@9&?Jmlr@CxXY}^#yqB-#YqH|OuMfG0G{!^z;ZIa=89>la4Z{E1blBxsFQU;63oyw$~ zl9KLJxML$a3shH6VWVcp_oxHIrOx}HK|5pyLhxe1j3MRKK*xLekez=&8RN8-W*&MX zYcRmXe=}*mWgdNJM8g(JgW83)9;t+cgsji?#i%b;JuNG{jGMlG{d&gut?^Kb?CuU3 zj;&n)RPQp;_!!z*O~Fl-X6gv*> z2M^BkXs+K%qiJpoITJdy8tUpJf$VcGA0CnUpyVxx*H}9kz8$=KCo}j@oDyZrK662) z+#O%(W50Uz=+Pfv&GImV5j%gy3Y#>SACf{v;V6yS`D2FttQQS+byIXOR8Rwjd|fh2uW>C>bQ0}>;HCH90N^Moln_@PrAeHmyX zrfO*In(~hynZCIAMCzlxYleo)TZLSF^FwA*P)!q|Fmt)u7PmV_vJ?@bY_-nUE^F;6 zyX+GJ6Qrv?xAXH?5v!|xlx;U7zyW#tHga%c$MB1@Z#EsOY5V*x3l*kNtyyBtgU z-m9x>yML=5yXc67$!D;zwSkC8pAUY^&R(j0;|2!RsSry}0qS2AA*%2 zq`gK72-k`=O))!DAK&6noM5zj0IoDD0{8LM5i!cTgoa`h7sp7Y3kD(XkJN)x-VBdY z?z2!KwfD3JTG1UFiWIis-7S5ybCB9_H2_)J>D2%I%L>VDftc>;iBwC~fpy<}=NG8( z@wuH5IBjVSqKUF)f*>Anp^XW4_;1MRjE86Xd-(tRssFV|W{`Oo4aTN@*FhpFZf<+c znQxx?R+b5ZO&BtSc-sxx-^0d*hTh5NAyWoLT!ZvMu+V<=nC&}-ub#hC6~2aXOdEdr z#Hqk>Sp1BJwD14f14-rM7MT5B0tFTb-{y-SpVw!ELa<}8%k8Xq+U&k|iLx{OrC3uQ z@y69vjfl1ksUg8=5N9FyBH|Z{*J^$jSg^bQci&5vtOOa`S%Hq4p_gmdUu!J$%(Oc( zZ|*svtvpmS5D;kt@&VZgWQPy>y?h?ojzb>2?lDVNT1dntT8Bdyb$3(MwPSOEtJFb`@cOT0&w;u8{J?^OIxF&j?^K>8zq@gT~Fe_A-B4~hI<7%uB~4VbaM>PTJOyZlYwdsLiy+-5aW8! zg|FM%3X6rWAMvfHCX>|6&CL}Q6fTBsctHhCtm!KLPx#InLx=hJ0tn%ZZAx)rrtZy~ z2^AUNzw1ET8;hQ@VS5akzltz47DCPd3)b44U?mjVkg=W2m+h?K%e{s#11<~(WDJ&2 znyjp-=!6};Zfsn+(S+S?pv0$}++s(MF3z;X@nLMRT@QBV=H{LWDL)4)XTncq2p0hd zz@OLm%VBr*IHexwf|Kg%Y1~3emTQ;gxH&d;$U zAd=ahPhO*y+-M9&=GX;$!<#n`T)TD+I6FYkI5|1(P#pHk#+4ECcicKtqnam6Sj6S! zU&qGo7e2HPNLWJ6`}gl%TwE@C^h$bW5`D0_Ka<3Ksa%lO&Wf(q_N)Ysu|UGX6OLbS zYed5cb%2n~KpzggEXEAXBD{`1GB)N#H8>?9VO0|-#h}yNL4QJ+a5gkN=nzhQOKku- z^C~052-F-X-g-rnGPG1fk#p-x4|#54+2YX64)otX%;1qDM={{-`1Yq z-h0%;*`GeWzvRqu^5jWWqSI{mN2sN>^;LShAp)TYV&9oFi6|2c2@F)2AjL9O87>_7 zAKCf&zkTgN;ZH<_`faa!02GyD*Frv3k4rA%_tZ!QN8y`IJY5?-@!zDs_^`z%CQbv*9EP-!L@mXLjAGc3GSZe@% zn^m6=HVw25y?uR*-8ByMvZKrO>v03!XH7B>26LQSTU#qc)M+OC{h4I5mS0dXTo+P4 zun7XUEOCTEz#7t6X=EMpQu1UV$3tTNYkdk%gFXuaHpuJbEB z@M}@g8AZi`2UmM~dQke*7cUNj^m;^KP`%$V+m(%wme?cw{QRI?Hm6>jKqh$Cm5C+@ zg%DP_fB2JL;;A!dqB}Y|loEr%o@i`My>vHRhT3cvdzG3B#PK=CHnqH!4R}!iMhTvvd;tWXQ1KI|QmM8`B7!_N2-Ka@8q+JK z?6NzQyLCRGg#%@ulam9w!!H<2%Us}Puc3=z^}q0V_pvH}kQRJLkGj^M)zA=b^!57N zegOw2v!%3O1Lz2>1$A;mg7#sKMgRxD!j|jzH8LxMV_*rlhkEtumBEc0r{v}NYKg{X zW_-o<8`f!ypx;#njl^wWF)n>B?dUKB2o6v>$>D%+?Ck6Szhi*C`%MZ7j9)YvwXZle zRgls@NwD!XhYVua22McQK|xCGDHmw!e?qpDFscDFmV@7$eQ4Am_8y~oSn^*(jL|6wx-^> zKgYLWD;g|uo3?BM^tZ!G#kX&M3qzNTGc}mR0<6`@sHh{nygE1(1M>pB0a%SsK-&ef zeMinDKK*7l2RfF`z8eU3gTdSXv*i-A;V9W-tu@kPTzY<+`6m^0{hIOBA|1yk{|h>` B9+dz9 literal 6192 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 0; --z) { + const zIndexItems = items[z]; + for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) { + declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], declutterTree); + } + } + items.length = 0; + return declutterTree; +} diff --git a/src/ol/renderer/Map.js b/src/ol/renderer/Map.js index 488698d081..9955be7a51 100644 --- a/src/ol/renderer/Map.js +++ b/src/ol/renderer/Map.js @@ -10,6 +10,7 @@ import {TRUE} from '../functions.js'; import {visibleAtResolution} from '../layer/Layer.js'; import {shared as iconImageCache} from '../style/IconImageCache.js'; import {compose as composeTransform, makeInverse} from '../transform.js'; +import {renderDeclutterItems} from '../render.js'; /** * @abstract @@ -266,17 +267,7 @@ class MapRenderer extends Disposable { * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. */ renderFrame(frameState) { - if (this.declutterTree_) { - this.declutterTree_.clear(); - } - const items = frameState.declutterItems; - for (let z = items.length - 1; z >= 0; --z) { - const zIndexItems = items[z]; - for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) { - this.declutterTree_ = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], this.declutterTree_); - } - } - items.length = 0; + this.declutterTree_ = renderDeclutterItems(frameState, this.declutterTree_); } /** diff --git a/src/ol/renderer/canvas/VectorImageLayer.js b/src/ol/renderer/canvas/VectorImageLayer.js index c92c36885e..8d7e7b20b3 100644 --- a/src/ol/renderer/canvas/VectorImageLayer.js +++ b/src/ol/renderer/canvas/VectorImageLayer.js @@ -11,6 +11,7 @@ import CanvasVectorLayerRenderer from './VectorLayer.js'; import {listen} from '../../events.js'; import EventType from '../../events/EventType.js'; import ImageState from '../../ImageState.js'; +import {renderDeclutterItems} from '../../render.js'; /** * @classdesc @@ -72,6 +73,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { let skippedFeatures = this.skippedFeatures_; const context = vectorRenderer.context; const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, { + declutterItems: [], size: [ getWidth(renderedExtent) / viewResolution, getHeight(renderedExtent) / viewResolution @@ -86,6 +88,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { (vectorRenderer.replayGroupChanged || !equals(skippedFeatures, newSkippedFeatures))) { vectorRenderer.renderFrame(imageFrameState, layerState); + renderDeclutterItems(imageFrameState, null); skippedFeatures = newSkippedFeatures; callback(); } From 00c09eb281050dd01683c86cc7ac73d1c320eeee Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 15:05:02 +0200 Subject: [PATCH 4/7] Make rendering tests more cross-platform proof --- .../layer-vector-decluttering/expected.png | Bin 6393 -> 6354 bytes .../cases/layer-vector-decluttering/main.js | 2 +- .../expected.png | Bin 6841 -> 6816 bytes .../layer-vectorimage-decluttering/main.js | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rendering/cases/layer-vector-decluttering/expected.png b/rendering/cases/layer-vector-decluttering/expected.png index f81cac79e07124739b423c5d84fbb7b7a5ea0409..55ef4b2926a7179792a58ed8721a45f98053f6e4 100644 GIT binary patch literal 6354 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 JmfW&=`CnQR@EZUC literal 6393 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 diff --git a/rendering/cases/layer-vector-decluttering/main.js b/rendering/cases/layer-vector-decluttering/main.js index 1af3a6f395..d551f268dc 100644 --- a/rendering/cases/layer-vector-decluttering/main.js +++ b/rendering/cases/layer-vector-decluttering/main.js @@ -71,7 +71,7 @@ layer1.setStyle(function(feature) { }); map.addLayer(layer1); -center = [center[0] + 500, center[1] + 500]; +center = [center[0] + 500, center[1] + 700]; const feature2 = new Feature({ geometry: new Point(center), text: 'center', diff --git a/rendering/cases/layer-vectorimage-decluttering/expected.png b/rendering/cases/layer-vectorimage-decluttering/expected.png index 5ccebf610e8df3494230a7860df838968de8ea54..73be4ebb8e18325b0ba3071694d001916940b70a 100644 GIT binary patch literal 6816 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 SvEVN!=+;f08-;4tPyPeK3hciC literal 6841 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 B9+dz9 diff --git a/rendering/cases/layer-vectorimage-decluttering/main.js b/rendering/cases/layer-vectorimage-decluttering/main.js index 1a6d6c16ca..83428d97f0 100644 --- a/rendering/cases/layer-vectorimage-decluttering/main.js +++ b/rendering/cases/layer-vectorimage-decluttering/main.js @@ -71,7 +71,7 @@ layer1.setStyle(function(feature) { }); map.addLayer(layer1); -center = [center[0] + 500, center[1] + 500]; +center = [center[0] + 500, center[1] + 700]; const feature2 = new Feature({ geometry: new Point(center), text: 'center', From 86f304ae02bae809a47f662789d859b45be22e73 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 15:11:22 +0200 Subject: [PATCH 5/7] Fix typos --- changelog/upgrade-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 25ed045ef9..d150d3c48a 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -100,7 +100,7 @@ If you were previously using `Vector` layers with `renderMode: 'image'`, you hav ##### New declutter behavior -If a map has more than one layer with `declutter` set to true, decluttering now considers all `Vector` and `VectorTile` instead of decluttering each layer separately. Only `VectorImage` layers continue to be decluttered separately. The higher the z-index of the layer, the higher the priority of decluttered items. +If a map has more than one layer with `declutter` set to true, decluttering now considers all `Vector` and `VectorTile` layers, instead of decluttering each layer separately. Only `VectorImage` layers continue to be decluttered separately. The higher the z-index of a layer, the higher the priority of its decluttered items. Within a layer, the declutter order has changed. Previously, styles with a lower `zIndex` were prioritized over those with a higher `zIndex`. Now the opposite order is used. From 0e08d9e0fd7e77a36daace2f2a70d104591cf38e Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Tue, 7 May 2019 10:08:02 +0200 Subject: [PATCH 6/7] Add empty declutterItems in RasterSource frameState To please the type checker. --- src/ol/source/Raster.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ol/source/Raster.js b/src/ol/source/Raster.js index 558e426d96..ed44849ff8 100644 --- a/src/ol/source/Raster.js +++ b/src/ol/source/Raster.js @@ -227,7 +227,8 @@ class RasterSource extends ImageSource { rotation: 0 }), viewHints: [], - wantedTiles: {} + wantedTiles: {}, + declutterItems: [] }; this.setAttributions(function(frameState) { From d30f6175ceb6e0da2890490c1852d894e963ae7e Mon Sep 17 00:00:00 2001 From: Frederic Junod Date: Tue, 7 May 2019 10:12:19 +0200 Subject: [PATCH 7/7] Add function JSDoc tag --- src/ol/render.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ol/render.js b/src/ol/render.js index 0b0beb371a..c413506596 100644 --- a/src/ol/render.js +++ b/src/ol/render.js @@ -111,6 +111,11 @@ export function getRenderPixel(event, pixel) { return result; } +/** + * @param {import("./PluggableMap.js").FrameState} frameState Frame state. + * @param {?} declutterTree Declutter tree. + * @returns {?} Declutter tree. + */ export function renderDeclutterItems(frameState, declutterTree) { if (declutterTree) { declutterTree.clear();