From 9d125ee340334f0ed6f3166f3a8434b77bdb1b43 Mon Sep 17 00:00:00 2001 From: mike-000 <49240900+mike-000@users.noreply.github.com> Date: Wed, 4 Sep 2019 11:51:06 +0100 Subject: [PATCH] Respect mutiWorld: false same as explicit extent Fixes #9577 The multiWorld: false constraint is currently not taken into account when constrainResolution is set or when an explicit resolutions array is specified, while an explicit extent constraint is respected in the same situations. This pull request takes a global projection extent into consideration in that same situations that an explicit extent would be. Add multiWorld tests with resolution constraints includes fix for #9937 --- src/ol/View.js | 29 ++++++++++--------- src/ol/resolutionconstraint.js | 3 ++ test/spec/ol/view.test.js | 53 +++++++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/ol/View.js b/src/ol/View.js index 253371cc78..7eab596b95 100644 --- a/src/ol/View.js +++ b/src/ol/View.js @@ -198,7 +198,7 @@ const DEFAULT_MIN_ZOOM = 0; * * ### The view states * - * An View is determined by three states: `center`, `resolution`, + * A View is determined by three states: `center`, `resolution`, * and `rotation`. Each state has a corresponding getter and setter, e.g. * `getCenter` and `setCenter` for the `center` state. * @@ -1452,6 +1452,15 @@ export function createResolutionConstraint(options) { const smooth = options.smoothResolutionConstraint !== undefined ? options.smoothResolutionConstraint : true; + const projection = createProjection(options.projection, 'EPSG:3857'); + const projExtent = projection.getExtent(); + let constrainOnlyCenter = options.constrainOnlyCenter; + let extent = options.extent; + if (!multiWorld && !extent && projection.isGlobal()) { + constrainOnlyCenter = false; + extent = projExtent; + } + if (options.resolutions !== undefined) { const resolutions = options.resolutions; maxResolution = resolutions[minZoom]; @@ -1460,20 +1469,18 @@ export function createResolutionConstraint(options) { if (options.constrainResolution) { resolutionConstraint = createSnapToResolutions(resolutions, smooth, - !options.constrainOnlyCenter && options.extent); + !constrainOnlyCenter && extent); } else { resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth, - !options.constrainOnlyCenter && options.extent); + !constrainOnlyCenter && extent); } } else { // calculate the default min and max resolution - const projection = createProjection(options.projection, 'EPSG:3857'); - const extent = projection.getExtent(); - const size = !extent ? + const size = !projExtent ? // use an extent that can fit the whole world if need be 360 * METERS_PER_UNIT[Units.DEGREES] / projection.getMetersPerUnit() : - Math.max(getWidth(extent), getHeight(extent)); + Math.max(getWidth(projExtent), getHeight(projExtent)); const defaultMaxResolution = size / DEFAULT_TILE_SIZE / Math.pow( defaultZoomFactor, DEFAULT_MIN_ZOOM); @@ -1511,14 +1518,8 @@ export function createResolutionConstraint(options) { if (options.constrainResolution) { resolutionConstraint = createSnapToPower( zoomFactor, maxResolution, minResolution, smooth, - !options.constrainOnlyCenter && options.extent); + !constrainOnlyCenter && extent); } else { - let constrainOnlyCenter = options.constrainOnlyCenter; - let extent = options.extent; - if (!multiWorld && !extent && projection.isGlobal()) { - constrainOnlyCenter = false; - extent = projection.getExtent(); - } resolutionConstraint = createMinMaxResolution(maxResolution, minResolution, smooth, !constrainOnlyCenter && extent); } diff --git a/src/ol/resolutionconstraint.js b/src/ol/resolutionconstraint.js index b0c36d5b6d..72594e9730 100644 --- a/src/ol/resolutionconstraint.js +++ b/src/ol/resolutionconstraint.js @@ -82,6 +82,9 @@ export function createSnapToResolutions(resolutions, opt_smooth, opt_maxExtent) const capped = Math.min(cappedMaxRes, resolution); const z = Math.floor(linearFindNearest(resolutions, capped, direction)); + if (resolutions[z] > cappedMaxRes && z < resolutions.length - 1) { + return resolutions[z + 1]; + } return resolutions[z]; } else { return undefined; diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index d4bf59b078..96b7d84830 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -430,6 +430,8 @@ describe('ol.View', function() { const defaultMaxRes = 156543.03392804097; const size = [512, 512]; + const maxResolution = 160000; + const resolutions = [160000, 80000, 40000, 20000, 10000, 5000]; function getConstraint(options) { return createResolutionConstraint(options).constraint; } @@ -439,12 +441,61 @@ describe('ol.View', function() { expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes / 2); }); - it('can be enabled by setting multiWorld to truet', function() { + it('can be enabled by setting multiWorld to true', function() { const fn = getConstraint({ multiWorld: true }); expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes); }); + + it('disabled, with constrainResolution', function() { + const fn = getConstraint({ + maxResolution: maxResolution, + constrainResolution: true + }); + expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes / 2); + }); + + it('enabled, with constrainResolution', function() { + const fn = getConstraint({ + maxResolution: maxResolution, + constrainResolution: true, + multiWorld: true + }); + expect(fn(defaultMaxRes, 0, size)).to.be(maxResolution); + }); + + it('disabled, with resolutions array', function() { + const fn = getConstraint({ + resolutions: resolutions + }); + expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes / 2); + }); + + it('enabled, with resolutions array', function() { + const fn = getConstraint({ + resolutions: resolutions, + multiWorld: true + }); + expect(fn(defaultMaxRes, 0, size)).to.be(defaultMaxRes); + }); + + it('disabled, with resolutions array and constrainResolution', function() { + const fn = getConstraint({ + resolutions: resolutions, + constrainResolution: true + }); + expect(fn(defaultMaxRes, 0, size)).to.be(resolutions[2]); + }); + + it('enabled, with resolutions array and constrainResolution', function() { + const fn = getConstraint({ + resolutions: resolutions, + constrainResolution: true, + multiWorld: true + }); + expect(fn(defaultMaxRes, 0, size)).to.be(resolutions[0]); + }); }); });