Merge pull request #10198 from jahow/fix-webgl-renderer-loading-extent

WebGL renderer / use the specified loading strategy for the vector data
This commit is contained in:
Olivier Guyot
2019-10-28 16:19:52 +01:00
committed by GitHub
3 changed files with 57 additions and 25 deletions

View File

@@ -16,16 +16,15 @@ const vector = new HeatmapLayer({
}) })
}), }),
blur: parseInt(blur.value, 10), blur: parseInt(blur.value, 10),
radius: parseInt(radius.value, 10) radius: parseInt(radius.value, 10),
}); weight: function(feature) {
// 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a
vector.getSource().on('addfeature', function(event) { // standards-violating <magnitude> tag in each Placemark. We extract it from
// 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a // the Placemark's name instead.
// standards-violating <magnitude> tag in each Placemark. We extract it from const name = feature.get('name');
// the Placemark's name instead. const magnitude = parseFloat(name.substr(2));
const name = event.feature.get('name'); return magnitude - 5;
const magnitude = parseFloat(name.substr(2)); }
event.feature.set('weight', magnitude - 5);
}); });
const raster = new TileLayer({ const raster = new TileLayer({
@@ -34,7 +33,7 @@ const raster = new TileLayer({
}) })
}); });
const map = new Map({ new Map({
layers: [raster, vector], layers: [raster, vector],
target: 'map', target: 'map',
view: new View({ view: new View({

View File

@@ -7,7 +7,7 @@ import {AttributeType, DefaultUniform} from '../../webgl/Helper.js';
import GeometryType from '../../geom/GeometryType.js'; import GeometryType from '../../geom/GeometryType.js';
import WebGLLayerRenderer, {colorDecodeId, colorEncodeId, WebGLWorkerMessageType} from './Layer.js'; import WebGLLayerRenderer, {colorDecodeId, colorEncodeId, WebGLWorkerMessageType} from './Layer.js';
import ViewHint from '../../ViewHint.js'; import ViewHint from '../../ViewHint.js';
import {createEmpty, equals} from '../../extent.js'; import {buffer, createEmpty, equals} from '../../extent.js';
import { import {
apply as applyTransform, apply as applyTransform,
create as createTransform, create as createTransform,
@@ -18,6 +18,7 @@ import {create as createWebGLWorker} from '../../worker/webgl.js';
import {getUid} from '../../util.js'; import {getUid} from '../../util.js';
import WebGLRenderTarget from '../../webgl/RenderTarget.js'; import WebGLRenderTarget from '../../webgl/RenderTarget.js';
import {assert} from '../../asserts.js'; import {assert} from '../../asserts.js';
import BaseVector from '../../layer/BaseVector.js';
/** /**
* @typedef {Object} CustomAttribute A description of a custom attribute to be passed on to the GPU, with a value different * @typedef {Object} CustomAttribute A description of a custom attribute to be passed on to the GPU, with a value different
@@ -300,20 +301,22 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
const layer = this.getLayer(); const layer = this.getLayer();
const vectorSource = layer.getSource(); const vectorSource = layer.getSource();
const viewState = frameState.viewState; const viewState = frameState.viewState;
// the source has changed: clear the feature cache & reload features
const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
if (sourceChanged) {
this.sourceRevision_ = vectorSource.getRevision();
const projection = viewState.projection;
const resolution = viewState.resolution;
vectorSource.loadFeatures([-Infinity, -Infinity, Infinity, Infinity], resolution, projection);
}
const viewNotMoving = !frameState.viewHints[ViewHint.ANIMATING] && !frameState.viewHints[ViewHint.INTERACTING]; const viewNotMoving = !frameState.viewHints[ViewHint.ANIMATING] && !frameState.viewHints[ViewHint.INTERACTING];
const extentChanged = !equals(this.previousExtent_, frameState.extent); const extentChanged = !equals(this.previousExtent_, frameState.extent);
if ((sourceChanged || extentChanged) && viewNotMoving) { const sourceChanged = this.sourceRevision_ < vectorSource.getRevision();
if (sourceChanged) {
this.sourceRevision_ = vectorSource.getRevision();
}
if (viewNotMoving && (extentChanged || sourceChanged)) {
const projection = viewState.projection;
const resolution = viewState.resolution;
const renderBuffer = layer instanceof BaseVector ? layer.getRenderBuffer() : 0;
const extent = buffer(frameState.extent, renderBuffer * resolution);
vectorSource.loadFeatures(extent, resolution, projection);
this.rebuildBuffers_(frameState); this.rebuildBuffers_(frameState);
this.previousExtent_ = frameState.extent.slice(); this.previousExtent_ = frameState.extent.slice();
} }

View File

@@ -104,7 +104,8 @@ describe('ol.renderer.webgl.PointsLayer', function() {
beforeEach(function() { beforeEach(function() {
layer = new VectorLayer({ layer = new VectorLayer({
source: new VectorSource() source: new VectorSource(),
renderBuffer: 10
}); });
renderer = new WebGLPointsLayerRenderer(layer, { renderer = new WebGLPointsLayerRenderer(layer, {
vertexShader: simpleVertexShader, vertexShader: simpleVertexShader,
@@ -233,6 +234,35 @@ describe('ol.renderer.webgl.PointsLayer', function() {
renderer.prepareFrame(frameState); renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(2); expect(spy.callCount).to.be(2);
}); });
it('triggers source loading when the extent changes', function() {
const spy = sinon.spy(layer.getSource(), 'loadFeatures');
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(1);
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(1);
frameState.extent = [10, 20, 30, 40];
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(2);
expect(spy.getCall(1).args[0]).to.eql([0, 10, 40, 50]); // renderBuffer is 10
});
it('triggers source loading when the source revision changes', function() {
const spy = sinon.spy(layer.getSource(), 'loadFeatures');
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(1);
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(1);
layer.getSource().changed();
renderer.prepareFrame(frameState);
expect(spy.callCount).to.be(2);
});
}); });
describe('#forEachFeatureAtCoordinate', function() { describe('#forEachFeatureAtCoordinate', function() {