diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js b/misc/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js new file mode 100644 index 0000000..f647238 --- /dev/null +++ b/misc/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js @@ -0,0 +1,319 @@ +/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the 2-clause BSD license. + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Layer.js + */ + +/** + * Class: OpenLayers.Layer.FixedZoomLevels + * Some Layers will already have established zoom levels (like google + * or ve). Instead of trying to determine them and populate a resolutions[] + * Array with those values, we will hijack the resolution functionality + * here. + * + * When you subclass FixedZoomLevels: + * + * The initResolutions() call gets nullified, meaning no resolutions[] array + * is set up. Which would be a big problem getResolution() in Layer, since + * it merely takes map.zoom and indexes into resolutions[]... but.... + * + * The getResolution() call is also overridden. Instead of using the + * resolutions[] array, we simply calculate the current resolution based + * on the current extent and the current map size. But how will we be able + * to calculate the current extent without knowing the resolution...? + * + * The getExtent() function is also overridden. Instead of calculating extent + * based on the center point and the current resolution, we instead + * calculate the extent by getting the lonlats at the top-left and + * bottom-right by using the getLonLatFromViewPortPx() translation function, + * taken from the pixel locations (0,0) and the size of the map. But how + * will we be able to do lonlat-px translation without resolution....? + * + * The getZoomForResolution() method is overridden. Instead of indexing into + * the resolutions[] array, we call OpenLayers.Layer.getExent(), passing in + * the desired resolution. With this extent, we then call getZoomForExtent() + * + * + * Whenever you implement a layer using OpenLayers.Layer.FixedZoomLevels, + * it is your responsibility to provide the following three functions: + * + * - getLonLatFromViewPortPx + * - getViewPortPxFromLonLat + * - getZoomForExtent + * + * ...those three functions should generally be provided by any reasonable + * API that you might be working from. + * + */ +OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({ + + /********************************************************/ + /* */ + /* Baselayer Functions */ + /* */ + /* The following functions must all be implemented */ + /* by all base layers */ + /* */ + /********************************************************/ + + /** + * Constructor: OpenLayers.Layer.FixedZoomLevels + * Create a new fixed zoom levels layer. + */ + initialize: function() { + //this class is only just to add the following functions... + // nothing to actually do here... but it is probably a good + // idea to have layers that use these functions call this + // inititalize() anyways, in case at some point we decide we + // do want to put some functionality or state in here. + }, + + /** + * Method: initResolutions + * Populate the resolutions array + */ + initResolutions: function() { + + var props = ['minZoomLevel', 'maxZoomLevel', 'numZoomLevels']; + + for(var i=0, len=props.length; i<len; i++) { + var property = props[i]; + this[property] = (this.options[property] != null) + ? this.options[property] + : this.map[property]; + } + + if ( (this.minZoomLevel == null) || + (this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){ + this.minZoomLevel = this.MIN_ZOOM_LEVEL; + } + + // + // At this point, we know what the minimum desired zoom level is, and + // we must calculate the total number of zoom levels. + // + // Because we allow for the setting of either the 'numZoomLevels' + // or the 'maxZoomLevel' properties... on either the layer or the + // map, we have to define some rules to see which we take into + // account first in this calculation. + // + // The following is the precedence list for these properties: + // + // (1) numZoomLevels set on layer + // (2) maxZoomLevel set on layer + // (3) numZoomLevels set on map + // (4) maxZoomLevel set on map* + // (5) none of the above* + // + // *Note that options (4) and (5) are only possible if the user + // _explicitly_ sets the 'numZoomLevels' property on the map to + // null, since it is set by default to 16. + // + + // + // Note to future: In 3.0, I think we should remove the default + // value of 16 for map.numZoomLevels. Rather, I think that value + // should be set as a default on the Layer.WMS class. If someone + // creates a 3rd party layer and does not specify any 'minZoomLevel', + // 'maxZoomLevel', or 'numZoomLevels', and has not explicitly + // specified any of those on the map object either.. then I think + // it is fair to say that s/he wants all the zoom levels available. + // + // By making map.numZoomLevels *null* by default, that will be the + // case. As it is, I don't feel comfortable changing that right now + // as it would be a glaring API change and actually would probably + // break many peoples' codes. + // + + //the number of zoom levels we'd like to have. + var desiredZoomLevels; + + //this is the maximum number of zoom levels the layer will allow, + // given the specified starting minimum zoom level. + var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1; + + if ( ((this.options.numZoomLevels == null) && + (this.options.maxZoomLevel != null)) // (2) + || + ((this.numZoomLevels == null) && + (this.maxZoomLevel != null)) // (4) + ) { + //calculate based on specified maxZoomLevel (on layer or map) + desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1; + } else { + //calculate based on specified numZoomLevels (on layer or map) + // this covers cases (1) and (3) + desiredZoomLevels = this.numZoomLevels; + } + + if (desiredZoomLevels != null) { + //Now that we know what we would *like* the number of zoom levels + // to be, based on layer or map options, we have to make sure that + // it does not conflict with the actual limit, as specified by + // the constants on the layer itself (and calculated into the + // 'limitZoomLevels' variable). + this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels); + } else { + // case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was + // set on either the layer or the map. So we just use the + // maximum limit as calculated by the layer's constants. + this.numZoomLevels = limitZoomLevels; + } + + //now that the 'numZoomLevels' is appropriately, safely set, + // we go back and re-calculate the 'maxZoomLevel'. + this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1; + + if (this.RESOLUTIONS != null) { + var resolutionsIndex = 0; + this.resolutions = []; + for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) { + this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i]; + } + this.maxResolution = this.resolutions[0]; + this.minResolution = this.resolutions[this.resolutions.length - 1]; + } + }, + + /** + * APIMethod: getResolution + * Get the current map resolution + * + * Returns: + * {Float} Map units per Pixel + */ + getResolution: function() { + + if (this.resolutions != null) { + return OpenLayers.Layer.prototype.getResolution.apply(this, arguments); + } else { + var resolution = null; + + var viewSize = this.map.getSize(); + var extent = this.getExtent(); + + if ((viewSize != null) && (extent != null)) { + resolution = Math.max( extent.getWidth() / viewSize.w, + extent.getHeight() / viewSize.h ); + } + return resolution; + } + }, + + /** + * APIMethod: getExtent + * Calculates using px-> lonlat translation functions on tl and br + * corners of viewport + * + * Returns: + * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat + * bounds of the current viewPort. + */ + getExtent: function () { + var size = this.map.getSize(); + var tl = this.getLonLatFromViewPortPx({ + x: 0, y: 0 + }); + var br = this.getLonLatFromViewPortPx({ + x: size.w, y: size.h + }); + + if ((tl != null) && (br != null)) { + return new OpenLayers.Bounds(tl.lon, br.lat, br.lon, tl.lat); + } else { + return null; + } + }, + + /** + * Method: getZoomForResolution + * Get the zoom level for a given resolution + * + * Parameters: + * resolution - {Float} + * + * Returns: + * {Integer} A suitable zoom level for the specified resolution. + * If no baselayer is set, returns null. + */ + getZoomForResolution: function(resolution) { + + if (this.resolutions != null) { + return OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments); + } else { + var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []); + return this.getZoomForExtent(extent); + } + }, + + + + + /********************************************************/ + /* */ + /* Translation Functions */ + /* */ + /* The following functions translate GMaps and OL */ + /* formats for Pixel, LonLat, Bounds, and Zoom */ + /* */ + /********************************************************/ + + + // + // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom + // + + /** + * Method: getOLZoomFromMapObjectZoom + * Get the OL zoom index from the map object zoom level + * + * Parameters: + * moZoom - {Integer} + * + * Returns: + * {Integer} An OpenLayers Zoom level, translated from the passed in zoom + * Returns null if null value is passed in + */ + getOLZoomFromMapObjectZoom: function(moZoom) { + var zoom = null; + if (moZoom != null) { + zoom = moZoom - this.minZoomLevel; + if (this.map.baseLayer !== this) { + zoom = this.map.baseLayer.getZoomForResolution( + this.getResolutionForZoom(zoom) + ); + } + } + return zoom; + }, + + /** + * Method: getMapObjectZoomFromOLZoom + * Get the map object zoom level from the OL zoom level + * + * Parameters: + * olZoom - {Integer} + * + * Returns: + * {Integer} A MapObject level, translated from the passed in olZoom + * Returns null if null value is passed in + */ + getMapObjectZoomFromOLZoom: function(olZoom) { + var zoom = null; + if (olZoom != null) { + zoom = olZoom + this.minZoomLevel; + if (this.map.baseLayer !== this) { + zoom = this.getZoomForResolution( + this.map.baseLayer.getResolutionForZoom(zoom) + ); + } + } + return zoom; + }, + + CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels" +}); + |