Skip to content

Commit

Permalink
Merge pull request #15796 from ahocevar/vector-deferred-worlds-and-op…
Browse files Browse the repository at this point in the history
…acity

Fix deferred rendering of layer extents, multiple worlds and non-1 opacity
  • Loading branch information
ahocevar committed May 4, 2024
2 parents b282730 + 9d7208e commit 8d1324f
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/ol/renderer/canvas/Layer.js
Expand Up @@ -283,7 +283,7 @@ class CanvasLayerRenderer extends LayerRenderer {
canvas.width = width;
canvas.height = height;
} else {
this.getRenderContext(frameState).clearRect(0, 0, width, height);
this.context.clearRect(0, 0, width, height);
}
if (canvasTransform !== canvas.style.transform) {
canvas.style.transform = canvasTransform;
Expand Down
23 changes: 18 additions & 5 deletions src/ol/renderer/canvas/VectorLayer.js
Expand Up @@ -68,6 +68,13 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
this.hitDetectionImageData_ = null;

/**
* @private
* @type {boolean}
*/
this.clipped_ = false;

/**
* @private
* @type {Array<import("../../Feature.js").default>}
*/
this.renderedFeatures_ = null;
Expand Down Expand Up @@ -197,7 +204,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
? Math.floor((extent[0] - projectionExtent[0]) / worldWidth)
: 0;
do {
const transform = this.getRenderTransform(
let transform = this.getRenderTransform(
center,
resolution,
0,
Expand All @@ -206,6 +213,9 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
height,
world * worldWidth,
);
if (frameState.declutter) {
transform = transform.slice(0);
}
executorGroup.execute(
context,
[context.canvas.width, context.canvas.height],
Expand Down Expand Up @@ -274,6 +284,9 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
return;
}
this.replayGroup_.renderDeferred();
if (this.clipped_) {
this.context.restore();
}
this.resetDrawContext_();
}

Expand Down Expand Up @@ -309,12 +322,12 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
const projection = viewState.projection;

// clipped rendering if layer extent is set
let clipped = false;
this.clipped_ = false;
if (render && layerState.extent && this.clipping) {
const layerExtent = fromUserExtent(layerState.extent, projection);
render = intersectsExtent(layerExtent, frameState.extent);
clipped = render && !containsExtent(layerExtent, frameState.extent);
if (clipped) {
this.clipped_ = render && !containsExtent(layerExtent, frameState.extent);
if (this.clipped_) {
this.clipUnrotated(context, frameState, layerExtent);
}
}
Expand All @@ -327,7 +340,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
);
}

if (clipped) {
if (!frameState.declutter && this.clipped_) {
context.restore();
}

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,27 @@
import GeoJSON from '../../../../src/ol/format/GeoJSON.js';
import Map from '../../../../src/ol/Map.js';
import VectorLayer from '../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
import {transformExtent} from '../../../../src/ol/proj.js';

new Map({
target: 'map',
view: new View({
center: [0, 0],
zoom: 1,
rotation: Math.PI / 4,
}),
layers: [
new VectorLayer({
declutter: true,
extent: transformExtent([-50, -45, 50, 45], 'EPSG:4326', 'EPSG:3857'),
source: new VectorSource({
url: '/data/countries.json',
format: new GeoJSON(),
}),
}),
],
});

render();
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions test/rendering/cases/layer-vector-multi-world-declutter/main.js
@@ -0,0 +1,70 @@
import Feature from '../../../../src/ol/Feature.js';
import Fill from '../../../../src/ol/style/Fill.js';
import Map from '../../../../src/ol/Map.js';
import Polygon from '../../../../src/ol/geom/Polygon.js';
import Style from '../../../../src/ol/style/Style.js';
import VectorLayer from '../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js';
import {Projection, addCoordinateTransforms} from '../../../../src/ol/proj.js';
import {fromEPSG4326, toEPSG4326} from '../../../../src/ol/proj/epsg3857.js';

const projection = new Projection({
code: 'custom',
units: 'm',
global: true,
extent: [-40075016.68557849, -20037508.342789244, 0, 20037508.342789244],
});

addCoordinateTransforms(
'EPSG:4326',
projection,
function (coord) {
const converted = fromEPSG4326(coord);
converted[0] -= 20037508.342789244;
return converted;
},
function (coord) {
return toEPSG4326([coord[0] + 20037508.342789244, coord[1]]);
},
);

const feature = new Feature({
geometry: new Polygon([
[
[-20037508.342789244, 20037508.342789244],
[-20037508.342789244, -20037508.342789244],
[-16037508.342789244, -20037508.342789244],
[-16037508.342789244, 20037508.342789244],
[-20037508.342789244, 20037508.342789244],
],
]),
});

new Map({
pixelRatio: 1,
layers: [
new VectorLayer({
renderBuffer: 0,
declutter: true,
source: new VectorSource({
features: [feature],
}),
style: new Style({
fill: new Fill({
color: 'black',
}),
}),
}),
],
target: 'map',
view: new View({
projection: projection,
multiWorld: true,
maxResolution: 485254.1017841229,
zoom: 0,
center: [2000000, 0],
}),
});

render();
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions test/rendering/cases/vector-layer-opacity-declutter/main.js
@@ -0,0 +1,46 @@
import Feature from '../../../../src/ol/Feature.js';
import Map from '../../../../src/ol/Map.js';
import View from '../../../../src/ol/View.js';
import {Polygon} from '../../../../src/ol/geom.js';
import {Vector as VectorLayer} from '../../../../src/ol/layer.js';
import {Vector as VectorSource} from '../../../../src/ol/source.js';
import {fromLonLat} from '../../../../src/ol/proj.js';

const center = fromLonLat([8.6, 50.2]);

const geometry = new Polygon([
[
[center[0] - 10000, center[1] - 10000],
[center[0] + 10000, center[1] - 10000],
[center[0] + 10000, center[1] + 10000],
[center[0] - 10000, center[1] + 10000],
[center[0] - 10000, center[1] - 10000],
],
]);

const map = new Map({
layers: [
new VectorLayer({
opacity: 0.9,
declutter: true,
style: {
'stroke-color': 'red',
'stroke-width': 3,
},
source: new VectorSource({
features: [new Feature(geometry)],
}),
}),
],
target: 'map',
view: new View({
center: center,
zoom: 9,
}),
});

map.once('rendercomplete', function () {
map.getView().setCenter(fromLonLat([8.5, 50.1]));
map.renderSync();
render();
});

0 comments on commit 8d1324f

Please sign in to comment.