diff --git a/src/ol/View.js b/src/ol/View.js index 4c03566bdc..c3645663d1 100644 --- a/src/ol/View.js +++ b/src/ol/View.js @@ -665,28 +665,6 @@ class View extends BaseObject { return size; } - /** - * Get the constrained resolution of this view. - * @param {number|undefined} resolution Resolution. - * @param {number=} opt_delta Delta. Default is `0`. - * @param {number=} opt_direction Direction. Default is `0`. - * @return {number|undefined} Constrained resolution. - * @private - */ - constrainResolution(resolution, opt_delta, opt_direction) { - const delta = opt_delta || 0; - const direction = opt_direction || 0; - - const size = this.getSizeFromViewport_(); - const rotation = this.getRotation() || 0; - const rotatedSize = [ - Math.abs(size[0] * Math.cos(rotation)) + Math.abs(size[1] * Math.sin(rotation)), - Math.abs(size[0] * Math.sin(rotation)) + Math.abs(size[1] * Math.cos(rotation)) - ]; - - return this.constraints_.resolution(resolution, delta, direction, rotatedSize); - } - /** * Get the view center. * @return {import("./coordinate.js").Coordinate|undefined} The center of the view. @@ -964,8 +942,14 @@ class View extends BaseObject { * @api */ getResolutionForZoom(zoom) { - return /** @type {number} */ (this.constrainResolution( - this.maxResolution_, zoom - this.minZoom_, 0)); + if (this.resolutions_) { + const baseLevel = clamp(Math.floor(zoom), 0, this.resolutions_.length - 2); + const zoomFactor = this.resolutions_[baseLevel] / this.resolutions_[baseLevel + 1]; + return this.resolutions_[baseLevel] / Math.pow(zoomFactor, clamp(zoom - baseLevel, 0, 1)); + } else { + return clamp(this.maxResolution_ / Math.pow(this.zoomFactor_, zoom - this.minZoom_), + this.minResolution_, this.maxResolution_); + } } /** @@ -1008,8 +992,7 @@ class View extends BaseObject { if (options.minResolution !== undefined) { minResolution = options.minResolution; } else if (options.maxZoom !== undefined) { - minResolution = this.constrainResolution( - this.maxResolution_, options.maxZoom - this.minZoom_, 0); + minResolution = this.getResolutionForZoom(options.maxZoom); } else { minResolution = 0; } @@ -1040,12 +1023,7 @@ class View extends BaseObject { resolution = isNaN(resolution) ? minResolution : Math.max(resolution, minResolution); if (constrainResolution) { - let constrainedResolution = this.constrainResolution(resolution, 0, 0); - if (!nearest && constrainedResolution < resolution) { - constrainedResolution = this.constrainResolution( - constrainedResolution, -1, 0); - } - resolution = constrainedResolution; + resolution = this.getValidResolution(resolution, nearest ? 0 : 1); } // calculate center @@ -1196,7 +1174,7 @@ class View extends BaseObject { Math.abs(size[0] * Math.sin(rotation)) + Math.abs(size[1] * Math.cos(rotation)) ]; - const newResolution = this.constraints_.resolution(this.targetResolution_, 0, 0, rotatedSize, isMoving); + const newResolution = this.constraints_.resolution(this.targetResolution_, 0, rotatedSize, isMoving); const newCenter = this.constraints_.center(this.targetCenter_, newResolution, rotatedSize, isMoving); this.set(ViewProperty.ROTATION, newRotation); @@ -1226,7 +1204,7 @@ class View extends BaseObject { /** * Get a valid zoom level according to the current view constraints. - * @param {number|undefined} targetZoom Target resolution. + * @param {number|undefined} targetZoom Target zoom. * @param {number=} opt_direction Direction. Default is `0`. Specify `-1` or `1` to return * the available value respectively lower or greater than the target one. Leaving `0` will simply choose * the nearest available value. @@ -1234,10 +1212,21 @@ class View extends BaseObject { * @api */ getValidZoomLevel(targetZoom, opt_direction) { - const direction = opt_direction || 0; - const currentRes = this.getResolution(); - const currentZoom = this.getZoom(); + const targetRes = this.getResolutionForZoom(targetZoom); + return this.getZoomForResolution(this.getValidResolution(targetRes)); + } + /** + * Get a valid resolution according to the current view constraints. + * @param {number|undefined} targetResolution Target resolution. + * @param {number=} opt_direction Direction. Default is `0`. Specify `-1` or `1` to return + * the available value respectively lower or greater than the target one. Leaving `0` will simply choose + * the nearest available value. + * @return {number|undefined} Valid resolution. + * @api + */ + getValidResolution(targetResolution, opt_direction) { + const direction = opt_direction || 0; const size = this.getSizeFromViewport_(); const rotation = this.getRotation() || 0; const rotatedSize = [ @@ -1245,8 +1234,7 @@ class View extends BaseObject { Math.abs(size[0] * Math.sin(rotation)) + Math.abs(size[1] * Math.cos(rotation)) ]; - return this.getZoomForResolution( - this.constraints_.resolution(currentRes, targetZoom - currentZoom, direction, rotatedSize)); + return(this.constraints_.resolution(targetResolution, direction, rotatedSize)); } } @@ -1350,7 +1338,7 @@ export function createResolutionConstraint(options) { minResolution = maxResolution / Math.pow(zoomFactor, maxZoom - minZoom); resolutionConstraint = createSnapToPower( - zoomFactor, maxResolution, maxZoom - minZoom, + zoomFactor, maxResolution, minResolution, !options.constrainOnlyCenter && options.extent); } return {constraint: resolutionConstraint, maxResolution: maxResolution, diff --git a/src/ol/resolutionconstraint.js b/src/ol/resolutionconstraint.js index d007b81dc9..575d603286 100644 --- a/src/ol/resolutionconstraint.js +++ b/src/ol/resolutionconstraint.js @@ -4,10 +4,11 @@ import {linearFindNearest} from './array.js'; import {clamp} from './math.js'; import {getHeight, getWidth} from './extent'; +import {clamp} from './math'; /** - * @typedef {function((number|undefined), number, number, import("./size.js").Size, boolean=): (number|undefined)} Type + * @typedef {function((number|undefined), number, import("./size.js").Size, boolean=): (number|undefined)} Type */ @@ -20,13 +21,12 @@ export function createSnapToResolutions(resolutions, opt_maxExtent) { return ( /** * @param {number|undefined} resolution Resolution. - * @param {number} delta Delta. * @param {number} direction Direction. * @param {import("./size.js").Size} size Viewport size. * @param {boolean=} opt_isMoving True if an interaction or animation is in progress. * @return {number|undefined} Resolution. */ - function(resolution, delta, direction, size, opt_isMoving) { + function(resolution, direction, size, opt_isMoving) { if (resolution !== undefined) { let cappedRes = resolution; @@ -39,19 +39,13 @@ export function createSnapToResolutions(resolutions, opt_maxExtent) { // during interacting or animating, allow intermediary values if (opt_isMoving) { - // TODO: actually take delta and direction into account - return Math.min(resolution, cappedRes); + const maxResolution = resolutions[0]; + const minResolution = resolutions[resolutions.length - 1]; + return clamp(cappedRes, minResolution, maxResolution); } - let z = linearFindNearest(resolutions, cappedRes, direction); - z = clamp(z + delta, 0, resolutions.length - 1); - const index = Math.floor(z); - if (z != index && index < resolutions.length - 1) { - const power = resolutions[index] / resolutions[index + 1]; - return resolutions[index] / Math.pow(power, z - index); - } else { - return resolutions[index]; - } + let z = Math.floor(linearFindNearest(resolutions, cappedRes, direction)); + return resolutions[z]; } else { return undefined; } @@ -63,23 +57,22 @@ export function createSnapToResolutions(resolutions, opt_maxExtent) { /** * @param {number} power Power. * @param {number} maxResolution Maximum resolution. - * @param {number=} opt_maxLevel Maximum level. + * @param {number=} opt_minResolution Minimum resolution. * @param {import("./extent.js").Extent=} opt_maxExtent Maximum allowed extent. * @return {Type} Zoom function. */ -export function createSnapToPower(power, maxResolution, opt_maxLevel, opt_maxExtent) { +export function createSnapToPower(power, maxResolution, opt_minResolution, opt_maxExtent) { return ( /** * @param {number|undefined} resolution Resolution. - * @param {number} delta Delta. * @param {number} direction Direction. * @param {import("./size.js").Size} size Viewport size. * @param {boolean=} opt_isMoving True if an interaction or animation is in progress. * @return {number|undefined} Resolution. */ - function(resolution, delta, direction, size, opt_isMoving) { + function(resolution, direction, size, opt_isMoving) { if (resolution !== undefined) { - let cappedRes = resolution; + let cappedRes = Math.min(resolution, maxResolution); // apply constraint related to max extent if (opt_maxExtent) { @@ -90,18 +83,16 @@ export function createSnapToPower(power, maxResolution, opt_maxLevel, opt_maxExt // during interacting or animating, allow intermediary values if (opt_isMoving) { - // TODO: actually take delta and direction into account - return Math.min(resolution, cappedRes); + return opt_minResolution !== undefined ? Math.max(opt_minResolution, cappedRes) : cappedRes; } - const offset = -direction / 2 + 0.5; - const oldLevel = Math.floor( + const offset = -direction * (0.5 - 1e-9) + 0.5; + const zoomLevel = Math.floor( Math.log(maxResolution / cappedRes) / Math.log(power) + offset); - let newLevel = Math.max(oldLevel + delta, 0); - if (opt_maxLevel !== undefined) { - newLevel = Math.min(newLevel, opt_maxLevel); - } - return maxResolution / Math.pow(power, newLevel); + let newResolution = maxResolution / Math.pow(power, zoomLevel); + return opt_minResolution !== undefined ? + clamp(newResolution, opt_minResolution, maxResolution) : + Math.min(maxResolution, newResolution); } else { return undefined; } diff --git a/test/spec/ol/interaction/dragzoom.test.js b/test/spec/ol/interaction/dragzoom.test.js index de9f3ec6af..77201d253e 100644 --- a/test/spec/ol/interaction/dragzoom.test.js +++ b/test/spec/ol/interaction/dragzoom.test.js @@ -103,7 +103,7 @@ describe('ol.interaction.DragZoom', function() { setTimeout(function() { const view = map.getView(); const resolution = view.getResolution(); - expect(resolution).to.eql(view.constrainResolution(0.5)); + expect(resolution).to.eql(view.getValidResolution(0.5)); done(); }, 50); }, 50); diff --git a/test/spec/ol/resolutionconstraint.test.js b/test/spec/ol/resolutionconstraint.test.js index c48ea0fe10..9ba06c788d 100644 --- a/test/spec/ol/resolutionconstraint.test.js +++ b/test/spec/ol/resolutionconstraint.test.js @@ -12,30 +12,30 @@ describe('ol.resolutionconstraint', function() { [1000, 500, 250, 100]); }); - describe('delta 0', function() { + describe('direction 0', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1000, 0, 0)).to.eql(1000); - expect(resolutionConstraint(500, 0, 0)).to.eql(500); - expect(resolutionConstraint(250, 0, 0)).to.eql(250); - expect(resolutionConstraint(100, 0, 0)).to.eql(100); + expect(resolutionConstraint(1000, 0)).to.eql(1000); + expect(resolutionConstraint(500, 0)).to.eql(500); + expect(resolutionConstraint(250, 0)).to.eql(250); + expect(resolutionConstraint(100, 0)).to.eql(100); }); }); - describe('zoom in', function() { + describe('direction 1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1000, 1, 0)).to.eql(500); - expect(resolutionConstraint(500, 1, 0)).to.eql(250); - expect(resolutionConstraint(250, 1, 0)).to.eql(100); - expect(resolutionConstraint(100, 1, 0)).to.eql(100); + expect(resolutionConstraint(1000, 1)).to.eql(1000); + expect(resolutionConstraint(500, 1)).to.eql(500); + expect(resolutionConstraint(250, 1)).to.eql(250); + expect(resolutionConstraint(100, 1)).to.eql(100); }); }); - describe('zoom out', function() { + describe('direction -1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1000, -1, 0)).to.eql(1000); - expect(resolutionConstraint(500, -1, 0)).to.eql(1000); - expect(resolutionConstraint(250, -1, 0)).to.eql(500); - expect(resolutionConstraint(100, -1, 0)).to.eql(250); + expect(resolutionConstraint(1000, -1)).to.eql(1000); + expect(resolutionConstraint(500, -1)).to.eql(500); + expect(resolutionConstraint(250, -1)).to.eql(250); + expect(resolutionConstraint(100, -1)).to.eql(100); }); }); }); @@ -50,42 +50,42 @@ describe('ol.resolutionconstraint', function() { [1000, 500, 250, 100]); }); - describe('delta 0', function() { + describe('direction 0', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, 0, 0)).to.eql(1000); - expect(resolutionConstraint(950, 0, 0)).to.eql(1000); - expect(resolutionConstraint(550, 0, 0)).to.eql(500); - expect(resolutionConstraint(400, 0, 0)).to.eql(500); - expect(resolutionConstraint(300, 0, 0)).to.eql(250); - expect(resolutionConstraint(200, 0, 0)).to.eql(250); - expect(resolutionConstraint(150, 0, 0)).to.eql(100); - expect(resolutionConstraint(50, 0, 0)).to.eql(100); + expect(resolutionConstraint(1050, 0)).to.eql(1000); + expect(resolutionConstraint(950, 0)).to.eql(1000); + expect(resolutionConstraint(550, 0)).to.eql(500); + expect(resolutionConstraint(400, 0)).to.eql(500); + expect(resolutionConstraint(300, 0)).to.eql(250); + expect(resolutionConstraint(200, 0)).to.eql(250); + expect(resolutionConstraint(150, 0)).to.eql(100); + expect(resolutionConstraint(50, 0)).to.eql(100); }); }); - describe('zoom in', function() { + describe('direction 1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, 1, 0)).to.eql(500); - expect(resolutionConstraint(950, 1, 0)).to.eql(500); - expect(resolutionConstraint(550, 1, 0)).to.eql(250); - expect(resolutionConstraint(450, 1, 0)).to.eql(250); - expect(resolutionConstraint(300, 1, 0)).to.eql(100); - expect(resolutionConstraint(200, 1, 0)).to.eql(100); - expect(resolutionConstraint(150, 1, 0)).to.eql(100); - expect(resolutionConstraint(50, 1, 0)).to.eql(100); + expect(resolutionConstraint(1050, 1)).to.eql(1000); + expect(resolutionConstraint(950, 1)).to.eql(1000); + expect(resolutionConstraint(550, 1)).to.eql(1000); + expect(resolutionConstraint(450, 1)).to.eql(500); + expect(resolutionConstraint(300, 1)).to.eql(500); + expect(resolutionConstraint(200, 1)).to.eql(250); + expect(resolutionConstraint(150, 1)).to.eql(250); + expect(resolutionConstraint(50, 1)).to.eql(100); }); }); - describe('zoom out', function() { + describe('direction -1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, -1, 0)).to.eql(1000); - expect(resolutionConstraint(950, -1, 0)).to.eql(1000); - expect(resolutionConstraint(550, -1, 0)).to.eql(1000); - expect(resolutionConstraint(450, -1, 0)).to.eql(1000); - expect(resolutionConstraint(300, -1, 0)).to.eql(500); - expect(resolutionConstraint(200, -1, 0)).to.eql(500); - expect(resolutionConstraint(150, -1, 0)).to.eql(250); - expect(resolutionConstraint(50, -1, 0)).to.eql(250); + expect(resolutionConstraint(1050, -1)).to.eql(1000); + expect(resolutionConstraint(950, -1)).to.eql(500); + expect(resolutionConstraint(550, -1)).to.eql(500); + expect(resolutionConstraint(450, -1)).to.eql(250); + expect(resolutionConstraint(300, -1)).to.eql(250); + expect(resolutionConstraint(200, -1)).to.eql(100); + expect(resolutionConstraint(150, -1)).to.eql(100); + expect(resolutionConstraint(50, -1)).to.eql(100); }); }); }); @@ -96,54 +96,54 @@ describe('ol.resolutionconstraint', function() { beforeEach(function() { resolutionConstraint = - createSnapToPower(2, 1024, 10); + createSnapToPower(2, 1024, 1); }); describe('delta 0', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1024, 0, 0)).to.eql(1024); - expect(resolutionConstraint(512, 0, 0)).to.eql(512); - expect(resolutionConstraint(256, 0, 0)).to.eql(256); - expect(resolutionConstraint(128, 0, 0)).to.eql(128); - expect(resolutionConstraint(64, 0, 0)).to.eql(64); - expect(resolutionConstraint(32, 0, 0)).to.eql(32); - expect(resolutionConstraint(16, 0, 0)).to.eql(16); - expect(resolutionConstraint(8, 0, 0)).to.eql(8); - expect(resolutionConstraint(4, 0, 0)).to.eql(4); - expect(resolutionConstraint(2, 0, 0)).to.eql(2); - expect(resolutionConstraint(1, 0, 0)).to.eql(1); + expect(resolutionConstraint(1024, 0)).to.eql(1024); + expect(resolutionConstraint(512, 0)).to.eql(512); + expect(resolutionConstraint(256, 0)).to.eql(256); + expect(resolutionConstraint(128, 0)).to.eql(128); + expect(resolutionConstraint(64, 0)).to.eql(64); + expect(resolutionConstraint(32, 0)).to.eql(32); + expect(resolutionConstraint(16, 0)).to.eql(16); + expect(resolutionConstraint(8, 0)).to.eql(8); + expect(resolutionConstraint(4, 0)).to.eql(4); + expect(resolutionConstraint(2, 0)).to.eql(2); + expect(resolutionConstraint(1, 0)).to.eql(1); }); }); - describe('zoom in', function() { + describe('direction 1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1024, 1, 0)).to.eql(512); - expect(resolutionConstraint(512, 1, 0)).to.eql(256); - expect(resolutionConstraint(256, 1, 0)).to.eql(128); - expect(resolutionConstraint(128, 1, 0)).to.eql(64); - expect(resolutionConstraint(64, 1, 0)).to.eql(32); - expect(resolutionConstraint(32, 1, 0)).to.eql(16); - expect(resolutionConstraint(16, 1, 0)).to.eql(8); - expect(resolutionConstraint(8, 1, 0)).to.eql(4); - expect(resolutionConstraint(4, 1, 0)).to.eql(2); - expect(resolutionConstraint(2, 1, 0)).to.eql(1); - expect(resolutionConstraint(1, 1, 0)).to.eql(1); + expect(resolutionConstraint(1024, 1)).to.eql(1024); + expect(resolutionConstraint(512, 1)).to.eql(512); + expect(resolutionConstraint(256, 1)).to.eql(256); + expect(resolutionConstraint(128, 1)).to.eql(128); + expect(resolutionConstraint(64, 1)).to.eql(64); + expect(resolutionConstraint(32, 1)).to.eql(32); + expect(resolutionConstraint(16, 1)).to.eql(16); + expect(resolutionConstraint(8, 1)).to.eql(8); + expect(resolutionConstraint(4, 1)).to.eql(4); + expect(resolutionConstraint(2, 1)).to.eql(2); + expect(resolutionConstraint(1, 1)).to.eql(1); }); }); - describe('zoom out', function() { + describe('direction -1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1024, -1, 0)).to.eql(1024); - expect(resolutionConstraint(512, -1, 0)).to.eql(1024); - expect(resolutionConstraint(256, -1, 0)).to.eql(512); - expect(resolutionConstraint(128, -1, 0)).to.eql(256); - expect(resolutionConstraint(64, -1, 0)).to.eql(128); - expect(resolutionConstraint(32, -1, 0)).to.eql(64); - expect(resolutionConstraint(16, -1, 0)).to.eql(32); - expect(resolutionConstraint(8, -1, 0)).to.eql(16); - expect(resolutionConstraint(4, -1, 0)).to.eql(8); - expect(resolutionConstraint(2, -1, 0)).to.eql(4); - expect(resolutionConstraint(1, -1, 0)).to.eql(2); + expect(resolutionConstraint(1024, -1)).to.eql(1024); + expect(resolutionConstraint(512, -1)).to.eql(512); + expect(resolutionConstraint(256, -1)).to.eql(256); + expect(resolutionConstraint(128, -1)).to.eql(128); + expect(resolutionConstraint(64, -1)).to.eql(64); + expect(resolutionConstraint(32, -1)).to.eql(32); + expect(resolutionConstraint(16, -1)).to.eql(16); + expect(resolutionConstraint(8, -1)).to.eql(8); + expect(resolutionConstraint(4, -1)).to.eql(4); + expect(resolutionConstraint(2, -1)).to.eql(2); + expect(resolutionConstraint(1, -1)).to.eql(1); }); }); }); @@ -154,87 +154,87 @@ describe('ol.resolutionconstraint', function() { beforeEach(function() { resolutionConstraint = - createSnapToPower(2, 1024, 10); + createSnapToPower(2, 1024, 1); }); - describe('delta 0, direction 0', function() { + describe('direction 0', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, 0, 0)).to.eql(1024); - expect(resolutionConstraint(9050, 0, 0)).to.eql(1024); - expect(resolutionConstraint(550, 0, 0)).to.eql(512); - expect(resolutionConstraint(450, 0, 0)).to.eql(512); - expect(resolutionConstraint(300, 0, 0)).to.eql(256); - expect(resolutionConstraint(250, 0, 0)).to.eql(256); - expect(resolutionConstraint(150, 0, 0)).to.eql(128); - expect(resolutionConstraint(100, 0, 0)).to.eql(128); - expect(resolutionConstraint(75, 0, 0)).to.eql(64); - expect(resolutionConstraint(50, 0, 0)).to.eql(64); - expect(resolutionConstraint(40, 0, 0)).to.eql(32); - expect(resolutionConstraint(30, 0, 0)).to.eql(32); - expect(resolutionConstraint(20, 0, 0)).to.eql(16); - expect(resolutionConstraint(12, 0, 0)).to.eql(16); - expect(resolutionConstraint(9, 0, 0)).to.eql(8); - expect(resolutionConstraint(7, 0, 0)).to.eql(8); - expect(resolutionConstraint(5, 0, 0)).to.eql(4); - expect(resolutionConstraint(3.5, 0, 0)).to.eql(4); - expect(resolutionConstraint(2.1, 0, 0)).to.eql(2); - expect(resolutionConstraint(1.9, 0, 0)).to.eql(2); - expect(resolutionConstraint(1.1, 0, 0)).to.eql(1); - expect(resolutionConstraint(0.9, 0, 0)).to.eql(1); + expect(resolutionConstraint(1050, 0)).to.eql(1024); + expect(resolutionConstraint(9050, 0)).to.eql(1024); + expect(resolutionConstraint(550, 0)).to.eql(512); + expect(resolutionConstraint(450, 0)).to.eql(512); + expect(resolutionConstraint(300, 0)).to.eql(256); + expect(resolutionConstraint(250, 0)).to.eql(256); + expect(resolutionConstraint(150, 0)).to.eql(128); + expect(resolutionConstraint(100, 0)).to.eql(128); + expect(resolutionConstraint(75, 0)).to.eql(64); + expect(resolutionConstraint(50, 0)).to.eql(64); + expect(resolutionConstraint(40, 0)).to.eql(32); + expect(resolutionConstraint(30, 0)).to.eql(32); + expect(resolutionConstraint(20, 0)).to.eql(16); + expect(resolutionConstraint(12, 0)).to.eql(16); + expect(resolutionConstraint(9, 0)).to.eql(8); + expect(resolutionConstraint(7, 0)).to.eql(8); + expect(resolutionConstraint(5, 0)).to.eql(4); + expect(resolutionConstraint(3.5, 0)).to.eql(4); + expect(resolutionConstraint(2.1, 0)).to.eql(2); + expect(resolutionConstraint(1.9, 0)).to.eql(2); + expect(resolutionConstraint(1.1, 0)).to.eql(1); + expect(resolutionConstraint(0.9, 0)).to.eql(1); }); }); - describe('delta 0, direction > 0', function() { + describe('direction 1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, 0, 1)).to.eql(1024); - expect(resolutionConstraint(9050, 0, 1)).to.eql(1024); - expect(resolutionConstraint(550, 0, 1)).to.eql(1024); - expect(resolutionConstraint(450, 0, 1)).to.eql(512); - expect(resolutionConstraint(300, 0, 1)).to.eql(512); - expect(resolutionConstraint(250, 0, 1)).to.eql(256); - expect(resolutionConstraint(150, 0, 1)).to.eql(256); - expect(resolutionConstraint(100, 0, 1)).to.eql(128); - expect(resolutionConstraint(75, 0, 1)).to.eql(128); - expect(resolutionConstraint(50, 0, 1)).to.eql(64); - expect(resolutionConstraint(40, 0, 1)).to.eql(64); - expect(resolutionConstraint(30, 0, 1)).to.eql(32); - expect(resolutionConstraint(20, 0, 1)).to.eql(32); - expect(resolutionConstraint(12, 0, 1)).to.eql(16); - expect(resolutionConstraint(9, 0, 1)).to.eql(16); - expect(resolutionConstraint(7, 0, 1)).to.eql(8); - expect(resolutionConstraint(5, 0, 1)).to.eql(8); - expect(resolutionConstraint(3.5, 0, 1)).to.eql(4); - expect(resolutionConstraint(2.1, 0, 1)).to.eql(4); - expect(resolutionConstraint(1.9, 0, 1)).to.eql(2); - expect(resolutionConstraint(1.1, 0, 1)).to.eql(2); - expect(resolutionConstraint(0.9, 0, 1)).to.eql(1); + expect(resolutionConstraint(1050, 1)).to.eql(1024); + expect(resolutionConstraint(9050, 1)).to.eql(1024); + expect(resolutionConstraint(550, 1)).to.eql(1024); + expect(resolutionConstraint(450, 1)).to.eql(512); + expect(resolutionConstraint(300, 1)).to.eql(512); + expect(resolutionConstraint(250, 1)).to.eql(256); + expect(resolutionConstraint(150, 1)).to.eql(256); + expect(resolutionConstraint(100, 1)).to.eql(128); + expect(resolutionConstraint(75, 1)).to.eql(128); + expect(resolutionConstraint(50, 1)).to.eql(64); + expect(resolutionConstraint(40, 1)).to.eql(64); + expect(resolutionConstraint(30, 1)).to.eql(32); + expect(resolutionConstraint(20, 1)).to.eql(32); + expect(resolutionConstraint(12, 1)).to.eql(16); + expect(resolutionConstraint(9, 1)).to.eql(16); + expect(resolutionConstraint(7, 1)).to.eql(8); + expect(resolutionConstraint(5, 1)).to.eql(8); + expect(resolutionConstraint(3.5, 1)).to.eql(4); + expect(resolutionConstraint(2.1, 1)).to.eql(4); + expect(resolutionConstraint(1.9, 1)).to.eql(2); + expect(resolutionConstraint(1.1, 1)).to.eql(2); + expect(resolutionConstraint(0.9, 1)).to.eql(1); }); }); - describe('delta 0, direction < 0', function() { + describe('direction -1', function() { it('returns expected resolution value', function() { - expect(resolutionConstraint(1050, 0, -1)).to.eql(1024); - expect(resolutionConstraint(9050, 0, -1)).to.eql(1024); - expect(resolutionConstraint(550, 0, -1)).to.eql(512); - expect(resolutionConstraint(450, 0, -1)).to.eql(256); - expect(resolutionConstraint(300, 0, -1)).to.eql(256); - expect(resolutionConstraint(250, 0, -1)).to.eql(128); - expect(resolutionConstraint(150, 0, -1)).to.eql(128); - expect(resolutionConstraint(100, 0, -1)).to.eql(64); - expect(resolutionConstraint(75, 0, -1)).to.eql(64); - expect(resolutionConstraint(50, 0, -1)).to.eql(32); - expect(resolutionConstraint(40, 0, -1)).to.eql(32); - expect(resolutionConstraint(30, 0, -1)).to.eql(16); - expect(resolutionConstraint(20, 0, -1)).to.eql(16); - expect(resolutionConstraint(12, 0, -1)).to.eql(8); - expect(resolutionConstraint(9, 0, -1)).to.eql(8); - expect(resolutionConstraint(7, 0, -1)).to.eql(4); - expect(resolutionConstraint(5, 0, -1)).to.eql(4); - expect(resolutionConstraint(3.5, 0, -1)).to.eql(2); - expect(resolutionConstraint(2.1, 0, -1)).to.eql(2); - expect(resolutionConstraint(1.9, 0, -1)).to.eql(1); - expect(resolutionConstraint(1.1, 0, -1)).to.eql(1); - expect(resolutionConstraint(0.9, 0, -1)).to.eql(1); + expect(resolutionConstraint(1050, -1)).to.eql(1024); + expect(resolutionConstraint(9050, -1)).to.eql(1024); + expect(resolutionConstraint(550, -1)).to.eql(512); + expect(resolutionConstraint(450, -1)).to.eql(256); + expect(resolutionConstraint(300, -1)).to.eql(256); + expect(resolutionConstraint(250, -1)).to.eql(128); + expect(resolutionConstraint(150, -1)).to.eql(128); + expect(resolutionConstraint(100, -1)).to.eql(64); + expect(resolutionConstraint(75, -1)).to.eql(64); + expect(resolutionConstraint(50, -1)).to.eql(32); + expect(resolutionConstraint(40, -1)).to.eql(32); + expect(resolutionConstraint(30, -1)).to.eql(16); + expect(resolutionConstraint(20, -1)).to.eql(16); + expect(resolutionConstraint(12, -1)).to.eql(8); + expect(resolutionConstraint(9, -1)).to.eql(8); + expect(resolutionConstraint(7, -1)).to.eql(4); + expect(resolutionConstraint(5, -1)).to.eql(4); + expect(resolutionConstraint(3.5, -1)).to.eql(2); + expect(resolutionConstraint(2.1, -1)).to.eql(2); + expect(resolutionConstraint(1.9, -1)).to.eql(1); + expect(resolutionConstraint(1.1, -1)).to.eql(1); + expect(resolutionConstraint(0.9, -1)).to.eql(1); }); }); }); diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index 88b18e4718..b41cc34f67 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -1104,7 +1104,9 @@ describe('ol.View', function() { const min = view.getMinZoom(); expect(view.getResolutionForZoom(max)).to.be(view.getMinResolution()); + expect(view.getResolutionForZoom(max + 1)).to.be(view.getMinResolution()); expect(view.getResolutionForZoom(min)).to.be(view.getMaxResolution()); + expect(view.getResolutionForZoom(min - 1)).to.be(view.getMaxResolution()); }); it('returns correct zoom levels for specifically configured resolutions', function() { @@ -1112,11 +1114,30 @@ describe('ol.View', function() { resolutions: [10, 8, 6, 4, 2] }); + expect(view.getResolutionForZoom(-1)).to.be(10); expect(view.getResolutionForZoom(0)).to.be(10); expect(view.getResolutionForZoom(1)).to.be(8); expect(view.getResolutionForZoom(2)).to.be(6); expect(view.getResolutionForZoom(3)).to.be(4); expect(view.getResolutionForZoom(4)).to.be(2); + expect(view.getResolutionForZoom(5)).to.be(2); + }); + + it('returns correct zoom levels for resolutions with variable zoom levels', function() { + const view = new View({ + resolutions: [50, 10, 5, 2.5, 1.25, 0.625] + }); + + expect(view.getResolutionForZoom(-1)).to.be(50); + expect(view.getResolutionForZoom(0)).to.be(50); + expect(view.getResolutionForZoom(0.5)).to.be(50 / Math.pow(5, 0.5)); + expect(view.getResolutionForZoom(1)).to.be(10); + expect(view.getResolutionForZoom(2)).to.be(5); + expect(view.getResolutionForZoom(2.75)).to.be(5 / Math.pow(2, 0.75)); + expect(view.getResolutionForZoom(3)).to.be(2.5); + expect(view.getResolutionForZoom(4)).to.be(1.25); + expect(view.getResolutionForZoom(5)).to.be(0.625); + expect(view.getResolutionForZoom(6)).to.be(0.625); }); }); @@ -1470,6 +1491,41 @@ describe('ol.View', function() { expect(view.getValidZoomLevel(8)).to.be(6); }); }); + + describe('#getValidResolution()', function() { + let view; + const defaultMaxRes = 156543.03392804097; + + it('works correctly by snapping to power of 2', function() { + view = new View(); + expect(view.getValidResolution(1000000)).to.be(defaultMaxRes); + expect(view.getValidResolution(defaultMaxRes / 8)).to.be(defaultMaxRes / 8); + }); + it('works correctly by snapping to a custom zoom factor', function() { + view = new View({ + maxResolution: 2500, + zoomFactor: 5, + maxZoom: 4 + }); + expect(view.getValidResolution(90, 1)).to.be(100); + expect(view.getValidResolution(90, -1)).to.be(20); + expect(view.getValidResolution(20)).to.be(20); + expect(view.getValidResolution(5)).to.be(4); + expect(view.getValidResolution(1)).to.be(4); + }); + it('works correctly with a specific resolution set', function() { + view = new View({ + zoom: 0, + resolutions: [512, 256, 128, 64, 32, 16, 8] + }); + expect(view.getValidResolution(1000, 1)).to.be(512); + expect(view.getValidResolution(260, 1)).to.be(512); + expect(view.getValidResolution(260)).to.be(256); + expect(view.getValidResolution(30)).to.be(32); + expect(view.getValidResolution(30, -1)).to.be(16); + expect(view.getValidResolution(4, -1)).to.be(8); + }); + }); }); describe('ol.View.isNoopAnimation()', function() {