diff --git a/src/ol/renderer/webgl/PointsLayer.js b/src/ol/renderer/webgl/PointsLayer.js index 811925df7a..868f9b7473 100644 --- a/src/ol/renderer/webgl/PointsLayer.js +++ b/src/ol/renderer/webgl/PointsLayer.js @@ -287,30 +287,50 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { */ this.featureCache_ = {}; + /** + * Amount of features in the cache. + * @type {number} + * @private + */ + this.featureCount_ = 0; + const source = this.getLayer().getSource(); this.sourceListenKeys_ = [ - listen(source, VectorEventType.ADDFEATURE, this.handleSourceFeatureChanged_, this), + listen(source, VectorEventType.ADDFEATURE, this.handleSourceFeatureAdded_, this), listen(source, VectorEventType.CHANGEFEATURE, this.handleSourceFeatureChanged_, this), listen(source, VectorEventType.REMOVEFEATURE, this.handleSourceFeatureDelete_, this) ]; - source.getFeatures().forEach(function(feature) { - const uid = getUid(feature); - this.featureCache_[uid] = { + source.forEachFeature(function(feature) { + this.featureCache_[getUid(feature)] = { feature: feature, properties: feature.getProperties(), geometry: feature.getGeometry() }; + this.featureCount_++; }.bind(this)); } + /** + * @param {import("../../source/Vector.js").VectorSourceEvent} event Event. + * @private + */ + handleSourceFeatureAdded_(event) { + const feature = event.feature; + this.featureCache_[getUid(feature)] = { + feature: feature, + properties: feature.getProperties(), + geometry: feature.getGeometry() + }; + this.featureCount_++; + } + /** * @param {import("../../source/Vector.js").VectorSourceEvent} event Event. * @private */ handleSourceFeatureChanged_(event) { const feature = event.feature; - const uid = getUid(feature); - this.featureCache_[uid] = { + this.featureCache_[getUid(feature)] = { feature: feature, properties: feature.getProperties(), geometry: feature.getGeometry() @@ -323,8 +343,8 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { */ handleSourceFeatureDelete_(event) { const feature = event.feature; - const uid = getUid(feature); - delete this.featureCache_[uid]; + delete this.featureCache_[getUid(feature)]; + this.featureCount_--; } /** @@ -403,32 +423,29 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { const projectionTransform = createTransform(); this.helper.makeProjectionTransform(frameState, projectionTransform); - const featureUids = Object.keys(this.featureCache_); - // here we anticipate the amount of render instructions that we well generate // this can be done since we know that for normal render we only have x, y as base instructions, // and x, y, r, g, b, a and featureUid for hit render instructions // and we also know the amount of custom attributes to append to these - const totalInstructionsCount = (2 + this.customAttributes.length) * featureUids.length; + const totalInstructionsCount = (2 + this.customAttributes.length) * this.featureCount_; if (!this.renderInstructions_ || this.renderInstructions_.length !== totalInstructionsCount) { this.renderInstructions_ = new Float32Array(totalInstructionsCount); } if (this.hitDetectionEnabled_) { - const totalHitInstructionsCount = (7 + this.customAttributes.length) * featureUids.length; + const totalHitInstructionsCount = (7 + this.customAttributes.length) * this.featureCount_; if (!this.hitRenderInstructions_ || this.hitRenderInstructions_.length !== totalHitInstructionsCount) { this.hitRenderInstructions_ = new Float32Array(totalHitInstructionsCount); } } // loop on features to fill the buffer - let featureUid, featureCache, geometry; + let featureCache, geometry; const tmpCoords = []; const tmpColor = []; let renderIndex = 0; let hitIndex = 0; let hitColor; - for (let i = 0; i < featureUids.length; i++) { - featureUid = featureUids[i]; + for (const featureUid in this.featureCache_) { featureCache = this.featureCache_[featureUid]; geometry = /** @type {import("../../geom").Point} */(featureCache.geometry); if (!geometry || geometry.getType() !== GeometryType.POINT) { diff --git a/src/ol/webgl/RenderTarget.js b/src/ol/webgl/RenderTarget.js index a3933ae414..28e156f237 100644 --- a/src/ol/webgl/RenderTarget.js +++ b/src/ol/webgl/RenderTarget.js @@ -123,7 +123,10 @@ class WebGLRenderTarget { */ readPixel(x, y) { if (x < 0 || y < 0 || x > this.size_[0] || y >= this.size_[1]) { - tmpArray4[0] = tmpArray4[1] = tmpArray4[2] = tmpArray4[3] = 0; + tmpArray4[0] = 0; + tmpArray4[1] = 0; + tmpArray4[2] = 0; + tmpArray4[3] = 0; return tmpArray4; } diff --git a/test/spec/ol/renderer/webgl/pointslayer.test.js b/test/spec/ol/renderer/webgl/pointslayer.test.js index d68fc78c0d..583f90992a 100644 --- a/test/spec/ol/renderer/webgl/pointslayer.test.js +++ b/test/spec/ol/renderer/webgl/pointslayer.test.js @@ -425,7 +425,7 @@ describe('ol.renderer.webgl.PointsLayer', function() { vertexShader: simpleVertexShader, fragmentShader: simpleFragmentShader }); - expect(Object.keys(renderer.featureCache_).length).to.be(0); + expect(renderer.featureCount_).to.be(0); }); it('contains the features initially present in the source', function() { @@ -434,7 +434,7 @@ describe('ol.renderer.webgl.PointsLayer', function() { vertexShader: simpleVertexShader, fragmentShader: simpleFragmentShader }); - expect(Object.keys(renderer.featureCache_).length).to.be(3); + expect(renderer.featureCount_).to.be(3); expect(getCache(features[0], renderer).feature).to.be(features[0]); expect(getCache(features[0], renderer).geometry).to.be(features[0].getGeometry()); expect(getCache(features[0], renderer).properties['test']).to.be(features[0].get('test')); @@ -453,10 +453,10 @@ describe('ol.renderer.webgl.PointsLayer', function() { }); source.addFeature(features[0]); - expect(Object.keys(renderer.featureCache_).length).to.be(1); + expect(renderer.featureCount_).to.be(1); source.addFeature(features[1]); - expect(Object.keys(renderer.featureCache_).length).to.be(2); + expect(renderer.featureCount_).to.be(2); expect(getCache(features[0], renderer).feature).to.be(features[0]); expect(getCache(features[0], renderer).geometry).to.be(features[0].getGeometry()); @@ -473,10 +473,10 @@ describe('ol.renderer.webgl.PointsLayer', function() { }); source.addFeatures(features); - expect(Object.keys(renderer.featureCache_).length).to.be(3); + expect(renderer.featureCount_).to.be(3); source.removeFeature(features[1]); - expect(Object.keys(renderer.featureCache_).length).to.be(2); + expect(renderer.featureCount_).to.be(2); expect(getCache(features[0], renderer).feature).to.be(features[0]); expect(getCache(features[0], renderer).geometry).to.be(features[0].getGeometry()); @@ -496,7 +496,7 @@ describe('ol.renderer.webgl.PointsLayer', function() { features[0].set('test', 'updated'); features[0].set('added', true); features[0].getGeometry().setCoordinates([10, 20]); - expect(Object.keys(renderer.featureCache_).length).to.be(3); + expect(renderer.featureCount_).to.be(3); expect(getCache(features[0], renderer).feature).to.be(features[0]); expect(getCache(features[0], renderer).geometry.getCoordinates()).to.eql([10, 20]);