diff --git a/lib/OpenLayers/Control/Snapping.js b/lib/OpenLayers/Control/Snapping.js index 6be3c49fe4..d1042cd20b 100644 --- a/lib/OpenLayers/Control/Snapping.js +++ b/lib/OpenLayers/Control/Snapping.js @@ -165,6 +165,14 @@ OpenLayers.Control.Snapping = OpenLayers.Class(OpenLayers.Control, { * filter - {OpenLayers.Filter} Optional filter to evaluate to determine if * feature is eligible for snapping. If filter evaluates to true for a * target feature a vertex may be snapped to the feature. + * minResolution - {Number} If a minResolution is provided, snapping to this + * target will only be considered if the map resolution is greater than + * or equal to this value (the minResolution is inclusive). Default is + * no minimum resolution limit. + * maxResolution - {Number} If a maxResolution is provided, snapping to this + * target will only be considered if the map resolution is strictly + * less than this value (the maxResolution is exclusive). Default is + * no maximum resolution limit. */ initialize: function(options) { // concatenate events specific to measure with those from the base @@ -436,10 +444,21 @@ OpenLayers.Control.Snapping = OpenLayers.Class(OpenLayers.Control, { * Returns null if candidate is not eligible for snapping. */ testTarget: function(target, loc) { + var resolution = this.layer.map.getResolution(); + if ("minResolution" in target) { + if (resolution < target.minResolution) { + return null; + } + } + if ("maxResolution" in target) { + if (resolution >= target.maxResolution) { + return null; + } + } var tolerance = { - node: this.getGeoTolerance(target.nodeTolerance), - vertex: this.getGeoTolerance(target.vertexTolerance), - edge: this.getGeoTolerance(target.edgeTolerance) + node: this.getGeoTolerance(target.nodeTolerance, resolution), + vertex: this.getGeoTolerance(target.vertexTolerance, resolution), + edge: this.getGeoTolerance(target.edgeTolerance, resolution) }; // this could be cached if we don't support setting tolerance values directly var maxTolerance = Math.max( @@ -512,12 +531,12 @@ OpenLayers.Control.Snapping = OpenLayers.Class(OpenLayers.Control, { * * Parameters: * tolerance - {Number} A tolerance value in pixels. + * resolution - {Number} Map resolution. * * Returns: * {Number} A tolerance value in map units. */ - getGeoTolerance: function(tolerance) { - var resolution = this.layer.map.getResolution(); + getGeoTolerance: function(tolerance, resolution) { if(resolution !== this.resolution) { this.resolution = resolution; this.geoToleranceCache = {}; diff --git a/tests/Control/Snapping.html b/tests/Control/Snapping.html index ded37b8c45..38e77704cc 100644 --- a/tests/Control/Snapping.html +++ b/tests/Control/Snapping.html @@ -173,6 +173,70 @@ control.destroy(); } + function test_resolution_limits(t) { + t.plan(7); + + var map = new OpenLayers.Map("map", { + resolutions: [1], + maxExtent: new OpenLayers.Bounds(0, 0, 100, 100) + }); + + var layer = new OpenLayers.Layer.Vector(null, { + isBaseLayer: true + }); + layer.addFeatures([ + new OpenLayers.Feature.Vector(OpenLayers.Geometry.fromWKT( + "POINT(50 50)" + )) + ]); + + map.addLayer(layer); + map.zoomToMaxExtent(); + + var control = new OpenLayers.Control.Snapping({layer: layer}); + + var result; + var loc = new OpenLayers.Geometry.Point(49, 49); + + // 1) test a target with no constraints + control.setTargets([{layer: layer}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "1) target is eligible"); + + // 2) test a target with minResolution < map.resolution + control.setTargets([{layer: layer, minResolution: 0.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "2) target is eligible"); + + // 3) test a target with minResolution === map.resolution + control.setTargets([{layer: layer, minResolution: 1}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "3) target is eligible"); + + // 4) test a target with minResolution > map.resolution + control.setTargets([{layer: layer, minResolution: 1.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "4) target is not eligible"); + + // 5) test a target with maxResolution < map.resolution + control.setTargets([{layer: layer, maxResolution: 0.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "5) target is not eligible"); + + // 6) test a target with maxResolution === map.resolution + control.setTargets([{layer: layer, maxResolution: 1}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result === null, "6) target is not eligible"); + + // 7) test a target with maxResolution > map.resolution + control.setTargets([{layer: layer, maxResolution: 1.5}]); + result = control.testTarget(control.targets[0], loc); + t.ok(result !== null, "7) target is eligible"); + + map.destroy(); + + } + function test_snapping(t) { t.plan(46);