From 6efaf328e567142ae07290322c12c946c914b019 Mon Sep 17 00:00:00 2001 From: crschmidt Date: Wed, 9 Aug 2006 19:14:16 +0000 Subject: [PATCH] Commit scale-based methods back into trunk. Layers or Maps now support setting a list of scales or resolutions in the options to the constructor, from which resolutions are calculated. Map now has a 'setScale' function which will allow you to zoom to as close to a given scale as possible. git-svn-id: http://svn.openlayers.org/trunk/openlayers@1171 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- lib/OpenLayers/Layer.js | 22 ++++++++++++ lib/OpenLayers/Layer/Grid.js | 11 ------ lib/OpenLayers/Layer/HTTPRequest.js | 35 +++++++++++++++++++ lib/OpenLayers/Map.js | 28 ++++++++++++--- lib/OpenLayers/Util.js | 54 +++++++++++++++++++++-------- 5 files changed, 120 insertions(+), 30 deletions(-) diff --git a/lib/OpenLayers/Layer.js b/lib/OpenLayers/Layer.js index 1c43161083..6625f5ad39 100644 --- a/lib/OpenLayers/Layer.js +++ b/lib/OpenLayers/Layer.js @@ -54,7 +54,15 @@ OpenLayers.Layer.prototype = { /** @type int */ maxZoomLevel: null, + + /** @type float */ + minScale: null, + /** @type float */ + maxScale: null, + + /** @type String */ + units: null, /** * @constructor @@ -162,6 +170,20 @@ OpenLayers.Layer.prototype = { */ setMap: function(map) { this.map = map; + + var properties = new Array( + 'projection', 'minExtent', 'maxExtent', + 'minScale', 'maxScale', + 'maxResolution', 'minResolution', + 'minZoomLevel', 'maxZoomLevel', 'units', + 'scales', 'resolutions' + + ); + for(var i=0; i < properties.length; i++) { + if (this[properties[i]] == null) { + this[properties[i]] = this.map[properties[i]]; + } + } }, /** diff --git a/lib/OpenLayers/Layer/Grid.js b/lib/OpenLayers/Layer/Grid.js index efdcbddb55..c22e6e209f 100644 --- a/lib/OpenLayers/Layer/Grid.js +++ b/lib/OpenLayers/Layer/Grid.js @@ -288,17 +288,6 @@ OpenLayers.Layer.Grid.prototype = /* */ /********************************************************/ - /** - * @returns Degrees per Pixel - * @type float - */ - getResolution: function() { - var maxRes = this.map.getMaxResolution(); - var zoom = this.map.getZoom(); - - return maxRes / Math.pow(2, zoom); - }, - /** Calculates based on resolution, center, and mapsize * * @returns A Bounds object which represents the lon/lat bounds of the diff --git a/lib/OpenLayers/Layer/HTTPRequest.js b/lib/OpenLayers/Layer/HTTPRequest.js index 99f6c0190d..60c8cc20b6 100644 --- a/lib/OpenLayers/Layer/HTTPRequest.js +++ b/lib/OpenLayers/Layer/HTTPRequest.js @@ -36,6 +36,10 @@ OpenLayers.Layer.HTTPRequest.prototype = this.params = Object.extend( new Object(), params); }, + setMap: function(map) { + OpenLayers.Layer.prototype.setMap.apply(this, arguments); + this.initResolutions(); + }, /** * */ @@ -137,6 +141,37 @@ OpenLayers.Layer.HTTPRequest.prototype = } return requestString; }, + + initResolutions: function() { + if (this.scales != null) { + this.resolutions = new Array(); + for(var i = 0; i < this.scales.length; i++) + this.resolutions[i] = OpenLayers.Util.getResolutionFromScale(this.scales[i], this.units); + this.maxZoomLevel = this.resolutions.length; + } else if (this.resolutions != null) { + this.maxZoomLevel = this.resolutions.length; + } else { + this.resolutions = new Array(); + if (this.minScale) + this.maxResolution = OpenLayers.Util.getResolutionFromScale(this.minScale, this.units); + var maxRes = this.getMaxResolution(); + if (this.maxScale) { + /* This will cause this.map.getMaxZoomLevel() to be set the next time + * it is called, which means that the next portion here will succeed. */ + var minRes = OpenLayers.Util.getResolutionFromScale(this.maxScale); + this.maxZoomLevel = Math.floor(Math.log(maxRes/minRes) / Math.log(2)); + } + for (var i=this.getMinZoomLevel(); i <= this.getMaxZoomLevel(); i++) { + this.resolutions.push(maxRes / Math.pow(2, i)); + } + } + }, + + getResolution: function() { + var zoom = this.map.getZoom(); + + return this.resolutions[zoom]; + }, /** @final @type String */ CLASS_NAME: "OpenLayers.Layer.HTTPRequest" diff --git a/lib/OpenLayers/Map.js b/lib/OpenLayers/Map.js index 431b0596b4..1caba750c4 100644 --- a/lib/OpenLayers/Map.js +++ b/lib/OpenLayers/Map.js @@ -87,7 +87,7 @@ OpenLayers.Map.prototype = { * zoom level 0 on gmaps * * @type float */ - maxResolution: 1.40625, + maxResolution: null, /** @type int */ minZoomLevel: 0, @@ -210,14 +210,13 @@ OpenLayers.Map.prototype = { // if maxResolution is specified as "auto", calculate it // based on the maxExtent and the viewSize // - - if (this.maxResolution == null && this.minScale) { - this.maxResolution = OpenLayers.Util.getResolutionFromScale(this.minScale, this.units); - } else if (this.maxResolution == "auto" || this.maxResolution == null) { + if (this.maxResolution == "auto") { var maxExtent = this.getMaxExtent(); var viewSize = this.getSize(); this.maxResolution = Math.max(maxExtent.getWidth() / viewSize.w, maxExtent.getHeight() / viewSize.h ); + } else { + this.maxResolution = 1.40625; } }, @@ -826,6 +825,25 @@ OpenLayers.Map.prototype = { /* */ /********************************************************/ + /** zoom to a specified scale + * + * @param {float} scale + */ + setScale: function(scale) { + var res = OpenLayers.Util.getResolutionFromScale(scale, this.baseLayer.units); + var size = this.getSize(); + var w_deg = size.w * res; + var h_deg = size.h * res; + var center = this.getCenter(); + + var extent = new OpenLayers.Bounds(center.lon - w_deg / 2, + center.lat - h_deg / 2, + center.lon + w_deg / 2, + center.lat + h_deg / 2); + this.zoomToExtent(extent); + + }, + /** Zoom to a specific zoom level * * @param {int} zoom diff --git a/lib/OpenLayers/Util.js b/lib/OpenLayers/Util.js index 69cd650eff..f39dd205fa 100644 --- a/lib/OpenLayers/Util.js +++ b/lib/OpenLayers/Util.js @@ -1113,32 +1113,58 @@ OpenLayers.Util.createUniqueID = function(prefix) { return prefix + Math.round(Math.random() * 10000); }; -/** constant inches per unit */ -OpenLayers.INCHES_PER_UNIT = { // borrowed from MapServer mapscale.c +/** Constant inches per unit + * -- borrowed from MapServer mapscale.c + * + * @type Object */ +OpenLayers.INCHES_PER_UNIT = { 'inches': 1.0, - 'in': 1.0, 'ft': 12.0, 'mi': 63360.0, 'm': 39.3701, 'km': 39370.1, 'dd': 4374754, - 'degrees': 4374754 }; +OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches; +OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd; -/** sensible default */ +/** A sensible default + * @type int */ OpenLayers.DOTS_PER_INCH = 72; +/** + * @param {float} scale + * + * @returns A normalized scale value, in 1 / X format. + * This means that if a value less than one ( already 1/x) is passed + * in, it just returns scale directly. Otherwise, it returns + * 1 / scale + * @type float + */ OpenLayers.Util.normalizeScale = function (scale) { - if (scale > 1.0) - return 1.0 / scale; - else - return scale; + var normScale = (scale > 1.0) ? (1.0 / scale) + : scale; + return normScale; }; +/** + * @param {float} scale + * @param {String} units Index into OpenLayers.INCHES_PER_UNIT hashtable. + * Default is degrees + * + * @returns The corresponding resolution given passed-in scale and unit + * parameters. + * @type float + */ OpenLayers.Util.getResolutionFromScale = function (scale, units) { - if (!units) units = "degrees"; - scale = OpenLayers.Util.normalizeScale(scale); - return 1 / (scale * OpenLayers.INCHES_PER_UNIT[units] - * OpenLayers.DOTS_PER_INCH); -}; + if (units == null) { + units = "degrees"; + } + + normScale = OpenLayers.Util.normalizeScale(scale); + + var resolution = 1 / (normScale * OpenLayers.INCHES_PER_UNIT[units] + * OpenLayers.DOTS_PER_INCH); + return resolution; +}; \ No newline at end of file