Load two extents for views that cross the date line
This commit is contained in:
@@ -361,7 +361,7 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const center = viewState.center.slice();
|
const center = viewState.center.slice();
|
||||||
const extent = buffer(frameStateExtent,
|
const extent = buffer(frameStateExtent,
|
||||||
vectorLayerRenderBuffer * resolution);
|
vectorLayerRenderBuffer * resolution);
|
||||||
const loadExtent = extent.slice();
|
const loadExtents = [extent.slice()];
|
||||||
const projectionExtent = viewState.projection.getExtent();
|
const projectionExtent = viewState.projection.getExtent();
|
||||||
|
|
||||||
if (vectorSource.getWrapX() && viewState.projection.canWrapX() &&
|
if (vectorSource.getWrapX() && viewState.projection.canWrapX() &&
|
||||||
@@ -377,8 +377,15 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
extent[2] = projectionExtent[2] + gutter;
|
extent[2] = projectionExtent[2] + gutter;
|
||||||
const worldsAway = Math.floor((center[0] - projectionExtent[0]) / worldWidth);
|
const worldsAway = Math.floor((center[0] - projectionExtent[0]) / worldWidth);
|
||||||
center[0] -= (worldsAway * worldWidth);
|
center[0] -= (worldsAway * worldWidth);
|
||||||
|
const loadExtent = loadExtents[0];
|
||||||
loadExtent[0] -= (worldsAway * worldWidth);
|
loadExtent[0] -= (worldsAway * worldWidth);
|
||||||
loadExtent[2] -= (worldsAway * worldWidth);
|
loadExtent[2] -= (worldsAway * worldWidth);
|
||||||
|
// If the extent crosses the date line, we load data for both edges of the worlds
|
||||||
|
if (loadExtent[0] < projectionExtent[0] && loadExtent[2] < projectionExtent[2]) {
|
||||||
|
loadExtents.push([loadExtent[0] + worldWidth, loadExtent[1], loadExtent[2] + worldWidth, loadExtent[3]]);
|
||||||
|
} else if (loadExtent[0] > projectionExtent[0] && loadExtent[2] > projectionExtent[2]) {
|
||||||
|
loadExtents.push([loadExtent[0] - worldWidth, loadExtent[1], loadExtent[2] - worldWidth, loadExtent[3]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.dirty_ &&
|
if (!this.dirty_ &&
|
||||||
@@ -401,10 +408,14 @@ class CanvasVectorLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const userProjection = getUserProjection();
|
const userProjection = getUserProjection();
|
||||||
let userTransform;
|
let userTransform;
|
||||||
if (userProjection) {
|
if (userProjection) {
|
||||||
vectorSource.loadFeatures(toUserExtent(loadExtent, projection), resolution, userProjection);
|
for (let i = 0, ii = loadExtents.length; i < ii; ++i) {
|
||||||
|
vectorSource.loadFeatures(toUserExtent(loadExtents[i], projection), resolution, userProjection);
|
||||||
|
}
|
||||||
userTransform = getTransformFromProjections(userProjection, projection);
|
userTransform = getTransformFromProjections(userProjection, projection);
|
||||||
} else {
|
} else {
|
||||||
vectorSource.loadFeatures(loadExtent, resolution, projection);
|
for (let i = 0, ii = loadExtents.length; i < ii; ++i) {
|
||||||
|
vectorSource.loadFeatures(loadExtents[i], resolution, projection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const squaredTolerance = getSquaredRenderTolerance(resolution, pixelRatio);
|
const squaredTolerance = getSquaredRenderTolerance(resolution, pixelRatio);
|
||||||
|
|||||||
@@ -221,10 +221,11 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('#prepareFrame and #compose', function() {
|
describe('#prepareFrame and #compose', function() {
|
||||||
let frameState, projExtent, renderer, worldWidth, buffer, loadExtent;
|
let frameState, projExtent, renderer, worldWidth, buffer, loadExtents;
|
||||||
const loader = function(extent) {
|
|
||||||
loadExtent = extent;
|
function loader(extent) {
|
||||||
};
|
loadExtents.push(extent);
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
const layer = new VectorLayer({
|
const layer = new VectorLayer({
|
||||||
@@ -239,7 +240,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent = projection.getExtent();
|
projExtent = projection.getExtent();
|
||||||
worldWidth = getWidth(projExtent);
|
worldWidth = getWidth(projExtent);
|
||||||
buffer = layer.getRenderBuffer();
|
buffer = layer.getRenderBuffer();
|
||||||
loadExtent = undefined;
|
loadExtents = [];
|
||||||
frameState = {
|
frameState = {
|
||||||
viewHints: [],
|
viewHints: [],
|
||||||
viewState: {
|
viewState: {
|
||||||
@@ -263,7 +264,10 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent[0] - worldWidth + buffer,
|
projExtent[0] - worldWidth + buffer,
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
-10000, projExtent[2] + worldWidth - buffer, 10000
|
||||||
], buffer));
|
], buffer));
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
expect(loadExtents.length).to.be(2);
|
||||||
|
expect(loadExtents[0]).to.eql(bufferExtent(frameState.extent, buffer));
|
||||||
|
const otherExtent = [projExtent[2] - 10000, -10000, projExtent[2] + 10000, 10000];
|
||||||
|
expect(loadExtents[1]).to.eql(bufferExtent(otherExtent, buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets correct extent for viewport less than 1 world wide', function() {
|
it('sets correct extent for viewport less than 1 world wide', function() {
|
||||||
@@ -274,7 +278,10 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent[0] - worldWidth + buffer,
|
projExtent[0] - worldWidth + buffer,
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
-10000, projExtent[2] + worldWidth - buffer, 10000
|
||||||
], buffer));
|
], buffer));
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
expect(loadExtents.length).to.be(2);
|
||||||
|
expect(loadExtents[0]).to.eql(bufferExtent(frameState.extent, buffer));
|
||||||
|
const otherExtent = [projExtent[0] - 10000 + worldWidth, -10000, projExtent[2] - 10000 + worldWidth, 10000];
|
||||||
|
expect(loadExtents[1]).to.eql(bufferExtent(otherExtent, buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets correct extent for viewport more than 1 world wide', function() {
|
it('sets correct extent for viewport more than 1 world wide', function() {
|
||||||
@@ -285,7 +292,8 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent[0] - worldWidth + buffer,
|
projExtent[0] - worldWidth + buffer,
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
-10000, projExtent[2] + worldWidth - buffer, 10000
|
||||||
], buffer));
|
], buffer));
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
expect(loadExtents.length).to.be(1);
|
||||||
|
expect(loadExtents[0]).to.eql(bufferExtent(frameState.extent, buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets correct extent for viewport more than 2 worlds wide, one world away', function() {
|
it('sets correct extent for viewport more than 2 worlds wide, one world away', function() {
|
||||||
@@ -298,11 +306,12 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent[0] - 2 * worldWidth - 10000,
|
projExtent[0] - 2 * worldWidth - 10000,
|
||||||
-10000, projExtent[2] + 2 * worldWidth + 10000, 10000
|
-10000, projExtent[2] + 2 * worldWidth + 10000, 10000
|
||||||
], buffer));
|
], buffer));
|
||||||
|
expect(loadExtents.length).to.be(1);
|
||||||
const normalizedExtent = [projExtent[0] - 2 * worldWidth + worldWidth - 10000, -10000, projExtent[0] + 2 * worldWidth + worldWidth + 10000, 10000];
|
const normalizedExtent = [projExtent[0] - 2 * worldWidth + worldWidth - 10000, -10000, projExtent[0] + 2 * worldWidth + worldWidth + 10000, 10000];
|
||||||
expect(loadExtent).to.eql(bufferExtent(normalizedExtent, buffer));
|
expect(loadExtents[0]).to.eql(bufferExtent(normalizedExtent, buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets correct extent for small viewport near dateline, one world away', function() {
|
it('sets correct extent for small viewport, one world away', function() {
|
||||||
|
|
||||||
setExtent([-worldWidth - 10000, -10000, -worldWidth + 10000, 10000]);
|
setExtent([-worldWidth - 10000, -10000, -worldWidth + 10000, 10000]);
|
||||||
renderer.prepareFrame(frameState);
|
renderer.prepareFrame(frameState);
|
||||||
@@ -310,8 +319,9 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
projExtent[0] - worldWidth + buffer,
|
projExtent[0] - worldWidth + buffer,
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
-10000, projExtent[2] + worldWidth - buffer, 10000
|
||||||
], buffer));
|
], buffer));
|
||||||
|
expect(loadExtents.length).to.be(1);
|
||||||
const normalizedExtent = [-10000, -10000, 10000, 10000];
|
const normalizedExtent = [-10000, -10000, 10000, 10000];
|
||||||
expect(loadExtent).to.eql(bufferExtent(normalizedExtent, buffer));
|
expect(loadExtents[0]).to.eql(bufferExtent(normalizedExtent, buffer));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets replayGroupChanged correctly', function() {
|
it('sets replayGroupChanged correctly', function() {
|
||||||
@@ -344,90 +354,6 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#prepareFrame with a loadWrapX: false source', function() {
|
|
||||||
let frameState, projExtent, renderer, worldWidth, buffer, loadExtent;
|
|
||||||
const loader = function(extent) {
|
|
||||||
loadExtent = extent;
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
const layer = new VectorLayer({
|
|
||||||
source: new VectorSource({
|
|
||||||
wrapX: true,
|
|
||||||
loadWrapX: false,
|
|
||||||
loader: loader,
|
|
||||||
strategy: bboxStrategy
|
|
||||||
})
|
|
||||||
});
|
|
||||||
renderer = new CanvasVectorLayerRenderer(layer);
|
|
||||||
const projection = getProjection('EPSG:3857');
|
|
||||||
projExtent = projection.getExtent();
|
|
||||||
worldWidth = getWidth(projExtent);
|
|
||||||
buffer = layer.getRenderBuffer();
|
|
||||||
loadExtent = undefined;
|
|
||||||
frameState = {
|
|
||||||
viewHints: [],
|
|
||||||
viewState: {
|
|
||||||
center: [0, 0],
|
|
||||||
projection: projection,
|
|
||||||
resolution: 1,
|
|
||||||
rotation: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads correct extent for small viewport near dateline', function() {
|
|
||||||
|
|
||||||
frameState.extent =
|
|
||||||
[projExtent[0] - 10000, -10000, projExtent[0] + 10000, 10000];
|
|
||||||
renderer.prepareFrame(frameState);
|
|
||||||
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
|
|
||||||
projExtent[0] - worldWidth + buffer,
|
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
|
||||||
], buffer));
|
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads correct extent for viewport less than 1 world wide', function() {
|
|
||||||
|
|
||||||
frameState.extent =
|
|
||||||
[projExtent[0] - 10000, -10000, projExtent[1] - 10000, 10000];
|
|
||||||
renderer.prepareFrame(frameState);
|
|
||||||
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
|
|
||||||
projExtent[0] - worldWidth + buffer,
|
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
|
||||||
], buffer));
|
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads correct extent for viewport more than 1 world wide', function() {
|
|
||||||
|
|
||||||
frameState.extent =
|
|
||||||
[2 * projExtent[0] - 10000, -10000, 2 * projExtent[1] + 10000, 10000];
|
|
||||||
renderer.prepareFrame(frameState);
|
|
||||||
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
|
|
||||||
projExtent[0] - worldWidth + buffer,
|
|
||||||
-10000, projExtent[2] + worldWidth - buffer, 10000
|
|
||||||
], buffer));
|
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads correct extent for viewport more than 2 worlds wide', function() {
|
|
||||||
|
|
||||||
frameState.extent = [
|
|
||||||
projExtent[0] - 2 * worldWidth - 10000,
|
|
||||||
-10000, projExtent[1] + 2 * worldWidth + 10000, 10000
|
|
||||||
];
|
|
||||||
renderer.prepareFrame(frameState);
|
|
||||||
expect(renderer.replayGroup_.maxExtent_).to.eql(bufferExtent([
|
|
||||||
projExtent[0] - 2 * worldWidth - 10000,
|
|
||||||
-10000, projExtent[2] + 2 * worldWidth + 10000, 10000
|
|
||||||
], buffer));
|
|
||||||
expect(loadExtent).to.eql(bufferExtent(frameState.extent, buffer));
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('hit detection', function() {
|
describe('hit detection', function() {
|
||||||
|
|
||||||
it('with no fill and transparent fill', function() {
|
it('with no fill and transparent fill', function() {
|
||||||
|
|||||||
Reference in New Issue
Block a user